162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// soc-component.c
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright 2009-2011 Wolfson Microelectronics PLC.
662306a36Sopenharmony_ci// Copyright (C) 2019 Renesas Electronics Corp.
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Mark Brown <broonie@opensource.wolfsonmicro.com>
962306a36Sopenharmony_ci// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
1062306a36Sopenharmony_ci//
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1362306a36Sopenharmony_ci#include <sound/soc.h>
1462306a36Sopenharmony_ci#include <linux/bitops.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret, -1)
1762306a36Sopenharmony_ci#define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret(dai, __func__, ret, reg)
1862306a36Sopenharmony_cistatic inline int _soc_component_ret(struct snd_soc_component *component,
1962306a36Sopenharmony_ci				     const char *func, int ret, int reg)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	/* Positive/Zero values are not errors */
2262306a36Sopenharmony_ci	if (ret >= 0)
2362306a36Sopenharmony_ci		return ret;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	/* Negative values might be errors */
2662306a36Sopenharmony_ci	switch (ret) {
2762306a36Sopenharmony_ci	case -EPROBE_DEFER:
2862306a36Sopenharmony_ci	case -ENOTSUPP:
2962306a36Sopenharmony_ci		break;
3062306a36Sopenharmony_ci	default:
3162306a36Sopenharmony_ci		if (reg == -1)
3262306a36Sopenharmony_ci			dev_err(component->dev,
3362306a36Sopenharmony_ci				"ASoC: error at %s on %s: %d\n",
3462306a36Sopenharmony_ci				func, component->name, ret);
3562306a36Sopenharmony_ci		else
3662306a36Sopenharmony_ci			dev_err(component->dev,
3762306a36Sopenharmony_ci				"ASoC: error at %s on %s for register: [0x%08x] %d\n",
3862306a36Sopenharmony_ci				func, component->name, reg, ret);
3962306a36Sopenharmony_ci	}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	return ret;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic inline int soc_component_field_shift(struct snd_soc_component *component,
4562306a36Sopenharmony_ci					    unsigned int mask)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	if (!mask) {
4862306a36Sopenharmony_ci		dev_err(component->dev,	"ASoC: error field mask is zero for %s\n",
4962306a36Sopenharmony_ci			component->name);
5062306a36Sopenharmony_ci		return 0;
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	return (ffs(mask) - 1);
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*
5762306a36Sopenharmony_ci * We might want to check substream by using list.
5862306a36Sopenharmony_ci * In such case, we can update these macros.
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_ci#define soc_component_mark_push(component, substream, tgt)	((component)->mark_##tgt = substream)
6162306a36Sopenharmony_ci#define soc_component_mark_pop(component, substream, tgt)	((component)->mark_##tgt = NULL)
6262306a36Sopenharmony_ci#define soc_component_mark_match(component, substream, tgt)	((component)->mark_##tgt == substream)
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_civoid snd_soc_component_set_aux(struct snd_soc_component *component,
6562306a36Sopenharmony_ci			       struct snd_soc_aux_dev *aux)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	component->init = (aux) ? aux->init : NULL;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ciint snd_soc_component_init(struct snd_soc_component *component)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	int ret = 0;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if (component->init)
7562306a36Sopenharmony_ci		ret = component->init(component);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	return soc_component_ret(component, ret);
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/**
8162306a36Sopenharmony_ci * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
8262306a36Sopenharmony_ci * @component: COMPONENT
8362306a36Sopenharmony_ci * @clk_id: DAI specific clock ID
8462306a36Sopenharmony_ci * @source: Source for the clock
8562306a36Sopenharmony_ci * @freq: new clock frequency in Hz
8662306a36Sopenharmony_ci * @dir: new clock direction - input/output.
8762306a36Sopenharmony_ci *
8862306a36Sopenharmony_ci * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_ciint snd_soc_component_set_sysclk(struct snd_soc_component *component,
9162306a36Sopenharmony_ci				 int clk_id, int source, unsigned int freq,
9262306a36Sopenharmony_ci				 int dir)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	int ret = -ENOTSUPP;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (component->driver->set_sysclk)
9762306a36Sopenharmony_ci		ret = component->driver->set_sysclk(component, clk_id, source,
9862306a36Sopenharmony_ci						     freq, dir);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	return soc_component_ret(component, ret);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/*
10562306a36Sopenharmony_ci * snd_soc_component_set_pll - configure component PLL.
10662306a36Sopenharmony_ci * @component: COMPONENT
10762306a36Sopenharmony_ci * @pll_id: DAI specific PLL ID
10862306a36Sopenharmony_ci * @source: DAI specific source for the PLL
10962306a36Sopenharmony_ci * @freq_in: PLL input clock frequency in Hz
11062306a36Sopenharmony_ci * @freq_out: requested PLL output clock frequency in Hz
11162306a36Sopenharmony_ci *
11262306a36Sopenharmony_ci * Configures and enables PLL to generate output clock based on input clock.
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_ciint snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
11562306a36Sopenharmony_ci			      int source, unsigned int freq_in,
11662306a36Sopenharmony_ci			      unsigned int freq_out)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	int ret = -EINVAL;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (component->driver->set_pll)
12162306a36Sopenharmony_ci		ret = component->driver->set_pll(component, pll_id, source,
12262306a36Sopenharmony_ci						  freq_in, freq_out);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return soc_component_ret(component, ret);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_civoid snd_soc_component_seq_notifier(struct snd_soc_component *component,
12962306a36Sopenharmony_ci				    enum snd_soc_dapm_type type, int subseq)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	if (component->driver->seq_notifier)
13262306a36Sopenharmony_ci		component->driver->seq_notifier(component, type, subseq);
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ciint snd_soc_component_stream_event(struct snd_soc_component *component,
13662306a36Sopenharmony_ci				   int event)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	int ret = 0;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	if (component->driver->stream_event)
14162306a36Sopenharmony_ci		ret = component->driver->stream_event(component, event);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	return soc_component_ret(component, ret);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ciint snd_soc_component_set_bias_level(struct snd_soc_component *component,
14762306a36Sopenharmony_ci				     enum snd_soc_bias_level level)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	int ret = 0;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	if (component->driver->set_bias_level)
15262306a36Sopenharmony_ci		ret = component->driver->set_bias_level(component, level);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	return soc_component_ret(component, ret);
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciint snd_soc_component_enable_pin(struct snd_soc_component *component,
15862306a36Sopenharmony_ci				 const char *pin)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
16162306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
16262306a36Sopenharmony_ci	return snd_soc_dapm_enable_pin(dapm, pin);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciint snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
16762306a36Sopenharmony_ci					  const char *pin)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
17062306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
17162306a36Sopenharmony_ci	return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciint snd_soc_component_disable_pin(struct snd_soc_component *component,
17662306a36Sopenharmony_ci				  const char *pin)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
17962306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
18062306a36Sopenharmony_ci	return snd_soc_dapm_disable_pin(dapm, pin);
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ciint snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
18562306a36Sopenharmony_ci					   const char *pin)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
18862306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
18962306a36Sopenharmony_ci	return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ciint snd_soc_component_nc_pin(struct snd_soc_component *component,
19462306a36Sopenharmony_ci			     const char *pin)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
19762306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
19862306a36Sopenharmony_ci	return snd_soc_dapm_nc_pin(dapm, pin);
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ciint snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
20362306a36Sopenharmony_ci				      const char *pin)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
20662306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
20762306a36Sopenharmony_ci	return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ciint snd_soc_component_get_pin_status(struct snd_soc_component *component,
21262306a36Sopenharmony_ci				     const char *pin)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
21562306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
21662306a36Sopenharmony_ci	return snd_soc_dapm_get_pin_status(dapm, pin);
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ciint snd_soc_component_force_enable_pin(struct snd_soc_component *component,
22162306a36Sopenharmony_ci				       const char *pin)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
22462306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
22562306a36Sopenharmony_ci	return snd_soc_dapm_force_enable_pin(dapm, pin);
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ciint snd_soc_component_force_enable_pin_unlocked(
23062306a36Sopenharmony_ci	struct snd_soc_component *component,
23162306a36Sopenharmony_ci	const char *pin)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
23462306a36Sopenharmony_ci		snd_soc_component_get_dapm(component);
23562306a36Sopenharmony_ci	return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ciint snd_soc_component_notify_control(struct snd_soc_component *component,
24062306a36Sopenharmony_ci				     const char * const ctl)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
24362306a36Sopenharmony_ci	struct snd_kcontrol *kctl;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	/* When updating, change also snd_soc_dapm_widget_name_cmp() */
24662306a36Sopenharmony_ci	if (component->name_prefix)
24762306a36Sopenharmony_ci		snprintf(name, ARRAY_SIZE(name), "%s %s", component->name_prefix, ctl);
24862306a36Sopenharmony_ci	else
24962306a36Sopenharmony_ci		snprintf(name, ARRAY_SIZE(name), "%s", ctl);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	kctl = snd_soc_card_get_kcontrol(component->card, name);
25262306a36Sopenharmony_ci	if (!kctl)
25362306a36Sopenharmony_ci		return soc_component_ret(component, -EINVAL);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	snd_ctl_notify(component->card->snd_card,
25662306a36Sopenharmony_ci		       SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	return 0;
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_notify_control);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci/**
26362306a36Sopenharmony_ci * snd_soc_component_set_jack - configure component jack.
26462306a36Sopenharmony_ci * @component: COMPONENTs
26562306a36Sopenharmony_ci * @jack: structure to use for the jack
26662306a36Sopenharmony_ci * @data: can be used if codec driver need extra data for configuring jack
26762306a36Sopenharmony_ci *
26862306a36Sopenharmony_ci * Configures and enables jack detection function.
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_ciint snd_soc_component_set_jack(struct snd_soc_component *component,
27162306a36Sopenharmony_ci			       struct snd_soc_jack *jack, void *data)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	int ret = -ENOTSUPP;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (component->driver->set_jack)
27662306a36Sopenharmony_ci		ret = component->driver->set_jack(component, jack, data);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	return soc_component_ret(component, ret);
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci/**
28362306a36Sopenharmony_ci * snd_soc_component_get_jack_type
28462306a36Sopenharmony_ci * @component: COMPONENTs
28562306a36Sopenharmony_ci *
28662306a36Sopenharmony_ci * Returns the jack type of the component
28762306a36Sopenharmony_ci * This can either be the supported type or one read from
28862306a36Sopenharmony_ci * devicetree with the property: jack-type.
28962306a36Sopenharmony_ci */
29062306a36Sopenharmony_ciint snd_soc_component_get_jack_type(
29162306a36Sopenharmony_ci	struct snd_soc_component *component)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	int ret = -ENOTSUPP;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	if (component->driver->get_jack_type)
29662306a36Sopenharmony_ci		ret = component->driver->get_jack_type(component);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	return soc_component_ret(component, ret);
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_get_jack_type);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ciint snd_soc_component_module_get(struct snd_soc_component *component,
30362306a36Sopenharmony_ci				 void *mark, int upon_open)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	int ret = 0;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (component->driver->module_get_upon_open == !!upon_open &&
30862306a36Sopenharmony_ci	    !try_module_get(component->dev->driver->owner))
30962306a36Sopenharmony_ci		ret = -ENODEV;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/* mark module if succeeded */
31262306a36Sopenharmony_ci	if (ret == 0)
31362306a36Sopenharmony_ci		soc_component_mark_push(component, mark, module);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	return soc_component_ret(component, ret);
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_civoid snd_soc_component_module_put(struct snd_soc_component *component,
31962306a36Sopenharmony_ci				  void *mark, int upon_open, int rollback)
32062306a36Sopenharmony_ci{
32162306a36Sopenharmony_ci	if (rollback && !soc_component_mark_match(component, mark, module))
32262306a36Sopenharmony_ci		return;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	if (component->driver->module_get_upon_open == !!upon_open)
32562306a36Sopenharmony_ci		module_put(component->dev->driver->owner);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* remove the mark from module */
32862306a36Sopenharmony_ci	soc_component_mark_pop(component, mark, module);
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ciint snd_soc_component_open(struct snd_soc_component *component,
33262306a36Sopenharmony_ci			   struct snd_pcm_substream *substream)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	int ret = 0;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (component->driver->open)
33762306a36Sopenharmony_ci		ret = component->driver->open(component, substream);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	/* mark substream if succeeded */
34062306a36Sopenharmony_ci	if (ret == 0)
34162306a36Sopenharmony_ci		soc_component_mark_push(component, substream, open);
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	return soc_component_ret(component, ret);
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ciint snd_soc_component_close(struct snd_soc_component *component,
34762306a36Sopenharmony_ci			    struct snd_pcm_substream *substream,
34862306a36Sopenharmony_ci			    int rollback)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	int ret = 0;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (rollback && !soc_component_mark_match(component, substream, open))
35362306a36Sopenharmony_ci		return 0;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	if (component->driver->close)
35662306a36Sopenharmony_ci		ret = component->driver->close(component, substream);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	/* remove marked substream */
35962306a36Sopenharmony_ci	soc_component_mark_pop(component, substream, open);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	return soc_component_ret(component, ret);
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_civoid snd_soc_component_suspend(struct snd_soc_component *component)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	if (component->driver->suspend)
36762306a36Sopenharmony_ci		component->driver->suspend(component);
36862306a36Sopenharmony_ci	component->suspended = 1;
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_civoid snd_soc_component_resume(struct snd_soc_component *component)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	if (component->driver->resume)
37462306a36Sopenharmony_ci		component->driver->resume(component);
37562306a36Sopenharmony_ci	component->suspended = 0;
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ciint snd_soc_component_is_suspended(struct snd_soc_component *component)
37962306a36Sopenharmony_ci{
38062306a36Sopenharmony_ci	return component->suspended;
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ciint snd_soc_component_probe(struct snd_soc_component *component)
38462306a36Sopenharmony_ci{
38562306a36Sopenharmony_ci	int ret = 0;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (component->driver->probe)
38862306a36Sopenharmony_ci		ret = component->driver->probe(component);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	return soc_component_ret(component, ret);
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_civoid snd_soc_component_remove(struct snd_soc_component *component)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	if (component->driver->remove)
39662306a36Sopenharmony_ci		component->driver->remove(component);
39762306a36Sopenharmony_ci}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ciint snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
40062306a36Sopenharmony_ci				      struct device_node *ep)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	int ret = -ENOTSUPP;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	if (component->driver->of_xlate_dai_id)
40562306a36Sopenharmony_ci		ret = component->driver->of_xlate_dai_id(component, ep);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	return soc_component_ret(component, ret);
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ciint snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
41162306a36Sopenharmony_ci					const struct of_phandle_args *args,
41262306a36Sopenharmony_ci					const char **dai_name)
41362306a36Sopenharmony_ci{
41462306a36Sopenharmony_ci	if (component->driver->of_xlate_dai_name)
41562306a36Sopenharmony_ci		return component->driver->of_xlate_dai_name(component,
41662306a36Sopenharmony_ci							    args, dai_name);
41762306a36Sopenharmony_ci	/*
41862306a36Sopenharmony_ci	 * Don't use soc_component_ret here because we may not want to report
41962306a36Sopenharmony_ci	 * the error just yet. If a device has more than one component, the
42062306a36Sopenharmony_ci	 * first may not match and we don't want spam the log with this.
42162306a36Sopenharmony_ci	 */
42262306a36Sopenharmony_ci	return -ENOTSUPP;
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_civoid snd_soc_component_setup_regmap(struct snd_soc_component *component)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	int val_bytes = regmap_get_val_bytes(component->regmap);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/* Errors are legitimate for non-integer byte multiples */
43062306a36Sopenharmony_ci	if (val_bytes > 0)
43162306a36Sopenharmony_ci		component->val_bytes = val_bytes;
43262306a36Sopenharmony_ci}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci#ifdef CONFIG_REGMAP
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci/**
43762306a36Sopenharmony_ci * snd_soc_component_init_regmap() - Initialize regmap instance for the
43862306a36Sopenharmony_ci *                                   component
43962306a36Sopenharmony_ci * @component: The component for which to initialize the regmap instance
44062306a36Sopenharmony_ci * @regmap: The regmap instance that should be used by the component
44162306a36Sopenharmony_ci *
44262306a36Sopenharmony_ci * This function allows deferred assignment of the regmap instance that is
44362306a36Sopenharmony_ci * associated with the component. Only use this if the regmap instance is not
44462306a36Sopenharmony_ci * yet ready when the component is registered. The function must also be called
44562306a36Sopenharmony_ci * before the first IO attempt of the component.
44662306a36Sopenharmony_ci */
44762306a36Sopenharmony_civoid snd_soc_component_init_regmap(struct snd_soc_component *component,
44862306a36Sopenharmony_ci				   struct regmap *regmap)
44962306a36Sopenharmony_ci{
45062306a36Sopenharmony_ci	component->regmap = regmap;
45162306a36Sopenharmony_ci	snd_soc_component_setup_regmap(component);
45262306a36Sopenharmony_ci}
45362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci/**
45662306a36Sopenharmony_ci * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
45762306a36Sopenharmony_ci *                                   component
45862306a36Sopenharmony_ci * @component: The component for which to de-initialize the regmap instance
45962306a36Sopenharmony_ci *
46062306a36Sopenharmony_ci * Calls regmap_exit() on the regmap instance associated to the component and
46162306a36Sopenharmony_ci * removes the regmap instance from the component.
46262306a36Sopenharmony_ci *
46362306a36Sopenharmony_ci * This function should only be used if snd_soc_component_init_regmap() was used
46462306a36Sopenharmony_ci * to initialize the regmap instance.
46562306a36Sopenharmony_ci */
46662306a36Sopenharmony_civoid snd_soc_component_exit_regmap(struct snd_soc_component *component)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	regmap_exit(component->regmap);
46962306a36Sopenharmony_ci	component->regmap = NULL;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci#endif
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ciint snd_soc_component_compr_open(struct snd_soc_component *component,
47662306a36Sopenharmony_ci				 struct snd_compr_stream *cstream)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	int ret = 0;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	if (component->driver->compress_ops &&
48162306a36Sopenharmony_ci	    component->driver->compress_ops->open)
48262306a36Sopenharmony_ci		ret = component->driver->compress_ops->open(component, cstream);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	/* mark substream if succeeded */
48562306a36Sopenharmony_ci	if (ret == 0)
48662306a36Sopenharmony_ci		soc_component_mark_push(component, cstream, compr_open);
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	return soc_component_ret(component, ret);
48962306a36Sopenharmony_ci}
49062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_open);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_civoid snd_soc_component_compr_free(struct snd_soc_component *component,
49362306a36Sopenharmony_ci				  struct snd_compr_stream *cstream,
49462306a36Sopenharmony_ci				  int rollback)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	if (rollback && !soc_component_mark_match(component, cstream, compr_open))
49762306a36Sopenharmony_ci		return;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (component->driver->compress_ops &&
50062306a36Sopenharmony_ci	    component->driver->compress_ops->free)
50162306a36Sopenharmony_ci		component->driver->compress_ops->free(component, cstream);
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	/* remove marked substream */
50462306a36Sopenharmony_ci	soc_component_mark_pop(component, cstream, compr_open);
50562306a36Sopenharmony_ci}
50662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ciint snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd)
50962306a36Sopenharmony_ci{
51062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
51162306a36Sopenharmony_ci	struct snd_soc_component *component;
51262306a36Sopenharmony_ci	int i, ret;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
51562306a36Sopenharmony_ci		if (component->driver->compress_ops &&
51662306a36Sopenharmony_ci		    component->driver->compress_ops->trigger) {
51762306a36Sopenharmony_ci			ret = component->driver->compress_ops->trigger(
51862306a36Sopenharmony_ci				component, cstream, cmd);
51962306a36Sopenharmony_ci			if (ret < 0)
52062306a36Sopenharmony_ci				return soc_component_ret(component, ret);
52162306a36Sopenharmony_ci		}
52262306a36Sopenharmony_ci	}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	return 0;
52562306a36Sopenharmony_ci}
52662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ciint snd_soc_component_compr_set_params(struct snd_compr_stream *cstream,
52962306a36Sopenharmony_ci				       struct snd_compr_params *params)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
53262306a36Sopenharmony_ci	struct snd_soc_component *component;
53362306a36Sopenharmony_ci	int i, ret;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
53662306a36Sopenharmony_ci		if (component->driver->compress_ops &&
53762306a36Sopenharmony_ci		    component->driver->compress_ops->set_params) {
53862306a36Sopenharmony_ci			ret = component->driver->compress_ops->set_params(
53962306a36Sopenharmony_ci				component, cstream, params);
54062306a36Sopenharmony_ci			if (ret < 0)
54162306a36Sopenharmony_ci				return soc_component_ret(component, ret);
54262306a36Sopenharmony_ci		}
54362306a36Sopenharmony_ci	}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	return 0;
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params);
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ciint snd_soc_component_compr_get_params(struct snd_compr_stream *cstream,
55062306a36Sopenharmony_ci				       struct snd_codec *params)
55162306a36Sopenharmony_ci{
55262306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
55362306a36Sopenharmony_ci	struct snd_soc_component *component;
55462306a36Sopenharmony_ci	int i, ret;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
55762306a36Sopenharmony_ci		if (component->driver->compress_ops &&
55862306a36Sopenharmony_ci		    component->driver->compress_ops->get_params) {
55962306a36Sopenharmony_ci			ret = component->driver->compress_ops->get_params(
56062306a36Sopenharmony_ci				component, cstream, params);
56162306a36Sopenharmony_ci			return soc_component_ret(component, ret);
56262306a36Sopenharmony_ci		}
56362306a36Sopenharmony_ci	}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	return 0;
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params);
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ciint snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream,
57062306a36Sopenharmony_ci				     struct snd_compr_caps *caps)
57162306a36Sopenharmony_ci{
57262306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
57362306a36Sopenharmony_ci	struct snd_soc_component *component;
57462306a36Sopenharmony_ci	int i, ret = 0;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	snd_soc_dpcm_mutex_lock(rtd);
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
57962306a36Sopenharmony_ci		if (component->driver->compress_ops &&
58062306a36Sopenharmony_ci		    component->driver->compress_ops->get_caps) {
58162306a36Sopenharmony_ci			ret = component->driver->compress_ops->get_caps(
58262306a36Sopenharmony_ci				component, cstream, caps);
58362306a36Sopenharmony_ci			break;
58462306a36Sopenharmony_ci		}
58562306a36Sopenharmony_ci	}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	snd_soc_dpcm_mutex_unlock(rtd);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	return soc_component_ret(component, ret);
59062306a36Sopenharmony_ci}
59162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps);
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ciint snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream,
59462306a36Sopenharmony_ci					   struct snd_compr_codec_caps *codec)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
59762306a36Sopenharmony_ci	struct snd_soc_component *component;
59862306a36Sopenharmony_ci	int i, ret = 0;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	snd_soc_dpcm_mutex_lock(rtd);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
60362306a36Sopenharmony_ci		if (component->driver->compress_ops &&
60462306a36Sopenharmony_ci		    component->driver->compress_ops->get_codec_caps) {
60562306a36Sopenharmony_ci			ret = component->driver->compress_ops->get_codec_caps(
60662306a36Sopenharmony_ci				component, cstream, codec);
60762306a36Sopenharmony_ci			break;
60862306a36Sopenharmony_ci		}
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	snd_soc_dpcm_mutex_unlock(rtd);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	return soc_component_ret(component, ret);
61462306a36Sopenharmony_ci}
61562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ciint snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
61862306a36Sopenharmony_ci{
61962306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
62062306a36Sopenharmony_ci	struct snd_soc_component *component;
62162306a36Sopenharmony_ci	int i, ret;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
62462306a36Sopenharmony_ci		if (component->driver->compress_ops &&
62562306a36Sopenharmony_ci		    component->driver->compress_ops->ack) {
62662306a36Sopenharmony_ci			ret = component->driver->compress_ops->ack(
62762306a36Sopenharmony_ci				component, cstream, bytes);
62862306a36Sopenharmony_ci			if (ret < 0)
62962306a36Sopenharmony_ci				return soc_component_ret(component, ret);
63062306a36Sopenharmony_ci		}
63162306a36Sopenharmony_ci	}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	return 0;
63462306a36Sopenharmony_ci}
63562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_ack);
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ciint snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
63862306a36Sopenharmony_ci				    struct snd_compr_tstamp *tstamp)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
64162306a36Sopenharmony_ci	struct snd_soc_component *component;
64262306a36Sopenharmony_ci	int i, ret;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
64562306a36Sopenharmony_ci		if (component->driver->compress_ops &&
64662306a36Sopenharmony_ci		    component->driver->compress_ops->pointer) {
64762306a36Sopenharmony_ci			ret = component->driver->compress_ops->pointer(
64862306a36Sopenharmony_ci				component, cstream, tstamp);
64962306a36Sopenharmony_ci			return soc_component_ret(component, ret);
65062306a36Sopenharmony_ci		}
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	return 0;
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ciint snd_soc_component_compr_copy(struct snd_compr_stream *cstream,
65862306a36Sopenharmony_ci				 char __user *buf, size_t count)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
66162306a36Sopenharmony_ci	struct snd_soc_component *component;
66262306a36Sopenharmony_ci	int i, ret = 0;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	snd_soc_dpcm_mutex_lock(rtd);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
66762306a36Sopenharmony_ci		if (component->driver->compress_ops &&
66862306a36Sopenharmony_ci		    component->driver->compress_ops->copy) {
66962306a36Sopenharmony_ci			ret = component->driver->compress_ops->copy(
67062306a36Sopenharmony_ci				component, cstream, buf, count);
67162306a36Sopenharmony_ci			break;
67262306a36Sopenharmony_ci		}
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	snd_soc_dpcm_mutex_unlock(rtd);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	return soc_component_ret(component, ret);
67862306a36Sopenharmony_ci}
67962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_copy);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ciint snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,
68262306a36Sopenharmony_ci					 struct snd_compr_metadata *metadata)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
68562306a36Sopenharmony_ci	struct snd_soc_component *component;
68662306a36Sopenharmony_ci	int i, ret;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
68962306a36Sopenharmony_ci		if (component->driver->compress_ops &&
69062306a36Sopenharmony_ci		    component->driver->compress_ops->set_metadata) {
69162306a36Sopenharmony_ci			ret = component->driver->compress_ops->set_metadata(
69262306a36Sopenharmony_ci				component, cstream, metadata);
69362306a36Sopenharmony_ci			if (ret < 0)
69462306a36Sopenharmony_ci				return soc_component_ret(component, ret);
69562306a36Sopenharmony_ci		}
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	return 0;
69962306a36Sopenharmony_ci}
70062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata);
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ciint snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream,
70362306a36Sopenharmony_ci					 struct snd_compr_metadata *metadata)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
70662306a36Sopenharmony_ci	struct snd_soc_component *component;
70762306a36Sopenharmony_ci	int i, ret;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
71062306a36Sopenharmony_ci		if (component->driver->compress_ops &&
71162306a36Sopenharmony_ci		    component->driver->compress_ops->get_metadata) {
71262306a36Sopenharmony_ci			ret = component->driver->compress_ops->get_metadata(
71362306a36Sopenharmony_ci				component, cstream, metadata);
71462306a36Sopenharmony_ci			return soc_component_ret(component, ret);
71562306a36Sopenharmony_ci		}
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	return 0;
71962306a36Sopenharmony_ci}
72062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata);
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_cistatic unsigned int soc_component_read_no_lock(
72362306a36Sopenharmony_ci	struct snd_soc_component *component,
72462306a36Sopenharmony_ci	unsigned int reg)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci	int ret;
72762306a36Sopenharmony_ci	unsigned int val = 0;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	if (component->regmap)
73062306a36Sopenharmony_ci		ret = regmap_read(component->regmap, reg, &val);
73162306a36Sopenharmony_ci	else if (component->driver->read) {
73262306a36Sopenharmony_ci		ret = 0;
73362306a36Sopenharmony_ci		val = component->driver->read(component, reg);
73462306a36Sopenharmony_ci	}
73562306a36Sopenharmony_ci	else
73662306a36Sopenharmony_ci		ret = -EIO;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	if (ret < 0)
73962306a36Sopenharmony_ci		return soc_component_ret_reg_rw(component, ret, reg);
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	return val;
74262306a36Sopenharmony_ci}
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci/**
74562306a36Sopenharmony_ci * snd_soc_component_read() - Read register value
74662306a36Sopenharmony_ci * @component: Component to read from
74762306a36Sopenharmony_ci * @reg: Register to read
74862306a36Sopenharmony_ci *
74962306a36Sopenharmony_ci * Return: read value
75062306a36Sopenharmony_ci */
75162306a36Sopenharmony_ciunsigned int snd_soc_component_read(struct snd_soc_component *component,
75262306a36Sopenharmony_ci				    unsigned int reg)
75362306a36Sopenharmony_ci{
75462306a36Sopenharmony_ci	unsigned int val;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	mutex_lock(&component->io_mutex);
75762306a36Sopenharmony_ci	val = soc_component_read_no_lock(component, reg);
75862306a36Sopenharmony_ci	mutex_unlock(&component->io_mutex);
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	return val;
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_read);
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_cistatic int soc_component_write_no_lock(
76562306a36Sopenharmony_ci	struct snd_soc_component *component,
76662306a36Sopenharmony_ci	unsigned int reg, unsigned int val)
76762306a36Sopenharmony_ci{
76862306a36Sopenharmony_ci	int ret = -EIO;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci	if (component->regmap)
77162306a36Sopenharmony_ci		ret = regmap_write(component->regmap, reg, val);
77262306a36Sopenharmony_ci	else if (component->driver->write)
77362306a36Sopenharmony_ci		ret = component->driver->write(component, reg, val);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	return soc_component_ret_reg_rw(component, ret, reg);
77662306a36Sopenharmony_ci}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci/**
77962306a36Sopenharmony_ci * snd_soc_component_write() - Write register value
78062306a36Sopenharmony_ci * @component: Component to write to
78162306a36Sopenharmony_ci * @reg: Register to write
78262306a36Sopenharmony_ci * @val: Value to write to the register
78362306a36Sopenharmony_ci *
78462306a36Sopenharmony_ci * Return: 0 on success, a negative error code otherwise.
78562306a36Sopenharmony_ci */
78662306a36Sopenharmony_ciint snd_soc_component_write(struct snd_soc_component *component,
78762306a36Sopenharmony_ci			    unsigned int reg, unsigned int val)
78862306a36Sopenharmony_ci{
78962306a36Sopenharmony_ci	int ret;
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	mutex_lock(&component->io_mutex);
79262306a36Sopenharmony_ci	ret = soc_component_write_no_lock(component, reg, val);
79362306a36Sopenharmony_ci	mutex_unlock(&component->io_mutex);
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	return ret;
79662306a36Sopenharmony_ci}
79762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_write);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_cistatic int snd_soc_component_update_bits_legacy(
80062306a36Sopenharmony_ci	struct snd_soc_component *component, unsigned int reg,
80162306a36Sopenharmony_ci	unsigned int mask, unsigned int val, bool *change)
80262306a36Sopenharmony_ci{
80362306a36Sopenharmony_ci	unsigned int old, new;
80462306a36Sopenharmony_ci	int ret = 0;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	mutex_lock(&component->io_mutex);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	old = soc_component_read_no_lock(component, reg);
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	new = (old & ~mask) | (val & mask);
81162306a36Sopenharmony_ci	*change = old != new;
81262306a36Sopenharmony_ci	if (*change)
81362306a36Sopenharmony_ci		ret = soc_component_write_no_lock(component, reg, new);
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	mutex_unlock(&component->io_mutex);
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	return soc_component_ret_reg_rw(component, ret, reg);
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci/**
82162306a36Sopenharmony_ci * snd_soc_component_update_bits() - Perform read/modify/write cycle
82262306a36Sopenharmony_ci * @component: Component to update
82362306a36Sopenharmony_ci * @reg: Register to update
82462306a36Sopenharmony_ci * @mask: Mask that specifies which bits to update
82562306a36Sopenharmony_ci * @val: New value for the bits specified by mask
82662306a36Sopenharmony_ci *
82762306a36Sopenharmony_ci * Return: 1 if the operation was successful and the value of the register
82862306a36Sopenharmony_ci * changed, 0 if the operation was successful, but the value did not change.
82962306a36Sopenharmony_ci * Returns a negative error code otherwise.
83062306a36Sopenharmony_ci */
83162306a36Sopenharmony_ciint snd_soc_component_update_bits(struct snd_soc_component *component,
83262306a36Sopenharmony_ci				  unsigned int reg, unsigned int mask, unsigned int val)
83362306a36Sopenharmony_ci{
83462306a36Sopenharmony_ci	bool change;
83562306a36Sopenharmony_ci	int ret;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	if (component->regmap)
83862306a36Sopenharmony_ci		ret = regmap_update_bits_check(component->regmap, reg, mask,
83962306a36Sopenharmony_ci					       val, &change);
84062306a36Sopenharmony_ci	else
84162306a36Sopenharmony_ci		ret = snd_soc_component_update_bits_legacy(component, reg,
84262306a36Sopenharmony_ci							   mask, val, &change);
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	if (ret < 0)
84562306a36Sopenharmony_ci		return soc_component_ret_reg_rw(component, ret, reg);
84662306a36Sopenharmony_ci	return change;
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci/**
85162306a36Sopenharmony_ci * snd_soc_component_update_bits_async() - Perform asynchronous
85262306a36Sopenharmony_ci *  read/modify/write cycle
85362306a36Sopenharmony_ci * @component: Component to update
85462306a36Sopenharmony_ci * @reg: Register to update
85562306a36Sopenharmony_ci * @mask: Mask that specifies which bits to update
85662306a36Sopenharmony_ci * @val: New value for the bits specified by mask
85762306a36Sopenharmony_ci *
85862306a36Sopenharmony_ci * This function is similar to snd_soc_component_update_bits(), but the update
85962306a36Sopenharmony_ci * operation is scheduled asynchronously. This means it may not be completed
86062306a36Sopenharmony_ci * when the function returns. To make sure that all scheduled updates have been
86162306a36Sopenharmony_ci * completed snd_soc_component_async_complete() must be called.
86262306a36Sopenharmony_ci *
86362306a36Sopenharmony_ci * Return: 1 if the operation was successful and the value of the register
86462306a36Sopenharmony_ci * changed, 0 if the operation was successful, but the value did not change.
86562306a36Sopenharmony_ci * Returns a negative error code otherwise.
86662306a36Sopenharmony_ci */
86762306a36Sopenharmony_ciint snd_soc_component_update_bits_async(struct snd_soc_component *component,
86862306a36Sopenharmony_ci					unsigned int reg, unsigned int mask, unsigned int val)
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	bool change;
87162306a36Sopenharmony_ci	int ret;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	if (component->regmap)
87462306a36Sopenharmony_ci		ret = regmap_update_bits_check_async(component->regmap, reg,
87562306a36Sopenharmony_ci						     mask, val, &change);
87662306a36Sopenharmony_ci	else
87762306a36Sopenharmony_ci		ret = snd_soc_component_update_bits_legacy(component, reg,
87862306a36Sopenharmony_ci							   mask, val, &change);
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	if (ret < 0)
88162306a36Sopenharmony_ci		return soc_component_ret_reg_rw(component, ret, reg);
88262306a36Sopenharmony_ci	return change;
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci/**
88762306a36Sopenharmony_ci * snd_soc_component_read_field() - Read register field value
88862306a36Sopenharmony_ci * @component: Component to read from
88962306a36Sopenharmony_ci * @reg: Register to read
89062306a36Sopenharmony_ci * @mask: mask of the register field
89162306a36Sopenharmony_ci *
89262306a36Sopenharmony_ci * Return: read value of register field.
89362306a36Sopenharmony_ci */
89462306a36Sopenharmony_ciunsigned int snd_soc_component_read_field(struct snd_soc_component *component,
89562306a36Sopenharmony_ci					  unsigned int reg, unsigned int mask)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci	unsigned int val;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	val = snd_soc_component_read(component, reg);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	val = (val & mask) >> soc_component_field_shift(component, mask);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	return val;
90462306a36Sopenharmony_ci}
90562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_read_field);
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci/**
90862306a36Sopenharmony_ci * snd_soc_component_write_field() - write to register field
90962306a36Sopenharmony_ci * @component: Component to write to
91062306a36Sopenharmony_ci * @reg: Register to write
91162306a36Sopenharmony_ci * @mask: mask of the register field to update
91262306a36Sopenharmony_ci * @val: value of the field to write
91362306a36Sopenharmony_ci *
91462306a36Sopenharmony_ci * Return: 1 for change, otherwise 0.
91562306a36Sopenharmony_ci */
91662306a36Sopenharmony_ciint snd_soc_component_write_field(struct snd_soc_component *component,
91762306a36Sopenharmony_ci				  unsigned int reg, unsigned int mask,
91862306a36Sopenharmony_ci				  unsigned int val)
91962306a36Sopenharmony_ci{
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	val = (val << soc_component_field_shift(component, mask)) & mask;
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	return snd_soc_component_update_bits(component, reg, mask, val);
92462306a36Sopenharmony_ci}
92562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_write_field);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci/**
92862306a36Sopenharmony_ci * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
92962306a36Sopenharmony_ci * @component: Component for which to wait
93062306a36Sopenharmony_ci *
93162306a36Sopenharmony_ci * This function blocks until all asynchronous I/O which has previously been
93262306a36Sopenharmony_ci * scheduled using snd_soc_component_update_bits_async() has completed.
93362306a36Sopenharmony_ci */
93462306a36Sopenharmony_civoid snd_soc_component_async_complete(struct snd_soc_component *component)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	if (component->regmap)
93762306a36Sopenharmony_ci		regmap_async_complete(component->regmap);
93862306a36Sopenharmony_ci}
93962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci/**
94262306a36Sopenharmony_ci * snd_soc_component_test_bits - Test register for change
94362306a36Sopenharmony_ci * @component: component
94462306a36Sopenharmony_ci * @reg: Register to test
94562306a36Sopenharmony_ci * @mask: Mask that specifies which bits to test
94662306a36Sopenharmony_ci * @value: Value to test against
94762306a36Sopenharmony_ci *
94862306a36Sopenharmony_ci * Tests a register with a new value and checks if the new value is
94962306a36Sopenharmony_ci * different from the old value.
95062306a36Sopenharmony_ci *
95162306a36Sopenharmony_ci * Return: 1 for change, otherwise 0.
95262306a36Sopenharmony_ci */
95362306a36Sopenharmony_ciint snd_soc_component_test_bits(struct snd_soc_component *component,
95462306a36Sopenharmony_ci				unsigned int reg, unsigned int mask, unsigned int value)
95562306a36Sopenharmony_ci{
95662306a36Sopenharmony_ci	unsigned int old, new;
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	old = snd_soc_component_read(component, reg);
95962306a36Sopenharmony_ci	new = (old & ~mask) | value;
96062306a36Sopenharmony_ci	return old != new;
96162306a36Sopenharmony_ci}
96262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ciint snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
96762306a36Sopenharmony_ci	struct snd_soc_component *component;
96862306a36Sopenharmony_ci	int i;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	/* FIXME: use 1st pointer */
97162306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component)
97262306a36Sopenharmony_ci		if (component->driver->pointer)
97362306a36Sopenharmony_ci			return component->driver->pointer(component, substream);
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	return 0;
97662306a36Sopenharmony_ci}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_cistatic bool snd_soc_component_is_codec_on_rtd(struct snd_soc_pcm_runtime *rtd,
97962306a36Sopenharmony_ci					      struct snd_soc_component *component)
98062306a36Sopenharmony_ci{
98162306a36Sopenharmony_ci	struct snd_soc_dai *dai;
98262306a36Sopenharmony_ci	int i;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	for_each_rtd_codec_dais(rtd, i, dai) {
98562306a36Sopenharmony_ci		if (dai->component == component)
98662306a36Sopenharmony_ci			return true;
98762306a36Sopenharmony_ci	}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	return false;
99062306a36Sopenharmony_ci}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_civoid snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
99362306a36Sopenharmony_ci				 snd_pcm_sframes_t *cpu_delay,
99462306a36Sopenharmony_ci				 snd_pcm_sframes_t *codec_delay)
99562306a36Sopenharmony_ci{
99662306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
99762306a36Sopenharmony_ci	struct snd_soc_component *component;
99862306a36Sopenharmony_ci	snd_pcm_sframes_t delay;
99962306a36Sopenharmony_ci	int i;
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	/*
100262306a36Sopenharmony_ci	 * We're looking for the delay through the full audio path so it needs to
100362306a36Sopenharmony_ci	 * be the maximum of the Components doing transmit and the maximum of the
100462306a36Sopenharmony_ci	 * Components doing receive (ie, all CPUs and all CODECs) rather than
100562306a36Sopenharmony_ci	 * just the maximum of all Components.
100662306a36Sopenharmony_ci	 */
100762306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
100862306a36Sopenharmony_ci		if (!component->driver->delay)
100962306a36Sopenharmony_ci			continue;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci		delay = component->driver->delay(component, substream);
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci		if (snd_soc_component_is_codec_on_rtd(rtd, component))
101462306a36Sopenharmony_ci			*codec_delay = max(*codec_delay, delay);
101562306a36Sopenharmony_ci		else
101662306a36Sopenharmony_ci			*cpu_delay = max(*cpu_delay, delay);
101762306a36Sopenharmony_ci	}
101862306a36Sopenharmony_ci}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ciint snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
102162306a36Sopenharmony_ci				unsigned int cmd, void *arg)
102262306a36Sopenharmony_ci{
102362306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
102462306a36Sopenharmony_ci	struct snd_soc_component *component;
102562306a36Sopenharmony_ci	int i;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	/* FIXME: use 1st ioctl */
102862306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component)
102962306a36Sopenharmony_ci		if (component->driver->ioctl)
103062306a36Sopenharmony_ci			return soc_component_ret(
103162306a36Sopenharmony_ci				component,
103262306a36Sopenharmony_ci				component->driver->ioctl(component,
103362306a36Sopenharmony_ci							 substream, cmd, arg));
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	return snd_pcm_lib_ioctl(substream, cmd, arg);
103662306a36Sopenharmony_ci}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ciint snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
103962306a36Sopenharmony_ci{
104062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
104162306a36Sopenharmony_ci	struct snd_soc_component *component;
104262306a36Sopenharmony_ci	int i, ret;
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
104562306a36Sopenharmony_ci		if (component->driver->sync_stop) {
104662306a36Sopenharmony_ci			ret = component->driver->sync_stop(component,
104762306a36Sopenharmony_ci							   substream);
104862306a36Sopenharmony_ci			if (ret < 0)
104962306a36Sopenharmony_ci				return soc_component_ret(component, ret);
105062306a36Sopenharmony_ci		}
105162306a36Sopenharmony_ci	}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	return 0;
105462306a36Sopenharmony_ci}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ciint snd_soc_pcm_component_copy(struct snd_pcm_substream *substream,
105762306a36Sopenharmony_ci			       int channel, unsigned long pos,
105862306a36Sopenharmony_ci			       struct iov_iter *iter, unsigned long bytes)
105962306a36Sopenharmony_ci{
106062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
106162306a36Sopenharmony_ci	struct snd_soc_component *component;
106262306a36Sopenharmony_ci	int i;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	/* FIXME. it returns 1st copy now */
106562306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component)
106662306a36Sopenharmony_ci		if (component->driver->copy)
106762306a36Sopenharmony_ci			return soc_component_ret(component,
106862306a36Sopenharmony_ci				component->driver->copy(component, substream,
106962306a36Sopenharmony_ci					channel, pos, iter, bytes));
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	return -EINVAL;
107262306a36Sopenharmony_ci}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_cistruct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
107562306a36Sopenharmony_ci					unsigned long offset)
107662306a36Sopenharmony_ci{
107762306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
107862306a36Sopenharmony_ci	struct snd_soc_component *component;
107962306a36Sopenharmony_ci	struct page *page;
108062306a36Sopenharmony_ci	int i;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	/* FIXME. it returns 1st page now */
108362306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
108462306a36Sopenharmony_ci		if (component->driver->page) {
108562306a36Sopenharmony_ci			page = component->driver->page(component,
108662306a36Sopenharmony_ci						       substream, offset);
108762306a36Sopenharmony_ci			if (page)
108862306a36Sopenharmony_ci				return page;
108962306a36Sopenharmony_ci		}
109062306a36Sopenharmony_ci	}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	return NULL;
109362306a36Sopenharmony_ci}
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ciint snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
109662306a36Sopenharmony_ci			       struct vm_area_struct *vma)
109762306a36Sopenharmony_ci{
109862306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
109962306a36Sopenharmony_ci	struct snd_soc_component *component;
110062306a36Sopenharmony_ci	int i;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	/* FIXME. it returns 1st mmap now */
110362306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component)
110462306a36Sopenharmony_ci		if (component->driver->mmap)
110562306a36Sopenharmony_ci			return soc_component_ret(
110662306a36Sopenharmony_ci				component,
110762306a36Sopenharmony_ci				component->driver->mmap(component,
110862306a36Sopenharmony_ci							substream, vma));
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	return -EINVAL;
111162306a36Sopenharmony_ci}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ciint snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
111462306a36Sopenharmony_ci{
111562306a36Sopenharmony_ci	struct snd_soc_component *component;
111662306a36Sopenharmony_ci	int ret;
111762306a36Sopenharmony_ci	int i;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
112062306a36Sopenharmony_ci		if (component->driver->pcm_construct) {
112162306a36Sopenharmony_ci			ret = component->driver->pcm_construct(component, rtd);
112262306a36Sopenharmony_ci			if (ret < 0)
112362306a36Sopenharmony_ci				return soc_component_ret(component, ret);
112462306a36Sopenharmony_ci		}
112562306a36Sopenharmony_ci	}
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	return 0;
112862306a36Sopenharmony_ci}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_civoid snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	struct snd_soc_component *component;
113362306a36Sopenharmony_ci	int i;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	if (!rtd->pcm)
113662306a36Sopenharmony_ci		return;
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component)
113962306a36Sopenharmony_ci		if (component->driver->pcm_destruct)
114062306a36Sopenharmony_ci			component->driver->pcm_destruct(component, rtd->pcm);
114162306a36Sopenharmony_ci}
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ciint snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
114462306a36Sopenharmony_ci{
114562306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
114662306a36Sopenharmony_ci	struct snd_soc_component *component;
114762306a36Sopenharmony_ci	int i, ret;
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
115062306a36Sopenharmony_ci		if (component->driver->prepare) {
115162306a36Sopenharmony_ci			ret = component->driver->prepare(component, substream);
115262306a36Sopenharmony_ci			if (ret < 0)
115362306a36Sopenharmony_ci				return soc_component_ret(component, ret);
115462306a36Sopenharmony_ci		}
115562306a36Sopenharmony_ci	}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	return 0;
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ciint snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
116162306a36Sopenharmony_ci				    struct snd_pcm_hw_params *params)
116262306a36Sopenharmony_ci{
116362306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
116462306a36Sopenharmony_ci	struct snd_soc_component *component;
116562306a36Sopenharmony_ci	int i, ret;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
116862306a36Sopenharmony_ci		if (component->driver->hw_params) {
116962306a36Sopenharmony_ci			ret = component->driver->hw_params(component,
117062306a36Sopenharmony_ci							   substream, params);
117162306a36Sopenharmony_ci			if (ret < 0)
117262306a36Sopenharmony_ci				return soc_component_ret(component, ret);
117362306a36Sopenharmony_ci		}
117462306a36Sopenharmony_ci		/* mark substream if succeeded */
117562306a36Sopenharmony_ci		soc_component_mark_push(component, substream, hw_params);
117662306a36Sopenharmony_ci	}
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	return 0;
117962306a36Sopenharmony_ci}
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_civoid snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
118262306a36Sopenharmony_ci				   int rollback)
118362306a36Sopenharmony_ci{
118462306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
118562306a36Sopenharmony_ci	struct snd_soc_component *component;
118662306a36Sopenharmony_ci	int i, ret;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
118962306a36Sopenharmony_ci		if (rollback && !soc_component_mark_match(component, substream, hw_params))
119062306a36Sopenharmony_ci			continue;
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci		if (component->driver->hw_free) {
119362306a36Sopenharmony_ci			ret = component->driver->hw_free(component, substream);
119462306a36Sopenharmony_ci			if (ret < 0)
119562306a36Sopenharmony_ci				soc_component_ret(component, ret);
119662306a36Sopenharmony_ci		}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci		/* remove marked substream */
119962306a36Sopenharmony_ci		soc_component_mark_pop(component, substream, hw_params);
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_cistatic int soc_component_trigger(struct snd_soc_component *component,
120462306a36Sopenharmony_ci				 struct snd_pcm_substream *substream,
120562306a36Sopenharmony_ci				 int cmd)
120662306a36Sopenharmony_ci{
120762306a36Sopenharmony_ci	int ret = 0;
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	if (component->driver->trigger)
121062306a36Sopenharmony_ci		ret = component->driver->trigger(component, substream, cmd);
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	return soc_component_ret(component, ret);
121362306a36Sopenharmony_ci}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ciint snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
121662306a36Sopenharmony_ci				  int cmd, int rollback)
121762306a36Sopenharmony_ci{
121862306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
121962306a36Sopenharmony_ci	struct snd_soc_component *component;
122062306a36Sopenharmony_ci	int i, r, ret = 0;
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	switch (cmd) {
122362306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
122462306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
122562306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
122662306a36Sopenharmony_ci		for_each_rtd_components(rtd, i, component) {
122762306a36Sopenharmony_ci			ret = soc_component_trigger(component, substream, cmd);
122862306a36Sopenharmony_ci			if (ret < 0)
122962306a36Sopenharmony_ci				break;
123062306a36Sopenharmony_ci			soc_component_mark_push(component, substream, trigger);
123162306a36Sopenharmony_ci		}
123262306a36Sopenharmony_ci		break;
123362306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
123462306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
123562306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
123662306a36Sopenharmony_ci		for_each_rtd_components(rtd, i, component) {
123762306a36Sopenharmony_ci			if (rollback && !soc_component_mark_match(component, substream, trigger))
123862306a36Sopenharmony_ci				continue;
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci			r = soc_component_trigger(component, substream, cmd);
124162306a36Sopenharmony_ci			if (r < 0)
124262306a36Sopenharmony_ci				ret = r; /* use last ret */
124362306a36Sopenharmony_ci			soc_component_mark_pop(component, substream, trigger);
124462306a36Sopenharmony_ci		}
124562306a36Sopenharmony_ci	}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	return ret;
124862306a36Sopenharmony_ci}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ciint snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
125162306a36Sopenharmony_ci					 void *stream)
125262306a36Sopenharmony_ci{
125362306a36Sopenharmony_ci	struct snd_soc_component *component;
125462306a36Sopenharmony_ci	int i;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
125762306a36Sopenharmony_ci		int ret = pm_runtime_get_sync(component->dev);
125862306a36Sopenharmony_ci		if (ret < 0 && ret != -EACCES) {
125962306a36Sopenharmony_ci			pm_runtime_put_noidle(component->dev);
126062306a36Sopenharmony_ci			return soc_component_ret(component, ret);
126162306a36Sopenharmony_ci		}
126262306a36Sopenharmony_ci		/* mark stream if succeeded */
126362306a36Sopenharmony_ci		soc_component_mark_push(component, stream, pm);
126462306a36Sopenharmony_ci	}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	return 0;
126762306a36Sopenharmony_ci}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_civoid snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
127062306a36Sopenharmony_ci					  void *stream, int rollback)
127162306a36Sopenharmony_ci{
127262306a36Sopenharmony_ci	struct snd_soc_component *component;
127362306a36Sopenharmony_ci	int i;
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component) {
127662306a36Sopenharmony_ci		if (rollback && !soc_component_mark_match(component, stream, pm))
127762306a36Sopenharmony_ci			continue;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci		pm_runtime_mark_last_busy(component->dev);
128062306a36Sopenharmony_ci		pm_runtime_put_autosuspend(component->dev);
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci		/* remove marked stream */
128362306a36Sopenharmony_ci		soc_component_mark_pop(component, stream, pm);
128462306a36Sopenharmony_ci	}
128562306a36Sopenharmony_ci}
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ciint snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
128862306a36Sopenharmony_ci{
128962306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
129062306a36Sopenharmony_ci	struct snd_soc_component *component;
129162306a36Sopenharmony_ci	int i;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	/* FIXME: use 1st pointer */
129462306a36Sopenharmony_ci	for_each_rtd_components(rtd, i, component)
129562306a36Sopenharmony_ci		if (component->driver->ack)
129662306a36Sopenharmony_ci			return component->driver->ack(component, substream);
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	return 0;
129962306a36Sopenharmony_ci}
1300