Alsa-devel
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
December 2017
- 145 participants
- 233 discussions
[alsa-devel] [PATCH v7] ASoC: TSCS42xx: Add support for Tempo Semiconductor's TSCS42xx audio CODEC
by Steven Eckhoff 07 Jan '18
by Steven Eckhoff 07 Jan '18
07 Jan '18
Currently there is no support for TSCS42xx audio CODECs.
Add support for TSCS42xx audio CODECs.
Reviewed-by: Charles Keepax <ckeepax(a)opensource.cirrus.com>
Acked-by: Philippe Ombredanne <pombredanne(a)nexb.com>
Signed-off-by: Steven Eckhoff <steven.eckhoff.opensource(a)gmail.com>
---
Thank you to everyone involved in improving this driver.
In the following history I have attempted to address every comment made
during the review process.
History:
v7:
- Remove unused D2S mux controls
- Add coeff_ram_get and coeff_ram_put to COEFF_RAM_CTL
- Remove get/put arguments from COEFF_RAM_CTL
- Add Reviewed-by: Charles Keepax <ckeepax(a)opensource.cirrus.com>
v6:
- Remove leftover TLV stuff
- Make bytes_ext_info static
- Make compatible strings for specific devices
- Change vendor prefix from tscs to tempo
- Add upper bound to daccrstat reads
- Reove PLL power up/down from mute callbacks
- Add PLL DAPM widget
- Wire up PLL DAPM widget
- Add comment about why slave is not supported
- Replace non-standard reg patch with regmap patch
- Remove empty tscs42xx_remove call back
- Make I2C ids explicit part numbers
- Add Acked-by: Philippe Ombredanne <pombredanne(a)nexb.com>
v5:
- No change
v4:
- Add SPDX ids
v3:
- Remove sysfs interface used to program coefficients
- Add standard ALSA binary interface for programming coefficients
- Put Kconfig entry in sorted order
- Remove dev_info
- Replace mdelay with msleep
- Increase granularity of locking
- Make locking self documenting
- Remove redundant case in tscs42xx_set_dai_fmt
- Fix Kernel coding style issue
- Replace non-standard I2C read/write calls with regmap calls
- Remove clocking logic
- Add MCLK1 case
- Add module_i2c_driver()
v2:
- Fix email address
v1:
- Initial patch
diffstat:
.../devicetree/bindings/sound/tscs42xx.txt | 16 +
.../devicetree/bindings/vendor-prefixes.txt | 1 +
MAINTAINERS | 7 +
sound/soc/codecs/Kconfig | 8 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/tscs42xx.c | 1456 +++++++++++
sound/soc/codecs/tscs42xx.h | 2693 ++++++++++++++++++++
7 files changed, 4183 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/tscs42xx.txt
create mode 100644 sound/soc/codecs/tscs42xx.c
create mode 100644 sound/soc/codecs/tscs42xx.h
diff --git a/Documentation/devicetree/bindings/sound/tscs42xx.txt b/Documentation/devicetree/bindings/sound/tscs42xx.txt
new file mode 100644
index 000000000000..2ac2f0996697
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tscs42xx.txt
@@ -0,0 +1,16 @@
+TSCS42XX Audio CODEC
+
+Required Properties:
+
+ - compatible : "tempo,tscs42A1" for analog mic
+ "tempo,tscs42A2" for digital mic
+
+ - reg : <0x71> for analog mic
+ <0x69> for digital mic
+
+Example:
+
+wookie: codec@69 {
+ compatible = "tempo,tscs42A2";
+ reg = <0x69>;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 19e1ef73ab0d..4543e688c5d4 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -54,6 +54,7 @@ snps Synopsys, Inc.
st STMicroelectronics
ste ST-Ericsson
stericsson ST-Ericsson
+tempo Tempo Semiconductor
ti Texas Instruments
toshiba Toshiba Corporation
via VIA Technologies, Inc.
diff --git a/MAINTAINERS b/MAINTAINERS
index 8bdd7a7ef2f4..6c9adfcbc7a4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8094,6 +8094,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git
S: Maintained
K: ^Subject:.*(?i)trivial
+TEMPO SEMICONDUCTOR DRIVERS
+M: Steven Eckhoff <steven.eckhoff.opensource(a)gmail.com>
+S: Maintained
+F: sound/soc/codecs/tscs*.c
+F: sound/soc/codecs/tscs*.h
+F: Documentation/devicetree/bindings/sound/tscs*.txt
+
TTY LAYER
M: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
M: Jiri Slaby <jslaby(a)suse.cz>
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 45b72561c615..dcedfaa2c94d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -69,6 +69,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TLV320AIC3X if I2C
select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C
+ select SND_SOC_TSCS42XX if I2C
select SND_SOC_TWL4030 if TWL4030_CORE
select SND_SOC_TWL6040 if TWL6040_CORE
select SND_SOC_UDA134X
@@ -336,6 +337,13 @@ config SND_SOC_TLV320AIC3X
config SND_SOC_TLV320DAC33
tristate
+config SND_SOC_TSCS42XX
+ tristate "Tempo Semiconductor TSCS42xx CODEC"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Add support for Tempo Semiconductor's TSCS42xx audio CODEC.
+
config SND_SOC_TWL4030
select MFD_TWL4030_AUDIO
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 6a3b3c3b8b41..2d42710a6bc2 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -60,6 +60,7 @@ snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
snd-soc-tlv320dac33-objs := tlv320dac33.o
+snd-soc-tscs42xx-objs := tscs42xx.o
snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
@@ -182,6 +183,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
+obj-$(CONFIG_SND_SOC_TSCS42XX) += snd-soc-tscs42xx.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c
new file mode 100644
index 000000000000..eedd600875e5
--- /dev/null
+++ b/sound/soc/codecs/tscs42xx.c
@@ -0,0 +1,1456 @@
+// SPDX-License-Identifier: GPL-2.0
+// tscs42xx.c -- TSCS42xx ALSA SoC Audio driver
+// Copyright 2017 Tempo Semiconductor, Inc.
+// Author: Steven Eckhoff <steven.eckhoff.opensource(a)gmail.com>
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "tscs42xx.h"
+
+#define COEFF_SIZE 3
+#define BIQUAD_COEFF_COUNT 5
+#define BIQUAD_SIZE (COEFF_SIZE * BIQUAD_COEFF_COUNT)
+
+#define COEFF_RAM_MAX_ADDR 0xcd
+#define COEFF_RAM_COEFF_COUNT (COEFF_RAM_MAX_ADDR + 1)
+#define COEFF_RAM_SIZE (COEFF_SIZE * COEFF_RAM_COEFF_COUNT)
+
+struct tscs42xx {
+
+ int bclk_ratio;
+ int samplerate;
+ unsigned int blrcm;
+ struct mutex audio_params_lock;
+
+ u8 coeff_ram[COEFF_RAM_SIZE];
+ bool coeff_ram_synced;
+ struct mutex coeff_ram_lock;
+
+ struct mutex pll_lock;
+
+ struct regmap *regmap;
+
+ struct device *dev;
+};
+
+struct coeff_ram_ctl {
+ unsigned int addr;
+ struct soc_bytes_ext bytes_ext;
+};
+
+static bool tscs42xx_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case R_DACCRWRL:
+ case R_DACCRWRM:
+ case R_DACCRWRH:
+ case R_DACCRRDL:
+ case R_DACCRRDM:
+ case R_DACCRRDH:
+ case R_DACCRSTAT:
+ case R_DACCRADDR:
+ case R_PLLCTL0:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tscs42xx_precious(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case R_DACCRWRL:
+ case R_DACCRWRM:
+ case R_DACCRWRH:
+ case R_DACCRRDL:
+ case R_DACCRRDM:
+ case R_DACCRRDH:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config tscs42xx_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .volatile_reg = tscs42xx_volatile,
+ .precious_reg = tscs42xx_precious,
+ .max_register = R_DACMBCREL3H,
+
+ .cache_type = REGCACHE_RBTREE,
+ .can_multi_write = true,
+};
+
+#define MAX_PLL_LOCK_20MS_WAITS 1
+static bool plls_locked(struct snd_soc_codec *codec)
+{
+ int ret;
+ int count = MAX_PLL_LOCK_20MS_WAITS;
+
+ do {
+ ret = snd_soc_read(codec, R_PLLCTL0);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to read PLL lock status (%d)\n", ret);
+ return false;
+ } else if (ret > 0) {
+ return true;
+ }
+ msleep(20);
+ } while (count--);
+
+ return false;
+}
+
+static int sample_rate_to_pll_freq_out(int sample_rate)
+{
+ switch (sample_rate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ return 112896000;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 96000:
+ return 122880000;
+ default:
+ return -EINVAL;
+ }
+}
+
+#define DACCRSTAT_MAX_TRYS 10
+static int write_coeff_ram(struct snd_soc_codec *codec, u8 *coeff_ram,
+ unsigned int addr, unsigned int coeff_cnt)
+{
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ int cnt;
+ int trys;
+ int ret;
+
+ for (cnt = 0; cnt < coeff_cnt; cnt++, addr++) {
+
+ for (trys = 0; trys < DACCRSTAT_MAX_TRYS; trys++) {
+ ret = snd_soc_read(codec, R_DACCRSTAT);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to read stat (%d)\n", ret);
+ return ret;
+ }
+ if (!ret)
+ break;
+ }
+
+ if (trys == DACCRSTAT_MAX_TRYS) {
+ ret = -EIO;
+ dev_err(codec->dev,
+ "dac coefficient write error (%d)\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(tscs42xx->regmap, R_DACCRADDR, addr);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to write dac ram address (%d)\n", ret);
+ return ret;
+ }
+
+ ret = regmap_bulk_write(tscs42xx->regmap, R_DACCRWRL,
+ &coeff_ram[addr * COEFF_SIZE],
+ COEFF_SIZE);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to write dac ram (%d)\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int power_up_audio_plls(struct snd_soc_codec *codec)
+{
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ int freq_out;
+ int ret;
+ unsigned int mask;
+ unsigned int val;
+
+ freq_out = sample_rate_to_pll_freq_out(tscs42xx->samplerate);
+ switch (freq_out) {
+ case 122880000: /* 48k */
+ mask = RM_PLLCTL1C_PDB_PLL1;
+ val = RV_PLLCTL1C_PDB_PLL1_ENABLE;
+ break;
+ case 112896000: /* 44.1k */
+ mask = RM_PLLCTL1C_PDB_PLL2;
+ val = RV_PLLCTL1C_PDB_PLL2_ENABLE;
+ break;
+ default:
+ ret = -EINVAL;
+ dev_err(codec->dev, "Unrecognized PLL output freq (%d)\n", ret);
+ return ret;
+ }
+
+ mutex_lock(&tscs42xx->pll_lock);
+
+ ret = snd_soc_update_bits(codec, R_PLLCTL1C, mask, val);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to turn PLL on (%d)\n", ret);
+ goto exit;
+ }
+
+ if (!plls_locked(codec)) {
+ dev_err(codec->dev, "Failed to lock plls\n");
+ ret = -ENOMSG;
+ goto exit;
+ }
+
+ ret = 0;
+exit:
+ mutex_unlock(&tscs42xx->pll_lock);
+
+ return ret;
+}
+
+static int power_down_audio_plls(struct snd_soc_codec *codec)
+{
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ mutex_lock(&tscs42xx->pll_lock);
+
+ ret = snd_soc_update_bits(codec, R_PLLCTL1C,
+ RM_PLLCTL1C_PDB_PLL1,
+ RV_PLLCTL1C_PDB_PLL1_DISABLE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to turn PLL off (%d)\n", ret);
+ goto exit;
+ }
+ ret = snd_soc_update_bits(codec, R_PLLCTL1C,
+ RM_PLLCTL1C_PDB_PLL2,
+ RV_PLLCTL1C_PDB_PLL2_DISABLE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to turn PLL off (%d)\n", ret);
+ goto exit;
+ }
+
+ ret = 0;
+exit:
+ mutex_unlock(&tscs42xx->pll_lock);
+
+ return ret;
+}
+
+static int coeff_ram_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ struct coeff_ram_ctl *ctl =
+ (struct coeff_ram_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+
+ mutex_lock(&tscs42xx->coeff_ram_lock);
+
+ memcpy(ucontrol->value.bytes.data,
+ &tscs42xx->coeff_ram[ctl->addr * COEFF_SIZE], params->max);
+
+ mutex_unlock(&tscs42xx->coeff_ram_lock);
+
+ return 0;
+}
+
+static int coeff_ram_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ struct coeff_ram_ctl *ctl =
+ (struct coeff_ram_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+ unsigned int coeff_cnt = params->max / COEFF_SIZE;
+ int ret;
+
+ mutex_lock(&tscs42xx->coeff_ram_lock);
+
+ tscs42xx->coeff_ram_synced = false;
+
+ memcpy(&tscs42xx->coeff_ram[ctl->addr * COEFF_SIZE],
+ ucontrol->value.bytes.data, params->max);
+
+ mutex_lock(&tscs42xx->pll_lock);
+
+ if (plls_locked(codec)) {
+ ret = write_coeff_ram(codec, tscs42xx->coeff_ram,
+ ctl->addr, coeff_cnt);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to flush coeff ram cache (%d)\n", ret);
+ goto exit;
+ }
+ tscs42xx->coeff_ram_synced = true;
+ }
+
+ ret = 0;
+exit:
+ mutex_unlock(&tscs42xx->pll_lock);
+
+ mutex_unlock(&tscs42xx->coeff_ram_lock);
+
+ return ret;
+}
+
+/* Input L Capture Route */
+static char const * const input_select_text[] = {
+ "Line 1", "Line 2", "Line 3", "D2S"
+};
+
+static const struct soc_enum left_input_select_enum =
+SOC_ENUM_SINGLE(R_INSELL, FB_INSELL, ARRAY_SIZE(input_select_text),
+ input_select_text);
+
+static const struct snd_kcontrol_new left_input_select =
+SOC_DAPM_ENUM("LEFT_INPUT_SELECT_ENUM", left_input_select_enum);
+
+/* Input R Capture Route */
+static const struct soc_enum right_input_select_enum =
+SOC_ENUM_SINGLE(R_INSELR, FB_INSELR, ARRAY_SIZE(input_select_text),
+ input_select_text);
+
+static const struct snd_kcontrol_new right_input_select =
+SOC_DAPM_ENUM("RIGHT_INPUT_SELECT_ENUM", right_input_select_enum);
+
+/* Input Channel Mapping */
+static char const * const ch_map_select_text[] = {
+ "Normal", "Left to Right", "Right to Left", "Swap"
+};
+
+static const struct soc_enum ch_map_select_enum =
+SOC_ENUM_SINGLE(R_AIC2, FB_AIC2_ADCDSEL, ARRAY_SIZE(ch_map_select_text),
+ ch_map_select_text);
+
+static int dapm_vref_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ msleep(20);
+ return 0;
+}
+
+static int dapm_micb_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ msleep(20);
+ return 0;
+}
+
+int pll_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ int ret;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ ret = power_up_audio_plls(codec);
+ else
+ ret = power_down_audio_plls(codec);
+
+ return ret;
+}
+
+int dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ mutex_lock(&tscs42xx->coeff_ram_lock);
+
+ if (tscs42xx->coeff_ram_synced == false) {
+ ret = write_coeff_ram(codec, tscs42xx->coeff_ram, 0x00,
+ COEFF_RAM_COEFF_COUNT);
+ if (ret < 0)
+ goto exit;
+ tscs42xx->coeff_ram_synced = true;
+ }
+
+ ret = 0;
+exit:
+ mutex_unlock(&tscs42xx->coeff_ram_lock);
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget tscs42xx_dapm_widgets[] = {
+ /* Vref */
+ SND_SOC_DAPM_SUPPLY_S("Vref", 1, R_PWRM2, FB_PWRM2_VREF, 0,
+ dapm_vref_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
+
+ /* PLL */
+ SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, pll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Headphone */
+ SND_SOC_DAPM_DAC_E("DAC L", "HiFi Playback", R_PWRM2, FB_PWRM2_HPL, 0,
+ dac_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_DAC_E("DAC R", "HiFi Playback", R_PWRM2, FB_PWRM2_HPR, 0,
+ dac_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_OUTPUT("Headphone L"),
+ SND_SOC_DAPM_OUTPUT("Headphone R"),
+
+ /* Speaker */
+ SND_SOC_DAPM_DAC_E("ClassD L", "HiFi Playback",
+ R_PWRM2, FB_PWRM2_SPKL, 0,
+ dac_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_DAC_E("ClassD R", "HiFi Playback",
+ R_PWRM2, FB_PWRM2_SPKR, 0,
+ dac_event, SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_OUTPUT("Speaker L"),
+ SND_SOC_DAPM_OUTPUT("Speaker R"),
+
+ /* Capture */
+ SND_SOC_DAPM_PGA("Analog In PGA L", R_PWRM1, FB_PWRM1_PGAL, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Analog In PGA R", R_PWRM1, FB_PWRM1_PGAR, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Analog Boost L", R_PWRM1, FB_PWRM1_BSTL, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Analog Boost R", R_PWRM1, FB_PWRM1_BSTR, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ADC Mute", R_CNVRTR0, FB_CNVRTR0_HPOR, true, NULL, 0),
+ SND_SOC_DAPM_ADC("ADC L", "HiFi Capture", R_PWRM1, FB_PWRM1_ADCL, 0),
+ SND_SOC_DAPM_ADC("ADC R", "HiFi Capture", R_PWRM1, FB_PWRM1_ADCR, 0),
+
+ /* Capture Input */
+ SND_SOC_DAPM_MUX("Input L Capture Route", R_PWRM2,
+ FB_PWRM2_INSELL, 0, &left_input_select),
+ SND_SOC_DAPM_MUX("Input R Capture Route", R_PWRM2,
+ FB_PWRM2_INSELR, 0, &right_input_select),
+
+ /* Digital Mic */
+ SND_SOC_DAPM_SUPPLY_S("Digital Mic Enable", 2, R_DMICCTL,
+ FB_DMICCTL_DMICEN, 0, NULL,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
+
+ /* Analog Mic */
+ SND_SOC_DAPM_SUPPLY_S("Mic Bias", 2, R_PWRM1, FB_PWRM1_MICB,
+ 0, dapm_micb_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
+
+ /* Line In */
+ SND_SOC_DAPM_INPUT("Line In 1 L"),
+ SND_SOC_DAPM_INPUT("Line In 1 R"),
+ SND_SOC_DAPM_INPUT("Line In 2 L"),
+ SND_SOC_DAPM_INPUT("Line In 2 R"),
+ SND_SOC_DAPM_INPUT("Line In 3 L"),
+ SND_SOC_DAPM_INPUT("Line In 3 R"),
+};
+
+static const struct snd_soc_dapm_route tscs42xx_intercon[] = {
+ {"DAC L", NULL, "PLL"},
+ {"DAC R", NULL, "PLL"},
+ {"DAC L", NULL, "Vref"},
+ {"DAC R", NULL, "Vref"},
+ {"Headphone L", NULL, "DAC L"},
+ {"Headphone R", NULL, "DAC R"},
+
+ {"ClassD L", NULL, "PLL"},
+ {"ClassD R", NULL, "PLL"},
+ {"ClassD L", NULL, "Vref"},
+ {"ClassD R", NULL, "Vref"},
+ {"Speaker L", NULL, "ClassD L"},
+ {"Speaker R", NULL, "ClassD R"},
+
+ {"Input L Capture Route", NULL, "Vref"},
+ {"Input R Capture Route", NULL, "Vref"},
+
+ {"Mic Bias", NULL, "Vref"},
+
+ {"Input L Capture Route", "Line 1", "Line In 1 L"},
+ {"Input R Capture Route", "Line 1", "Line In 1 R"},
+ {"Input L Capture Route", "Line 2", "Line In 2 L"},
+ {"Input R Capture Route", "Line 2", "Line In 2 R"},
+ {"Input L Capture Route", "Line 3", "Line In 3 L"},
+ {"Input R Capture Route", "Line 3", "Line In 3 R"},
+
+ {"Analog In PGA L", NULL, "Input L Capture Route"},
+ {"Analog In PGA R", NULL, "Input R Capture Route"},
+ {"Analog Boost L", NULL, "Analog In PGA L"},
+ {"Analog Boost R", NULL, "Analog In PGA R"},
+ {"ADC Mute", NULL, "Analog Boost L"},
+ {"ADC Mute", NULL, "Analog Boost R"},
+ {"ADC L", NULL, "PLL"},
+ {"ADC R", NULL, "PLL"},
+ {"ADC L", NULL, "ADC Mute"},
+ {"ADC R", NULL, "ADC Mute"},
+};
+
+/************
+ * CONTROLS *
+ ************/
+
+static char const * const eq_band_enable_text[] = {
+ "Prescale only",
+ "Band1",
+ "Band1:2",
+ "Band1:3",
+ "Band1:4",
+ "Band1:5",
+ "Band1:6",
+};
+
+static char const * const level_detection_text[] = {
+ "Average",
+ "Peak",
+};
+
+static char const * const level_detection_window_text[] = {
+ "512 Samples",
+ "64 Samples",
+};
+
+static char const * const compressor_ratio_text[] = {
+ "Reserved", "1.5:1", "2:1", "3:1", "4:1", "5:1", "6:1",
+ "7:1", "8:1", "9:1", "10:1", "11:1", "12:1", "13:1", "14:1",
+ "15:1", "16:1", "17:1", "18:1", "19:1", "20:1",
+};
+
+static DECLARE_TLV_DB_SCALE(hpvol_scale, -8850, 75, 0);
+static DECLARE_TLV_DB_SCALE(spkvol_scale, -7725, 75, 0);
+static DECLARE_TLV_DB_SCALE(dacvol_scale, -9563, 38, 0);
+static DECLARE_TLV_DB_SCALE(adcvol_scale, -7125, 38, 0);
+static DECLARE_TLV_DB_SCALE(invol_scale, -1725, 75, 0);
+static DECLARE_TLV_DB_SCALE(mic_boost_scale, 0, 1000, 0);
+static DECLARE_TLV_DB_MINMAX(mugain_scale, 0, 4650);
+static DECLARE_TLV_DB_MINMAX(compth_scale, -9562, 0);
+
+static const struct soc_enum eq1_band_enable_enum =
+ SOC_ENUM_SINGLE(R_CONFIG1, FB_CONFIG1_EQ1_BE,
+ ARRAY_SIZE(eq_band_enable_text), eq_band_enable_text);
+
+static const struct soc_enum eq2_band_enable_enum =
+ SOC_ENUM_SINGLE(R_CONFIG1, FB_CONFIG1_EQ2_BE,
+ ARRAY_SIZE(eq_band_enable_text), eq_band_enable_text);
+
+static const struct soc_enum cle_level_detection_enum =
+ SOC_ENUM_SINGLE(R_CLECTL, FB_CLECTL_LVL_MODE,
+ ARRAY_SIZE(level_detection_text),
+ level_detection_text);
+
+static const struct soc_enum cle_level_detection_window_enum =
+ SOC_ENUM_SINGLE(R_CLECTL, FB_CLECTL_WINDOWSEL,
+ ARRAY_SIZE(level_detection_window_text),
+ level_detection_window_text);
+
+static const struct soc_enum mbc_level_detection_enums[] = {
+ SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_LVLMODE1,
+ ARRAY_SIZE(level_detection_text),
+ level_detection_text),
+ SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_LVLMODE2,
+ ARRAY_SIZE(level_detection_text),
+ level_detection_text),
+ SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_LVLMODE3,
+ ARRAY_SIZE(level_detection_text),
+ level_detection_text),
+};
+
+static const struct soc_enum mbc_level_detection_window_enums[] = {
+ SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_WINSEL1,
+ ARRAY_SIZE(level_detection_window_text),
+ level_detection_window_text),
+ SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_WINSEL2,
+ ARRAY_SIZE(level_detection_window_text),
+ level_detection_window_text),
+ SOC_ENUM_SINGLE(R_DACMBCCTL, FB_DACMBCCTL_WINSEL3,
+ ARRAY_SIZE(level_detection_window_text),
+ level_detection_window_text),
+};
+
+static const struct soc_enum compressor_ratio_enum =
+ SOC_ENUM_SINGLE(R_CMPRAT, FB_CMPRAT,
+ ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
+
+static const struct soc_enum dac_mbc1_compressor_ratio_enum =
+ SOC_ENUM_SINGLE(R_DACMBCRAT1, FB_DACMBCRAT1_RATIO,
+ ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
+
+static const struct soc_enum dac_mbc2_compressor_ratio_enum =
+ SOC_ENUM_SINGLE(R_DACMBCRAT2, FB_DACMBCRAT2_RATIO,
+ ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
+
+static const struct soc_enum dac_mbc3_compressor_ratio_enum =
+ SOC_ENUM_SINGLE(R_DACMBCRAT3, FB_DACMBCRAT3_RATIO,
+ ARRAY_SIZE(compressor_ratio_text), compressor_ratio_text);
+
+static int bytes_info_ext(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *ucontrol)
+{
+ struct coeff_ram_ctl *ctl =
+ (struct coeff_ram_ctl *)kcontrol->private_value;
+ struct soc_bytes_ext *params = &ctl->bytes_ext;
+
+ ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ ucontrol->count = params->max;
+
+ return 0;
+}
+
+#define COEFF_RAM_CTL(xname, xcount, xaddr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = bytes_info_ext, \
+ .get = coeff_ram_get, .put = coeff_ram_put, \
+ .private_value = (unsigned long)&(struct coeff_ram_ctl) { \
+ .addr = xaddr, \
+ .bytes_ext = {.max = xcount, }, \
+ } \
+}
+
+static const struct snd_kcontrol_new tscs42xx_snd_controls[] = {
+ /* Volumes */
+ SOC_DOUBLE_R_TLV("Headphone Playback Volume", R_HPVOLL, R_HPVOLR,
+ FB_HPVOLL, 0x7F, 0, hpvol_scale),
+ SOC_DOUBLE_R_TLV("Speaker Playback Volume", R_SPKVOLL, R_SPKVOLR,
+ FB_SPKVOLL, 0x7F, 0, spkvol_scale),
+ SOC_DOUBLE_R_TLV("Master Playback Volume", R_DACVOLL, R_DACVOLR,
+ FB_DACVOLL, 0xFF, 0, dacvol_scale),
+ SOC_DOUBLE_R_TLV("PCM Capture Volume", R_ADCVOLL, R_ADCVOLR,
+ FB_ADCVOLL, 0xFF, 0, adcvol_scale),
+ SOC_DOUBLE_R_TLV("Master Capture Volume", R_INVOLL, R_INVOLR,
+ FB_INVOLL, 0x3F, 0, invol_scale),
+
+ /* INSEL */
+ SOC_DOUBLE_R_TLV("Mic Boost Capture Volume", R_INSELL, R_INSELR,
+ FB_INSELL_MICBSTL, FV_INSELL_MICBSTL_30DB,
+ 0, mic_boost_scale),
+
+ /* Input Channel Map */
+ SOC_ENUM("Input Channel Map Switch", ch_map_select_enum),
+
+ /* Coefficient Ram */
+ COEFF_RAM_CTL("Cascade1L BiQuad1", BIQUAD_SIZE, 0x00),
+ COEFF_RAM_CTL("Cascade1L BiQuad2", BIQUAD_SIZE, 0x05),
+ COEFF_RAM_CTL("Cascade1L BiQuad3", BIQUAD_SIZE, 0x0a),
+ COEFF_RAM_CTL("Cascade1L BiQuad4", BIQUAD_SIZE, 0x0f),
+ COEFF_RAM_CTL("Cascade1L BiQuad5", BIQUAD_SIZE, 0x14),
+ COEFF_RAM_CTL("Cascade1L BiQuad6", BIQUAD_SIZE, 0x19),
+
+ COEFF_RAM_CTL("Cascade1R BiQuad1", BIQUAD_SIZE, 0x20),
+ COEFF_RAM_CTL("Cascade1R BiQuad2", BIQUAD_SIZE, 0x25),
+ COEFF_RAM_CTL("Cascade1R BiQuad3", BIQUAD_SIZE, 0x2a),
+ COEFF_RAM_CTL("Cascade1R BiQuad4", BIQUAD_SIZE, 0x2f),
+ COEFF_RAM_CTL("Cascade1R BiQuad5", BIQUAD_SIZE, 0x34),
+ COEFF_RAM_CTL("Cascade1R BiQuad6", BIQUAD_SIZE, 0x39),
+
+ COEFF_RAM_CTL("Cascade1L Prescale", COEFF_SIZE, 0x1f),
+ COEFF_RAM_CTL("Cascade1R Prescale", COEFF_SIZE, 0x3f),
+
+ COEFF_RAM_CTL("Cascade2L BiQuad1", BIQUAD_SIZE, 0x40),
+ COEFF_RAM_CTL("Cascade2L BiQuad2", BIQUAD_SIZE, 0x45),
+ COEFF_RAM_CTL("Cascade2L BiQuad3", BIQUAD_SIZE, 0x4a),
+ COEFF_RAM_CTL("Cascade2L BiQuad4", BIQUAD_SIZE, 0x4f),
+ COEFF_RAM_CTL("Cascade2L BiQuad5", BIQUAD_SIZE, 0x54),
+ COEFF_RAM_CTL("Cascade2L BiQuad6", BIQUAD_SIZE, 0x59),
+
+ COEFF_RAM_CTL("Cascade2R BiQuad1", BIQUAD_SIZE, 0x60),
+ COEFF_RAM_CTL("Cascade2R BiQuad2", BIQUAD_SIZE, 0x65),
+ COEFF_RAM_CTL("Cascade2R BiQuad3", BIQUAD_SIZE, 0x6a),
+ COEFF_RAM_CTL("Cascade2R BiQuad4", BIQUAD_SIZE, 0x6f),
+ COEFF_RAM_CTL("Cascade2R BiQuad5", BIQUAD_SIZE, 0x74),
+ COEFF_RAM_CTL("Cascade2R BiQuad6", BIQUAD_SIZE, 0x79),
+
+ COEFF_RAM_CTL("Cascade2L Prescale", COEFF_SIZE, 0x5f),
+ COEFF_RAM_CTL("Cascade2R Prescale", COEFF_SIZE, 0x7f),
+
+ COEFF_RAM_CTL("Bass Extraction BiQuad1", BIQUAD_SIZE, 0x80),
+ COEFF_RAM_CTL("Bass Extraction BiQuad2", BIQUAD_SIZE, 0x85),
+
+ COEFF_RAM_CTL("Bass Non Linear Function 1", COEFF_SIZE, 0x8a),
+ COEFF_RAM_CTL("Bass Non Linear Function 2", COEFF_SIZE, 0x8b),
+
+ COEFF_RAM_CTL("Bass Limiter BiQuad", BIQUAD_SIZE, 0x8c),
+
+ COEFF_RAM_CTL("Bass Cut Off BiQuad", BIQUAD_SIZE, 0x91),
+
+ COEFF_RAM_CTL("Bass Mix", COEFF_SIZE, 0x96),
+
+ COEFF_RAM_CTL("Treb Extraction BiQuad1", BIQUAD_SIZE, 0x97),
+ COEFF_RAM_CTL("Treb Extraction BiQuad2", BIQUAD_SIZE, 0x9c),
+
+ COEFF_RAM_CTL("Treb Non Linear Function 1", COEFF_SIZE, 0xa1),
+ COEFF_RAM_CTL("Treb Non Linear Function 2", COEFF_SIZE, 0xa2),
+
+ COEFF_RAM_CTL("Treb Limiter BiQuad", BIQUAD_SIZE, 0xa3),
+
+ COEFF_RAM_CTL("Treb Cut Off BiQuad", BIQUAD_SIZE, 0xa8),
+
+ COEFF_RAM_CTL("Treb Mix", COEFF_SIZE, 0xad),
+
+ COEFF_RAM_CTL("3D", COEFF_SIZE, 0xae),
+
+ COEFF_RAM_CTL("3D Mix", COEFF_SIZE, 0xaf),
+
+ COEFF_RAM_CTL("MBC1 BiQuad1", BIQUAD_SIZE, 0xb0),
+ COEFF_RAM_CTL("MBC1 BiQuad2", BIQUAD_SIZE, 0xb5),
+
+ COEFF_RAM_CTL("MBC2 BiQuad1", BIQUAD_SIZE, 0xba),
+ COEFF_RAM_CTL("MBC2 BiQuad2", BIQUAD_SIZE, 0xbf),
+
+ COEFF_RAM_CTL("MBC3 BiQuad1", BIQUAD_SIZE, 0xc4),
+ COEFF_RAM_CTL("MBC3 BiQuad2", BIQUAD_SIZE, 0xc9),
+
+ /* EQ */
+ SOC_SINGLE("EQ1 Switch", R_CONFIG1, FB_CONFIG1_EQ1_EN, 1, 0),
+ SOC_SINGLE("EQ2 Switch", R_CONFIG1, FB_CONFIG1_EQ2_EN, 1, 0),
+ SOC_ENUM("EQ1 Band Enable Switch", eq1_band_enable_enum),
+ SOC_ENUM("EQ2 Band Enable Switch", eq2_band_enable_enum),
+
+ /* CLE */
+ SOC_ENUM("CLE Level Detect Switch",
+ cle_level_detection_enum),
+ SOC_ENUM("CLE Level Detect Win Switch",
+ cle_level_detection_window_enum),
+ SOC_SINGLE("Expander Switch",
+ R_CLECTL, FB_CLECTL_EXP_EN, 1, 0),
+ SOC_SINGLE("Limiter Switch",
+ R_CLECTL, FB_CLECTL_LIMIT_EN, 1, 0),
+ SOC_SINGLE("Comp Switch",
+ R_CLECTL, FB_CLECTL_COMP_EN, 1, 0),
+ SOC_SINGLE_TLV("CLE Make-Up Gain Playback Volume",
+ R_MUGAIN, FB_MUGAIN_CLEMUG, 0x1f, 0, mugain_scale),
+ SOC_SINGLE_TLV("Comp Thresh Playback Volume",
+ R_COMPTH, FB_COMPTH, 0xff, 0, compth_scale),
+ SOC_ENUM("Comp Ratio Switch", compressor_ratio_enum),
+ SND_SOC_BYTES("Comp Atk Time", R_CATKTCL, 2),
+
+ /* Effects */
+ SOC_SINGLE("3D Switch", R_FXCTL, FB_FXCTL_3DEN, 1, 0),
+ SOC_SINGLE("Treble Switch", R_FXCTL, FB_FXCTL_TEEN, 1, 0),
+ SOC_SINGLE("Treble Bypass Switch", R_FXCTL, FB_FXCTL_TNLFBYPASS, 1, 0),
+ SOC_SINGLE("Bass Switch", R_FXCTL, FB_FXCTL_BEEN, 1, 0),
+ SOC_SINGLE("Bass Bypass Switch", R_FXCTL, FB_FXCTL_BNLFBYPASS, 1, 0),
+
+ /* MBC */
+ SOC_SINGLE("MBC Band1 Switch", R_DACMBCEN, FB_DACMBCEN_MBCEN1, 1, 0),
+ SOC_SINGLE("MBC Band2 Switch", R_DACMBCEN, FB_DACMBCEN_MBCEN2, 1, 0),
+ SOC_SINGLE("MBC Band3 Switch", R_DACMBCEN, FB_DACMBCEN_MBCEN3, 1, 0),
+ SOC_ENUM("MBC Band1 Level Detect Switch",
+ mbc_level_detection_enums[0]),
+ SOC_ENUM("MBC Band2 Level Detect Switch",
+ mbc_level_detection_enums[1]),
+ SOC_ENUM("MBC Band3 Level Detect Switch",
+ mbc_level_detection_enums[2]),
+ SOC_ENUM("MBC Band1 Level Detect Win Switch",
+ mbc_level_detection_window_enums[0]),
+ SOC_ENUM("MBC Band2 Level Detect Win Switch",
+ mbc_level_detection_window_enums[1]),
+ SOC_ENUM("MBC Band3 Level Detect Win Switch",
+ mbc_level_detection_window_enums[2]),
+
+ SOC_SINGLE("MBC1 Phase Invert", R_DACMBCMUG1, FB_DACMBCMUG1_PHASE,
+ 1, 0),
+ SOC_SINGLE_TLV("DAC MBC1 Make-Up Gain Playback Volume",
+ R_DACMBCMUG1, FB_DACMBCMUG1_MUGAIN, 0x1f, 0, mugain_scale),
+ SOC_SINGLE_TLV("DAC MBC1 Comp Thresh Playback Volume",
+ R_DACMBCTHR1, FB_DACMBCTHR1_THRESH, 0xff, 0, compth_scale),
+ SOC_ENUM("DAC MBC1 Comp Ratio Switch",
+ dac_mbc1_compressor_ratio_enum),
+ SND_SOC_BYTES("DAC MBC1 Comp Atk Time", R_DACMBCATK1L, 2),
+ SND_SOC_BYTES("DAC MBC1 Comp Rel Time Const",
+ R_DACMBCREL1L, 2),
+
+ SOC_SINGLE("MBC2 Phase Invert", R_DACMBCMUG2, FB_DACMBCMUG2_PHASE,
+ 1, 0),
+ SOC_SINGLE_TLV("DAC MBC2 Make-Up Gain Playback Volume",
+ R_DACMBCMUG2, FB_DACMBCMUG2_MUGAIN, 0x1f, 0, mugain_scale),
+ SOC_SINGLE_TLV("DAC MBC2 Comp Thresh Playback Volume",
+ R_DACMBCTHR2, FB_DACMBCTHR2_THRESH, 0xff, 0, compth_scale),
+ SOC_ENUM("DAC MBC2 Comp Ratio Switch",
+ dac_mbc2_compressor_ratio_enum),
+ SND_SOC_BYTES("DAC MBC2 Comp Atk Time", R_DACMBCATK2L, 2),
+ SND_SOC_BYTES("DAC MBC2 Comp Rel Time Const",
+ R_DACMBCREL2L, 2),
+
+ SOC_SINGLE("MBC3 Phase Invert", R_DACMBCMUG3, FB_DACMBCMUG3_PHASE,
+ 1, 0),
+ SOC_SINGLE_TLV("DAC MBC3 Make-Up Gain Playback Volume",
+ R_DACMBCMUG3, FB_DACMBCMUG3_MUGAIN, 0x1f, 0, mugain_scale),
+ SOC_SINGLE_TLV("DAC MBC3 Comp Thresh Playback Volume",
+ R_DACMBCTHR3, FB_DACMBCTHR3_THRESH, 0xff, 0, compth_scale),
+ SOC_ENUM("DAC MBC3 Comp Ratio Switch",
+ dac_mbc3_compressor_ratio_enum),
+ SND_SOC_BYTES("DAC MBC3 Comp Atk Time", R_DACMBCATK3L, 2),
+ SND_SOC_BYTES("DAC MBC3 Comp Rel Time Const",
+ R_DACMBCREL3L, 2),
+};
+
+static int setup_sample_format(struct snd_soc_codec *codec,
+ snd_pcm_format_t format)
+{
+ unsigned int width;
+ int ret;
+
+ switch (format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ width = RV_AIC1_WL_16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ width = RV_AIC1_WL_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ width = RV_AIC1_WL_24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ width = RV_AIC1_WL_32;
+ break;
+ default:
+ ret = -EINVAL;
+ dev_err(codec->dev, "Unsupported format width (%d)\n", ret);
+ return ret;
+ }
+ ret = snd_soc_update_bits(codec, R_AIC1, RM_AIC1_WL, width);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set sample width (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int setup_sample_rate(struct snd_soc_codec *codec, unsigned int rate)
+{
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ unsigned int br, bm;
+ int ret;
+
+ switch (rate) {
+ case 8000:
+ br = RV_DACSR_DBR_32;
+ bm = RV_DACSR_DBM_PT25;
+ break;
+ case 16000:
+ br = RV_DACSR_DBR_32;
+ bm = RV_DACSR_DBM_PT5;
+ break;
+ case 24000:
+ br = RV_DACSR_DBR_48;
+ bm = RV_DACSR_DBM_PT5;
+ break;
+ case 32000:
+ br = RV_DACSR_DBR_32;
+ bm = RV_DACSR_DBM_1;
+ break;
+ case 48000:
+ br = RV_DACSR_DBR_48;
+ bm = RV_DACSR_DBM_1;
+ break;
+ case 96000:
+ br = RV_DACSR_DBR_48;
+ bm = RV_DACSR_DBM_2;
+ break;
+ case 11025:
+ br = RV_DACSR_DBR_44_1;
+ bm = RV_DACSR_DBM_PT25;
+ break;
+ case 22050:
+ br = RV_DACSR_DBR_44_1;
+ bm = RV_DACSR_DBM_PT5;
+ break;
+ case 44100:
+ br = RV_DACSR_DBR_44_1;
+ bm = RV_DACSR_DBM_1;
+ break;
+ case 88200:
+ br = RV_DACSR_DBR_44_1;
+ bm = RV_DACSR_DBM_2;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported sample rate %d\n", rate);
+ return -EINVAL;
+ }
+
+ /* DAC and ADC share bit and frame clock */
+ ret = snd_soc_update_bits(codec, R_DACSR, RM_DACSR_DBR, br);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to update register (%d)\n", ret);
+ return ret;
+ }
+ ret = snd_soc_update_bits(codec, R_DACSR, RM_DACSR_DBM, bm);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to update register (%d)\n", ret);
+ return ret;
+ }
+ ret = snd_soc_update_bits(codec, R_ADCSR, RM_DACSR_DBR, br);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to update register (%d)\n", ret);
+ return ret;
+ }
+ ret = snd_soc_update_bits(codec, R_ADCSR, RM_DACSR_DBM, bm);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to update register (%d)\n", ret);
+ return ret;
+ }
+
+ mutex_lock(&tscs42xx->audio_params_lock);
+
+ tscs42xx->samplerate = rate;
+
+ mutex_unlock(&tscs42xx->audio_params_lock);
+
+ return 0;
+}
+
+struct reg_setting {
+ unsigned int addr;
+ unsigned int val;
+ unsigned int mask;
+};
+
+#define PLL_REG_SETTINGS_COUNT 13
+struct pll_ctl {
+ int input_freq;
+ struct reg_setting settings[PLL_REG_SETTINGS_COUNT];
+};
+
+#define PLL_CTL(f, rt, rd, r1b_l, r9, ra, rb, \
+ rc, r12, r1b_h, re, rf, r10, r11) \
+ { \
+ .input_freq = f, \
+ .settings = { \
+ {R_TIMEBASE, rt, 0xFF}, \
+ {R_PLLCTLD, rd, 0xFF}, \
+ {R_PLLCTL1B, r1b_l, 0x0F}, \
+ {R_PLLCTL9, r9, 0xFF}, \
+ {R_PLLCTLA, ra, 0xFF}, \
+ {R_PLLCTLB, rb, 0xFF}, \
+ {R_PLLCTLC, rc, 0xFF}, \
+ {R_PLLCTL12, r12, 0xFF}, \
+ {R_PLLCTL1B, r1b_h, 0xF0}, \
+ {R_PLLCTLE, re, 0xFF}, \
+ {R_PLLCTLF, rf, 0xFF}, \
+ {R_PLLCTL10, r10, 0xFF}, \
+ {R_PLLCTL11, r11, 0xFF}, \
+ }, \
+ }
+
+static const struct pll_ctl pll_ctls[] = {
+ PLL_CTL(1411200, 0x05,
+ 0x39, 0x04, 0x07, 0x02, 0xC3, 0x04,
+ 0x1B, 0x10, 0x03, 0x03, 0xD0, 0x02),
+ PLL_CTL(1536000, 0x05,
+ 0x1A, 0x04, 0x02, 0x03, 0xE0, 0x01,
+ 0x1A, 0x10, 0x02, 0x03, 0xB9, 0x01),
+ PLL_CTL(2822400, 0x0A,
+ 0x23, 0x04, 0x07, 0x04, 0xC3, 0x04,
+ 0x22, 0x10, 0x05, 0x03, 0x58, 0x02),
+ PLL_CTL(3072000, 0x0B,
+ 0x22, 0x04, 0x07, 0x03, 0x48, 0x03,
+ 0x1A, 0x10, 0x04, 0x03, 0xB9, 0x01),
+ PLL_CTL(5644800, 0x15,
+ 0x23, 0x04, 0x0E, 0x04, 0xC3, 0x04,
+ 0x1A, 0x10, 0x08, 0x03, 0xE0, 0x01),
+ PLL_CTL(6144000, 0x17,
+ 0x1A, 0x04, 0x08, 0x03, 0xE0, 0x01,
+ 0x1A, 0x10, 0x08, 0x03, 0xB9, 0x01),
+ PLL_CTL(12000000, 0x2E,
+ 0x1B, 0x04, 0x19, 0x03, 0x00, 0x03,
+ 0x2A, 0x10, 0x19, 0x05, 0x98, 0x04),
+ PLL_CTL(19200000, 0x4A,
+ 0x13, 0x04, 0x14, 0x03, 0x80, 0x01,
+ 0x1A, 0x10, 0x19, 0x03, 0xB9, 0x01),
+ PLL_CTL(22000000, 0x55,
+ 0x2A, 0x04, 0x37, 0x05, 0x00, 0x06,
+ 0x22, 0x10, 0x26, 0x03, 0x49, 0x02),
+ PLL_CTL(22579200, 0x57,
+ 0x22, 0x04, 0x31, 0x03, 0x20, 0x03,
+ 0x1A, 0x10, 0x1D, 0x03, 0xB3, 0x01),
+ PLL_CTL(24000000, 0x5D,
+ 0x13, 0x04, 0x19, 0x03, 0x80, 0x01,
+ 0x1B, 0x10, 0x19, 0x05, 0x4C, 0x02),
+ PLL_CTL(24576000, 0x5F,
+ 0x13, 0x04, 0x1D, 0x03, 0xB3, 0x01,
+ 0x22, 0x10, 0x40, 0x03, 0x72, 0x03),
+ PLL_CTL(27000000, 0x68,
+ 0x22, 0x04, 0x4B, 0x03, 0x00, 0x04,
+ 0x2A, 0x10, 0x7D, 0x03, 0x20, 0x06),
+ PLL_CTL(36000000, 0x8C,
+ 0x1B, 0x04, 0x4B, 0x03, 0x00, 0x03,
+ 0x2A, 0x10, 0x7D, 0x03, 0x98, 0x04),
+ PLL_CTL(25000000, 0x61,
+ 0x1B, 0x04, 0x37, 0x03, 0x2B, 0x03,
+ 0x1A, 0x10, 0x2A, 0x03, 0x39, 0x02),
+ PLL_CTL(26000000, 0x65,
+ 0x23, 0x04, 0x41, 0x05, 0x00, 0x06,
+ 0x1A, 0x10, 0x26, 0x03, 0xEF, 0x01),
+ PLL_CTL(12288000, 0x2F,
+ 0x1A, 0x04, 0x12, 0x03, 0x1C, 0x02,
+ 0x22, 0x10, 0x20, 0x03, 0x72, 0x03),
+ PLL_CTL(40000000, 0x9B,
+ 0x22, 0x08, 0x7D, 0x03, 0x80, 0x04,
+ 0x23, 0x10, 0x7D, 0x05, 0xE4, 0x06),
+ PLL_CTL(512000, 0x01,
+ 0x22, 0x04, 0x01, 0x03, 0xD0, 0x02,
+ 0x1B, 0x10, 0x01, 0x04, 0x72, 0x03),
+ PLL_CTL(705600, 0x02,
+ 0x22, 0x04, 0x02, 0x03, 0x15, 0x04,
+ 0x22, 0x10, 0x01, 0x04, 0x80, 0x02),
+ PLL_CTL(1024000, 0x03,
+ 0x22, 0x04, 0x02, 0x03, 0xD0, 0x02,
+ 0x1B, 0x10, 0x02, 0x04, 0x72, 0x03),
+ PLL_CTL(2048000, 0x07,
+ 0x22, 0x04, 0x04, 0x03, 0xD0, 0x02,
+ 0x1B, 0x10, 0x04, 0x04, 0x72, 0x03),
+ PLL_CTL(2400000, 0x08,
+ 0x22, 0x04, 0x05, 0x03, 0x00, 0x03,
+ 0x23, 0x10, 0x05, 0x05, 0x98, 0x04),
+};
+
+static const struct pll_ctl *get_pll_ctl(int input_freq)
+{
+ int i;
+ const struct pll_ctl *pll_ctl = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(pll_ctls); ++i)
+ if (input_freq == pll_ctls[i].input_freq) {
+ pll_ctl = &pll_ctls[i];
+ break;
+ }
+
+ return pll_ctl;
+}
+
+static int set_pll_ctl_from_input_freq(struct snd_soc_codec *codec,
+ const int input_freq)
+{
+ int ret;
+ int i;
+ const struct pll_ctl *pll_ctl;
+
+ pll_ctl = get_pll_ctl(input_freq);
+ if (!pll_ctl) {
+ ret = -EINVAL;
+ dev_err(codec->dev, "No PLL input entry for %d (%d)\n",
+ input_freq, ret);
+ return ret;
+ }
+
+ for (i = 0; i < PLL_REG_SETTINGS_COUNT; ++i) {
+ ret = snd_soc_update_bits(codec,
+ pll_ctl->settings[i].addr,
+ pll_ctl->settings[i].mask,
+ pll_ctl->settings[i].val);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set pll ctl (%d)\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int tscs42xx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int ret;
+
+ ret = setup_sample_format(codec, params_format(params));
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to setup sample format (%d)\n",
+ ret);
+ return ret;
+ }
+
+ ret = setup_sample_rate(codec, params_rate(params));
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to setup sample rate (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline int dac_mute(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_update_bits(codec, R_CNVRTR1, RM_CNVRTR1_DACMU,
+ RV_CNVRTR1_DACMU_ENABLE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to mute DAC (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline int dac_unmute(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_update_bits(codec, R_CNVRTR1, RM_CNVRTR1_DACMU,
+ RV_CNVRTR1_DACMU_DISABLE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to unmute DAC (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline int adc_mute(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_update_bits(codec, R_CNVRTR0, RM_CNVRTR0_ADCMU,
+ RV_CNVRTR0_ADCMU_ENABLE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to mute ADC (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline int adc_unmute(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_update_bits(codec, R_CNVRTR0, RM_CNVRTR0_ADCMU,
+ RV_CNVRTR0_ADCMU_DISABLE);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to unmute ADC (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tscs42xx_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int ret;
+
+ if (mute)
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = dac_mute(codec);
+ else
+ ret = adc_mute(codec);
+ else
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = dac_unmute(codec);
+ else
+ ret = adc_unmute(codec);
+
+ return ret;
+}
+
+static int tscs42xx_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int ret;
+
+ /* Slave mode not supported since it needs always-on frame clock */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ ret = snd_soc_update_bits(codec, R_AIC1, RM_AIC1_MS,
+ RV_AIC1_MS_MASTER);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to set codec DAI master (%d)\n", ret);
+ return ret;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ dev_err(codec->dev, "Unsupported format (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tscs42xx_set_dai_bclk_ratio(struct snd_soc_dai *codec_dai,
+ unsigned int ratio)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct tscs42xx *tscs42xx = snd_soc_codec_get_drvdata(codec);
+ unsigned int value;
+ int ret = 0;
+
+ switch (ratio) {
+ case 32:
+ value = RV_DACSR_DBCM_32;
+ break;
+ case 40:
+ value = RV_DACSR_DBCM_40;
+ break;
+ case 64:
+ value = RV_DACSR_DBCM_64;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported bclk ratio (%d)\n", ret);
+ return -EINVAL;
+ }
+
+ ret = snd_soc_update_bits(codec, R_DACSR, RM_DACSR_DBCM, value);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set DAC BCLK ratio (%d)\n", ret);
+ return ret;
+ }
+ ret = snd_soc_update_bits(codec, R_ADCSR, RM_ADCSR_ABCM, value);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set ADC BCLK ratio (%d)\n", ret);
+ return ret;
+ }
+
+ mutex_lock(&tscs42xx->audio_params_lock);
+
+ tscs42xx->bclk_ratio = ratio;
+
+ mutex_unlock(&tscs42xx->audio_params_lock);
+
+ return 0;
+}
+
+static int tscs42xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int ret;
+
+ switch (clk_id) {
+ case TSCS42XX_PLL_SRC_XTAL:
+ case TSCS42XX_PLL_SRC_MCLK1:
+ ret = snd_soc_write(codec, R_PLLREFSEL,
+ RV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1 |
+ RV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to set pll reference input (%d)\n",
+ ret);
+ return ret;
+ }
+ break;
+ case TSCS42XX_PLL_SRC_MCLK2:
+ ret = snd_soc_write(codec, R_PLLREFSEL,
+ RV_PLLREFSEL_PLL1_REF_SEL_MCLK2 |
+ RV_PLLREFSEL_PLL2_REF_SEL_MCLK2);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to set PLL reference (%d)\n", ret);
+ return ret;
+ }
+ break;
+ default:
+ dev_err(codec->dev, "pll src is unsupported\n");
+ return -EINVAL;
+ }
+
+ ret = set_pll_ctl_from_input_freq(codec, freq);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to setup PLL input freq (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops tscs42xx_dai_ops = {
+ .hw_params = tscs42xx_hw_params,
+ .mute_stream = tscs42xx_mute_stream,
+ .set_fmt = tscs42xx_set_dai_fmt,
+ .set_bclk_ratio = tscs42xx_set_dai_bclk_ratio,
+ .set_sysclk = tscs42xx_set_dai_sysclk,
+};
+
+static int part_is_valid(struct tscs42xx *tscs42xx)
+{
+ int val;
+ int ret;
+ unsigned int reg;
+
+ ret = regmap_read(tscs42xx->regmap, R_DEVIDH, ®);
+ if (ret < 0)
+ return ret;
+
+ val = reg << 8;
+ ret = regmap_read(tscs42xx->regmap, R_DEVIDL, ®);
+ if (ret < 0)
+ return ret;
+
+ val |= reg;
+
+ switch (val) {
+ case 0x4A74:
+ case 0x4A73:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_tscs42xx = {
+ .component_driver = {
+ .dapm_widgets = tscs42xx_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tscs42xx_dapm_widgets),
+ .dapm_routes = tscs42xx_intercon,
+ .num_dapm_routes = ARRAY_SIZE(tscs42xx_intercon),
+ .controls = tscs42xx_snd_controls,
+ .num_controls = ARRAY_SIZE(tscs42xx_snd_controls),
+ },
+};
+
+static inline void init_coeff_ram_cache(struct tscs42xx *tscs42xx)
+{
+ const u8 norm_addrs[] = { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1f,
+ 0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3f, 0x40, 0x45, 0x4a,
+ 0x4f, 0x54, 0x59, 0x5f, 0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79,
+ 0x7f, 0x80, 0x85, 0x8c, 0x91, 0x96, 0x97, 0x9c, 0xa3, 0xa8,
+ 0xad, 0xaf, 0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, };
+ u8 *coeff_ram = tscs42xx->coeff_ram;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(norm_addrs); i++)
+ coeff_ram[((norm_addrs[i] + 1) * COEFF_SIZE) - 1] = 0x40;
+}
+
+#define TSCS42XX_RATES SNDRV_PCM_RATE_8000_96000
+
+#define TSCS42XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+ | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver tscs42xx_dai = {
+ .name = "tscs42xx-HiFi",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = TSCS42XX_RATES,
+ .formats = TSCS42XX_FORMATS,},
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = TSCS42XX_RATES,
+ .formats = TSCS42XX_FORMATS,},
+ .ops = &tscs42xx_dai_ops,
+ .symmetric_rates = 1,
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+};
+
+static const struct reg_sequence tscs42xx_patch[] = {
+ { R_AIC2, RV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED },
+};
+
+static int tscs42xx_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct tscs42xx *tscs42xx;
+ int ret = 0;
+
+ tscs42xx = devm_kzalloc(&i2c->dev, sizeof(*tscs42xx), GFP_KERNEL);
+ if (!tscs42xx) {
+ ret = -ENOMEM;
+ dev_err(&i2c->dev,
+ "Failed to allocate memory for data (%d)\n", ret);
+ return ret;
+ }
+ i2c_set_clientdata(i2c, tscs42xx);
+ tscs42xx->dev = &i2c->dev;
+
+ tscs42xx->regmap = devm_regmap_init_i2c(i2c, &tscs42xx_regmap);
+ if (IS_ERR(tscs42xx->regmap)) {
+ ret = PTR_ERR(tscs42xx->regmap);
+ dev_err(tscs42xx->dev, "Failed to allocate regmap (%d)\n", ret);
+ return ret;
+ }
+
+ init_coeff_ram_cache(tscs42xx);
+
+ ret = part_is_valid(tscs42xx);
+ if (ret <= 0) {
+ dev_err(tscs42xx->dev, "No valid part (%d)\n", ret);
+ ret = -ENODEV;
+ return ret;
+ }
+
+ ret = regmap_write(tscs42xx->regmap, R_RESET, RV_RESET_ENABLE);
+ if (ret < 0) {
+ dev_err(tscs42xx->dev, "Failed to reset device (%d)\n", ret);
+ return ret;
+ }
+
+ ret = regmap_register_patch(tscs42xx->regmap, tscs42xx_patch,
+ ARRAY_SIZE(tscs42xx_patch));
+ if (ret < 0) {
+ dev_err(tscs42xx->dev, "Failed to apply patch (%d)\n", ret);
+ return ret;
+ }
+
+ mutex_init(&tscs42xx->audio_params_lock);
+ mutex_init(&tscs42xx->coeff_ram_lock);
+ mutex_init(&tscs42xx->pll_lock);
+
+ ret = snd_soc_register_codec(tscs42xx->dev, &soc_codec_dev_tscs42xx,
+ &tscs42xx_dai, 1);
+ if (ret) {
+ dev_err(tscs42xx->dev, "Failed to register codec (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tscs42xx_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+
+ return 0;
+}
+
+static const struct i2c_device_id tscs42xx_i2c_id[] = {
+ { "tscs42A1", 0 },
+ { "tscs42A2", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tscs42xx_i2c_id);
+
+static const struct of_device_id tscs42xx_of_match[] = {
+ { .compatible = "tempo,tscs42A1", },
+ { .compatible = "tempo,tscs42A2", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tscs42xx_of_match);
+
+static struct i2c_driver tscs42xx_i2c_driver = {
+ .driver = {
+ .name = "tscs42xx",
+ .owner = THIS_MODULE,
+ .of_match_table = tscs42xx_of_match,
+ },
+ .probe = tscs42xx_i2c_probe,
+ .remove = tscs42xx_i2c_remove,
+ .id_table = tscs42xx_i2c_id,
+};
+
+module_i2c_driver(tscs42xx_i2c_driver);
+
+MODULE_AUTHOR("Tempo Semiconductor <steven.eckhoff.opensource(a)gmail.com");
+MODULE_DESCRIPTION("ASoC TSCS42xx driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tscs42xx.h b/sound/soc/codecs/tscs42xx.h
new file mode 100644
index 000000000000..d4a30bcbf64b
--- /dev/null
+++ b/sound/soc/codecs/tscs42xx.h
@@ -0,0 +1,2693 @@
+// SPDX-License-Identifier: GPL-2.0
+// tscs42xx.h -- TSCS42xx ALSA SoC Audio driver
+// Copyright 2017 Tempo Semiconductor, Inc.
+// Author: Steven Eckhoff <steven.eckhoff.opensource(a)gmail.com>
+
+#ifndef __WOOKIE_H__
+#define __WOOKIE_H__
+
+enum {
+ TSCS42XX_PLL_SRC_NONE,
+ TSCS42XX_PLL_SRC_XTAL,
+ TSCS42XX_PLL_SRC_MCLK1,
+ TSCS42XX_PLL_SRC_MCLK2,
+};
+
+#define R_HPVOLL 0x0
+#define R_HPVOLR 0x1
+#define R_SPKVOLL 0x2
+#define R_SPKVOLR 0x3
+#define R_DACVOLL 0x4
+#define R_DACVOLR 0x5
+#define R_ADCVOLL 0x6
+#define R_ADCVOLR 0x7
+#define R_INVOLL 0x8
+#define R_INVOLR 0x9
+#define R_INMODE 0x0B
+#define R_INSELL 0x0C
+#define R_INSELR 0x0D
+#define R_AIC1 0x13
+#define R_AIC2 0x14
+#define R_CNVRTR0 0x16
+#define R_ADCSR 0x17
+#define R_CNVRTR1 0x18
+#define R_DACSR 0x19
+#define R_PWRM1 0x1A
+#define R_PWRM2 0x1B
+#define R_CONFIG0 0x1F
+#define R_CONFIG1 0x20
+#define R_DMICCTL 0x24
+#define R_CLECTL 0x25
+#define R_MUGAIN 0x26
+#define R_COMPTH 0x27
+#define R_CMPRAT 0x28
+#define R_CATKTCL 0x29
+#define R_CATKTCH 0x2A
+#define R_CRELTCL 0x2B
+#define R_CRELTCH 0x2C
+#define R_LIMTH 0x2D
+#define R_LIMTGT 0x2E
+#define R_LATKTCL 0x2F
+#define R_LATKTCH 0x30
+#define R_LRELTCL 0x31
+#define R_LRELTCH 0x32
+#define R_EXPTH 0x33
+#define R_EXPRAT 0x34
+#define R_XATKTCL 0x35
+#define R_XATKTCH 0x36
+#define R_XRELTCL 0x37
+#define R_XRELTCH 0x38
+#define R_FXCTL 0x39
+#define R_DACCRWRL 0x3A
+#define R_DACCRWRM 0x3B
+#define R_DACCRWRH 0x3C
+#define R_DACCRRDL 0x3D
+#define R_DACCRRDM 0x3E
+#define R_DACCRRDH 0x3F
+#define R_DACCRADDR 0x40
+#define R_DCOFSEL 0x41
+#define R_PLLCTL9 0x4E
+#define R_PLLCTLA 0x4F
+#define R_PLLCTLB 0x50
+#define R_PLLCTLC 0x51
+#define R_PLLCTLD 0x52
+#define R_PLLCTLE 0x53
+#define R_PLLCTLF 0x54
+#define R_PLLCTL10 0x55
+#define R_PLLCTL11 0x56
+#define R_PLLCTL12 0x57
+#define R_PLLCTL1B 0x60
+#define R_PLLCTL1C 0x61
+#define R_TIMEBASE 0x77
+#define R_DEVIDL 0x7D
+#define R_DEVIDH 0x7E
+#define R_RESET 0x80
+#define R_DACCRSTAT 0x8A
+#define R_PLLCTL0 0x8E
+#define R_PLLREFSEL 0x8F
+#define R_DACMBCEN 0xC7
+#define R_DACMBCCTL 0xC8
+#define R_DACMBCMUG1 0xC9
+#define R_DACMBCTHR1 0xCA
+#define R_DACMBCRAT1 0xCB
+#define R_DACMBCATK1L 0xCC
+#define R_DACMBCATK1H 0xCD
+#define R_DACMBCREL1L 0xCE
+#define R_DACMBCREL1H 0xCF
+#define R_DACMBCMUG2 0xD0
+#define R_DACMBCTHR2 0xD1
+#define R_DACMBCRAT2 0xD2
+#define R_DACMBCATK2L 0xD3
+#define R_DACMBCATK2H 0xD4
+#define R_DACMBCREL2L 0xD5
+#define R_DACMBCREL2H 0xD6
+#define R_DACMBCMUG3 0xD7
+#define R_DACMBCTHR3 0xD8
+#define R_DACMBCRAT3 0xD9
+#define R_DACMBCATK3L 0xDA
+#define R_DACMBCATK3H 0xDB
+#define R_DACMBCREL3L 0xDC
+#define R_DACMBCREL3H 0xDD
+
+/* Helpers */
+#define RM(m, b) ((m)<<(b))
+#define RV(v, b) ((v)<<(b))
+
+/****************************
+ * R_HPVOLL (0x0) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_HPVOLL 0
+
+/* Field Masks */
+#define FM_HPVOLL 0X7F
+
+/* Field Values */
+#define FV_HPVOLL_P6DB 0x7F
+#define FV_HPVOLL_N88PT5DB 0x1
+#define FV_HPVOLL_MUTE 0x0
+
+/* Register Masks */
+#define RM_HPVOLL RM(FM_HPVOLL, FB_HPVOLL)
+
+/* Register Values */
+#define RV_HPVOLL_P6DB RV(FV_HPVOLL_P6DB, FB_HPVOLL)
+#define RV_HPVOLL_N88PT5DB RV(FV_HPVOLL_N88PT5DB, FB_HPVOLL)
+#define RV_HPVOLL_MUTE RV(FV_HPVOLL_MUTE, FB_HPVOLL)
+
+/****************************
+ * R_HPVOLR (0x1) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_HPVOLR 0
+
+/* Field Masks */
+#define FM_HPVOLR 0X7F
+
+/* Field Values */
+#define FV_HPVOLR_P6DB 0x7F
+#define FV_HPVOLR_N88PT5DB 0x1
+#define FV_HPVOLR_MUTE 0x0
+
+/* Register Masks */
+#define RM_HPVOLR RM(FM_HPVOLR, FB_HPVOLR)
+
+/* Register Values */
+#define RV_HPVOLR_P6DB RV(FV_HPVOLR_P6DB, FB_HPVOLR)
+#define RV_HPVOLR_N88PT5DB RV(FV_HPVOLR_N88PT5DB, FB_HPVOLR)
+#define RV_HPVOLR_MUTE RV(FV_HPVOLR_MUTE, FB_HPVOLR)
+
+/*****************************
+ * R_SPKVOLL (0x2) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_SPKVOLL 0
+
+/* Field Masks */
+#define FM_SPKVOLL 0X7F
+
+/* Field Values */
+#define FV_SPKVOLL_P12DB 0x7F
+#define FV_SPKVOLL_N77PT25DB 0x8
+#define FV_SPKVOLL_MUTE 0x0
+
+/* Register Masks */
+#define RM_SPKVOLL RM(FM_SPKVOLL, FB_SPKVOLL)
+
+/* Register Values */
+#define RV_SPKVOLL_P12DB RV(FV_SPKVOLL_P12DB, FB_SPKVOLL)
+#define RV_SPKVOLL_N77PT25DB \
+ RV(FV_SPKVOLL_N77PT25DB, FB_SPKVOLL)
+
+#define RV_SPKVOLL_MUTE RV(FV_SPKVOLL_MUTE, FB_SPKVOLL)
+
+/*****************************
+ * R_SPKVOLR (0x3) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_SPKVOLR 0
+
+/* Field Masks */
+#define FM_SPKVOLR 0X7F
+
+/* Field Values */
+#define FV_SPKVOLR_P12DB 0x7F
+#define FV_SPKVOLR_N77PT25DB 0x8
+#define FV_SPKVOLR_MUTE 0x0
+
+/* Register Masks */
+#define RM_SPKVOLR RM(FM_SPKVOLR, FB_SPKVOLR)
+
+/* Register Values */
+#define RV_SPKVOLR_P12DB RV(FV_SPKVOLR_P12DB, FB_SPKVOLR)
+#define RV_SPKVOLR_N77PT25DB \
+ RV(FV_SPKVOLR_N77PT25DB, FB_SPKVOLR)
+
+#define RV_SPKVOLR_MUTE RV(FV_SPKVOLR_MUTE, FB_SPKVOLR)
+
+/*****************************
+ * R_DACVOLL (0x4) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_DACVOLL 0
+
+/* Field Masks */
+#define FM_DACVOLL 0XFF
+
+/* Field Values */
+#define FV_DACVOLL_0DB 0xFF
+#define FV_DACVOLL_N95PT625DB 0x1
+#define FV_DACVOLL_MUTE 0x0
+
+/* Register Masks */
+#define RM_DACVOLL RM(FM_DACVOLL, FB_DACVOLL)
+
+/* Register Values */
+#define RV_DACVOLL_0DB RV(FV_DACVOLL_0DB, FB_DACVOLL)
+#define RV_DACVOLL_N95PT625DB \
+ RV(FV_DACVOLL_N95PT625DB, FB_DACVOLL)
+
+#define RV_DACVOLL_MUTE RV(FV_DACVOLL_MUTE, FB_DACVOLL)
+
+/*****************************
+ * R_DACVOLR (0x5) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_DACVOLR 0
+
+/* Field Masks */
+#define FM_DACVOLR 0XFF
+
+/* Field Values */
+#define FV_DACVOLR_0DB 0xFF
+#define FV_DACVOLR_N95PT625DB 0x1
+#define FV_DACVOLR_MUTE 0x0
+
+/* Register Masks */
+#define RM_DACVOLR RM(FM_DACVOLR, FB_DACVOLR)
+
+/* Register Values */
+#define RV_DACVOLR_0DB RV(FV_DACVOLR_0DB, FB_DACVOLR)
+#define RV_DACVOLR_N95PT625DB \
+ RV(FV_DACVOLR_N95PT625DB, FB_DACVOLR)
+
+#define RV_DACVOLR_MUTE RV(FV_DACVOLR_MUTE, FB_DACVOLR)
+
+/*****************************
+ * R_ADCVOLL (0x6) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_ADCVOLL 0
+
+/* Field Masks */
+#define FM_ADCVOLL 0XFF
+
+/* Field Values */
+#define FV_ADCVOLL_P24DB 0xFF
+#define FV_ADCVOLL_N71PT25DB 0x1
+#define FV_ADCVOLL_MUTE 0x0
+
+/* Register Masks */
+#define RM_ADCVOLL RM(FM_ADCVOLL, FB_ADCVOLL)
+
+/* Register Values */
+#define RV_ADCVOLL_P24DB RV(FV_ADCVOLL_P24DB, FB_ADCVOLL)
+#define RV_ADCVOLL_N71PT25DB \
+ RV(FV_ADCVOLL_N71PT25DB, FB_ADCVOLL)
+
+#define RV_ADCVOLL_MUTE RV(FV_ADCVOLL_MUTE, FB_ADCVOLL)
+
+/*****************************
+ * R_ADCVOLR (0x7) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_ADCVOLR 0
+
+/* Field Masks */
+#define FM_ADCVOLR 0XFF
+
+/* Field Values */
+#define FV_ADCVOLR_P24DB 0xFF
+#define FV_ADCVOLR_N71PT25DB 0x1
+#define FV_ADCVOLR_MUTE 0x0
+
+/* Register Masks */
+#define RM_ADCVOLR RM(FM_ADCVOLR, FB_ADCVOLR)
+
+/* Register Values */
+#define RV_ADCVOLR_P24DB RV(FV_ADCVOLR_P24DB, FB_ADCVOLR)
+#define RV_ADCVOLR_N71PT25DB \
+ RV(FV_ADCVOLR_N71PT25DB, FB_ADCVOLR)
+
+#define RV_ADCVOLR_MUTE RV(FV_ADCVOLR_MUTE, FB_ADCVOLR)
+
+/****************************
+ * R_INVOLL (0x8) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_INVOLL_INMUTEL 7
+#define FB_INVOLL_IZCL 6
+#define FB_INVOLL 0
+
+/* Field Masks */
+#define FM_INVOLL_INMUTEL 0X1
+#define FM_INVOLL_IZCL 0X1
+#define FM_INVOLL 0X3F
+
+/* Field Values */
+#define FV_INVOLL_INMUTEL_ENABLE 0x1
+#define FV_INVOLL_INMUTEL_DISABLE 0x0
+#define FV_INVOLL_IZCL_ENABLE 0x1
+#define FV_INVOLL_IZCL_DISABLE 0x0
+#define FV_INVOLL_P30DB 0x3F
+#define FV_INVOLL_N17PT25DB 0x0
+
+/* Register Masks */
+#define RM_INVOLL_INMUTEL \
+ RM(FM_INVOLL_INMUTEL, FB_INVOLL_INMUTEL)
+
+#define RM_INVOLL_IZCL RM(FM_INVOLL_IZCL, FB_INVOLL_IZCL)
+#define RM_INVOLL RM(FM_INVOLL, FB_INVOLL)
+
+/* Register Values */
+#define RV_INVOLL_INMUTEL_ENABLE \
+ RV(FV_INVOLL_INMUTEL_ENABLE, FB_INVOLL_INMUTEL)
+
+#define RV_INVOLL_INMUTEL_DISABLE \
+ RV(FV_INVOLL_INMUTEL_DISABLE, FB_INVOLL_INMUTEL)
+
+#define RV_INVOLL_IZCL_ENABLE \
+ RV(FV_INVOLL_IZCL_ENABLE, FB_INVOLL_IZCL)
+
+#define RV_INVOLL_IZCL_DISABLE \
+ RV(FV_INVOLL_IZCL_DISABLE, FB_INVOLL_IZCL)
+
+#define RV_INVOLL_P30DB RV(FV_INVOLL_P30DB, FB_INVOLL)
+#define RV_INVOLL_N17PT25DB RV(FV_INVOLL_N17PT25DB, FB_INVOLL)
+
+/****************************
+ * R_INVOLR (0x9) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_INVOLR_INMUTER 7
+#define FB_INVOLR_IZCR 6
+#define FB_INVOLR 0
+
+/* Field Masks */
+#define FM_INVOLR_INMUTER 0X1
+#define FM_INVOLR_IZCR 0X1
+#define FM_INVOLR 0X3F
+
+/* Field Values */
+#define FV_INVOLR_INMUTER_ENABLE 0x1
+#define FV_INVOLR_INMUTER_DISABLE 0x0
+#define FV_INVOLR_IZCR_ENABLE 0x1
+#define FV_INVOLR_IZCR_DISABLE 0x0
+#define FV_INVOLR_P30DB 0x3F
+#define FV_INVOLR_N17PT25DB 0x0
+
+/* Register Masks */
+#define RM_INVOLR_INMUTER \
+ RM(FM_INVOLR_INMUTER, FB_INVOLR_INMUTER)
+
+#define RM_INVOLR_IZCR RM(FM_INVOLR_IZCR, FB_INVOLR_IZCR)
+#define RM_INVOLR RM(FM_INVOLR, FB_INVOLR)
+
+/* Register Values */
+#define RV_INVOLR_INMUTER_ENABLE \
+ RV(FV_INVOLR_INMUTER_ENABLE, FB_INVOLR_INMUTER)
+
+#define RV_INVOLR_INMUTER_DISABLE \
+ RV(FV_INVOLR_INMUTER_DISABLE, FB_INVOLR_INMUTER)
+
+#define RV_INVOLR_IZCR_ENABLE \
+ RV(FV_INVOLR_IZCR_ENABLE, FB_INVOLR_IZCR)
+
+#define RV_INVOLR_IZCR_DISABLE \
+ RV(FV_INVOLR_IZCR_DISABLE, FB_INVOLR_IZCR)
+
+#define RV_INVOLR_P30DB RV(FV_INVOLR_P30DB, FB_INVOLR)
+#define RV_INVOLR_N17PT25DB RV(FV_INVOLR_N17PT25DB, FB_INVOLR)
+
+/*****************************
+ * R_INMODE (0x0B) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_INMODE_DS 0
+
+/* Field Masks */
+#define FM_INMODE_DS 0X1
+
+/* Field Values */
+#define FV_INMODE_DS_LRIN1 0x0
+#define FV_INMODE_DS_LRIN2 0x1
+
+/* Register Masks */
+#define RM_INMODE_DS RM(FM_INMODE_DS, FB_INMODE_DS)
+
+/* Register Values */
+#define RV_INMODE_DS_LRIN1 \
+ RV(FV_INMODE_DS_LRIN1, FB_INMODE_DS)
+
+#define RV_INMODE_DS_LRIN2 \
+ RV(FV_INMODE_DS_LRIN2, FB_INMODE_DS)
+
+
+/*****************************
+ * R_INSELL (0x0C) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_INSELL 6
+#define FB_INSELL_MICBSTL 4
+
+/* Field Masks */
+#define FM_INSELL 0X3
+#define FM_INSELL_MICBSTL 0X3
+
+/* Field Values */
+#define FV_INSELL_IN1 0x0
+#define FV_INSELL_IN2 0x1
+#define FV_INSELL_IN3 0x2
+#define FV_INSELL_D2S 0x3
+#define FV_INSELL_MICBSTL_OFF 0x0
+#define FV_INSELL_MICBSTL_10DB 0x1
+#define FV_INSELL_MICBSTL_20DB 0x2
+#define FV_INSELL_MICBSTL_30DB 0x3
+
+/* Register Masks */
+#define RM_INSELL RM(FM_INSELL, FB_INSELL)
+#define RM_INSELL_MICBSTL \
+ RM(FM_INSELL_MICBSTL, FB_INSELL_MICBSTL)
+
+
+/* Register Values */
+#define RV_INSELL_IN1 RV(FV_INSELL_IN1, FB_INSELL)
+#define RV_INSELL_IN2 RV(FV_INSELL_IN2, FB_INSELL)
+#define RV_INSELL_IN3 RV(FV_INSELL_IN3, FB_INSELL)
+#define RV_INSELL_D2S RV(FV_INSELL_D2S, FB_INSELL)
+#define RV_INSELL_MICBSTL_OFF \
+ RV(FV_INSELL_MICBSTL_OFF, FB_INSELL_MICBSTL)
+
+#define RV_INSELL_MICBSTL_10DB \
+ RV(FV_INSELL_MICBSTL_10DB, FB_INSELL_MICBSTL)
+
+#define RV_INSELL_MICBSTL_20DB \
+ RV(FV_INSELL_MICBSTL_20DB, FB_INSELL_MICBSTL)
+
+#define RV_INSELL_MICBSTL_30DB \
+ RV(FV_INSELL_MICBSTL_30DB, FB_INSELL_MICBSTL)
+
+
+/*****************************
+ * R_INSELR (0x0D) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_INSELR 6
+#define FB_INSELR_MICBSTR 4
+
+/* Field Masks */
+#define FM_INSELR 0X3
+#define FM_INSELR_MICBSTR 0X3
+
+/* Field Values */
+#define FV_INSELR_IN1 0x0
+#define FV_INSELR_IN2 0x1
+#define FV_INSELR_IN3 0x2
+#define FV_INSELR_D2S 0x3
+#define FV_INSELR_MICBSTR_OFF 0x0
+#define FV_INSELR_MICBSTR_10DB 0x1
+#define FV_INSELR_MICBSTR_20DB 0x2
+#define FV_INSELR_MICBSTR_30DB 0x3
+
+/* Register Masks */
+#define RM_INSELR RM(FM_INSELR, FB_INSELR)
+#define RM_INSELR_MICBSTR \
+ RM(FM_INSELR_MICBSTR, FB_INSELR_MICBSTR)
+
+
+/* Register Values */
+#define RV_INSELR_IN1 RV(FV_INSELR_IN1, FB_INSELR)
+#define RV_INSELR_IN2 RV(FV_INSELR_IN2, FB_INSELR)
+#define RV_INSELR_IN3 RV(FV_INSELR_IN3, FB_INSELR)
+#define RV_INSELR_D2S RV(FV_INSELR_D2S, FB_INSELR)
+#define RV_INSELR_MICBSTR_OFF \
+ RV(FV_INSELR_MICBSTR_OFF, FB_INSELR_MICBSTR)
+
+#define RV_INSELR_MICBSTR_10DB \
+ RV(FV_INSELR_MICBSTR_10DB, FB_INSELR_MICBSTR)
+
+#define RV_INSELR_MICBSTR_20DB \
+ RV(FV_INSELR_MICBSTR_20DB, FB_INSELR_MICBSTR)
+
+#define RV_INSELR_MICBSTR_30DB \
+ RV(FV_INSELR_MICBSTR_30DB, FB_INSELR_MICBSTR)
+
+
+/***************************
+ * R_AIC1 (0x13) *
+ ***************************/
+
+/* Field Offsets */
+#define FB_AIC1_BCLKINV 6
+#define FB_AIC1_MS 5
+#define FB_AIC1_LRP 4
+#define FB_AIC1_WL 2
+#define FB_AIC1_FORMAT 0
+
+/* Field Masks */
+#define FM_AIC1_BCLKINV 0X1
+#define FM_AIC1_MS 0X1
+#define FM_AIC1_LRP 0X1
+#define FM_AIC1_WL 0X3
+#define FM_AIC1_FORMAT 0X3
+
+/* Field Values */
+#define FV_AIC1_BCLKINV_ENABLE 0x1
+#define FV_AIC1_BCLKINV_DISABLE 0x0
+#define FV_AIC1_MS_MASTER 0x1
+#define FV_AIC1_MS_SLAVE 0x0
+#define FV_AIC1_LRP_INVERT 0x1
+#define FV_AIC1_LRP_NORMAL 0x0
+#define FV_AIC1_WL_16 0x0
+#define FV_AIC1_WL_20 0x1
+#define FV_AIC1_WL_24 0x2
+#define FV_AIC1_WL_32 0x3
+#define FV_AIC1_FORMAT_RIGHT 0x0
+#define FV_AIC1_FORMAT_LEFT 0x1
+#define FV_AIC1_FORMAT_I2S 0x2
+
+/* Register Masks */
+#define RM_AIC1_BCLKINV \
+ RM(FM_AIC1_BCLKINV, FB_AIC1_BCLKINV)
+
+#define RM_AIC1_MS RM(FM_AIC1_MS, FB_AIC1_MS)
+#define RM_AIC1_LRP RM(FM_AIC1_LRP, FB_AIC1_LRP)
+#define RM_AIC1_WL RM(FM_AIC1_WL, FB_AIC1_WL)
+#define RM_AIC1_FORMAT RM(FM_AIC1_FORMAT, FB_AIC1_FORMAT)
+
+/* Register Values */
+#define RV_AIC1_BCLKINV_ENABLE \
+ RV(FV_AIC1_BCLKINV_ENABLE, FB_AIC1_BCLKINV)
+
+#define RV_AIC1_BCLKINV_DISABLE \
+ RV(FV_AIC1_BCLKINV_DISABLE, FB_AIC1_BCLKINV)
+
+#define RV_AIC1_MS_MASTER RV(FV_AIC1_MS_MASTER, FB_AIC1_MS)
+#define RV_AIC1_MS_SLAVE RV(FV_AIC1_MS_SLAVE, FB_AIC1_MS)
+#define RV_AIC1_LRP_INVERT \
+ RV(FV_AIC1_LRP_INVERT, FB_AIC1_LRP)
+
+#define RV_AIC1_LRP_NORMAL \
+ RV(FV_AIC1_LRP_NORMAL, FB_AIC1_LRP)
+
+#define RV_AIC1_WL_16 RV(FV_AIC1_WL_16, FB_AIC1_WL)
+#define RV_AIC1_WL_20 RV(FV_AIC1_WL_20, FB_AIC1_WL)
+#define RV_AIC1_WL_24 RV(FV_AIC1_WL_24, FB_AIC1_WL)
+#define RV_AIC1_WL_32 RV(FV_AIC1_WL_32, FB_AIC1_WL)
+#define RV_AIC1_FORMAT_RIGHT \
+ RV(FV_AIC1_FORMAT_RIGHT, FB_AIC1_FORMAT)
+
+#define RV_AIC1_FORMAT_LEFT \
+ RV(FV_AIC1_FORMAT_LEFT, FB_AIC1_FORMAT)
+
+#define RV_AIC1_FORMAT_I2S \
+ RV(FV_AIC1_FORMAT_I2S, FB_AIC1_FORMAT)
+
+
+/***************************
+ * R_AIC2 (0x14) *
+ ***************************/
+
+/* Field Offsets */
+#define FB_AIC2_DACDSEL 6
+#define FB_AIC2_ADCDSEL 4
+#define FB_AIC2_TRI 3
+#define FB_AIC2_BLRCM 0
+
+/* Field Masks */
+#define FM_AIC2_DACDSEL 0X3
+#define FM_AIC2_ADCDSEL 0X3
+#define FM_AIC2_TRI 0X1
+#define FM_AIC2_BLRCM 0X7
+
+/* Field Values */
+#define FV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED 0x3
+
+/* Register Masks */
+#define RM_AIC2_DACDSEL \
+ RM(FM_AIC2_DACDSEL, FB_AIC2_DACDSEL)
+
+#define RM_AIC2_ADCDSEL \
+ RM(FM_AIC2_ADCDSEL, FB_AIC2_ADCDSEL)
+
+#define RM_AIC2_TRI RM(FM_AIC2_TRI, FB_AIC2_TRI)
+#define RM_AIC2_BLRCM RM(FM_AIC2_BLRCM, FB_AIC2_BLRCM)
+
+/* Register Values */
+#define RV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED \
+ RV(FV_AIC2_BLRCM_DAC_BCLK_LRCLK_SHARED, FB_AIC2_BLRCM)
+
+
+/******************************
+ * R_CNVRTR0 (0x16) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CNVRTR0_ADCPOLR 7
+#define FB_CNVRTR0_ADCPOLL 6
+#define FB_CNVRTR0_AMONOMIX 4
+#define FB_CNVRTR0_ADCMU 3
+#define FB_CNVRTR0_HPOR 2
+#define FB_CNVRTR0_ADCHPDR 1
+#define FB_CNVRTR0_ADCHPDL 0
+
+/* Field Masks */
+#define FM_CNVRTR0_ADCPOLR 0X1
+#define FM_CNVRTR0_ADCPOLL 0X1
+#define FM_CNVRTR0_AMONOMIX 0X3
+#define FM_CNVRTR0_ADCMU 0X1
+#define FM_CNVRTR0_HPOR 0X1
+#define FM_CNVRTR0_ADCHPDR 0X1
+#define FM_CNVRTR0_ADCHPDL 0X1
+
+/* Field Values */
+#define FV_CNVRTR0_ADCPOLR_INVERT 0x1
+#define FV_CNVRTR0_ADCPOLR_NORMAL 0x0
+#define FV_CNVRTR0_ADCPOLL_INVERT 0x1
+#define FV_CNVRTR0_ADCPOLL_NORMAL 0x0
+#define FV_CNVRTR0_ADCMU_ENABLE 0x1
+#define FV_CNVRTR0_ADCMU_DISABLE 0x0
+#define FV_CNVRTR0_ADCHPDR_ENABLE 0x1
+#define FV_CNVRTR0_ADCHPDR_DISABLE 0x0
+#define FV_CNVRTR0_ADCHPDL_ENABLE 0x1
+#define FV_CNVRTR0_ADCHPDL_DISABLE 0x0
+
+/* Register Masks */
+#define RM_CNVRTR0_ADCPOLR \
+ RM(FM_CNVRTR0_ADCPOLR, FB_CNVRTR0_ADCPOLR)
+
+#define RM_CNVRTR0_ADCPOLL \
+ RM(FM_CNVRTR0_ADCPOLL, FB_CNVRTR0_ADCPOLL)
+
+#define RM_CNVRTR0_AMONOMIX \
+ RM(FM_CNVRTR0_AMONOMIX, FB_CNVRTR0_AMONOMIX)
+
+#define RM_CNVRTR0_ADCMU \
+ RM(FM_CNVRTR0_ADCMU, FB_CNVRTR0_ADCMU)
+
+#define RM_CNVRTR0_HPOR \
+ RM(FM_CNVRTR0_HPOR, FB_CNVRTR0_HPOR)
+
+#define RM_CNVRTR0_ADCHPDR \
+ RM(FM_CNVRTR0_ADCHPDR, FB_CNVRTR0_ADCHPDR)
+
+#define RM_CNVRTR0_ADCHPDL \
+ RM(FM_CNVRTR0_ADCHPDL, FB_CNVRTR0_ADCHPDL)
+
+
+/* Register Values */
+#define RV_CNVRTR0_ADCPOLR_INVERT \
+ RV(FV_CNVRTR0_ADCPOLR_INVERT, FB_CNVRTR0_ADCPOLR)
+
+#define RV_CNVRTR0_ADCPOLR_NORMAL \
+ RV(FV_CNVRTR0_ADCPOLR_NORMAL, FB_CNVRTR0_ADCPOLR)
+
+#define RV_CNVRTR0_ADCPOLL_INVERT \
+ RV(FV_CNVRTR0_ADCPOLL_INVERT, FB_CNVRTR0_ADCPOLL)
+
+#define RV_CNVRTR0_ADCPOLL_NORMAL \
+ RV(FV_CNVRTR0_ADCPOLL_NORMAL, FB_CNVRTR0_ADCPOLL)
+
+#define RV_CNVRTR0_ADCMU_ENABLE \
+ RV(FV_CNVRTR0_ADCMU_ENABLE, FB_CNVRTR0_ADCMU)
+
+#define RV_CNVRTR0_ADCMU_DISABLE \
+ RV(FV_CNVRTR0_ADCMU_DISABLE, FB_CNVRTR0_ADCMU)
+
+#define RV_CNVRTR0_ADCHPDR_ENABLE \
+ RV(FV_CNVRTR0_ADCHPDR_ENABLE, FB_CNVRTR0_ADCHPDR)
+
+#define RV_CNVRTR0_ADCHPDR_DISABLE \
+ RV(FV_CNVRTR0_ADCHPDR_DISABLE, FB_CNVRTR0_ADCHPDR)
+
+#define RV_CNVRTR0_ADCHPDL_ENABLE \
+ RV(FV_CNVRTR0_ADCHPDL_ENABLE, FB_CNVRTR0_ADCHPDL)
+
+#define RV_CNVRTR0_ADCHPDL_DISABLE \
+ RV(FV_CNVRTR0_ADCHPDL_DISABLE, FB_CNVRTR0_ADCHPDL)
+
+
+/****************************
+ * R_ADCSR (0x17) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_ADCSR_ABCM 6
+#define FB_ADCSR_ABR 3
+#define FB_ADCSR_ABM 0
+
+/* Field Masks */
+#define FM_ADCSR_ABCM 0X3
+#define FM_ADCSR_ABR 0X3
+#define FM_ADCSR_ABM 0X7
+
+/* Field Values */
+#define FV_ADCSR_ABCM_AUTO 0x0
+#define FV_ADCSR_ABCM_32 0x1
+#define FV_ADCSR_ABCM_40 0x2
+#define FV_ADCSR_ABCM_64 0x3
+#define FV_ADCSR_ABR_32 0x0
+#define FV_ADCSR_ABR_44_1 0x1
+#define FV_ADCSR_ABR_48 0x2
+#define FV_ADCSR_ABM_PT25 0x0
+#define FV_ADCSR_ABM_PT5 0x1
+#define FV_ADCSR_ABM_1 0x2
+#define FV_ADCSR_ABM_2 0x3
+
+/* Register Masks */
+#define RM_ADCSR_ABCM RM(FM_ADCSR_ABCM, FB_ADCSR_ABCM)
+#define RM_ADCSR_ABR RM(FM_ADCSR_ABR, FB_ADCSR_ABR)
+#define RM_ADCSR_ABM RM(FM_ADCSR_ABM, FB_ADCSR_ABM)
+
+/* Register Values */
+#define RV_ADCSR_ABCM_AUTO \
+ RV(FV_ADCSR_ABCM_AUTO, FB_ADCSR_ABCM)
+
+#define RV_ADCSR_ABCM_32 \
+ RV(FV_ADCSR_ABCM_32, FB_ADCSR_ABCM)
+
+#define RV_ADCSR_ABCM_40 \
+ RV(FV_ADCSR_ABCM_40, FB_ADCSR_ABCM)
+
+#define RV_ADCSR_ABCM_64 \
+ RV(FV_ADCSR_ABCM_64, FB_ADCSR_ABCM)
+
+#define RV_ADCSR_ABR_32 RV(FV_ADCSR_ABR_32, FB_ADCSR_ABR)
+#define RV_ADCSR_ABR_44_1 \
+ RV(FV_ADCSR_ABR_44_1, FB_ADCSR_ABR)
+
+#define RV_ADCSR_ABR_48 RV(FV_ADCSR_ABR_48, FB_ADCSR_ABR)
+#define RV_ADCSR_ABR_ RV(FV_ADCSR_ABR_, FB_ADCSR_ABR)
+#define RV_ADCSR_ABM_PT25 \
+ RV(FV_ADCSR_ABM_PT25, FB_ADCSR_ABM)
+
+#define RV_ADCSR_ABM_PT5 RV(FV_ADCSR_ABM_PT5, FB_ADCSR_ABM)
+#define RV_ADCSR_ABM_1 RV(FV_ADCSR_ABM_1, FB_ADCSR_ABM)
+#define RV_ADCSR_ABM_2 RV(FV_ADCSR_ABM_2, FB_ADCSR_ABM)
+
+/******************************
+ * R_CNVRTR1 (0x18) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CNVRTR1_DACPOLR 7
+#define FB_CNVRTR1_DACPOLL 6
+#define FB_CNVRTR1_DMONOMIX 4
+#define FB_CNVRTR1_DACMU 3
+#define FB_CNVRTR1_DEEMPH 2
+#define FB_CNVRTR1_DACDITH 0
+
+/* Field Masks */
+#define FM_CNVRTR1_DACPOLR 0X1
+#define FM_CNVRTR1_DACPOLL 0X1
+#define FM_CNVRTR1_DMONOMIX 0X3
+#define FM_CNVRTR1_DACMU 0X1
+#define FM_CNVRTR1_DEEMPH 0X1
+#define FM_CNVRTR1_DACDITH 0X3
+
+/* Field Values */
+#define FV_CNVRTR1_DACPOLR_INVERT 0x1
+#define FV_CNVRTR1_DACPOLR_NORMAL 0x0
+#define FV_CNVRTR1_DACPOLL_INVERT 0x1
+#define FV_CNVRTR1_DACPOLL_NORMAL 0x0
+#define FV_CNVRTR1_DMONOMIX_ENABLE 0x1
+#define FV_CNVRTR1_DMONOMIX_DISABLE 0x0
+#define FV_CNVRTR1_DACMU_ENABLE 0x1
+#define FV_CNVRTR1_DACMU_DISABLE 0x0
+
+/* Register Masks */
+#define RM_CNVRTR1_DACPOLR \
+ RM(FM_CNVRTR1_DACPOLR, FB_CNVRTR1_DACPOLR)
+
+#define RM_CNVRTR1_DACPOLL \
+ RM(FM_CNVRTR1_DACPOLL, FB_CNVRTR1_DACPOLL)
+
+#define RM_CNVRTR1_DMONOMIX \
+ RM(FM_CNVRTR1_DMONOMIX, FB_CNVRTR1_DMONOMIX)
+
+#define RM_CNVRTR1_DACMU \
+ RM(FM_CNVRTR1_DACMU, FB_CNVRTR1_DACMU)
+
+#define RM_CNVRTR1_DEEMPH \
+ RM(FM_CNVRTR1_DEEMPH, FB_CNVRTR1_DEEMPH)
+
+#define RM_CNVRTR1_DACDITH \
+ RM(FM_CNVRTR1_DACDITH, FB_CNVRTR1_DACDITH)
+
+
+/* Register Values */
+#define RV_CNVRTR1_DACPOLR_INVERT \
+ RV(FV_CNVRTR1_DACPOLR_INVERT, FB_CNVRTR1_DACPOLR)
+
+#define RV_CNVRTR1_DACPOLR_NORMAL \
+ RV(FV_CNVRTR1_DACPOLR_NORMAL, FB_CNVRTR1_DACPOLR)
+
+#define RV_CNVRTR1_DACPOLL_INVERT \
+ RV(FV_CNVRTR1_DACPOLL_INVERT, FB_CNVRTR1_DACPOLL)
+
+#define RV_CNVRTR1_DACPOLL_NORMAL \
+ RV(FV_CNVRTR1_DACPOLL_NORMAL, FB_CNVRTR1_DACPOLL)
+
+#define RV_CNVRTR1_DMONOMIX_ENABLE \
+ RV(FV_CNVRTR1_DMONOMIX_ENABLE, FB_CNVRTR1_DMONOMIX)
+
+#define RV_CNVRTR1_DMONOMIX_DISABLE \
+ RV(FV_CNVRTR1_DMONOMIX_DISABLE, FB_CNVRTR1_DMONOMIX)
+
+#define RV_CNVRTR1_DACMU_ENABLE \
+ RV(FV_CNVRTR1_DACMU_ENABLE, FB_CNVRTR1_DACMU)
+
+#define RV_CNVRTR1_DACMU_DISABLE \
+ RV(FV_CNVRTR1_DACMU_DISABLE, FB_CNVRTR1_DACMU)
+
+
+/****************************
+ * R_DACSR (0x19) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_DACSR_DBCM 6
+#define FB_DACSR_DBR 3
+#define FB_DACSR_DBM 0
+
+/* Field Masks */
+#define FM_DACSR_DBCM 0X3
+#define FM_DACSR_DBR 0X3
+#define FM_DACSR_DBM 0X7
+
+/* Field Values */
+#define FV_DACSR_DBCM_AUTO 0x0
+#define FV_DACSR_DBCM_32 0x1
+#define FV_DACSR_DBCM_40 0x2
+#define FV_DACSR_DBCM_64 0x3
+#define FV_DACSR_DBR_32 0x0
+#define FV_DACSR_DBR_44_1 0x1
+#define FV_DACSR_DBR_48 0x2
+#define FV_DACSR_DBM_PT25 0x0
+#define FV_DACSR_DBM_PT5 0x1
+#define FV_DACSR_DBM_1 0x2
+#define FV_DACSR_DBM_2 0x3
+
+/* Register Masks */
+#define RM_DACSR_DBCM RM(FM_DACSR_DBCM, FB_DACSR_DBCM)
+#define RM_DACSR_DBR RM(FM_DACSR_DBR, FB_DACSR_DBR)
+#define RM_DACSR_DBM RM(FM_DACSR_DBM, FB_DACSR_DBM)
+
+/* Register Values */
+#define RV_DACSR_DBCM_AUTO \
+ RV(FV_DACSR_DBCM_AUTO, FB_DACSR_DBCM)
+
+#define RV_DACSR_DBCM_32 \
+ RV(FV_DACSR_DBCM_32, FB_DACSR_DBCM)
+
+#define RV_DACSR_DBCM_40 \
+ RV(FV_DACSR_DBCM_40, FB_DACSR_DBCM)
+
+#define RV_DACSR_DBCM_64 \
+ RV(FV_DACSR_DBCM_64, FB_DACSR_DBCM)
+
+#define RV_DACSR_DBR_32 RV(FV_DACSR_DBR_32, FB_DACSR_DBR)
+#define RV_DACSR_DBR_44_1 \
+ RV(FV_DACSR_DBR_44_1, FB_DACSR_DBR)
+
+#define RV_DACSR_DBR_48 RV(FV_DACSR_DBR_48, FB_DACSR_DBR)
+#define RV_DACSR_DBM_PT25 \
+ RV(FV_DACSR_DBM_PT25, FB_DACSR_DBM)
+
+#define RV_DACSR_DBM_PT5 RV(FV_DACSR_DBM_PT5, FB_DACSR_DBM)
+#define RV_DACSR_DBM_1 RV(FV_DACSR_DBM_1, FB_DACSR_DBM)
+#define RV_DACSR_DBM_2 RV(FV_DACSR_DBM_2, FB_DACSR_DBM)
+
+/****************************
+ * R_PWRM1 (0x1A) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_PWRM1_BSTL 7
+#define FB_PWRM1_BSTR 6
+#define FB_PWRM1_PGAL 5
+#define FB_PWRM1_PGAR 4
+#define FB_PWRM1_ADCL 3
+#define FB_PWRM1_ADCR 2
+#define FB_PWRM1_MICB 1
+#define FB_PWRM1_DIGENB 0
+
+/* Field Masks */
+#define FM_PWRM1_BSTL 0X1
+#define FM_PWRM1_BSTR 0X1
+#define FM_PWRM1_PGAL 0X1
+#define FM_PWRM1_PGAR 0X1
+#define FM_PWRM1_ADCL 0X1
+#define FM_PWRM1_ADCR 0X1
+#define FM_PWRM1_MICB 0X1
+#define FM_PWRM1_DIGENB 0X1
+
+/* Field Values */
+#define FV_PWRM1_BSTL_ENABLE 0x1
+#define FV_PWRM1_BSTL_DISABLE 0x0
+#define FV_PWRM1_BSTR_ENABLE 0x1
+#define FV_PWRM1_BSTR_DISABLE 0x0
+#define FV_PWRM1_PGAL_ENABLE 0x1
+#define FV_PWRM1_PGAL_DISABLE 0x0
+#define FV_PWRM1_PGAR_ENABLE 0x1
+#define FV_PWRM1_PGAR_DISABLE 0x0
+#define FV_PWRM1_ADCL_ENABLE 0x1
+#define FV_PWRM1_ADCL_DISABLE 0x0
+#define FV_PWRM1_ADCR_ENABLE 0x1
+#define FV_PWRM1_ADCR_DISABLE 0x0
+#define FV_PWRM1_MICB_ENABLE 0x1
+#define FV_PWRM1_MICB_DISABLE 0x0
+#define FV_PWRM1_DIGENB_DISABLE 0x1
+#define FV_PWRM1_DIGENB_ENABLE 0x0
+
+/* Register Masks */
+#define RM_PWRM1_BSTL RM(FM_PWRM1_BSTL, FB_PWRM1_BSTL)
+#define RM_PWRM1_BSTR RM(FM_PWRM1_BSTR, FB_PWRM1_BSTR)
+#define RM_PWRM1_PGAL RM(FM_PWRM1_PGAL, FB_PWRM1_PGAL)
+#define RM_PWRM1_PGAR RM(FM_PWRM1_PGAR, FB_PWRM1_PGAR)
+#define RM_PWRM1_ADCL RM(FM_PWRM1_ADCL, FB_PWRM1_ADCL)
+#define RM_PWRM1_ADCR RM(FM_PWRM1_ADCR, FB_PWRM1_ADCR)
+#define RM_PWRM1_MICB RM(FM_PWRM1_MICB, FB_PWRM1_MICB)
+#define RM_PWRM1_DIGENB \
+ RM(FM_PWRM1_DIGENB, FB_PWRM1_DIGENB)
+
+
+/* Register Values */
+#define RV_PWRM1_BSTL_ENABLE \
+ RV(FV_PWRM1_BSTL_ENABLE, FB_PWRM1_BSTL)
+
+#define RV_PWRM1_BSTL_DISABLE \
+ RV(FV_PWRM1_BSTL_DISABLE, FB_PWRM1_BSTL)
+
+#define RV_PWRM1_BSTR_ENABLE \
+ RV(FV_PWRM1_BSTR_ENABLE, FB_PWRM1_BSTR)
+
+#define RV_PWRM1_BSTR_DISABLE \
+ RV(FV_PWRM1_BSTR_DISABLE, FB_PWRM1_BSTR)
+
+#define RV_PWRM1_PGAL_ENABLE \
+ RV(FV_PWRM1_PGAL_ENABLE, FB_PWRM1_PGAL)
+
+#define RV_PWRM1_PGAL_DISABLE \
+ RV(FV_PWRM1_PGAL_DISABLE, FB_PWRM1_PGAL)
+
+#define RV_PWRM1_PGAR_ENABLE \
+ RV(FV_PWRM1_PGAR_ENABLE, FB_PWRM1_PGAR)
+
+#define RV_PWRM1_PGAR_DISABLE \
+ RV(FV_PWRM1_PGAR_DISABLE, FB_PWRM1_PGAR)
+
+#define RV_PWRM1_ADCL_ENABLE \
+ RV(FV_PWRM1_ADCL_ENABLE, FB_PWRM1_ADCL)
+
+#define RV_PWRM1_ADCL_DISABLE \
+ RV(FV_PWRM1_ADCL_DISABLE, FB_PWRM1_ADCL)
+
+#define RV_PWRM1_ADCR_ENABLE \
+ RV(FV_PWRM1_ADCR_ENABLE, FB_PWRM1_ADCR)
+
+#define RV_PWRM1_ADCR_DISABLE \
+ RV(FV_PWRM1_ADCR_DISABLE, FB_PWRM1_ADCR)
+
+#define RV_PWRM1_MICB_ENABLE \
+ RV(FV_PWRM1_MICB_ENABLE, FB_PWRM1_MICB)
+
+#define RV_PWRM1_MICB_DISABLE \
+ RV(FV_PWRM1_MICB_DISABLE, FB_PWRM1_MICB)
+
+#define RV_PWRM1_DIGENB_DISABLE \
+ RV(FV_PWRM1_DIGENB_DISABLE, FB_PWRM1_DIGENB)
+
+#define RV_PWRM1_DIGENB_ENABLE \
+ RV(FV_PWRM1_DIGENB_ENABLE, FB_PWRM1_DIGENB)
+
+
+/****************************
+ * R_PWRM2 (0x1B) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_PWRM2_D2S 7
+#define FB_PWRM2_HPL 6
+#define FB_PWRM2_HPR 5
+#define FB_PWRM2_SPKL 4
+#define FB_PWRM2_SPKR 3
+#define FB_PWRM2_INSELL 2
+#define FB_PWRM2_INSELR 1
+#define FB_PWRM2_VREF 0
+
+/* Field Masks */
+#define FM_PWRM2_D2S 0X1
+#define FM_PWRM2_HPL 0X1
+#define FM_PWRM2_HPR 0X1
+#define FM_PWRM2_SPKL 0X1
+#define FM_PWRM2_SPKR 0X1
+#define FM_PWRM2_INSELL 0X1
+#define FM_PWRM2_INSELR 0X1
+#define FM_PWRM2_VREF 0X1
+
+/* Field Values */
+#define FV_PWRM2_D2S_ENABLE 0x1
+#define FV_PWRM2_D2S_DISABLE 0x0
+#define FV_PWRM2_HPL_ENABLE 0x1
+#define FV_PWRM2_HPL_DISABLE 0x0
+#define FV_PWRM2_HPR_ENABLE 0x1
+#define FV_PWRM2_HPR_DISABLE 0x0
+#define FV_PWRM2_SPKL_ENABLE 0x1
+#define FV_PWRM2_SPKL_DISABLE 0x0
+#define FV_PWRM2_SPKR_ENABLE 0x1
+#define FV_PWRM2_SPKR_DISABLE 0x0
+#define FV_PWRM2_INSELL_ENABLE 0x1
+#define FV_PWRM2_INSELL_DISABLE 0x0
+#define FV_PWRM2_INSELR_ENABLE 0x1
+#define FV_PWRM2_INSELR_DISABLE 0x0
+#define FV_PWRM2_VREF_ENABLE 0x1
+#define FV_PWRM2_VREF_DISABLE 0x0
+
+/* Register Masks */
+#define RM_PWRM2_D2S RM(FM_PWRM2_D2S, FB_PWRM2_D2S)
+#define RM_PWRM2_HPL RM(FM_PWRM2_HPL, FB_PWRM2_HPL)
+#define RM_PWRM2_HPR RM(FM_PWRM2_HPR, FB_PWRM2_HPR)
+#define RM_PWRM2_SPKL RM(FM_PWRM2_SPKL, FB_PWRM2_SPKL)
+#define RM_PWRM2_SPKR RM(FM_PWRM2_SPKR, FB_PWRM2_SPKR)
+#define RM_PWRM2_INSELL \
+ RM(FM_PWRM2_INSELL, FB_PWRM2_INSELL)
+
+#define RM_PWRM2_INSELR \
+ RM(FM_PWRM2_INSELR, FB_PWRM2_INSELR)
+
+#define RM_PWRM2_VREF RM(FM_PWRM2_VREF, FB_PWRM2_VREF)
+
+/* Register Values */
+#define RV_PWRM2_D2S_ENABLE \
+ RV(FV_PWRM2_D2S_ENABLE, FB_PWRM2_D2S)
+
+#define RV_PWRM2_D2S_DISABLE \
+ RV(FV_PWRM2_D2S_DISABLE, FB_PWRM2_D2S)
+
+#define RV_PWRM2_HPL_ENABLE \
+ RV(FV_PWRM2_HPL_ENABLE, FB_PWRM2_HPL)
+
+#define RV_PWRM2_HPL_DISABLE \
+ RV(FV_PWRM2_HPL_DISABLE, FB_PWRM2_HPL)
+
+#define RV_PWRM2_HPR_ENABLE \
+ RV(FV_PWRM2_HPR_ENABLE, FB_PWRM2_HPR)
+
+#define RV_PWRM2_HPR_DISABLE \
+ RV(FV_PWRM2_HPR_DISABLE, FB_PWRM2_HPR)
+
+#define RV_PWRM2_SPKL_ENABLE \
+ RV(FV_PWRM2_SPKL_ENABLE, FB_PWRM2_SPKL)
+
+#define RV_PWRM2_SPKL_DISABLE \
+ RV(FV_PWRM2_SPKL_DISABLE, FB_PWRM2_SPKL)
+
+#define RV_PWRM2_SPKR_ENABLE \
+ RV(FV_PWRM2_SPKR_ENABLE, FB_PWRM2_SPKR)
+
+#define RV_PWRM2_SPKR_DISABLE \
+ RV(FV_PWRM2_SPKR_DISABLE, FB_PWRM2_SPKR)
+
+#define RV_PWRM2_INSELL_ENABLE \
+ RV(FV_PWRM2_INSELL_ENABLE, FB_PWRM2_INSELL)
+
+#define RV_PWRM2_INSELL_DISABLE \
+ RV(FV_PWRM2_INSELL_DISABLE, FB_PWRM2_INSELL)
+
+#define RV_PWRM2_INSELR_ENABLE \
+ RV(FV_PWRM2_INSELR_ENABLE, FB_PWRM2_INSELR)
+
+#define RV_PWRM2_INSELR_DISABLE \
+ RV(FV_PWRM2_INSELR_DISABLE, FB_PWRM2_INSELR)
+
+#define RV_PWRM2_VREF_ENABLE \
+ RV(FV_PWRM2_VREF_ENABLE, FB_PWRM2_VREF)
+
+#define RV_PWRM2_VREF_DISABLE \
+ RV(FV_PWRM2_VREF_DISABLE, FB_PWRM2_VREF)
+
+
+/******************************
+ * R_CONFIG0 (0x1F) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CONFIG0_ASDM 6
+#define FB_CONFIG0_DSDM 4
+#define FB_CONFIG0_DC_BYPASS 1
+#define FB_CONFIG0_SD_FORCE_ON 0
+
+/* Field Masks */
+#define FM_CONFIG0_ASDM 0X3
+#define FM_CONFIG0_DSDM 0X3
+#define FM_CONFIG0_DC_BYPASS 0X1
+#define FM_CONFIG0_SD_FORCE_ON 0X1
+
+/* Field Values */
+#define FV_CONFIG0_ASDM_HALF 0x1
+#define FV_CONFIG0_ASDM_FULL 0x2
+#define FV_CONFIG0_ASDM_AUTO 0x3
+#define FV_CONFIG0_DSDM_HALF 0x1
+#define FV_CONFIG0_DSDM_FULL 0x2
+#define FV_CONFIG0_DSDM_AUTO 0x3
+#define FV_CONFIG0_DC_BYPASS_ENABLE 0x1
+#define FV_CONFIG0_DC_BYPASS_DISABLE 0x0
+#define FV_CONFIG0_SD_FORCE_ON_ENABLE 0x1
+#define FV_CONFIG0_SD_FORCE_ON_DISABLE 0x0
+
+/* Register Masks */
+#define RM_CONFIG0_ASDM \
+ RM(FM_CONFIG0_ASDM, FB_CONFIG0_ASDM)
+
+#define RM_CONFIG0_DSDM \
+ RM(FM_CONFIG0_DSDM, FB_CONFIG0_DSDM)
+
+#define RM_CONFIG0_DC_BYPASS \
+ RM(FM_CONFIG0_DC_BYPASS, FB_CONFIG0_DC_BYPASS)
+
+#define RM_CONFIG0_SD_FORCE_ON \
+ RM(FM_CONFIG0_SD_FORCE_ON, FB_CONFIG0_SD_FORCE_ON)
+
+
+/* Register Values */
+#define RV_CONFIG0_ASDM_HALF \
+ RV(FV_CONFIG0_ASDM_HALF, FB_CONFIG0_ASDM)
+
+#define RV_CONFIG0_ASDM_FULL \
+ RV(FV_CONFIG0_ASDM_FULL, FB_CONFIG0_ASDM)
+
+#define RV_CONFIG0_ASDM_AUTO \
+ RV(FV_CONFIG0_ASDM_AUTO, FB_CONFIG0_ASDM)
+
+#define RV_CONFIG0_DSDM_HALF \
+ RV(FV_CONFIG0_DSDM_HALF, FB_CONFIG0_DSDM)
+
+#define RV_CONFIG0_DSDM_FULL \
+ RV(FV_CONFIG0_DSDM_FULL, FB_CONFIG0_DSDM)
+
+#define RV_CONFIG0_DSDM_AUTO \
+ RV(FV_CONFIG0_DSDM_AUTO, FB_CONFIG0_DSDM)
+
+#define RV_CONFIG0_DC_BYPASS_ENABLE \
+ RV(FV_CONFIG0_DC_BYPASS_ENABLE, FB_CONFIG0_DC_BYPASS)
+
+#define RV_CONFIG0_DC_BYPASS_DISABLE \
+ RV(FV_CONFIG0_DC_BYPASS_DISABLE, FB_CONFIG0_DC_BYPASS)
+
+#define RV_CONFIG0_SD_FORCE_ON_ENABLE \
+ RV(FV_CONFIG0_SD_FORCE_ON_ENABLE, FB_CONFIG0_SD_FORCE_ON)
+
+#define RV_CONFIG0_SD_FORCE_ON_DISABLE \
+ RV(FV_CONFIG0_SD_FORCE_ON_DISABLE, FB_CONFIG0_SD_FORCE_ON)
+
+
+/******************************
+ * R_CONFIG1 (0x20) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CONFIG1_EQ2_EN 7
+#define FB_CONFIG1_EQ2_BE 4
+#define FB_CONFIG1_EQ1_EN 3
+#define FB_CONFIG1_EQ1_BE 0
+
+/* Field Masks */
+#define FM_CONFIG1_EQ2_EN 0X1
+#define FM_CONFIG1_EQ2_BE 0X7
+#define FM_CONFIG1_EQ1_EN 0X1
+#define FM_CONFIG1_EQ1_BE 0X7
+
+/* Field Values */
+#define FV_CONFIG1_EQ2_EN_ENABLE 0x1
+#define FV_CONFIG1_EQ2_EN_DISABLE 0x0
+#define FV_CONFIG1_EQ2_BE_PRE 0x0
+#define FV_CONFIG1_EQ2_BE_PRE_EQ_0 0x1
+#define FV_CONFIG1_EQ2_BE_PRE_EQ0_1 0x2
+#define FV_CONFIG1_EQ2_BE_PRE_EQ0_2 0x3
+#define FV_CONFIG1_EQ2_BE_PRE_EQ0_3 0x4
+#define FV_CONFIG1_EQ2_BE_PRE_EQ0_4 0x5
+#define FV_CONFIG1_EQ2_BE_PRE_EQ0_5 0x6
+#define FV_CONFIG1_EQ1_EN_ENABLE 0x1
+#define FV_CONFIG1_EQ1_EN_DISABLE 0x0
+#define FV_CONFIG1_EQ1_BE_PRE 0x0
+#define FV_CONFIG1_EQ1_BE_PRE_EQ_0 0x1
+#define FV_CONFIG1_EQ1_BE_PRE_EQ0_1 0x2
+#define FV_CONFIG1_EQ1_BE_PRE_EQ0_2 0x3
+#define FV_CONFIG1_EQ1_BE_PRE_EQ0_3 0x4
+#define FV_CONFIG1_EQ1_BE_PRE_EQ0_4 0x5
+#define FV_CONFIG1_EQ1_BE_PRE_EQ0_5 0x6
+
+/* Register Masks */
+#define RM_CONFIG1_EQ2_EN \
+ RM(FM_CONFIG1_EQ2_EN, FB_CONFIG1_EQ2_EN)
+
+#define RM_CONFIG1_EQ2_BE \
+ RM(FM_CONFIG1_EQ2_BE, FB_CONFIG1_EQ2_BE)
+
+#define RM_CONFIG1_EQ1_EN \
+ RM(FM_CONFIG1_EQ1_EN, FB_CONFIG1_EQ1_EN)
+
+#define RM_CONFIG1_EQ1_BE \
+ RM(FM_CONFIG1_EQ1_BE, FB_CONFIG1_EQ1_BE)
+
+
+/* Register Values */
+#define RV_CONFIG1_EQ2_EN_ENABLE \
+ RV(FV_CONFIG1_EQ2_EN_ENABLE, FB_CONFIG1_EQ2_EN)
+
+#define RV_CONFIG1_EQ2_EN_DISABLE \
+ RV(FV_CONFIG1_EQ2_EN_DISABLE, FB_CONFIG1_EQ2_EN)
+
+#define RV_CONFIG1_EQ2_BE_PRE \
+ RV(FV_CONFIG1_EQ2_BE_PRE, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ2_BE_PRE_EQ_0 \
+ RV(FV_CONFIG1_EQ2_BE_PRE_EQ_0, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ2_BE_PRE_EQ0_1 \
+ RV(FV_CONFIG1_EQ2_BE_PRE_EQ0_1, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ2_BE_PRE_EQ0_2 \
+ RV(FV_CONFIG1_EQ2_BE_PRE_EQ0_2, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ2_BE_PRE_EQ0_3 \
+ RV(FV_CONFIG1_EQ2_BE_PRE_EQ0_3, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ2_BE_PRE_EQ0_4 \
+ RV(FV_CONFIG1_EQ2_BE_PRE_EQ0_4, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ2_BE_PRE_EQ0_5 \
+ RV(FV_CONFIG1_EQ2_BE_PRE_EQ0_5, FB_CONFIG1_EQ2_BE)
+
+#define RV_CONFIG1_EQ1_EN_ENABLE \
+ RV(FV_CONFIG1_EQ1_EN_ENABLE, FB_CONFIG1_EQ1_EN)
+
+#define RV_CONFIG1_EQ1_EN_DISABLE \
+ RV(FV_CONFIG1_EQ1_EN_DISABLE, FB_CONFIG1_EQ1_EN)
+
+#define RV_CONFIG1_EQ1_BE_PRE \
+ RV(FV_CONFIG1_EQ1_BE_PRE, FB_CONFIG1_EQ1_BE)
+
+#define RV_CONFIG1_EQ1_BE_PRE_EQ_0 \
+ RV(FV_CONFIG1_EQ1_BE_PRE_EQ_0, FB_CONFIG1_EQ1_BE)
+
+#define RV_CONFIG1_EQ1_BE_PRE_EQ0_1 \
+ RV(FV_CONFIG1_EQ1_BE_PRE_EQ0_1, FB_CONFIG1_EQ1_BE)
+
+#define RV_CONFIG1_EQ1_BE_PRE_EQ0_2 \
+ RV(FV_CONFIG1_EQ1_BE_PRE_EQ0_2, FB_CONFIG1_EQ1_BE)
+
+#define RV_CONFIG1_EQ1_BE_PRE_EQ0_3 \
+ RV(FV_CONFIG1_EQ1_BE_PRE_EQ0_3, FB_CONFIG1_EQ1_BE)
+
+#define RV_CONFIG1_EQ1_BE_PRE_EQ0_4 \
+ RV(FV_CONFIG1_EQ1_BE_PRE_EQ0_4, FB_CONFIG1_EQ1_BE)
+
+#define RV_CONFIG1_EQ1_BE_PRE_EQ0_5 \
+ RV(FV_CONFIG1_EQ1_BE_PRE_EQ0_5, FB_CONFIG1_EQ1_BE)
+
+
+/******************************
+ * R_DMICCTL (0x24) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_DMICCTL_DMICEN 7
+#define FB_DMICCTL_DMONO 4
+#define FB_DMICCTL_DMPHADJ 2
+#define FB_DMICCTL_DMRATE 0
+
+/* Field Masks */
+#define FM_DMICCTL_DMICEN 0X1
+#define FM_DMICCTL_DMONO 0X1
+#define FM_DMICCTL_DMPHADJ 0X3
+#define FM_DMICCTL_DMRATE 0X3
+
+/* Field Values */
+#define FV_DMICCTL_DMICEN_ENABLE 0x1
+#define FV_DMICCTL_DMICEN_DISABLE 0x0
+#define FV_DMICCTL_DMONO_STEREO 0x0
+#define FV_DMICCTL_DMONO_MONO 0x1
+
+/* Register Masks */
+#define RM_DMICCTL_DMICEN \
+ RM(FM_DMICCTL_DMICEN, FB_DMICCTL_DMICEN)
+
+#define RM_DMICCTL_DMONO \
+ RM(FM_DMICCTL_DMONO, FB_DMICCTL_DMONO)
+
+#define RM_DMICCTL_DMPHADJ \
+ RM(FM_DMICCTL_DMPHADJ, FB_DMICCTL_DMPHADJ)
+
+#define RM_DMICCTL_DMRATE \
+ RM(FM_DMICCTL_DMRATE, FB_DMICCTL_DMRATE)
+
+
+/* Register Values */
+#define RV_DMICCTL_DMICEN_ENABLE \
+ RV(FV_DMICCTL_DMICEN_ENABLE, FB_DMICCTL_DMICEN)
+
+#define RV_DMICCTL_DMICEN_DISABLE \
+ RV(FV_DMICCTL_DMICEN_DISABLE, FB_DMICCTL_DMICEN)
+
+#define RV_DMICCTL_DMONO_STEREO \
+ RV(FV_DMICCTL_DMONO_STEREO, FB_DMICCTL_DMONO)
+
+#define RV_DMICCTL_DMONO_MONO \
+ RV(FV_DMICCTL_DMONO_MONO, FB_DMICCTL_DMONO)
+
+
+/*****************************
+ * R_CLECTL (0x25) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_CLECTL_LVL_MODE 4
+#define FB_CLECTL_WINDOWSEL 3
+#define FB_CLECTL_EXP_EN 2
+#define FB_CLECTL_LIMIT_EN 1
+#define FB_CLECTL_COMP_EN 0
+
+/* Field Masks */
+#define FM_CLECTL_LVL_MODE 0X1
+#define FM_CLECTL_WINDOWSEL 0X1
+#define FM_CLECTL_EXP_EN 0X1
+#define FM_CLECTL_LIMIT_EN 0X1
+#define FM_CLECTL_COMP_EN 0X1
+
+/* Field Values */
+#define FV_CLECTL_LVL_MODE_AVG 0x0
+#define FV_CLECTL_LVL_MODE_PEAK 0x1
+#define FV_CLECTL_WINDOWSEL_512 0x0
+#define FV_CLECTL_WINDOWSEL_64 0x1
+#define FV_CLECTL_EXP_EN_ENABLE 0x1
+#define FV_CLECTL_EXP_EN_DISABLE 0x0
+#define FV_CLECTL_LIMIT_EN_ENABLE 0x1
+#define FV_CLECTL_LIMIT_EN_DISABLE 0x0
+#define FV_CLECTL_COMP_EN_ENABLE 0x1
+#define FV_CLECTL_COMP_EN_DISABLE 0x0
+
+/* Register Masks */
+#define RM_CLECTL_LVL_MODE \
+ RM(FM_CLECTL_LVL_MODE, FB_CLECTL_LVL_MODE)
+
+#define RM_CLECTL_WINDOWSEL \
+ RM(FM_CLECTL_WINDOWSEL, FB_CLECTL_WINDOWSEL)
+
+#define RM_CLECTL_EXP_EN \
+ RM(FM_CLECTL_EXP_EN, FB_CLECTL_EXP_EN)
+
+#define RM_CLECTL_LIMIT_EN \
+ RM(FM_CLECTL_LIMIT_EN, FB_CLECTL_LIMIT_EN)
+
+#define RM_CLECTL_COMP_EN \
+ RM(FM_CLECTL_COMP_EN, FB_CLECTL_COMP_EN)
+
+
+/* Register Values */
+#define RV_CLECTL_LVL_MODE_AVG \
+ RV(FV_CLECTL_LVL_MODE_AVG, FB_CLECTL_LVL_MODE)
+
+#define RV_CLECTL_LVL_MODE_PEAK \
+ RV(FV_CLECTL_LVL_MODE_PEAK, FB_CLECTL_LVL_MODE)
+
+#define RV_CLECTL_WINDOWSEL_512 \
+ RV(FV_CLECTL_WINDOWSEL_512, FB_CLECTL_WINDOWSEL)
+
+#define RV_CLECTL_WINDOWSEL_64 \
+ RV(FV_CLECTL_WINDOWSEL_64, FB_CLECTL_WINDOWSEL)
+
+#define RV_CLECTL_EXP_EN_ENABLE \
+ RV(FV_CLECTL_EXP_EN_ENABLE, FB_CLECTL_EXP_EN)
+
+#define RV_CLECTL_EXP_EN_DISABLE \
+ RV(FV_CLECTL_EXP_EN_DISABLE, FB_CLECTL_EXP_EN)
+
+#define RV_CLECTL_LIMIT_EN_ENABLE \
+ RV(FV_CLECTL_LIMIT_EN_ENABLE, FB_CLECTL_LIMIT_EN)
+
+#define RV_CLECTL_LIMIT_EN_DISABLE \
+ RV(FV_CLECTL_LIMIT_EN_DISABLE, FB_CLECTL_LIMIT_EN)
+
+#define RV_CLECTL_COMP_EN_ENABLE \
+ RV(FV_CLECTL_COMP_EN_ENABLE, FB_CLECTL_COMP_EN)
+
+#define RV_CLECTL_COMP_EN_DISABLE \
+ RV(FV_CLECTL_COMP_EN_DISABLE, FB_CLECTL_COMP_EN)
+
+
+/*****************************
+ * R_MUGAIN (0x26) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_MUGAIN_CLEMUG 0
+
+/* Field Masks */
+#define FM_MUGAIN_CLEMUG 0X1F
+
+/* Field Values */
+#define FV_MUGAIN_CLEMUG_46PT5DB 0x1F
+#define FV_MUGAIN_CLEMUG_0DB 0x0
+
+/* Register Masks */
+#define RM_MUGAIN_CLEMUG \
+ RM(FM_MUGAIN_CLEMUG, FB_MUGAIN_CLEMUG)
+
+
+/* Register Values */
+#define RV_MUGAIN_CLEMUG_46PT5DB \
+ RV(FV_MUGAIN_CLEMUG_46PT5DB, FB_MUGAIN_CLEMUG)
+
+#define RV_MUGAIN_CLEMUG_0DB \
+ RV(FV_MUGAIN_CLEMUG_0DB, FB_MUGAIN_CLEMUG)
+
+
+/*****************************
+ * R_COMPTH (0x27) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_COMPTH 0
+
+/* Field Masks */
+#define FM_COMPTH 0XFF
+
+/* Field Values */
+#define FV_COMPTH_0DB 0xFF
+#define FV_COMPTH_N95PT625DB 0x0
+
+/* Register Masks */
+#define RM_COMPTH RM(FM_COMPTH, FB_COMPTH)
+
+/* Register Values */
+#define RV_COMPTH_0DB RV(FV_COMPTH_0DB, FB_COMPTH)
+#define RV_COMPTH_N95PT625DB \
+ RV(FV_COMPTH_N95PT625DB, FB_COMPTH)
+
+
+/*****************************
+ * R_CMPRAT (0x28) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_CMPRAT 0
+
+/* Field Masks */
+#define FM_CMPRAT 0X1F
+
+/* Register Masks */
+#define RM_CMPRAT RM(FM_CMPRAT, FB_CMPRAT)
+
+/******************************
+ * R_CATKTCL (0x29) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CATKTCL 0
+
+/* Field Masks */
+#define FM_CATKTCL 0XFF
+
+/* Register Masks */
+#define RM_CATKTCL RM(FM_CATKTCL, FB_CATKTCL)
+
+/******************************
+ * R_CATKTCH (0x2A) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CATKTCH 0
+
+/* Field Masks */
+#define FM_CATKTCH 0XFF
+
+/* Register Masks */
+#define RM_CATKTCH RM(FM_CATKTCH, FB_CATKTCH)
+
+/******************************
+ * R_CRELTCL (0x2B) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CRELTCL 0
+
+/* Field Masks */
+#define FM_CRELTCL 0XFF
+
+/* Register Masks */
+#define RM_CRELTCL RM(FM_CRELTCL, FB_CRELTCL)
+
+/******************************
+ * R_CRELTCH (0x2C) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_CRELTCH 0
+
+/* Field Masks */
+#define FM_CRELTCH 0XFF
+
+/* Register Masks */
+#define RM_CRELTCH RM(FM_CRELTCH, FB_CRELTCH)
+
+/****************************
+ * R_LIMTH (0x2D) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_LIMTH 0
+
+/* Field Masks */
+#define FM_LIMTH 0XFF
+
+/* Field Values */
+#define FV_LIMTH_0DB 0xFF
+#define FV_LIMTH_N95PT625DB 0x0
+
+/* Register Masks */
+#define RM_LIMTH RM(FM_LIMTH, FB_LIMTH)
+
+/* Register Values */
+#define RV_LIMTH_0DB RV(FV_LIMTH_0DB, FB_LIMTH)
+#define RV_LIMTH_N95PT625DB RV(FV_LIMTH_N95PT625DB, FB_LIMTH)
+
+/*****************************
+ * R_LIMTGT (0x2E) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_LIMTGT 0
+
+/* Field Masks */
+#define FM_LIMTGT 0XFF
+
+/* Field Values */
+#define FV_LIMTGT_0DB 0xFF
+#define FV_LIMTGT_N95PT625DB 0x0
+
+/* Register Masks */
+#define RM_LIMTGT RM(FM_LIMTGT, FB_LIMTGT)
+
+/* Register Values */
+#define RV_LIMTGT_0DB RV(FV_LIMTGT_0DB, FB_LIMTGT)
+#define RV_LIMTGT_N95PT625DB \
+ RV(FV_LIMTGT_N95PT625DB, FB_LIMTGT)
+
+
+/******************************
+ * R_LATKTCL (0x2F) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_LATKTCL 0
+
+/* Field Masks */
+#define FM_LATKTCL 0XFF
+
+/* Register Masks */
+#define RM_LATKTCL RM(FM_LATKTCL, FB_LATKTCL)
+
+/******************************
+ * R_LATKTCH (0x30) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_LATKTCH 0
+
+/* Field Masks */
+#define FM_LATKTCH 0XFF
+
+/* Register Masks */
+#define RM_LATKTCH RM(FM_LATKTCH, FB_LATKTCH)
+
+/******************************
+ * R_LRELTCL (0x31) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_LRELTCL 0
+
+/* Field Masks */
+#define FM_LRELTCL 0XFF
+
+/* Register Masks */
+#define RM_LRELTCL RM(FM_LRELTCL, FB_LRELTCL)
+
+/******************************
+ * R_LRELTCH (0x32) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_LRELTCH 0
+
+/* Field Masks */
+#define FM_LRELTCH 0XFF
+
+/* Register Masks */
+#define RM_LRELTCH RM(FM_LRELTCH, FB_LRELTCH)
+
+/****************************
+ * R_EXPTH (0x33) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_EXPTH 0
+
+/* Field Masks */
+#define FM_EXPTH 0XFF
+
+/* Field Values */
+#define FV_EXPTH_0DB 0xFF
+#define FV_EXPTH_N95PT625DB 0x0
+
+/* Register Masks */
+#define RM_EXPTH RM(FM_EXPTH, FB_EXPTH)
+
+/* Register Values */
+#define RV_EXPTH_0DB RV(FV_EXPTH_0DB, FB_EXPTH)
+#define RV_EXPTH_N95PT625DB RV(FV_EXPTH_N95PT625DB, FB_EXPTH)
+
+/*****************************
+ * R_EXPRAT (0x34) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_EXPRAT 0
+
+/* Field Masks */
+#define FM_EXPRAT 0X7
+
+/* Register Masks */
+#define RM_EXPRAT RM(FM_EXPRAT, FB_EXPRAT)
+
+/******************************
+ * R_XATKTCL (0x35) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_XATKTCL 0
+
+/* Field Masks */
+#define FM_XATKTCL 0XFF
+
+/* Register Masks */
+#define RM_XATKTCL RM(FM_XATKTCL, FB_XATKTCL)
+
+/******************************
+ * R_XATKTCH (0x36) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_XATKTCH 0
+
+/* Field Masks */
+#define FM_XATKTCH 0XFF
+
+/* Register Masks */
+#define RM_XATKTCH RM(FM_XATKTCH, FB_XATKTCH)
+
+/******************************
+ * R_XRELTCL (0x37) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_XRELTCL 0
+
+/* Field Masks */
+#define FM_XRELTCL 0XFF
+
+/* Register Masks */
+#define RM_XRELTCL RM(FM_XRELTCL, FB_XRELTCL)
+
+/******************************
+ * R_XRELTCH (0x38) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_XRELTCH 0
+
+/* Field Masks */
+#define FM_XRELTCH 0XFF
+
+/* Register Masks */
+#define RM_XRELTCH RM(FM_XRELTCH, FB_XRELTCH)
+
+/****************************
+ * R_FXCTL (0x39) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_FXCTL_3DEN 4
+#define FB_FXCTL_TEEN 3
+#define FB_FXCTL_TNLFBYPASS 2
+#define FB_FXCTL_BEEN 1
+#define FB_FXCTL_BNLFBYPASS 0
+
+/* Field Masks */
+#define FM_FXCTL_3DEN 0X1
+#define FM_FXCTL_TEEN 0X1
+#define FM_FXCTL_TNLFBYPASS 0X1
+#define FM_FXCTL_BEEN 0X1
+#define FM_FXCTL_BNLFBYPASS 0X1
+
+/* Field Values */
+#define FV_FXCTL_3DEN_ENABLE 0x1
+#define FV_FXCTL_3DEN_DISABLE 0x0
+#define FV_FXCTL_TEEN_ENABLE 0x1
+#define FV_FXCTL_TEEN_DISABLE 0x0
+#define FV_FXCTL_TNLFBYPASS_ENABLE 0x1
+#define FV_FXCTL_TNLFBYPASS_DISABLE 0x0
+#define FV_FXCTL_BEEN_ENABLE 0x1
+#define FV_FXCTL_BEEN_DISABLE 0x0
+#define FV_FXCTL_BNLFBYPASS_ENABLE 0x1
+#define FV_FXCTL_BNLFBYPASS_DISABLE 0x0
+
+/* Register Masks */
+#define RM_FXCTL_3DEN RM(FM_FXCTL_3DEN, FB_FXCTL_3DEN)
+#define RM_FXCTL_TEEN RM(FM_FXCTL_TEEN, FB_FXCTL_TEEN)
+#define RM_FXCTL_TNLFBYPASS \
+ RM(FM_FXCTL_TNLFBYPASS, FB_FXCTL_TNLFBYPASS)
+
+#define RM_FXCTL_BEEN RM(FM_FXCTL_BEEN, FB_FXCTL_BEEN)
+#define RM_FXCTL_BNLFBYPASS \
+ RM(FM_FXCTL_BNLFBYPASS, FB_FXCTL_BNLFBYPASS)
+
+
+/* Register Values */
+#define RV_FXCTL_3DEN_ENABLE \
+ RV(FV_FXCTL_3DEN_ENABLE, FB_FXCTL_3DEN)
+
+#define RV_FXCTL_3DEN_DISABLE \
+ RV(FV_FXCTL_3DEN_DISABLE, FB_FXCTL_3DEN)
+
+#define RV_FXCTL_TEEN_ENABLE \
+ RV(FV_FXCTL_TEEN_ENABLE, FB_FXCTL_TEEN)
+
+#define RV_FXCTL_TEEN_DISABLE \
+ RV(FV_FXCTL_TEEN_DISABLE, FB_FXCTL_TEEN)
+
+#define RV_FXCTL_TNLFBYPASS_ENABLE \
+ RV(FV_FXCTL_TNLFBYPASS_ENABLE, FB_FXCTL_TNLFBYPASS)
+
+#define RV_FXCTL_TNLFBYPASS_DISABLE \
+ RV(FV_FXCTL_TNLFBYPASS_DISABLE, FB_FXCTL_TNLFBYPASS)
+
+#define RV_FXCTL_BEEN_ENABLE \
+ RV(FV_FXCTL_BEEN_ENABLE, FB_FXCTL_BEEN)
+
+#define RV_FXCTL_BEEN_DISABLE \
+ RV(FV_FXCTL_BEEN_DISABLE, FB_FXCTL_BEEN)
+
+#define RV_FXCTL_BNLFBYPASS_ENABLE \
+ RV(FV_FXCTL_BNLFBYPASS_ENABLE, FB_FXCTL_BNLFBYPASS)
+
+#define RV_FXCTL_BNLFBYPASS_DISABLE \
+ RV(FV_FXCTL_BNLFBYPASS_DISABLE, FB_FXCTL_BNLFBYPASS)
+
+
+/*******************************
+ * R_DACCRWRL (0x3A) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACCRWRL_DACCRWDL 0
+
+/* Field Masks */
+#define FM_DACCRWRL_DACCRWDL 0XFF
+
+/* Register Masks */
+#define RM_DACCRWRL_DACCRWDL \
+ RM(FM_DACCRWRL_DACCRWDL, FB_DACCRWRL_DACCRWDL)
+
+
+/*******************************
+ * R_DACCRWRM (0x3B) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACCRWRM_DACCRWDM 0
+
+/* Field Masks */
+#define FM_DACCRWRM_DACCRWDM 0XFF
+
+/* Register Masks */
+#define RM_DACCRWRM_DACCRWDM \
+ RM(FM_DACCRWRM_DACCRWDM, FB_DACCRWRM_DACCRWDM)
+
+
+/*******************************
+ * R_DACCRWRH (0x3C) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACCRWRH_DACCRWDH 0
+
+/* Field Masks */
+#define FM_DACCRWRH_DACCRWDH 0XFF
+
+/* Register Masks */
+#define RM_DACCRWRH_DACCRWDH \
+ RM(FM_DACCRWRH_DACCRWDH, FB_DACCRWRH_DACCRWDH)
+
+
+/*******************************
+ * R_DACCRRDL (0x3D) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACCRRDL 0
+
+/* Field Masks */
+#define FM_DACCRRDL 0XFF
+
+/* Register Masks */
+#define RM_DACCRRDL RM(FM_DACCRRDL, FB_DACCRRDL)
+
+/*******************************
+ * R_DACCRRDM (0x3E) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACCRRDM 0
+
+/* Field Masks */
+#define FM_DACCRRDM 0XFF
+
+/* Register Masks */
+#define RM_DACCRRDM RM(FM_DACCRRDM, FB_DACCRRDM)
+
+/*******************************
+ * R_DACCRRDH (0x3F) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACCRRDH 0
+
+/* Field Masks */
+#define FM_DACCRRDH 0XFF
+
+/* Register Masks */
+#define RM_DACCRRDH RM(FM_DACCRRDH, FB_DACCRRDH)
+
+/********************************
+ * R_DACCRADDR (0x40) *
+ ********************************/
+
+/* Field Offsets */
+#define FB_DACCRADDR_DACCRADD 0
+
+/* Field Masks */
+#define FM_DACCRADDR_DACCRADD 0XFF
+
+/* Register Masks */
+#define RM_DACCRADDR_DACCRADD \
+ RM(FM_DACCRADDR_DACCRADD, FB_DACCRADDR_DACCRADD)
+
+
+/******************************
+ * R_DCOFSEL (0x41) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_DCOFSEL_DC_COEF_SEL 0
+
+/* Field Masks */
+#define FM_DCOFSEL_DC_COEF_SEL 0X7
+
+/* Field Values */
+#define FV_DCOFSEL_DC_COEF_SEL_2_N8 0x0
+#define FV_DCOFSEL_DC_COEF_SEL_2_N9 0x1
+#define FV_DCOFSEL_DC_COEF_SEL_2_N10 0x2
+#define FV_DCOFSEL_DC_COEF_SEL_2_N11 0x3
+#define FV_DCOFSEL_DC_COEF_SEL_2_N12 0x4
+#define FV_DCOFSEL_DC_COEF_SEL_2_N13 0x5
+#define FV_DCOFSEL_DC_COEF_SEL_2_N14 0x6
+#define FV_DCOFSEL_DC_COEF_SEL_2_N15 0x7
+
+/* Register Masks */
+#define RM_DCOFSEL_DC_COEF_SEL \
+ RM(FM_DCOFSEL_DC_COEF_SEL, FB_DCOFSEL_DC_COEF_SEL)
+
+
+/* Register Values */
+#define RV_DCOFSEL_DC_COEF_SEL_2_N8 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N8, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N9 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N9, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N10 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N10, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N11 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N11, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N12 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N12, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N13 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N13, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N14 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N14, FB_DCOFSEL_DC_COEF_SEL)
+
+#define RV_DCOFSEL_DC_COEF_SEL_2_N15 \
+ RV(FV_DCOFSEL_DC_COEF_SEL_2_N15, FB_DCOFSEL_DC_COEF_SEL)
+
+
+/******************************
+ * R_PLLCTL9 (0x4E) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL9_REFDIV_PLL1 0
+
+/* Field Masks */
+#define FM_PLLCTL9_REFDIV_PLL1 0XFF
+
+/* Register Masks */
+#define RM_PLLCTL9_REFDIV_PLL1 \
+ RM(FM_PLLCTL9_REFDIV_PLL1, FB_PLLCTL9_REFDIV_PLL1)
+
+
+/******************************
+ * R_PLLCTLA (0x4F) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTLA_OUTDIV_PLL1 0
+
+/* Field Masks */
+#define FM_PLLCTLA_OUTDIV_PLL1 0XFF
+
+/* Register Masks */
+#define RM_PLLCTLA_OUTDIV_PLL1 \
+ RM(FM_PLLCTLA_OUTDIV_PLL1, FB_PLLCTLA_OUTDIV_PLL1)
+
+
+/******************************
+ * R_PLLCTLB (0x50) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTLB_FBDIV_PLL1L 0
+
+/* Field Masks */
+#define FM_PLLCTLB_FBDIV_PLL1L 0XFF
+
+/* Register Masks */
+#define RM_PLLCTLB_FBDIV_PLL1L \
+ RM(FM_PLLCTLB_FBDIV_PLL1L, FB_PLLCTLB_FBDIV_PLL1L)
+
+
+/******************************
+ * R_PLLCTLC (0x51) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTLC_FBDIV_PLL1H 0
+
+/* Field Masks */
+#define FM_PLLCTLC_FBDIV_PLL1H 0X7
+
+/* Register Masks */
+#define RM_PLLCTLC_FBDIV_PLL1H \
+ RM(FM_PLLCTLC_FBDIV_PLL1H, FB_PLLCTLC_FBDIV_PLL1H)
+
+
+/******************************
+ * R_PLLCTLD (0x52) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTLD_RZ_PLL1 3
+#define FB_PLLCTLD_CP_PLL1 0
+
+/* Field Masks */
+#define FM_PLLCTLD_RZ_PLL1 0X7
+#define FM_PLLCTLD_CP_PLL1 0X7
+
+/* Register Masks */
+#define RM_PLLCTLD_RZ_PLL1 \
+ RM(FM_PLLCTLD_RZ_PLL1, FB_PLLCTLD_RZ_PLL1)
+
+#define RM_PLLCTLD_CP_PLL1 \
+ RM(FM_PLLCTLD_CP_PLL1, FB_PLLCTLD_CP_PLL1)
+
+
+/******************************
+ * R_PLLCTLE (0x53) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTLE_REFDIV_PLL2 0
+
+/* Field Masks */
+#define FM_PLLCTLE_REFDIV_PLL2 0XFF
+
+/* Register Masks */
+#define RM_PLLCTLE_REFDIV_PLL2 \
+ RM(FM_PLLCTLE_REFDIV_PLL2, FB_PLLCTLE_REFDIV_PLL2)
+
+
+/******************************
+ * R_PLLCTLF (0x54) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTLF_OUTDIV_PLL2 0
+
+/* Field Masks */
+#define FM_PLLCTLF_OUTDIV_PLL2 0XFF
+
+/* Register Masks */
+#define RM_PLLCTLF_OUTDIV_PLL2 \
+ RM(FM_PLLCTLF_OUTDIV_PLL2, FB_PLLCTLF_OUTDIV_PLL2)
+
+
+/*******************************
+ * R_PLLCTL10 (0x55) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL10_FBDIV_PLL2L 0
+
+/* Field Masks */
+#define FM_PLLCTL10_FBDIV_PLL2L 0XFF
+
+/* Register Masks */
+#define RM_PLLCTL10_FBDIV_PLL2L \
+ RM(FM_PLLCTL10_FBDIV_PLL2L, FB_PLLCTL10_FBDIV_PLL2L)
+
+
+/*******************************
+ * R_PLLCTL11 (0x56) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL11_FBDIV_PLL2H 0
+
+/* Field Masks */
+#define FM_PLLCTL11_FBDIV_PLL2H 0X7
+
+/* Register Masks */
+#define RM_PLLCTL11_FBDIV_PLL2H \
+ RM(FM_PLLCTL11_FBDIV_PLL2H, FB_PLLCTL11_FBDIV_PLL2H)
+
+
+/*******************************
+ * R_PLLCTL12 (0x57) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL12_RZ_PLL2 3
+#define FB_PLLCTL12_CP_PLL2 0
+
+/* Field Masks */
+#define FM_PLLCTL12_RZ_PLL2 0X7
+#define FM_PLLCTL12_CP_PLL2 0X7
+
+/* Register Masks */
+#define RM_PLLCTL12_RZ_PLL2 \
+ RM(FM_PLLCTL12_RZ_PLL2, FB_PLLCTL12_RZ_PLL2)
+
+#define RM_PLLCTL12_CP_PLL2 \
+ RM(FM_PLLCTL12_CP_PLL2, FB_PLLCTL12_CP_PLL2)
+
+
+/*******************************
+ * R_PLLCTL1B (0x60) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL1B_VCOI_PLL2 4
+#define FB_PLLCTL1B_VCOI_PLL1 2
+
+/* Field Masks */
+#define FM_PLLCTL1B_VCOI_PLL2 0X3
+#define FM_PLLCTL1B_VCOI_PLL1 0X3
+
+/* Register Masks */
+#define RM_PLLCTL1B_VCOI_PLL2 \
+ RM(FM_PLLCTL1B_VCOI_PLL2, FB_PLLCTL1B_VCOI_PLL2)
+
+#define RM_PLLCTL1B_VCOI_PLL1 \
+ RM(FM_PLLCTL1B_VCOI_PLL1, FB_PLLCTL1B_VCOI_PLL1)
+
+
+/*******************************
+ * R_PLLCTL1C (0x61) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL1C_PDB_PLL2 2
+#define FB_PLLCTL1C_PDB_PLL1 1
+
+/* Field Masks */
+#define FM_PLLCTL1C_PDB_PLL2 0X1
+#define FM_PLLCTL1C_PDB_PLL1 0X1
+
+/* Field Values */
+#define FV_PLLCTL1C_PDB_PLL2_ENABLE 0x1
+#define FV_PLLCTL1C_PDB_PLL2_DISABLE 0x0
+#define FV_PLLCTL1C_PDB_PLL1_ENABLE 0x1
+#define FV_PLLCTL1C_PDB_PLL1_DISABLE 0x0
+
+/* Register Masks */
+#define RM_PLLCTL1C_PDB_PLL2 \
+ RM(FM_PLLCTL1C_PDB_PLL2, FB_PLLCTL1C_PDB_PLL2)
+
+#define RM_PLLCTL1C_PDB_PLL1 \
+ RM(FM_PLLCTL1C_PDB_PLL1, FB_PLLCTL1C_PDB_PLL1)
+
+
+/* Register Values */
+#define RV_PLLCTL1C_PDB_PLL2_ENABLE \
+ RV(FV_PLLCTL1C_PDB_PLL2_ENABLE, FB_PLLCTL1C_PDB_PLL2)
+
+#define RV_PLLCTL1C_PDB_PLL2_DISABLE \
+ RV(FV_PLLCTL1C_PDB_PLL2_DISABLE, FB_PLLCTL1C_PDB_PLL2)
+
+#define RV_PLLCTL1C_PDB_PLL1_ENABLE \
+ RV(FV_PLLCTL1C_PDB_PLL1_ENABLE, FB_PLLCTL1C_PDB_PLL1)
+
+#define RV_PLLCTL1C_PDB_PLL1_DISABLE \
+ RV(FV_PLLCTL1C_PDB_PLL1_DISABLE, FB_PLLCTL1C_PDB_PLL1)
+
+
+/*******************************
+ * R_TIMEBASE (0x77) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_TIMEBASE_DIVIDER 0
+
+/* Field Masks */
+#define FM_TIMEBASE_DIVIDER 0XFF
+
+/* Register Masks */
+#define RM_TIMEBASE_DIVIDER \
+ RM(FM_TIMEBASE_DIVIDER, FB_TIMEBASE_DIVIDER)
+
+
+/*****************************
+ * R_DEVIDL (0x7D) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_DEVIDL_DIDL 0
+
+/* Field Masks */
+#define FM_DEVIDL_DIDL 0XFF
+
+/* Register Masks */
+#define RM_DEVIDL_DIDL RM(FM_DEVIDL_DIDL, FB_DEVIDL_DIDL)
+
+/*****************************
+ * R_DEVIDH (0x7E) *
+ *****************************/
+
+/* Field Offsets */
+#define FB_DEVIDH_DIDH 0
+
+/* Field Masks */
+#define FM_DEVIDH_DIDH 0XFF
+
+/* Register Masks */
+#define RM_DEVIDH_DIDH RM(FM_DEVIDH_DIDH, FB_DEVIDH_DIDH)
+
+/****************************
+ * R_RESET (0x80) *
+ ****************************/
+
+/* Field Offsets */
+#define FB_RESET 0
+
+/* Field Masks */
+#define FM_RESET 0XFF
+
+/* Field Values */
+#define FV_RESET_ENABLE 0x85
+
+/* Register Masks */
+#define RM_RESET RM(FM_RESET, FB_RESET)
+
+/* Register Values */
+#define RV_RESET_ENABLE RV(FV_RESET_ENABLE, FB_RESET)
+
+/********************************
+ * R_DACCRSTAT (0x8A) *
+ ********************************/
+
+/* Field Offsets */
+#define FB_DACCRSTAT_DACCR_BUSY 7
+
+/* Field Masks */
+#define FM_DACCRSTAT_DACCR_BUSY 0X1
+
+/* Register Masks */
+#define RM_DACCRSTAT_DACCR_BUSY \
+ RM(FM_DACCRSTAT_DACCR_BUSY, FB_DACCRSTAT_DACCR_BUSY)
+
+
+/******************************
+ * R_PLLCTL0 (0x8E) *
+ ******************************/
+
+/* Field Offsets */
+#define FB_PLLCTL0_PLL2_LOCK 1
+#define FB_PLLCTL0_PLL1_LOCK 0
+
+/* Field Masks */
+#define FM_PLLCTL0_PLL2_LOCK 0X1
+#define FM_PLLCTL0_PLL1_LOCK 0X1
+
+/* Register Masks */
+#define RM_PLLCTL0_PLL2_LOCK \
+ RM(FM_PLLCTL0_PLL2_LOCK, FB_PLLCTL0_PLL2_LOCK)
+
+#define RM_PLLCTL0_PLL1_LOCK \
+ RM(FM_PLLCTL0_PLL1_LOCK, FB_PLLCTL0_PLL1_LOCK)
+
+
+/********************************
+ * R_PLLREFSEL (0x8F) *
+ ********************************/
+
+/* Field Offsets */
+#define FB_PLLREFSEL_PLL2_REF_SEL 4
+#define FB_PLLREFSEL_PLL1_REF_SEL 0
+
+/* Field Masks */
+#define FM_PLLREFSEL_PLL2_REF_SEL 0X7
+#define FM_PLLREFSEL_PLL1_REF_SEL 0X7
+
+/* Field Values */
+#define FV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1 0x0
+#define FV_PLLREFSEL_PLL2_REF_SEL_MCLK2 0x1
+#define FV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1 0x0
+#define FV_PLLREFSEL_PLL1_REF_SEL_MCLK2 0x1
+
+/* Register Masks */
+#define RM_PLLREFSEL_PLL2_REF_SEL \
+ RM(FM_PLLREFSEL_PLL2_REF_SEL, FB_PLLREFSEL_PLL2_REF_SEL)
+
+#define RM_PLLREFSEL_PLL1_REF_SEL \
+ RM(FM_PLLREFSEL_PLL1_REF_SEL, FB_PLLREFSEL_PLL1_REF_SEL)
+
+
+/* Register Values */
+#define RV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1 \
+ RV(FV_PLLREFSEL_PLL2_REF_SEL_XTAL_MCLK1, FB_PLLREFSEL_PLL2_REF_SEL)
+
+#define RV_PLLREFSEL_PLL2_REF_SEL_MCLK2 \
+ RV(FV_PLLREFSEL_PLL2_REF_SEL_MCLK2, FB_PLLREFSEL_PLL2_REF_SEL)
+
+#define RV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1 \
+ RV(FV_PLLREFSEL_PLL1_REF_SEL_XTAL_MCLK1, FB_PLLREFSEL_PLL1_REF_SEL)
+
+#define RV_PLLREFSEL_PLL1_REF_SEL_MCLK2 \
+ RV(FV_PLLREFSEL_PLL1_REF_SEL_MCLK2, FB_PLLREFSEL_PLL1_REF_SEL)
+
+
+/*******************************
+ * R_DACMBCEN (0xC7) *
+ *******************************/
+
+/* Field Offsets */
+#define FB_DACMBCEN_MBCEN3 2
+#define FB_DACMBCEN_MBCEN2 1
+#define FB_DACMBCEN_MBCEN1 0
+
+/* Field Masks */
+#define FM_DACMBCEN_MBCEN3 0X1
+#define FM_DACMBCEN_MBCEN2 0X1
+#define FM_DACMBCEN_MBCEN1 0X1
+
+/* Register Masks */
+#define RM_DACMBCEN_MBCEN3 \
+ RM(FM_DACMBCEN_MBCEN3, FB_DACMBCEN_MBCEN3)
+
+#define RM_DACMBCEN_MBCEN2 \
+ RM(FM_DACMBCEN_MBCEN2, FB_DACMBCEN_MBCEN2)
+
+#define RM_DACMBCEN_MBCEN1 \
+ RM(FM_DACMBCEN_MBCEN1, FB_DACMBCEN_MBCEN1)
+
+
+/********************************
+ * R_DACMBCCTL (0xC8) *
+ ********************************/
+
+/* Field Offsets */
+#define FB_DACMBCCTL_LVLMODE3 5
+#define FB_DACMBCCTL_WINSEL3 4
+#define FB_DACMBCCTL_LVLMODE2 3
+#define FB_DACMBCCTL_WINSEL2 2
+#define FB_DACMBCCTL_LVLMODE1 1
+#define FB_DACMBCCTL_WINSEL1 0
+
+/* Field Masks */
+#define FM_DACMBCCTL_LVLMODE3 0X1
+#define FM_DACMBCCTL_WINSEL3 0X1
+#define FM_DACMBCCTL_LVLMODE2 0X1
+#define FM_DACMBCCTL_WINSEL2 0X1
+#define FM_DACMBCCTL_LVLMODE1 0X1
+#define FM_DACMBCCTL_WINSEL1 0X1
+
+/* Register Masks */
+#define RM_DACMBCCTL_LVLMODE3 \
+ RM(FM_DACMBCCTL_LVLMODE3, FB_DACMBCCTL_LVLMODE3)
+
+#define RM_DACMBCCTL_WINSEL3 \
+ RM(FM_DACMBCCTL_WINSEL3, FB_DACMBCCTL_WINSEL3)
+
+#define RM_DACMBCCTL_LVLMODE2 \
+ RM(FM_DACMBCCTL_LVLMODE2, FB_DACMBCCTL_LVLMODE2)
+
+#define RM_DACMBCCTL_WINSEL2 \
+ RM(FM_DACMBCCTL_WINSEL2, FB_DACMBCCTL_WINSEL2)
+
+#define RM_DACMBCCTL_LVLMODE1 \
+ RM(FM_DACMBCCTL_LVLMODE1, FB_DACMBCCTL_LVLMODE1)
+
+#define RM_DACMBCCTL_WINSEL1 \
+ RM(FM_DACMBCCTL_WINSEL1, FB_DACMBCCTL_WINSEL1)
+
+
+/*********************************
+ * R_DACMBCMUG1 (0xC9) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCMUG1_PHASE 5
+#define FB_DACMBCMUG1_MUGAIN 0
+
+/* Field Masks */
+#define FM_DACMBCMUG1_PHASE 0X1
+#define FM_DACMBCMUG1_MUGAIN 0X1F
+
+/* Register Masks */
+#define RM_DACMBCMUG1_PHASE \
+ RM(FM_DACMBCMUG1_PHASE, FB_DACMBCMUG1_PHASE)
+
+#define RM_DACMBCMUG1_MUGAIN \
+ RM(FM_DACMBCMUG1_MUGAIN, FB_DACMBCMUG1_MUGAIN)
+
+
+/*********************************
+ * R_DACMBCTHR1 (0xCA) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCTHR1_THRESH 0
+
+/* Field Masks */
+#define FM_DACMBCTHR1_THRESH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCTHR1_THRESH \
+ RM(FM_DACMBCTHR1_THRESH, FB_DACMBCTHR1_THRESH)
+
+
+/*********************************
+ * R_DACMBCRAT1 (0xCB) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCRAT1_RATIO 0
+
+/* Field Masks */
+#define FM_DACMBCRAT1_RATIO 0X1F
+
+/* Register Masks */
+#define RM_DACMBCRAT1_RATIO \
+ RM(FM_DACMBCRAT1_RATIO, FB_DACMBCRAT1_RATIO)
+
+
+/**********************************
+ * R_DACMBCATK1L (0xCC) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCATK1L_TCATKL 0
+
+/* Field Masks */
+#define FM_DACMBCATK1L_TCATKL 0XFF
+
+/* Register Masks */
+#define RM_DACMBCATK1L_TCATKL \
+ RM(FM_DACMBCATK1L_TCATKL, FB_DACMBCATK1L_TCATKL)
+
+
+/**********************************
+ * R_DACMBCATK1H (0xCD) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCATK1H_TCATKH 0
+
+/* Field Masks */
+#define FM_DACMBCATK1H_TCATKH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCATK1H_TCATKH \
+ RM(FM_DACMBCATK1H_TCATKH, FB_DACMBCATK1H_TCATKH)
+
+
+/**********************************
+ * R_DACMBCREL1L (0xCE) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCREL1L_TCRELL 0
+
+/* Field Masks */
+#define FM_DACMBCREL1L_TCRELL 0XFF
+
+/* Register Masks */
+#define RM_DACMBCREL1L_TCRELL \
+ RM(FM_DACMBCREL1L_TCRELL, FB_DACMBCREL1L_TCRELL)
+
+
+/**********************************
+ * R_DACMBCREL1H (0xCF) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCREL1H_TCRELH 0
+
+/* Field Masks */
+#define FM_DACMBCREL1H_TCRELH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCREL1H_TCRELH \
+ RM(FM_DACMBCREL1H_TCRELH, FB_DACMBCREL1H_TCRELH)
+
+
+/*********************************
+ * R_DACMBCMUG2 (0xD0) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCMUG2_PHASE 5
+#define FB_DACMBCMUG2_MUGAIN 0
+
+/* Field Masks */
+#define FM_DACMBCMUG2_PHASE 0X1
+#define FM_DACMBCMUG2_MUGAIN 0X1F
+
+/* Register Masks */
+#define RM_DACMBCMUG2_PHASE \
+ RM(FM_DACMBCMUG2_PHASE, FB_DACMBCMUG2_PHASE)
+
+#define RM_DACMBCMUG2_MUGAIN \
+ RM(FM_DACMBCMUG2_MUGAIN, FB_DACMBCMUG2_MUGAIN)
+
+
+/*********************************
+ * R_DACMBCTHR2 (0xD1) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCTHR2_THRESH 0
+
+/* Field Masks */
+#define FM_DACMBCTHR2_THRESH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCTHR2_THRESH \
+ RM(FM_DACMBCTHR2_THRESH, FB_DACMBCTHR2_THRESH)
+
+
+/*********************************
+ * R_DACMBCRAT2 (0xD2) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCRAT2_RATIO 0
+
+/* Field Masks */
+#define FM_DACMBCRAT2_RATIO 0X1F
+
+/* Register Masks */
+#define RM_DACMBCRAT2_RATIO \
+ RM(FM_DACMBCRAT2_RATIO, FB_DACMBCRAT2_RATIO)
+
+
+/**********************************
+ * R_DACMBCATK2L (0xD3) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCATK2L_TCATKL 0
+
+/* Field Masks */
+#define FM_DACMBCATK2L_TCATKL 0XFF
+
+/* Register Masks */
+#define RM_DACMBCATK2L_TCATKL \
+ RM(FM_DACMBCATK2L_TCATKL, FB_DACMBCATK2L_TCATKL)
+
+
+/**********************************
+ * R_DACMBCATK2H (0xD4) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCATK2H_TCATKH 0
+
+/* Field Masks */
+#define FM_DACMBCATK2H_TCATKH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCATK2H_TCATKH \
+ RM(FM_DACMBCATK2H_TCATKH, FB_DACMBCATK2H_TCATKH)
+
+
+/**********************************
+ * R_DACMBCREL2L (0xD5) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCREL2L_TCRELL 0
+
+/* Field Masks */
+#define FM_DACMBCREL2L_TCRELL 0XFF
+
+/* Register Masks */
+#define RM_DACMBCREL2L_TCRELL \
+ RM(FM_DACMBCREL2L_TCRELL, FB_DACMBCREL2L_TCRELL)
+
+
+/**********************************
+ * R_DACMBCREL2H (0xD6) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCREL2H_TCRELH 0
+
+/* Field Masks */
+#define FM_DACMBCREL2H_TCRELH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCREL2H_TCRELH \
+ RM(FM_DACMBCREL2H_TCRELH, FB_DACMBCREL2H_TCRELH)
+
+
+/*********************************
+ * R_DACMBCMUG3 (0xD7) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCMUG3_PHASE 5
+#define FB_DACMBCMUG3_MUGAIN 0
+
+/* Field Masks */
+#define FM_DACMBCMUG3_PHASE 0X1
+#define FM_DACMBCMUG3_MUGAIN 0X1F
+
+/* Register Masks */
+#define RM_DACMBCMUG3_PHASE \
+ RM(FM_DACMBCMUG3_PHASE, FB_DACMBCMUG3_PHASE)
+
+#define RM_DACMBCMUG3_MUGAIN \
+ RM(FM_DACMBCMUG3_MUGAIN, FB_DACMBCMUG3_MUGAIN)
+
+
+/*********************************
+ * R_DACMBCTHR3 (0xD8) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCTHR3_THRESH 0
+
+/* Field Masks */
+#define FM_DACMBCTHR3_THRESH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCTHR3_THRESH \
+ RM(FM_DACMBCTHR3_THRESH, FB_DACMBCTHR3_THRESH)
+
+
+/*********************************
+ * R_DACMBCRAT3 (0xD9) *
+ *********************************/
+
+/* Field Offsets */
+#define FB_DACMBCRAT3_RATIO 0
+
+/* Field Masks */
+#define FM_DACMBCRAT3_RATIO 0X1F
+
+/* Register Masks */
+#define RM_DACMBCRAT3_RATIO \
+ RM(FM_DACMBCRAT3_RATIO, FB_DACMBCRAT3_RATIO)
+
+
+/**********************************
+ * R_DACMBCATK3L (0xDA) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCATK3L_TCATKL 0
+
+/* Field Masks */
+#define FM_DACMBCATK3L_TCATKL 0XFF
+
+/* Register Masks */
+#define RM_DACMBCATK3L_TCATKL \
+ RM(FM_DACMBCATK3L_TCATKL, FB_DACMBCATK3L_TCATKL)
+
+
+/**********************************
+ * R_DACMBCATK3H (0xDB) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCATK3H_TCATKH 0
+
+/* Field Masks */
+#define FM_DACMBCATK3H_TCATKH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCATK3H_TCATKH \
+ RM(FM_DACMBCATK3H_TCATKH, FB_DACMBCATK3H_TCATKH)
+
+
+/**********************************
+ * R_DACMBCREL3L (0xDC) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCREL3L_TCRELL 0
+
+/* Field Masks */
+#define FM_DACMBCREL3L_TCRELL 0XFF
+
+/* Register Masks */
+#define RM_DACMBCREL3L_TCRELL \
+ RM(FM_DACMBCREL3L_TCRELL, FB_DACMBCREL3L_TCRELL)
+
+
+/**********************************
+ * R_DACMBCREL3H (0xDD) *
+ **********************************/
+
+/* Field Offsets */
+#define FB_DACMBCREL3H_TCRELH 0
+
+/* Field Masks */
+#define FM_DACMBCREL3H_TCRELH 0XFF
+
+/* Register Masks */
+#define RM_DACMBCREL3H_TCRELH \
+ RM(FM_DACMBCREL3H_TCRELH, FB_DACMBCREL3H_TCRELH)
+
+
+#endif /* __WOOKIE_H__ */
--
2.11.0
2
4
06 Jan '18
We are going to merge this series thru sound tree, need Mark's ack on
regmap patch or to take it thru regmap tree.
This patch series adds a new SoundWire subsystem which implements a
new MIPI bus protocol 'SoundWire'.
The SoundWire protocol is a robust, scalable, low complexity, low
power, low latency, two-pin (clock and data) multi-drop bus that
allows for the transfer of multiple audio streams and embedded
control/commands. SoundWire provides synchronization capabilities
and supports both PCM and PDM, multichannel data, isochronous and
asynchronous modes.
This series adds SoundWire Bus, IO transfers, DisCo (Discovery and
Configuration) sysfs interface, regmap and Documentation summary.
This patch series is also available on
git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire.git topic/patch_v6
v5: https://lkml.org/lkml/2017/12/6/545
v4: https://lkml.org/lkml/2017/12/1/205
v3: https://lkml.org/lkml/2017/11/30/160
v2: https://lkml.org/lkml/2017/11/10/216
v1: https://lkml.org/lkml/2017/10/18/1030
RFC: https://lkml.org/lkml/2016/10/21/395
Changes in v6:
- Add reviewed/acked tags from Philippe, Pierre, Takashi and Greg
- Fix nitpicks from Takashi
- Drop the sysfs patch for now
Changes in v5:
- Address comments by Pierre
- add reference to mid.mipi.org in documentation
- add group and master device number and don't use those for enumeration
- fix unused calls in disco code and also remove superfluous initialization
- remove sdw_transfer apis slave arg, make enum values integer and not
bitmaps
- clarify the sdw_program_device_num loop and fix interrupt handling
Changes in v4:
- Remove text licenses and add SPDX tags only with C99 style comments
- make bus_type code as GPL v2.0 only
Changes in v3:
- Update the kernel-doc styles and fix included headers for files
- handle dev_pm_domain_attach() for defered probe
- remove OF placeholders
- change regmap license to GPLv2 only
Changes in v2:
- move documentation into driver-api and do rst conversion
- fix documentation comments
- add SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) to all
source files
- rework the transfer logic and paging logic as commented on v1
- remove dummy sysfs fns
- registration checks and fixes
- remove slave check for regamp as that turned superfluous
- remove depends SoundWire symbol
- make modalias api arg const
- use bitmap for tracking assigned
- add counter for report present tracking
todo: add the dt-bindings
Sanyog Kale (4):
Documentation: Add SoundWire summary
soundwire: Add SoundWire MIPI defined registers
soundwire: Add Slave status handling helpers
soundwire: cdns: Add sdw_master_ops and IO transfer support
Vinod Koul (10):
soundwire: Add SoundWire bus type
soundwire: Add Master registration
soundwire: Add MIPI DisCo property helpers
soundwire: Add IO transfer
regmap: Add SoundWire bus support
soundwire: Add slave status handling
soundwire: cdns: Add cadence library
soundwire: intel: Add Intel Master driver
soundwire: intel: Add Intel init module
MAINTAINERS: Add SoundWire entry
Documentation/driver-api/index.rst | 1 +
Documentation/driver-api/soundwire/index.rst | 15 +
Documentation/driver-api/soundwire/summary.rst | 207 +++++
MAINTAINERS | 9 +
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/base/regmap/Kconfig | 4 +
drivers/base/regmap/Makefile | 1 +
drivers/base/regmap/regmap-sdw.c | 92 +++
drivers/soundwire/Kconfig | 37 +
drivers/soundwire/Makefile | 18 +
drivers/soundwire/bus.c | 997 +++++++++++++++++++++++++
drivers/soundwire/bus.h | 71 ++
drivers/soundwire/bus_type.c | 193 +++++
drivers/soundwire/cadence_master.c | 751 +++++++++++++++++++
drivers/soundwire/cadence_master.h | 48 ++
drivers/soundwire/intel.c | 345 +++++++++
drivers/soundwire/intel.h | 23 +
drivers/soundwire/intel_init.c | 198 +++++
drivers/soundwire/mipi_disco.c | 401 ++++++++++
drivers/soundwire/slave.c | 114 +++
include/linux/mod_devicetable.h | 6 +
include/linux/regmap.h | 37 +
include/linux/soundwire/sdw.h | 479 ++++++++++++
include/linux/soundwire/sdw_intel.h | 24 +
include/linux/soundwire/sdw_registers.h | 194 +++++
include/linux/soundwire/sdw_type.h | 19 +
scripts/mod/devicetable-offsets.c | 4 +
scripts/mod/file2alias.c | 15 +
29 files changed, 4306 insertions(+)
create mode 100644 Documentation/driver-api/soundwire/index.rst
create mode 100644 Documentation/driver-api/soundwire/summary.rst
create mode 100644 drivers/base/regmap/regmap-sdw.c
create mode 100644 drivers/soundwire/Kconfig
create mode 100644 drivers/soundwire/Makefile
create mode 100644 drivers/soundwire/bus.c
create mode 100644 drivers/soundwire/bus.h
create mode 100644 drivers/soundwire/bus_type.c
create mode 100644 drivers/soundwire/cadence_master.c
create mode 100644 drivers/soundwire/cadence_master.h
create mode 100644 drivers/soundwire/intel.c
create mode 100644 drivers/soundwire/intel.h
create mode 100644 drivers/soundwire/intel_init.c
create mode 100644 drivers/soundwire/mipi_disco.c
create mode 100644 drivers/soundwire/slave.c
create mode 100644 include/linux/soundwire/sdw.h
create mode 100644 include/linux/soundwire/sdw_intel.h
create mode 100644 include/linux/soundwire/sdw_registers.h
create mode 100644 include/linux/soundwire/sdw_type.h
--
2.7.4
5
28
[alsa-devel] [PATCH 1/1] timecounter: Make cyclecounter struct part of timecounter struct
by Sagar Arun Kamble 06 Jan '18
by Sagar Arun Kamble 06 Jan '18
06 Jan '18
There is no real need for the users of timecounters to define cyclecounter
and timecounter variables separately. Since timecounter will always be
based on cyclecounter, have cyclecounter struct as member of timecounter
struct.
Suggested-by: Chris Wilson <chris(a)chris-wilson.co.uk>
Signed-off-by: Sagar Arun Kamble <sagar.a.kamble(a)intel.com>
Cc: Chris Wilson <chris(a)chris-wilson.co.uk>
Cc: Richard Cochran <richardcochran(a)gmail.com>
Cc: John Stultz <john.stultz(a)linaro.org>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: Stephen Boyd <sboyd(a)codeaurora.org>
Cc: linux-kernel(a)vger.kernel.org
Cc: linux-arm-kernel(a)lists.infradead.org
Cc: netdev(a)vger.kernel.org
Cc: intel-wired-lan(a)lists.osuosl.org
Cc: linux-rdma(a)vger.kernel.org
Cc: alsa-devel(a)alsa-project.org
Cc: kvmarm(a)lists.cs.columbia.edu
---
arch/microblaze/kernel/timer.c | 20 ++++++------
drivers/clocksource/arm_arch_timer.c | 19 ++++++------
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 3 +-
drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 9 +++---
drivers/net/ethernet/amd/xgbe/xgbe.h | 1 -
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 1 -
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 20 ++++++------
drivers/net/ethernet/freescale/fec.h | 1 -
drivers/net/ethernet/freescale/fec_ptp.c | 30 +++++++++---------
drivers/net/ethernet/intel/e1000e/e1000.h | 1 -
drivers/net/ethernet/intel/e1000e/netdev.c | 27 ++++++++--------
drivers/net/ethernet/intel/e1000e/ptp.c | 2 +-
drivers/net/ethernet/intel/igb/igb.h | 1 -
drivers/net/ethernet/intel/igb/igb_ptp.c | 25 ++++++++-------
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 -
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 17 +++++-----
drivers/net/ethernet/mellanox/mlx4/en_clock.c | 28 ++++++++---------
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 -
.../net/ethernet/mellanox/mlx5/core/lib/clock.c | 34 ++++++++++----------
drivers/net/ethernet/qlogic/qede/qede_ptp.c | 20 ++++++------
drivers/net/ethernet/ti/cpts.c | 36 ++++++++++++----------
drivers/net/ethernet/ti/cpts.h | 1 -
include/linux/mlx5/driver.h | 1 -
include/linux/timecounter.h | 4 +--
include/sound/hdaudio.h | 1 -
kernel/time/timecounter.c | 28 ++++++++---------
sound/hda/hdac_stream.c | 7 +++--
virt/kvm/arm/arch_timer.c | 6 ++--
28 files changed, 163 insertions(+), 182 deletions(-)
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 7de941c..b7f89e9 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -199,27 +199,25 @@ static u64 xilinx_read(struct clocksource *cs)
return (u64)xilinx_clock_read();
}
-static struct timecounter xilinx_tc = {
- .cc = NULL,
-};
-
static u64 xilinx_cc_read(const struct cyclecounter *cc)
{
return xilinx_read(NULL);
}
-static struct cyclecounter xilinx_cc = {
- .read = xilinx_cc_read,
- .mask = CLOCKSOURCE_MASK(32),
- .shift = 8,
+static struct timecounter xilinx_tc = {
+ .cc.read = xilinx_cc_read,
+ .cc.mask = CLOCKSOURCE_MASK(32),
+ .cc.mult = 0,
+ .cc.shift = 8,
};
static int __init init_xilinx_timecounter(void)
{
- xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
- xilinx_cc.shift);
+ struct cyclecounter *cc = &xilinx_tc.cc;
+
+ cc->mult = div_sc(timer_clock_freq, NSEC_PER_SEC, cc->shift);
- timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
+ timecounter_init(&xilinx_tc, sched_clock());
return 0;
}
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57cb2f0..31543e5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -179,11 +179,6 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc)
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-static struct cyclecounter cyclecounter __ro_after_init = {
- .read = arch_counter_read_cc,
- .mask = CLOCKSOURCE_MASK(56),
-};
-
struct ate_acpi_oem_info {
char oem_id[ACPI_OEM_ID_SIZE + 1];
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
@@ -915,7 +910,10 @@ static u64 arch_counter_get_cntvct_mem(void)
return ((u64) vct_hi << 32) | vct_lo;
}
-static struct arch_timer_kvm_info arch_timer_kvm_info;
+static struct arch_timer_kvm_info arch_timer_kvm_info = {
+ .timecounter.cc.read = arch_counter_read_cc,
+ .timecounter.cc.mask = CLOCKSOURCE_MASK(56),
+};
struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
{
@@ -925,6 +923,7 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
static void __init arch_counter_register(unsigned type)
{
u64 start_count;
+ struct cyclecounter *cc = &arch_timer_kvm_info.timecounter.cc;
/* Register the CP15 based counter if we have one */
if (type & ARCH_TIMER_TYPE_CP15) {
@@ -943,10 +942,10 @@ static void __init arch_counter_register(unsigned type)
clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
start_count = arch_timer_read_counter();
clocksource_register_hz(&clocksource_counter, arch_timer_rate);
- cyclecounter.mult = clocksource_counter.mult;
- cyclecounter.shift = clocksource_counter.shift;
- timecounter_init(&arch_timer_kvm_info.timecounter,
- &cyclecounter, start_count);
+
+ cc->mult = clocksource_counter.mult;
+ cc->shift = clocksource_counter.shift;
+ timecounter_init(&arch_timer_kvm_info.timecounter, start_count);
/* 56 bits minimum, so we assume worst case rollover */
sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index e107e18..5005c87 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1622,8 +1622,7 @@ static int xgbe_config_tstamp(struct xgbe_prv_data *pdata,
xgbe_set_tstamp_time(pdata, 0, 0);
/* Initialize the timecounter */
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&pdata->tstamp_tc, ktime_to_ns(ktime_get_real()));
return 0;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
index d06d260..5ea4edf 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
@@ -126,7 +126,7 @@ static u64 xgbe_cc_read(const struct cyclecounter *cc)
{
struct xgbe_prv_data *pdata = container_of(cc,
struct xgbe_prv_data,
- tstamp_cc);
+ tstamp_tc.cc);
u64 nsec;
nsec = pdata->hw_if.get_tstamp_time(pdata);
@@ -211,7 +211,7 @@ static int xgbe_settime(struct ptp_clock_info *info,
spin_lock_irqsave(&pdata->tstamp_lock, flags);
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
+ timecounter_init(&pdata->tstamp_tc, nsec);
spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
@@ -228,7 +228,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
{
struct ptp_clock_info *info = &pdata->ptp_clock_info;
struct ptp_clock *clock;
- struct cyclecounter *cc = &pdata->tstamp_cc;
+ struct cyclecounter *cc = &pdata->tstamp_tc.cc;
u64 dividend;
snprintf(info->name, sizeof(info->name), "%s",
@@ -263,8 +263,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata)
cc->mult = 1;
cc->shift = 0;
- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&pdata->tstamp_tc, ktime_to_ns(ktime_get_real()));
/* Disable all timestamping to start */
XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index ad102c8..2445103 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -1168,7 +1168,6 @@ struct xgbe_prv_data {
struct ptp_clock_info ptp_clock_info;
struct ptp_clock *ptp_clock;
struct hwtstamp_config tstamp_config;
- struct cyclecounter tstamp_cc;
struct timecounter tstamp_tc;
unsigned int tstamp_addend;
struct work_struct tx_tstamp_work;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 352beff..f164fe0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1827,7 +1827,6 @@ struct bnx2x {
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
struct work_struct ptp_task;
- struct cyclecounter cyclecounter;
struct timecounter timecounter;
bool timecounter_init_done;
struct sk_buff *ptp_tx_skb;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 91e2a75..83624ad 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13850,7 +13850,7 @@ static int bnx2x_ptp_settime(struct ptp_clock_info *ptp,
DP(BNX2X_MSG_PTP, "PTP settime called, ns = %llu\n", ns);
/* Re-init the timecounter */
- timecounter_init(&bp->timecounter, &bp->cyclecounter, ns);
+ timecounter_init(&bp->timecounter, ns);
return 0;
}
@@ -15254,7 +15254,7 @@ void bnx2x_set_rx_ts(struct bnx2x *bp, struct sk_buff *skb)
/* Read the PHC */
static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc)
{
- struct bnx2x *bp = container_of(cc, struct bnx2x, cyclecounter);
+ struct bnx2x *bp = container_of(cc, struct bnx2x, timecounter.cc);
int port = BP_PORT(bp);
u32 wb_data[2];
u64 phc_cycles;
@@ -15269,13 +15269,13 @@ static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc)
return phc_cycles;
}
-static void bnx2x_init_cyclecounter(struct bnx2x *bp)
+static void bnx2x_init_cyclecounter(struct cyclecounter *cc)
{
- memset(&bp->cyclecounter, 0, sizeof(bp->cyclecounter));
- bp->cyclecounter.read = bnx2x_cyclecounter_read;
- bp->cyclecounter.mask = CYCLECOUNTER_MASK(64);
- bp->cyclecounter.shift = 0;
- bp->cyclecounter.mult = 1;
+ memset(cc, 0, sizeof(*cc));
+ cc->read = bnx2x_cyclecounter_read;
+ cc->mask = CYCLECOUNTER_MASK(64);
+ cc->shift = 0;
+ cc->mult = 1;
}
static int bnx2x_send_reset_timesync_ramrod(struct bnx2x *bp)
@@ -15511,8 +15511,8 @@ void bnx2x_init_ptp(struct bnx2x *bp)
* unload / load (e.g. MTU change) while it is running.
*/
if (!bp->timecounter_init_done) {
- bnx2x_init_cyclecounter(bp);
- timecounter_init(&bp->timecounter, &bp->cyclecounter,
+ bnx2x_init_cyclecounter(&bp->timecounter.cc);
+ timecounter_init(&bp->timecounter,
ktime_to_ns(ktime_get_real()));
bp->timecounter_init_done = 1;
}
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 5385074..d54b501 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -549,7 +549,6 @@ struct fec_enet_private {
struct ptp_clock_info ptp_caps;
unsigned long last_overflow_check;
spinlock_t tmreg_lock;
- struct cyclecounter cc;
struct timecounter tc;
int rx_hwtstamp_filter;
u32 base_incval;
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index f814397..b1261d1 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -186,13 +186,14 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
* ptp counter, which maybe cause 32-bit wrap. Since the
* (NSEC_PER_SEC - (u32)ts.tv_nsec) is less than 2 second.
* We can ensure the wrap will not cause issue. If the offset
- * is bigger than fep->cc.mask would be a error.
+ * is bigger than fep->tc.cc.mask would be a error.
*/
- val &= fep->cc.mask;
+ val &= fep->tc.cc.mask;
writel(val, fep->hwp + FEC_TCCR(fep->pps_channel));
/* Calculate the second the compare event timestamp */
- fep->next_counter = (val + fep->reload_period) & fep->cc.mask;
+ fep->next_counter = (val + fep->reload_period) &
+ fep->tc.cc.mask;
/* * Enable compare event when overflow */
val = readl(fep->hwp + FEC_ATIME_CTRL);
@@ -211,7 +212,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
* the third timestamp. Refer the TCCR register detail in the spec.
*/
writel(fep->next_counter, fep->hwp + FEC_TCCR(fep->pps_channel));
- fep->next_counter = (fep->next_counter + fep->reload_period) & fep->cc.mask;
+ fep->next_counter = (fep->next_counter + fep->reload_period) &
+ fep->tc.cc.mask;
} else {
writel(0, fep->hwp + FEC_TCSR(fep->pps_channel));
}
@@ -233,7 +235,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
static u64 fec_ptp_read(const struct cyclecounter *cc)
{
struct fec_enet_private *fep =
- container_of(cc, struct fec_enet_private, cc);
+ container_of(cc, struct fec_enet_private, tc.cc);
const struct platform_device_id *id_entry =
platform_get_device_id(fep->pdev);
u32 tempval;
@@ -276,14 +278,14 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
writel(FEC_T_CTRL_ENABLE | FEC_T_CTRL_PERIOD_RST,
fep->hwp + FEC_ATIME_CTRL);
- memset(&fep->cc, 0, sizeof(fep->cc));
- fep->cc.read = fec_ptp_read;
- fep->cc.mask = CLOCKSOURCE_MASK(31);
- fep->cc.shift = 31;
- fep->cc.mult = FEC_CC_MULT;
+ memset(&fep->tc.cc, 0, sizeof(fep->tc.cc));
+ fep->tc.cc.read = fec_ptp_read;
+ fep->tc.cc.mask = CLOCKSOURCE_MASK(31);
+ fep->tc.cc.shift = 31;
+ fep->tc.cc.mult = FEC_CC_MULT;
/* reset the ns time counter */
- timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real()));
+ timecounter_init(&fep->tc, ktime_to_ns(ktime_get_real()));
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
}
@@ -434,11 +436,11 @@ static int fec_ptp_settime(struct ptp_clock_info *ptp,
/* Get the timer value based on timestamp.
* Update the counter with the masked value.
*/
- counter = ns & fep->cc.mask;
+ counter = ns & fep->tc.cc.mask;
spin_lock_irqsave(&fep->tmreg_lock, flags);
writel(counter, fep->hwp + FEC_ATIME);
- timecounter_init(&fep->tc, &fep->cc, ns);
+ timecounter_init(&fep->tc, ns);
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
mutex_unlock(&fep->ptp_clk_mutex);
return 0;
@@ -570,7 +572,7 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id)
/* Update the counter; */
fep->next_counter = (fep->next_counter + fep->reload_period) &
- fep->cc.mask;
+ fep->tc.cc.mask;
event.type = PTP_CLOCK_PPS;
ptp_clock_event(fep->ptp_clock, &event);
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 2311b31..b59f82a 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -340,7 +340,6 @@ struct e1000_adapter {
unsigned long tx_hwtstamp_start;
struct work_struct tx_hwtstamp_work;
spinlock_t systim_lock; /* protects SYSTIML/H regsters */
- struct cyclecounter cc;
struct timecounter tc;
struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 9f18d39..c9f7ba3 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3536,7 +3536,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_96MHZ;
incvalue = INCVALUE_96MHZ;
shift = INCVALUE_SHIFT_96MHZ;
- adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
+ adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
break;
case e1000_pch_lpt:
if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) {
@@ -3544,13 +3544,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_96MHZ;
incvalue = INCVALUE_96MHZ;
shift = INCVALUE_SHIFT_96MHZ;
- adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
+ adapter->tc.cc.shift = shift + INCPERIOD_SHIFT_96MHZ;
} else {
/* Stable 25MHz frequency */
incperiod = INCPERIOD_25MHZ;
incvalue = INCVALUE_25MHZ;
shift = INCVALUE_SHIFT_25MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
}
break;
case e1000_pch_spt:
@@ -3559,7 +3559,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_24MHZ;
incvalue = INCVALUE_24MHZ;
shift = INCVALUE_SHIFT_24MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
break;
}
return -EINVAL;
@@ -3569,13 +3569,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_24MHZ;
incvalue = INCVALUE_24MHZ;
shift = INCVALUE_SHIFT_24MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
} else {
/* Stable 38400KHz frequency */
incperiod = INCPERIOD_38400KHZ;
incvalue = INCVALUE_38400KHZ;
shift = INCVALUE_SHIFT_38400KHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
}
break;
case e1000_82574:
@@ -3584,7 +3584,7 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
incperiod = INCPERIOD_25MHZ;
incvalue = INCVALUE_25MHZ;
shift = INCVALUE_SHIFT_25MHZ;
- adapter->cc.shift = shift;
+ adapter->tc.cc.shift = shift;
break;
default:
return -EINVAL;
@@ -3955,8 +3955,7 @@ static void e1000e_systim_reset(struct e1000_adapter *adapter)
/* reset the systim ns time counter */
spin_lock_irqsave(&adapter->systim_lock, flags);
- timecounter_init(&adapter->tc, &adapter->cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&adapter->tc, ktime_to_ns(ktime_get_real()));
spin_unlock_irqrestore(&adapter->systim_lock, flags);
/* restore the previous hwtstamp configuration settings */
@@ -4389,7 +4388,7 @@ static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim)
static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc)
{
struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
- cc);
+ tc.cc);
struct e1000_hw *hw = &adapter->hw;
u32 systimel, systimeh;
u64 systim;
@@ -4449,10 +4448,10 @@ static int e1000_sw_init(struct e1000_adapter *adapter)
/* Setup hardware time stamping cyclecounter */
if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) {
- adapter->cc.read = e1000e_cyclecounter_read;
- adapter->cc.mask = CYCLECOUNTER_MASK(64);
- adapter->cc.mult = 1;
- /* cc.shift set in e1000e_get_base_tininca() */
+ adapter->tc.cc.read = e1000e_cyclecounter_read;
+ adapter->tc.cc.mask = CYCLECOUNTER_MASK(64);
+ adapter->tc.cc.mult = 1;
+ /* tc.cc.shift set in e1000e_get_base_tininca() */
spin_lock_init(&adapter->systim_lock);
INIT_WORK(&adapter->tx_hwtstamp_work, e1000e_tx_hwtstamp_work);
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
index b366885..03d5f2a 100644
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
@@ -222,7 +222,7 @@ static int e1000e_phc_settime(struct ptp_clock_info *ptp,
/* reset the timecounter */
spin_lock_irqsave(&adapter->systim_lock, flags);
- timecounter_init(&adapter->tc, &adapter->cc, ns);
+ timecounter_init(&adapter->tc, ns);
spin_unlock_irqrestore(&adapter->systim_lock, flags);
return 0;
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 9284569..4eac4f2 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -565,7 +565,6 @@ struct igb_adapter {
unsigned long last_rx_timestamp;
unsigned int ptp_flags;
spinlock_t tmreg_lock;
- struct cyclecounter cc;
struct timecounter tc;
u32 tx_hwtstamp_timeouts;
u32 tx_hwtstamp_skipped;
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index 841c2a0..0745eff 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -79,7 +79,7 @@
/* SYSTIM read access for the 82576 */
static u64 igb_ptp_read_82576(const struct cyclecounter *cc)
{
- struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
+ struct igb_adapter *igb = container_of(cc, struct igb_adapter, tc.cc);
struct e1000_hw *hw = &igb->hw;
u64 val;
u32 lo, hi;
@@ -96,7 +96,7 @@ static u64 igb_ptp_read_82576(const struct cyclecounter *cc)
/* SYSTIM read access for the 82580 */
static u64 igb_ptp_read_82580(const struct cyclecounter *cc)
{
- struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
+ struct igb_adapter *igb = container_of(cc, struct igb_adapter, tc.cc);
struct e1000_hw *hw = &igb->hw;
u32 lo, hi;
u64 val;
@@ -330,7 +330,7 @@ static int igb_ptp_settime_82576(struct ptp_clock_info *ptp,
spin_lock_irqsave(&igb->tmreg_lock, flags);
- timecounter_init(&igb->tc, &igb->cc, ns);
+ timecounter_init(&igb->tc, ns);
spin_unlock_irqrestore(&igb->tmreg_lock, flags);
@@ -1126,10 +1126,10 @@ void igb_ptp_init(struct igb_adapter *adapter)
adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;
adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
adapter->ptp_caps.enable = igb_ptp_feature_enable;
- adapter->cc.read = igb_ptp_read_82576;
- adapter->cc.mask = CYCLECOUNTER_MASK(64);
- adapter->cc.mult = 1;
- adapter->cc.shift = IGB_82576_TSYNC_SHIFT;
+ adapter->tc.cc.read = igb_ptp_read_82576;
+ adapter->tc.cc.mask = CYCLECOUNTER_MASK(64);
+ adapter->tc.cc.mult = 1;
+ adapter->tc.cc.shift = IGB_82576_TSYNC_SHIFT;
adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK;
break;
case e1000_82580:
@@ -1145,10 +1145,10 @@ void igb_ptp_init(struct igb_adapter *adapter)
adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;
adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
adapter->ptp_caps.enable = igb_ptp_feature_enable;
- adapter->cc.read = igb_ptp_read_82580;
- adapter->cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580);
- adapter->cc.mult = 1;
- adapter->cc.shift = 0;
+ adapter->tc.cc.read = igb_ptp_read_82580;
+ adapter->tc.cc.mask = CYCLECOUNTER_MASK(IGB_NBITS_82580);
+ adapter->tc.cc.mult = 1;
+ adapter->tc.cc.shift = 0;
adapter->ptp_flags |= IGB_PTP_OVERFLOW_CHECK;
break;
case e1000_i210:
@@ -1289,8 +1289,7 @@ void igb_ptp_reset(struct igb_adapter *adapter)
igb_ptp_write_i210(adapter, &ts);
} else {
- timecounter_init(&adapter->tc, &adapter->cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&adapter->tc, ktime_to_ns(ktime_get_real()));
}
out:
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 468c355..5c391a0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -738,7 +738,6 @@ struct ixgbe_adapter {
unsigned long last_rx_ptp_check;
unsigned long last_rx_timestamp;
spinlock_t tmreg_lock;
- struct cyclecounter hw_cc;
struct timecounter hw_tc;
u32 base_incval;
u32 tx_hwtstamp_timeouts;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index ae312c4..6e9f2c0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -179,7 +179,7 @@
static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- int shift = adapter->hw_cc.shift;
+ int shift = adapter->hw_tc.cc.shift;
u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem;
u64 ns = 0, clock_edge = 0;
@@ -237,7 +237,7 @@ static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter)
/**
* ixgbe_ptp_read_X550 - read cycle counter value
- * @hw_cc: cyclecounter structure
+ * @cc: cyclecounter structure
*
* This function reads SYSTIME registers. It is called by the cyclecounter
* structure to convert from internal representation into nanoseconds. We need
@@ -245,10 +245,10 @@ static void ixgbe_ptp_setup_sdp_x540(struct ixgbe_adapter *adapter)
* result of SYSTIME is 32bits of "billions of cycles" and 32 bits of
* "cycles", rather than seconds and nanoseconds.
*/
-static u64 ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc)
+static u64 ixgbe_ptp_read_X550(const struct cyclecounter *cc)
{
struct ixgbe_adapter *adapter =
- container_of(hw_cc, struct ixgbe_adapter, hw_cc);
+ container_of(cc, struct ixgbe_adapter, hw_tc.cc);
struct ixgbe_hw *hw = &adapter->hw;
struct timespec64 ts;
@@ -285,7 +285,7 @@ static u64 ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc)
static u64 ixgbe_ptp_read_82599(const struct cyclecounter *cc)
{
struct ixgbe_adapter *adapter =
- container_of(cc, struct ixgbe_adapter, hw_cc);
+ container_of(cc, struct ixgbe_adapter, hw_tc.cc);
struct ixgbe_hw *hw = &adapter->hw;
u64 stamp = 0;
@@ -508,7 +508,7 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp,
/* reset the timecounter */
spin_lock_irqsave(&adapter->tmreg_lock, flags);
- timecounter_init(&adapter->hw_tc, &adapter->hw_cc, ns);
+ timecounter_init(&adapter->hw_tc, ns);
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
if (adapter->ptp_setup_sdp)
@@ -1164,7 +1164,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
/* need lock to prevent incorrect read while modifying cyclecounter */
spin_lock_irqsave(&adapter->tmreg_lock, flags);
- memcpy(&adapter->hw_cc, &cc, sizeof(adapter->hw_cc));
+ memcpy(&adapter->hw_tc.cc, &cc, sizeof(adapter->hw_tc.cc));
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
}
@@ -1195,8 +1195,7 @@ void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
ixgbe_ptp_start_cyclecounter(adapter);
spin_lock_irqsave(&adapter->tmreg_lock, flags);
- timecounter_init(&adapter->hw_tc, &adapter->hw_cc,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&adapter->hw_tc, ktime_to_ns(ktime_get_real()));
spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
adapter->last_overflow_check = jiffies;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_clock.c b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
index 0247885..35987b5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_clock.c
@@ -38,13 +38,13 @@
/* mlx4_en_read_clock - read raw cycle counter (to be used by time counter)
*/
-static u64 mlx4_en_read_clock(const struct cyclecounter *tc)
+static u64 mlx4_en_read_clock(const struct cyclecounter *cc)
{
struct mlx4_en_dev *mdev =
- container_of(tc, struct mlx4_en_dev, cycles);
+ container_of(cc, struct mlx4_en_dev, clock.cc);
struct mlx4_dev *dev = mdev->dev;
- return mlx4_read_clock(dev) & tc->mask;
+ return mlx4_read_clock(dev) & cc->mask;
}
u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe)
@@ -138,7 +138,7 @@ static int mlx4_en_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
write_seqlock_irqsave(&mdev->clock_lock, flags);
timecounter_read(&mdev->clock);
- mdev->cycles.mult = neg_adj ? mult - diff : mult + diff;
+ mdev->clock.cc.mult = neg_adj ? mult - diff : mult + diff;
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
return 0;
@@ -207,7 +207,7 @@ static int mlx4_en_phc_settime(struct ptp_clock_info *ptp,
/* reset the timecounter */
write_seqlock_irqsave(&mdev->clock_lock, flags);
- timecounter_init(&mdev->clock, &mdev->cycles, ns);
+ timecounter_init(&mdev->clock, ns);
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
return 0;
@@ -274,17 +274,17 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
seqlock_init(&mdev->clock_lock);
- memset(&mdev->cycles, 0, sizeof(mdev->cycles));
- mdev->cycles.read = mlx4_en_read_clock;
- mdev->cycles.mask = CLOCKSOURCE_MASK(48);
- mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock);
- mdev->cycles.mult =
- clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
- mdev->nominal_c_mult = mdev->cycles.mult;
+ memset(&mdev->clock.cc, 0, sizeof(mdev->clock.cc));
+ mdev->clock.cc.read = mlx4_en_read_clock;
+ mdev->clock.cc.mask = CLOCKSOURCE_MASK(48);
+ mdev->clock.cc.shift = freq_to_shift(dev->caps.hca_core_clock);
+ mdev->clock.cc.mult =
+ clocksource_khz2mult(1000 * dev->caps.hca_core_clock,
+ mdev->clock.cc.shift);
+ mdev->nominal_c_mult = mdev->clock.cc.mult;
write_seqlock_irqsave(&mdev->clock_lock, flags);
- timecounter_init(&mdev->clock, &mdev->cycles,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&mdev->clock, ktime_to_ns(ktime_get_real()));
write_sequnlock_irqrestore(&mdev->clock_lock, flags);
/* Configure the PHC */
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 1856e27..e301dcf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -422,7 +422,6 @@ struct mlx4_en_dev {
spinlock_t uar_lock;
u8 mac_removed[MLX4_MAX_PORTS + 1];
u32 nominal_c_mult;
- struct cyclecounter cycles;
seqlock_t clock_lock;
struct timecounter clock;
unsigned long last_overflow_check;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index fa8aed6..8cb6838 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -64,7 +64,7 @@ enum {
static u64 read_internal_timer(const struct cyclecounter *cc)
{
- struct mlx5_clock *clock = container_of(cc, struct mlx5_clock, cycles);
+ struct mlx5_clock *clock = container_of(cc, struct mlx5_clock, tc.cc);
struct mlx5_core_dev *mdev = container_of(clock, struct mlx5_core_dev,
clock);
@@ -122,7 +122,7 @@ static int mlx5_ptp_settime(struct ptp_clock_info *ptp,
unsigned long flags;
write_lock_irqsave(&clock->lock, flags);
- timecounter_init(&clock->tc, &clock->cycles, ns);
+ timecounter_init(&clock->tc, ns);
write_unlock_irqrestore(&clock->lock, flags);
return 0;
@@ -177,8 +177,8 @@ static int mlx5_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
write_lock_irqsave(&clock->lock, flags);
timecounter_read(&clock->tc);
- clock->cycles.mult = neg_adj ? clock->nominal_c_mult - diff :
- clock->nominal_c_mult + diff;
+ clock->tc.cc.mult = neg_adj ? clock->nominal_c_mult - diff :
+ clock->nominal_c_mult + diff;
write_unlock_irqrestore(&clock->lock, flags);
return 0;
@@ -281,8 +281,8 @@ static int mlx5_perout_configure(struct ptp_clock_info *ptp,
write_lock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
nsec_delta = ns - nsec_now;
- cycles_delta = div64_u64(nsec_delta << clock->cycles.shift,
- clock->cycles.mult);
+ cycles_delta = div64_u64(nsec_delta << clock->tc.cc.shift,
+ clock->tc.cc.mult);
write_unlock_irqrestore(&clock->lock, flags);
time_stamp = cycles_now + cycles_delta;
field_select = MLX5_MTPPS_FS_PIN_MODE |
@@ -440,8 +440,8 @@ void mlx5_pps_event(struct mlx5_core_dev *mdev,
write_lock_irqsave(&clock->lock, flags);
nsec_now = timecounter_cyc2time(&clock->tc, cycles_now);
nsec_delta = ns - nsec_now;
- cycles_delta = div64_u64(nsec_delta << clock->cycles.shift,
- clock->cycles.mult);
+ cycles_delta = div64_u64(nsec_delta << clock->tc.cc.shift,
+ clock->tc.cc.mult);
clock->pps_info.start[pin] = cycles_now + cycles_delta;
schedule_work(&clock->pps_info.out_work);
write_unlock_irqrestore(&clock->lock, flags);
@@ -454,6 +454,7 @@ void mlx5_pps_event(struct mlx5_core_dev *mdev,
void mlx5_init_clock(struct mlx5_core_dev *mdev)
{
struct mlx5_clock *clock = &mdev->clock;
+ struct cyclecounter *cc = &clock->tc.cc;
u64 ns;
u64 frac = 0;
u32 dev_freq;
@@ -464,21 +465,18 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
return;
}
rwlock_init(&clock->lock);
- clock->cycles.read = read_internal_timer;
- clock->cycles.shift = MLX5_CYCLES_SHIFT;
- clock->cycles.mult = clocksource_khz2mult(dev_freq,
- clock->cycles.shift);
- clock->nominal_c_mult = clock->cycles.mult;
- clock->cycles.mask = CLOCKSOURCE_MASK(41);
+ cc->read = read_internal_timer;
+ cc->shift = MLX5_CYCLES_SHIFT;
+ cc->mult = clocksource_khz2mult(dev_freq, cc->shift);
+ clock->nominal_c_mult = cc->mult;
+ cc->mask = CLOCKSOURCE_MASK(41);
- timecounter_init(&clock->tc, &clock->cycles,
- ktime_to_ns(ktime_get_real()));
+ timecounter_init(&clock->tc, ktime_to_ns(ktime_get_real()));
/* Calculate period in seconds to call the overflow watchdog - to make
* sure counter is checked at least once every wrap around.
*/
- ns = cyclecounter_cyc2ns(&clock->cycles, clock->cycles.mask,
- frac, &frac);
+ ns = cyclecounter_cyc2ns(cc, cc->mask, frac, &frac);
do_div(ns, NSEC_PER_SEC / 2 / HZ);
clock->overflow_period = ns;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
index 9b2280b..95bb8a8 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
@@ -34,7 +34,6 @@
struct qede_ptp {
const struct qed_eth_ptp_ops *ops;
struct ptp_clock_info clock_info;
- struct cyclecounter cc;
struct timecounter tc;
struct ptp_clock *clock;
struct work_struct work;
@@ -132,7 +131,7 @@ static int qede_ptp_settime(struct ptp_clock_info *info,
/* Re-init the timecounter */
spin_lock_bh(&ptp->lock);
- timecounter_init(&ptp->tc, &ptp->cc, ns);
+ timecounter_init(&ptp->tc, ns);
spin_unlock_bh(&ptp->lock);
return 0;
@@ -196,7 +195,7 @@ static u64 qede_ptp_read_cc(const struct cyclecounter *cc)
u64 phc_cycles;
int rc;
- ptp = container_of(cc, struct qede_ptp, cc);
+ ptp = container_of(cc, struct qede_ptp, tc.cc);
edev = ptp->edev;
rc = ptp->ops->read_cc(edev->cdev, &phc_cycles);
if (rc)
@@ -428,14 +427,13 @@ static int qede_ptp_init(struct qede_dev *edev, bool init_tc)
* unload / load (e.g. MTU change) while it is running.
*/
if (init_tc) {
- memset(&ptp->cc, 0, sizeof(ptp->cc));
- ptp->cc.read = qede_ptp_read_cc;
- ptp->cc.mask = CYCLECOUNTER_MASK(64);
- ptp->cc.shift = 0;
- ptp->cc.mult = 1;
-
- timecounter_init(&ptp->tc, &ptp->cc,
- ktime_to_ns(ktime_get_real()));
+ memset(&ptp->tc.cc, 0, sizeof(ptp->tc.cc));
+ ptp->tc.cc.read = qede_ptp_read_cc;
+ ptp->tc.cc.mask = CYCLECOUNTER_MASK(64);
+ ptp->tc.cc.shift = 0;
+ ptp->tc.cc.mult = 1;
+
+ timecounter_init(&ptp->tc, ktime_to_ns(ktime_get_real()));
}
return rc;
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
index e7b76f6..b8fe843 100644
--- a/drivers/net/ethernet/ti/cpts.c
+++ b/drivers/net/ethernet/ti/cpts.c
@@ -182,7 +182,7 @@ static u64 cpts_systim_read(const struct cyclecounter *cc)
u64 val = 0;
struct cpts_event *event;
struct list_head *this, *next;
- struct cpts *cpts = container_of(cc, struct cpts, cc);
+ struct cpts *cpts = container_of(cc, struct cpts, tc.cc);
cpts_write32(cpts, TS_PUSH, ts_push);
if (cpts_fifo_read(cpts, CPTS_EV_PUSH))
@@ -224,7 +224,7 @@ static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
timecounter_read(&cpts->tc);
- cpts->cc.mult = neg_adj ? mult - diff : mult + diff;
+ cpts->tc.cc.mult = neg_adj ? mult - diff : mult + diff;
spin_unlock_irqrestore(&cpts->lock, flags);
@@ -268,7 +268,7 @@ static int cpts_ptp_settime(struct ptp_clock_info *ptp,
ns = timespec64_to_ns(ts);
spin_lock_irqsave(&cpts->lock, flags);
- timecounter_init(&cpts->tc, &cpts->cc, ns);
+ timecounter_init(&cpts->tc, ns);
spin_unlock_irqrestore(&cpts->lock, flags);
return 0;
@@ -447,7 +447,7 @@ int cpts_register(struct cpts *cpts)
cpts_write32(cpts, CPTS_EN, control);
cpts_write32(cpts, TS_PEND_EN, int_enable);
- timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
+ timecounter_init(&cpts->tc, ktime_to_ns(ktime_get_real()));
cpts->clock = ptp_clock_register(&cpts->info, cpts->dev);
if (IS_ERR(cpts->clock)) {
@@ -486,6 +486,7 @@ void cpts_unregister(struct cpts *cpts)
static void cpts_calc_mult_shift(struct cpts *cpts)
{
+ struct cyclecounter *cc = &cpts->tc.cc;
u64 frac, maxsec, ns;
u32 freq;
@@ -494,7 +495,7 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
/* Calc the maximum number of seconds which we can run before
* wrapping around.
*/
- maxsec = cpts->cc.mask;
+ maxsec = cc->mask;
do_div(maxsec, freq);
/* limit conversation rate to 10 sec as higher values will produce
* too small mult factors and so reduce the conversion accuracy
@@ -507,18 +508,19 @@ static void cpts_calc_mult_shift(struct cpts *cpts)
dev_info(cpts->dev, "cpts: overflow check period %lu (jiffies)\n",
cpts->ov_check_period);
- if (cpts->cc.mult || cpts->cc.shift)
+ if (cc->mult || cc->shift)
return;
- clocks_calc_mult_shift(&cpts->cc.mult, &cpts->cc.shift,
+ clocks_calc_mult_shift(&cc->mult, &cc->shift,
freq, NSEC_PER_SEC, maxsec);
frac = 0;
- ns = cyclecounter_cyc2ns(&cpts->cc, freq, cpts->cc.mask, &frac);
+ ns = cyclecounter_cyc2ns(cc, freq, cc->mask, &frac);
dev_info(cpts->dev,
"CPTS: ref_clk_freq:%u calc_mult:%u calc_shift:%u error:%lld nsec/sec\n",
- freq, cpts->cc.mult, cpts->cc.shift, (ns - NSEC_PER_SEC));
+ freq, cc->mult, cc->shift,
+ (ns - NSEC_PER_SEC));
}
static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
@@ -527,13 +529,13 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
u32 prop;
if (!of_property_read_u32(node, "cpts_clock_mult", &prop))
- cpts->cc.mult = prop;
+ cpts->tc.cc.mult = prop;
if (!of_property_read_u32(node, "cpts_clock_shift", &prop))
- cpts->cc.shift = prop;
+ cpts->tc.cc.shift = prop;
- if ((cpts->cc.mult && !cpts->cc.shift) ||
- (!cpts->cc.mult && cpts->cc.shift))
+ if ((cpts->tc.cc.mult && !cpts->tc.cc.shift) ||
+ (!cpts->tc.cc.mult && cpts->tc.cc.shift))
goto of_error;
return 0;
@@ -569,15 +571,15 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
clk_prepare(cpts->refclk);
- cpts->cc.read = cpts_systim_read;
- cpts->cc.mask = CLOCKSOURCE_MASK(32);
+ cpts->tc.cc.read = cpts_systim_read;
+ cpts->tc.cc.mask = CLOCKSOURCE_MASK(32);
cpts->info = cpts_info;
cpts_calc_mult_shift(cpts);
- /* save cc.mult original value as it can be modified
+ /* save tc.cc.mult original value as it can be modified
* by cpts_ptp_adjfreq().
*/
- cpts->cc_mult = cpts->cc.mult;
+ cpts->cc_mult = cpts->tc.cc.mult;
return cpts;
}
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
index 73d73fa..a7174eb 100644
--- a/drivers/net/ethernet/ti/cpts.h
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -117,7 +117,6 @@ struct cpts {
struct ptp_clock *clock;
spinlock_t lock; /* protects time registers */
u32 cc_mult; /* for the nominal frequency */
- struct cyclecounter cc;
struct timecounter tc;
int phc_index;
struct clk *refclk;
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index a886b51..c81c615 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -780,7 +780,6 @@ struct mlx5_pps {
struct mlx5_clock {
rwlock_t lock;
- struct cyclecounter cycles;
struct timecounter tc;
struct hwtstamp_config hwtstamp_config;
u32 nominal_c_mult;
diff --git a/include/linux/timecounter.h b/include/linux/timecounter.h
index 2496ad4..6daca06 100644
--- a/include/linux/timecounter.h
+++ b/include/linux/timecounter.h
@@ -62,7 +62,7 @@ struct cyclecounter {
* @frac: accumulated fractional nanoseconds
*/
struct timecounter {
- const struct cyclecounter *cc;
+ struct cyclecounter cc;
u64 cycle_last;
u64 nsec;
u64 mask;
@@ -98,7 +98,6 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta)
/**
* timecounter_init - initialize a time counter
* @tc: Pointer to time counter which is to be initialized/reset
- * @cc: A cycle counter, ready to be used.
* @start_tstamp: Arbitrary initial time stamp.
*
* After this call the current cycle register (roughly) corresponds to
@@ -106,7 +105,6 @@ static inline void timecounter_adjtime(struct timecounter *tc, s64 delta)
* the time stamp counter by the number of elapsed nanoseconds.
*/
extern void timecounter_init(struct timecounter *tc,
- const struct cyclecounter *cc,
u64 start_tstamp);
/**
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 68169e3..3061f44 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -445,7 +445,6 @@ struct hdac_stream {
unsigned long start_wallclk; /* start + minimum wallclk */
unsigned long period_wallclk; /* wallclk for period */
struct timecounter tc;
- struct cyclecounter cc;
int delay_negative_threshold;
struct list_head list;
diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c
index 8afd789..7919acb 100644
--- a/kernel/time/timecounter.c
+++ b/kernel/time/timecounter.c
@@ -18,11 +18,10 @@
#include <linux/export.h>
#include <linux/timecounter.h>
-void timecounter_init(struct timecounter *tc,
- const struct cyclecounter *cc,
- u64 start_tstamp)
+void timecounter_init(struct timecounter *tc, u64 start_tstamp)
{
- tc->cc = cc;
+ struct cyclecounter *cc = &tc->cc;
+
tc->cycle_last = cc->read(cc);
tc->nsec = start_tstamp;
tc->mask = (1ULL << cc->shift) - 1;
@@ -43,17 +42,18 @@ void timecounter_init(struct timecounter *tc,
*/
static u64 timecounter_read_delta(struct timecounter *tc)
{
+ struct cyclecounter *cc = &tc->cc;
u64 cycle_now, cycle_delta;
u64 ns_offset;
/* read cycle counter: */
- cycle_now = tc->cc->read(tc->cc);
+ cycle_now = cc->read(cc);
/* calculate the delta since the last timecounter_read_delta(): */
- cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
+ cycle_delta = (cycle_now - tc->cycle_last) & cc->mask;
/* convert to nanoseconds: */
- ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
+ ns_offset = cyclecounter_cyc2ns(cc, cycle_delta,
tc->mask, &tc->frac);
/* update time stamp of timecounter_read_delta() call: */
@@ -89,10 +89,10 @@ static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
return ns;
}
-u64 timecounter_cyc2time(struct timecounter *tc,
- u64 cycle_tstamp)
+u64 timecounter_cyc2time(struct timecounter *tc, u64 cycle_tstamp)
{
- u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
+ struct cyclecounter *cc = &tc->cc;
+ u64 delta = (cycle_tstamp - tc->cycle_last) & cc->mask;
u64 nsec = tc->nsec, frac = tc->frac;
/*
@@ -100,11 +100,11 @@ u64 timecounter_cyc2time(struct timecounter *tc,
* than tc->cycle_last, detect when it is too far in the
* future and treat it as old time stamp instead.
*/
- if (delta > tc->cc->mask / 2) {
- delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
- nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
+ if (delta > cc->mask / 2) {
+ delta = (tc->cycle_last - cycle_tstamp) & cc->mask;
+ nsec -= cc_cyc2ns_backwards(cc, delta, tc->mask, frac);
} else {
- nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
+ nsec += cyclecounter_cyc2ns(cc, delta, tc->mask, &frac);
}
return nsec;
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index e1472c7..9426c1a 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -467,7 +467,8 @@ int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
static u64 azx_cc_read(const struct cyclecounter *cc)
{
- struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream, cc);
+ struct hdac_stream *azx_dev = container_of(cc, struct hdac_stream,
+ tc.cc);
return snd_hdac_chip_readl(azx_dev->bus, WALLCLK);
}
@@ -476,7 +477,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev,
bool force, u64 last)
{
struct timecounter *tc = &azx_dev->tc;
- struct cyclecounter *cc = &azx_dev->cc;
+ struct cyclecounter *cc = &azx_dev->tc.cc;
u64 nsec;
cc->read = azx_cc_read;
@@ -496,7 +497,7 @@ static void azx_timecounter_init(struct hdac_stream *azx_dev,
cc->shift = 0;
nsec = 0; /* audio time is elapsed time since trigger */
- timecounter_init(tc, cc, nsec);
+ timecounter_init(tc, nsec);
if (force) {
/*
* force timecounter to use predefined value,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4151250..f3505bd 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -53,7 +53,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
u64 kvm_phys_timer_read(void)
{
- return timecounter->cc->read(timecounter->cc);
+ return timecounter->cc.read(&timecounter->cc);
}
static void soft_timer_start(struct hrtimer *hrt, u64 ns)
@@ -138,7 +138,7 @@ static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
if (now < cval) {
u64 ns;
- ns = cyclecounter_cyc2ns(timecounter->cc,
+ ns = cyclecounter_cyc2ns(&timecounter->cc,
cval - now,
timecounter->mask,
&timecounter->frac);
@@ -734,7 +734,7 @@ int kvm_timer_hyp_init(void)
info = arch_timer_get_kvm_info();
timecounter = &info->timecounter;
- if (!timecounter->cc) {
+ if (!timecounter->cc.mask) {
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
return -ENODEV;
}
--
1.9.1
4
4
I have the following sound devices:
hwinfo --sound
Absolute path to 'hwinfo' is '/usr/sbin/hwinfo', so running it may require
superuser privileges (eg. root).
freek@eiktum:~> /usr/sbin/hwinfo --sound
16: PCI 14.2: 0403 Audio device
[Created at pci.378]
Unique ID: 5Dex.BDUuYMOWyw7
SysFS ID: /devices/pci0000:00/0000:00:14.2
SysFS BusID: 0000:00:14.2
Hardware Class: sound
Model: "ATI SBx00 Azalia (Intel HDA)"
Vendor: pci 0x1002 "ATI Technologies Inc"
Device: pci 0x4383 "SBx00 Azalia (Intel HDA)"
SubVendor: pci 0x1002 "ATI Technologies Inc"
SubDevice: pci 0x4383
Revision: 0x40
Memory Range: 0xfe6f8000-0xfe6fbfff (rw,non-prefetchable)
IRQ: 10 (no events)
Module Alias: "pci:v00001002d00004383sv00001002sd00004383bc04sc03i00"
Driver Info #0:
Driver Status: snd_hda_intel is active
Driver Activation Cmd: "modprobe snd_hda_intel"
Config Status: cfg=yes, avail=yes, need=no, active=unknown
26: PCI 500.1: 0403 Audio device
[Created at pci.378]
Unique ID: 5yAR.dhjYDcGDBr3
Parent ID: _Znp.ZJmKoWxd6BF
SysFS ID: /devices/pci0000:00/0000:00:02.0/0000:05:00.1
SysFS BusID: 0000:05:00.1
Hardware Class: sound
Model: "ATI RV770 HDMI Audio [Radeon HD 4850/4870]"
Vendor: pci 0x1002 "ATI Technologies Inc"
Device: pci 0xaa30 "RV770 HDMI Audio [Radeon HD 4850/4870]"
SubVendor: pci 0x1787 "Hightech Information System Ltd."
SubDevice: pci 0xaa30
Driver: "snd_hda_intel"
Driver Modules: "snd_hda_intel"
Memory Range: 0xfe9ec000-0xfe9effff (rw,non-prefetchable)
IRQ: 36 (1104 events)
Module Alias: "pci:v00001002d0000AA30sv00001787sd0000AA30bc04sc03i00"
Driver Info #0:
Driver Status: snd_hda_intel is active
Driver Activation Cmd: "modprobe snd_hda_intel"
Config Status: cfg=yes, avail=yes, need=no, active=unknown
Attached to: #18 (PCI bridge)
I have my monitor connected via HDMI and that monitor has speakers. The
monitor is:
hwinfo --monitor
29: None 00.0: 10002 LCD Monitor
[Created at monitor.125]
Unique ID: rdCR.ukgc1_4VzS0
Parent ID: Ddhb.zvQlrOmSRQ8
Hardware Class: monitor
Model: "R231"
Vendor: ACR
Device: eisa 0x0504 "R231"
Serial ID: "T6GEE0012400"
Resolution: 720x400@70Hz
Resolution: 640x480@60Hz
Resolution: 640x480@67Hz
Resolution: 800x600@56Hz
Resolution: 800x600@60Hz
Resolution: 1024x768@60Hz
Resolution: 1024x768@70Hz
Resolution: 1152x864@75Hz
Resolution: 1280x1024@60Hz
Resolution: 1280x720@60Hz
Resolution: 1920x1080@60Hz
Size: 509x286 mm
Year of Manufacture: 2016
Week of Manufacture: 4
Detailed Timings #0:
Resolution: 1920x1080
Horizontal: 1920 2008 2052 2200 (+88 +132 +280) +hsync
Vertical: 1080 1084 1089 1125 (+4 +9 +45) +vsync
Frequencies: 148.50 MHz, 67.50 kHz, 60.00 Hz
Driver Info #0:
Max. Resolution: 1920x1080
Vert. Sync Range: 56-75 Hz
Hor. Sync Range: 31-75 kHz
Bandwidth: 148 MHz
Config Status: cfg=no, avail=yes, need=no, active=unknown
Attached to: #8 (VGA compatible controller)
The sound is working OK, however the problem is that the sound is delayed by
about one second compared to the picture on the screen.
Most visible/hearable by using Musescore, where a music note is highlighted
when it is played. Using VGA and the other sound card there is no delay.
alsa-info.sh
--
fr.gr.
member openSUSE
Freek de Kruijf
2
2
04 Jan '18
Register "micbias1" and "micbias2" to supply widegts as modern drivers do.
Signed-off-by: Bard Liao <bardliao(a)realtek.com>
---
sound/soc/codecs/rt5645.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index cd82302..8f37afd 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -1977,10 +1977,10 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
/* Input Side */
/* micbias */
- SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2,
- RT5645_PWR_MB1_BIT, 0),
- SND_SOC_DAPM_MICBIAS("micbias2", RT5645_PWR_ANLG2,
- RT5645_PWR_MB2_BIT, 0),
+ SND_SOC_DAPM_SUPPLY("micbias1", RT5645_PWR_ANLG2,
+ RT5645_PWR_MB1_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("micbias2", RT5645_PWR_ANLG2,
+ RT5645_PWR_MB2_BIT, 0, NULL, 0),
/* Input Lines */
SND_SOC_DAPM_INPUT("DMIC L1"),
SND_SOC_DAPM_INPUT("DMIC R1"),
--
2.7.4
2
1
Signed-off-by: Ryan Lee <ryans.lee(a)maximintegrated.com>
---
Changes since v1:
* Removed 'codec' from 'max98373_priv' structure
: Now 'max98373_set_clock' function use 'dai->codec.dev' instead of using 'max98373->codec.dev'.
* Removed 'max98373_dai_set_sysclk' function
: This function is not necessary. Removed 'sysclk' from 'max98373_priv' as well.
* Removed 'iface' from 'max98373_priv' structure
: There is no function who refer max98373->iface variable.
* Added SPDX-License-Identifier
.../devicetree/bindings/sound/max98373.txt | 43 +
sound/soc/codecs/Kconfig | 5 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/max98373.c | 974 +++++++++++++++++++++
sound/soc/codecs/max98373.h | 212 +++++
5 files changed, 1236 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/max98373.txt
create mode 100644 sound/soc/codecs/max98373.c
create mode 100644 sound/soc/codecs/max98373.h
diff --git a/Documentation/devicetree/bindings/sound/max98373.txt b/Documentation/devicetree/bindings/sound/max98373.txt
new file mode 100644
index 0000000..22cd259
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/max98373.txt
@@ -0,0 +1,43 @@
+Maxim Integrated MAX98373 Speaker Amplifier
+
+This device supports I2C.
+
+Required properties:
+
+ - compatible : should be one of the following
+ - "maxim,max98373"
+
+ - reg : the I2C address of the device.
+
+Optional properties:
+
+ - maxim,vmon-slot-no : slot number used to send voltage information
+ or in inteleave mode this will be used as
+ interleave slot.
+ slot range : 0 ~ 15, Default : 0
+
+ - maxim,imon-slot-no : slot number used to send current information
+ slot range : 0 ~ 15, Default : 0
+
+ - maxim,spkfb-slot-no : slot number used to send speaker feedback information
+ slot range : 0 ~ 15, Default : 0
+
+ - maxim,interleave-mode : When using two MAX98373 in a system it is
+ possible to create ADC data that that will
+ overflow the frame size. Digital Audio Interleave
+ mode provides a means to output VMON and IMON data
+ from two devices on a single DOUT line when running
+ smaller frames sizes such as 32 BCLKS per LRCLK or
+ 48 BCLKS per LRCLK.
+ Range : 0 (off), 1 (on), Default : 0
+
+Example:
+
+codec: max98373@31 {
+ compatible = "maxim,max98373";
+ reg = <0x31>;
+ maxim,vmon-slot-no = <0>;
+ maxim,imon-slot-no = <1>;
+ maxim,spkfb-slot-no = <2>;
+ maxim,interleave-mode = <0>;
+};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 8b02bc8..9af2588 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -95,6 +95,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MAX98925 if I2C
select SND_SOC_MAX98926 if I2C
select SND_SOC_MAX98927 if I2C
+ select SND_SOC_MAX98373 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9860 if I2C
select SND_SOC_MAX9768 if I2C
@@ -626,6 +627,10 @@ config SND_SOC_MAX98927
tristate "Maxim Integrated MAX98927 Speaker Amplifier"
depends on I2C
+config SND_SOC_MAX98373
+ tristate "Maxim Integrated MAX98373 Speaker Amplifier"
+ depends on I2C
+
config SND_SOC_MAX9850
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 0977349..49db8e9 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -90,6 +90,7 @@ snd-soc-max9867-objs := max9867.o
snd-soc-max98925-objs := max98925.o
snd-soc-max98926-objs := max98926.o
snd-soc-max98927-objs := max98927.o
+snd-soc-max98373-objs := max98373.o
snd-soc-max9850-objs := max9850.o
snd-soc-max9860-objs := max9860.o
snd-soc-mc13783-objs := mc13783.o
@@ -334,6 +335,7 @@ obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o
obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o
+obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c
new file mode 100644
index 0000000..93d6dc7
--- /dev/null
+++ b/sound/soc/codecs/max98373.c
@@ -0,0 +1,974 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2017, Maxim Integrated */
+
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <sound/tlv.h>
+#include "max98373.h"
+
+static struct reg_default max98373_reg[] = {
+ {MAX98373_R2000_SW_RESET, 0x00},
+ {MAX98373_R2001_INT_RAW1, 0x00},
+ {MAX98373_R2002_INT_RAW2, 0x00},
+ {MAX98373_R2003_INT_RAW3, 0x00},
+ {MAX98373_R2004_INT_STATE1, 0x00},
+ {MAX98373_R2005_INT_STATE2, 0x00},
+ {MAX98373_R2006_INT_STATE3, 0x00},
+ {MAX98373_R2007_INT_FLAG1, 0x00},
+ {MAX98373_R2008_INT_FLAG2, 0x00},
+ {MAX98373_R2009_INT_FLAG3, 0x00},
+ {MAX98373_R200A_INT_EN1, 0x00},
+ {MAX98373_R200B_INT_EN2, 0x00},
+ {MAX98373_R200C_INT_EN3, 0x00},
+ {MAX98373_R200D_INT_FLAG_CLR1, 0x00},
+ {MAX98373_R200E_INT_FLAG_CLR2, 0x00},
+ {MAX98373_R200F_INT_FLAG_CLR3, 0x00},
+ {MAX98373_R2010_IRQ_CTRL, 0x00},
+ {MAX98373_R2014_THERM_WARN_THRESH, 0x10},
+ {MAX98373_R2015_THERM_SHDN_THRESH, 0x27},
+ {MAX98373_R2016_THERM_HYSTERESIS, 0x01},
+ {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0},
+ {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00},
+ {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55},
+ {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE},
+ {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF},
+ {MAX98373_R2022_PCM_TX_SRC_1, 0x00},
+ {MAX98373_R2023_PCM_TX_SRC_2, 0x00},
+ {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0},
+ {MAX98373_R2025_AUDIO_IF_MODE, 0x00},
+ {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04},
+ {MAX98373_R2027_PCM_SR_SETUP_1, 0x08},
+ {MAX98373_R2028_PCM_SR_SETUP_2, 0x88},
+ {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00},
+ {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00},
+ {MAX98373_R202B_PCM_RX_EN, 0x00},
+ {MAX98373_R202C_PCM_TX_EN, 0x00},
+ {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00},
+ {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00},
+ {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF},
+ {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF},
+ {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30},
+ {MAX98373_R2034_ICC_TX_CNTL, 0x00},
+ {MAX98373_R2035_ICC_TX_EN, 0x00},
+ {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05},
+ {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00},
+ {MAX98373_R203E_AMP_PATH_GAIN, 0x08},
+ {MAX98373_R203F_AMP_DSP_CFG, 0x02},
+ {MAX98373_R2040_TONE_GEN_CFG, 0x00},
+ {MAX98373_R2041_AMP_CFG, 0x03},
+ {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00},
+ {MAX98373_R2043_AMP_EN, 0x00},
+ {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04},
+ {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00},
+ {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00},
+ {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00},
+ {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00},
+ {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00},
+ {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00},
+ {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00},
+ {MAX98373_R2090_BDE_LVL_HOLD, 0x00},
+ {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00},
+ {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00},
+ {MAX98373_R2097_BDE_L1_THRESH, 0x00},
+ {MAX98373_R2098_BDE_L2_THRESH, 0x00},
+ {MAX98373_R2099_BDE_L3_THRESH, 0x00},
+ {MAX98373_R209A_BDE_L4_THRESH, 0x00},
+ {MAX98373_R209B_BDE_THRESH_HYST, 0x00},
+ {MAX98373_R20A8_BDE_L1_CFG_1, 0x00},
+ {MAX98373_R20A9_BDE_L1_CFG_2, 0x00},
+ {MAX98373_R20AA_BDE_L1_CFG_3, 0x00},
+ {MAX98373_R20AB_BDE_L2_CFG_1, 0x00},
+ {MAX98373_R20AC_BDE_L2_CFG_2, 0x00},
+ {MAX98373_R20AD_BDE_L2_CFG_3, 0x00},
+ {MAX98373_R20AE_BDE_L3_CFG_1, 0x00},
+ {MAX98373_R20AF_BDE_L3_CFG_2, 0x00},
+ {MAX98373_R20B0_BDE_L3_CFG_3, 0x00},
+ {MAX98373_R20B1_BDE_L4_CFG_1, 0x00},
+ {MAX98373_R20B2_BDE_L4_CFG_2, 0x00},
+ {MAX98373_R20B3_BDE_L4_CFG_3, 0x00},
+ {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00},
+ {MAX98373_R20B5_BDE_EN, 0x00},
+ {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00},
+ {MAX98373_R20D1_DHT_CFG, 0x01},
+ {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02},
+ {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03},
+ {MAX98373_R20D4_DHT_EN, 0x00},
+ {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00},
+ {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00},
+ {MAX98373_R20E2_LIMITER_EN, 0x00},
+ {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00},
+ {MAX98373_R20FF_GLOBAL_SHDN, 0x00},
+ {MAX98373_R21FF_REV_ID, 0x42},
+};
+
+static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ unsigned int format = 0;
+ unsigned int invert = 0;
+
+ dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE;
+ break;
+ default:
+ dev_err(codec->dev, "DAI invert mode unsupported\n");
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2026_PCM_CLOCK_RATIO,
+ MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE,
+ invert);
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ format = MAX98373_PCM_FORMAT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format = MAX98373_PCM_FORMAT_LJ;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ format = MAX98373_PCM_FORMAT_TDM_MODE1;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ format = MAX98373_PCM_FORMAT_TDM_MODE0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_MODE_CFG_FORMAT_MASK,
+ format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT);
+
+ return 0;
+}
+
+/* BCLKs per LRCLK */
+static const int bclk_sel_table[] = {
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 320,
+};
+
+static int max98373_get_bclk_sel(int bclk)
+{
+ int i;
+ /* match BCLKs per LRCLK */
+ for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
+ if (bclk_sel_table[i] == bclk)
+ return i + 2;
+ }
+ return 0;
+}
+static int max98373_set_clock(struct snd_soc_codec *codec,
+ struct snd_pcm_hw_params *params)
+{
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ /* BCLK/LRCLK ratio calculation */
+ int blr_clk_ratio = params_channels(params) * max98373->ch_size;
+ int value;
+
+ if (!max98373->tdm_mode) {
+ /* BCLK configuration */
+ value = max98373_get_bclk_sel(blr_clk_ratio);
+ if (!value) {
+ dev_err(codec->dev, "format unsupported %d\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2026_PCM_CLOCK_RATIO,
+ MAX98373_PCM_CLK_SETUP_BSEL_MASK,
+ value);
+ }
+ return 0;
+}
+
+static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ unsigned int sampling_rate = 0;
+ unsigned int chan_sz = 0;
+
+ /* pcm mode configuration */
+ switch (snd_pcm_format_width(params_format(params))) {
+ case 16:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
+ break;
+ case 24:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
+ break;
+ case 32:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
+ break;
+ default:
+ dev_err(codec->dev, "format unsupported %d\n",
+ params_format(params));
+ goto err;
+ }
+
+ max98373->ch_size = snd_pcm_format_width(params_format(params));
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
+
+ dev_dbg(codec->dev, "format supported %d",
+ params_format(params));
+
+ /* sampling rate configuration */
+ switch (params_rate(params)) {
+ case 8000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_8000;
+ break;
+ case 11025:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_11025;
+ break;
+ case 12000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_12000;
+ break;
+ case 16000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_16000;
+ break;
+ case 22050:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_22050;
+ break;
+ case 24000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_24000;
+ break;
+ case 32000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_32000;
+ break;
+ case 44100:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_44100;
+ break;
+ case 48000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
+ break;
+ default:
+ dev_err(codec->dev, "rate %d not supported\n",
+ params_rate(params));
+ goto err;
+ }
+ /* set DAI_SR to correct LRCLK frequency */
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2027_PCM_SR_SETUP_1,
+ MAX98373_PCM_SR_SET1_SR_MASK,
+ sampling_rate);
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2028_PCM_SR_SETUP_2,
+ MAX98373_PCM_SR_SET2_SR_MASK,
+ sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT);
+
+ /* set sampling rate of IV */
+ if (max98373->interleave_mode &&
+ sampling_rate > MAX98373_PCM_SR_SET1_SR_16000)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2028_PCM_SR_SETUP_2,
+ MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
+ sampling_rate - 3);
+ else
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2028_PCM_SR_SETUP_2,
+ MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
+ sampling_rate);
+
+ return max98373_set_clock(codec, params);
+err:
+ return -EINVAL;
+}
+
+static int max98373_dai_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ int bsel = 0;
+ unsigned int chan_sz = 0;
+ unsigned int mask;
+ int x, slot_found;
+
+ max98373->tdm_mode = true;
+
+ /* BCLK configuration */
+ bsel = max98373_get_bclk_sel(slots * slot_width);
+ if (bsel == 0) {
+ dev_err(codec->dev, "BCLK %d not supported\n",
+ slots * slot_width);
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2026_PCM_CLOCK_RATIO,
+ MAX98373_PCM_CLK_SETUP_BSEL_MASK,
+ bsel);
+
+ /* Channel size configuration */
+ switch (slot_width) {
+ case 16:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
+ break;
+ case 24:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
+ break;
+ case 32:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
+ break;
+ default:
+ dev_err(codec->dev, "format unsupported %d\n",
+ slot_width);
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
+
+ /* Rx slot configuration */
+ slot_found = 0;
+ mask = rx_mask;
+ for (x = 0 ; x < 16 ; x++, mask >>= 1) {
+ if (mask & 0x1) {
+ if (slot_found == 0)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
+ MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x);
+ else
+ regmap_write(max98373->regmap,
+ MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2,
+ x);
+ slot_found++;
+ if (slot_found > 1)
+ break;
+ }
+ }
+
+ /* Tx slot Hi-Z configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ ~tx_mask & 0xFF);
+ regmap_write(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ (~tx_mask & 0xFF00) >> 8);
+
+ return 0;
+}
+
+#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000
+
+#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static const struct snd_soc_dai_ops max98373_dai_ops = {
+ .set_fmt = max98373_dai_set_fmt,
+ .hw_params = max98373_dai_hw_params,
+ .set_tdm_slot = max98373_dai_tdm_slot,
+};
+
+static int max98373_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R20FF_GLOBAL_SHDN,
+ MAX98373_GLOBAL_EN_MASK, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R20FF_GLOBAL_SHDN,
+ MAX98373_GLOBAL_EN_MASK, 0);
+ max98373->tdm_mode = 0;
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+static const char * const max98373_switch_text[] = {
+ "Left", "Right", "LeftRight"};
+
+static const struct soc_enum dai_sel_enum =
+ SOC_ENUM_SINGLE(MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
+ MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT,
+ 3, max98373_switch_text);
+
+static const struct snd_kcontrol_new max98373_dai_controls =
+ SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
+
+static const struct snd_kcontrol_new max98373_vi_control =
+ SOC_DAPM_SINGLE("Switch", MAX98373_R202C_PCM_TX_EN, 0, 1, 0);
+
+static const struct snd_kcontrol_new max98373_spkfb_control =
+ SOC_DAPM_SINGLE("Switch", MAX98373_R2043_AMP_EN, 1, 1, 0);
+
+static const struct snd_soc_dapm_widget max98373_dapm_widgets[] = {
+SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback",
+ MAX98373_R202B_PCM_RX_EN, 0, 0, max98373_dac_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
+ &max98373_dai_controls),
+SND_SOC_DAPM_OUTPUT("BE_OUT"),
+SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0,
+ MAX98373_R2047_IV_SENSE_ADC_EN, 0, 0),
+SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0,
+ MAX98373_R2047_IV_SENSE_ADC_EN, 1, 0),
+SND_SOC_DAPM_AIF_OUT("Speaker FB Sense", "HiFi Capture", 0,
+ SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0,
+ &max98373_vi_control),
+SND_SOC_DAPM_SWITCH("SpkFB Sense", SND_SOC_NOPM, 0, 0,
+ &max98373_spkfb_control),
+SND_SOC_DAPM_SIGGEN("VMON"),
+SND_SOC_DAPM_SIGGEN("IMON"),
+SND_SOC_DAPM_SIGGEN("FBMON"),
+};
+
+static DECLARE_TLV_DB_SCALE(max98373_digital_tlv, 0, -50, 0);
+static const DECLARE_TLV_DB_RANGE(max98373_spk_tlv,
+ 0, 8, TLV_DB_SCALE_ITEM(0, 50, 0),
+ 9, 10, TLV_DB_SCALE_ITEM(500, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_spkgain_max_tlv,
+ 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_dht_step_size_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(25, 25, 0),
+ 2, 4, TLV_DB_SCALE_ITEM(100, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_dht_spkgain_min_tlv,
+ 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_dht_rotation_point_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0),
+ 2, 7, TLV_DB_SCALE_ITEM(-200, -100, 0),
+ 8, 9, TLV_DB_SCALE_ITEM(-1000, -200, 0),
+ 10, 11, TLV_DB_SCALE_ITEM(-1500, -300, 0),
+ 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0),
+ 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_limiter_thresh_tlv,
+ 0, 15, TLV_DB_SCALE_ITEM(0, -100, 0),
+);
+
+static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv,
+ 0, 60, TLV_DB_SCALE_ITEM(0, -25, 0),
+);
+
+static bool max98373_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3:
+ case MAX98373_R2010_IRQ_CTRL:
+ case MAX98373_R2014_THERM_WARN_THRESH
+ ... MAX98373_R2018_THERM_FOLDBACK_EN:
+ case MAX98373_R201E_PIN_DRIVE_STRENGTH
+ ... MAX98373_R2036_SOUNDWIRE_CTRL:
+ case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN:
+ case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG
+ ... MAX98373_R2047_IV_SENSE_ADC_EN:
+ case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE
+ ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN:
+ case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE:
+ case MAX98373_R2097_BDE_L1_THRESH
+ ... MAX98373_R209B_BDE_THRESH_HYST:
+ case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3:
+ case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK:
+ case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN:
+ case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN:
+ case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG
+ ... MAX98373_R20FF_GLOBAL_SHDN:
+ case MAX98373_R21FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
+};
+
+static bool max98373_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3:
+ case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK:
+ case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK:
+ case MAX98373_R20B6_BDE_CUR_STATE_READBACK:
+ case MAX98373_R21FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const char * const max98373_output_voltage_lvl_text[] = {
+ "5.43V", "6.09V", "6.83V", "7.67V", "8.60V",
+ "9.65V", "10.83V", "12.15V", "13.63V", "15.29V"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_out_volt_enum,
+ MAX98373_R203E_AMP_PATH_GAIN, 0,
+ max98373_output_voltage_lvl_text);
+
+static const char * const max98373_dht_attack_rate_text[] = {
+ "17.5us", "35us", "70us", "140us",
+ "280us", "560us", "1120us", "2240us"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_dht_attack_rate_enum,
+ MAX98373_R20D2_DHT_ATTACK_CFG, 0,
+ max98373_dht_attack_rate_text);
+
+static const char * const max98373_dht_release_rate_text[] = {
+ "45ms", "225ms", "450ms", "1150ms",
+ "2250ms", "3100ms", "4500ms", "6750ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_dht_release_rate_enum,
+ MAX98373_R20D3_DHT_RELEASE_CFG, 0,
+ max98373_dht_release_rate_text);
+
+static const char * const max98373_limiter_attack_rate_text[] = {
+ "10us", "20us", "40us", "80us",
+ "160us", "320us", "640us", "1.28ms",
+ "2.56ms", "5.12ms", "10.24ms", "20.48ms",
+ "40.96ms", "81.92ms", "16.384ms", "32.768ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_limiter_attack_rate_enum,
+ MAX98373_R20E1_LIMITER_ATK_REL_RATES, 4,
+ max98373_limiter_attack_rate_text);
+
+static const char * const max98373_limiter_release_rate_text[] = {
+ "40us", "80us", "160us", "320us",
+ "640us", "1.28ms", "2.56ms", "5.120ms",
+ "10.24ms", "20.48ms", "40.96ms", "81.92ms",
+ "163.84ms", "327.68ms", "655.36ms", "1310.72ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_limiter_release_rate_enum,
+ MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0,
+ max98373_limiter_release_rate_text);
+
+static const char * const max98373_ADC_samplerate_text[] = {
+ "333kHz", "192kHz", "64kHz", "48kHz"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_adc_samplerate_enum,
+ MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0,
+ max98373_ADC_samplerate_text);
+
+static const struct snd_kcontrol_new max98373_snd_controls[] = {
+SOC_SINGLE("Digital Vol Sel Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_VOL_SEL_SHIFT, 1, 0),
+SOC_SINGLE("Volume Location Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_VOL_SEL_SHIFT, 1, 0),
+SOC_SINGLE("Ramp Up Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0),
+SOC_SINGLE("Ramp Down Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0),
+SOC_SINGLE("CLK Monitor Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG,
+ MAX98373_CLOCK_MON_SHIFT, 1, 0),
+SOC_SINGLE("Dither Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_DITH_SHIFT, 1, 0),
+SOC_SINGLE("DC Blocker Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_DCBLK_SHIFT, 1, 0),
+SOC_SINGLE_TLV("Digital Volume", MAX98373_R203D_AMP_DIG_VOL_CTRL,
+ 0, 0x7F, 0, max98373_digital_tlv),
+SOC_SINGLE_TLV("Speaker Volume", MAX98373_R203E_AMP_PATH_GAIN,
+ MAX98373_SPK_DIGI_GAIN_SHIFT, 10, 0, max98373_spk_tlv),
+SOC_SINGLE_TLV("FS Max Volume", MAX98373_R203E_AMP_PATH_GAIN,
+ MAX98373_FS_GAIN_MAX_SHIFT, 9, 0, max98373_spkgain_max_tlv),
+SOC_ENUM("Output Voltage", max98373_out_volt_enum),
+/* Dynamic Headroom Tracking */
+SOC_SINGLE("DHT Switch", MAX98373_R20D4_DHT_EN,
+ MAX98373_DHT_EN_SHIFT, 1, 0),
+SOC_SINGLE_TLV("DHT Gain Min", MAX98373_R20D1_DHT_CFG,
+ MAX98373_DHT_SPK_GAIN_MIN_SHIFT, 9, 0, max98373_dht_spkgain_min_tlv),
+SOC_SINGLE_TLV("DHT Rot Pnt", MAX98373_R20D1_DHT_CFG,
+ MAX98373_DHT_ROT_PNT_SHIFT, 15, 0, max98373_dht_rotation_point_tlv),
+SOC_SINGLE_TLV("DHT Attack Step", MAX98373_R20D2_DHT_ATTACK_CFG,
+ MAX98373_DHT_ATTACK_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv),
+SOC_SINGLE_TLV("DHT Release Step", MAX98373_R20D3_DHT_RELEASE_CFG,
+ MAX98373_DHT_RELEASE_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv),
+SOC_ENUM("DHT Attack Rate", max98373_dht_attack_rate_enum),
+SOC_ENUM("DHT Release Rate", max98373_dht_release_rate_enum),
+/* ADC configuration */
+SOC_SINGLE("ADC PVDD CH Switch", MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0, 1, 0),
+SOC_SINGLE("ADC PVDD FLT Switch", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG,
+ MAX98373_FLT_EN_SHIFT, 1, 0),
+SOC_SINGLE("ADC TEMP FLT Switch", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG,
+ MAX98373_FLT_EN_SHIFT, 1, 0),
+SOC_SINGLE("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0),
+SOC_SINGLE("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0),
+SOC_SINGLE("ADC PVDD FLT Coeff", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG,
+ 0, 0x3, 0),
+SOC_SINGLE("ADC TEMP FLT Coeff", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG,
+ 0, 0x3, 0),
+SOC_ENUM("ADC SampleRate", max98373_adc_samplerate_enum),
+/* Brownout Detection Engine */
+SOC_SINGLE("BDE Switch", MAX98373_R20B5_BDE_EN, MAX98373_BDE_EN_SHIFT, 1, 0),
+SOC_SINGLE("BDE LVL4 Mute Switch", MAX98373_R20B2_BDE_L4_CFG_2,
+ MAX98373_LVL4_MUTE_EN_SHIFT, 1, 0),
+SOC_SINGLE("BDE LVL4 Hold Switch", MAX98373_R20B2_BDE_L4_CFG_2,
+ MAX98373_LVL4_HOLD_EN_SHIFT, 1, 0),
+SOC_SINGLE("BDE LVL1 Thresh", MAX98373_R2097_BDE_L1_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE LVL2 Thresh", MAX98373_R2098_BDE_L2_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE LVL3 Thresh", MAX98373_R2099_BDE_L3_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE LVL4 Thresh", MAX98373_R209A_BDE_L4_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0),
+SOC_SINGLE("BDE Clip Mode Switch", MAX98373_R2092_BDE_CLIPPER_MODE, 0, 1, 0),
+SOC_SINGLE("BDE Thresh Hysteresis", MAX98373_R209B_BDE_THRESH_HYST, 0, 0xFF, 0),
+SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0),
+SOC_SINGLE("BDE Attack Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 4, 0xF, 0),
+SOC_SINGLE("BDE Release Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0, 0xF, 0),
+SOC_SINGLE_TLV("BDE LVL1 Clip Thresh", MAX98373_R20A9_BDE_L1_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL2 Clip Thresh", MAX98373_R20AC_BDE_L2_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL3 Clip Thresh", MAX98373_R20AF_BDE_L3_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL4 Clip Thresh", MAX98373_R20B2_BDE_L4_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL1 Clip Gain Reduct", MAX98373_R20AA_BDE_L1_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL2 Clip Gain Reduct", MAX98373_R20AD_BDE_L2_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL3 Clip Gain Reduct", MAX98373_R20B0_BDE_L3_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL4 Clip Gain Reduct", MAX98373_R20B3_BDE_L4_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL1 Limiter Thresh", MAX98373_R20A8_BDE_L1_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+SOC_SINGLE_TLV("BDE LVL2 Limiter Thresh", MAX98373_R20AB_BDE_L2_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+SOC_SINGLE_TLV("BDE LVL3 Limiter Thresh", MAX98373_R20AE_BDE_L3_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+SOC_SINGLE_TLV("BDE LVL4 Limiter Thresh", MAX98373_R20B1_BDE_L4_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+/* Limiter */
+SOC_SINGLE("Limiter Switch", MAX98373_R20E2_LIMITER_EN,
+ MAX98373_LIMITER_EN_SHIFT, 1, 0),
+SOC_SINGLE("Limiter Src Switch", MAX98373_R20E0_LIMITER_THRESH_CFG,
+ MAX98373_LIMITER_THRESH_SRC_SHIFT, 1, 0),
+SOC_SINGLE_TLV("Limiter Thresh", MAX98373_R20E0_LIMITER_THRESH_CFG,
+ MAX98373_LIMITER_THRESH_SHIFT, 15, 0, max98373_limiter_thresh_tlv),
+SOC_ENUM("Limiter Attack Rate", max98373_limiter_attack_rate_enum),
+SOC_ENUM("Limiter Release Rate", max98373_limiter_release_rate_enum),
+};
+
+static const struct snd_soc_dapm_route max98373_audio_map[] = {
+ /* Plabyack */
+ {"DAI Sel Mux", "Left", "Amp Enable"},
+ {"DAI Sel Mux", "Right", "Amp Enable"},
+ {"DAI Sel Mux", "LeftRight", "Amp Enable"},
+ {"BE_OUT", NULL, "DAI Sel Mux"},
+ /* Capture */
+ { "VI Sense", "Switch", "VMON" },
+ { "VI Sense", "Switch", "IMON" },
+ { "SpkFB Sense", "Switch", "FBMON" },
+ { "Voltage Sense", NULL, "VI Sense" },
+ { "Current Sense", NULL, "VI Sense" },
+ { "Speaker FB Sense", NULL, "SpkFB Sense" },
+};
+
+static struct snd_soc_dai_driver max98373_dai[] = {
+ {
+ .name = "max98373-aif1",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98373_RATES,
+ .formats = MAX98373_FORMATS,
+ },
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98373_RATES,
+ .formats = MAX98373_FORMATS,
+ },
+ .ops = &max98373_dai_ops,
+ }
+};
+
+static int max98373_probe(struct snd_soc_codec *codec)
+{
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+
+ codec->control_data = max98373->regmap;
+
+ /* Software Reset */
+ regmap_write(max98373->regmap,
+ MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
+
+ /* IV default slot configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ 0xFF);
+ regmap_write(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ 0xFF);
+ /* L/R mix configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
+ 0x80);
+ regmap_write(max98373->regmap,
+ MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2,
+ 0x1);
+ /* Set inital volume (0dB) */
+ regmap_write(max98373->regmap,
+ MAX98373_R203D_AMP_DIG_VOL_CTRL,
+ 0x00);
+ regmap_write(max98373->regmap,
+ MAX98373_R203E_AMP_PATH_GAIN,
+ 0x00);
+ /* Enable DC blocker */
+ regmap_write(max98373->regmap,
+ MAX98373_R203F_AMP_DSP_CFG,
+ 0x3);
+ /* Enable IMON VMON DC blocker */
+ regmap_write(max98373->regmap,
+ MAX98373_R2046_IV_SENSE_ADC_DSP_CFG,
+ 0x7);
+ /* voltage, current slot configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2022_PCM_TX_SRC_1,
+ (max98373->i_slot << MAX98373_PCM_TX_CH_SRC_A_I_SHIFT |
+ max98373->v_slot) & 0xFF);
+ if (max98373->v_slot < 8)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ 1 << max98373->v_slot, 0);
+ else
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ 1 << (max98373->v_slot - 8), 0);
+
+ if (max98373->i_slot < 8)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ 1 << max98373->i_slot, 0);
+ else
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ 1 << (max98373->i_slot - 8), 0);
+
+ /* speaker feedback slot configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2023_PCM_TX_SRC_2,
+ max98373->spkfb_slot & 0xFF);
+
+ /* Set interleave mode */
+ if (max98373->interleave_mode)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_TX_CH_INTERLEAVE_MASK,
+ MAX98373_PCM_TX_CH_INTERLEAVE_MASK);
+
+ /* Speaker enable */
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2043_AMP_EN,
+ MAX98373_SPK_EN_MASK, 1);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max98373_suspend(struct device *dev)
+{
+ struct max98373_priv *max98373 = dev_get_drvdata(dev);
+
+ regcache_cache_only(max98373->regmap, true);
+ regcache_mark_dirty(max98373->regmap);
+ return 0;
+}
+static int max98373_resume(struct device *dev)
+{
+ struct max98373_priv *max98373 = dev_get_drvdata(dev);
+
+ regmap_write(max98373->regmap,
+ MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
+ regcache_cache_only(max98373->regmap, false);
+ regcache_sync(max98373->regmap);
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops max98373_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume)
+};
+
+static const struct snd_soc_codec_driver soc_codec_dev_max98373 = {
+ .probe = max98373_probe,
+ .component_driver = {
+ .controls = max98373_snd_controls,
+ .num_controls = ARRAY_SIZE(max98373_snd_controls),
+ .dapm_widgets = max98373_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(max98373_dapm_widgets),
+ .dapm_routes = max98373_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(max98373_audio_map),
+ },
+};
+
+static const struct regmap_config max98373_regmap = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = MAX98373_R21FF_REV_ID,
+ .reg_defaults = max98373_reg,
+ .num_reg_defaults = ARRAY_SIZE(max98373_reg),
+ .readable_reg = max98373_readable_register,
+ .volatile_reg = max98373_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static void max98373_slot_config(struct i2c_client *i2c,
+ struct max98373_priv *max98373)
+{
+ int value;
+ struct device *dev = &i2c->dev;
+
+ if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value))
+ max98373->v_slot = value & 0xF;
+ else
+ max98373->v_slot = 0;
+
+ if (!device_property_read_u32(dev, "maxim,imon-slot-no", &value))
+ max98373->i_slot = value & 0xF;
+ else
+ max98373->i_slot = 1;
+
+ if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value))
+ max98373->spkfb_slot = value & 0xF;
+ else
+ max98373->spkfb_slot = 2;
+}
+
+static int max98373_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+
+ int ret = 0, value;
+ int reg = 0;
+ struct max98373_priv *max98373 = NULL;
+
+ max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL);
+
+ if (!max98373) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ i2c_set_clientdata(i2c, max98373);
+
+ /* update interleave mode info */
+ if (!device_property_read_u32(&i2c->dev,
+ "maxim,interleave_mode", &value)) {
+ if (value > 0)
+ max98373->interleave_mode = 1;
+ else
+ max98373->interleave_mode = 0;
+ } else
+ max98373->interleave_mode = 0;
+
+ /* regmap initialization */
+ max98373->regmap
+ = devm_regmap_init_i2c(i2c, &max98373_regmap);
+ if (IS_ERR(max98373->regmap)) {
+ ret = PTR_ERR(max98373->regmap);
+ dev_err(&i2c->dev,
+ "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
+ /* Check Revision ID */
+ ret = regmap_read(max98373->regmap,
+ MAX98373_R21FF_REV_ID, ®);
+ if (ret < 0) {
+ dev_err(&i2c->dev,
+ "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID);
+ return ret;
+ }
+ dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg);
+
+ /* voltage/current slot configuration */
+ max98373_slot_config(i2c, max98373);
+
+ /* codec registeration */
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98373,
+ max98373_dai, ARRAY_SIZE(max98373_dai));
+ if (ret < 0)
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+
+ return ret;
+}
+
+static int max98373_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id max98373_i2c_id[] = {
+ { "max98373", 0},
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, max98373_i2c_id);
+
+#if defined(CONFIG_OF)
+static const struct of_device_id max98373_of_match[] = {
+ { .compatible = "maxim,max98373", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max98373_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id max98373_acpi_match[] = {
+ { "MX98373", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, max98373_acpi_match);
+#endif
+
+static struct i2c_driver max98373_i2c_driver = {
+ .driver = {
+ .name = "max98373",
+ .of_match_table = of_match_ptr(max98373_of_match),
+ .acpi_match_table = ACPI_PTR(max98373_acpi_match),
+ .pm = &max98373_pm,
+ },
+ .probe = max98373_i2c_probe,
+ .remove = max98373_i2c_remove,
+ .id_table = max98373_i2c_id,
+};
+
+module_i2c_driver(max98373_i2c_driver)
+
+MODULE_DESCRIPTION("ALSA SoC MAX98373 driver");
+MODULE_AUTHOR("Ryan Lee <ryans.lee(a)maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h
new file mode 100644
index 0000000..d0b359d
--- /dev/null
+++ b/sound/soc/codecs/max98373.h
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2017, Maxim Integrated */
+#ifndef _MAX98373_H
+#define _MAX98373_H
+
+#define MAX98373_R2000_SW_RESET 0x2000
+#define MAX98373_R2001_INT_RAW1 0x2001
+#define MAX98373_R2002_INT_RAW2 0x2002
+#define MAX98373_R2003_INT_RAW3 0x2003
+#define MAX98373_R2004_INT_STATE1 0x2004
+#define MAX98373_R2005_INT_STATE2 0x2005
+#define MAX98373_R2006_INT_STATE3 0x2006
+#define MAX98373_R2007_INT_FLAG1 0x2007
+#define MAX98373_R2008_INT_FLAG2 0x2008
+#define MAX98373_R2009_INT_FLAG3 0x2009
+#define MAX98373_R200A_INT_EN1 0x200A
+#define MAX98373_R200B_INT_EN2 0x200B
+#define MAX98373_R200C_INT_EN3 0x200C
+#define MAX98373_R200D_INT_FLAG_CLR1 0x200D
+#define MAX98373_R200E_INT_FLAG_CLR2 0x200E
+#define MAX98373_R200F_INT_FLAG_CLR3 0x200F
+#define MAX98373_R2010_IRQ_CTRL 0x2010
+#define MAX98373_R2014_THERM_WARN_THRESH 0x2014
+#define MAX98373_R2015_THERM_SHDN_THRESH 0x2015
+#define MAX98373_R2016_THERM_HYSTERESIS 0x2016
+#define MAX98373_R2017_THERM_FOLDBACK_SET 0x2017
+#define MAX98373_R2018_THERM_FOLDBACK_EN 0x2018
+#define MAX98373_R201E_PIN_DRIVE_STRENGTH 0x201E
+#define MAX98373_R2020_PCM_TX_HIZ_EN_1 0x2020
+#define MAX98373_R2021_PCM_TX_HIZ_EN_2 0x2021
+#define MAX98373_R2022_PCM_TX_SRC_1 0x2022
+#define MAX98373_R2023_PCM_TX_SRC_2 0x2023
+#define MAX98373_R2024_PCM_DATA_FMT_CFG 0x2024
+#define MAX98373_R2025_AUDIO_IF_MODE 0x2025
+#define MAX98373_R2026_PCM_CLOCK_RATIO 0x2026
+#define MAX98373_R2027_PCM_SR_SETUP_1 0x2027
+#define MAX98373_R2028_PCM_SR_SETUP_2 0x2028
+#define MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 0x2029
+#define MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2 0x202A
+#define MAX98373_R202B_PCM_RX_EN 0x202B
+#define MAX98373_R202C_PCM_TX_EN 0x202C
+#define MAX98373_R202E_ICC_RX_CH_EN_1 0x202E
+#define MAX98373_R202F_ICC_RX_CH_EN_2 0x202F
+#define MAX98373_R2030_ICC_TX_HIZ_EN_1 0x2030
+#define MAX98373_R2031_ICC_TX_HIZ_EN_2 0x2031
+#define MAX98373_R2032_ICC_LINK_EN_CFG 0x2032
+#define MAX98373_R2034_ICC_TX_CNTL 0x2034
+#define MAX98373_R2035_ICC_TX_EN 0x2035
+#define MAX98373_R2036_SOUNDWIRE_CTRL 0x2036
+#define MAX98373_R203D_AMP_DIG_VOL_CTRL 0x203D
+#define MAX98373_R203E_AMP_PATH_GAIN 0x203E
+#define MAX98373_R203F_AMP_DSP_CFG 0x203F
+#define MAX98373_R2040_TONE_GEN_CFG 0x2040
+#define MAX98373_R2041_AMP_CFG 0x2041
+#define MAX98373_R2042_AMP_EDGE_RATE_CFG 0x2042
+#define MAX98373_R2043_AMP_EN 0x2043
+#define MAX98373_R2046_IV_SENSE_ADC_DSP_CFG 0x2046
+#define MAX98373_R2047_IV_SENSE_ADC_EN 0x2047
+#define MAX98373_R2051_MEAS_ADC_SAMPLING_RATE 0x2051
+#define MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG 0x2052
+#define MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG 0x2053
+#define MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK 0x2054
+#define MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK 0x2055
+#define MAX98373_R2056_MEAS_ADC_PVDD_CH_EN 0x2056
+#define MAX98373_R2090_BDE_LVL_HOLD 0x2090
+#define MAX98373_R2091_BDE_GAIN_ATK_REL_RATE 0x2091
+#define MAX98373_R2092_BDE_CLIPPER_MODE 0x2092
+#define MAX98373_R2097_BDE_L1_THRESH 0x2097
+#define MAX98373_R2098_BDE_L2_THRESH 0x2098
+#define MAX98373_R2099_BDE_L3_THRESH 0x2099
+#define MAX98373_R209A_BDE_L4_THRESH 0x209A
+#define MAX98373_R209B_BDE_THRESH_HYST 0x209B
+#define MAX98373_R20A8_BDE_L1_CFG_1 0x20A8
+#define MAX98373_R20A9_BDE_L1_CFG_2 0x20A9
+#define MAX98373_R20AA_BDE_L1_CFG_3 0x20AA
+#define MAX98373_R20AB_BDE_L2_CFG_1 0x20AB
+#define MAX98373_R20AC_BDE_L2_CFG_2 0x20AC
+#define MAX98373_R20AD_BDE_L2_CFG_3 0x20AD
+#define MAX98373_R20AE_BDE_L3_CFG_1 0x20AE
+#define MAX98373_R20AF_BDE_L3_CFG_2 0x20AF
+#define MAX98373_R20B0_BDE_L3_CFG_3 0x20B0
+#define MAX98373_R20B1_BDE_L4_CFG_1 0x20B1
+#define MAX98373_R20B2_BDE_L4_CFG_2 0x20B2
+#define MAX98373_R20B3_BDE_L4_CFG_3 0x20B3
+#define MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE 0x20B4
+#define MAX98373_R20B5_BDE_EN 0x20B5
+#define MAX98373_R20B6_BDE_CUR_STATE_READBACK 0x20B6
+#define MAX98373_R20D1_DHT_CFG 0x20D1
+#define MAX98373_R20D2_DHT_ATTACK_CFG 0x20D2
+#define MAX98373_R20D3_DHT_RELEASE_CFG 0x20D3
+#define MAX98373_R20D4_DHT_EN 0x20D4
+#define MAX98373_R20E0_LIMITER_THRESH_CFG 0x20E0
+#define MAX98373_R20E1_LIMITER_ATK_REL_RATES 0x20E1
+#define MAX98373_R20E2_LIMITER_EN 0x20E2
+#define MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG 0x20FE
+#define MAX98373_R20FF_GLOBAL_SHDN 0x20FF
+#define MAX98373_R21FF_REV_ID 0x21FF
+
+/* MAX98373_R2022_PCM_TX_SRC_1 */
+#define MAX98373_PCM_TX_CH_SRC_A_V_SHIFT (0)
+#define MAX98373_PCM_TX_CH_SRC_A_I_SHIFT (4)
+
+/* MAX98373_R2024_PCM_DATA_FMT_CFG */
+#define MAX98373_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3)
+#define MAX98373_PCM_MODE_CFG_FORMAT_SHIFT (3)
+#define MAX98373_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 2)
+#define MAX98373_PCM_FORMAT_I2S (0x0 << 0)
+#define MAX98373_PCM_FORMAT_LJ (0x1 << 0)
+#define MAX98373_PCM_FORMAT_TDM_MODE0 (0x3 << 0)
+#define MAX98373_PCM_FORMAT_TDM_MODE1 (0x4 << 0)
+#define MAX98373_PCM_FORMAT_TDM_MODE2 (0x5 << 0)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6)
+
+/* MAX98373_R2026_PCM_CLOCK_RATIO */
+#define MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 4)
+#define MAX98373_PCM_CLK_SETUP_BSEL_MASK (0xF << 0)
+
+/* MAX98373_R2027_PCM_SR_SETUP_1 */
+#define MAX98373_PCM_SR_SET1_SR_MASK (0xF << 0)
+#define MAX98373_PCM_SR_SET1_SR_8000 (0x0 << 0)
+#define MAX98373_PCM_SR_SET1_SR_11025 (0x1 << 0)
+#define MAX98373_PCM_SR_SET1_SR_12000 (0x2 << 0)
+#define MAX98373_PCM_SR_SET1_SR_16000 (0x3 << 0)
+#define MAX98373_PCM_SR_SET1_SR_22050 (0x4 << 0)
+#define MAX98373_PCM_SR_SET1_SR_24000 (0x5 << 0)
+#define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0)
+#define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0)
+#define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0)
+
+/* MAX98373_R2028_PCM_SR_SETUP_2 */
+#define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4)
+#define MAX98373_PCM_SR_SET2_SR_SHIFT (4)
+#define MAX98373_PCM_SR_SET2_IVADC_SR_MASK (0xF << 0)
+
+/* MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 */
+#define MAX98373_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6)
+#define MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6)
+#define MAX98373_PCM_TO_SPK_CH0_SRC_MASK (0xF << 0)
+
+/* MAX98373_R203E_AMP_PATH_GAIN */
+#define MAX98373_SPK_DIGI_GAIN_MASK (0xF << 4)
+#define MAX98373_SPK_DIGI_GAIN_SHIFT (4)
+#define MAX98373_FS_GAIN_MAX_MASK (0xF << 0)
+#define MAX98373_FS_GAIN_MAX_SHIFT (0)
+
+/* MAX98373_R203F_AMP_DSP_CFG */
+#define MAX98373_AMP_DSP_CFG_DCBLK_SHIFT (0)
+#define MAX98373_AMP_DSP_CFG_DITH_SHIFT (1)
+#define MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT (2)
+#define MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT (3)
+#define MAX98373_AMP_DSP_CFG_DAC_INV_SHIFT (5)
+#define MAX98373_AMP_VOL_SEL_SHIFT (7)
+
+/* MAX98373_R2043_AMP_EN */
+#define MAX98373_SPKFB_EN_MASK (0x1 << 1)
+#define MAX98373_SPK_EN_MASK (0x1 << 0)
+#define MAX98373_SPKFB_EN_SHIFT (1)
+
+/*MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG */
+#define MAX98373_FLT_EN_SHIFT (4)
+
+/* MAX98373_R20B2_BDE_L4_CFG_2 */
+#define MAX98373_LVL4_MUTE_EN_SHIFT (7)
+#define MAX98373_LVL4_HOLD_EN_SHIFT (6)
+
+/* MAX98373_R20B5_BDE_EN */
+#define MAX98373_BDE_EN_SHIFT (0)
+
+/* MAX98373_R20D1_DHT_CFG */
+#define MAX98373_DHT_SPK_GAIN_MIN_SHIFT (4)
+#define MAX98373_DHT_ROT_PNT_SHIFT (0)
+
+/* MAX98373_R20D2_DHT_ATTACK_CFG */
+#define MAX98373_DHT_ATTACK_STEP_SHIFT (3)
+#define MAX98373_DHT_ATTACK_RATE_SHIFT (0)
+
+/* MAX98373_R20D3_DHT_RELEASE_CFG */
+#define MAX98373_DHT_RELEASE_STEP_SHIFT (3)
+#define MAX98373_DHT_RELEASE_RATE_SHIFT (0)
+
+/* MAX98373_R20D4_DHT_EN */
+#define MAX98373_DHT_EN_SHIFT (0)
+
+/* MAX98373_R20E0_LIMITER_THRESH_CFG */
+#define MAX98373_LIMITER_THRESH_SHIFT (2)
+#define MAX98373_LIMITER_THRESH_SRC_SHIFT (0)
+
+/* MAX98373_R20E2_LIMITER_EN */
+#define MAX98373_LIMITER_EN_SHIFT (0)
+
+/* MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG */
+#define MAX98373_CLOCK_MON_SHIFT (0)
+
+/* MAX98373_R20FF_GLOBAL_SHDN */
+#define MAX98373_GLOBAL_EN_MASK (0x1 << 0)
+
+/* MAX98373_R2000_SW_RESET */
+#define MAX98373_SOFT_RESET (0x1 << 0)
+
+struct max98373_priv {
+ struct regmap *regmap;
+ unsigned int v_slot;
+ unsigned int i_slot;
+ unsigned int spkfb_slot;
+ bool interleave_mode;
+ unsigned int ch_size;
+ bool tdm_mode;
+};
+#endif
--
2.7.4
2
2
[alsa-devel] [PATCH] ASoC: rcar: tidyup simple-card example for CPU node
by Kuninori Morimoto 03 Jan '18
by Kuninori Morimoto 03 Jan '18
03 Jan '18
From: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
commit a5702e1cb3c ("ASoC: rsnd: Drop unit-addresses without reg
properties") modifies simple-card multi CPU nodes.
But, naming of "cpu-x" breaks probing.
Let's add reg = <x>; instead of renaming node.
Reported-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx(a)renesas.com>
CC: Geert Uytterhoeven <geert+renesas(a)glider.be>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
---
Documentation/devicetree/bindings/sound/renesas,rsnd.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index 085bec3..51b7324 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -197,12 +197,17 @@ Ex)
[MEM] -> [SRC2] -> [CTU03] -+
sound {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
compatible = "simple-scu-audio-card";
...
- simple-audio-card,cpu-0 {
+ simple-audio-card,cpu@0 {
+ reg = <0>;
sound-dai = <&rcar_sound 0>;
};
- simple-audio-card,cpu-1 {
+ simple-audio-card,cpu@1 {
+ reg = <1>;
sound-dai = <&rcar_sound 1>;
};
simple-audio-card,codec {
--
1.9.1
3
2
Signed-off-by: Ryan Lee <ryans.lee(a)maximintegrated.com>
---
Created max98373 amplifier driver.
.../devicetree/bindings/sound/max98373.txt | 43 +
sound/soc/codecs/Kconfig | 5 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/max98373.c | 996 +++++++++++++++++++++
sound/soc/codecs/max98373.h | 225 +++++
5 files changed, 1271 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/max98373.txt
create mode 100644 sound/soc/codecs/max98373.c
create mode 100644 sound/soc/codecs/max98373.h
diff --git a/Documentation/devicetree/bindings/sound/max98373.txt b/Documentation/devicetree/bindings/sound/max98373.txt
new file mode 100644
index 0000000..22cd259
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/max98373.txt
@@ -0,0 +1,43 @@
+Maxim Integrated MAX98373 Speaker Amplifier
+
+This device supports I2C.
+
+Required properties:
+
+ - compatible : should be one of the following
+ - "maxim,max98373"
+
+ - reg : the I2C address of the device.
+
+Optional properties:
+
+ - maxim,vmon-slot-no : slot number used to send voltage information
+ or in inteleave mode this will be used as
+ interleave slot.
+ slot range : 0 ~ 15, Default : 0
+
+ - maxim,imon-slot-no : slot number used to send current information
+ slot range : 0 ~ 15, Default : 0
+
+ - maxim,spkfb-slot-no : slot number used to send speaker feedback information
+ slot range : 0 ~ 15, Default : 0
+
+ - maxim,interleave-mode : When using two MAX98373 in a system it is
+ possible to create ADC data that that will
+ overflow the frame size. Digital Audio Interleave
+ mode provides a means to output VMON and IMON data
+ from two devices on a single DOUT line when running
+ smaller frames sizes such as 32 BCLKS per LRCLK or
+ 48 BCLKS per LRCLK.
+ Range : 0 (off), 1 (on), Default : 0
+
+Example:
+
+codec: max98373@31 {
+ compatible = "maxim,max98373";
+ reg = <0x31>;
+ maxim,vmon-slot-no = <0>;
+ maxim,imon-slot-no = <1>;
+ maxim,spkfb-slot-no = <2>;
+ maxim,interleave-mode = <0>;
+};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 8b02bc8..9af2588 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -95,6 +95,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MAX98925 if I2C
select SND_SOC_MAX98926 if I2C
select SND_SOC_MAX98927 if I2C
+ select SND_SOC_MAX98373 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9860 if I2C
select SND_SOC_MAX9768 if I2C
@@ -626,6 +627,10 @@ config SND_SOC_MAX98927
tristate "Maxim Integrated MAX98927 Speaker Amplifier"
depends on I2C
+config SND_SOC_MAX98373
+ tristate "Maxim Integrated MAX98373 Speaker Amplifier"
+ depends on I2C
+
config SND_SOC_MAX9850
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 0977349..49db8e9 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -90,6 +90,7 @@ snd-soc-max9867-objs := max9867.o
snd-soc-max98925-objs := max98925.o
snd-soc-max98926-objs := max98926.o
snd-soc-max98927-objs := max98927.o
+snd-soc-max98373-objs := max98373.o
snd-soc-max9850-objs := max9850.o
snd-soc-max9860-objs := max9860.o
snd-soc-mc13783-objs := mc13783.o
@@ -334,6 +335,7 @@ obj-$(CONFIG_SND_SOC_MAX9867) += snd-soc-max9867.o
obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o
obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o
obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o
+obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c
new file mode 100644
index 0000000..434c367
--- /dev/null
+++ b/sound/soc/codecs/max98373.c
@@ -0,0 +1,996 @@
+/*
+ * max98373.c -- MAX98373 ALSA Soc Audio driver
+ *
+ * Copyright (C) 2017 Maxim Integrated Products
+ * Author: Ryan Lee <ryans.lee(a)maximintegrated.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <sound/tlv.h>
+#include "max98373.h"
+
+static struct reg_default max98373_reg[] = {
+ {MAX98373_R2000_SW_RESET, 0x00},
+ {MAX98373_R2001_INT_RAW1, 0x00},
+ {MAX98373_R2002_INT_RAW2, 0x00},
+ {MAX98373_R2003_INT_RAW3, 0x00},
+ {MAX98373_R2004_INT_STATE1, 0x00},
+ {MAX98373_R2005_INT_STATE2, 0x00},
+ {MAX98373_R2006_INT_STATE3, 0x00},
+ {MAX98373_R2007_INT_FLAG1, 0x00},
+ {MAX98373_R2008_INT_FLAG2, 0x00},
+ {MAX98373_R2009_INT_FLAG3, 0x00},
+ {MAX98373_R200A_INT_EN1, 0x00},
+ {MAX98373_R200B_INT_EN2, 0x00},
+ {MAX98373_R200C_INT_EN3, 0x00},
+ {MAX98373_R200D_INT_FLAG_CLR1, 0x00},
+ {MAX98373_R200E_INT_FLAG_CLR2, 0x00},
+ {MAX98373_R200F_INT_FLAG_CLR3, 0x00},
+ {MAX98373_R2010_IRQ_CTRL, 0x00},
+ {MAX98373_R2014_THERM_WARN_THRESH, 0x10},
+ {MAX98373_R2015_THERM_SHDN_THRESH, 0x27},
+ {MAX98373_R2016_THERM_HYSTERESIS, 0x01},
+ {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0},
+ {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00},
+ {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55},
+ {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE},
+ {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF},
+ {MAX98373_R2022_PCM_TX_SRC_1, 0x00},
+ {MAX98373_R2023_PCM_TX_SRC_2, 0x00},
+ {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0},
+ {MAX98373_R2025_AUDIO_IF_MODE, 0x00},
+ {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04},
+ {MAX98373_R2027_PCM_SR_SETUP_1, 0x08},
+ {MAX98373_R2028_PCM_SR_SETUP_2, 0x88},
+ {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00},
+ {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00},
+ {MAX98373_R202B_PCM_RX_EN, 0x00},
+ {MAX98373_R202C_PCM_TX_EN, 0x00},
+ {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00},
+ {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00},
+ {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF},
+ {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF},
+ {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30},
+ {MAX98373_R2034_ICC_TX_CNTL, 0x00},
+ {MAX98373_R2035_ICC_TX_EN, 0x00},
+ {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05},
+ {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00},
+ {MAX98373_R203E_AMP_PATH_GAIN, 0x08},
+ {MAX98373_R203F_AMP_DSP_CFG, 0x02},
+ {MAX98373_R2040_TONE_GEN_CFG, 0x00},
+ {MAX98373_R2041_AMP_CFG, 0x03},
+ {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00},
+ {MAX98373_R2043_AMP_EN, 0x00},
+ {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04},
+ {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00},
+ {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00},
+ {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00},
+ {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00},
+ {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00},
+ {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00},
+ {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00},
+ {MAX98373_R2090_BDE_LVL_HOLD, 0x00},
+ {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00},
+ {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00},
+ {MAX98373_R2097_BDE_L1_THRESH, 0x00},
+ {MAX98373_R2098_BDE_L2_THRESH, 0x00},
+ {MAX98373_R2099_BDE_L3_THRESH, 0x00},
+ {MAX98373_R209A_BDE_L4_THRESH, 0x00},
+ {MAX98373_R209B_BDE_THRESH_HYST, 0x00},
+ {MAX98373_R20A8_BDE_L1_CFG_1, 0x00},
+ {MAX98373_R20A9_BDE_L1_CFG_2, 0x00},
+ {MAX98373_R20AA_BDE_L1_CFG_3, 0x00},
+ {MAX98373_R20AB_BDE_L2_CFG_1, 0x00},
+ {MAX98373_R20AC_BDE_L2_CFG_2, 0x00},
+ {MAX98373_R20AD_BDE_L2_CFG_3, 0x00},
+ {MAX98373_R20AE_BDE_L3_CFG_1, 0x00},
+ {MAX98373_R20AF_BDE_L3_CFG_2, 0x00},
+ {MAX98373_R20B0_BDE_L3_CFG_3, 0x00},
+ {MAX98373_R20B1_BDE_L4_CFG_1, 0x00},
+ {MAX98373_R20B2_BDE_L4_CFG_2, 0x00},
+ {MAX98373_R20B3_BDE_L4_CFG_3, 0x00},
+ {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00},
+ {MAX98373_R20B5_BDE_EN, 0x00},
+ {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00},
+ {MAX98373_R20D1_DHT_CFG, 0x01},
+ {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02},
+ {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03},
+ {MAX98373_R20D4_DHT_EN, 0x00},
+ {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00},
+ {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00},
+ {MAX98373_R20E2_LIMITER_EN, 0x00},
+ {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00},
+ {MAX98373_R20FF_GLOBAL_SHDN, 0x00},
+ {MAX98373_R21FF_REV_ID, 0x42},
+};
+
+static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ unsigned int format = 0;
+ unsigned int invert = 0;
+
+ dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE;
+ break;
+ default:
+ dev_err(codec->dev, "DAI invert mode unsupported\n");
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2026_PCM_CLOCK_RATIO,
+ MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE,
+ invert);
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ format = MAX98373_PCM_FORMAT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format = MAX98373_PCM_FORMAT_LJ;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ format = MAX98373_PCM_FORMAT_TDM_MODE1;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ format = MAX98373_PCM_FORMAT_TDM_MODE0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ max98373->iface = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_MODE_CFG_FORMAT_MASK,
+ format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT);
+
+ return 0;
+}
+
+/* BCLKs per LRCLK */
+static const int bclk_sel_table[] = {
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 320,
+};
+
+static int max98373_get_bclk_sel(int bclk)
+{
+ int i;
+ /* match BCLKs per LRCLK */
+ for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
+ if (bclk_sel_table[i] == bclk)
+ return i + 2;
+ }
+ return 0;
+}
+static int max98373_set_clock(struct max98373_priv *max98373,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_codec *codec = max98373->codec;
+ /* BCLK/LRCLK ratio calculation */
+ int blr_clk_ratio = params_channels(params) * max98373->ch_size;
+ int value;
+
+ if (!max98373->tdm_mode) {
+ /* BCLK configuration */
+ value = max98373_get_bclk_sel(blr_clk_ratio);
+ if (!value) {
+ dev_err(codec->dev, "format unsupported %d\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2026_PCM_CLOCK_RATIO,
+ MAX98373_PCM_CLK_SETUP_BSEL_MASK,
+ value);
+ }
+ return 0;
+}
+
+static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ unsigned int sampling_rate = 0;
+ unsigned int chan_sz = 0;
+
+ /* pcm mode configuration */
+ switch (snd_pcm_format_width(params_format(params))) {
+ case 16:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
+ break;
+ case 24:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
+ break;
+ case 32:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
+ break;
+ default:
+ dev_err(codec->dev, "format unsupported %d\n",
+ params_format(params));
+ goto err;
+ }
+
+ max98373->ch_size = snd_pcm_format_width(params_format(params));
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
+
+ dev_dbg(codec->dev, "format supported %d",
+ params_format(params));
+
+ /* sampling rate configuration */
+ switch (params_rate(params)) {
+ case 8000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_8000;
+ break;
+ case 11025:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_11025;
+ break;
+ case 12000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_12000;
+ break;
+ case 16000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_16000;
+ break;
+ case 22050:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_22050;
+ break;
+ case 24000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_24000;
+ break;
+ case 32000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_32000;
+ break;
+ case 44100:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_44100;
+ break;
+ case 48000:
+ sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
+ break;
+ default:
+ dev_err(codec->dev, "rate %d not supported\n",
+ params_rate(params));
+ goto err;
+ }
+ /* set DAI_SR to correct LRCLK frequency */
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2027_PCM_SR_SETUP_1,
+ MAX98373_PCM_SR_SET1_SR_MASK,
+ sampling_rate);
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2028_PCM_SR_SETUP_2,
+ MAX98373_PCM_SR_SET2_SR_MASK,
+ sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT);
+
+ /* set sampling rate of IV */
+ if (max98373->interleave_mode &&
+ sampling_rate > MAX98373_PCM_SR_SET1_SR_16000)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2028_PCM_SR_SETUP_2,
+ MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
+ sampling_rate - 3);
+ else
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2028_PCM_SR_SETUP_2,
+ MAX98373_PCM_SR_SET2_IVADC_SR_MASK,
+ sampling_rate);
+
+ return max98373_set_clock(max98373, params);
+err:
+ return -EINVAL;
+}
+
+static int max98373_dai_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int tx_mask, unsigned int rx_mask,
+ int slots, int slot_width)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+ int bsel = 0;
+ unsigned int chan_sz = 0;
+ unsigned int mask;
+ int x, slot_found;
+
+ max98373->tdm_mode = true;
+
+ /* BCLK configuration */
+ bsel = max98373_get_bclk_sel(slots * slot_width);
+ if (bsel == 0) {
+ dev_err(codec->dev, "BCLK %d not supported\n",
+ slots * slot_width);
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2026_PCM_CLOCK_RATIO,
+ MAX98373_PCM_CLK_SETUP_BSEL_MASK,
+ bsel);
+
+ /* Channel size configuration */
+ switch (slot_width) {
+ case 16:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16;
+ break;
+ case 24:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24;
+ break;
+ case 32:
+ chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32;
+ break;
+ default:
+ dev_err(codec->dev, "format unsupported %d\n",
+ slot_width);
+ return -EINVAL;
+ }
+
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);
+
+ /* Rx slot configuration */
+ slot_found = 0;
+ mask = rx_mask;
+ for (x = 0 ; x < 16 ; x++, mask >>= 1) {
+ if (mask & 0x1) {
+ if (slot_found == 0)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
+ MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x);
+ else
+ regmap_write(max98373->regmap,
+ MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2,
+ x);
+ slot_found++;
+ if (slot_found > 1)
+ break;
+ }
+ }
+
+ /* Tx slot Hi-Z configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ ~tx_mask & 0xFF);
+ regmap_write(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ (~tx_mask & 0xFF00) >> 8);
+
+ return 0;
+}
+
+#define MAX98373_RATES SNDRV_PCM_RATE_8000_96000
+
+#define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static int max98373_dai_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+
+ max98373->sysclk = freq;
+ return 0;
+}
+
+static const struct snd_soc_dai_ops max98373_dai_ops = {
+ .set_sysclk = max98373_dai_set_sysclk,
+ .set_fmt = max98373_dai_set_fmt,
+ .hw_params = max98373_dai_hw_params,
+ .set_tdm_slot = max98373_dai_tdm_slot,
+};
+
+static int max98373_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R20FF_GLOBAL_SHDN,
+ MAX98373_GLOBAL_EN_MASK, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R20FF_GLOBAL_SHDN,
+ MAX98373_GLOBAL_EN_MASK, 0);
+ max98373->tdm_mode = 0;
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+static const char * const max98373_switch_text[] = {
+ "Left", "Right", "LeftRight"};
+
+static const struct soc_enum dai_sel_enum =
+ SOC_ENUM_SINGLE(MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
+ MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT,
+ 3, max98373_switch_text);
+
+static const struct snd_kcontrol_new max98373_dai_controls =
+ SOC_DAPM_ENUM("DAI Sel", dai_sel_enum);
+
+static const struct snd_kcontrol_new max98373_vi_control =
+ SOC_DAPM_SINGLE("Switch", MAX98373_R202C_PCM_TX_EN, 0, 1, 0);
+
+static const struct snd_kcontrol_new max98373_spkfb_control =
+ SOC_DAPM_SINGLE("Switch", MAX98373_R2043_AMP_EN, 1, 1, 0);
+
+static const struct snd_soc_dapm_widget max98373_dapm_widgets[] = {
+SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback",
+ MAX98373_R202B_PCM_RX_EN, 0, 0, max98373_dac_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
+ &max98373_dai_controls),
+SND_SOC_DAPM_OUTPUT("BE_OUT"),
+SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0,
+ MAX98373_R2047_IV_SENSE_ADC_EN, 0, 0),
+SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0,
+ MAX98373_R2047_IV_SENSE_ADC_EN, 1, 0),
+SND_SOC_DAPM_AIF_OUT("Speaker FB Sense", "HiFi Capture", 0,
+ SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0,
+ &max98373_vi_control),
+SND_SOC_DAPM_SWITCH("SpkFB Sense", SND_SOC_NOPM, 0, 0,
+ &max98373_spkfb_control),
+SND_SOC_DAPM_SIGGEN("VMON"),
+SND_SOC_DAPM_SIGGEN("IMON"),
+SND_SOC_DAPM_SIGGEN("FBMON"),
+};
+
+static DECLARE_TLV_DB_SCALE(max98373_digital_tlv, 0, -50, 0);
+static const DECLARE_TLV_DB_RANGE(max98373_spk_tlv,
+ 0, 8, TLV_DB_SCALE_ITEM(0, 50, 0),
+ 9, 10, TLV_DB_SCALE_ITEM(500, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_spkgain_max_tlv,
+ 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_dht_step_size_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(25, 25, 0),
+ 2, 4, TLV_DB_SCALE_ITEM(100, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_dht_spkgain_min_tlv,
+ 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_dht_rotation_point_tlv,
+ 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0),
+ 2, 7, TLV_DB_SCALE_ITEM(-200, -100, 0),
+ 8, 9, TLV_DB_SCALE_ITEM(-1000, -200, 0),
+ 10, 11, TLV_DB_SCALE_ITEM(-1500, -300, 0),
+ 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0),
+ 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0),
+);
+static const DECLARE_TLV_DB_RANGE(max98373_limiter_thresh_tlv,
+ 0, 15, TLV_DB_SCALE_ITEM(0, -100, 0),
+);
+
+static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv,
+ 0, 60, TLV_DB_SCALE_ITEM(0, -25, 0),
+);
+
+static bool max98373_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3:
+ case MAX98373_R2010_IRQ_CTRL:
+ case MAX98373_R2014_THERM_WARN_THRESH
+ ... MAX98373_R2018_THERM_FOLDBACK_EN:
+ case MAX98373_R201E_PIN_DRIVE_STRENGTH
+ ... MAX98373_R2036_SOUNDWIRE_CTRL:
+ case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN:
+ case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG
+ ... MAX98373_R2047_IV_SENSE_ADC_EN:
+ case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE
+ ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN:
+ case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE:
+ case MAX98373_R2097_BDE_L1_THRESH
+ ... MAX98373_R209B_BDE_THRESH_HYST:
+ case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3:
+ case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK:
+ case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN:
+ case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN:
+ case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG
+ ... MAX98373_R20FF_GLOBAL_SHDN:
+ case MAX98373_R21FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
+};
+
+static bool max98373_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3:
+ case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK:
+ case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK:
+ case MAX98373_R20B6_BDE_CUR_STATE_READBACK:
+ case MAX98373_R21FF_REV_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const char * const max98373_output_voltage_lvl_text[] = {
+ "5.43V", "6.09V", "6.83V", "7.67V", "8.60V",
+ "9.65V", "10.83V", "12.15V", "13.63V", "15.29V"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_out_volt_enum,
+ MAX98373_R203E_AMP_PATH_GAIN, 0,
+ max98373_output_voltage_lvl_text);
+
+static const char * const max98373_dht_attack_rate_text[] = {
+ "17.5us", "35us", "70us", "140us",
+ "280us", "560us", "1120us", "2240us"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_dht_attack_rate_enum,
+ MAX98373_R20D2_DHT_ATTACK_CFG, 0,
+ max98373_dht_attack_rate_text);
+
+static const char * const max98373_dht_release_rate_text[] = {
+ "45ms", "225ms", "450ms", "1150ms",
+ "2250ms", "3100ms", "4500ms", "6750ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_dht_release_rate_enum,
+ MAX98373_R20D3_DHT_RELEASE_CFG, 0,
+ max98373_dht_release_rate_text);
+
+static const char * const max98373_limiter_attack_rate_text[] = {
+ "10us", "20us", "40us", "80us",
+ "160us", "320us", "640us", "1.28ms",
+ "2.56ms", "5.12ms", "10.24ms", "20.48ms",
+ "40.96ms", "81.92ms", "16.384ms", "32.768ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_limiter_attack_rate_enum,
+ MAX98373_R20E1_LIMITER_ATK_REL_RATES, 4,
+ max98373_limiter_attack_rate_text);
+
+static const char * const max98373_limiter_release_rate_text[] = {
+ "40us", "80us", "160us", "320us",
+ "640us", "1.28ms", "2.56ms", "5.120ms",
+ "10.24ms", "20.48ms", "40.96ms", "81.92ms",
+ "163.84ms", "327.68ms", "655.36ms", "1310.72ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_limiter_release_rate_enum,
+ MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0,
+ max98373_limiter_release_rate_text);
+
+static const char * const max98373_ADC_samplerate_text[] = {
+ "333kHz", "192kHz", "64kHz", "48kHz"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98373_adc_samplerate_enum,
+ MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0,
+ max98373_ADC_samplerate_text);
+
+static const struct snd_kcontrol_new max98373_snd_controls[] = {
+SOC_SINGLE("Digital Vol Sel Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_VOL_SEL_SHIFT, 1, 0),
+SOC_SINGLE("Volume Location Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_VOL_SEL_SHIFT, 1, 0),
+SOC_SINGLE("Ramp Up Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0),
+SOC_SINGLE("Ramp Down Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0),
+SOC_SINGLE("CLK Monitor Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG,
+ MAX98373_CLOCK_MON_SHIFT, 1, 0),
+SOC_SINGLE("Dither Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_DITH_SHIFT, 1, 0),
+SOC_SINGLE("DC Blocker Switch", MAX98373_R203F_AMP_DSP_CFG,
+ MAX98373_AMP_DSP_CFG_DCBLK_SHIFT, 1, 0),
+SOC_SINGLE_TLV("Digital Volume", MAX98373_R203D_AMP_DIG_VOL_CTRL,
+ 0, 0x7F, 0, max98373_digital_tlv),
+SOC_SINGLE_TLV("Speaker Volume", MAX98373_R203E_AMP_PATH_GAIN,
+ MAX98373_SPK_DIGI_GAIN_SHIFT, 10, 0, max98373_spk_tlv),
+SOC_SINGLE_TLV("FS Max Volume", MAX98373_R203E_AMP_PATH_GAIN,
+ MAX98373_FS_GAIN_MAX_SHIFT, 9, 0, max98373_spkgain_max_tlv),
+SOC_ENUM("Output Voltage", max98373_out_volt_enum),
+/* Dynamic Headroom Tracking */
+SOC_SINGLE("DHT Switch", MAX98373_R20D4_DHT_EN,
+ MAX98373_DHT_EN_SHIFT, 1, 0),
+SOC_SINGLE_TLV("DHT Gain Min", MAX98373_R20D1_DHT_CFG,
+ MAX98373_DHT_SPK_GAIN_MIN_SHIFT, 9, 0, max98373_dht_spkgain_min_tlv),
+SOC_SINGLE_TLV("DHT Rot Pnt", MAX98373_R20D1_DHT_CFG,
+ MAX98373_DHT_ROT_PNT_SHIFT, 15, 0, max98373_dht_rotation_point_tlv),
+SOC_SINGLE_TLV("DHT Attack Step", MAX98373_R20D2_DHT_ATTACK_CFG,
+ MAX98373_DHT_ATTACK_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv),
+SOC_SINGLE_TLV("DHT Release Step", MAX98373_R20D3_DHT_RELEASE_CFG,
+ MAX98373_DHT_RELEASE_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv),
+SOC_ENUM("DHT Attack Rate", max98373_dht_attack_rate_enum),
+SOC_ENUM("DHT Release Rate", max98373_dht_release_rate_enum),
+/* ADC configuration */
+SOC_SINGLE("ADC PVDD CH Switch", MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0, 1, 0),
+SOC_SINGLE("ADC PVDD FLT Switch", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG,
+ MAX98373_FLT_EN_SHIFT, 1, 0),
+SOC_SINGLE("ADC TEMP FLT Switch", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG,
+ MAX98373_FLT_EN_SHIFT, 1, 0),
+SOC_SINGLE("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0),
+SOC_SINGLE("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0),
+SOC_SINGLE("ADC PVDD FLT Coeff", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG,
+ 0, 0x3, 0),
+SOC_SINGLE("ADC TEMP FLT Coeff", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG,
+ 0, 0x3, 0),
+SOC_ENUM("ADC SampleRate", max98373_adc_samplerate_enum),
+/* Brownout Detection Engine */
+SOC_SINGLE("BDE Switch", MAX98373_R20B5_BDE_EN, MAX98373_BDE_EN_SHIFT, 1, 0),
+SOC_SINGLE("BDE LVL4 Mute Switch", MAX98373_R20B2_BDE_L4_CFG_2,
+ MAX98373_LVL4_MUTE_EN_SHIFT, 1, 0),
+SOC_SINGLE("BDE LVL4 Hold Switch", MAX98373_R20B2_BDE_L4_CFG_2,
+ MAX98373_LVL4_HOLD_EN_SHIFT, 1, 0),
+SOC_SINGLE("BDE LVL1 Thresh", MAX98373_R2097_BDE_L1_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE LVL2 Thresh", MAX98373_R2098_BDE_L2_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE LVL3 Thresh", MAX98373_R2099_BDE_L3_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE LVL4 Thresh", MAX98373_R209A_BDE_L4_THRESH, 0, 0xFF, 0),
+SOC_SINGLE("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0),
+SOC_SINGLE("BDE Clip Mode Switch", MAX98373_R2092_BDE_CLIPPER_MODE, 0, 1, 0),
+SOC_SINGLE("BDE Thresh Hysteresis", MAX98373_R209B_BDE_THRESH_HYST, 0, 0xFF, 0),
+SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0),
+SOC_SINGLE("BDE Attack Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 4, 0xF, 0),
+SOC_SINGLE("BDE Release Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0, 0xF, 0),
+SOC_SINGLE_TLV("BDE LVL1 Clip Thresh", MAX98373_R20A9_BDE_L1_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL2 Clip Thresh", MAX98373_R20AC_BDE_L2_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL3 Clip Thresh", MAX98373_R20AF_BDE_L3_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL4 Clip Thresh", MAX98373_R20B2_BDE_L4_CFG_2,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL1 Clip Gain Reduct", MAX98373_R20AA_BDE_L1_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL2 Clip Gain Reduct", MAX98373_R20AD_BDE_L2_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL3 Clip Gain Reduct", MAX98373_R20B0_BDE_L3_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL4 Clip Gain Reduct", MAX98373_R20B3_BDE_L4_CFG_3,
+ 0, 0x3C, 0, max98373_bde_gain_tlv),
+SOC_SINGLE_TLV("BDE LVL1 Limiter Thresh", MAX98373_R20A8_BDE_L1_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+SOC_SINGLE_TLV("BDE LVL2 Limiter Thresh", MAX98373_R20AB_BDE_L2_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+SOC_SINGLE_TLV("BDE LVL3 Limiter Thresh", MAX98373_R20AE_BDE_L3_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+SOC_SINGLE_TLV("BDE LVL4 Limiter Thresh", MAX98373_R20B1_BDE_L4_CFG_1,
+ 0, 0xF, 0, max98373_limiter_thresh_tlv),
+/* Limiter */
+SOC_SINGLE("Limiter Switch", MAX98373_R20E2_LIMITER_EN,
+ MAX98373_LIMITER_EN_SHIFT, 1, 0),
+SOC_SINGLE("Limiter Src Switch", MAX98373_R20E0_LIMITER_THRESH_CFG,
+ MAX98373_LIMITER_THRESH_SRC_SHIFT, 1, 0),
+SOC_SINGLE_TLV("Limiter Thresh", MAX98373_R20E0_LIMITER_THRESH_CFG,
+ MAX98373_LIMITER_THRESH_SHIFT, 15, 0, max98373_limiter_thresh_tlv),
+SOC_ENUM("Limiter Attack Rate", max98373_limiter_attack_rate_enum),
+SOC_ENUM("Limiter Release Rate", max98373_limiter_release_rate_enum),
+};
+
+static const struct snd_soc_dapm_route max98373_audio_map[] = {
+ /* Plabyack */
+ {"DAI Sel Mux", "Left", "Amp Enable"},
+ {"DAI Sel Mux", "Right", "Amp Enable"},
+ {"DAI Sel Mux", "LeftRight", "Amp Enable"},
+ {"BE_OUT", NULL, "DAI Sel Mux"},
+ /* Capture */
+ { "VI Sense", "Switch", "VMON" },
+ { "VI Sense", "Switch", "IMON" },
+ { "SpkFB Sense", "Switch", "FBMON" },
+ { "Voltage Sense", NULL, "VI Sense" },
+ { "Current Sense", NULL, "VI Sense" },
+ { "Speaker FB Sense", NULL, "SpkFB Sense" },
+};
+
+static struct snd_soc_dai_driver max98373_dai[] = {
+ {
+ .name = "max98373-aif1",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98373_RATES,
+ .formats = MAX98373_FORMATS,
+ },
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98373_RATES,
+ .formats = MAX98373_FORMATS,
+ },
+ .ops = &max98373_dai_ops,
+ }
+};
+
+static int max98373_probe(struct snd_soc_codec *codec)
+{
+ struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec);
+
+ max98373->codec = codec;
+ codec->control_data = max98373->regmap;
+
+ /* Software Reset */
+ regmap_write(max98373->regmap,
+ MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
+
+ /* IV default slot configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ 0xFF);
+ regmap_write(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ 0xFF);
+ /* L/R mix configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1,
+ 0x80);
+ regmap_write(max98373->regmap,
+ MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2,
+ 0x1);
+ /* Set inital volume (0dB) */
+ regmap_write(max98373->regmap,
+ MAX98373_R203D_AMP_DIG_VOL_CTRL,
+ 0x00);
+ regmap_write(max98373->regmap,
+ MAX98373_R203E_AMP_PATH_GAIN,
+ 0x00);
+ /* Enable DC blocker */
+ regmap_write(max98373->regmap,
+ MAX98373_R203F_AMP_DSP_CFG,
+ 0x3);
+ /* Enable IMON VMON DC blocker */
+ regmap_write(max98373->regmap,
+ MAX98373_R2046_IV_SENSE_ADC_DSP_CFG,
+ 0x7);
+ /* voltage, current slot configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2022_PCM_TX_SRC_1,
+ (max98373->i_slot << MAX98373_PCM_TX_CH_SRC_A_I_SHIFT |
+ max98373->v_slot) & 0xFF);
+ if (max98373->v_slot < 8)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ 1 << max98373->v_slot, 0);
+ else
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ 1 << (max98373->v_slot - 8), 0);
+
+ if (max98373->i_slot < 8)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2020_PCM_TX_HIZ_EN_1,
+ 1 << max98373->i_slot, 0);
+ else
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2021_PCM_TX_HIZ_EN_2,
+ 1 << (max98373->i_slot - 8), 0);
+
+ /* speaker feedback slot configuration */
+ regmap_write(max98373->regmap,
+ MAX98373_R2023_PCM_TX_SRC_2,
+ max98373->spkfb_slot & 0xFF);
+
+ /* Set interleave mode */
+ if (max98373->interleave_mode)
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2024_PCM_DATA_FMT_CFG,
+ MAX98373_PCM_TX_CH_INTERLEAVE_MASK,
+ MAX98373_PCM_TX_CH_INTERLEAVE_MASK);
+
+ /* Speaker enable */
+ regmap_update_bits(max98373->regmap,
+ MAX98373_R2043_AMP_EN,
+ MAX98373_SPK_EN_MASK, 1);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max98373_suspend(struct device *dev)
+{
+ struct max98373_priv *max98373 = dev_get_drvdata(dev);
+
+ regcache_cache_only(max98373->regmap, true);
+ regcache_mark_dirty(max98373->regmap);
+ return 0;
+}
+static int max98373_resume(struct device *dev)
+{
+ struct max98373_priv *max98373 = dev_get_drvdata(dev);
+
+ regmap_write(max98373->regmap,
+ MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
+ regcache_cache_only(max98373->regmap, false);
+ regcache_sync(max98373->regmap);
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops max98373_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume)
+};
+
+static const struct snd_soc_codec_driver soc_codec_dev_max98373 = {
+ .probe = max98373_probe,
+ .component_driver = {
+ .controls = max98373_snd_controls,
+ .num_controls = ARRAY_SIZE(max98373_snd_controls),
+ .dapm_widgets = max98373_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(max98373_dapm_widgets),
+ .dapm_routes = max98373_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(max98373_audio_map),
+ },
+};
+
+static const struct regmap_config max98373_regmap = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = MAX98373_R21FF_REV_ID,
+ .reg_defaults = max98373_reg,
+ .num_reg_defaults = ARRAY_SIZE(max98373_reg),
+ .readable_reg = max98373_readable_register,
+ .volatile_reg = max98373_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static void max98373_slot_config(struct i2c_client *i2c,
+ struct max98373_priv *max98373)
+{
+ int value;
+ struct device *dev = &i2c->dev;
+
+ if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value))
+ max98373->v_slot = value & 0xF;
+ else
+ max98373->v_slot = 0;
+
+ if (!device_property_read_u32(dev, "maxim,imon-slot-no", &value))
+ max98373->i_slot = value & 0xF;
+ else
+ max98373->i_slot = 1;
+
+ if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value))
+ max98373->spkfb_slot = value & 0xF;
+ else
+ max98373->spkfb_slot = 2;
+}
+
+static int max98373_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+
+ int ret = 0, value;
+ int reg = 0;
+ struct max98373_priv *max98373 = NULL;
+
+ max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL);
+
+ if (!max98373) {
+ ret = -ENOMEM;
+ return ret;
+ }
+ i2c_set_clientdata(i2c, max98373);
+
+ /* update interleave mode info */
+ if (!device_property_read_u32(&i2c->dev,
+ "maxim,interleave_mode", &value)) {
+ if (value > 0)
+ max98373->interleave_mode = 1;
+ else
+ max98373->interleave_mode = 0;
+ } else
+ max98373->interleave_mode = 0;
+
+ /* regmap initialization */
+ max98373->regmap
+ = devm_regmap_init_i2c(i2c, &max98373_regmap);
+ if (IS_ERR(max98373->regmap)) {
+ ret = PTR_ERR(max98373->regmap);
+ dev_err(&i2c->dev,
+ "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
+ /* Check Revision ID */
+ ret = regmap_read(max98373->regmap,
+ MAX98373_R21FF_REV_ID, ®);
+ if (ret < 0) {
+ dev_err(&i2c->dev,
+ "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID);
+ return ret;
+ }
+ dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg);
+
+ /* voltage/current slot configuration */
+ max98373_slot_config(i2c, max98373);
+
+ /* codec registeration */
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98373,
+ max98373_dai, ARRAY_SIZE(max98373_dai));
+ if (ret < 0)
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+
+ return ret;
+}
+
+static int max98373_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id max98373_i2c_id[] = {
+ { "max98373", 0},
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, max98373_i2c_id);
+
+#if defined(CONFIG_OF)
+static const struct of_device_id max98373_of_match[] = {
+ { .compatible = "maxim,max98373", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, max98373_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id max98373_acpi_match[] = {
+ { "MX98373", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, max98373_acpi_match);
+#endif
+
+static struct i2c_driver max98373_i2c_driver = {
+ .driver = {
+ .name = "max98373",
+ .of_match_table = of_match_ptr(max98373_of_match),
+ .acpi_match_table = ACPI_PTR(max98373_acpi_match),
+ .pm = &max98373_pm,
+ },
+ .probe = max98373_i2c_probe,
+ .remove = max98373_i2c_remove,
+ .id_table = max98373_i2c_id,
+};
+
+module_i2c_driver(max98373_i2c_driver)
+
+MODULE_DESCRIPTION("ALSA SoC MAX98373 driver");
+MODULE_AUTHOR("Ryan Lee <ryans.lee(a)maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h
new file mode 100644
index 0000000..bbb2271
--- /dev/null
+++ b/sound/soc/codecs/max98373.h
@@ -0,0 +1,225 @@
+/*
+ * max98373.h -- MAX98373 ALSA Soc Audio driver
+ *
+ * Copyright 2017 Maxim Integrated Products
+ * Author: Ryan Lee <ryans.lee(a)maximintegrated.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef _MAX98373_H
+#define _MAX98373_H
+
+#define MAX98373_R2000_SW_RESET 0x2000
+#define MAX98373_R2001_INT_RAW1 0x2001
+#define MAX98373_R2002_INT_RAW2 0x2002
+#define MAX98373_R2003_INT_RAW3 0x2003
+#define MAX98373_R2004_INT_STATE1 0x2004
+#define MAX98373_R2005_INT_STATE2 0x2005
+#define MAX98373_R2006_INT_STATE3 0x2006
+#define MAX98373_R2007_INT_FLAG1 0x2007
+#define MAX98373_R2008_INT_FLAG2 0x2008
+#define MAX98373_R2009_INT_FLAG3 0x2009
+#define MAX98373_R200A_INT_EN1 0x200A
+#define MAX98373_R200B_INT_EN2 0x200B
+#define MAX98373_R200C_INT_EN3 0x200C
+#define MAX98373_R200D_INT_FLAG_CLR1 0x200D
+#define MAX98373_R200E_INT_FLAG_CLR2 0x200E
+#define MAX98373_R200F_INT_FLAG_CLR3 0x200F
+#define MAX98373_R2010_IRQ_CTRL 0x2010
+#define MAX98373_R2014_THERM_WARN_THRESH 0x2014
+#define MAX98373_R2015_THERM_SHDN_THRESH 0x2015
+#define MAX98373_R2016_THERM_HYSTERESIS 0x2016
+#define MAX98373_R2017_THERM_FOLDBACK_SET 0x2017
+#define MAX98373_R2018_THERM_FOLDBACK_EN 0x2018
+#define MAX98373_R201E_PIN_DRIVE_STRENGTH 0x201E
+#define MAX98373_R2020_PCM_TX_HIZ_EN_1 0x2020
+#define MAX98373_R2021_PCM_TX_HIZ_EN_2 0x2021
+#define MAX98373_R2022_PCM_TX_SRC_1 0x2022
+#define MAX98373_R2023_PCM_TX_SRC_2 0x2023
+#define MAX98373_R2024_PCM_DATA_FMT_CFG 0x2024
+#define MAX98373_R2025_AUDIO_IF_MODE 0x2025
+#define MAX98373_R2026_PCM_CLOCK_RATIO 0x2026
+#define MAX98373_R2027_PCM_SR_SETUP_1 0x2027
+#define MAX98373_R2028_PCM_SR_SETUP_2 0x2028
+#define MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 0x2029
+#define MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2 0x202A
+#define MAX98373_R202B_PCM_RX_EN 0x202B
+#define MAX98373_R202C_PCM_TX_EN 0x202C
+#define MAX98373_R202E_ICC_RX_CH_EN_1 0x202E
+#define MAX98373_R202F_ICC_RX_CH_EN_2 0x202F
+#define MAX98373_R2030_ICC_TX_HIZ_EN_1 0x2030
+#define MAX98373_R2031_ICC_TX_HIZ_EN_2 0x2031
+#define MAX98373_R2032_ICC_LINK_EN_CFG 0x2032
+#define MAX98373_R2034_ICC_TX_CNTL 0x2034
+#define MAX98373_R2035_ICC_TX_EN 0x2035
+#define MAX98373_R2036_SOUNDWIRE_CTRL 0x2036
+#define MAX98373_R203D_AMP_DIG_VOL_CTRL 0x203D
+#define MAX98373_R203E_AMP_PATH_GAIN 0x203E
+#define MAX98373_R203F_AMP_DSP_CFG 0x203F
+#define MAX98373_R2040_TONE_GEN_CFG 0x2040
+#define MAX98373_R2041_AMP_CFG 0x2041
+#define MAX98373_R2042_AMP_EDGE_RATE_CFG 0x2042
+#define MAX98373_R2043_AMP_EN 0x2043
+#define MAX98373_R2046_IV_SENSE_ADC_DSP_CFG 0x2046
+#define MAX98373_R2047_IV_SENSE_ADC_EN 0x2047
+#define MAX98373_R2051_MEAS_ADC_SAMPLING_RATE 0x2051
+#define MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG 0x2052
+#define MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG 0x2053
+#define MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK 0x2054
+#define MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK 0x2055
+#define MAX98373_R2056_MEAS_ADC_PVDD_CH_EN 0x2056
+#define MAX98373_R2090_BDE_LVL_HOLD 0x2090
+#define MAX98373_R2091_BDE_GAIN_ATK_REL_RATE 0x2091
+#define MAX98373_R2092_BDE_CLIPPER_MODE 0x2092
+#define MAX98373_R2097_BDE_L1_THRESH 0x2097
+#define MAX98373_R2098_BDE_L2_THRESH 0x2098
+#define MAX98373_R2099_BDE_L3_THRESH 0x2099
+#define MAX98373_R209A_BDE_L4_THRESH 0x209A
+#define MAX98373_R209B_BDE_THRESH_HYST 0x209B
+#define MAX98373_R20A8_BDE_L1_CFG_1 0x20A8
+#define MAX98373_R20A9_BDE_L1_CFG_2 0x20A9
+#define MAX98373_R20AA_BDE_L1_CFG_3 0x20AA
+#define MAX98373_R20AB_BDE_L2_CFG_1 0x20AB
+#define MAX98373_R20AC_BDE_L2_CFG_2 0x20AC
+#define MAX98373_R20AD_BDE_L2_CFG_3 0x20AD
+#define MAX98373_R20AE_BDE_L3_CFG_1 0x20AE
+#define MAX98373_R20AF_BDE_L3_CFG_2 0x20AF
+#define MAX98373_R20B0_BDE_L3_CFG_3 0x20B0
+#define MAX98373_R20B1_BDE_L4_CFG_1 0x20B1
+#define MAX98373_R20B2_BDE_L4_CFG_2 0x20B2
+#define MAX98373_R20B3_BDE_L4_CFG_3 0x20B3
+#define MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE 0x20B4
+#define MAX98373_R20B5_BDE_EN 0x20B5
+#define MAX98373_R20B6_BDE_CUR_STATE_READBACK 0x20B6
+#define MAX98373_R20D1_DHT_CFG 0x20D1
+#define MAX98373_R20D2_DHT_ATTACK_CFG 0x20D2
+#define MAX98373_R20D3_DHT_RELEASE_CFG 0x20D3
+#define MAX98373_R20D4_DHT_EN 0x20D4
+#define MAX98373_R20E0_LIMITER_THRESH_CFG 0x20E0
+#define MAX98373_R20E1_LIMITER_ATK_REL_RATES 0x20E1
+#define MAX98373_R20E2_LIMITER_EN 0x20E2
+#define MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG 0x20FE
+#define MAX98373_R20FF_GLOBAL_SHDN 0x20FF
+#define MAX98373_R21FF_REV_ID 0x21FF
+
+/* MAX98373_R2022_PCM_TX_SRC_1 */
+#define MAX98373_PCM_TX_CH_SRC_A_V_SHIFT (0)
+#define MAX98373_PCM_TX_CH_SRC_A_I_SHIFT (4)
+
+/* MAX98373_R2024_PCM_DATA_FMT_CFG */
+#define MAX98373_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3)
+#define MAX98373_PCM_MODE_CFG_FORMAT_SHIFT (3)
+#define MAX98373_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 2)
+#define MAX98373_PCM_FORMAT_I2S (0x0 << 0)
+#define MAX98373_PCM_FORMAT_LJ (0x1 << 0)
+#define MAX98373_PCM_FORMAT_TDM_MODE0 (0x3 << 0)
+#define MAX98373_PCM_FORMAT_TDM_MODE1 (0x4 << 0)
+#define MAX98373_PCM_FORMAT_TDM_MODE2 (0x5 << 0)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
+#define MAX98373_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6)
+
+/* MAX98373_R2026_PCM_CLOCK_RATIO */
+#define MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 4)
+#define MAX98373_PCM_CLK_SETUP_BSEL_MASK (0xF << 0)
+
+/* MAX98373_R2027_PCM_SR_SETUP_1 */
+#define MAX98373_PCM_SR_SET1_SR_MASK (0xF << 0)
+#define MAX98373_PCM_SR_SET1_SR_8000 (0x0 << 0)
+#define MAX98373_PCM_SR_SET1_SR_11025 (0x1 << 0)
+#define MAX98373_PCM_SR_SET1_SR_12000 (0x2 << 0)
+#define MAX98373_PCM_SR_SET1_SR_16000 (0x3 << 0)
+#define MAX98373_PCM_SR_SET1_SR_22050 (0x4 << 0)
+#define MAX98373_PCM_SR_SET1_SR_24000 (0x5 << 0)
+#define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0)
+#define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0)
+#define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0)
+
+/* MAX98373_R2028_PCM_SR_SETUP_2 */
+#define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4)
+#define MAX98373_PCM_SR_SET2_SR_SHIFT (4)
+#define MAX98373_PCM_SR_SET2_IVADC_SR_MASK (0xF << 0)
+
+/* MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 */
+#define MAX98373_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6)
+#define MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6)
+#define MAX98373_PCM_TO_SPK_CH0_SRC_MASK (0xF << 0)
+
+/* MAX98373_R203E_AMP_PATH_GAIN */
+#define MAX98373_SPK_DIGI_GAIN_MASK (0xF << 4)
+#define MAX98373_SPK_DIGI_GAIN_SHIFT (4)
+#define MAX98373_FS_GAIN_MAX_MASK (0xF << 0)
+#define MAX98373_FS_GAIN_MAX_SHIFT (0)
+
+/* MAX98373_R203F_AMP_DSP_CFG */
+#define MAX98373_AMP_DSP_CFG_DCBLK_SHIFT (0)
+#define MAX98373_AMP_DSP_CFG_DITH_SHIFT (1)
+#define MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT (2)
+#define MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT (3)
+#define MAX98373_AMP_DSP_CFG_DAC_INV_SHIFT (5)
+#define MAX98373_AMP_VOL_SEL_SHIFT (7)
+
+/* MAX98373_R2043_AMP_EN */
+#define MAX98373_SPKFB_EN_MASK (0x1 << 1)
+#define MAX98373_SPK_EN_MASK (0x1 << 0)
+#define MAX98373_SPKFB_EN_SHIFT (1)
+
+/*MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG */
+#define MAX98373_FLT_EN_SHIFT (4)
+
+/* MAX98373_R20B2_BDE_L4_CFG_2 */
+#define MAX98373_LVL4_MUTE_EN_SHIFT (7)
+#define MAX98373_LVL4_HOLD_EN_SHIFT (6)
+
+/* MAX98373_R20B5_BDE_EN */
+#define MAX98373_BDE_EN_SHIFT (0)
+
+/* MAX98373_R20D1_DHT_CFG */
+#define MAX98373_DHT_SPK_GAIN_MIN_SHIFT (4)
+#define MAX98373_DHT_ROT_PNT_SHIFT (0)
+
+/* MAX98373_R20D2_DHT_ATTACK_CFG */
+#define MAX98373_DHT_ATTACK_STEP_SHIFT (3)
+#define MAX98373_DHT_ATTACK_RATE_SHIFT (0)
+
+/* MAX98373_R20D3_DHT_RELEASE_CFG */
+#define MAX98373_DHT_RELEASE_STEP_SHIFT (3)
+#define MAX98373_DHT_RELEASE_RATE_SHIFT (0)
+
+/* MAX98373_R20D4_DHT_EN */
+#define MAX98373_DHT_EN_SHIFT (0)
+
+/* MAX98373_R20E0_LIMITER_THRESH_CFG */
+#define MAX98373_LIMITER_THRESH_SHIFT (2)
+#define MAX98373_LIMITER_THRESH_SRC_SHIFT (0)
+
+/* MAX98373_R20E2_LIMITER_EN */
+#define MAX98373_LIMITER_EN_SHIFT (0)
+
+/* MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG */
+#define MAX98373_CLOCK_MON_SHIFT (0)
+
+/* MAX98373_R20FF_GLOBAL_SHDN */
+#define MAX98373_GLOBAL_EN_MASK (0x1 << 0)
+
+/* MAX98373_R2000_SW_RESET */
+#define MAX98373_SOFT_RESET (0x1 << 0)
+
+struct max98373_priv {
+ struct regmap *regmap;
+ struct snd_soc_codec *codec;
+ unsigned int sysclk;
+ unsigned int v_slot;
+ unsigned int i_slot;
+ unsigned int spkfb_slot;
+ bool interleave_mode;
+ unsigned int ch_size;
+ unsigned int iface;
+ bool tdm_mode;
+};
+#endif
--
2.7.4
4
6
[alsa-devel] [PATCH v6 0/6] ASoC: Intel: Skylake: Add a clk driver to enable ssp clks early
by Sriram Periyasamy 03 Jan '18
by Sriram Periyasamy 03 Jan '18
03 Jan '18
For certain platforms, clocks (mclk/sclk/fs) are required to be up before
the stream start. Example: some codecs needs the mclk/sclk/fs to be
enabled early for a successful clock synchronization. Some platforms
require clock to be enabled at boot and be always ON.
By sending set_dma_control IPC (with the i2s blobs queried from NHLT),
these clocks can be enabled early after the firmware is downloaded.
With this series, a virtual clock driver is created which provides
interface to send the required IPCs from machine driver to enable the
clocks. NHLT is parsed during probe and the clock information is populated.
The pointer to blob is cached and sent along with the set_dma_control IPC
structure during the clk prepare/unprepare callback. Clocks are created for
a ssp if the nhlt table has endpoint configuration for that particular ssp.
Kabylake machine driver uses the clock interface to enable the clocks early
as it is required by the rt5663 driver for clock synchronization.
v5 -> v6
- Remove unwanted checks from clk ops
- Modify recalc_rate to return just the cached rate and remove the
rate calculations
- Add license based on SPDX
v4 -> v5
- Remove checks for clock enable status from machine driver since
taken care in the framework already
- Add check in the skl_clk_set_rate to avoid different rates when
clock is enabled already
v3 -> v4
- Add missing signed-offs
v2 -> v3
- Moved the clk ops and IPCs from Skylake driver to clk driver and
reordered commits accordingly
- Add the support for extended I2S blob config which supports
multiple mclk dividers in NHLT
- Enable the clocks as well in DAPM PMU event instead of hw_params
in machine drivers as confirmed by codec vendor
- Do not register the clk if there is no valid clock source is
avail in the I2S blob
- Take care of error return in the clk driver
- Address rest of the review comments and more optimization added
- Fix the warning
sound/soc/intel/skylake/skl.c:724:1-3:
WARNING: PTR_ERR_OR_ZERO can be used
reported by scripts/coccinelle/api/ptr_ret.cocci
- Modified DSP replies as human readable to ease the debugging
- Add firmware replies for MCLK/SCLK clocks if they are running
already
v1 -> v2
- Register parent clocks with skylake device.
With the patch "clk: Add support for runtime PM" soon to be merged
will help DSP to stay active on call to clock enable.
Reference: (https://patchwork.kernel.org/patch/9911741/)
- Fix the machine driver to enable clocks early for headphone
playback path as well to fix a pop noise issue
Harsha Priya (1):
ASoC: Intel: kbl: Enable mclk and ssp sclk early
Naveen M (1):
ASoC: Intel: eve: Enable mclk and ssp sclk early
Sriram Periyasamy (2):
ASoC: Intel: Skylake: Add ssp clock driver
ASoC: Intel: Skylake: Add extended I2S config blob support in Clock
driver
Subhransu S. Prusty (2):
ASoC: Intel: Skylake: Make DSP replies more human readable
ASoC: Intel: Skylake: Add FW reply for MCLK/SCLK IPC
sound/soc/intel/Kconfig | 3 +
sound/soc/intel/boards/Kconfig | 2 +
sound/soc/intel/boards/kbl_rt5663_max98927.c | 95 ++++-
.../soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 94 +++++
sound/soc/intel/skylake/Makefile | 5 +
sound/soc/intel/skylake/skl-i2s.h | 31 ++
sound/soc/intel/skylake/skl-messages.c | 1 +
sound/soc/intel/skylake/skl-nhlt.c | 41 +-
sound/soc/intel/skylake/skl-ssp-clk.c | 432 +++++++++++++++++++++
sound/soc/intel/skylake/skl-ssp-clk.h | 38 ++
sound/soc/intel/skylake/skl-sst-ipc.c | 50 ++-
sound/soc/intel/skylake/skl.h | 6 +
12 files changed, 774 insertions(+), 24 deletions(-)
create mode 100644 sound/soc/intel/skylake/skl-ssp-clk.c
--
2.7.4
4
10
[alsa-devel] Cherry Trail + RT5645 devices analog microphone not working.
by Hans de Goede 02 Jan '18
by Hans de Goede 02 Jan '18
02 Jan '18
Hi Bard,
I've been looking into getting the microphone to work on
some Cherry Trail + RT5645 devices with what appears to
be a simple analog microphone.
You can see the microphone on one of the models I'm trying
to get it to work on soldered onto the right side of the PCB
here: https://i.imgur.com/bJzBQWe.jpg
I'm using this ucm config:
https://fedorapeople.org/~jwrdegoede/chtrt5645/
Which is basically Pierre-Louis Bossart's config from:
https://github.com/plbossart/UCM
Adjusted because the devices all have a mono speaker.
I've been trying to get this to work myself and I can get
some sound while recording by adding:
cset "name='RECMIXL BST2 Switch' on"
cset "name='RECMIXR BST2 Switch' on"
But then I mainly get noise, I do get some sound from the
microphone if I talk really really loudly, but it is
barely above the noise-floor. I've the feeling that BST2
is only picking up the microphone via cross-talk and
that BST1 indeed is the correct input, but for some reason
I get complete silence when recording when only BST1 is
selected in the RECMIXR, and yes I've checked / set the
"IN1 boost volume".
TL;DR: I'm trying to get an analog mic to work on 3
different models Cherry Trail + RT5645 devices and I've
been unable to get this to work. I've put a registerdump
of the rt5645 with gnome-sound-recorder running here:
https://fedorapeople.org/~jwrdegoede/rt5645-mic-red.dump
Any insights / help with this would be very much
welcome.
Regards,
Hans
2
10