summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2020-06-15 20:58:42 +0100
committerMark Brown <broonie@kernel.org>2020-06-15 20:58:42 +0100
commit13919056bf44dc8f70c2301915433fa2b474c1ba (patch)
treeac39f9f703aa219244b0709983cb91716f50e7e7 /sound
parentb7a742cff3f618d848e62e5a1ade0ff816e93092 (diff)
parent45108214dbfdba4a07061d2a4db6dc12475049f2 (diff)
Merge series "ASoC: soc-component: collect component functions" from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:
Hi Mark We have soc-component.c now, but still many component related functions are implemented many place. This patch-set collect these into soc-component.c. v1 -> v2 - remove soc-compress.c exchange (But I have plan to repost it) - fixup loop break issue on some functions - direct return on some functions Link: https://lore.kernel.org/r/87a71nzhy2.wl-kuninori.morimoto.gx@renesas.com Kuninori Morimoto (12): ASoC: soc-component: add soc_component_pin() and share code ASoC: soc-component: move snd_soc_component_xxx_regmap() to soc-component ASoC: soc-component: move snd_soc_component_initialize() to soc-component.c ASoC: soc-component: add soc_component_err() ASoC: soc-component: add snd_soc_pcm_component_prepare() ASoC: soc-component: add snd_soc_pcm_component_hw_params() ASoC: soc-component: add snd_soc_pcm_component_hw_free() ASoC: soc-component: add snd_soc_pcm_component_trigger() ASoC: soc-component: add snd_soc_component_init() ASoC: soc-component: merge soc-io.c into soc-component.c ASoC: soc-component: merge soc_pcm_trigger_start/stop() ASoC: soc-component: tidyup Copyright include/sound/soc-component.h | 29 +- sound/soc/Makefile | 2 +- sound/soc/soc-component.c | 666 ++++++++++++++++++++++++---------- sound/soc/soc-core.c | 102 +----- sound/soc/soc-io.c | 202 ----------- sound/soc/soc-pcm.c | 114 ++---- 6 files changed, 531 insertions(+), 584 deletions(-) delete mode 100644 sound/soc/soc-io.c -- 2.17.1
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/soc-component.c666
-rw-r--r--sound/soc/soc-core.c102
-rw-r--r--sound/soc/soc-io.c202
-rw-r--r--sound/soc/soc-pcm.c114
5 files changed, 513 insertions, 573 deletions
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 7f1747518e79..ddbac3a2169f 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o
-snd-soc-core-objs += soc-pcm.o soc-io.o soc-devres.o soc-ops.o soc-link.o soc-card.o
+snd-soc-core-objs += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o
snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o
ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 785a0385cc7f..d121f5f7633c 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -2,12 +2,69 @@
//
// soc-component.c
//
+// Copyright 2009-2011 Wolfson Microelectronics PLC.
// Copyright (C) 2019 Renesas Electronics Corp.
+//
+// Mark Brown <broonie@opensource.wolfsonmicro.com>
// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
//
#include <linux/module.h>
#include <sound/soc.h>
+#define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret)
+static inline int _soc_component_ret(struct snd_soc_component *component,
+ const char *func, int ret)
+{
+ /* Positive/Zero values are not errors */
+ if (ret >= 0)
+ return ret;
+
+ /* Negative values might be errors */
+ switch (ret) {
+ case -EPROBE_DEFER:
+ case -ENOTSUPP:
+ break;
+ default:
+ dev_err(component->dev,
+ "ASoC: error at %s on %s: %d\n",
+ func, component->name, ret);
+ }
+
+ return ret;
+}
+
+int snd_soc_component_initialize(struct snd_soc_component *component,
+ const struct snd_soc_component_driver *driver,
+ struct device *dev, const char *name)
+{
+ INIT_LIST_HEAD(&component->dai_list);
+ INIT_LIST_HEAD(&component->dobj_list);
+ INIT_LIST_HEAD(&component->card_list);
+ mutex_init(&component->io_mutex);
+
+ component->name = name;
+ component->dev = dev;
+ component->driver = driver;
+
+ return 0;
+}
+
+void snd_soc_component_set_aux(struct snd_soc_component *component,
+ struct snd_soc_aux_dev *aux)
+{
+ component->init = (aux) ? aux->init : NULL;
+}
+
+int snd_soc_component_init(struct snd_soc_component *component)
+{
+ int ret = 0;
+
+ if (component->init)
+ ret = component->init(component);
+
+ return soc_component_ret(component, ret);
+}
+
/**
* snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
* @component: COMPONENT
@@ -22,11 +79,13 @@ int snd_soc_component_set_sysclk(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq,
int dir)
{
+ int ret = -ENOTSUPP;
+
if (component->driver->set_sysclk)
- return component->driver->set_sysclk(component, clk_id, source,
+ ret = component->driver->set_sysclk(component, clk_id, source,
freq, dir);
- return -ENOTSUPP;
+ return soc_component_ret(component, ret);
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
@@ -44,11 +103,13 @@ int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
int source, unsigned int freq_in,
unsigned int freq_out)
{
+ int ret = -EINVAL;
+
if (component->driver->set_pll)
- return component->driver->set_pll(component, pll_id, source,
+ ret = component->driver->set_pll(component, pll_id, source,
freq_in, freq_out);
- return -EINVAL;
+ return soc_component_ret(component, ret);
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
@@ -62,194 +123,105 @@ void snd_soc_component_seq_notifier(struct snd_soc_component *component,
int snd_soc_component_stream_event(struct snd_soc_component *component,
int event)
{
+ int ret = 0;
+
if (component->driver->stream_event)
- return component->driver->stream_event(component, event);
+ ret = component->driver->stream_event(component, event);
- return 0;
+ return soc_component_ret(component, ret);
}
int snd_soc_component_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
+ int ret = 0;
+
if (component->driver->set_bias_level)
- return component->driver->set_bias_level(component, level);
+ ret = component->driver->set_bias_level(component, level);
- return 0;
+ return soc_component_ret(component, ret);
}
-int snd_soc_component_enable_pin(struct snd_soc_component *component,
- const char *pin)
+static int soc_component_pin(struct snd_soc_component *component,
+ const char *pin,
+ int (*pin_func)(struct snd_soc_dapm_context *dapm,
+ const char *pin))
{
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
char *full_name;
int ret;
- if (!component->name_prefix)
- return snd_soc_dapm_enable_pin(dapm, pin);
+ if (!component->name_prefix) {
+ ret = pin_func(dapm, pin);
+ goto end;
+ }
full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
+ if (!full_name) {
+ ret = -ENOMEM;
+ goto end;
+ }
- ret = snd_soc_dapm_enable_pin(dapm, full_name);
+ ret = pin_func(dapm, full_name);
kfree(full_name);
+end:
+ return soc_component_ret(component, ret);
+}
- return ret;
+int snd_soc_component_enable_pin(struct snd_soc_component *component,
+ const char *pin)
+{
+ return soc_component_pin(component, pin, snd_soc_dapm_enable_pin);
}
EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked);
}
EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
int snd_soc_component_disable_pin(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_disable_pin(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_disable_pin(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_disable_pin);
}
EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked);
}
EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
int snd_soc_component_nc_pin(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_nc_pin(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_nc_pin(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_nc_pin);
}
EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked);
}
EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
int snd_soc_component_get_pin_status(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_get_pin_status(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_get_pin_status(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status);
}
EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_force_enable_pin(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_force_enable_pin(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin);
}
EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
@@ -257,22 +229,7 @@ int snd_soc_component_force_enable_pin_unlocked(
struct snd_soc_component *component,
const char *pin)
{
- struct snd_soc_dapm_context *dapm =
- snd_soc_component_get_dapm(component);
- char *full_name;
- int ret;
-
- if (!component->name_prefix)
- return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
-
- full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
- if (!full_name)
- return -ENOMEM;
-
- ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name);
- kfree(full_name);
-
- return ret;
+ return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked);
}
EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
@@ -287,21 +244,25 @@ EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
int snd_soc_component_set_jack(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data)
{
+ int ret = -ENOTSUPP;
+
if (component->driver->set_jack)
- return component->driver->set_jack(component, jack, data);
+ ret = component->driver->set_jack(component, jack, data);
- return -ENOTSUPP;
+ return soc_component_ret(component, ret);
}
EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
int snd_soc_component_module_get(struct snd_soc_component *component,
int upon_open)
{
+ int ret = 0;
+
if (component->driver->module_get_upon_open == !!upon_open &&
!try_module_get(component->dev->driver->owner))
- return -ENODEV;
+ ret = -ENODEV;
- return 0;
+ return soc_component_ret(component, ret);
}
void snd_soc_component_module_put(struct snd_soc_component *component,
@@ -314,52 +275,23 @@ void snd_soc_component_module_put(struct snd_soc_component *component,
int snd_soc_component_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
+ int ret = 0;
+
if (component->driver->open)
- return component->driver->open(component, substream);
- return 0;
+ ret = component->driver->open(component, substream);
+
+ return soc_component_ret(component, ret);
}
int snd_soc_component_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- if (component->driver->close)
- return component->driver->close(component, substream);
- return 0;
-}
-
-int snd_soc_component_prepare(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- if (component->driver->prepare)
- return component->driver->prepare(component, substream);
- return 0;
-}
+ int ret = 0;
-int snd_soc_component_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- if (component->driver->hw_params)
- return component->driver->hw_params(component,
- substream, params);
- return 0;
-}
-
-int snd_soc_component_hw_free(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- if (component->driver->hw_free)
- return component->driver->hw_free(component, substream);
- return 0;
-}
+ if (component->driver->close)
+ ret = component->driver->close(component, substream);
-int snd_soc_component_trigger(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- int cmd)
-{
- if (component->driver->trigger)
- return component->driver->trigger(component, substream, cmd);
- return 0;
+ return soc_component_ret(component, ret);
}
void snd_soc_component_suspend(struct snd_soc_component *component)
@@ -383,10 +315,12 @@ int snd_soc_component_is_suspended(struct snd_soc_component *component)
int snd_soc_component_probe(struct snd_soc_component *component)
{
+ int ret = 0;
+
if (component->driver->probe)
- return component->driver->probe(component);
+ ret = component->driver->probe(component);
- return 0;
+ return soc_component_ret(component, ret);
}
void snd_soc_component_remove(struct snd_soc_component *component)
@@ -398,21 +332,267 @@ void snd_soc_component_remove(struct snd_soc_component *component)
int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
struct device_node *ep)
{
+ int ret = -ENOTSUPP;
+
if (component->driver->of_xlate_dai_id)
- return component->driver->of_xlate_dai_id(component, ep);
+ ret = component->driver->of_xlate_dai_id(component, ep);
- return -ENOTSUPP;
+ return soc_component_ret(component, ret);
}
int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
struct of_phandle_args *args,
const char **dai_name)
{
+ int ret = -ENOTSUPP;
+
if (component->driver->of_xlate_dai_name)
- return component->driver->of_xlate_dai_name(component,
- args, dai_name);
- return -ENOTSUPP;
+ ret = component->driver->of_xlate_dai_name(component,
+ args, dai_name);
+
+ return soc_component_ret(component, ret);
+}
+
+void snd_soc_component_setup_regmap(struct snd_soc_component *component)
+{
+ int val_bytes = regmap_get_val_bytes(component->regmap);
+
+ /* Errors are legitimate for non-integer byte multiples */
+ if (val_bytes > 0)
+ component->val_bytes = val_bytes;
+}
+
+#ifdef CONFIG_REGMAP
+
+/**
+ * snd_soc_component_init_regmap() - Initialize regmap instance for the
+ * component
+ * @component: The component for which to initialize the regmap instance
+ * @regmap: The regmap instance that should be used by the component
+ *
+ * This function allows deferred assignment of the regmap instance that is
+ * associated with the component. Only use this if the regmap instance is not
+ * yet ready when the component is registered. The function must also be called
+ * before the first IO attempt of the component.
+ */
+void snd_soc_component_init_regmap(struct snd_soc_component *component,
+ struct regmap *regmap)
+{
+ component->regmap = regmap;
+ snd_soc_component_setup_regmap(component);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
+
+/**
+ * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
+ * component
+ * @component: The component for which to de-initialize the regmap instance
+ *
+ * Calls regmap_exit() on the regmap instance associated to the component and
+ * removes the regmap instance from the component.
+ *
+ * This function should only be used if snd_soc_component_init_regmap() was used
+ * to initialize the regmap instance.
+ */
+void snd_soc_component_exit_regmap(struct snd_soc_component *component)
+{
+ regmap_exit(component->regmap);
+ component->regmap = NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
+
+#endif
+
+/**
+ * snd_soc_component_read() - Read register value
+ * @component: Component to read from
+ * @reg: Register to read
+ * @val: Pointer to where the read value is stored
+ *
+ * Return: 0 on success, a negative error code otherwise.
+ */
+int snd_soc_component_read(struct snd_soc_component *component,
+ unsigned int reg, unsigned int *val)
+{
+ int ret;
+
+ if (component->regmap)
+ ret = regmap_read(component->regmap, reg, val);
+ else if (component->driver->read) {
+ *val = component->driver->read(component, reg);
+ ret = 0;
+ }
+ else
+ ret = -EIO;
+
+ return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_read);
+
+unsigned int snd_soc_component_read32(struct snd_soc_component *component,
+ unsigned int reg)
+{
+ unsigned int val;
+ int ret;
+
+ ret = snd_soc_component_read(component, reg, &val);
+ if (ret < 0)
+ return soc_component_ret(component, -1);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_read32);
+
+/**
+ * snd_soc_component_write() - Write register value
+ * @component: Component to write to
+ * @reg: Register to write
+ * @val: Value to write to the register
+ *
+ * Return: 0 on success, a negative error code otherwise.
+ */
+int snd_soc_component_write(struct snd_soc_component *component,
+ unsigned int reg, unsigned int val)
+{
+ int ret = -EIO;
+
+ if (component->regmap)
+ ret = regmap_write(component->regmap, reg, val);
+ else if (component->driver->write)
+ ret = component->driver->write(component, reg, val);
+
+ return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_write);
+
+static int snd_soc_component_update_bits_legacy(
+ struct snd_soc_component *component, unsigned int reg,
+ unsigned int mask, unsigned int val, bool *change)
+{
+ unsigned int old, new;
+ int ret;
+
+ mutex_lock(&component->io_mutex);
+
+ ret = snd_soc_component_read(component, reg, &old);
+ if (ret < 0)
+ goto out_unlock;
+
+ new = (old & ~mask) | (val & mask);
+ *change = old != new;
+ if (*change)
+ ret = snd_soc_component_write(component, reg, new);
+out_unlock:
+ mutex_unlock(&component->io_mutex);
+
+ return soc_component_ret(component, ret);
+}
+
+/**
+ * snd_soc_component_update_bits() - Perform read/modify/write cycle
+ * @component: Component to update
+ * @reg: Register to update
+ * @mask: Mask that specifies which bits to update
+ * @val: New value for the bits specified by mask
+ *
+ * Return: 1 if the operation was successful and the value of the register
+ * changed, 0 if the operation was successful, but the value did not change.
+ * Returns a negative error code otherwise.
+ */
+int snd_soc_component_update_bits(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask, unsigned int val)
+{
+ bool change;
+ int ret;
+
+ if (component->regmap)
+ ret = regmap_update_bits_check(component->regmap, reg, mask,
+ val, &change);
+ else
+ ret = snd_soc_component_update_bits_legacy(component, reg,
+ mask, val, &change);
+
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ return change;
}
+EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
+
+/**
+ * snd_soc_component_update_bits_async() - Perform asynchronous
+ * read/modify/write cycle
+ * @component: Component to update
+ * @reg: Register to update
+ * @mask: Mask that specifies which bits to update
+ * @val: New value for the bits specified by mask
+ *
+ * This function is similar to snd_soc_component_update_bits(), but the update
+ * operation is scheduled asynchronously. This means it may not be completed
+ * when the function returns. To make sure that all scheduled updates have been
+ * completed snd_soc_component_async_complete() must be called.
+ *
+ * Return: 1 if the operation was successful and the value of the register
+ * changed, 0 if the operation was successful, but the value did not change.
+ * Returns a negative error code otherwise.
+ */
+int snd_soc_component_update_bits_async(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask, unsigned int val)
+{
+ bool change;
+ int ret;
+
+ if (component->regmap)
+ ret = regmap_update_bits_check_async(component->regmap, reg,
+ mask, val, &change);
+ else
+ ret = snd_soc_component_update_bits_legacy(component, reg,
+ mask, val, &change);
+
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ return change;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
+
+/**
+ * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
+ * @component: Component for which to wait
+ *
+ * This function blocks until all asynchronous I/O which has previously been
+ * scheduled using snd_soc_component_update_bits_async() has completed.
+ */
+void snd_soc_component_async_complete(struct snd_soc_component *component)
+{
+ if (component->regmap)
+ regmap_async_complete(component->regmap);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
+
+/**
+ * snd_soc_component_test_bits - Test register for change
+ * @component: component
+ * @reg: Register to test
+ * @mask: Mask that specifies which bits to test
+ * @value: Value to test against
+ *
+ * Tests a register with a new value and checks if the new value is
+ * different from the old value.
+ *
+ * Return: 1 for change, otherwise 0.
+ */
+int snd_soc_component_test_bits(struct snd_soc_component *component,
+ unsigned int reg, unsigned int mask, unsigned int value)
+{
+ unsigned int old, new;
+ int ret;
+
+ ret = snd_soc_component_read(component, reg, &old);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ new = (old & ~mask) | value;
+ return old != new;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
{
@@ -438,8 +618,10 @@ int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
/* FIXME: use 1st ioctl */
for_each_rtd_components(rtd, i, component)
if (component->driver->ioctl)
- return component->driver->ioctl(component, substream,
- cmd, arg);
+ return soc_component_ret(
+ component,
+ component->driver->ioctl(component,
+ substream, cmd, arg));
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
@@ -455,7 +637,7 @@ int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
ret = component->driver->sync_stop(component,
substream);
if (ret < 0)
- return ret;
+ soc_component_ret(component, ret);
}
}
@@ -473,8 +655,11 @@ int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
/* FIXME. it returns 1st copy now */
for_each_rtd_components(rtd, i, component)
if (component->driver->copy_user)
- return component->driver->copy_user(
- component, substream, channel, pos, buf, bytes);
+ return soc_component_ret(
+ component,
+ component->driver->copy_user(
+ component, substream, channel,
+ pos, buf, bytes));
return -EINVAL;
}
@@ -510,8 +695,10 @@ int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
/* FIXME. it returns 1st mmap now */
for_each_rtd_components(rtd, i, component)
if (component->driver->mmap)
- return component->driver->mmap(component,
- substream, vma);
+ soc_component_ret(
+ component,
+ component->driver->mmap(component,
+ substream, vma));
return -EINVAL;
}
@@ -526,7 +713,7 @@ int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
if (component->driver->pcm_construct) {
ret = component->driver->pcm_construct(component, rtd);
if (ret < 0)
- return ret;
+ soc_component_ret(component, ret);
}
}
@@ -545,3 +732,80 @@ void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
if (component->driver->pcm_destruct)
component->driver->pcm_destruct(component, rtd->pcm);
}
+
+int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->prepare) {
+ ret = component->driver->prepare(component, substream);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+
+int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_component **last)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->hw_params) {
+ ret = component->driver->hw_params(component,
+ substream, params);
+ if (ret < 0) {
+ *last = component;
+ return soc_component_ret(component, ret);
+ }
+ }
+ }
+
+ *last = NULL;
+ return 0;
+}
+
+void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_component *last)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component == last)
+ break;
+
+ if (component->driver->hw_free) {
+ ret = component->driver->hw_free(component, substream);
+ if (ret < 0)
+ soc_component_ret(component, ret);
+ }
+ }
+}
+
+int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->trigger) {
+ ret = component->driver->trigger(component, substream, cmd);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 0f30f5aabaa8..c38bb423e695 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1208,15 +1208,14 @@ static int soc_probe_component(struct snd_soc_card *card,
component->name);
probed = 1;
- /* machine specific init */
- if (component->init) {
- ret = component->init(component);
- if (ret < 0) {
- dev_err(component->dev,
- "Failed to do machine specific init %d\n", ret);
- goto err_probe;
- }
- }
+ /*
+ * machine specific init
+ * see
+ * snd_soc_component_set_aux()
+ */
+ ret = snd_soc_component_init(component);
+ if (ret < 0)
+ goto err_probe;
ret = snd_soc_add_component_controls(component,
component->driver->controls,
@@ -1330,7 +1329,8 @@ static void soc_unbind_aux_dev(struct snd_soc_card *card)
struct snd_soc_component *component, *_component;
for_each_card_auxs_safe(card, component, _component) {
- component->init = NULL;
+ /* for snd_soc_component_init() */
+ snd_soc_component_set_aux(component, NULL);
list_del(&component->card_aux_list);
}
}
@@ -1347,7 +1347,8 @@ static int soc_bind_aux_dev(struct snd_soc_card *card)
if (!component)
return -EPROBE_DEFER;
- component->init = aux->init;
+ /* for snd_soc_component_init() */
+ snd_soc_component_set_aux(component, aux);
/* see for_each_card_auxs */
list_add(&component->card_aux_list, &card->aux_comp_list);
}
@@ -2378,76 +2379,6 @@ err:
return ret;
}
-static int snd_soc_component_initialize(struct snd_soc_component *component,
- const struct snd_soc_component_driver *driver, struct device *dev)
-{
- INIT_LIST_HEAD(&component->dai_list);
- INIT_LIST_HEAD(&component->dobj_list);
- INIT_LIST_HEAD(&component->card_list);
- mutex_init(&component->io_mutex);
-
- component->name = fmt_single_name(dev, &component->id);
- if (!component->name) {
- dev_err(dev, "ASoC: Failed to allocate name\n");
- return -ENOMEM;
- }
-
- component->dev = dev;
- component->driver = driver;
-
- return 0;
-}
-
-static void snd_soc_component_setup_regmap(struct snd_soc_component *component)
-{
- int val_bytes = regmap_get_val_bytes(component->regmap);
-
- /* Errors are legitimate for non-integer byte multiples */
- if (val_bytes > 0)
- component->val_bytes = val_bytes;
-}
-
-#ifdef CONFIG_REGMAP
-
-/**
- * snd_soc_component_init_regmap() - Initialize regmap instance for the
- * component
- * @component: The component for which to initialize the regmap instance
- * @regmap: The regmap instance that should be used by the component
- *
- * This function allows deferred assignment of the regmap instance that is
- * associated with the component. Only use this if the regmap instance is not
- * yet ready when the component is registered. The function must also be called
- * before the first IO attempt of the component.
- */
-void snd_soc_component_init_regmap(struct snd_soc_component *component,
- struct regmap *regmap)
-{
- component->regmap = regmap;
- snd_soc_component_setup_regmap(component);
-}
-EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
-
-/**
- * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
- * component
- * @component: The component for which to de-initialize the regmap instance
- *
- * Calls regmap_exit() on the regmap instance associated to the component and
- * removes the regmap instance from the component.
- *
- * This function should only be used if snd_soc_component_init_regmap() was used
- * to initialize the regmap instance.
- */
-void snd_soc_component_exit_regmap(struct snd_soc_component *component)
-{
- regmap_exit(component->regmap);
- component->regmap = NULL;
-}
-EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
-
-#endif
-
#define ENDIANNESS_MAP(name) \
(SNDRV_PCM_FMTBIT_##name##LE | SNDRV_PCM_FMTBIT_##name##BE)
static u64 endianness_format_map[] = {
@@ -2510,12 +2441,19 @@ int snd_soc_add_component(struct device *dev,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
+ const char *name = fmt_single_name(dev, &component->id);
int ret;
int i;
+ if (!name) {
+ dev_err(dev, "ASoC: Failed to allocate name\n");
+ return -ENOMEM;
+ }
+
mutex_lock(&client_mutex);
- ret = snd_soc_component_initialize(component, component_driver, dev);
+ ret = snd_soc_component_initialize(component, component_driver,
+ dev, name);
if (ret)
goto err_free;
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
deleted file mode 100644
index 1ff9175e9d5e..000000000000
--- a/sound/soc/soc-io.c
+++ /dev/null
@@ -1,202 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-//
-// soc-io.c -- ASoC register I/O helpers
-//
-// Copyright 2009-2011 Wolfson Microelectronics PLC.
-//
-// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
-
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
-#include <linux/regmap.h>
-#include <linux/export.h>
-#include <sound/soc.h>
-
-/**
- * snd_soc_component_read() - Read register value
- * @component: Component to read from
- * @reg: Register to read