summaryrefslogtreecommitdiff
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/Kconfig13
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ad1836.c2
-rw-r--r--sound/soc/codecs/ad1980.c2
-rw-r--r--sound/soc/codecs/adau1372.c2
-rw-r--r--sound/soc/codecs/adau1373.c2
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/adau1761.c2
-rw-r--r--sound/soc/codecs/adau1781.c2
-rw-r--r--sound/soc/codecs/adau1977.c2
-rw-r--r--sound/soc/codecs/adau7118-i2c.c2
-rw-r--r--sound/soc/codecs/adav80x.c2
-rw-r--r--sound/soc/codecs/audio-iio-aux.c344
-rw-r--r--sound/soc/codecs/cs35l36.c2
-rw-r--r--sound/soc/codecs/cs35l41-lib.c122
-rw-r--r--sound/soc/codecs/cs35l41.c18
-rw-r--r--sound/soc/codecs/cs35l45-tables.c4
-rw-r--r--sound/soc/codecs/cs35l56-i2c.c14
-rw-r--r--sound/soc/codecs/cs35l56-sdw.c72
-rw-r--r--sound/soc/codecs/cs35l56-shared.c482
-rw-r--r--sound/soc/codecs/cs35l56-spi.c10
-rw-r--r--sound/soc/codecs/cs35l56.c649
-rw-r--r--sound/soc/codecs/cs35l56.h15
-rw-r--r--sound/soc/codecs/cs4265.c2
-rw-r--r--sound/soc/codecs/cs4270.c2
-rw-r--r--sound/soc/codecs/cs42l51.c2
-rw-r--r--sound/soc/codecs/cs42l52.c2
-rw-r--r--sound/soc/codecs/cs42l56.c2
-rw-r--r--sound/soc/codecs/cs42xx8.c2
-rw-r--r--sound/soc/codecs/cs4349.c2
-rw-r--r--sound/soc/codecs/es8316.c5
-rw-r--r--sound/soc/codecs/es8326.c75
-rw-r--r--sound/soc/codecs/es8326.h9
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c10
-rw-r--r--sound/soc/codecs/lpass-tx-macro.c10
-rw-r--r--sound/soc/codecs/lpass-va-macro.c6
-rw-r--r--sound/soc/codecs/lpass-wsa-macro.c10
-rw-r--r--sound/soc/codecs/msm8916-wcd-analog.c56
-rw-r--r--sound/soc/codecs/nau8825.c93
-rw-r--r--sound/soc/codecs/rt5645.c50
-rw-r--r--sound/soc/codecs/rt5677.c117
-rw-r--r--sound/soc/codecs/rt5677.h92
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c2
-rw-r--r--sound/soc/codecs/rt722-sdca.c3
-rw-r--r--sound/soc/codecs/sigmadsp.c25
-rw-r--r--sound/soc/codecs/tas2781-i2c.c1
-rw-r--r--sound/soc/codecs/wcd9335.c2
-rw-r--r--sound/soc/codecs/wcd938x-sdw.c2
-rw-r--r--sound/soc/codecs/wm2200.c2
-rw-r--r--sound/soc/codecs/wm5100.c2
-rw-r--r--sound/soc/codecs/wm8510.c2
-rw-r--r--sound/soc/codecs/wm8523.c2
-rw-r--r--sound/soc/codecs/wm8580.c2
-rw-r--r--sound/soc/codecs/wm8711.c2
-rw-r--r--sound/soc/codecs/wm8728.c2
-rw-r--r--sound/soc/codecs/wm8731.c2
-rw-r--r--sound/soc/codecs/wm8737.c2
-rw-r--r--sound/soc/codecs/wm8741.c2
-rw-r--r--sound/soc/codecs/wm8750.c2
-rw-r--r--sound/soc/codecs/wm8753.c2
-rw-r--r--sound/soc/codecs/wm8770.c2
-rw-r--r--sound/soc/codecs/wm8776.c2
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8900.c2
-rw-r--r--sound/soc/codecs/wm8903.c2
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8940.c2
-rw-r--r--sound/soc/codecs/wm8955.c2
-rw-r--r--sound/soc/codecs/wm8960.c12
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c2
-rw-r--r--sound/soc/codecs/wm8971.c2
-rw-r--r--sound/soc/codecs/wm8978.c2
-rw-r--r--sound/soc/codecs/wm8983.c2
-rw-r--r--sound/soc/codecs/wm8985.c2
-rw-r--r--sound/soc/codecs/wm8988.c2
-rw-r--r--sound/soc/codecs/wm8991.c2
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8995.c2
-rw-r--r--sound/soc/codecs/wm8996.c2
-rw-r--r--sound/soc/codecs/wm9081.c2
-rw-r--r--sound/soc/codecs/wm9090.c2
-rw-r--r--sound/soc/codecs/wm9705.c2
-rw-r--r--sound/soc/codecs/wm9712.c2
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wsa881x.c2
-rw-r--r--sound/soc/codecs/wsa883x.c2
87 files changed, 1361 insertions, 1076 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c2de4ee72183..88c3dbe47d71 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_AK5558
imply SND_SOC_ALC5623
imply SND_SOC_ALC5632
+ imply SND_SOC_AUDIO_IIO_AUX
imply SND_SOC_AW8738
imply SND_SOC_AW88395
imply SND_SOC_BT_SCO
@@ -614,6 +615,17 @@ config SND_SOC_ALC5632
tristate
depends on I2C
+config SND_SOC_AUDIO_IIO_AUX
+ tristate "Audio IIO Auxiliary device"
+ depends on IIO
+ help
+ Enable support for Industrial I/O devices as audio auxiliary devices.
+ This allows to have an IIO device present in the audio path and
+ controlled using mixer controls.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-soc-audio-iio-aux.
+
config SND_SOC_AW8738
tristate "Awinic AW8738 Audio Amplifier"
select GPIOLIB
@@ -1708,6 +1720,7 @@ config SND_SOC_STA529
config SND_SOC_STAC9766
tristate
depends on SND_SOC_AC97_BUS
+ select REGMAP_AC97
config SND_SOC_STI_SAS
tristate "codec Audio support for STI SAS codec"
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index b48a9a323b84..32dcc6de58bd 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -45,6 +45,7 @@ snd-soc-ak4671-objs := ak4671.o
snd-soc-ak5386-objs := ak5386.o
snd-soc-ak5558-objs := ak5558.o
snd-soc-arizona-objs := arizona.o arizona-jack.o
+snd-soc-audio-iio-aux-objs := audio-iio-aux.o
snd-soc-aw8738-objs := aw8738.o
snd-soc-aw88395-lib-objs := aw88395/aw88395_lib.o
snd-soc-aw88395-objs := aw88395/aw88395.o \
@@ -428,6 +429,7 @@ obj-$(CONFIG_SND_SOC_AK5558) += snd-soc-ak5558.o
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_ARIZONA) += snd-soc-arizona.o
+obj-$(CONFIG_SND_SOC_AUDIO_IIO_AUX) += snd-soc-audio-iio-aux.o
obj-$(CONFIG_SND_SOC_AW8738) += snd-soc-aw8738.o
obj-$(CONFIG_SND_SOC_AW88395_LIB) += snd-soc-aw88395-lib.o
obj-$(CONFIG_SND_SOC_AW88395) +=snd-soc-aw88395.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 2c64df96b5ce..949077108bef 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -358,7 +358,7 @@ static const struct regmap_config ad1836_regmap_config = {
.max_register = AD1836_ADC_CTRL3,
.reg_defaults = ad1836_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int ad1836_spi_probe(struct spi_device *spi)
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 5e777d7fd5d9..3c1ae13c1aae 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -92,7 +92,7 @@ static const struct regmap_config ad1980_regmap_config = {
.reg_stride = 2,
.val_bits = 16,
.max_register = 0x7e,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = regmap_ac97_default_volatile,
.readable_reg = ad1980_readable_reg,
diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
index d9bde7eb043a..98380a7ce64d 100644
--- a/sound/soc/codecs/adau1372.c
+++ b/sound/soc/codecs/adau1372.c
@@ -1056,7 +1056,7 @@ const struct regmap_config adau1372_regmap_config = {
.reg_defaults = adau1372_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adau1372_reg_defaults),
.volatile_reg = adau1372_volatile_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(adau1372_regmap_config);
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index c5b087b8fffc..b0ab0a69b207 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1451,7 +1451,7 @@ static const struct regmap_config adau1373_regmap_config = {
.volatile_reg = adau1373_register_volatile,
.max_register = ADAU1373_SOFT_RESET,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = adau1373_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults),
};
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 8c8de3b3c901..94831aad7ac6 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -778,7 +778,7 @@ static const struct regmap_config adau1701_regmap = {
.reg_bits = 16,
.val_bits = 32,
.max_register = ADAU1701_MAX_REGISTER,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = adau1701_volatile_reg,
.reg_write = adau1701_reg_write,
.reg_read = adau1701_reg_read,
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c
index 3ccc7acac205..1f09ea385f8a 100644
--- a/sound/soc/codecs/adau1761.c
+++ b/sound/soc/codecs/adau1761.c
@@ -1014,7 +1014,7 @@ const struct regmap_config adau1761_regmap_config = {
.readable_reg = adau1761_readable_register,
.volatile_reg = adau17x1_volatile_register,
.precious_reg = adau17x1_precious_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(adau1761_regmap_config);
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c
index ff6be24863bf..faad2f9f8dd2 100644
--- a/sound/soc/codecs/adau1781.c
+++ b/sound/soc/codecs/adau1781.c
@@ -472,7 +472,7 @@ const struct regmap_config adau1781_regmap_config = {
.readable_reg = adau1781_readable_register,
.volatile_reg = adau17x1_volatile_register,
.precious_reg = adau17x1_precious_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(adau1781_regmap_config);
diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c
index 7a9672f94fc6..ae59efb38f26 100644
--- a/sound/soc/codecs/adau1977.c
+++ b/sound/soc/codecs/adau1977.c
@@ -991,7 +991,7 @@ const struct regmap_config adau1977_regmap_config = {
.max_register = ADAU1977_REG_DC_HPF_CAL,
.volatile_reg = adau1977_register_volatile,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = adau1977_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults),
};
diff --git a/sound/soc/codecs/adau7118-i2c.c b/sound/soc/codecs/adau7118-i2c.c
index 73f181f7757e..b302b28eca7c 100644
--- a/sound/soc/codecs/adau7118-i2c.c
+++ b/sound/soc/codecs/adau7118-i2c.c
@@ -43,7 +43,7 @@ static const struct regmap_config adau7118_regmap_config = {
.val_bits = 8,
.reg_defaults = adau7118_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adau7118_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = ADAU7118_REG_RESET,
.volatile_reg = adau7118_volatile,
};
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index fcff35f26cec..bb08969c5917 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -870,7 +870,7 @@ const struct regmap_config adav80x_regmap_config = {
.max_register = ADAV80X_PLL_OUTE,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = adav80x_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
};
diff --git a/sound/soc/codecs/audio-iio-aux.c b/sound/soc/codecs/audio-iio-aux.c
new file mode 100644
index 000000000000..a8bf14239bd7
--- /dev/null
+++ b/sound/soc/codecs/audio-iio-aux.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// ALSA SoC glue to use IIO devices as audio components
+//
+// Copyright 2023 CS GROUP France
+//
+// Author: Herve Codina <herve.codina@bootlin.com>
+
+#include <linux/iio/consumer.h>
+#include <linux/minmax.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string_helpers.h>
+
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+struct audio_iio_aux_chan {
+ struct iio_channel *iio_chan;
+ const char *name;
+ int max;
+ int min;
+ bool is_invert_range;
+};
+
+struct audio_iio_aux {
+ struct device *dev;
+ struct audio_iio_aux_chan *chans;
+ unsigned int num_chans;
+};
+
+static int audio_iio_aux_info_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value;
+
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = chan->max - chan->min;
+ uinfo->type = (uinfo->value.integer.max == 1) ?
+ SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+ return 0;
+}
+
+static int audio_iio_aux_get_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value;
+ int max = chan->max;
+ int min = chan->min;
+ bool invert_range = chan->is_invert_range;
+ int ret;
+ int val;
+
+ ret = iio_read_channel_raw(chan->iio_chan, &val);
+ if (ret < 0)
+ return ret;
+
+ ucontrol->value.integer.value[0] = val - min;
+ if (invert_range)
+ ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
+static int audio_iio_aux_put_volsw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value;
+ int max = chan->max;
+ int min = chan->min;
+ bool invert_range = chan->is_invert_range;
+ int val;
+ int ret;
+ int tmp;
+
+ val = ucontrol->value.integer.value[0];
+ if (val < 0)
+ return -EINVAL;
+ if (val > max - min)
+ return -EINVAL;
+
+ val = val + min;
+ if (invert_range)
+ val = max - val;
+
+ ret = iio_read_channel_raw(chan->iio_chan, &tmp);
+ if (ret < 0)
+ return ret;
+
+ if (tmp == val)
+ return 0;
+
+ ret = iio_write_channel_raw(chan->iio_chan, val);
+ if (ret)
+ return ret;
+
+ return 1; /* The value changed */
+}
+
+static int audio_iio_aux_add_controls(struct snd_soc_component *component,
+ struct audio_iio_aux_chan *chan)
+{
+ struct snd_kcontrol_new control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = chan->name,
+ .info = audio_iio_aux_info_volsw,
+ .get = audio_iio_aux_get_volsw,
+ .put = audio_iio_aux_put_volsw,
+ .private_value = (unsigned long)chan,
+ };
+
+ return snd_soc_add_component_controls(component, &control, 1);
+}
+
+/*
+ * These data could be on stack but they are pretty big.
+ * As ASoC internally copy them and protect them against concurrent accesses
+ * (snd_soc_bind_card() protects using client_mutex), keep them in the global
+ * data area.
+ */
+static struct snd_soc_dapm_widget widgets[3];
+static struct snd_soc_dapm_route routes[2];
+
+/* Be sure sizes are correct (need 3 widgets and 2 routes) */
+static_assert(ARRAY_SIZE(widgets) >= 3, "3 widgets are needed");
+static_assert(ARRAY_SIZE(routes) >= 2, "2 routes are needed");
+
+static int audio_iio_aux_add_dapms(struct snd_soc_component *component,
+ struct audio_iio_aux_chan *chan)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+ char *output_name;
+ char *input_name;
+ char *pga_name;
+ int ret;
+
+ input_name = kasprintf(GFP_KERNEL, "%s IN", chan->name);
+ if (!input_name)
+ return -ENOMEM;
+
+ output_name = kasprintf(GFP_KERNEL, "%s OUT", chan->name);
+ if (!output_name) {
+ ret = -ENOMEM;
+ goto out_free_input_name;
+ }
+
+ pga_name = kasprintf(GFP_KERNEL, "%s PGA", chan->name);
+ if (!pga_name) {
+ ret = -ENOMEM;
+ goto out_free_output_name;
+ }
+
+ widgets[0] = SND_SOC_DAPM_INPUT(input_name);
+ widgets[1] = SND_SOC_DAPM_OUTPUT(output_name);
+ widgets[2] = SND_SOC_DAPM_PGA(pga_name, SND_SOC_NOPM, 0, 0, NULL, 0);
+ ret = snd_soc_dapm_new_controls(dapm, widgets, 3);
+ if (ret)
+ goto out_free_pga_name;
+
+ routes[0].sink = pga_name;
+ routes[0].control = NULL;
+ routes[0].source = input_name;
+ routes[1].sink = output_name;
+ routes[1].control = NULL;
+ routes[1].source = pga_name;
+ ret = snd_soc_dapm_add_routes(dapm, routes, 2);
+
+ /* Allocated names are no more needed (duplicated in ASoC internals) */
+
+out_free_pga_name:
+ kfree(pga_name);
+out_free_output_name:
+ kfree(output_name);
+out_free_input_name:
+ kfree(input_name);
+ return ret;
+}
+
+static int audio_iio_aux_component_probe(struct snd_soc_component *component)
+{
+ struct audio_iio_aux *iio_aux = snd_soc_component_get_drvdata(component);
+ struct audio_iio_aux_chan *chan;
+ int ret;
+ int i;
+
+ for (i = 0; i < iio_aux->num_chans; i++) {
+ chan = iio_aux->chans + i;
+
+ ret = iio_read_max_channel_raw(chan->iio_chan, &chan->max);
+ if (ret)
+ return dev_err_probe(component->dev, ret,
+ "chan[%d] %s: Cannot get max raw value\n",
+ i, chan->name);
+
+ ret = iio_read_min_channel_raw(chan->iio_chan, &chan->min);
+ if (ret)
+ return dev_err_probe(component->dev, ret,
+ "chan[%d] %s: Cannot get min raw value\n",
+ i, chan->name);
+
+ if (chan->min > chan->max) {
+ /*
+ * This should never happen but to avoid any check
+ * later, just swap values here to ensure that the
+ * minimum value is lower than the maximum value.
+ */
+ dev_dbg(component->dev, "chan[%d] %s: Swap min and max\n",
+ i, chan->name);
+ swap(chan->min, chan->max);
+ }
+
+ /* Set initial value */
+ ret = iio_write_channel_raw(chan->iio_chan,
+ chan->is_invert_range ? chan->max : chan->min);
+ if (ret)
+ return dev_err_probe(component->dev, ret,
+ "chan[%d] %s: Cannot set initial value\n",
+ i, chan->name);
+
+ ret = audio_iio_aux_add_controls(component, chan);
+ if (ret)
+ return ret;
+
+ ret = audio_iio_aux_add_dapms(component, chan);
+ if (ret)
+ return ret;
+
+ dev_dbg(component->dev, "chan[%d]: Added %s (min=%d, max=%d, invert=%s)\n",
+ i, chan->name, chan->min, chan->max,
+ str_on_off(chan->is_invert_range));
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver audio_iio_aux_component_driver = {
+ .probe = audio_iio_aux_component_probe,
+};
+
+static int audio_iio_aux_probe(struct platform_device *pdev)
+{
+ struct audio_iio_aux_chan *iio_aux_chan;
+ struct device *dev = &pdev->dev;
+ struct audio_iio_aux *iio_aux;
+ const char **names;
+ u32 *invert_ranges;
+ int count;
+ int ret;
+ int i;
+
+ iio_aux = devm_kzalloc(dev, sizeof(*iio_aux), GFP_KERNEL);
+ if (!iio_aux)
+ return -ENOMEM;
+
+ iio_aux->dev = dev;
+
+ count = device_property_string_array_count(dev, "io-channel-names");
+ if (count < 0)
+ return dev_err_probe(dev, count, "failed to count io-channel-names\n");
+
+ iio_aux->num_chans = count;
+
+ iio_aux->chans = devm_kmalloc_array(dev, iio_aux->num_chans,
+ sizeof(*iio_aux->chans), GFP_KERNEL);
+ if (!iio_aux->chans)
+ return -ENOMEM;
+
+ names = kcalloc(iio_aux->num_chans, sizeof(*names), GFP_KERNEL);
+ if (!names)
+ return -ENOMEM;
+
+ invert_ranges = kcalloc(iio_aux->num_chans, sizeof(*invert_ranges), GFP_KERNEL);
+ if (!invert_ranges) {
+ ret = -ENOMEM;
+ goto out_free_names;
+ }
+
+ ret = device_property_read_string_array(dev, "io-channel-names",
+ names, iio_aux->num_chans);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "failed to read io-channel-names\n");
+ goto out_free_invert_ranges;
+ }
+
+ /*
+ * snd-control-invert-range is optional and can contain fewer items
+ * than the number of channels. Unset values default to 0.
+ */
+ count = device_property_count_u32(dev, "snd-control-invert-range");
+ if (count > 0) {
+ count = min_t(unsigned int, count, iio_aux->num_chans);
+ ret = device_property_read_u32_array(dev, "snd-control-invert-range",
+ invert_ranges, count);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "failed to read snd-control-invert-range\n");
+ goto out_free_invert_ranges;
+ }
+ }
+
+ for (i = 0; i < iio_aux->num_chans; i++) {
+ iio_aux_chan = iio_aux->chans + i;
+ iio_aux_chan->name = names[i];
+ iio_aux_chan->is_invert_range = invert_ranges[i];
+
+ iio_aux_chan->iio_chan = devm_iio_channel_get(dev, iio_aux_chan->name);
+ if (IS_ERR(iio_aux_chan->iio_chan)) {
+ ret = PTR_ERR(iio_aux_chan->iio_chan);
+ dev_err_probe(dev, ret, "get IIO channel '%s' failed\n",
+ iio_aux_chan->name);
+ goto out_free_invert_ranges;
+ }
+ }
+
+ platform_set_drvdata(pdev, iio_aux);
+
+ ret = devm_snd_soc_register_component(dev, &audio_iio_aux_component_driver,
+ NULL, 0);
+out_free_invert_ranges:
+ kfree(invert_ranges);
+out_free_names:
+ kfree(names);
+ return ret;
+}
+
+static const struct of_device_id audio_iio_aux_ids[] = {
+ { .compatible = "audio-iio-aux" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, audio_iio_aux_ids);
+
+static struct platform_driver audio_iio_aux_driver = {
+ .driver = {
+ .name = "audio-iio-aux",
+ .of_match_table = audio_iio_aux_ids,
+ },
+ .probe = audio_iio_aux_probe,
+};
+module_platform_driver(audio_iio_aux_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("IIO ALSA SoC aux driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
index 04ba7f25012e..20084c7d3acb 100644
--- a/sound/soc/codecs/cs35l36.c
+++ b/sound/soc/codecs/cs35l36.c
@@ -1312,7 +1312,7 @@ static struct regmap_config cs35l36_regmap = {
.precious_reg = cs35l36_precious_reg,
.volatile_reg = cs35l36_volatile_reg,
.readable_reg = cs35l36_readable_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static irqreturn_t cs35l36_irq(int irq, void *data)
diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c
index 1e4205295a0d..4ec306cd2f47 100644
--- a/sound/soc/codecs/cs35l41-lib.c
+++ b/sound/soc/codecs/cs35l41-lib.c
@@ -743,7 +743,7 @@ struct regmap_config cs35l41_regmap_i2c = {
.volatile_reg = cs35l41_volatile_reg,
.readable_reg = cs35l41_readable_reg,
.precious_reg = cs35l41_precious_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(cs35l41_regmap_i2c);
@@ -760,7 +760,7 @@ struct regmap_config cs35l41_regmap_spi = {
.volatile_reg = cs35l41_volatile_reg,
.readable_reg = cs35l41_readable_reg,
.precious_reg = cs35l41_precious_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
@@ -1080,28 +1080,32 @@ static const struct reg_sequence cs35l41_safe_to_reset[] = {
{ 0x00000040, 0x00000033 },
};
-static const struct reg_sequence cs35l41_active_to_safe[] = {
+static const struct reg_sequence cs35l41_active_to_safe_start[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x00007438, 0x00585941 },
{ CS35L41_PWR_CTRL1, 0x00000000 },
- { 0x0000742C, 0x00000009, 3000 },
+ { 0x0000742C, 0x00000009 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe_end[] = {
{ 0x00007438, 0x00580941 },
{ 0x00000040, 0x000000CC },
{ 0x00000040, 0x00000033 },
};
-static const struct reg_sequence cs35l41_safe_to_active[] = {
+static const struct reg_sequence cs35l41_safe_to_active_start[] = {
{ 0x00000040, 0x00000055 },
{ 0x00000040, 0x000000AA },
{ 0x0000742C, 0x0000000F },
{ 0x0000742C, 0x00000079 },
{ 0x00007438, 0x00585941 },
- { CS35L41_PWR_CTRL1, 0x00000001, 3000 }, // GLOBAL_EN = 1
+ { CS35L41_PWR_CTRL1, 0x00000001 }, // GLOBAL_EN = 1
+};
+
+static const struct reg_sequence cs35l41_safe_to_active_en_spk[] = {
{ 0x0000742C, 0x000000F9 },
{ 0x00007438, 0x00580941 },
- { 0x00000040, 0x000000CC },
- { 0x00000040, 0x00000033 },
};
static const struct reg_sequence cs35l41_reset_to_safe[] = {
@@ -1188,11 +1192,12 @@ bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type)
}
EXPORT_SYMBOL_GPL(cs35l41_safe_reset);
-int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable,
- struct completion *pll_lock)
+int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type,
+ int enable, struct completion *pll_lock, bool firmware_running)
{
int ret;
- unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3;
+ unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3, int_status, pup_pdn_mask;
+ unsigned int pwr_ctl1_val;
struct reg_sequence cs35l41_mdsync_down_seq[] = {
{CS35L41_PWR_CTRL3, 0},
{CS35L41_GPIO_PAD_CONTROL, 0},
@@ -1204,6 +1209,20 @@ int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type,
{CS35L41_PWR_CTRL1, 0x00000001, 3000},
};
+ pup_pdn_mask = enable ? CS35L41_PUP_DONE_MASK : CS35L41_PDN_DONE_MASK;
+
+ ret = regmap_read(regmap, CS35L41_PWR_CTRL1, &pwr_ctl1_val);
+ if (ret)
+ return ret;
+
+ if ((pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && enable) {
+ dev_dbg(dev, "Cannot set Global Enable - already set.\n");
+ return 0;
+ } else if (!(pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && !enable) {
+ dev_dbg(dev, "Cannot unset Global Enable - not set.\n");
+ return 0;
+ }
+
switch (b_type) {
case CS35L41_SHD_BOOST_ACTV:
case CS35L41_SHD_BOOST_PASS:
@@ -1240,20 +1259,85 @@ int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type,
ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_up_seq,
ARRAY_SIZE(cs35l41_mdsync_up_seq));
}
+
+ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1,
+ int_status, int_status & pup_pdn_mask,
+ 1000, 100000);
+ if (ret)
+ dev_err(dev, "Enable(%d) failed: %d\n", enable, ret);
+
+ // Clear PUP/PDN status
+ regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask);
break;
case CS35L41_INT_BOOST:
ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK,
enable << CS35L41_GLOBAL_EN_SHIFT);
- usleep_range(3000, 3100);
+ if (ret) {
+ dev_err(dev, "CS35L41_PWR_CTRL1 set failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1,
+ int_status, int_status & pup_pdn_mask,
+ 1000, 100000);
+ if (ret)
+ dev_err(dev, "Enable(%d) failed: %d\n", enable, ret);
+
+ /* Clear PUP/PDN status */
+ regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask);
break;
case CS35L41_EXT_BOOST:
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
- if (enable)
- ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active,
- ARRAY_SIZE(cs35l41_safe_to_active));
- else
- ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe,
- ARRAY_SIZE(cs35l41_active_to_safe));
+ if (enable) {
+ /* Test Key is unlocked here */
+ ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active_start,
+ ARRAY_SIZE(cs35l41_safe_to_active_start));
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status,
+ int_status & CS35L41_PUP_DONE_MASK, 1000, 100000);
+ if (ret) {
+ dev_err(dev, "Failed waiting for CS35L41_PUP_DONE_MASK: %d\n", ret);
+ /* Lock the test key, it was unlocked during the multi_reg_write */
+ cs35l41_test_key_lock(dev, regmap);
+ return ret;
+ }
+ regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PUP_DONE_MASK);
+
+ if (firmware_running)
+ ret = cs35l41_set_cspl_mbox_cmd(dev, regmap,
+ CSPL_MBOX_CMD_SPK_OUT_ENABLE);
+ else
+ ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active_en_spk,
+ ARRAY_SIZE(cs35l41_safe_to_active_en_spk));
+
+ /* Lock the test key, it was unlocked during the multi_reg_write */
+ cs35l41_test_key_lock(dev, regmap);
+ } else {
+ /* Test Key is unlocked here */
+ ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_start,
+ ARRAY_SIZE(cs35l41_active_to_safe_start));
+ if (ret) {
+ /* Lock the test key, it was unlocked during the multi_reg_write */
+ cs35l41_test_key_lock(dev, regmap);
+ return ret;
+ }
+
+ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status,
+ int_status & CS35L41_PDN_DONE_MASK, 1000, 100000);
+ if (ret) {
+ dev_err(dev, "Failed waiting for CS35L41_PDN_DONE_MASK: %d\n", ret);
+ /* Lock the test key, it was unlocked during the multi_reg_write */
+ cs35l41_test_key_lock(dev, regmap);
+ return ret;
+ }
+ regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PDN_DONE_MASK);
+
+ /* Test Key is locked here */
+ ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_end,
+ ARRAY_SIZE(cs35l41_active_to_safe_end));
+ }
break;
default:
ret = -EINVAL;
@@ -1344,6 +1428,8 @@ static bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd,
return (sts == CSPL_MBOX_STS_RUNNING);
case CSPL_MBOX_CMD_STOP_PRE_REINIT:
return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT);
+ case CSPL_MBOX_CMD_SPK_OUT_ENABLE:
+ return (sts == CSPL_MBOX_STS_RUNNING);
default:
return false;
}
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 8a879b6f4829..722b69a6de26 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -491,7 +491,6 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
- unsigned int val;
int ret = 0;
switch (event) {
@@ -500,21 +499,12 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
cs35l41_pup_patch,
ARRAY_SIZE(cs35l41_pup_patch));
- cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1,
- &cs35l41->pll_lock);
+ ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type,
+ 1, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running);
break;
case SND_SOC_DAPM_POST_PMD:
- cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0,
- &cs35l41->pll_lock);
-
- ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
- val, val & CS35L41_PDN_DONE_MASK,
- 1000, 100000);
- if (ret)
- dev_warn(cs35l41->dev, "PDN failed: %d\n", ret);
-
- regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
- CS35L41_PDN_DONE_MASK);
+ ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type,
+ 0, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running);
regmap_multi_reg_write_bypassed(cs35l41->regmap,
cs35l41_pdn_patch,
diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c
index 066f83c0c7ac..621af1785979 100644
--- a/sound/soc/codecs/cs35l45-tables.c
+++ b/sound/soc/codecs/cs35l45-tables.c
@@ -255,7 +255,7 @@ const struct regmap_config cs35l45_i2c_regmap = {
.num_reg_defaults = ARRAY_SIZE(cs35l45_defaults),
.volatile_reg = cs35l45_volatile_reg,
.readable_reg = cs35l45_readable_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_NS_GPL(cs35l45_i2c_regmap, SND_SOC_CS35L45);
@@ -271,7 +271,7 @@ const struct regmap_config cs35l45_spi_regmap = {
.num_reg_defaults = ARRAY_SIZE(cs35l45_defaults),
.volatile_reg = cs35l45_volatile_reg,
.readable_reg = cs35l45_readable_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_NS_GPL(cs35l45_spi_regmap, SND_SOC_CS35L45);
diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c
index 40666e6698ba..9f4f2f4f23f5 100644
--- a/sound/soc/codecs/cs35l56-i2c.c
+++ b/sound/soc/codecs/cs35l56-i2c.c
@@ -26,14 +26,14 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
if (!cs35l56)
return -ENOMEM;
- cs35l56->dev = dev;
- cs35l56->can_hibernate = true;
+ cs35l56->base.dev = dev;
+ cs35l56->base.can_hibernate = true;
i2c_set_clientdata(client, cs35l56);
- cs35l56->regmap = devm_regmap_init_i2c(client, regmap_config);
- if (IS_ERR(cs35l56->regmap)) {
- ret = PTR_ERR(cs35l56->regmap);
- return dev_err_probe(cs35l56->dev, ret, "Failed to allocate register map\n");
+ cs35l56->base.regmap = devm_regmap_init_i2c(client, regmap_config);
+ if (IS_ERR(cs35l56->base.regmap)) {
+ ret = PTR_ERR(cs35l56->base.regmap);
+ return dev_err_probe(cs35l56->base.dev, ret, "Failed to allocate register map\n");
}
ret = cs35l56_common_probe(cs35l56);
@@ -42,7 +42,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
ret = cs35l56_init(cs35l56);
if (ret == 0)
- ret = cs35l56_irq_request(cs35l56, client->irq);
+ ret = cs35l56_irq_request(&cs35l56->base, client->irq);
if (ret < 0)
cs35l56_remove(cs35l56);
diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c
index 2cde78605ba9..b433266b7844 100644
--- a/sound/soc/codecs/cs35l56-sdw.c
+++ b/sound/soc/codecs/cs35l56-sdw.c
@@ -166,13 +166,13 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
int ret;
- pm_runtime_get_noresume(cs35l56->dev);
+ pm_runtime_get_noresume(cs35l56->base.dev);
- regcache_cache_only(cs35l56->regmap, false);
+ regcache_cache_only(cs35l56->base.regmap, false);
ret = cs35l56_init(cs35l56);
if (ret < 0) {
- regcache_cache_only(cs35l56->regmap, true);
+ regcache_cache_only(cs35l56->base.regmap, true);
goto out;
}
@@ -180,15 +180,15 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
* cs35l56_init can return with !init_done if it triggered
* a soft reset.
*/
- if (cs35l56->init_done) {
+ if (cs35l56->base.init_done) {
/* Enable SoundWire interrupts */
sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1,
CS35L56_SDW_INT_MASK_CODEC_IRQ);
}
out:
- pm_runtime_mark_last_busy(cs35l56->dev);
- pm_runtime_put_autosuspend(cs35l56->dev);
+ pm_runtime_mark_last_busy(cs35l56->base.dev);
+ pm_runtime_put_autosuspend(cs35l56->base.dev);
}
static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral,
@@ -198,7 +198,7 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral,
/* SoundWire core holds our pm_runtime when calling this function. */
- dev_dbg(cs35l56->dev, "int control_port=%#x\n", status->control_port);
+ dev_dbg(cs35l56->base.dev, "int control_port=%#x\n", status->control_port);
if ((status->control_port & SDW_SCP_INT1_IMPL_DEF) == 0)
return 0;
@@ -207,7 +207,7 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral,
* Prevent bus manager suspending and possibly issuing a
* bus-reset before the queued work has run.
*/
- pm_runtime_get_noresume(cs35l56->dev);
+ pm_runtime_get_noresume(cs35l56->base.dev);
/*
* Mask and clear until it has been handled. The read of GEN_INT_STAT_1
@@ -230,14 +230,14 @@ static void cs35l56_sdw_irq_work(struct work_struct *work)
struct cs35l56_private,
sdw_irq_work);
- cs35l56_irq(-1, cs35l56);
+ cs35l56_irq(-1, &cs35l56->base);
/* unmask interrupts */
if (!cs35l56->sdw_irq_no_unmask)
sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1,
CS35L56_SDW_INT_MASK_CODEC_IRQ);
- pm_runtime_put_autosuspend(cs35l56->dev);
+ pm_runtime_put_autosuspend(cs35l56->base.dev);
}
static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral)
@@ -246,7 +246,7 @@ static int cs35l56_sdw_read_prop(struct sdw_slave *peripheral)
struct sdw_slave_prop *prop = &peripheral->prop;
struct sdw_dpn_prop *ports;
- ports = devm_kcalloc(cs35l56->dev, 2, sizeof(*ports), GFP_KERNEL);
+ ports = devm_kcalloc(cs35l56->base.dev, 2, sizeof(*ports), GFP_KERNEL);
if (!ports)
return -ENOMEM;
@@ -279,17 +279,17 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
switch (status) {
case SDW_SLAVE_ATTACHED:
- dev_dbg(cs35l56->dev, "%s: ATTACHED\n", __func__);
+ dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__);
if (cs35l56->sdw_attached)
break;
- if (!cs35l56->init_done || cs35l56->soft_resetting)
+ if (!cs35l56->base.init_done || cs35l56->soft_resetting)
cs35l56_sdw_init(peripheral);
cs35l56->sdw_attached = true;
break;
case SDW_SLAVE_UNATTACHED:
- dev_dbg(cs35l56->dev, "%s: UNATTACHED\n", __func__);
+ dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__);
cs35l56->sdw_attached = false;
break;
default:
@@ -305,7 +305,7 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56,
unsigned int curr_scale_reg, next_scale_reg;
int curr_scale, next_scale, ret;
- if (!cs35l56->init_done)
+ if (!cs35l56->base.init_done)
return 0;
if (peripheral->bus->params.curr_bank) {
@@ -324,13 +324,13 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56,
*/
curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg);
if (curr_scale < 0) {
- dev_err(cs35l56->dev, "Failed to read current clock scale: %d\n", curr_scale);
+ dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale);
return curr_scale;
}
next_scale = sdw_read_no_pm(peripheral, next_scale_reg);
if (next_scale < 0) {
- dev_err(cs35l56->dev, "Failed to read next clock scale: %d\n", next_scale);
+ dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale);
return next_scale;
}
@@ -338,7 +338,8 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56,
next_scale = cs35l56->old_sdw_clock_scale;
ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale);
if (ret < 0) {
- dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret);
+ dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n",
+ ret);
return ret;
}
}
@@ -346,11 +347,11 @@ static int cs35l56_a1_kick_divider(struct cs35l56_private *cs35l56,
cs35l56->old_sdw_clock_scale = curr_scale;
ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE);
if (ret < 0) {
- dev_err(cs35l56->dev, "Failed to modify current clock scale: %d\n", ret);
+ dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret);
return ret;
}
- dev_dbg(cs35l56->dev, "Next bus scale: %#x\n", next_scale);
+ dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale);
return 0;
}
@@ -362,9 +363,10 @@ static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral,
int sclk;
sclk = params->curr_dr_freq / 2;
- dev_dbg(cs35l56->dev, "%s: sclk=%u c=%u r=%u\n", __func__, sclk, params->col, params->row);
+ dev_dbg(cs35l56->base.dev, "%s: sclk=%u c=%u r=%u\n",
+ __func__, sclk, params->col, params->row);
- if (cs35l56->rev < 0xb0)
+ if (cs35l56->base.rev < 0xb0)
return cs35l56_a1_kick_divider(cs35l56, peripheral);
return 0;
@@ -376,7 +378,7 @@ static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral,
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
- dev_dbg(cs35l56->dev, "%s: mode:%d type:%d\n", __func__, mode, type);
+ dev_dbg(cs35l56->base.dev, "%s: mode:%d type:%d\n", __func__, mode, type);
return 0;
}
@@ -397,10 +399,10 @@ static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs
if (peripheral->unattach_request) {
/* Cannot access registers until bus is re-initialized. */
- dev_dbg(cs35l56->dev, "Wait for initialization_complete\n");
+ dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n");
if (!wait_for_completion_timeout(&peripheral->initialization_complete,
msecs_to_jiffies(5000))) {
- dev_err(cs35l56->dev, "initialization_complete timed out\n");
+ dev_err(cs35l56->base.dev, "initialization_complete timed out\n");
return -ETIMEDOUT;
}
@@ -419,10 +421,10 @@ static int __maybe_unused cs35l56_sdw_runtime_suspend(struct device *dev)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
- if (!cs35l56->init_done)
+ if (!cs35l56->base.init_done)
return 0;
- return cs35l56_runtime_suspend(dev);
+ return cs35l56_runtime_suspend_common(&cs35l56->base);
}
static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev)
@@ -432,14 +434,14 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev)
dev_dbg(dev, "Runtime resume\n");
- if (!cs35l56->init_done)
+ if (!cs35l56->base.init_done)
return 0;
ret = cs35l56_sdw_handle_unattach(cs35l56);
if (ret < 0)
return ret;
- ret = cs35l56_runtime_resume_common(cs35l56);
+ ret = cs35l56_runtime_resume_common(&cs35l56->base, true);
if (ret)
return ret;
@@ -454,7 +456,7 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
- if (!cs35l56->init_done)
+ if (!cs35l56->base.init_done)
return 0;
/*
@@ -493,21 +495,21 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi
if (!cs35l56)
return -ENOMEM;
- cs35l56->dev = dev;
+ cs35l56->base.dev = dev;
cs35l56->sdw_peripheral = peripheral;
INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work);
dev_set_drvdata(dev, cs35l56);
- cs35l56->regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw,
+ cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw,
peripheral, &cs35l56_regmap_sdw);
- if (IS_ERR(cs35l56->regmap)) {
- ret = PTR_ERR(cs35l56->regmap);
+ if (IS_ERR(cs35l56->base.regmap)) {
+ ret = PTR_ERR(cs35l56->base.regmap);
return dev_err_probe(dev, ret, "Failed to allocate register map\n");
}
/* Start in cache-only until device is enumerated */
- regcache_cache_only(cs35l56->regmap, true);
+ regcache_cache_only(cs35l56->base.regmap, true);
ret = cs35l56_common_probe(cs35l56);
if (ret != 0)
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index 60da8c75b7b9..ae373f335ea8 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -11,6 +11,20 @@
#include "cs35l56.h"
+static const struct reg_sequence cs35l56_patch[] = {
+ /* These are not reset by a soft-reset, so patch to defaults. */
+ { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
+ { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
+ { CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
+};
+
+int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)
+{
+ return regmap_register_patch(cs35l56_base->regmap, cs35l56_patch,
+ ARRAY_SIZE(cs35l56_patch));
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
+
static const struct reg_default cs35l56_reg_defaults[] = {
{ CS35L56_ASP1_ENABLES1, 0x00000000 },
{ CS35L56_ASP1_CONTROL1, 0x00000028 },
@@ -35,9 +49,9 @@ static const struct reg_default cs35l56_reg_defaults[] = {
{ CS35L56_IRQ1_MASK_8, 0xfc000fff },
{ CS35L56_IRQ1_MASK_18, 0x1f7df0ff },
{ CS35L56_IRQ1_MASK_20, 0x15c00000 },
- /* CS35L56_MAIN_RENDER_USER_MUTE - soft register, no default */
- /* CS35L56_MAIN_RENDER_USER_VOLUME - soft register, no default */
- /* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default */
+ { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
+ { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
+ { CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
};
static bool cs35l56_is_dsp_memory(unsigned int reg)
@@ -181,33 +195,463 @@ static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
}
}
-static const u32 cs35l56_firmware_registers[] = {
- CS35L56_MAIN_RENDER_USER_MUTE,
- CS35L56_MAIN_RENDER_USER_VOLUME,
- CS35L56_MAIN_POSTURE_NUMBER,
+int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)
+{
+ unsigned int val;
+ int ret;
+
+ regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command);
+ ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
+ val, (val == 0),
+ CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);
+ if (ret) {
+ dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);
+
+int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
+{
+ int ret;
+ unsigned int reg;
+ unsigned int val;
+
+ ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN);
+ if (ret)
+ return ret;
+
+ if (cs35l56_base->rev < CS35L56_REVID_B0)
+ reg = CS35L56_DSP1_PM_CUR_STATE_A1;
+ else
+ reg = CS35L56_DSP1_PM_CUR_STATE;
+
+ ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg,
+ val, (val == CS35L56_HALO_STATE_SHUTDOWN),
+ CS35L56_HALO_STATE_POLL_US,
+ CS35L56_HALO_STATE_TIMEOUT_US);
+ if (ret < 0)
+ dev_err(cs35l56_base->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",
+ val, ret);
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);
+
+int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
+{
+ unsigned int reg;
+ unsigned int val;
+ int ret;
+
+ if (cs35l56_base->rev < CS35L56_REVID_B0)
+ reg = CS35L56_DSP1_HALO_STATE_A1;
+ else
+ reg = CS35L56_DSP1_HALO_STATE;
+
+ ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg,
+ val,
+ (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
+ CS35L56_HALO_STATE_POLL_US,
+ CS35L56_HALO_STATE_TIMEOUT_US);
+
+ if ((ret < 0) && (ret != -ETIMEDOUT)) {
+ dev_err(cs35l56_base->dev, "Failed to read HALO_STATE: %d\n", ret);
+ return ret;
+ }
+
+ if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) {
+ dev_err(cs35l56_base->dev, "Firmware boot fail: HALO_STATE=%#x\n", val);
+ return -EIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED);
+
+void cs35l56_wait_control_port_ready(void)
+{
+ /* Wait for control port to be ready (datasheet tIRS). */
+ usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED);
+
+void cs35l56_wait_min_reset_pulse(void)
+{
+ /* Satisfy minimum reset pulse width spec */
+ usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED);
+
+static const struct reg_sequence cs35l56_system_reset_seq[] = {
+ REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
};
-void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap)
+void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
+{
+ /*
+ * Must enter cache-only first so there can't be any more register
+ * accesses other than the controlled system reset sequence below.
+ */
+ regcache_cache_only(cs35l56_base->regmap, true);
+ regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
+ cs35l56_system_reset_seq,
+ ARRAY_SIZE(cs35l56_system_reset_seq));
+
+ /* On SoundWire the registers won't be accessible until it re-enumerates. */
+ if (is_soundwire)
+ return;
+
+ cs35l56_wait_control_port_ready();
+ regcache_cache_only(cs35l56_base->regmap, false);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
+
+int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
+{
+ int ret;
+
+ if (!irq)
+ return 0;
+
+ ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq,
+ IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
+ "cs35l56", cs35l56_base);
+ if (!ret)
+ cs35l56_base->irq = irq;
+ else
+ dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED);
+
+irqreturn_t cs35l56_irq(int irq, void *data)
+{
+ struct cs35l56_base *cs35l56_base = data;
+ unsigned int status1 = 0, status8 = 0, status20 = 0;
+ unsigned int mask1, mask8, mask20;
+ unsigned int val;
+ int rv;
+
+ irqreturn_t ret = IRQ_NONE;
+
+ if (!cs35l56_base->init_done)
+ return IRQ_NONE;
+
+ mutex_lock(&cs35l56_base->irq_lock);
+
+ rv = pm_runtime_resume_and_get(cs35l56_base->dev);
+ if (rv < 0) {
+ dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv);
+ goto err_unlock;
+ }
+
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);
+ if ((val & CS35L56_IRQ1_STS_MASK) == 0) {
+ dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n");
+ goto err;
+ }
+
+ /* Ack interrupts */
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1);
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1);
+ status1 &= ~mask1;
+ regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1);
+
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8);
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8);
+ status8 &= ~mask8;
+ regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8);
+
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20);
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20);
+ status20 &= ~mask20;
+ /* We don't want EINT20 but they default to unmasked: force mask */
+ regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
+
+ dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8);
+
+ /* Check to see if unmasked bits are active */
+ if (!status1 && !status8 && !status20)
+ goto err;
+
+ if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)
+ dev_crit(cs35l56_base->dev, "Amp short error\n");
+
+ if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)
+ dev_crit(cs35l56_base->dev, "Overtemp error\n");
+
+ ret = IRQ_HANDLED;
+
+err:
+ pm_runtime_put(cs35l56_base->dev);
+err_unlock:
+ mutex_unlock(&cs35l56_base->irq_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED);
+
+int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
+{
+ unsigned int val;
+ int ret;
+
+ /* Nothing to re-patch if we haven't done any patching yet. */
+ if (!cs35l56_base->fw_patched)
+ return false;
+
+ /*
+ * If we have control of RESET we will have asserted it so the firmware
+ * will need re-patching.
+ */
+ if (cs35l56_base->reset_gpio)
+ return true;
+
+ /*
+ * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
+ * can't be used here to test for memory retention.
+ * Assume that tuning must be re-loaded.
+ */
+ if (cs35l56_base->secured)
+ return true;
+
+ ret = pm_runtime_resume_and_get(cs35l56_base->dev);
+ if (ret) {
+ dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val);
+ if (ret)
+ dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);
+ else
+ ret = !!(val & CS35L56_FIRMWARE_MISSING);
+
+ pm_runtime_put_autosuspend(cs35l56_base->dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED);
+
+static const struct reg_sequence cs35l56_hibernate_seq[] = {
+ /* This must be the last register access */
+ REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW),
+};
+
+static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
+ REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
+};
+
+int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)
{
- int i;
unsigned int val;
+ int ret;
+
+ if (!cs35l56_base->init_done)
+ return 0;
- for (i = 0; i < ARRAY_SIZE(cs35l56_firmware_registers); i++) {
- regmap_read(regmap, cs35l56_firmware_registers[i], &val);
- dev_dbg(dev, "%s: %d: %#x: %#x\n", __func__,
- i, cs35l56_firmware_registers[i], val);
+ /* Firmware must have entered a power-save state */
+ ret = regmap_read_poll_timeout(cs35l56_base->regmap,
+ CS35L56_TRANSDUCER_ACTUAL_PS,
+ val, (val >= CS35L56_PS3),
+ CS35L56_PS3_POLL_US,
+ CS35L56_PS3_TIMEOUT_US);
+ if (ret)
+ dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret);
+
+ /* Clear BOOT_DONE so it can be used to detect a reboot */
+ regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
+
+ if (!cs35l56_base->can_hibernate) {
+ regcache_cache_only(cs35l56_base->regmap, true);
+ dev_dbg(cs35l56_base->dev, "Suspended: no hibernate");
+
+ return 0;
}
+
+ /*
+ * Enable auto-hibernate. If it is woken by some other wake source
+ * it will automatically return to hibernate.
+ */
+ cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);
+
+ /*
+ * Must enter cache-only first so there can't be any more register
+ * accesses other than the controlled hibernate sequence below.
+ */
+ regcache_cache_only(cs35l56_base->regmap, true);
+
+ regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
+ cs35l56_hibernate_seq,
+ ARRAY_SIZE(cs35l56_hibernate_seq));
+
+ dev_dbg(cs35l56_base->dev, "Suspended: hibernate");
+
+ return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_reread_firmware_registers, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED);
+
+int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)
+{
+ unsigned int val;
+ int ret;
+
+ if (!cs35l56_base->init_done)
+ return 0;
+
+ if (!cs35l56_base->can_hibernate)
+ goto out_sync;
+
+ if (!is_soundwire) {
+ /*
+ * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C.
+ * Must be done before releasing cache-only.
+ */
+ regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
+ cs35l56_hibernate_wake_seq,
+ ARRAY_SIZE(cs35l56_hibernate_wake_seq));
-const struct cs_dsp_region cs35l56_dsp1_regions[] = {
+ cs35l56_wait_control_port_ready();
+ }
+
+out_sync:
+ regcache_cache_only(cs35l56_base->regmap, false);
+
+ ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
+ if (ret) {
+ dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
+ goto err;
+ }
+
+ ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
+ if (ret)
+ goto err;
+
+ /* BOOT_DONE will be 1 if the amp reset */
+ regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, &val);
+ if (val & CS35L56_OTP_BOOT_DONE_MASK) {
+ dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n");
+ regcache_mark_dirty(cs35l56_base->regmap);
+ }
+
+ regcache_sync(cs35l56_base->regmap);
+
+ dev_dbg(cs35l56_base->dev, "Resumed");
+
+ return 0;
+
+err:
+ regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
+ CS35L56_MBOX_CMD_HIBERNATE_NOW);
+
+ regcache_cache_only(cs35l56_base->regmap, true);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED);
+
+static const struct cs_dsp_region cs35l56_dsp1_regions[] = {
{ .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 },
{ .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 },
{ .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 },
{ .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 },
{ .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 },
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_dsp1_regions, SND_SOC_CS35L56_SHARED);
+
+void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp)
+{
+ cs_dsp->num = 1;
+ cs_dsp->type = WMFW_HALO;
+ cs_dsp->rev = 0;
+ cs_dsp->dev = cs35l56_base->dev;
+ cs_dsp->regmap = cs35l56_base->regmap;
+ cs_dsp->base = CS35L56_DSP1_CORE_BASE;
+ cs_dsp->base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;
+ cs_dsp->mem = cs35l56_dsp1_regions;
+ cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
+ cs_dsp->no_core_startstop = true;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED);
+
+int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
+{
+ int ret;
+ unsigned int devid, revid, otpid, secured;
+
+ /*
+ * If the system is not using a reset_gpio then issue a
+ * dummy read to force a wakeup.
+ */
+ if (!cs35l56_base->reset_gpio)
+ regmap_read(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid);
+
+ cs35l56_wait_control_port_ready();
+
+ /*
+ * The HALO_STATE register is in different locations on Ax and B0
+ * devices so the REVID needs to be determined before waiting for the
+ * firmware to boot.
+ */
+ ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid);
+ if (ret < 0) {
+ dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
+ return ret;
+ }
+ cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);
+
+ ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid);
+ if (ret < 0) {
+ dev_err(cs35l56_base->dev, "Get Device ID failed\n");
+ return ret;
+ }
+ devid &= CS35L56_DEVID_MASK;
+
+ switch (devid) {
+ case 0x35A56:
+ break;
+ default:
+ dev_err(cs35l56_base->dev, "Unknown device %x\n", devid);
+ return ret;
+ }
+
+ ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
+ if (ret) {
+ dev_err(cs35l56_base->dev, "Get Secure status failed\n");
+ return ret;
+ }
+
+ /* When any bus is restricted treat the device as secured */
+ if (secured & CS35L56_RESTRICTED_MASK)
+ cs35l56_base->secured = true;
+
+ ret = regmap_read(cs35l56_base->regmap, CS35L56_OTPID, &otpid);
+ if (ret < 0) {
+ dev_err(cs35l56_base->dev, "Get OTP ID failed\n");
+ return ret;
+ }
+
+ dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n",
+ cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid);
+
+ /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
+ regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
+ regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1,
+ CS35L56_AMP_SHORT_ERR_EINT1_MASK,
+ 0);
+ regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8,
+ CS35L56_TEMP_ERR_EINT1_MASK,
+ 0);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
[0x0C] = 128000,
@@ -319,7 +763,7 @@ struct regmap_config cs35l56_regmap_i2c = {
.volatile_reg = cs35l56_volatile_reg,
.readable_reg = cs35l56_readable_reg,
.precious_reg = cs35l56_precious_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
@@ -336,7 +780,7 @@ struct regmap_config cs35l56_regmap_spi = {
.volatile_reg = cs35l56_volatile_reg,
.readable_reg = cs35l56_readable_reg,
.precious_reg = cs35l56_precious_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
@@ -352,7 +796,7 @@ struct regmap_config cs35l56_regmap_sdw = {
.volatile_reg = cs35l56_volatile_reg,
.readable_reg = cs35l56_readable_reg,
.precious_reg = cs35l56_precious_reg,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);
diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c
index 302f9c47407a..9962703915e1 100644
--- a/sound/soc/codecs/cs35l56-spi.c
+++ b/sound/soc/codecs/cs35l56-spi.c
@@ -25,13 +25,13 @@ static int cs35l56_spi_probe(struct spi_device *spi)
return -ENOMEM;
spi_set_drvdata(spi, cs35l56);
- cs35l56->regmap = devm_regmap_init_spi(spi, regmap_config);
- if (IS_ERR(cs35l56->regmap)) {
- ret = PTR_ERR(cs35l56->regmap);
+ cs35l56->base.regmap = devm_regmap_init_spi(spi, regmap_config);
+ if (IS_ERR(cs35l56->base.regmap)) {
+ ret = PTR_ERR(cs35l56->base.regmap);
return dev_err_probe(&spi->dev, ret, "Failed to allocate register map\n");
}
- cs35l56->dev = &spi->dev;
+ cs35l56->base.dev = &spi->dev;
ret = cs35l56_common_probe(cs35l56);
if (ret != 0)
@@ -39,7 +39,7 @@ static int cs35l56_spi_probe(struct spi_device *spi)
ret = cs35l56_init(cs35l56);
if (ret == 0)
- ret = cs35l56_irq_request(cs35l56, spi->irq);
+ ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
if (ret < 0)
cs35l56_remove(cs35l56);
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index fd06b9f9d496..ea3a4557619a 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -33,23 +33,6 @@
static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
-static int cs35l56_mbox_send(struct cs35l56_private *cs35l56, unsigned int command)
-{
- unsigned int val;
- int ret;
-
- regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command);
- ret = regmap_read_poll_timeout(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
- val, (val == 0),
- CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);
- if (ret) {
- dev_warn(cs35l56->dev, "MBOX command %#x failed: %d\n", command, ret);
- return ret;
- }
-
- return 0;
-}
-
static void cs35l56_wait_dsp_ready(struct cs35l56_private *cs35l56)
{
/* Wait for patching to complete */
@@ -173,25 +156,25 @@ static int cs35l56_play_event(struct snd_soc_dapm_widget *w,
unsigned int val;
int ret;
- dev_dbg(cs35l56->dev, "play: %d\n", event);
+ dev_dbg(cs35l56->base.dev, "play: %d\n", event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Don't wait for ACK, we check in POST_PMU that it completed */
- return regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
+ return regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
CS35L56_MBOX_CMD_AUDIO_PLAY);
case SND_SOC_DAPM_POST_PMU:
/* Wait for firmware to enter PS0 power state */
- ret = regmap_read_poll_timeout(cs35l56->regmap,
+ ret = regmap_read_poll_timeout(cs35l56->base.regmap,
CS35L56_TRANSDUCER_ACTUAL_PS,
val, (val == CS35L56_PS0),
CS35L56_PS0_POLL_US,
CS35L56_PS0_TIMEOUT_US);
if (ret)
- dev_err(cs35l56->dev, "PS0 wait failed: %d\n", ret);
+ dev_err(cs35l56->base.dev, "PS0 wait failed: %d\n", ret);
return ret;
case SND_SOC_DAPM_POST_PMD:
- return cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_PAUSE);
+ return cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE);
default:
return 0;
}
@@ -309,109 +292,23 @@ static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
- dev_dbg(cs35l56->dev, "%s: %d\n", __func__, event);
+ dev_dbg(cs35l56->base.dev, "%s: %d\n", __func__, event);
return wm_adsp_event(w, kcontrol, event);
}
-irqreturn_t cs35l56_irq(int irq, void *data)
-{
- struct cs35l56_private *cs35l56 = data;
- unsigned int status1 = 0, status8 = 0, status20 = 0;
- unsigned int mask1, mask8, mask20;
- unsigned int val;
- int rv;
-
- irqreturn_t ret = IRQ_NONE;
-
- if (!cs35l56->init_done)
- return IRQ_NONE;
-
- mutex_lock(&cs35l56->irq_lock);
-
- rv = pm_runtime_resume_and_get(cs35l56->dev);
- if (rv < 0) {
- dev_err(cs35l56->dev, "irq: failed to get pm_runtime: %d\n", rv);
- goto err_unlock;
- }
-
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_STATUS, &val);
- if ((val & CS35L56_IRQ1_STS_MASK) == 0) {
- dev_dbg(cs35l56->dev, "Spurious IRQ: no pending interrupt\n");
- goto err;
- }
-
- /* Ack interrupts */
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_1, &status1);
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_1, &mask1);
- status1 &= ~mask1;
- regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_1, status1);
-
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_8, &status8);
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_8, &mask8);
- status8 &= ~mask8;
- regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_8, status8);
-
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_20, &status20);
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_MASK_20, &mask20);
- status20 &= ~mask20;
- /* We don't want EINT20 but they default to unmasked: force mask */
- regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
-
- dev_dbg(cs35l56->dev, "%s: %#x %#x\n", __func__, status1, status8);
-
- /* Check to see if unmasked bits are active */
- if (!status1 && !status8 && !status20)
- goto err;
-
- if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)
- dev_crit(cs35l56->dev, "Amp short error\n");
-
- if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)
- dev_crit(cs35l56->dev, "Overtemp error\n");
-
- ret = IRQ_HANDLED;
-
-err:
- pm_runtime_put(cs35l56->dev);
-err_unlock:
- mutex_unlock(&cs35l56->irq_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_CORE);
-
-int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq)
-{
- int ret;
-
- if (!irq)
- return 0;
-
- ret = devm_request_threaded_irq(cs35l56->dev, irq, NULL, cs35l56_irq,
- IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
- "cs35l56", cs35l56);
- if (!ret)
- cs35l56->irq = irq;
- else
- dev_err(cs35l56->dev, "Failed to get IRQ: %d\n", ret);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_CORE);
-
static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(codec_dai->component);
unsigned int val;
- dev_dbg(cs35l56->dev, "%s: %#x\n", __func__, fmt);
+ dev_dbg(cs35l56->base.dev, "%s: %#x\n", __func__, fmt);
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
case SND_SOC_DAIFMT_CBC_CFC:
break;
default:
- dev_err(cs35l56->dev, "Unsupported clock source mode\n");
+ dev_err(cs35l56->base.dev, "Unsupported clock source mode\n");
return -EINVAL;
}
@@ -425,7 +322,7 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f
cs35l56->tdm_mode = false;
break;
default:
- dev_err(cs35l56->dev, "Unsupported DAI format\n");
+ dev_err(cs35l56->base.dev, "Unsupported DAI format\n");
return -EINVAL;
}
@@ -442,18 +339,18 @@ static int cs35l56_asp_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int f
case SND_SOC_DAIFMT_NB_NF:
break;
default:
- dev_err(cs35l56->dev, "Invalid clock invert\n");
+ dev_err(cs35l56->base.dev, "Invalid clock invert\n");
return -EINVAL;
}
- regmap_update_bits(cs35l56->regmap,
+ regmap_update_bits(cs35l56->base.regmap,
CS35L56_ASP1_CONTROL2,
CS35L56_ASP_FMT_MASK |
CS35L56_ASP_BCLK_INV_MASK | CS35L56_ASP_FSYNC_INV_MASK,
val);
/* Hi-Z DOUT in unused slots and when all TX are disabled */
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL3,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL3,
CS35L56_ASP1_DOUT_HIZ_CTRL_MASK,
CS35L56_ASP_UNUSED_HIZ_OFF_HIZ);
@@ -484,7 +381,7 @@ static void cs35l56_set_asp_slot_positions(struct cs35l56_private *cs35l56,
channel_shift += 8;
}
- regmap_write(cs35l56->regmap, reg, reg_val);
+ regmap_write(cs35l56->base.regmap, reg, reg_val);
}
static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
@@ -493,20 +390,20 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
if ((slots == 0) || (slot_width == 0)) {
- dev_dbg(cs35l56->dev, "tdm config cleared\n");
+ dev_dbg(cs35l56->base.dev, "tdm config cleared\n");
cs35l56->asp_slot_width = 0;
cs35l56->asp_slot_count = 0;
return 0;
}
if (slot_width > (CS35L56_ASP_RX_WIDTH_MASK >> CS35L56_ASP_RX_WIDTH_SHIFT)) {
- dev_err(cs35l56->dev, "tdm invalid slot width %d\n", slot_width);
+ dev_err(cs35l56->base.dev, "tdm invalid slot width %d\n", slot_width);
return -EINVAL;
}
/* More than 32 slots would give an unsupportable BCLK frequency */
if (slots > 32) {
- dev_err(cs35l56->dev, "tdm invalid slot count %d\n", slots);
+ dev_err(cs35l56->base.dev, "tdm invalid slot count %d\n", slots);
return -EINVAL;
}
@@ -523,7 +420,7 @@ static int cs35l56_asp_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx
cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL1, rx_mask);
cs35l56_set_asp_slot_positions(cs35l56, CS35L56_ASP1_FRAME_CONTROL5, tx_mask);
- dev_dbg(cs35l56->dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n",
+ dev_dbg(cs35l56->base.dev, "tdm slot width: %u count: %u tx_mask: %#x rx_mask: %#x\n",
cs35l56->asp_slot_width, cs35l56->asp_slot_count, tx_mask, rx_mask);
return 0;
@@ -543,7 +440,8 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream,
else
asp_width = asp_wl;
- dev_dbg(cs35l56->dev, "%s: wl=%d, width=%d, rate=%d", __func__, asp_wl, asp_width, rate);
+ dev_dbg(cs35l56->base.dev, "%s: wl=%d, width=%d, rate=%d",
+ __func__, asp_wl, asp_width, rate);
if (!cs35l56->sysclk_set) {
unsigned int slots = cs35l56->asp_slot_count;
@@ -561,26 +459,26 @@ static int cs35l56_asp_dai_hw_params(struct snd_pcm_substream *substream,
bclk_freq = asp_width * slots * rate;
freq_id = cs35l56_get_bclk_freq_id(bclk_freq);
if (freq_id < 0) {
- dev_err(cs35l56->dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq);
+ dev_err(cs35l56->base.dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq);
return -EINVAL;
}
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1,
CS35L56_ASP_BCLK_FREQ_MASK,
freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT);
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2,
CS35L56_ASP_RX_WIDTH_MASK, asp_width <<
CS35L56_ASP_RX_WIDTH_SHIFT);
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL5,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL5,
CS35L56_ASP_RX_WL_MASK, asp_wl);
} else {
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL2,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2,
CS35L56_ASP_TX_WIDTH_MASK, asp_width <<
CS35L56_ASP_TX_WIDTH_SHIFT);
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_DATA_CONTROL1,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL1,
CS35L56_ASP_TX_WL_MASK, asp_wl);
}
@@ -602,7 +500,7 @@ static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai,
if (freq_id < 0)
return freq_id;
- regmap_update_bits(cs35l56->regmap, CS35L56_ASP1_CONTROL1,
+ regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1,
CS35L56_ASP_BCLK_FREQ_MASK,
freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT);
cs35l56->sysclk_set = true;
@@ -645,9 +543,9 @@ static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream,
struct sdw_port_config pconfig;
int ret;
- dev_dbg(cs35l56->dev, "%s: rate %d\n", __func__, params_rate(params));
+ dev_dbg(cs35l56->base.dev, "%s: rate %d\n", __func__, params_rate(params));
- if (!cs35l56->init_done)
+ if (!cs35l56->base.init_done)
return -ENODEV;
if (!sdw_stream)
@@ -760,67 +658,6 @@ static struct snd_soc_dai_driver cs35l56_dai[] = {
}
};
-static int cs35l56_wait_for_firmware_boot(struct cs35l56_private *cs35l56)
-{
- unsigned int reg;
- unsigned int val;
- int ret;
-
- if (cs35l56->rev < CS35L56_REVID_B0)
- reg = CS35L56_DSP1_HALO_STATE_A1;
- else
- reg = CS35L56_DSP1_HALO_STATE;
-
- ret = regmap_read_poll_timeout(cs35l56->regmap, reg,
- val,
- (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
- CS35L56_HALO_STATE_POLL_US,
- CS35L56_HALO_STATE_TIMEOUT_US);
-
- if ((ret < 0) && (ret != -ETIMEDOUT)) {
- dev_err(cs35l56->dev, "Failed to read HALO_STATE: %d\n", ret);
- return ret;
- }
-
- if ((ret == -ETIMEDOUT) || (val != CS35L56_HALO_STATE_BOOT_DONE)) {
- dev_err(cs35l56->dev, "Firmware boot fail: HALO_STATE=%#x\n", val);
- return -EIO;
- }
-
- return 0;
-}
-
-static inline void cs35l56_wait_min_reset_pulse(void)
-{
- /* Satisfy minimum reset pulse width spec */
- usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);
-}
-
-static const struct reg_sequence cs35l56_system_reset_seq[] = {
- REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
-};
-
-static void cs35l56_system_reset(struct cs35l56_private *cs35l56)
-{
- cs35l56->soft_resetting = true;
-
- /*
- * Must enter cache-only first so there can't be any more register
- * accesses other than the controlled system reset sequence below.
- */
- regcache_cache_only(cs35l56->regmap, true);
- regmap_multi_reg_write_bypassed(cs35l56->regmap,
- cs35l56_system_reset_seq,
- ARRAY_SIZE(cs35l56_system_reset_seq));
-
- /* On SoundWire the registers won't be accessible until it re-enumerates. */
- if (cs35l56->sdw_peripheral)
- return;
-
- usleep_range(CS35L56_CONTROL_PORT_READY_US, CS35L56_CONTROL_PORT_READY_US + 400);
- regcache_cache_only(cs35l56->regmap, false);
-}
-
static void cs35l56_secure_patch(struct cs35l56_private *cs35l56)
{
int ret;
@@ -828,15 +665,13 @@ static void cs35l56_secure_patch(struct cs35l56_private *cs35l56)
/* Use wm_adsp to load and apply the firmware patch and coefficient files */
ret = wm_adsp_power_up(&cs35l56->dsp);
if (ret)
- dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
+ dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
else
- cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_AUDIO_REINIT);
+ cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);
}
static void cs35l56_patch(struct cs35l56_private *cs35l56)
{
- unsigned int reg;
- unsigned int val;
int ret;
/*
@@ -853,35 +688,23 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56)
flush_work(&cs35l56->sdw_irq_work);
}
- ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_SHUTDOWN);
+ ret = cs35l56_firmware_shutdown(&cs35l56->base);
if (ret)
goto err;
- if (cs35l56->rev < CS35L56_REVID_B0)
- reg = CS35L56_DSP1_PM_CUR_STATE_A1;
- else
- reg = CS35L56_DSP1_PM_CUR_STATE;
-
- ret = regmap_read_poll_timeout(cs35l56->regmap, reg,
- val, (val == CS35L56_HALO_STATE_SHUTDOWN),
- CS35L56_HALO_STATE_POLL_US,
- CS35L56_HALO_STATE_TIMEOUT_US);
- if (ret < 0)
- dev_err(cs35l56->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",
- val, ret);
-
/* Use wm_adsp to load and apply the firmware patch and coefficient files */
ret = wm_adsp_power_up(&cs35l56->dsp);
if (ret) {
- dev_dbg(cs35l56->dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
+ dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret);
goto err;
}
- mutex_lock(&cs35l56->irq_lock);
+ mutex_lock(&cs35l56->base.irq_lock);
init_completion(&cs35l56->init_completion);
- cs35l56_system_reset(cs35l56);
+ cs35l56->soft_resetting = true;
+ cs35l56_system_reset(&cs35l56->base, !!cs35l56->sdw_peripheral);
if (cs35l56->sdw_peripheral) {
/*
@@ -891,18 +714,20 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56)
*/
if (!wait_for_completion_timeout(&cs35l56->init_completion,
msecs_to_jiffies(5000))) {
- dev_err(cs35l56->dev, "%s: init_completion timed out (SDW)\n", __func__);
+ dev_err(cs35l56->base.dev, "%s: init_completion timed out (SDW)\n",
+ __func__);
goto err_unlock;
}
} else if (cs35l56_init(cs35l56)) {
goto err_unlock;
}
- regmap_clear_bits(cs35l56->regmap, CS35L56_PROTECTION_STATUS, CS35L56_FIRMWARE_MISSING);
- cs35l56->fw_patched = true;
+ regmap_clear_bits(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS,
+ CS35L56_FIRMWARE_MISSING);
+ cs35l56->base.fw_patched = true;
err_unlock:
- mutex_unlock(&cs35l56->irq_lock);
+ mutex_unlock(&cs35l56->base.irq_lock);
err:
/* Re-enable SoundWire interrupts */
if (cs35l56->sdw_peripheral) {
@@ -918,10 +743,10 @@ static void cs35l56_dsp_work(struct work_struct *work)
struct cs35l56_private,
dsp_work);
- if (!cs35l56->init_done)
+ if (!cs35l56->base.init_done)
return;
- pm_runtime_get_sync(cs35l56->dev);
+ pm_runtime_get_sync(cs35l56->base.dev);
/*
* When the device is running in secure mode the firmware files can
@@ -929,13 +754,13 @@ static void cs35l56_dsp_work(struct work_struct *work)
* shutdown the firmware to apply them and can use the lower cost
* reinit sequence instead.
*/
- if (cs35l56->secured)
+ if (cs35l56->base.secured)
cs35l56_secure_patch(cs35l56);
else
cs35l56_patch(cs35l56);
- pm_runtime_mark_last_busy(cs35l56->dev);
- pm_runtime_put_autosuspend(cs35l56->dev);
+ pm_runtime_mark_last_busy(cs35l56->base.dev);
+ pm_runtime_put_autosuspend(cs35l56->base.dev);
}
static int cs35l56_component_probe(struct snd_soc_component *component)
@@ -947,16 +772,16 @@ static int cs35l56_component_probe(struct snd_soc_component *component)
if (!wait_for_completion_timeout(&cs35l56->init_completion,
msecs_to_jiffies(5000))) {
- dev_err(cs35l56->dev, "%s: init_completion timed out\n", __func__);
+ dev_err(cs35l56->base.dev, "%s: init_completion timed out\n", __func__);
return -ENODEV;
}
cs35l56->component = component;
wm_adsp2_component_probe(&cs35l56->dsp, component);
- debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->init_done);
- debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->can_hibernate);
- debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->fw_patched);
+ debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->base.init_done);
+ debugfs_create_bool("can_hibernate", 0444, debugfs_root, &cs35l56->base.can_hibernate);
+ debugfs_create_bool("fw_patched", 0444, debugfs_root, &cs35l56->base.fw_patched);
queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work);
@@ -1008,171 +833,18 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l56 = {
.suspend_bias_off = 1, /* see cs35l56_system_resume() */
};
-static const struct reg_sequence cs35l56_hibernate_seq[] = {
- /* This must be the last register access */
- REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW),
-};
-
-static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
- REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
-};
-
-int cs35l56_runtime_suspend(struct device *dev)
+static int __maybe_unused cs35l56_runtime_suspend_i2c_spi(struct device *dev)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
- unsigned int val;
- int ret;
-
- if (!cs35l56->init_done)
- return 0;
- /* Firmware must have entered a power-save state */
- ret = regmap_read_poll_timeout(cs35l56->regmap,
- CS35L56_TRANSDUCER_ACTUAL_PS,
- val, (val >= CS35L56_PS3),
- CS35L56_PS3_POLL_US,
- CS35L56_PS3_TIMEOUT_US);
- if (ret)
- dev_warn(cs35l56->dev, "PS3 wait failed: %d\n", ret);
-
- /* Clear BOOT_DONE so it can be used to detect a reboot */
- regmap_write(cs35l56->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
-
- if (!cs35l56->can_hibernate) {
- regcache_cache_only(cs35l56->regmap, true);
- dev_dbg(dev, "Suspended: no hibernate");
-
- return 0;
- }
-
- /*
- * Enable auto-hibernate. If it is woken by some other wake source
- * it will automatically return to hibernate.
- */
- cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);
-
- /*
- * Must enter cache-only first so there can't be any more register
- * accesses other than the controlled hibernate sequence below.
- */
- regcache_cache_only(cs35l56->regmap, true);
-
- regmap_multi_reg_write_bypassed(cs35l56->regmap,
- cs35l56_hibernate_seq,
- ARRAY_SIZE(cs35l56_hibernate_seq));
-
- dev_dbg(dev, "Suspended: hibernate");
-
- return 0;
+ return cs35l56_runtime_suspend_common(&cs35l56->base);
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend, SND_SOC_CS35L56_CORE);
static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
- if (!cs35l56->init_done)
- return 0;
-
- return cs35l56_runtime_resume_common(cs35l56);
-}
-
-int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56)
-{
- unsigned int val;
- int ret;
-
- if (!cs35l56->can_hibernate)
- goto out_sync;
-
- if (!cs35l56->sdw_peripheral) {
- /*
- * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C.
- * Must be done before releasing cache-only.
- */
- regmap_multi_reg_write_bypassed(cs35l56->regmap,
- cs35l56_hibernate_wake_seq,
- ARRAY_SIZE(cs35l56_hibernate_wake_seq));
-
- usleep_range(CS35L56_CONTROL_PORT_READY_US,
- CS35L56_CONTROL_PORT_READY_US + 400);
- }
-
-out_sync:
- regcache_cache_only(cs35l56->regmap, false);
-
- ret = cs35l56_wait_for_firmware_boot(cs35l56);
- if (ret) {
- dev_err(cs35l56->dev, "Hibernate wake failed: %d\n", ret);
- goto err;
- }
-
- ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
- if (ret)
- goto err;
-
- /* BOOT_DONE will be 1 if the amp reset */
- regmap_read(cs35l56->regmap, CS35L56_IRQ1_EINT_4, &val);
- if (val & CS35L56_OTP_BOOT_DONE_MASK) {
- dev_dbg(cs35l56->dev, "Registers reset in suspend\n");
- regcache_mark_dirty(cs35l56->regmap);
- }
-
- regcache_sync(cs35l56->regmap);
-
- dev_dbg(cs35l56->dev, "Resumed");
-
- return 0;
-
-err:
- regmap_write(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
- CS35L56_MBOX_CMD_HIBERNATE_NOW);
-
- regcache_cache_only(cs35l56->regmap, true);
-
- return ret;
-}
-EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_CORE);
-
-static int cs35l56_is_fw_reload_needed(struct cs35l56_private *cs35l56)
-{
- unsigned int val;
- int ret;
-
- /* Nothing to re-patch if we haven't done any patching yet. */
- if (!cs35l56->fw_patched)
- return false;
-
- /*
- * If we have control of RESET we will have asserted it so the firmware
- * will need re-patching.
- */
- if (cs35l56->reset_gpio)
- return true;
-
- /*
- * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
- * can't be used here to test for memory retention.
- * Assume that tuning must be re-loaded.
- */
- if (cs35l56->secured)
- return true;
-
- ret = pm_runtime_resume_and_get(cs35l56->dev);
- if (ret) {
- dev_err(cs35l56->dev, "Failed to runtime_get: %d\n", ret);
- return ret;
- }
-
- ret = regmap_read(cs35l56->regmap, CS35L56_PROTECTION_STATUS, &val);
- if (ret)
- dev_err(cs35l56->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);
- else
- ret = !!(val & CS35L56_FIRMWARE_MISSING);
-
- pm_runtime_put_autosuspend(cs35l56->dev);
-
- return ret;
+ return cs35l56_runtime_resume_common(&cs35l56->base, false);
}
int cs35l56_system_suspend(struct device *dev)
@@ -1190,8 +862,8 @@ int cs35l56_system_suspend(struct device *dev)
* clear it. Prevent this race by temporarily disabling the parent irq
* until we reach _no_irq.
*/
- if (cs35l56->irq)
- disable_irq(cs35l56->irq);
+ if (cs35l56->base.irq)
+ disable_irq(cs35l56->base.irq);
return pm_runtime_force_suspend(dev);
}
@@ -1208,8 +880,8 @@ int cs35l56_system_suspend_late(struct device *dev)
* RESET is usually shared by all amps so it must not be asserted until
* all driver instances have done their suspend() stage.
*/
- if (cs35l56->reset_gpio) {
- gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
+ if (cs35l56->base.reset_gpio) {
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
cs35l56_wait_min_reset_pulse();
}
@@ -1226,8 +898,8 @@ int cs35l56_system_suspend_no_irq(struct device *dev)
dev_dbg(dev, "system_suspend_no_irq\n");
/* Handlers are now disabled so the parent IRQ can safely be re-enabled. */
- if (cs35l56->irq)
- enable_irq(cs35l56->irq);
+ if (cs35l56->base.irq)
+ enable_irq(cs35l56->base.irq);
return 0;
}
@@ -1246,8 +918,8 @@ int cs35l56_system_resume_no_irq(struct device *dev)
* clear it, until it has fully resumed. Prevent this race by temporarily
* disabling the parent irq until we complete resume().
*/
- if (cs35l56->irq)
- disable_irq(cs35l56->irq);
+ if (cs35l56->base.irq)
+ disable_irq(cs35l56->base.irq);
return 0;
}
@@ -1261,8 +933,8 @@ int cs35l56_system_resume_early(struct device *dev)
dev_dbg(dev, "system_resume_early\n");
/* Ensure a spec-compliant RESET pulse. */
- if (cs35l56->reset_gpio) {
- gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
+ if (cs35l56->base.reset_gpio) {
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
cs35l56_wait_min_reset_pulse();
}
@@ -1274,7 +946,7 @@ int cs35l56_system_resume_early(struct device *dev)
}
/* Release shared RESET before drivers start resume(). */
- gpiod_set_value_cansleep(cs35l56->reset_gpio, 1);
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
return 0;
}
@@ -1289,8 +961,8 @@ int cs35l56_system_resume(struct device *dev)
/* Undo pm_runtime_force_suspend() before re-enabling the irq */
ret = pm_runtime_force_resume(dev);
- if (cs35l56->irq)
- enable_irq(cs35l56->irq);
+ if (cs35l56->base.irq)
+ enable_irq(cs35l56->base.irq);
if (ret)
return ret;
@@ -1299,12 +971,12 @@ int cs35l56_system_resume(struct device *dev)
if (!cs35l56->component)
return 0;
- ret = cs35l56_is_fw_reload_needed(cs35l56);
- dev_dbg(cs35l56->dev, "fw_reload_needed: %d\n", ret);
+ ret = cs35l56_is_fw_reload_needed(&cs35l56->base);
+ dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret);
if (ret < 1)
return ret;
- cs35l56->fw_patched = false;
+ cs35l56->base.fw_patched = false;
queue_work(cs35l56->dsp_wq, &cs35l56->dsp_work);
/*
@@ -1328,25 +1000,16 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56)
INIT_WORK(&cs35l56->dsp_work, cs35l56_dsp_work);
dsp = &cs35l56->dsp;
+ cs35l56_init_cs_dsp(&cs35l56->base, &dsp->cs_dsp);
dsp->part = "cs35l56";
- dsp->cs_dsp.num = 1;
- dsp->cs_dsp.type = WMFW_HALO;
- dsp->cs_dsp.rev = 0;
dsp->fw = 12;
- dsp->cs_dsp.dev = cs35l56->dev;
- dsp->cs_dsp.regmap = cs35l56->regmap;
- dsp->cs_dsp.base = CS35L56_DSP1_CORE_BASE;
- dsp->cs_dsp.base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;
- dsp->cs_dsp.mem = cs35l56_dsp1_regions;
- dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
- dsp->cs_dsp.no_core_startstop = true;
dsp->wmfw_optional = true;
- dev_dbg(cs35l56->dev, "DSP system name: '%s'\n", dsp->system_name);
+ dev_dbg(cs35l56->base.dev, "DSP system name: '%s'\n", dsp->system_name);
ret = wm_halo_init(dsp);
if (ret != 0) {
- dev_err(cs35l56->dev, "wm_halo_init failed\n");
+ dev_err(cs35l56->base.dev, "wm_halo_init failed\n");
return ret;
}
@@ -1355,7 +1018,7 @@ static int cs35l56_dsp_init(struct cs35l56_private *cs35l56)
static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56)
{
- struct device *dev = cs35l56->dev;
+ struct device *dev = cs35l56->base.dev;
const char *prop;
int ret;
@@ -1378,38 +1041,39 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
int ret;
init_completion(&cs35l56->init_completion);
- mutex_init(&cs35l56->irq_lock);
+ mutex_init(&cs35l56->base.irq_lock);
- dev_set_drvdata(cs35l56->dev, cs35l56);
+ dev_set_drvdata(cs35l56->base.dev, cs35l56);
cs35l56_fill_supply_names(cs35l56->supplies);
- ret = devm_regulator_bulk_get(cs35l56->dev, ARRAY_SIZE(cs35l56->supplies),
+ ret = devm_regulator_bulk_get(cs35l56->base.dev, ARRAY_SIZE(cs35l56->supplies),
cs35l56->supplies);
if (ret != 0)
- return dev_err_probe(cs35l56->dev, ret, "Failed to request supplies\n");
+ return dev_err_probe(cs35l56->base.dev, ret, "Failed to request supplies\n");
/* Reset could be controlled by the BIOS or shared by multiple amps */
- cs35l56->reset_gpio = devm_gpiod_get_optional(cs35l56->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(cs35l56->reset_gpio)) {
- ret = PTR_ERR(cs35l56->reset_gpio);
+ cs35l56->base.reset_gpio = devm_gpiod_get_optional(cs35l56->base.dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(cs35l56->base.reset_gpio)) {
+ ret = PTR_ERR(cs35l56->base.reset_gpio);
/*
* If RESET is shared the first amp to probe will grab the reset
* line and reset all the amps
*/
if (ret != -EBUSY)
- return dev_err_probe(cs35l56->dev, ret, "Failed to get reset GPIO\n");
+ return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n");
- dev_info(cs35l56->dev, "Reset GPIO busy, assume shared reset\n");
- cs35l56->reset_gpio = NULL;
+ dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n");
+ cs35l56->base.reset_gpio = NULL;
}
ret = regulator_bulk_enable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
if (ret != 0)
- return dev_err_probe(cs35l56->dev, ret, "Failed to enable supplies\n");
+ return dev_err_probe(cs35l56->base.dev, ret, "Failed to enable supplies\n");
- if (cs35l56->reset_gpio) {
+ if (cs35l56->base.reset_gpio) {
cs35l56_wait_min_reset_pulse();
- gpiod_set_value_cansleep(cs35l56->reset_gpio, 1);
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);
}
ret = cs35l56_get_firmware_uid(cs35l56);
@@ -1418,22 +1082,22 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
ret = cs35l56_dsp_init(cs35l56);
if (ret < 0) {
- dev_err_probe(cs35l56->dev, ret, "DSP init failed\n");
+ dev_err_probe(cs35l56->base.dev, ret, "DSP init failed\n");
goto err;
}
- ret = devm_snd_soc_register_component(cs35l56->dev,
+ ret = devm_snd_soc_register_component(cs35l56->base.dev,
&soc_component_dev_cs35l56,
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
if (ret < 0) {
- dev_err_probe(cs35l56->dev, ret, "Register codec failed\n");
+ dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n");
goto err;
}
return 0;
err:
- gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
return ret;
@@ -1443,7 +1107,6 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, SND_SOC_CS35L56_CORE);
int cs35l56_init(struct cs35l56_private *cs35l56)
{
int ret;
- unsigned int devid, revid, otpid, secured;
/*
* Check whether the actions associated with soft reset or one time
@@ -1452,96 +1115,31 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
if (cs35l56->soft_resetting)
goto post_soft_reset;
- if (cs35l56->init_done)
+ if (cs35l56->base.init_done)
return 0;
- pm_runtime_set_autosuspend_delay(cs35l56->dev, 100);
- pm_runtime_use_autosuspend(cs35l56->dev);
- pm_runtime_set_active(cs35l56->dev);
- pm_runtime_enable(cs35l56->dev);
-
- /*
- * If the system is not using a reset_gpio then issue a
- * dummy read to force a wakeup.
- */
- if (!cs35l56->reset_gpio)
- regmap_read(cs35l56->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid);
-
- /* Wait for control port to be ready (datasheet tIRS). */
- usleep_range(CS35L56_CONTROL_PORT_READY_US,
- CS35L56_CONTROL_PORT_READY_US + 400);
-
- /*
- * The HALO_STATE register is in different locations on Ax and B0
- * devices so the REVID needs to be determined before waiting for the
- * firmware to boot.
- */
- ret = regmap_read(cs35l56->regmap, CS35L56_REVID, &revid);
- if (ret < 0) {
- dev_err(cs35l56->dev, "Get Revision ID failed\n");
- return ret;
- }
- cs35l56->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);
-
- ret = cs35l56_wait_for_firmware_boot(cs35l56);
- if (ret)
- return ret;
-
- ret = regmap_read(cs35l56->regmap, CS35L56_DEVID, &devid);
- if (ret < 0) {
- dev_err(cs35l56->dev, "Get Device ID failed\n");
- return ret;
- }
- devid &= CS35L56_DEVID_MASK;
-
- switch (devid) {
- case 0x35A56:
- break;
- default:
- dev_err(cs35l56->dev, "Unknown device %x\n", devid);
- return ret;
- }
-
- ret = regmap_read(cs35l56->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
- if (ret) {
- dev_err(cs35l56->dev, "Get Secure status failed\n");
- return ret;
- }
-
- /* When any bus is restricted treat the device as secured */
- if (secured & CS35L56_RESTRICTED_MASK)
- cs35l56->secured = true;
+ pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 100);
+ pm_runtime_use_autosuspend(cs35l56->base.dev);
+ pm_runtime_set_active(cs35l56->base.dev);
+ pm_runtime_enable(cs35l56->base.dev);
- ret = regmap_read(cs35l56->regmap, CS35L56_OTPID, &otpid);
- if (ret < 0) {
- dev_err(cs35l56->dev, "Get OTP ID failed\n");
+ ret = cs35l56_hw_init(&cs35l56->base);
+ if (ret < 0)
return ret;
- }
-
- dev_info(cs35l56->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n",
- cs35l56->secured ? "s" : "", cs35l56->rev, otpid);
/* Populate the DSP information with the revision and security state */
- cs35l56->dsp.part = devm_kasprintf(cs35l56->dev, GFP_KERNEL, "cs35l56%s-%02x",
- cs35l56->secured ? "s" : "", cs35l56->rev);
+ cs35l56->dsp.part = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "cs35l56%s-%02x",
+ cs35l56->base.secured ? "s" : "", cs35l56->base.rev);
if (!cs35l56->dsp.part)
return -ENOMEM;
- /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
- regmap_write(cs35l56->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
- regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_1,
- CS35L56_AMP_SHORT_ERR_EINT1_MASK,
- 0);
- regmap_update_bits(cs35l56->regmap, CS35L56_IRQ1_MASK_8,
- CS35L56_TEMP_ERR_EINT1_MASK,
- 0);
-
- if (!cs35l56->reset_gpio) {
- dev_dbg(cs35l56->dev, "No reset gpio: using soft reset\n");
- cs35l56_system_reset(cs35l56);
+ if (!cs35l56->base.reset_gpio) {
+ dev_dbg(cs35l56->base.dev, "No reset gpio: using soft reset\n");
+ cs35l56->soft_resetting = true;
+ cs35l56_system_reset(&cs35l56->base, !!cs35l56->sdw_peripheral);
if (cs35l56->sdw_peripheral) {
/* Keep alive while we wait for re-enumeration */
- pm_runtime_get_noresume(cs35l56->dev);
+ pm_runtime_get_noresume(cs35l56->base.dev);
return 0;
}
}
@@ -1551,29 +1149,30 @@ post_soft_reset:
cs35l56->soft_resetting = false;
/* Done re-enumerating after one-time init so release the keep-alive */
- if (cs35l56->sdw_peripheral && !cs35l56->init_done)
- pm_runtime_put_noidle(cs35l56->dev);
+ if (cs35l56->sdw_peripheral && !cs35l56->base.init_done)
+ pm_runtime_put_noidle(cs35l56->base.dev);
- regcache_mark_dirty(cs35l56->regmap);
- ret = cs35l56_wait_for_firmware_boot(cs35l56);
+ regcache_mark_dirty(cs35l56->base.regmap);
+ ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
if (ret)
return ret;
- dev_dbg(cs35l56->dev, "Firmware rebooted after soft reset\n");
+ dev_dbg(cs35l56->base.dev, "Firmware rebooted after soft reset\n");
}
/* Disable auto-hibernate so that runtime_pm has control */
- ret = cs35l56_mbox_send(cs35l56, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
+ ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
if (ret)
return ret;
- /* Populate soft registers in the regmap cache */
- cs35l56_reread_firmware_registers(cs35l56->dev, cs35l56->regmap);
+ ret = cs35l56_set_patch(&cs35l56->base);
+ if (ret)
+ return ret;
/* Registers could be dirty after soft reset or SoundWire enumeration */
- regcache_sync(cs35l56->regmap);
+ regcache_sync(cs35l56->base.regmap);
- cs35l56->init_done = true;
+ cs35l56->base.init_done = true;
complete(&cs35l56->init_completion);
return 0;
@@ -1582,30 +1181,30 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE);
void cs35l56_remove(struct cs35l56_private *cs35l56)
{
- cs35l56->init_done = false;
+ cs35l56->base.init_done = false;
/*
* WAKE IRQs unmask if CS35L56 hibernates so free the handler to
* prevent it racing with remove().
*/
- if (cs35l56->irq)
- devm_free_irq(cs35l56->dev, cs35l56->irq, cs35l56);
+ if (cs35l56->base.irq)
+ devm_free_irq(cs35l56->base.dev, cs35l56->base.irq, &cs35l56->base);
flush_workqueue(cs35l56->dsp_wq);
destroy_workqueue(cs35l56->dsp_wq);
- pm_runtime_suspend(cs35l56->dev);
- pm_runtime_disable(cs35l56->dev);
+ pm_runtime_suspend(cs35l56->base.dev);
+ pm_runtime_disable(cs35l56->base.dev);
- regcache_cache_only(cs35l56->regmap, true);
+ regcache_cache_only(cs35l56->base.regmap, true);
- gpiod_set_value_cansleep(cs35l56->reset_gpio, 0);
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
}
EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE);
const struct dev_pm_ops cs35l56_pm_ops_i2c_spi = {
- SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend, cs35l56_runtime_resume_i2c_spi, NULL)
+ SET_RUNTIME_PM_OPS(cs35l56_runtime_suspend_i2c_spi, cs35l56_runtime_resume_i2c_spi, NULL)
SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend, cs35l56_system_resume)
LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_late, cs35l56_system_resume_early)
NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_system_suspend_no_irq, cs35l56_system_resume_no_irq)
diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h
index 1f7894662fcb..8159c3e217d9 100644
--- a/sound/soc/codecs/cs35l56.h
+++ b/sound/soc/codecs/cs35l56.h
@@ -32,26 +32,17 @@ struct sdw_slave;
struct cs35l56_private {
struct wm_adsp dsp; /* must be first member */
+ struct cs35l56_base base;
struct work_struct dsp_work;
struct workqueue_struct *dsp_wq;
- struct mutex irq_lock;
struct snd_soc_component *component;
- struct device *dev;
- struct regmap *regmap;
struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES];
- int irq;
struct sdw_slave *sdw_peripheral;
- u8 rev;
struct work_struct sdw_irq_work;
- bool secured;
bool sdw_irq_no_unmask;
bool soft_resetting;
- bool init_done;
bool sdw_attached;
- bool fw_patched;
- bool can_hibernate;
struct completion init_completion;
- struct gpio_desc *reset_gpio;
u32 rx_mask;
u32 tx_mask;
@@ -64,8 +55,6 @@ struct cs35l56_private {
extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi;
-int cs35l56_runtime_suspend(struct device *dev);
-int cs35l56_runtime_resume_common(struct cs35l56_private *cs35l56);
int cs35l56_system_suspend(struct device *dev);
int cs35l56_system_suspend_late(struct device *dev);
int cs35l56_system_suspend_no_irq(struct device *dev);
@@ -73,7 +62,7 @@ int cs35l56_system_resume_no_irq(struct device *dev);
int cs35l56_system_resume_early(struct device *dev);
int cs35l56_system_resume(struct device *dev);
irqreturn_t cs35l56_irq(int irq, void *data);
-int cs35l56_irq_request(struct cs35l56_private *cs35l56, int irq);
+int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq);
int cs35l56_common_probe(struct cs35l56_private *cs35l56);
int cs35l56_init(struct cs35l56_private *cs35l56);
void cs35l56_remove(struct cs35l56_private *cs35l56);
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
index 0cfc5ab36a13..1ed1e60d8e53 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -564,7 +564,7 @@ static const struct regmap_config cs4265_regmap = {
.num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults),
.readable_reg = cs4265_readable_register,
.volatile_reg = cs4265_volatile_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int cs4265_i2c_probe(struct i2c_client *i2c_client)
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index ab32f15e3b44..3df567214952 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -636,7 +636,7 @@ static const struct regmap_config cs4270_regmap = {
.max_register = CS4270_LASTREG,
.reg_defaults = cs4270_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.write_flag_mask = CS4270_I2C_INCR,
.readable_reg = cs4270_reg_is_readable,
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index a7079ae0ca09..e4827b8c2bde 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -703,7 +703,7 @@ const struct regmap_config cs42l51_regmap = {
.volatile_reg = cs42l51_volatile_reg,
.writeable_reg = cs42l51_writeable_reg,
.max_register = CS42L51_CHARGE_FREQ,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(cs42l51_regmap);
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 1f1ded0ff0ac..4fc8a6ae8d92 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -1084,7 +1084,7 @@ static const struct regmap_config cs42l52_regmap = {
.num_reg_defaults = ARRAY_SIZE(cs42l52_reg_defaults),
.readable_reg = cs42l52_readable_register,
.volatile_reg = cs42l52_volatile_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int cs42l52_i2c_probe(struct i2c_client *i2c_client)
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index 4c646e8d72aa..1714857594fb 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -1125,7 +1125,7 @@ static const struct regmap_config cs42l56_regmap = {
.num_reg_defaults = ARRAY_SIZE(cs42l56_reg_defaults),
.readable_reg = cs42l56_readable_register,
.volatile_reg = cs42l56_volatile_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int cs42l56_handle_of_data(struct i2c_client *i2c_client,
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
index 4558ec38a7ac..9c44b6283b8f 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -458,7 +458,7 @@ const struct regmap_config cs42xx8_regmap_config = {
.num_reg_defaults = ARRAY_SIZE(cs42xx8_reg),
.volatile_reg = cs42xx8_volatile_register,
.writeable_reg = cs42xx8_writeable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
EXPORT_SYMBOL_GPL(cs42xx8_regmap_config);
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c
index 8365dd0ebe2a..ef08e51901b5 100644
--- a/sound/soc/codecs/cs4349.c
+++ b/sound/soc/codecs/cs4349.c
@@ -271,7 +271,7 @@ static const struct regmap_config cs4349_regmap = {
.num_reg_defaults = ARRAY_SIZE(cs4349_reg_defaults),
.readable_reg = cs4349_readable_register,
.writeable_reg = cs4349_writeable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int cs4349_i2c_probe(struct i2c_client *client)
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 65e497b455d3..a8f347f1affb 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -27,9 +27,9 @@
* MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
* Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
*/
-#define NR_SUPPORTED_MCLK_LRCK_RATIOS 6
+#define NR_SUPPORTED_MCLK_LRCK_RATIOS ARRAY_SIZE(supported_mclk_lrck_ratios)
static const unsigned int supported_mclk_lrck_ratios[] = {
- 256, 384, 400, 512, 768, 1024
+ 256, 384, 400, 500, 512, 768, 1024
};
struct es8316_priv {
@@ -494,6 +494,7 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
bclk_divider /= 20;
break;
case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
wordlen = ES8316_SERDATA2_LEN_24;
bclk_divider /= 24;
break;
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index 7cb5b57ae655..a7fbb758eeee 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -38,6 +38,9 @@ struct es8326_priv {
u8 interrupt_clk;
bool jd_inverted;
unsigned int sysclk;
+
+ bool calibrated;
+ int version;
};
static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(dac_vol_tlv, -9550, 50, 0);
@@ -121,33 +124,12 @@ static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = {
/* Analog Power Supply*/
SND_SOC_DAPM_DAC("Right DAC", NULL, ES8326_ANA_PDN, 0, 1),
SND_SOC_DAPM_DAC("Left DAC", NULL, ES8326_ANA_PDN, 1, 1),
- SND_SOC_DAPM_SUPPLY("Analog Power", ES8326_ANA_PDN, 7, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("IBias Power", ES8326_ANA_PDN, 6, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("ADC Vref", ES8326_ANA_PDN, 5, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("DAC Vref", ES8326_ANA_PDN, 4, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Vref Power", ES8326_ANA_PDN, 3, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", ES8326_ANA_MICBIAS, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", ES8326_ANA_MICBIAS, 3, 0, NULL, 0),
SND_SOC_DAPM_PGA("LHPMIX", ES8326_DAC2HPMIX, 7, 0, NULL, 0),
SND_SOC_DAPM_PGA("RHPMIX", ES8326_DAC2HPMIX, 3, 0, NULL, 0),
- /* Headphone Charge Pump and Output */
- SND_SOC_DAPM_SUPPLY("HPOR Cal", ES8326_HP_CAL, 7, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("HPOL Cal", ES8326_HP_CAL, 3, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", ES8326_HP_DRIVER,
- 3, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Headphone Driver Bias", ES8326_HP_DRIVER,
- 2, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Headphone LDO", ES8326_HP_DRIVER,
- 1, 1, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Headphone Reference", ES8326_HP_DRIVER,
- 0, 1, NULL, 0),
- SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOR Supply", ES8326_HP_CAL,
- ES8326_HPOR_SHIFT, 7, 7, 0),
- SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOL Supply", ES8326_HP_CAL,
- 0, 7, 7, 0),
-
SND_SOC_DAPM_OUTPUT("HPOL"),
SND_SOC_DAPM_OUTPUT("HPOR"),
};
@@ -166,34 +148,12 @@ static const struct snd_soc_dapm_route es8326_dapm_routes[] = {
{"I2S OUT", NULL, "ADC L"},
{"I2S OUT", NULL, "ADC R"},
- {"I2S OUT", NULL, "Analog Power"},
- {"I2S OUT", NULL, "ADC Vref"},
- {"I2S OUT", NULL, "Vref Power"},
- {"I2S OUT", NULL, "IBias Power"},
- {"I2S IN", NULL, "Analog Power"},
- {"I2S IN", NULL, "DAC Vref"},
- {"I2S IN", NULL, "Vref Power"},
- {"I2S IN", NULL, "IBias Power"},
-
{"Right DAC", NULL, "I2S IN"},
{"Left DAC", NULL, "I2S IN"},
{"LHPMIX", NULL, "Left DAC"},
{"RHPMIX", NULL, "Right DAC"},
- {"HPOR", NULL, "HPOR Cal"},
- {"HPOL", NULL, "HPOL Cal"},
- {"HPOR", NULL, "HPOR Supply"},
- {"HPOL", NULL, "HPOL Supply"},
- {"HPOL", NULL, "Headphone Charge Pump"},
- {"HPOR", NULL, "Headphone Charge Pump"},
- {"HPOL", NULL, "Headphone Driver Bias"},
- {"HPOR", NULL, "Headphone Driver Bias"},
- {"HPOL", NULL, "Headphone LDO"},
- {"HPOR", NULL, "Headphone LDO"},
- {"HPOL", NULL, "Headphone Reference"},
- {"HPOR", NULL, "Headphone Reference"},
-
{"HPOL", NULL, "LHPMIX"},
{"HPOR", NULL, "RHPMIX"},
};
@@ -419,6 +379,31 @@ static int es8326_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *component = dai->component;
+ struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+
+ if (mute) {
+ regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF);
+ regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE,
+ ES8326_MUTE_MASK, ES8326_MUTE);
+ regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xf0);
+ } else {
+ if (!es8326->calibrated) {
+ regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_FORCE_CAL);
+ msleep(30);
+ es8326->calibrated = true;
+ }
+ regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa0);
+ regmap_write(es8326->regmap, ES8326_HP_VOL, 0x00);
+ regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_ON);
+ regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE,
+ ES8326_MUTE_MASK, ~(ES8326_MUTE));
+ }
+ return 0;
+}
+
static int es8326_set_bias_level(struct snd_soc_component *codec,
enum snd_soc_bias_level level)
{
@@ -469,6 +454,8 @@ static const struct snd_soc_dai_ops es8326_ops = {
.hw_params = es8326_pcm_hw_params,
.set_fmt = es8326_set_dai_fmt,
.set_sysclk = es8326_set_dai_sysclk,
+ .mute_stream = es8326_mute,
+ .no_capture_mute = 1,
};
static struct snd_soc_dai_driver es8326_dai = {
@@ -691,7 +678,7 @@ static int es8326_suspend(struct snd_soc_component *component)
cancel_delayed_work_sync(&es8326->jack_detect_work);
es8326_disable_micbias(component);
-
+ es8326->calibrated = false;
regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_OFF);
regcache_cache_only(es8326->regmap, true);
regcache_mark_dirty(es8326->regmap);
diff --git a/sound/soc/codecs/es8326.h b/sound/soc/codecs/es8326.h
index 8e5ffe5ee10d..3f8f7da58062 100644
--- a/sound/soc/codecs/es8326.h
+++ b/sound/soc/codecs/es8326.h
@@ -9,8 +9,6 @@
#ifndef _ES8326_H
#define _ES8326_H
-#define CONFIG_HHTECH_MINIPMP 1
-
/* ES8326 register space */
#define ES8326_RESET 0x00
#define ES8326_CLK_CTL 0x01
@@ -94,6 +92,8 @@
#define ES8326_PWRUP_SEQ_EN (1 << 5)
#define ES8326_CODEC_RESET (0x0f << 0)
#define ES8326_CSM_OFF (0 << 7)
+#define ES8326_MUTE_MASK (3 << 0)
+#define ES8326_MUTE (3 << 0)
/* ES8326_CLK_CTL */
#define ES8326_CLK_ON (0x7f << 0)
@@ -122,7 +122,9 @@
#define ES8326_MIC2_SEL (1 << 5)
/* ES8326_HP_CAL */
-#define ES8326_HPOR_SHIFT 4
+#define ES8326_HP_OFF 0
+#define ES8326_HP_FORCE_CAL ((1 << 7) | (1 << 3))
+#define ES8326_HP_ON ((7 << 4) | (7 << 0))
/* ES8326_ADC1_SRC */
#define ES8326_ADC1_SHIFT 0
@@ -180,3 +182,4 @@
#define ES8326_VERSION_B (1 << 0)
#endif
+
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index 685ca95ef4a9..29197d34ec09 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -3537,25 +3537,25 @@ static int rx_macro_probe(struct platform_device *pdev)
rx->macro = devm_clk_get_optional(dev, "macro");
if (IS_ERR(rx->macro))
- return PTR_ERR(rx->macro);
+ return dev_err_probe(dev, PTR_ERR(rx->macro), "unable to get macro clock\n");
rx->dcodec = devm_clk_get_optional(dev, "dcodec");
if (IS_ERR(rx->dcodec))
- return PTR_ERR(rx->dcodec);
+ return dev_err_probe(dev, PTR_ERR(rx->dcodec), "unable to get dcodec clock\n");
rx->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(rx->mclk))
- return PTR_ERR(rx->mclk);
+ return dev_err_probe(dev, PTR_ERR(rx->mclk), "unable to get mclk clock\n");
if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) {
rx->npl = devm_clk_get(dev, "npl");
if (IS_ERR(rx->npl))
- return PTR_ERR(rx->npl);
+ return dev_err_probe(dev, PTR_ERR(rx->npl), "unable to get npl clock\n");
}
rx->fsgen = devm_clk_get(dev, "fsgen");
if (IS_ERR(rx->fsgen))
- return PTR_ERR(rx->fsgen);
+ return dev_err_probe(dev, PTR_ERR(rx->fsgen), "unable to get fsgen clock\n");
rx->pds = lpass_macro_pds_init(dev);
if (IS_ERR(rx->pds))
diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c
index de978c3d70b7..3e33418898e8 100644
--- a/sound/soc/codecs/lpass-tx-macro.c
+++ b/sound/soc/codecs/lpass-tx-macro.c
@@ -1967,25 +1967,25 @@ static int tx_macro_probe(struct platform_device *pdev)
tx->macro = devm_clk_get_optional(dev, "macro");
if (IS_ERR(tx->macro))
- return PTR_ERR(tx->macro);
+ return dev_err_probe(dev, PTR_ERR(tx->macro), "unable to get macro clock\n");
tx->dcodec = devm_clk_get_optional(dev, "dcodec");
if (IS_ERR(tx->dcodec))
- return PTR_ERR(tx->dcodec);
+ return dev_err_probe(dev, PTR_ERR(tx->dcodec), "unable to get dcodec clock\n");
tx->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(tx->mclk))
- return PTR_ERR(tx->mclk);
+ return dev_err_probe(dev, PTR_ERR(tx->mclk), "unable to get mclk clock\n");
if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) {
tx->npl = devm_clk_get(dev, "npl");
if (IS_ERR(tx->npl))
- return PTR_ERR(tx->npl);
+ return dev_err_probe(dev, PTR_ERR(tx->npl), "unable to get npl clock\n");
}
tx->fsgen = devm_clk_get(dev, "fsgen");
if (IS_ERR(tx->fsgen))
- return PTR_ERR(tx->fsgen);
+ return dev_err_probe(dev, PTR_ERR(tx->fsgen), "unable to get fsgen clock\n");
tx->pds = lpass_macro_pds_init(dev);
if (IS_ERR(tx->pds))
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index 74724448da50..b71ef03c4aef 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -1457,15 +1457,15 @@ static int va_macro_probe(struct platform_device *pdev)
va->macro = devm_clk_get_optional(dev, "macro");
if (IS_ERR(va->macro))
- return PTR_ERR(va->macro);
+ return dev_err_probe(dev, PTR_ERR(va->macro), "unable to get macro clock\n");
va->dcodec = devm_clk_get_optional(dev, "dcodec");
if (IS_ERR(va->dcodec))
- return PTR_ERR(va->dcodec);
+ return dev_err_probe(dev, PTR_ERR(va->dcodec), "unable to get dcodec clock\n");
va->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(va->mclk))
- return PTR_ERR(va->mclk);
+ return dev_err_probe(dev, PTR_ERR(va->mclk), "unable to get mclk clock\n");
va->pds = lpass_macro_pds_init(dev);
if (IS_ERR(va->pds))
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
index 8ba7dc89daaa..ec6859ec0d38 100644
--- a/sound/soc/codecs/lpass-wsa-macro.c
+++ b/sound/soc/codecs/lpass-wsa-macro.c
@@ -2396,25 +2396,25 @@ static int wsa_macro_probe(struct platform_device *pdev)
wsa->macro = devm_clk_get_optional(dev, "macro");
if (IS_ERR(wsa->macro))
- return PTR_ERR(wsa->macro);
+ return dev_err_probe(dev, PTR_ERR(wsa->macro), "unable to get macro clock\n");
wsa->dcodec = devm_clk_get_optional(dev, "dcodec");
if (IS_ERR(wsa->dcodec))
- return PTR_ERR(wsa->dcodec);
+ return dev_err_probe(dev, PTR_ERR(wsa->dcodec), "unable to get dcodec clock\n");
wsa->mclk = devm_clk_get(dev, "mclk");
if (IS_ERR(wsa->mclk))
- return PTR_ERR(wsa->mclk);
+ return dev_err_probe(dev, PTR_ERR(wsa->mclk), "unable to get mclk clock\n");
if (flags & LPASS_MACRO_FLAG_HAS_NPL_CLOCK) {
wsa->npl = devm_clk_get(dev, "npl");
if (IS_ERR(wsa->npl))
- return PTR_ERR(wsa->npl);
+ return dev_err_probe(dev, PTR_ERR(wsa->npl), "unable to get npl clock\n");
}
wsa->fsgen = devm_clk_get(dev, "fsgen");
if (IS_ERR(wsa->fsgen))
- return PTR_ERR(wsa->fsgen);
+ return dev_err_probe(dev, PTR_ERR(wsa->fsgen), "unable to get fsgen clock\n");
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c
index cec90cf920ff..9ca381812975 100644
--- a/sound/soc/codecs/msm8916-wcd-analog.c
+++ b/sound/soc/codecs/msm8916-wcd-analog.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
-#include <linux/clk.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -1198,12 +1197,6 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- priv->mclk = devm_clk_get(dev, "mclk");
- if (IS_ERR(priv->mclk)) {
- dev_err(dev, "failed to get mclk\n");
- return PTR_ERR(priv->mclk);
- }
-
for (i = 0; i < ARRAY_SIZE(supply_names); i++)
priv->supplies[i].supply = supply_names[i];
@@ -1214,55 +1207,48 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return ret;
}
- ret = clk_prepare_enable(priv->mclk);
- if (ret < 0) {
- dev_err(dev, "failed to enable mclk %d\n", ret);
- return ret;
- }
-
irq = platform_get_irq_byname(pdev, "mbhc_switch_int");
- if (irq < 0) {
- ret = irq;
- goto err_disable_clk;
- }
+ if (irq < 0)
+ return irq;
ret = devm_request_threaded_irq(dev, irq, NULL,
pm8916_mbhc_switch_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
"mbhc switch irq", priv);
- if (ret)
+ if (ret) {
dev_err(dev, "cannot request mbhc switch irq\n");
+ return ret;
+ }
if (priv->mbhc_btn_enabled) {
irq = platform_get_irq_byname(pdev, "mbhc_but_press_det");
- if (irq < 0) {
- ret = irq;
- goto err_disable_clk;
- }
+ if (irq < 0)
+ return irq;
ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_press_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"mbhc btn press irq", priv);
- if (ret)
+ if (ret) {
dev_err(dev, "cannot request mbhc button press irq\n");
+ return ret;
+ }
irq = platform_get_irq_byname(pdev, "mbhc_but_rel_det");
- if (irq < 0) {
- ret = irq;
- goto err_disable_clk;
- }
+ if (irq < 0)
+ return irq;
ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_release_irq_handler,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"mbhc btn release irq", priv);
- if (ret)
+ if (ret) {
dev_err(dev, "cannot request mbhc button release irq\n");
-
+ return ret;
+ }
}
dev_set_drvdata(dev, priv);
@@ -1270,17 +1256,6 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return devm_snd_soc_register_component(dev, &pm8916_wcd_analog,
pm8916_wcd_analog_dai,
ARRAY_SIZE(pm8916_wcd_analog_dai));
-
-err_disable_clk:
- clk_disable_unprepare(priv->mclk);
- return ret;
-}
-
-static void pm8916_wcd_analog_spmi_remove(struct platform_device *pdev)
-{
- struct pm8916_wcd_analog_priv *priv = dev_get_drvdata(&pdev->dev);
-
- clk_disable_unprepare(priv->mclk);
}
static const struct of_device_id pm8916_wcd_analog_spmi_match_table[] = {
@@ -1296,7 +1271,6 @@ static struct platform_driver pm8916_wcd_analog_spmi_driver = {
.of_match_table = pm8916_wcd_analog_spmi_match_table,
},
.probe = pm8916_wcd_analog_spmi_probe,
- .remove_new = pm8916_wcd_analog_spmi_remove,
};
module_platform_driver(pm8916_wcd_analog_spmi_driver);
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index 9e0e4ddf128e..5cb0de648bd3 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/int_log.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -38,7 +39,6 @@
#define NAU_FVCO_MIN 90000000
/* cross talk suppression detection */
-#define LOG10_MAGIC 646456993
#define GAIN_AUGMENT 22500
#define SIDETONE_BASE 207000
@@ -219,42 +219,6 @@ static const struct reg_sequence nau8825_regmap_patch[] = {
{ NAU8825_REG_MIC_BIAS, 0x0046 },
};
-
-static const unsigned short logtable[256] = {
- 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
- 0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
- 0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
- 0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
- 0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
- 0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
- 0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
- 0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
- 0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
- 0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
- 0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
- 0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
- 0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
- 0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
- 0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
- 0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
- 0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
- 0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
- 0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
- 0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
- 0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
- 0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
- 0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
- 0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
- 0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
- 0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
- 0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
- 0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
- 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
- 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
- 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
- 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
-};
-
/**
* nau8825_sema_acquire - acquire the semaphore of nau88l25
* @nau8825: component to register the codec private data with
@@ -368,65 +332,14 @@ static void nau8825_hpvol_ramp(struct nau8825 *nau8825,
}
/**
- * nau8825_intlog10_dec3 - Computes log10 of a value
- * the result is round off to 3 decimal. This function takes reference to
- * dvb-math. The source code locates as the following.
- * Linux/drivers/media/dvb-core/dvb_math.c
+ * nau8825_intlog10_dec3 - Computes log10 of a value, rounding the result to 3 decimal places.
* @value: input for log10
*
* return log10(value) * 1000
*/
static u32 nau8825_intlog10_dec3(u32 value)
{
- u32 msb, logentry, significand, interpolation, log10val;
- u64 log2val;
-
- /* first detect the msb (count begins at 0) */
- msb = fls(value) - 1;
- /**
- * now we use a logtable after the following method:
- *
- * log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
- * where x = msb and therefore 1 <= y < 2
- * first y is determined by shifting the value left
- * so that msb is bit 31
- * 0x00231f56 -> 0x8C7D5800
- * the result is y * 2^31 -> "significand"
- * then the highest 9 bits are used for a table lookup
- * the highest bit is discarded because it's always set
- * the highest nine bits in our example are 100011000
- * so we would use the entry 0x18
- */
- significand = value << (31 - msb);
- logentry = (significand >> 23) & 0xff;
- /**
- * last step we do is interpolation because of the
- * limitations of the log table the error is that part of
- * the significand which isn't used for lookup then we
- * compute the ratio between the error and the next table entry
- * and interpolate it between the log table entry used and the
- * next one the biggest error possible is 0x7fffff
- * (in our example it's 0x7D5800)
- * needed value for next table entry is 0x800000
- * so the interpolation is
- * (error / 0x800000) * (logtable_next - logtable_current)
- * in the implementation the division is moved to the end for
- * better accuracy there is also an overflow correction if
- * logtable_next is 256
- */
- interpolation = ((significand & 0x7fffff) *
- ((logtable[(logentry + 1) & 0xff] -
- logtable[logentry]) & 0xffff)) >> 15;
-
- log2val = ((msb << 24) + (logtable[logentry] << 8) + interpolation);
- /**
- * log10(x) = log2(x) * log10(2)
- */
- log10val = (log2val * LOG10_MAGIC) >> 31;
- /**
- * the result is round off to 3 decimal
- */
- return log10val / ((1 << 24) / 1000);
+ return intlog10(value) / ((1 << 24) / 1000);
}
/**
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index a506d940a2ea..5be5ec0260e9 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -3258,6 +3258,22 @@ int rt5645_set_jack_detect(struct snd_soc_component *component,
}
EXPORT_SYMBOL_GPL(rt5645_set_jack_detect);
+static int rt5645_component_set_jack(struct snd_soc_component *component,
+ struct snd_soc_jack *hs_jack, void *data)
+{
+ struct snd_soc_jack *mic_jack = NULL;
+ struct snd_soc_jack *btn_jack = NULL;
+ int *type = (int *)data;
+
+ if (*type & SND_JACK_MICROPHONE)
+ mic_jack = hs_jack;
+ if (*type & (SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3))
+ btn_jack = hs_jack;
+
+ return rt5645_set_jack_detect(component, hs_jack, mic_jack, btn_jack);
+}
+
static void rt5645_jack_detect_work(struct work_struct *work)
{
struct rt5645_priv *rt5645 =
@@ -3532,6 +3548,7 @@ static const struct snd_soc_component_driver soc_component_dev_rt5645 = {
.num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets),
.dapm_routes = rt5645_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes),
+ .set_jack = rt5645_component_set_jack,
.use_pmdown_time = 1,
.endianness = 1,
};
@@ -4182,11 +4199,44 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c)
regmap_write(rt5645->regmap, RT5645_RESET, 0);
}
+static int __maybe_unused rt5645_sys_suspend(struct device *dev)
+{
+ struct rt5645_priv *rt5645 = dev_get_drvdata(dev);
+
+ del_timer_sync(&rt5645->btn_check_timer);
+ cancel_delayed_work_sync(&rt5645->jack_detect_work);
+ cancel_delayed_work_sync(&rt5645->rcclock_work);
+
+ regcache_cache_only(rt5645->regmap, true);
+ regcache_mark_dirty(rt5645->regmap);
+ return 0;
+}
+
+static int __maybe_unused rt5645_sys_resume(struct device *dev)
+{
+ struct rt5645_priv *rt5645 = dev_get_drvdata(dev);
+
+ regcache_cache_only(rt5645->regmap, false);
+ regcache_sync(rt5645->regmap);
+
+ if (rt5645->hp_jack) {
+ rt5645->jack_type = 0;
+ queue_delayed_work(system_power_efficient_wq,
+ &rt5645->jack_detect_work, msecs_to_jiffies(0));
+ }
+ return 0;
+}
+
+static const struct dev_pm_ops rt5645_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(rt5645_sys_suspend, rt5645_sys_resume)
+};
+
static struct i2c_driver rt5645_i2c_driver = {
.driver = {
.name = "rt5645",
.of_match_table = of_match_ptr(rt5645_of_match),
.acpi_match_table = ACPI_PTR(rt5645_acpi_match),
+ .pm = &rt5645_pm,
},
.probe = rt5645_i2c_probe,
.remove = rt5645_i2c_remove,
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index ad14d18860fc..0e70a3ab42b5 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -6,23 +6,21 @@
* Author: Oder Chiou <oder_chiou@realtek.com>
*/
-#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
+#include <linux/platform_device.h>
#include <linux/pm.h>
+#include <linux/property.h>
#include <linux/regmap.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/spi/spi.h>
-#include <linux/firmware.h>
-#include <linux/of_device.h>
-#include <linux/property.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -4717,50 +4715,34 @@ static int rt5677_set_bias_level(struct snd_soc_component *component,
return 0;
}
+static int rt5677_update_gpio_bits(struct rt5677_priv *rt5677, unsigned offset, int m, int v)
+{
+ unsigned int bank = offset / 5;
+ unsigned int shift = (offset % 5) * 3;
+ unsigned int reg = bank ? RT5677_GPIO_CTRL3 : RT5677_GPIO_CTRL2;
+
+ return regmap_update_bits(rt5677->regmap, reg, m << shift, v << shift);
+}
+
#ifdef CONFIG_GPIOLIB
static void rt5677_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct rt5677_priv *rt5677 = gpiochip_get_data(chip);
+ int level = value ? RT5677_GPIOx_OUT_HI : RT5677_GPIOx_OUT_LO;
+ int m = RT5677_GPIOx_OUT_MASK;
- switch (offset) {
- case RT5677_GPIO1 ... RT5677_GPIO5:
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
- 0x1 << (offset * 3 + 1), !!value << (offset * 3 + 1));
- break;
-
- case RT5677_GPIO6:
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
- RT5677_GPIO6_OUT_MASK, !!value << RT5677_GPIO6_OUT_SFT);
- break;
-
- default:
- break;
- }
+ rt5677_update_gpio_bits(rt5677, offset, m, level);
}
static int rt5677_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value)
{
struct rt5677_priv *rt5677 = gpiochip_get_data(chip);
+ int level = value ? RT5677_GPIOx_OUT_HI : RT5677_GPIOx_OUT_LO;
+ int m = RT5677_GPIOx_DIR_MASK | RT5677_GPIOx_OUT_MASK;
+ int v = RT5677_GPIOx_DIR_OUT | level;
- switch (offset) {
- case RT5677_GPIO1 ... RT5677_GPIO5:
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
- 0x3 << (offset * 3 + 1),
- (0x2 | !!value) << (offset * 3 + 1));
- break;
-
- case RT5677_GPIO6:
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
- RT5677_GPIO6_DIR_MASK | RT5677_GPIO6_OUT_MASK,
- RT5677_GPIO6_DIR_OUT | !!value << RT5677_GPIO6_OUT_SFT);
- break;
-
- default:
- break;
- }
-
- return 0;
+ return rt5677_update_gpio_bits(rt5677, offset, m, v);
}
static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -4778,26 +4760,14 @@ static int rt5677_gpio_get(struct gpio_chip *chip, unsigned offset)
static int rt5677_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct rt5677_priv *rt5677 = gpiochip_get_data(chip);
+ int m = RT5677_GPIOx_DIR_MASK;
+ int v = RT5677_GPIOx_DIR_IN;
- switch (offset) {
- case RT5677_GPIO1 ... RT5677_GPIO5:
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
- 0x1 << (offset * 3 + 2), 0x0);
- break;
-
- case RT5677_GPIO6:
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL3,
- RT5677_GPIO6_DIR_MASK, RT5677_GPIO6_DIR_IN);
- break;
-
- default:
- break;
- }
-
- return 0;
+ return rt5677_update_gpio_bits(rt5677, offset, m, v);
}
-/** Configures the gpio as
+/*
+ * Configures the GPIO as
* 0 - floating
* 1 - pull down
* 2 - pull up
@@ -5539,7 +5509,7 @@ static int rt5677_init_irq(struct i2c_client *i2c)
RT5677_GPIO1_PIN_MASK, RT5677_GPIO1_PIN_IRQ);
/* Ready to listen for interrupts */
- rt5677->domain = irq_domain_add_linear(i2c->dev.of_node,
+ rt5677->domain = irq_domain_create_linear(dev_fwnode(&i2c->dev),
RT5677_IRQ_NUM, &rt5677_domain_ops, rt5677);
if (!rt5677->domain) {
dev_err(&i2c->dev, "Failed to create IRQ domain\n");
@@ -5559,6 +5529,7 @@ static int rt5677_init_irq(struct i2c_client *i2c)
static int rt5677_i2c_probe(struct i2c_client *i2c)
{
+ struct device *dev = &i2c->dev;
struct rt5677_priv *rt5677;
int ret;
unsigned int val;
@@ -5573,21 +5544,9 @@ static int rt5677_i2c_probe(struct i2c_client *i2c)
INIT_DELAYED_WORK(&rt5677->dsp_work, rt5677_dsp_work);
i2c_set_clientdata(i2c, rt5677);
- if (i2c->dev.of_node) {
- const struct of_device_id *match_id;
-
- match_id = of_match_device(rt5677_of_match, &i2c->dev);
- if (match_id)
- rt5677->type = (enum rt5677_type)match_id->data;
- } else if (ACPI_HANDLE(&i2c->dev)) {
- const struct acpi_device_id *acpi_id;
-
- acpi_id = acpi_match_device(rt5677_acpi_match, &i2c->dev);
- if (acpi_id)
- rt5677->type = (enum rt5677_type)acpi_id->driver_data;
- } else {
+ rt5677->type = (enum rt5677_type)(uintptr_t)device_get_match_data(dev);
+ if (rt5677->type == 0)
return -EINVAL;
- }
rt5677_read_device_properties(rt5677, &i2c->dev);
@@ -5673,9 +5632,9 @@ static int rt5677_i2c_probe(struct i2c_client *i2c)
regmap_update_bits(rt5677->regmap, RT5677_GEN_CTRL2,
RT5677_GPIO5_FUNC_MASK,
RT5677_GPIO5_FUNC_DMIC);
- regmap_update_bits(rt5677->regmap, RT5677_GPIO_CTRL2,
- RT5677_GPIO5_DIR_MASK,
- RT5677_GPIO5_DIR_OUT);
+ rt5677_update_gpio_bits(rt5677, RT5677_GPIO5,
+ RT5677_GPIOx_DIR_MASK,
+ RT5677_GPIOx_DIR_OUT);
}
if (rt5677->pdata.micbias1_vdd_3v3)
@@ -5702,7 +5661,7 @@ static struct i2c_driver rt5677_i2c_driver = {
.driver = {
.name = RT5677_DRV_NAME,
.of_match_table = rt5677_of_match,
- .acpi_match_table = ACPI_PTR(rt5677_acpi_match),
+ .acpi_match_table = rt5677_acpi_match,
},
.probe = rt5677_i2c_probe,
.remove = rt5677_i2c_remove,
diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h
index 944ae02aafc2..d67ebae067d9 100644
--- a/sound/soc/codecs/rt5677.h
+++ b/sound/soc/codecs/rt5677.h
@@ -1587,81 +1587,19 @@
#define RT5677_FUNC_MODE_DMIC_GPIO (0x0 << 13)
#define RT5677_FUNC_MODE_JTAG (0x1 << 13)
-/* GPIO Control 2 (0xc1) */
-#define RT5677_GPIO5_DIR_MASK (0x1 << 14)
-#define RT5677_GPIO5_DIR_SFT 14
-#define RT5677_GPIO5_DIR_IN (0x0 << 14)
-#define RT5677_GPIO5_DIR_OUT (0x1 << 14)
-#define RT5677_GPIO5_OUT_MASK (0x1 << 13)
-#define RT5677_GPIO5_OUT_SFT 13
-#define RT5677_GPIO5_OUT_LO (0x0 << 13)
-#define RT5677_GPIO5_OUT_HI (0x1 << 13)
-#define RT5677_GPIO5_P_MASK (0x1 << 12)
-#define RT5677_GPIO5_P_SFT 12
-#define RT5677_GPIO5_P_NOR (0x0 << 12)
-#define RT5677_GPIO5_P_INV (0x1 << 12)
-#define RT5677_GPIO4_DIR_MASK (0x1 << 11)
-#define RT5677_GPIO4_DIR_SFT 11
-#define RT5677_GPIO4_DIR_IN (0x0 << 11)
-#define RT5677_GPIO4_DIR_OUT (0x1 << 11)
-#define RT5677_GPIO4_OUT_MASK (0x1 << 10)
-#define RT5677_GPIO4_OUT_SFT 10
-#define RT5677_GPIO4_OUT_LO (0x0 << 10)
-#define RT5677_GPIO4_OUT_HI (0x1 << 10)
-#define RT5677_GPIO4_P_MASK (0x1 << 9)
-#define RT5677_GPIO4_P_SFT 9
-#define RT5677_GPIO4_P_NOR (0x0 << 9)
-#define RT5677_GPIO4_P_INV (0x1 << 9)
-#define RT5677_GPIO3_DIR_MASK (0x1 << 8)
-#define RT5677_GPIO3_DIR_SFT 8
-#define RT5677_GPIO3_DIR_IN (0x0 << 8)
-#define RT5677_GPIO3_DIR_OUT (0x1 << 8)
-#define RT5677_GPIO3_OUT_MASK (0x1 << 7)
-#define RT5677_GPIO3_OUT_SFT 7
-#define RT5677_GPIO3_OUT_LO (0x0 << 7)
-#define RT5677_GPIO3_OUT_HI (0x1 << 7)
-#define RT5677_GPIO3_P_MASK (0x1 << 6)
-#define RT5677_GPIO3_P_SFT 6
-#define RT5677_GPIO3_P_NOR (0x0 << 6)
-#define RT5677_GPIO3_P_INV (0x1 << 6)
-#define RT5677_GPIO2_DIR_MASK (0x1 << 5)
-#define RT5677_GPIO2_DIR_SFT 5
-#define RT5677_GPIO2_DIR_IN (0x0 << 5)
-#define RT5677_GPIO2_DIR_OUT (0x1 << 5)
-#define RT5677_GPIO2_OUT_MASK (0x1 << 4)
-#define RT5677_GPIO2_OUT_SFT 4
-#define RT5677_GPIO2_OUT_LO (0x0 << 4)
-#define RT5677_GPIO2_OUT_HI (0x1 << 4)
-#define RT5677_GPIO2_P_MASK (0x1 << 3)
-#define RT5677_GPIO2_P_SFT 3
-#define RT5677_GPIO2_P_NOR (0x0 << 3)
-#define RT5677_GPIO2_P_INV (0x1 << 3)
-#define RT5677_GPIO1_DIR_MASK (0x1 << 2)
-#define RT5677_GPIO1_DIR_SFT 2
-#define RT5677_GPIO1_DIR_IN (0x0 << 2)
-#define RT5677_GPIO1_DIR_OUT (0x1 << 2)
-#define RT5677_GPIO1_OUT_MASK (0x1 << 1)
-#define RT5677_GPIO1_OUT_SFT 1
-#define RT5677_GPIO1_OUT_LO (0x0 << 1)
-#define RT5677_GPIO1_OUT_HI (0x1 << 1)
-#define RT5677_GPIO1_P_MASK (0x1 << 0)
-#define RT5677_GPIO1_P_SFT 0
-#define RT5677_GPIO1_P_NOR (0x0 << 0)
-#define RT5677_GPIO1_P_INV (0x1 << 0)
-
-/* GPIO Control 3 (0xc2) */
-#define RT5677_GPIO6_DIR_MASK (0x1 << 2)
-#define RT5677_GPIO6_DIR_SFT 2
-#define RT5677_GPIO6_DIR_IN (0x0 << 2)
-#define RT5677_GPIO6_DIR_OUT (0x1 << 2)
-#define RT5677_GPIO6_OUT_MASK (0x1 << 1)
-#define RT5677_GPIO6_OUT_SFT 1
-#define RT5677_GPIO6_OUT_LO (0x0 << 1)
-#define RT5677_GPIO6_OUT_HI (0x1 << 1)
-#define RT5677_GPIO6_P_MASK (0x1 << 0)
-#define RT5677_GPIO6_P_SFT 0
-#define RT5677_GPIO6_P_NOR (0x0 << 0)
-#define RT5677_GPIO6_P_INV (0x1 << 0)
+/* GPIO Control 2 (0xc1) & 3 (0xc2) common bits */
+#define RT5677_GPIOx_DIR_MASK (0x1 << 2)
+#define RT5677_GPIOx_DIR_SFT 2
+#define RT5677_GPIOx_DIR_IN (0x0 << 2)
+#define RT5677_GPIOx_DIR_OUT (0x1 << 2)
+#define RT5677_GPIOx_OUT_MASK (0x1 << 1)
+#define RT5677_GPIOx_OUT_SFT 1
+#define RT5677_GPIOx_OUT_LO (0x0 << 1)
+#define RT5677_GPIOx_OUT_HI (0x1 << 1)
+#define RT5677_GPIOx_P_MASK (0x1 << 0)
+#define RT5677_GPIOx_P_SFT 0
+#define RT5677_GPIOx_P_NOR (0x0 << 0)
+#define RT5677_GPIOx_P_INV (0x1 << 0)
/* General Control (0xfa) */
#define RT5677_IRQ_DEBOUNCE_SEL_MASK (0x3 << 3)
@@ -1753,8 +1691,8 @@ enum {
};
enum rt5677_type {
- RT5677,
- RT5676,
+ RT5677 = 1,
+ RT5676 = 2,
};
/* ASRC clock source selection */
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index e9103ffb3f50..a38ec5862214 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -175,7 +175,7 @@ static int rt722_sdca_update_status(struct sdw_slave *slave,
* This also could sync with the cache value as the rt722_sdca_jack_init set.
*/
sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK1,
- SDW_SCP_SDCA_INTMASK_SDCA_0 | SDW_SCP_SDCA_INTMASK_SDCA_6);
+ SDW_SCP_SDCA_INTMASK_SDCA_6);
sdw_write_no_pm(rt722->slave, SDW_SCP_SDCA_INTMASK2,
SDW_SCP_SDCA_INTMASK_SDCA_8);
}
diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
index 9c0d34366c9e..0e1c65a20392 100644
--- a/sound/soc/codecs/rt722-sdca.c
+++ b/sound/soc/codecs/rt722-sdca.c
@@ -191,8 +191,7 @@ static void rt722_sdca_jack_detect_handler(struct work_struct *work)
return;
/* SDW_SCP_SDCA_INT_SDCA_6 is used for jack detection */
- if (rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6 ||
- rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) {
+ if (rt722->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_6) {
ret = rt722_sdca_headset_detect(rt722);
if (ret < 0)
return;
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
index 3047a6fbb380..b93c078a8040 100644
--- a/sound/soc/codecs/sigmadsp.c
+++ b/sound/soc/codecs/sigmadsp.c
@@ -669,36 +669,19 @@ static void sigmadsp_activate_ctrl(struct sigmadsp *sigmadsp,
struct sigmadsp_control *ctrl, unsigned int samplerate_mask)
{
struct snd_card *card = sigmadsp->component->card->snd_card;
- struct snd_kcontrol_volatile *vd;
- struct snd_ctl_elem_id id;
bool active;
- bool changed = false;
+ int changed;
active = sigmadsp_samplerate_valid(ctrl->samplerates, samplerate_mask);
-
- down_write(&card->controls_rwsem);
- if (!ctrl->kcontrol) {
- up_write(&card->controls_rwsem);
+ if (!ctrl->kcontrol)
return;
- }
-
- id = ctrl->kcontrol->id;
- vd = &ctrl->kcontrol->vd[0];
- if (active == (bool)(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)) {
- vd->access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
- changed = true;
- }
- up_write(&card->controls_rwsem);
-
- if (active && changed) {
+ changed = snd_ctl_activate_id(card, &ctrl->kcontrol->id, active);
+ if (active && changed > 0) {
mutex_lock(&sigmadsp->lock);
if (ctrl->cached)
sigmadsp_ctrl_write(sigmadsp, ctrl, ctrl->cache);
mutex_unlock(&sigmadsp->lock);
}
-
- if (changed)
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, &id);
}
/**
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index 4c59429a42b7..55cd5e3c23a5 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -743,7 +743,6 @@ MODULE_DEVICE_TABLE(acpi, tasdevice_acpi_match);
static struct i2c_driver tasdevice_i2c_driver = {
.driver = {
.name = "tas2781-codec",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(tasdevice_of_match),
#ifdef CONFIG_ACPI
.acpi_match_table = ACPI_PTR(tasdevice_acpi_match),
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 8bf3510a3ea3..a05b553e6472 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -4968,7 +4968,7 @@ static bool wcd9335_is_volatile_register(struct device *dev, unsigned int reg)
static struct regmap_config wcd9335_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = WCD9335_MAX_REGISTER,
.can_multi_write = true,
.ranges = wcd9335_ranges,
diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c
index bd0e9fbc12eb..6951120057e5 100644
--- a/sound/soc/codecs/wcd938x-sdw.c
+++ b/sound/soc/codecs/wcd938x-sdw.c
@@ -1183,7 +1183,7 @@ static const struct regmap_config wcd938x_regmap_config = {
.name = "wcd938x_csr",
.reg_bits = 32,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wcd938x_defaults,
.num_reg_defaults = ARRAY_SIZE(wcd938x_defaults),
.max_register = WCD938X_MAX_REGISTER,
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index 277b8c468c78..36cdf97993a5 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -2151,7 +2151,7 @@ static const struct regmap_config wm2200_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
.volatile_reg = wm2200_volatile_register,
.readable_reg = wm2200_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.ranges = wm2200_ranges,
.num_ranges = ARRAY_SIZE(wm2200_ranges),
};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index a86eacb2a9bb..ff63723928a1 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -2400,7 +2400,7 @@ static const struct regmap_config wm5100_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm5100_reg_defaults),
.volatile_reg = wm5100_volatile_register,
.readable_reg = wm5100_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const unsigned int wm5100_mic_ctrl_reg[] = {
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index c0ed76d5b65f..6636a70f3895 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -607,7 +607,7 @@ static const struct regmap_config wm8510_regmap = {
.reg_defaults = wm8510_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8510_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8510_volatile,
};
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 55c72c5ac845..ea87cd3cc0d6 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -437,7 +437,7 @@ static const struct regmap_config wm8523_regmap = {
.reg_defaults = wm8523_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8523_volatile_register,
};
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 34ae7fe05398..6d22f7d40ec2 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -975,7 +975,7 @@ static const struct regmap_config wm8580_regmap = {
.reg_defaults = wm8580_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8580_volatile,
};
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 903a0147d584..916f297164de 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -393,7 +393,7 @@ static const struct regmap_config wm8711_regmap = {
.reg_defaults = wm8711_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8711_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8711_volatile,
};
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 5ea6d8fd10f6..0c943e7d4159 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -236,7 +236,7 @@ static const struct regmap_config wm8728_regmap = {
.reg_defaults = wm8728_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8728_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
#if defined(CONFIG_SPI_MASTER)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index d5ab3ba126a6..efc160c75f40 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -642,7 +642,7 @@ const struct regmap_config wm8731_regmap = {
.max_register = WM8731_RESET,
.volatile_reg = wm8731_volatile,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8731_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 9f4e372e90ea..0d231c289ef3 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -599,7 +599,7 @@ static const struct regmap_config wm8737_regmap = {
.reg_defaults = wm8737_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8737_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8737_volatile,
};
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 787156b980a1..19e8fc4062c7 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -543,7 +543,7 @@ static const struct regmap_config wm8741_regmap = {
.reg_defaults = wm8741_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm8741_set_pdata(struct device *dev, struct wm8741_priv *wm8741)
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 20dc9ff9fea9..2d2feaf95e49 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -735,7 +735,7 @@ static const struct regmap_config wm8750_regmap = {
.reg_defaults = wm8750_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
#if defined(CONFIG_SPI_MASTER)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 5e8a8eb41b2b..b5d8290c37d9 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1507,7 +1507,7 @@ static const struct regmap_config wm8753_regmap = {
.max_register = WM8753_ADCTL2,
.volatile_reg = wm8753_volatile,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8753_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index e03fee8869c3..2469f4f3bea3 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -632,7 +632,7 @@ static const struct regmap_config wm8770_regmap = {
.reg_defaults = wm8770_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8770_volatile_reg,
};
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 212224a68006..0673bbd32bab 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -451,7 +451,7 @@ static const struct regmap_config wm8776_regmap = {
.reg_defaults = wm8776_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8776_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8776_volatile,
};
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 0b234bae480e..bbb4b6e3b41c 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -555,7 +555,7 @@ const struct regmap_config wm8804_regmap_config = {
.max_register = WM8804_MAX_REGISTER,
.volatile_reg = wm8804_volatile,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8804_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 320ccd92f318..84d06c190411 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1223,7 +1223,7 @@ static const struct regmap_config wm8900_regmap = {
.reg_defaults = wm8900_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8900_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8900_volatile_register,
};
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 901b65ef8de5..84ae1102ac88 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1902,7 +1902,7 @@ static const struct regmap_config wm8903_regmap = {
.volatile_reg = wm8903_volatile_register,
.readable_reg = wm8903_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8903_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8903_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f2baee7c332e..60319b468fb2 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2148,7 +2148,7 @@ static const struct regmap_config wm8904_regmap = {
.volatile_reg = wm8904_volatile_register,
.readable_reg = wm8904_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8904_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 53c27986d216..b9432f8b64e5 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -815,7 +815,7 @@ static const struct regmap_config wm8940_regmap = {
.max_register = WM8940_MONOMIX,
.reg_defaults = wm8940_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8940_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.readable_reg = wm8940_readable_register,
.volatile_reg = wm8940_volatile_register,
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 78044f580a67..4f4338326438 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -962,7 +962,7 @@ static const struct regmap_config wm8955_regmap = {
.volatile_reg = wm8955_volatile,
.writeable_reg = wm8955_writeable,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8955_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 366f5d769d6d..c2bd9ef41ebb 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -155,6 +155,7 @@ static const char *wm8960_adc_data_output_sel[] = {
"Left Data = Right ADC; Right Data = Left ADC",
};
static const char *wm8960_dmonomix[] = {"Stereo", "Mono"};
+static const char *wm8960_dacslope[] = {"Normal", "Sloping"};
static const struct soc_enum wm8960_enum[] = {
SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
@@ -165,6 +166,7 @@ static const struct soc_enum wm8960_enum[] = {
SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
SOC_ENUM_SINGLE(WM8960_ADDCTL1, 2, 4, wm8960_adc_data_output_sel),
SOC_ENUM_SINGLE(WM8960_ADDCTL1, 4, 2, wm8960_dmonomix),
+ SOC_ENUM_SINGLE(WM8960_DACCTL2, 1, 2, wm8960_dacslope),
};
static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
@@ -307,6 +309,7 @@ SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",
SOC_ENUM("ADC Data Output Select", wm8960_enum[6]),
SOC_ENUM("DAC Mono Mix", wm8960_enum[7]),
+SOC_ENUM("DAC Filter Characteristics", wm8960_enum[8]),
};
static const struct snd_kcontrol_new wm8960_lin_boost[] = {
@@ -1387,7 +1390,7 @@ static const struct regmap_config wm8960_regmap = {
.reg_defaults = wm8960_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8960_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8960_volatile,
};
@@ -1415,6 +1418,7 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8960_priv *wm8960;
int ret;
+ u8 val;
wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct wm8960_priv),
GFP_KERNEL);
@@ -1436,6 +1440,12 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
else if (i2c->dev.of_node)
wm8960_set_pdata_from_of(i2c, &wm8960->pdata);
+ ret = i2c_master_recv(i2c, &val, sizeof(val));
+ if (ret >= 0) {
+ dev_err(&i2c->dev, "Not wm8960, wm8960 reg can not read by i2c\n");
+ return -EINVAL;
+ }
+
ret = wm8960_reset(wm8960->regmap);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset\n");
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index c076f78d04ce..8f8330efb341 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -904,7 +904,7 @@ static const struct regmap_config wm8961_regmap = {
.reg_defaults = wm8961_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8961_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm8961_volatile,
.readable_reg = wm8961_readable,
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 68ea15be7330..83ce5dbecc45 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3573,7 +3573,7 @@ static const struct regmap_config wm8962_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8962_reg),
.volatile_reg = wm8962_volatile_register,
.readable_reg = wm8962_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm8962_set_pdata_from_of(struct i2c_client *i2c,
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index b22d8f0b59be..e88f323d28b2 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -668,7 +668,7 @@ static const struct regmap_config wm8971_regmap = {
.reg_defaults = wm8971_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm8971_i2c_probe(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 5c829301cf4c..718bfef302cc 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -1014,7 +1014,7 @@ static const struct regmap_config wm8978_regmap_config = {
.max_register = WM8978_MAX_REGISTER,
.volatile_reg = wm8978_volatile,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8978_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 2bd26e2478d9..b26d6a68e8d2 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -995,7 +995,7 @@ static const struct regmap_config wm8983_regmap = {
.reg_defaults = wm8983_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8983_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.max_register = WM8983_MAX_REGISTER,
.writeable_reg = wm8983_writeable,
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index c0816bcfa294..8606e0752a60 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1125,7 +1125,7 @@ static const struct regmap_config wm8985_regmap = {
.max_register = WM8985_MAX_REGISTER,
.writeable_reg = wm8985_writeable,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8985_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8985_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index b440719cca7d..76f214f12ce0 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -832,7 +832,7 @@ static const struct regmap_config wm8988_regmap = {
.max_register = WM8988_LPPB,
.writeable_reg = wm8988_writeable,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8988_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 8cb2ae829699..590318aafaea 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1253,7 +1253,7 @@ static const struct regmap_config wm8991_regmap = {
.volatile_reg = wm8991_volatile,
.reg_defaults = wm8991_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8991_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm8991_i2c_probe(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index feb997c698e2..5b788f35e5e4 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1608,7 +1608,7 @@ static const struct regmap_config wm8993_regmap = {
.volatile_reg = wm8993_volatile,
.readable_reg = wm8993_readable,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm8993_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults),
};
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 90588614edcc..4ffa1896faab 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2193,7 +2193,7 @@ static const struct regmap_config wm8995_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8995_reg_defaults),
.volatile_reg = wm8995_volatile,
.readable_reg = wm8995_readable,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
#if defined(CONFIG_SPI_MASTER)
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 5d0eb0ae0475..df6195778c57 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -2610,7 +2610,7 @@ static const struct regmap_config wm8996_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm8996_reg),
.volatile_reg = wm8996_volatile_register,
.readable_reg = wm8996_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm8996_probe(struct snd_soc_component *component)
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 34a07db7342a..e7ec799573d3 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1295,7 +1295,7 @@ static const struct regmap_config wm9081_regmap = {
.num_reg_defaults = ARRAY_SIZE(wm9081_reg),
.volatile_reg = wm9081_volatile_register,
.readable_reg = wm9081_readable_register,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static int wm9081_i2c_probe(struct i2c_client *i2c)
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 432729c753dd..50c1cbccfdb9 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -553,7 +553,7 @@ static const struct regmap_config wm9090_regmap = {
.volatile_reg = wm9090_volatile,
.readable_reg = wm9090_readable,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm9090_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults),
};
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index d04902ef1d5f..5c6aebe29cf1 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -64,7 +64,7 @@ static const struct regmap_config wm9705_regmap_config = {
.reg_stride = 2,
.val_bits = 16,
.max_register = 0x7e,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = regmap_ac97_default_volatile,
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index df9b7980706b..e63921de0c37 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -86,7 +86,7 @@ static const struct regmap_config wm9712_regmap_config = {
.reg_stride = 2,
.val_bits = 16,
.max_register = 0x7e,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.volatile_reg = wm9712_volatile_reg,
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 5d2e54e06e30..64b69316e4c7 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -727,7 +727,7 @@ static const struct regmap_config wm9713_regmap_config = {
.reg_stride = 2,
.val_bits = 16,
.max_register = 0x7e,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wm9713_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(wm9713_reg_defaults),
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
index 97f6873a0a8c..3c025dabaf7a 100644
--- a/sound/soc/codecs/wsa881x.c
+++ b/sound/soc/codecs/wsa881x.c
@@ -637,7 +637,7 @@ static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
static struct regmap_config wsa881x_regmap_config = {
.reg_bits = 32,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wsa881x_defaults,
.max_register = WSA881X_SPKR_STATUS3,
.num_reg_defaults = ARRAY_SIZE(wsa881x_defaults),
diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
index e40d583a1ce6..197fae23762f 100644
--- a/sound/soc/codecs/wsa883x.c
+++ b/sound/soc/codecs/wsa883x.c
@@ -938,7 +938,7 @@ static bool wsa883x_volatile_register(struct device *dev, unsigned int reg)
static struct regmap_config wsa883x_regmap_config = {
.reg_bits = 32,
.val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
.reg_defaults = wsa883x_defaults,
.max_register = WSA883X_MAX_REGISTER,
.num_reg_defaults = ARRAY_SIZE(wsa883x_defaults),