All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: Add max98925 codec driver
@ 2015-03-09 22:50 Anish Kumar
  2015-03-11 18:27 ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: Anish Kumar @ 2015-03-09 22:50 UTC (permalink / raw)
  To: broonie, perex, tiwai; +Cc: alsa-devel, Anish Kumar

Signed-off-by: Anish Kumar <yesanishhere@gmail.com>
---
changes in this version:
        - addressed mark brown comments regarding
          probe function.
        - changed the mixer namings
        - added device tree documentation
changes since v1:
	- addressed mark brown comments regarding
	  open coding functions.
	- changed the mixer namings
	- added some dapm widgets
 .../devicetree/bindings/sound/max98925.txt         |  22 +
 sound/soc/codecs/Kconfig                           |   4 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/max98925.c                        | 655 ++++++++++++++++
 sound/soc/codecs/max98925.h                        | 832 +++++++++++++++++++++
 5 files changed, 1515 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/max98925.txt
 create mode 100644 sound/soc/codecs/max98925.c
 create mode 100644 sound/soc/codecs/max98925.h

diff --git a/Documentation/devicetree/bindings/sound/max98925.txt b/Documentation/devicetree/bindings/sound/max98925.txt
new file mode 100644
index 0000000..27be63e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/max98925.txt
@@ -0,0 +1,22 @@
+max98925 audio CODEC
+
+This device supports I2C.
+
+Required properties:
+
+  - compatible : "maxim,max98925"
+
+  - vmon-slot-no : slot number used to send voltage information
+
+  - imon-slot-no : slot number used to send current information
+
+  - reg : the I2C address of the device for I2C
+
+Example:
+
+codec: max98925@1a {
+	compatible = "maxim,max98925";
+	vmon-slot-no = <0>;
+	imon-slot-no = <2>;
+	reg = <0x1a>;
+};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0bddd92..a7f44e3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -68,6 +68,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_LM49453 if I2C
 	select SND_SOC_MAX98088 if I2C
 	select SND_SOC_MAX98090 if I2C
+	select SND_SOC_MAX98925 if I2C
 	select SND_SOC_MAX98095 if I2C
 	select SND_SOC_MAX98357A if GPIOLIB
 	select SND_SOC_MAX9850 if I2C
@@ -455,6 +456,9 @@ config SND_SOC_MAX98088
 config SND_SOC_MAX98090
        tristate
 
+config SND_SOC_MAX98925
+       tristate
+
 config SND_SOC_MAX98095
        tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 7acb6c1..1658d19 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -63,6 +63,7 @@ snd-soc-lm49453-objs := lm49453.o
 snd-soc-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98090-objs := max98090.o
+snd-soc-max98925-objs := max98925.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max98357a-objs := max98357a.o
 snd-soc-max9850-objs := max9850.o
@@ -247,6 +248,7 @@ obj-$(CONFIG_SND_SOC_LM49453)   += snd-soc-lm49453.o
 obj-$(CONFIG_SND_SOC_MAX9768)	+= snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98090)	+= snd-soc-max98090.o
+obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX98357A)	+= snd-soc-max98357a.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c
new file mode 100644
index 0000000..74f4f0b
--- /dev/null
+++ b/sound/soc/codecs/max98925.c
@@ -0,0 +1,655 @@
+/*
+ * max98925.c -- ALSA SoC Stereo MAX98925 driver
+ * Copyright 2013-15 Maxim Integrated Products
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.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 <sound/tlv.h>
+#include "max98925.h"
+
+static const char *const dai_text[] = {
+	"Left", "Right", "LeftRight", "LeftRightDiv2",
+};
+
+static const char * const max98925_boost_voltage_text[] = {
+	"8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V",
+	"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V",	"6.5V", "6.5V"
+};
+
+static SOC_ENUM_SINGLE_DECL(max98925_boost_voltage,
+	MAX98925_CONFIGURATION, M98925_BST_VOUT_SHIFT,
+	max98925_boost_voltage_text);
+
+static const char *const hpf_text[] = {
+	"Disable", "DC Block", "100Hz",	"200Hz", "400Hz", "800Hz",
+};
+
+static struct reg_default max98925_reg[] = {
+	{ 0x0B, 0x00 }, /* IRQ Enable0 */
+	{ 0x0C, 0x00 }, /* IRQ Enable1 */
+	{ 0x0D, 0x00 }, /* IRQ Enable2 */
+	{ 0x0E, 0x00 }, /* IRQ Clear0 */
+	{ 0x0F, 0x00 }, /* IRQ Clear1 */
+	{ 0x10, 0x00 }, /* IRQ Clear2 */
+	{ 0x11, 0xC0 }, /* Map0 */
+	{ 0x12, 0x00 }, /* Map1 */
+	{ 0x13, 0x00 }, /* Map2 */
+	{ 0x14, 0xF0 }, /* Map3 */
+	{ 0x15, 0x00 }, /* Map4 */
+	{ 0x16, 0xAB }, /* Map5 */
+	{ 0x17, 0x89 }, /* Map6 */
+	{ 0x18, 0x00 }, /* Map7 */
+	{ 0x19, 0x00 }, /* Map8 */
+	{ 0x1A, 0x06 }, /* DAI Clock Mode 1 */
+	{ 0x1B, 0xC0 }, /* DAI Clock Mode 2 */
+	{ 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */
+	{ 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */
+	{ 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */
+	{ 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */
+	{ 0x20, 0x50 }, /* Format */
+	{ 0x21, 0x00 }, /* TDM Slot Select */
+	{ 0x22, 0x00 }, /* DOUT Configuration VMON */
+	{ 0x23, 0x00 }, /* DOUT Configuration IMON */
+	{ 0x24, 0x00 }, /* DOUT Configuration VBAT */
+	{ 0x25, 0x00 }, /* DOUT Configuration VBST */
+	{ 0x26, 0x00 }, /* DOUT Configuration FLAG */
+	{ 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */
+	{ 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */
+	{ 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */
+	{ 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */
+	{ 0x2B, 0x02 }, /* DOUT Drive Strength */
+	{ 0x2C, 0x90 }, /* Filters */
+	{ 0x2D, 0x00 }, /* Gain */
+	{ 0x2E, 0x02 }, /* Gain Ramping */
+	{ 0x2F, 0x00 }, /* Speaker Amplifier */
+	{ 0x30, 0x0A }, /* Threshold */
+	{ 0x31, 0x00 }, /* ALC Attack */
+	{ 0x32, 0x80 }, /* ALC Atten and Release */
+	{ 0x33, 0x00 }, /* ALC Infinite Hold Release */
+	{ 0x34, 0x92 }, /* ALC Configuration */
+	{ 0x35, 0x01 }, /* Boost Converter */
+	{ 0x36, 0x00 }, /* Block Enable */
+	{ 0x37, 0x00 }, /* Configuration */
+	{ 0x38, 0x00 }, /* Global Enable */
+	{ 0x3A, 0x00 }, /* Boost Limiter */
+};
+
+static const struct soc_enum max98925_dai_enum =
+	SOC_ENUM_SINGLE(MAX98925_GAIN, 5, ARRAY_SIZE(dai_text), dai_text);
+
+static const struct soc_enum max98925_hpf_enum =
+	SOC_ENUM_SINGLE(MAX98925_FILTERS, 0, ARRAY_SIZE(hpf_text), hpf_text);
+
+static const struct snd_kcontrol_new max98925_hpf_sel_mux =
+	SOC_DAPM_ENUM("Rc Filter MUX Mux", max98925_hpf_enum);
+
+static const struct snd_kcontrol_new max98925_dai_sel_mux =
+	SOC_DAPM_ENUM("DAI IN MUX Mux", max98925_dai_enum);
+
+static int max98925_dac_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_BLOCK_ENABLE,
+			M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
+			M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_BLOCK_ENABLE, M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK, 0);
+		break;
+	default:
+		return 0;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget max98925_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_MUX("DAI IN MUX", SND_SOC_NOPM, 0, 0,
+				&max98925_dai_sel_mux),
+	SND_SOC_DAPM_MUX("Rc Filter MUX", SND_SOC_NOPM, 0, 0,
+				&max98925_hpf_sel_mux),
+	SND_SOC_DAPM_DAC_E("Amp Enable", NULL, MAX98925_BLOCK_ENABLE,
+			M98925_SPK_EN_SHIFT, 0, max98925_dac_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("Global Enable", MAX98925_GLOBAL_ENABLE,
+			M98925_EN_SHIFT, 0, NULL, 0),
+	SND_SOC_DAPM_OUTPUT("BE_OUT"),
+};
+
+static const struct snd_soc_dapm_route max98925_audio_map[] = {
+	{"DAI IN MUX", "Left", "DAI_OUT"},
+	{"DAI IN MUX", "Right", "DAI_OUT"},
+	{"DAI IN MUX", "LeftRight", "DAI_OUT"},
+	{"DAI IN MUX", "LeftRightDiv2", "DAI_OUT"},
+	{"Rc Filter MUX", "Disable", "DAI IN MUX"},
+	{"Rc Filter MUX", "DC Block", "DAI IN MUX"},
+	{"Rc Filter MUX", "100Hz", "DAI IN MUX"},
+	{"Rc Filter MUX", "200Hz", "DAI IN MUX"},
+	{"Rc Filter MUX", "400Hz", "DAI IN MUX"},
+	{"Rc Filter MUX", "800Hz", "DAI IN MUX"},
+	{"Amp Enable", NULL, "Rc Filter MUX"},
+	{"BE_OUT", NULL, "Amp Enable"},
+	{"BE_OUT", NULL, "Global Enable"},
+};
+
+static bool max98925_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_VBAT_DATA:
+	case MAX98925_VBST_DATA:
+	case MAX98925_LIVE_STATUS0:
+	case MAX98925_LIVE_STATUS1:
+	case MAX98925_LIVE_STATUS2:
+	case MAX98925_STATE0:
+	case MAX98925_STATE1:
+	case MAX98925_STATE2:
+	case MAX98925_FLAG0:
+	case MAX98925_FLAG1:
+	case MAX98925_FLAG2:
+	case MAX98925_REV_VERSION:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max98925_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_IRQ_CLEAR0:
+	case MAX98925_IRQ_CLEAR1:
+	case MAX98925_IRQ_CLEAR2:
+	case MAX98925_ALC_HOLD_RLS:
+		return false;
+	default:
+		return true;
+	}
+}
+
+DECLARE_TLV_DB_SCALE(max98925_spk_tlv, -600, 100, 0);
+
+static const struct snd_kcontrol_new max98925_snd_controls[] = {
+	SOC_SINGLE_TLV("Speaker Volume", MAX98925_GAIN,
+		M98925_SPK_GAIN_SHIFT, (1<<M98925_SPK_GAIN_WIDTH)-1, 0,
+		max98925_spk_tlv),
+	SOC_SINGLE("Ramp Switch", MAX98925_GAIN_RAMPING,
+				M98925_SPK_RMP_EN_SHIFT, 1, 0),
+	SOC_SINGLE("ZCD Switch", MAX98925_GAIN_RAMPING,
+				M98925_SPK_ZCD_EN_SHIFT, 1, 0),
+	SOC_SINGLE("ALC Switch", MAX98925_THRESHOLD,
+				M98925_ALC_EN_SHIFT, 1, 0),
+	SOC_SINGLE("ALC Threshold", MAX98925_THRESHOLD, M98925_ALC_TH_SHIFT,
+				(1<<M98925_ALC_TH_WIDTH)-1, 0),
+	SOC_ENUM("Boost Output Voltage", max98925_boost_voltage),
+};
+
+/* codec sample rate and n/m dividers parameter table */
+static const struct {
+	int rate;
+	int  sr;
+	int divisors[3][2];
+} rate_table[] = {
+	{
+		.rate = 8000,
+		.sr = 0,
+		.divisors = { {1, 375}, {5, 1764}, {1, 384} }
+	},
+	{
+		.rate = 11025,
+		.sr = 1,
+		.divisors = { {147, 40000}, {1, 256}, {147, 40960} }
+	},
+	{
+		.rate = 12000,
+		.sr = 2,
+		.divisors = { {1, 250}, {5, 1176}, {1, 256} }
+	},
+	{
+		.rate = 16000,
+		.sr = 3,
+		.divisors = { {2, 375}, {5, 882}, {1, 192} }
+	},
+	{
+		.rate = 22050,
+		.sr = 4,
+		.divisors = { {147, 20000}, {1, 128}, {147, 20480} }
+	},
+	{
+		.rate = 24000,
+		.sr = 5,
+		.divisors = { {1, 125}, {5, 588}, {1, 128} }
+	},
+	{
+		.rate = 32000,
+		.sr = 6,
+		.divisors = { {4, 375}, {5, 441}, {1, 96} }
+	},
+	{
+		.rate = 44100,
+		.sr = 7,
+		.divisors = { {147, 10000}, {1, 64}, {147, 10240} }
+	},
+	{
+		.rate = 48000,
+		.sr = 8,
+		.divisors = { {2, 125}, {5, 294}, {1, 64} }
+	},
+};
+
+static inline int max98925_rate_value(struct snd_soc_codec *codec,
+		int rate, int clock, int *value, int *n, int *m)
+{
+	int ret = -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+		if (rate_table[i].rate >= rate) {
+			*value = rate_table[i].sr;
+			*n = rate_table[i].divisors[clock][0];
+			*m = rate_table[i].divisors[clock][1];
+			ret = 0;
+			break;
+		}
+	}
+	dev_dbg(codec->dev, "%s: sample rate is %d, returning %d\n",
+				__func__, rate_table[i].rate, *value);
+	return ret;
+}
+
+static void max98925_set_sense_data(struct max98925_priv *max98925)
+{
+	/* set VMON slots */
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_VMON,
+		M98925_DAI_VMON_EN_MASK, M98925_DAI_VMON_EN_MASK);
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_VMON,
+		M98925_DAI_VMON_SLOT_MASK,
+		max98925->v_slot << M98925_DAI_VMON_SLOT_SHIFT);
+	/* set IMON slots */
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_IMON,
+		M98925_DAI_IMON_EN_MASK, M98925_DAI_IMON_EN_MASK);
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_IMON,
+		M98925_DAI_IMON_SLOT_MASK,
+		max98925->i_slot << M98925_DAI_IMON_SLOT_SHIFT);
+}
+
+static int max98925_dai_set_fmt(struct snd_soc_dai *codec_dai,
+				 unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int invert = 0;
+
+	dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		/* set DAI to slave mode */
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, 0);
+		max98925_set_sense_data(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		/*
+		 * set left channel DAI to master mode,
+		 * right channel always slave
+		 */
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, M98925_DAI_MAS_MASK);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+	default:
+		dev_err(codec->dev, "DAI clock mode unsupported");
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		invert = M98925_DAI_WCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert = M98925_DAI_BCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		invert = M98925_DAI_BCI_MASK | M98925_DAI_WCI_MASK;
+		break;
+	default:
+		dev_err(codec->dev, "DAI invert mode unsupported");
+		return -EINVAL;
+	}
+
+	regmap_update_bits(max98925->regmap, MAX98925_FORMAT,
+			M98925_DAI_BCI_MASK | M98925_DAI_BCI_MASK, invert);
+	return 0;
+}
+
+static int max98925_set_clock(struct max98925_priv *max98925,
+		struct snd_pcm_hw_params *params)
+{
+	unsigned int dai_sr = 0, clock, mdll, n, m;
+	struct snd_soc_codec *codec = max98925->codec;
+	int rate = params_rate(params);
+	/* BCLK/LRCLK ratio calculation */
+	int blr_clk_ratio = params_channels(params) * max98925->ch_size;
+
+	switch (blr_clk_ratio) {
+	case 32:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_32);
+		break;
+	case 48:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_48);
+		break;
+	case 64:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (max98925->sysclk) {
+	case 6000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx16;
+		break;
+	case 11289600:
+		clock = 1;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12288000:
+		clock = 2;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	default:
+		dev_info(max98925->codec->dev, "unsupported sysclk %d\n",
+					max98925->sysclk);
+		return -EINVAL;
+	}
+
+	if (max98925_rate_value(codec, rate, clock, &dai_sr, &n, &m))
+		return -EINVAL;
+
+	/* set DAI_SR to correct LRCLK frequency */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_SR_MASK, dai_sr << M98925_DAI_SR_SHIFT);
+	/* set DAI m divider */
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_M_MSBS, m >> 8);
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_M_LSBS, m & 0xFF);
+	/* set DAI n divider */
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_N_MSBS, n >> 8);
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_N_LSBS, n & 0xFF);
+	/* set MDLL */
+	regmap_update_bits(max98925->regmap, MAX98925_DAI_CLK_MODE1,
+			M98925_MDLL_MULT_MASK, mdll << M98925_MDLL_MULT_SHIFT);
+	return 0;
+}
+
+static int max98925_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 max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (snd_pcm_format_width(params_format(params))) {
+	case 16:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_16);
+		max98925->ch_size = 16;
+		break;
+	case 24:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		max98925->ch_size = 32;
+		break;
+	case 32:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		max98925->ch_size = 32;
+		break;
+	default:
+		pr_err("%s: format unsupported %d",
+				__func__, params_format(params));
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "%s: format supported %d",
+				__func__, params_format(params));
+	return max98925_set_clock(max98925, params);
+}
+
+static int max98925_dai_set_sysclk(struct snd_soc_dai *dai,
+				   int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case 0:
+		/* use MCLK for Left channel, right channel always BCLK */
+		regmap_update_bits(max98925->regmap,
+				MAX98925_DAI_CLK_MODE1,
+				M98925_DAI_CLK_SOURCE_MASK, 0);
+		break;
+	case 1:
+		/* configure dai clock source to BCLK instead of MCLK */
+		regmap_update_bits(max98925->regmap,
+				MAX98925_DAI_CLK_MODE1,
+				M98925_DAI_CLK_SOURCE_MASK,
+				M98925_DAI_CLK_SOURCE_MASK);
+		break;
+	default:
+		return -EINVAL;
+	}
+	max98925->sysclk = freq;
+	return 0;
+}
+
+#define MAX98925_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops max98925_dai_ops = {
+	.set_sysclk = max98925_dai_set_sysclk,
+	.set_fmt = max98925_dai_set_fmt,
+	.hw_params = max98925_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver max98925_dai[] = {
+	{
+		.name = "max98925-aif1",
+		.playback = {
+			.stream_name = "HiFi Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HiFi Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.ops = &max98925_dai_ops,
+	}
+};
+
+static int max98925_probe(struct snd_soc_codec *codec)
+{
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	max98925->codec = codec;
+	codec->control_data = max98925->regmap;
+	regmap_write(max98925->regmap, MAX98925_GLOBAL_ENABLE, 0x00);
+	/* It's not the default but we need to set DAI_DLY */
+	regmap_write(max98925->regmap,
+			MAX98925_FORMAT, M98925_DAI_DLY_MASK);
+	regmap_write(max98925->regmap, MAX98925_TDM_SLOT_SELECT, 0xC8);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG1, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG2, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG3, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG4, 0xF0);
+	regmap_write(max98925->regmap, MAX98925_FILTERS, 0xD8);
+	regmap_write(max98925->regmap, MAX98925_ALC_CONFIGURATION, 0xF8);
+	regmap_write(max98925->regmap, MAX98925_CONFIGURATION, 0xF0);
+	/* Disable ALC muting */
+	regmap_write(max98925->regmap, MAX98925_BOOST_LIMITER, 0xF8);
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98925 = {
+	.probe            = max98925_probe,
+	.controls = max98925_snd_controls,
+	.num_controls = ARRAY_SIZE(max98925_snd_controls),
+	.dapm_routes = max98925_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(max98925_audio_map),
+	.dapm_widgets = max98925_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets),
+};
+
+static struct regmap_config max98925_regmap = {
+	.reg_bits         = 8,
+	.val_bits         = 8,
+	.max_register     = MAX98925_REV_VERSION,
+	.reg_defaults     = max98925_reg,
+	.num_reg_defaults = ARRAY_SIZE(max98925_reg),
+	.volatile_reg     = max98925_volatile_register,
+	.readable_reg     = max98925_readable_register,
+	.cache_type       = REGCACHE_RBTREE,
+};
+
+static int max98925_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	int ret, reg;
+	u32 value;
+	struct max98925_priv *max98925;
+
+	max98925 = devm_kzalloc(&i2c->dev,
+			sizeof(*max98925), GFP_KERNEL);
+	if (!max98925)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, max98925);
+	max98925->regmap = devm_regmap_init_i2c(i2c, &max98925_regmap);
+	if (IS_ERR(max98925->regmap)) {
+		ret = PTR_ERR(max98925->regmap);
+		dev_err(&i2c->dev,
+				"Failed to allocate regmap: %d\n", ret);
+		goto err_out;
+	}
+
+	if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
+		if (value > M98925_DAI_VMON_SLOT_1E_1F) {
+			dev_err(&i2c->dev, "vmon slot number is wrong:\n");
+			return -EINVAL;
+		}
+		max98925->v_slot = value;
+	}
+	if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) {
+		if (value > M98925_DAI_IMON_SLOT_1E_1F) {
+			dev_err(&i2c->dev, "imon slot number is wrong:\n");
+			return -EINVAL;
+		}
+		max98925->i_slot = value;
+	}
+	ret = regmap_read(max98925->regmap,
+			MAX98925_REV_VERSION, &reg);
+	if ((ret < 0) ||
+		((reg != MAX98925_VERSION) &&
+		(reg != MAX98925_VERSION1))) {
+		dev_err(&i2c->dev,
+			"device initialization error (%d 0x%02X)\n",
+			ret, reg);
+		goto err_out;
+	}
+	dev_info(&i2c->dev, "device version 0x%02X\n", reg);
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925,
+			max98925_dai, ARRAY_SIZE(max98925_dai));
+	if (ret < 0)
+		dev_err(&i2c->dev,
+				"Failed to register codec: %d\n", ret);
+err_out:
+	return ret;
+}
+
+static int max98925_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct i2c_device_id max98925_i2c_id[] = {
+	{ "max98925", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max98925_i2c_id);
+
+static const struct of_device_id max98925_of_match[] = {
+	{ .compatible = "maxim,max98925", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max98925_of_match);
+
+static struct i2c_driver max98925_i2c_driver = {
+	.driver = {
+		.name = "max98925",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(max98925_of_match),
+		.pm = NULL,
+	},
+	.probe  = max98925_i2c_probe,
+	.remove = max98925_i2c_remove,
+	.id_table = max98925_i2c_id,
+};
+
+module_i2c_driver(max98925_i2c_driver)
+
+MODULE_DESCRIPTION("ALSA SoC MAX98925 driver");
+MODULE_AUTHOR("Ralph Birt <rdbirt@gmail.com>, Anish kumar <anish.kumar@maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98925.h b/sound/soc/codecs/max98925.h
new file mode 100644
index 0000000..3783248
--- /dev/null
+++ b/sound/soc/codecs/max98925.h
@@ -0,0 +1,832 @@
+/*
+ * max98925.h -- MAX98925 ALSA SoC Audio driver
+ *
+ * Copyright 2013-2015 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX98925_H
+#define _MAX98925_H
+
+#define	MAX98925_VERSION	0x51
+#define	MAX98925_VERSION1	0x80
+#define MAX98925_VBAT_DATA		0x00
+#define MAX98925_VBST_DATA		0x01
+#define MAX98925_LIVE_STATUS0		0x02
+#define MAX98925_LIVE_STATUS1		0x03
+#define MAX98925_LIVE_STATUS2		0x04
+#define MAX98925_STATE0			0x05
+#define MAX98925_STATE1			0x06
+#define MAX98925_STATE2			0x07
+#define MAX98925_FLAG0			0x08
+#define MAX98925_FLAG1			0x09
+#define MAX98925_FLAG2			0x0A
+#define MAX98925_IRQ_ENABLE0		0x0B
+#define MAX98925_IRQ_ENABLE1		0x0C
+#define MAX98925_IRQ_ENABLE2		0x0D
+#define MAX98925_IRQ_CLEAR0		0x0E
+#define MAX98925_IRQ_CLEAR1		0x0F
+#define MAX98925_IRQ_CLEAR2		0x10
+#define MAX98925_MAP0			0x11
+#define MAX98925_MAP1			0x12
+#define MAX98925_MAP2			0x13
+#define MAX98925_MAP3			0x14
+#define MAX98925_MAP4			0x15
+#define MAX98925_MAP5			0x16
+#define MAX98925_MAP6			0x17
+#define MAX98925_MAP7			0x18
+#define MAX98925_MAP8			0x19
+#define MAX98925_DAI_CLK_MODE1		0x1A
+#define MAX98925_DAI_CLK_MODE2		0x1B
+#define MAX98925_DAI_CLK_DIV_M_MSBS	0x1C
+#define MAX98925_DAI_CLK_DIV_M_LSBS	0x1D
+#define MAX98925_DAI_CLK_DIV_N_MSBS	0x1E
+#define MAX98925_DAI_CLK_DIV_N_LSBS	0x1F
+#define MAX98925_FORMAT			0x20
+#define MAX98925_TDM_SLOT_SELECT	0x21
+#define MAX98925_DOUT_CFG_VMON		0x22
+#define MAX98925_DOUT_CFG_IMON		0x23
+#define MAX98925_DOUT_CFG_VBAT		0x24
+#define MAX98925_DOUT_CFG_VBST		0x25
+#define MAX98925_DOUT_CFG_FLAG		0x26
+#define MAX98925_DOUT_HIZ_CFG1		0x27
+#define MAX98925_DOUT_HIZ_CFG2		0x28
+#define MAX98925_DOUT_HIZ_CFG3		0x29
+#define MAX98925_DOUT_HIZ_CFG4		0x2A
+#define MAX98925_DOUT_DRV_STRENGTH	0x2B
+#define MAX98925_FILTERS		0x2C
+#define MAX98925_GAIN			0x2D
+#define MAX98925_GAIN_RAMPING		0x2E
+#define MAX98925_SPK_AMP		0x2F
+#define MAX98925_THRESHOLD		0x30
+#define MAX98925_ALC_ATTACK		0x31
+#define MAX98925_ALC_ATTEN_RLS		0x32
+#define MAX98925_ALC_HOLD_RLS		0x33
+#define MAX98925_ALC_CONFIGURATION	0x34
+#define MAX98925_BOOST_CONVERTER	0x35
+#define MAX98925_BLOCK_ENABLE		0x36
+#define MAX98925_CONFIGURATION		0x37
+#define MAX98925_GLOBAL_ENABLE		0x38
+#define MAX98925_BOOST_LIMITER		0x3A
+#define MAX98925_REV_VERSION		0xFF
+
+#define MAX98925_REG_CNT               (MAX98925_R03A_BOOST_LIMITER+1)
+
+/* MAX98925 Register Bit Fields */
+
+/* MAX98925_R002_LIVE_STATUS0 */
+#define M98925_THERMWARN_STATUS_MASK			(1<<3)
+#define M98925_THERMWARN_STATUS_SHIFT			3
+#define M98925_THERMWARN_STATUS_WIDTH			1
+#define M98925_THERMSHDN_STATUS_MASK			(1<<1)
+#define M98925_THERMSHDN_STATUS_SHIFT			1
+#define M98925_THERMSHDN_STATUS_WIDTH			1
+
+/* MAX98925_R003_LIVE_STATUS1 */
+#define M98925_SPKCURNT_STATUS_MASK			(1<<5)
+#define M98925_SPKCURNT_STATUS_SHIFT			5
+#define M98925_SPKCURNT_STATUS_WIDTH			1
+#define M98925_WATCHFAIL_STATUS_MASK			(1<<4)
+#define M98925_WATCHFAIL_STATUS_SHIFT			4
+#define M98925_WATCHFAIL_STATUS_WIDTH			1
+#define M98925_ALCINFH_STATUS_MASK			(1<<3)
+#define M98925_ALCINFH_STATUS_SHIFT			3
+#define M98925_ALCINFH_STATUS_WIDTH			1
+#define M98925_ALCACT_STATUS_MASK			(1<<2)
+#define M98925_ALCACT_STATUS_SHIFT			2
+#define M98925_ALCACT_STATUS_WIDTH			1
+#define M98925_ALCMUT_STATUS_MASK			(1<<1)
+#define M98925_ALCMUT_STATUS_SHIFT			1
+#define M98925_ALCMUT_STATUS_WIDTH			1
+#define M98925_ACLP_STATUS_MASK				(1<<0)
+#define M98925_ACLP_STATUS_SHIFT			0
+#define M98925_ACLP_STATUS_WIDTH			1
+
+/* MAX98925_R004_LIVE_STATUS2 */
+#define M98925_SLOTOVRN_STATUS_MASK			(1<<6)
+#define M98925_SLOTOVRN_STATUS_SHIFT			6
+#define M98925_SLOTOVRN_STATUS_WIDTH			1
+#define M98925_INVALSLOT_STATUS_MASK			(1<<5)
+#define M98925_INVALSLOT_STATUS_SHIFT			5
+#define M98925_INVALSLOT_STATUS_WIDTH			1
+#define M98925_SLOTCNFLT_STATUS_MASK			(1<<4)
+#define M98925_SLOTCNFLT_STATUS_SHIFT			4
+#define M98925_SLOTCNFLT_STATUS_WIDTH			1
+#define M98925_VBSTOVFL_STATUS_MASK			(1<<3)
+#define M98925_VBSTOVFL_STATUS_SHIFT			3
+#define M98925_VBSTOVFL_STATUS_WIDTH			1
+#define M98925_VBATOVFL_STATUS_MASK			(1<<2)
+#define M98925_VBATOVFL_STATUS_SHIFT			2
+#define M98925_VBATOVFL_STATUS_WIDTH			1
+#define M98925_IMONOVFL_STATUS_MASK			(1<<1)
+#define M98925_IMONOVFL_STATUS_SHIFT			1
+#define M98925_IMONOVFL_STATUS_WIDTH			1
+#define M98925_VMONOVFL_STATUS_MASK			(1<<0)
+#define M98925_VMONOVFL_STATUS_SHIFT			0
+#define M98925_VMONOVFL_STATUS_WIDTH			1
+
+/* MAX98925_R005_STATE0 */
+#define M98925_THERMWARN_END_STATE_MASK			(1<<3)
+#define M98925_THERMWARN_END_STATE_SHIFT		3
+#define M98925_THERMWARN_END_STATE_WIDTH		1
+#define M98925_THERMWARN_BGN_STATE_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_STATE_SHIFT		1
+#define M98925_THERMWARN_BGN_STATE_WIDTH		1
+#define M98925_THERMSHDN_END_STATE_MASK			(1<<1)
+#define M98925_THERMSHDN_END_STATE_SHIFT		1
+#define M98925_THERMSHDN_END_STATE_WIDTH		1
+#define M98925_THERMSHDN_BGN_STATE_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_STATE_SHIFT		0
+#define M98925_THERMSHDN_BGN_STATE_WIDTH		1
+
+/* MAX98925_R006_STATE1 */
+#define M98925_SPRCURNT_STATE_MASK			(1<<5)
+#define M98925_SPRCURNT_STATE_SHIFT			5
+#define M98925_SPRCURNT_STATE_WIDTH			1
+#define M98925_WATCHFAIL_STATE_MASK			(1<<4)
+#define M98925_WATCHFAIL_STATE_SHIFT			4
+#define M98925_WATCHFAIL_STATE_WIDTH			1
+#define M98925_ALCINFH_STATE_MASK			(1<<3)
+#define M98925_ALCINFH_STATE_SHIFT			3
+#define M98925_ALCINFH_STATE_WIDTH			1
+#define M98925_ALCACT_STATE_MASK			(1<<2)
+#define M98925_ALCACT_STATE_SHIFT			2
+#define M98925_ALCACT_STATE_WIDTH			1
+#define M98925_ALCMUT_STATE_MASK			(1<<1)
+#define M98925_ALCMUT_STATE_SHIFT			1
+#define M98925_ALCMUT_STATE_WIDTH			1
+#define M98925_ALCP_STATE_MASK				(1<<0)
+#define M98925_ALCP_STATE_SHIFT				0
+#define M98925_ALCP_STATE_WIDTH				1
+
+/* MAX98925_R007_STATE2 */
+#define M98925_SLOTOVRN_STATE_MASK			(1<<6)
+#define M98925_SLOTOVRN_STATE_SHIFT			6
+#define M98925_SLOTOVRN_STATE_WIDTH			1
+#define M98925_INVALSLOT_STATE_MASK			(1<<5)
+#define M98925_INVALSLOT_STATE_SHIFT			5
+#define M98925_INVALSLOT_STATE_WIDTH			1
+#define M98925_SLOTCNFLT_STATE_MASK			(1<<4)
+#define M98925_SLOTCNFLT_STATE_SHIFT			4
+#define M98925_SLOTCNFLT_STATE_WIDTH			1
+#define M98925_VBSTOVFL_STATE_MASK			(1<<3)
+#define M98925_VBSTOVFL_STATE_SHIFT			3
+#define M98925_VBSTOVFL_STATE_WIDTH			1
+#define M98925_VBATOVFL_STATE_MASK			(1<<2)
+#define M98925_VBATOVFL_STATE_SHIFT			2
+#define M98925_VBATOVFL_STATE_WIDTH			1
+#define M98925_IMONOVFL_STATE_MASK			(1<<1)
+#define M98925_IMONOVFL_STATE_SHIFT			1
+#define M98925_IMONOVFL_STATE_WIDTH			1
+#define M98925_VMONOVFL_STATE_MASK			(1<<0)
+#define M98925_VMONOVFL_STATE_SHIFT			0
+#define M98925_VMONOVFL_STATE_WIDTH			1
+
+/* MAX98925_R008_FLAG0 */
+#define M98925_THERMWARN_END_FLAG_MASK			(1<<3)
+#define M98925_THERMWARN_END_FLAG_SHIFT			3
+#define M98925_THERMWARN_END_FLAG_WIDTH			1
+#define M98925_THERMWARN_BGN_FLAG_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_FLAG_SHIFT			2
+#define M98925_THERMWARN_BGN_FLAG_WIDTH			1
+#define M98925_THERMSHDN_END_FLAG_MASK			(1<<1)
+#define M98925_THERMSHDN_END_FLAG_SHIFT			1
+#define M98925_THERMSHDN_END_FLAG_WIDTH			1
+#define M98925_THERMSHDN_BGN_FLAG_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_FLAG_SHIFT			0
+#define M98925_THERMSHDN_BGN_FLAG_WIDTH			1
+
+/* MAX98925_R009_FLAG1 */
+#define M98925_SPKCURNT_FLAG_MASK			(1<<5)
+#define M98925_SPKCURNT_FLAG_SHIFT			5
+#define M98925_SPKCURNT_FLAG_WIDTH			1
+#define M98925_WATCHFAIL_FLAG_MASK			(1<<4)
+#define M98925_WATCHFAIL_FLAG_SHIFT			4
+#define M98925_WATCHFAIL_FLAG_WIDTH			1
+#define M98925_ALCINFH_FLAG_MASK			(1<<3)
+#define M98925_ALCINFH_FLAG_SHIFT			3
+#define M98925_ALCINFH_FLAG_WIDTH			1
+#define M98925_ALCACT_FLAG_MASK				(1<<2)
+#define M98925_ALCACT_FLAG_SHIFT			2
+#define M98925_ALCACT_FLAG_WIDTH			1
+#define M98925_ALCMUT_FLAG_MASK				(1<<1)
+#define M98925_ALCMUT_FLAG_SHIFT			1
+#define M98925_ALCMUT_FLAG_WIDTH			1
+#define M98925_ALCP_FLAG_MASK				(1<<0)
+#define M98925_ALCP_FLAG_SHIFT				0
+#define M98925_ALCP_FLAG_WIDTH				1
+
+/* MAX98925_R00A_FLAG2 */
+#define M98925_SLOTOVRN_FLAG_MASK			(1<<6)
+#define M98925_SLOTOVRN_FLAG_SHIFT			6
+#define M98925_SLOTOVRN_FLAG_WIDTH			1
+#define M98925_INVALSLOT_FLAG_MASK			(1<<5)
+#define M98925_INVALSLOT_FLAG_SHIFT			5
+#define M98925_INVALSLOT_FLAG_WIDTH			1
+#define M98925_SLOTCNFLT_FLAG_MASK			(1<<4)
+#define M98925_SLOTCNFLT_FLAG_SHIFT			4
+#define M98925_SLOTCNFLT_FLAG_WIDTH			1
+#define M98925_VBSTOVFL_FLAG_MASK			(1<<3)
+#define M98925_VBSTOVFL_FLAG_SHIFT			3
+#define M98925_VBSTOVFL_FLAG_WIDTH			1
+#define M98925_VBATOVFL_FLAG_MASK			(1<<2)
+#define M98925_VBATOVFL_FLAG_SHIFT			2
+#define M98925_VBATOVFL_FLAG_WIDTH			1
+#define M98925_IMONOVFL_FLAG_MASK			(1<<1)
+#define M98925_IMONOVFL_FLAG_SHIFT			1
+#define M98925_IMONOVFL_FLAG_WIDTH			1
+#define M98925_VMONOVFL_FLAG_MASK			(1<<0)
+#define M98925_VMONOVFL_FLAG_SHIFT			0
+#define M98925_VMONOVFL_FLAG_WIDTH			1
+
+/* MAX98925_R00B_IRQ_ENABLE0 */
+#define M98925_THERMWARN_END_EN_MASK			(1<<3)
+#define M98925_THERMWARN_END_EN_SHIFT			3
+#define M98925_THERMWARN_END_EN_WIDTH			1
+#define M98925_THERMWARN_BGN_EN_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_EN_SHIFT			2
+#define M98925_THERMWARN_BGN_EN_WIDTH			1
+#define M98925_THERMSHDN_END_EN_MASK			(1<<1)
+#define M98925_THERMSHDN_END_EN_SHIFT			1
+#define M98925_THERMSHDN_END_EN_WIDTH			1
+#define M98925_THERMSHDN_BGN_EN_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_EN_SHIFT			0
+#define M98925_THERMSHDN_BGN_EN_WIDTH			1
+
+/* MAX98925_R00C_IRQ_ENABLE1 */
+#define M98925_SPKCURNT_EN_MASK				(1<<5)
+#define M98925_SPKCURNT_EN_SHIFT			5
+#define M98925_SPKCURNT_EN_WIDTH			1
+#define M98925_WATCHFAIL_EN_MASK			(1<<4)
+#define M98925_WATCHFAIL_EN_SHIFT			4
+#define M98925_WATCHFAIL_EN_WIDTH			1
+#define M98925_ALCINFH_EN_MASK				(1<<3)
+#define M98925_ALCINFH_EN_SHIFT				3
+#define M98925_ALCINFH_EN_WIDTH				1
+#define M98925_ALCACT_EN_MASK				(1<<2)
+#define M98925_ALCACT_EN_SHIFT				2
+#define M98925_ALCACT_EN_WIDTH				1
+#define M98925_ALCMUT_EN_MASK				(1<<1)
+#define M98925_ALCMUT_EN_SHIFT				1
+#define M98925_ALCMUT_EN_WIDTH				1
+#define M98925_ALCP_EN_MASK					(1<<0)
+#define M98925_ALCP_EN_SHIFT				0
+#define M98925_ALCP_EN_WIDTH				1
+
+/* MAX98925_R00D_IRQ_ENABLE2 */
+#define M98925_SLOTOVRN_EN_MASK					(1<<6)
+#define M98925_SLOTOVRN_EN_SHIFT				6
+#define M98925_SLOTOVRN_EN_WIDTH				1
+#define M98925_INVALSLOT_EN_MASK				(1<<5)
+#define M98925_INVALSLOT_EN_SHIFT				5
+#define M98925_INVALSLOT_EN_WIDTH				1
+#define M98925_SLOTCNFLT_EN_MASK				(1<<4)
+#define M98925_SLOTCNFLT_EN_SHIFT				4
+#define M98925_SLOTCNFLT_EN_WIDTH				1
+#define M98925_VBSTOVFL_EN_MASK					(1<<3)
+#define M98925_VBSTOVFL_EN_SHIFT				3
+#define M98925_VBSTOVFL_EN_WIDTH				1
+#define M98925_VBATOVFL_EN_MASK					(1<<2)
+#define M98925_VBATOVFL_EN_SHIFT				2
+#define M98925_VBATOVFL_EN_WIDTH				1
+#define M98925_IMONOVFL_EN_MASK					(1<<1)
+#define M98925_IMONOVFL_EN_SHIFT				1
+#define M98925_IMONOVFL_EN_WIDTH				1
+#define M98925_VMONOVFL_EN_MASK					(1<<0)
+#define M98925_VMONOVFL_EN_SHIFT				0
+#define M98925_VMONOVFL_EN_WIDTH				1
+
+/* MAX98925_R00E_IRQ_CLEAR0 */
+#define M98925_THERMWARN_END_CLR_MASK			(1<<3)
+#define M98925_THERMWARN_END_CLR_SHIFT			3
+#define M98925_THERMWARN_END_CLR_WIDTH			1
+#define M98925_THERMWARN_BGN_CLR_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_CLR_SHIFT			2
+#define M98925_THERMWARN_BGN_CLR_WIDTH			1
+#define M98925_THERMSHDN_END_CLR_MASK			(1<<1)
+#define M98925_THERMSHDN_END_CLR_SHIFT			1
+#define M98925_THERMSHDN_END_CLR_WIDTH			1
+#define M98925_THERMSHDN_BGN_CLR_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_CLR_SHIFT			0
+#define M98925_THERMSHDN_BGN_CLR_WIDTH			1
+
+/* MAX98925_R00F_IRQ_CLEAR1 */
+#define M98925_SPKCURNT_CLR_MASK				(1<<5)
+#define M98925_SPKCURNT_CLR_SHIFT				5
+#define M98925_SPKCURNT_CLR_WIDTH				1
+#define M98925_WATCHFAIL_CLR_MASK				(1<<4)
+#define M98925_WATCHFAIL_CLR_SHIFT				4
+#define M98925_WATCHFAIL_CLR_WIDTH				1
+#define M98925_ALCINFH_CLR_MASK					(1<<3)
+#define M98925_ALCINFH_CLR_SHIFT				3
+#define M98925_ALCINFH_CLR_WIDTH				1
+#define M98925_ALCACT_CLR_MASK					(1<<2)
+#define M98925_ALCACT_CLR_SHIFT					2
+#define M98925_ALCACT_CLR_WIDTH					1
+#define M98925_ALCMUT_CLR_MASK					(1<<1)
+#define M98925_ALCMUT_CLR_SHIFT					1
+#define M98925_ALCMUT_CLR_WIDTH					1
+#define M98925_ALCP_CLR_MASK					(1<<0)
+#define M98925_ALCP_CLR_SHIFT					0
+#define M98925_ALCP_CLR_WIDTH					1
+
+/* MAX98925_R010_IRQ_CLEAR2 */
+#define M98925_SLOTOVRN_CLR_MASK				(1<<6)
+#define M98925_SLOTOVRN_CLR_SHIFT				6
+#define M98925_SLOTOVRN_CLR_WIDTH				1
+#define M98925_INVALSLOT_CLR_MASK				(1<<5)
+#define M98925_INVALSLOT_CLR_SHIFT				5
+#define M98925_INVALSLOT_CLR_WIDTH				1
+#define M98925_SLOTCNFLT_CLR_MASK				(1<<4)
+#define M98925_SLOTCNFLT_CLR_SHIFT				4
+#define M98925_SLOTCNFLT_CLR_WIDTH				1
+#define M98925_VBSTOVFL_CLR_MASK				(1<<3)
+#define M98925_VBSTOVFL_CLR_SHIFT				3
+#define M98925_VBSTOVFL_CLR_WIDTH				1
+#define M98925_VBATOVFL_CLR_MASK				(1<<2)
+#define M98925_VBATOVFL_CLR_SHIFT				2
+#define M98925_VBATOVFL_CLR_WIDTH				1
+#define M98925_IMONOVFL_CLR_MASK				(1<<1)
+#define M98925_IMONOVFL_CLR_SHIFT				1
+#define M98925_IMONOVFL_CLR_WIDTH				1
+#define M98925_VMONOVFL_CLR_MASK				(1<<0)
+#define M98925_VMONOVFL_CLR_SHIFT				0
+#define M98925_VMONOVFL_CLR_WIDTH				1
+
+/* MAX98925_R011_MAP0 */
+#define M98925_ER_THERMWARN_EN_MASK				(1<<7)
+#define M98925_ER_THERMWARN_EN_SHIFT			7
+#define M98925_ER_THERMWARN_EN_WIDTH			1
+#define M98925_ER_THERMWARN_MAP_MASK			(0x07<<4)
+#define M98925_ER_THERMWARN_MAP_SHIFT			4
+#define M98925_ER_THERMWARN_MAP_WIDTH			3
+
+/* MAX98925_R012_MAP1 */
+#define M98925_ER_ALCMUT_EN_MASK				(1<<7)
+#define M98925_ER_ALCMUT_EN_SHIFT				7
+#define M98925_ER_ALCMUT_EN_WIDTH				1
+#define M98925_ER_ALCMUT_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCMUT_MAP_SHIFT				4
+#define M98925_ER_ALCMUT_MAP_WIDTH				3
+#define M98925_ER_ALCP_EN_MASK					(1<<3)
+#define M98925_ER_ALCP_EN_SHIFT					3
+#define M98925_ER_ALCP_EN_WIDTH					1
+#define M98925_ER_ALCP_MAP_MASK					(0x07<<0)
+#define M98925_ER_ALCP_MAP_SHIFT				0
+#define M98925_ER_ALCP_MAP_WIDTH				3
+
+/* MAX98925_R013_MAP2 */
+#define M98925_ER_ALCINFH_EN_MASK				(1<<7)
+#define M98925_ER_ALCINFH_EN_SHIFT				7
+#define M98925_ER_ALCINFH_EN_WIDTH				1
+#define M98925_ER_ALCINFH_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCINFH_MAP_SHIFT				4
+#define M98925_ER_ALCINFH_MAP_WIDTH				3
+#define M98925_ER_ALCACT_EN_MASK				(1<<3)
+#define M98925_ER_ALCACT_EN_SHIFT				3
+#define M98925_ER_ALCACT_EN_WIDTH				1
+#define M98925_ER_ALCACT_MAP_MASK				(0x07<<0)
+#define M98925_ER_ALCACT_MAP_SHIFT				0
+#define M98925_ER_ALCACT_MAP_WIDTH				3
+
+/* MAX98925_R014_MAP3 */
+#define M98925_ER_SPKCURNT_EN_MASK				(1<<7)
+#define M98925_ER_SPKCURNT_EN_SHIFT				7
+#define M98925_ER_SPKCURNT_EN_WIDTH				1
+#define M98925_ER_SPKCURNT_MAP_MASK				(0x07<<4)
+#define M98925_ER_SPKCURNT_MAP_SHIFT			4
+#define M98925_ER_SPKCURNT_MAP_WIDTH			3
+
+/* MAX98925_R015_MAP4 */
+/* RESERVED */
+
+/* MAX98925_R016_MAP5 */
+#define M98925_ER_IMONOVFL_EN_MASK				(1<<7)
+#define M98925_ER_IMONOVFL_EN_SHIFT				7
+#define M98925_ER_IMONOVFL_EN_WIDTH				1
+#define M98925_ER_IMONOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_IMONOVFL_MAP_SHIFT			4
+#define M98925_ER_IMONOVFL_MAP_WIDTH			3
+#define M98925_ER_VMONOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VMONOVFL_EN_SHIFT				3
+#define M98925_ER_VMONOVFL_EN_WIDTH				1
+#define M98925_ER_VMONOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VMONOVFL_MAP_SHIFT			0
+#define M98925_ER_VMONOVFL_MAP_WIDTH			3
+
+/* MAX98925_R017_MAP6 */
+#define M98925_ER_VBSTOVFL_EN_MASK				(1<<7)
+#define M98925_ER_VBSTOVFL_EN_SHIFT				7
+#define M98925_ER_VBSTOVFL_EN_WIDTH				1
+#define M98925_ER_VBSTOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_VBSTOVFL_MAP_SHIFT			4
+#define M98925_ER_VBSTOVFL_MAP_WIDTH			3
+#define M98925_ER_VBATOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VBATOVFL_EN_SHIFT				3
+#define M98925_ER_VBATOVFL_EN_WIDTH				1
+#define M98925_ER_VBATOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VBATOVFL_MAP_SHIFT			0
+#define M98925_ER_VBATOVFL_MAP_WIDTH			3
+
+/* MAX98925_R018_MAP7 */
+#define M98925_ER_INVALSLOT_EN_MASK				(1<<7)
+#define M98925_ER_INVALSLOT_EN_SHIFT			7
+#define M98925_ER_INVALSLOT_EN_WIDTH			1
+#define M98925_ER_INVALSLOT_MAP_MASK			(0x07<<4)
+#define M98925_ER_INVALSLOT_MAP_SHIFT			4
+#define M98925_ER_INVALSLOT_MAP_WIDTH			3
+#define M98925_ER_SLOTCNFLT_EN_MASK				(1<<3)
+#define M98925_ER_SLOTCNFLT_EN_SHIFT			3
+#define M98925_ER_SLOTCNFLT_EN_WIDTH			1
+#define M98925_ER_SLOTCNFLT_MAP_MASK			(0x07<<0)
+#define M98925_ER_SLOTCNFLT_MAP_SHIFT			0
+#define M98925_ER_SLOTCNFLT_MAP_WIDTH			3
+
+/* MAX98925_R019_MAP8 */
+#define M98925_ER_SLOTOVRN_EN_MASK	(1<<3)
+#define M98925_ER_SLOTOVRN_EN_SHIFT	3
+#define M98925_ER_SLOTOVRN_EN_WIDTH	1
+#define M98925_ER_SLOTOVRN_MAP_MASK	(0x07<<0)
+#define M98925_ER_SLOTOVRN_MAP_SHIFT	0
+#define M98925_ER_SLOTOVRN_MAP_WIDTH	3
+
+/* MAX98925_R01A_DAI_CLK_MODE1 */
+#define M98925_DAI_CLK_SOURCE_MASK	(1<<6)
+#define M98925_DAI_CLK_SOURCE_SHIFT	6
+#define M98925_DAI_CLK_SOURCE_WIDTH	1
+#define M98925_MDLL_MULT_MASK		(0x0F<<0)
+#define M98925_MDLL_MULT_SHIFT		0
+#define M98925_MDLL_MULT_WIDTH		4
+
+#define M98925_MDLL_MULT_MCLKx8		6
+#define M98925_MDLL_MULT_MCLKx16	8
+
+/* MAX98925_R01B_DAI_CLK_MODE2 */
+#define M98925_DAI_SR_MASK			(0x0F<<4)
+#define M98925_DAI_SR_SHIFT			4
+#define M98925_DAI_SR_WIDTH			4
+#define M98925_DAI_MAS_MASK			(1<<3)
+#define M98925_DAI_MAS_SHIFT			3
+#define M98925_DAI_MAS_WIDTH			1
+#define M98925_DAI_BSEL_MASK			(0x07<<0)
+#define M98925_DAI_BSEL_SHIFT			0
+#define M98925_DAI_BSEL_WIDTH			3
+
+#define M98925_DAI_BSEL_32 (0 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_48 (1 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_64 (2 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_256 (6 << M98925_DAI_BSEL_SHIFT)
+
+/* MAX98925_R01C_DAI_CLK_DIV_M_MSBS */
+#define M98925_DAI_M_MSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_MSBS_SHIFT					0
+#define M98925_DAI_M_MSBS_WIDTH					8
+
+/* MAX98925_R01D_DAI_CLK_DIV_M_LSBS */
+#define M98925_DAI_M_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_LSBS_SHIFT					0
+#define M98925_DAI_M_LSBS_WIDTH					8
+
+/* MAX98925_R01E_DAI_CLK_DIV_N_MSBS */
+#define M98925_DAI_N_MSBS_MASK					(0x7F<<0)
+#define M98925_DAI_N_MSBS_SHIFT					0
+#define M98925_DAI_N_MSBS_WIDTH					7
+
+/* MAX98925_R01F_DAI_CLK_DIV_N_LSBS */
+#define M98925_DAI_N_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_N_LSBS_SHIFT					0
+#define M98925_DAI_N_LSBS_WIDTH					8
+
+/* MAX98925_R020_FORMAT */
+#define M98925_DAI_CHANSZ_MASK					(0x03<<6)
+#define M98925_DAI_CHANSZ_SHIFT					6
+#define M98925_DAI_CHANSZ_WIDTH					2
+#define M98925_DAI_EXTBCLK_HIZ_MASK				(1<<4)
+#define M98925_DAI_EXTBCLK_HIZ_SHIFT			4
+#define M98925_DAI_EXTBCLK_HIZ_WIDTH			1
+#define M98925_DAI_WCI_MASK						(1<<3)
+#define M98925_DAI_WCI_SHIFT					3
+#define M98925_DAI_WCI_WIDTH					1
+#define M98925_DAI_BCI_MASK						(1<<2)
+#define M98925_DAI_BCI_SHIFT					2
+#define M98925_DAI_BCI_WIDTH					1
+#define M98925_DAI_DLY_MASK						(1<<1)
+#define M98925_DAI_DLY_SHIFT					1
+#define M98925_DAI_DLY_WIDTH					1
+#define M98925_DAI_TDM_MASK						(1<<0)
+#define M98925_DAI_TDM_SHIFT					0
+#define M98925_DAI_TDM_WIDTH					1
+
+#define M98925_DAI_CHANSZ_16 (1 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_24 (2 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_32 (3 << M98925_DAI_CHANSZ_SHIFT)
+
+/* MAX98925_R021_TDM_SLOT_SELECT */
+#define M98925_DAI_DO_EN_MASK					(1<<7)
+#define M98925_DAI_DO_EN_SHIFT					7
+#define M98925_DAI_DO_EN_WIDTH					1
+#define M98925_DAI_DIN_EN_MASK					(1<<6)
+#define M98925_DAI_DIN_EN_SHIFT					6
+#define M98925_DAI_DIN_EN_WIDTH					1
+#define M98925_DAI_INR_SOURCE_MASK				(0x07<<3)
+#define M98925_DAI_INR_SOURCE_SHIFT				3
+#define M98925_DAI_INR_SOURCE_WIDTH				3
+#define M98925_DAI_INL_SOURCE_MASK				(0x07<<0)
+#define M98925_DAI_INL_SOURCE_SHIFT				0
+#define M98925_DAI_INL_SOURCE_WIDTH				3
+
+/* MAX98925_R022_DOUT_CFG_VMON */
+#define M98925_DAI_VMON_EN_MASK					(1<<5)
+#define M98925_DAI_VMON_EN_SHIFT				5
+#define M98925_DAI_VMON_EN_WIDTH				1
+#define M98925_DAI_VMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VMON_SLOT_SHIFT				0
+#define M98925_DAI_VMON_SLOT_WIDTH				5
+
+#define M98925_DAI_VMON_SLOT_00_01 (0 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_01_02 (1 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_02_03 (2 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_03_04 (3 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_04_05 (4 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_05_06 (5 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_06_07 (6 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_07_08 (7 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_08_09 (8 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_09_0A (9 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0A_0B (10 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0B_0C (11 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0C_0D (12 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0D_0E (13 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0E_0F (14 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0F_10 (15 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_10_11 (16 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_11_12 (17 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_12_13 (18 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_13_14 (19 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_14_15 (20 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_15_16 (21 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_16_17 (22 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_17_18 (23 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_18_19 (24 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_19_1A (25 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1A_1B (26 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1B_1C (27 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1C_1D (28 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1D_1E (29 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1E_1F (30 << M98925_DAI_VMON_SLOT_SHIFT)
+
+/* MAX98925_R023_DOUT_CFG_IMON */
+#define M98925_DAI_IMON_EN_MASK					(1<<5)
+#define M98925_DAI_IMON_EN_SHIFT				5
+#define M98925_DAI_IMON_EN_WIDTH				1
+#define M98925_DAI_IMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_IMON_SLOT_SHIFT				0
+#define M98925_DAI_IMON_SLOT_WIDTH				5
+
+#define M98925_DAI_IMON_SLOT_00_01 (0 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_01_02 (1 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_02_03 (2 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_03_04 (3 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_04_05 (4 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_05_06 (5 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_06_07 (6 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_07_08 (7 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_08_09 (8 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_09_0A (9 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0A_0B (10 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0B_0C (11 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0C_0D (12 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0D_0E (13 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0E_0F (14 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0F_10 (15 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_10_11 (16 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_11_12 (17 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_12_13 (18 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_13_14 (19 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_14_15 (20 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_15_16 (21 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_16_17 (22 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_17_18 (23 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_18_19 (24 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_19_1A (25 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1A_1B (26 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1B_1C (27 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1C_1D (28 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1D_1E (29 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1E_1F (30 << M98925_DAI_IMON_SLOT_SHIFT)
+
+/* MAX98925_R024_DOUT_CFG_VBAT */
+#define M98925_DAI_VBAT_EN_MASK					(1<<5)
+#define M98925_DAI_VBAT_EN_SHIFT				5
+#define M98925_DAI_VBAT_EN_WIDTH				1
+#define M98925_DAI_VBAT_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBAT_SLOT_SHIFT				0
+#define M98925_DAI_VBAT_SLOT_WIDTH				5
+
+/* MAX98925_R025_DOUT_CFG_VBST */
+#define M98925_DAI_VBST_EN_MASK					(1<<5)
+#define M98925_DAI_VBST_EN_SHIFT				5
+#define M98925_DAI_VBST_EN_WIDTH				1
+#define M98925_DAI_VBST_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBST_SLOT_SHIFT				0
+#define M98925_DAI_VBST_SLOT_WIDTH				5
+
+/* MAX98925_R026_DOUT_CFG_FLAG */
+#define M98925_DAI_FLAG_EN_MASK					(1<<5)
+#define M98925_DAI_FLAG_EN_SHIFT				5
+#define M98925_DAI_FLAG_EN_WIDTH				1
+#define M98925_DAI_FLAG_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_FLAG_SLOT_SHIFT				0
+#define M98925_DAI_FLAG_SLOT_WIDTH				5
+
+/* MAX98925_R027_DOUT_HIZ_CFG1 */
+#define M98925_DAI_SLOT_HIZ_CFG1_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG1_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG1_WIDTH			8
+
+/* MAX98925_R028_DOUT_HIZ_CFG2 */
+#define M98925_DAI_SLOT_HIZ_CFG2_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG2_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG2_WIDTH			8
+
+/* MAX98925_R029_DOUT_HIZ_CFG3 */
+#define M98925_DAI_SLOT_HIZ_CFG3_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG3_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG3_WIDTH			8
+
+/* MAX98925_R02A_DOUT_HIZ_CFG4 */
+#define M98925_DAI_SLOT_HIZ_CFG4_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG4_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG4_WIDTH			8
+
+/* MAX98925_R02B_DOUT_DRV_STRENGTH */
+#define M98925_DAI_OUT_DRIVE_MASK				(0x03<<0)
+#define M98925_DAI_OUT_DRIVE_SHIFT				0
+#define M98925_DAI_OUT_DRIVE_WIDTH				2
+
+/* MAX98925_R02C_FILTERS */
+#define M98925_ADC_DITHER_EN_MASK				(1<<7)
+#define M98925_ADC_DITHER_EN_SHIFT				7
+#define M98925_ADC_DITHER_EN_WIDTH				1
+#define M98925_IV_DCB_EN_MASK					(1<<6)
+#define M98925_IV_DCB_EN_SHIFT					6
+#define M98925_IV_DCB_EN_WIDTH					1
+#define M98925_DAC_DITHER_EN_MASK				(1<<4)
+#define M98925_DAC_DITHER_EN_SHIFT				4
+#define M98925_DAC_DITHER_EN_WIDTH				1
+#define M98925_DAC_FILTER_MODE_MASK				(1<<3)
+#define M98925_DAC_FILTER_MODE_SHIFT			3
+#define M98925_DAC_FILTER_MODE_WIDTH			1
+#define M98925_DAC_HPF_MASK				(0x07<<0)
+#define M98925_DAC_HPF_SHIFT					0
+#define M98925_DAC_HPF_WIDTH					3
+#define M98925_DAC_HPF_DISABLE		(0 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_DC_BLOCK		(1 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_100		(2 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_200		(3 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_400		(4 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_800		(5 << M98925_DAC_HPF_SHIFT)
+
+/* MAX98925_R02D_GAIN */
+#define M98925_DAC_IN_SEL_MASK					(0x03<<5)
+#define M98925_DAC_IN_SEL_SHIFT					5
+#define M98925_DAC_IN_SEL_WIDTH					2
+#define M98925_SPK_GAIN_MASK					(0x1F<<0)
+#define M98925_SPK_GAIN_SHIFT					0
+#define M98925_SPK_GAIN_WIDTH					5
+
+#define M98925_DAC_IN_SEL_LEFT_DAI (0 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_RIGHT_DAI (1 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_SUMMED_DAI (2 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << M98925_DAC_IN_SEL_SHIFT)
+
+/* MAX98925_R02E_GAIN_RAMPING */
+#define M98925_SPK_RMP_EN_MASK		(1<<1)
+#define M98925_SPK_RMP_EN_SHIFT		1
+#define M98925_SPK_RMP_EN_WIDTH		1
+#define M98925_SPK_ZCD_EN_MASK		(1<<0)
+#define M98925_SPK_ZCD_EN_SHIFT		0
+#define M98925_SPK_ZCD_EN_WIDTH		1
+
+/* MAX98925_R02F_SPK_AMP */
+#define M98925_SPK_MODE_MASK		(1<<0)
+#define M98925_SPK_MODE_SHIFT		0
+#define M98925_SPK_MODE_WIDTH		1
+
+/* MAX98925_R030_THRESHOLD */
+#define M98925_ALC_EN_MASK			(1<<5)
+#define M98925_ALC_EN_SHIFT			5
+#define M98925_ALC_EN_WIDTH			1
+#define M98925_ALC_TH_MASK			(0x1F<<0)
+#define M98925_ALC_TH_SHIFT			0
+#define M98925_ALC_TH_WIDTH			5
+
+/* MAX98925_R031_ALC_ATTACK */
+#define M98925_ALC_ATK_STEP_MASK	(0x0F<<4)
+#define M98925_ALC_ATK_STEP_SHIFT	4
+#define M98925_ALC_ATK_STEP_WIDTH	4
+#define M98925_ALC_ATK_RATE_MASK	(0x7<<0)
+#define M98925_ALC_ATK_RATE_SHIFT	0
+#define M98925_ALC_ATK_RATE_WIDTH	3
+
+/* MAX98925_R032_ALC_ATTEN_RLS */
+#define M98925_ALC_MAX_ATTEN_MASK	(0x0F<<4)
+#define M98925_ALC_MAX_ATTEN_SHIFT	4
+#define M98925_ALC_MAX_ATTEN_WIDTH	4
+#define M98925_ALC_RLS_RATE_MASK	(0x7<<0)
+#define M98925_ALC_RLS_RATE_SHIFT	0
+#define M98925_ALC_RLS_RATE_WIDTH	3
+
+/* MAX98925_R033_ALC_HOLD_RLS */
+#define M98925_ALC_RLS_TGR_MASK		(1<<0)
+#define M98925_ALC_RLS_TGR_SHIFT	0
+#define M98925_ALC_RLS_TGR_WIDTH	1
+
+/* MAX98925_R034_ALC_CONFIGURATION */
+#define M98925_ALC_MUTE_EN_MASK		(1<<7)
+#define M98925_ALC_MUTE_EN_SHIFT	7
+#define M98925_ALC_MUTE_EN_WIDTH	1
+#define M98925_ALC_MUTE_DLY_MASK	(0x07<<4)
+#define M98925_ALC_MUTE_DLY_SHIFT	4
+#define M98925_ALC_MUTE_DLY_WIDTH	3
+#define M98925_ALC_RLS_DBT_MASK		(0x07<<0)
+#define M98925_ALC_RLS_DBT_SHIFT	0
+#define M98925_ALC_RLS_DBT_WIDTH	3
+
+/* MAX98925_R035_BOOST_CONVERTER */
+#define M98925_BST_SYNC_MASK		(1<<7)
+#define M98925_BST_SYNC_SHIFT		7
+#define M98925_BST_SYNC_WIDTH		1
+#define M98925_BST_PHASE_MASK		(0x03<<4)
+#define M98925_BST_PHASE_SHIFT		4
+#define M98925_BST_PHASE_WIDTH		2
+#define M98925_BST_SKIP_MODE_MASK	(0x03<<0)
+#define M98925_BST_SKIP_MODE_SHIFT	0
+#define M98925_BST_SKIP_MODE_WIDTH	2
+
+/* MAX98925_R036_BLOCK_ENABLE */
+#define M98925_BST_EN_MASK			(1<<7)
+#define M98925_BST_EN_SHIFT			7
+#define M98925_BST_EN_WIDTH			1
+#define M98925_WATCH_EN_MASK		(1<<6)
+#define M98925_WATCH_EN_SHIFT		6
+#define M98925_WATCH_EN_WIDTH		1
+#define M98925_CLKMON_EN_MASK		(1<<5)
+#define M98925_CLKMON_EN_SHIFT		5
+#define M98925_CLKMON_EN_WIDTH		1
+#define M98925_SPK_EN_MASK			(1<<4)
+#define M98925_SPK_EN_SHIFT			4
+#define M98925_SPK_EN_WIDTH			1
+#define M98925_ADC_VBST_EN_MASK		(1<<3)
+#define M98925_ADC_VBST_EN_SHIFT	3
+#define M98925_ADC_VBST_EN_WIDTH	1
+#define M98925_ADC_VBAT_EN_MASK		(1<<2)
+#define M98925_ADC_VBAT_EN_SHIFT	2
+#define M98925_ADC_VBAT_EN_WIDTH	1
+#define M98925_ADC_IMON_EN_MASK		(1<<1)
+#define M98925_ADC_IMON_EN_SHIFT	1
+#define M98925_ADC_IMON_EN_WIDTH	1
+#define M98925_ADC_VMON_EN_MASK		(1<<0)
+#define M98925_ADC_VMON_EN_SHIFT	0
+#define M98925_ADC_VMON_EN_WIDTH	1
+
+/* MAX98925_R037_CONFIGURATION */
+#define M98925_BST_VOUT_MASK		(0x0F<<4)
+#define M98925_BST_VOUT_SHIFT		4
+#define M98925_BST_VOUT_WIDTH		4
+#define M98925_THERMWARN_LEVEL_MASK	(0x03<<2)
+#define M98925_THERMWARN_LEVEL_SHIFT			2
+#define M98925_THERMWARN_LEVEL_WIDTH			2
+#define M98925_WATCH_TIME_MASK			(0x03<<0)
+#define M98925_WATCH_TIME_SHIFT			0
+#define M98925_WATCH_TIME_WIDTH			2
+
+/* MAX98925_R038_GLOBAL_ENABLE */
+#define M98925_EN_MASK			(1<<7)
+#define M98925_EN_SHIFT			7
+#define M98925_EN_WIDTH			1
+
+/* MAX98925_R03A_BOOST_LIMITER */
+#define M98925_BST_ILIM_MASK	(0x1F<<3)
+#define M98925_BST_ILIM_SHIFT	3
+#define M98925_BST_ILIM_WIDTH	5
+
+/* MAX98925_R0FF_VERSION */
+#define M98925_REV_ID_MASK	(0xFF<<0)
+#define M98925_REV_ID_SHIFT	0
+#define M98925_REV_ID_WIDTH	8
+
+struct max98925_priv {
+	struct regmap *regmap;
+	struct snd_soc_codec *codec;
+	struct max98925_pdata *pdata;
+	unsigned int sysclk;
+	unsigned int v_slot;
+	unsigned int i_slot;
+	unsigned int spk_gain;
+	unsigned int ch_size;
+};
+#endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-03-09 22:50 [PATCH] ASoC: Add max98925 codec driver Anish Kumar
@ 2015-03-11 18:27 ` Mark Brown
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2015-03-11 18:27 UTC (permalink / raw)
  To: Anish Kumar; +Cc: tiwai, alsa-devel


[-- Attachment #1.1: Type: text/plain, Size: 133 bytes --]

On Mon, Mar 09, 2015 at 03:50:34PM -0700, Anish Kumar wrote:
> Signed-off-by: Anish Kumar <yesanishhere@gmail.com>

Applied, thanks.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-03-05 23:15 Anish Kumar
@ 2015-03-06 20:46 ` Mark Brown
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2015-03-06 20:46 UTC (permalink / raw)
  To: Anish Kumar; +Cc: tiwai, alsa-devel


[-- Attachment #1.1: Type: text/plain, Size: 5573 bytes --]

On Thu, Mar 05, 2015 at 03:15:44PM -0800, Anish Kumar wrote:

Looks pretty good but still a few things which are hopefully fairly easy
to address.

> changes since v1:
> 	- addressed mark brown comments regarding
> 	  open coding functions.
> 	- changed the mixer namings
> 	- added some dapm widgets

Don't put stuff like this in the changelog, put it after the --- as
covered in SubmittingPatches.

> +static const struct soc_enum max98925_enum[] = {
> +	SOC_ENUM_SINGLE(MAX98925_GAIN, 5, 4, dai_text),
> +	SOC_ENUM_SINGLE(MAX98925_FILTERS, 0, 6, hpf_text),
> +};
> +
> +static const struct snd_kcontrol_new max98925_dai_sel =
> +	SOC_DAPM_ENUM("Route", max98925_enum[0]);
> +
> +static const struct snd_kcontrol_new max98925_hpf_sel =
> +	SOC_DAPM_ENUM("Route", max98925_enum[1]);

Don't use magic number indexes into a table of arrays, this does nothing
for legibility or maintainability.  Use individual variables like other
drivers do.

> +static int max98925_spk_gain_put(struct snd_kcontrol *kcontrol,
> +				struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +	unsigned int sel = ucontrol->value.integer.value[0];
> +
> +	if (sel < ((1 << M98925_SPK_GAIN_WIDTH) - 1)) {
> +		regmap_update_bits(max98925->regmap, MAX98925_GAIN,
> +			M98925_SPK_GAIN_MASK, sel << M98925_SPK_GAIN_SHIFT);
> +		max98925->spk_gain = sel;

My previous comment about this not being used anywere and this being
suitable for a normal control still seem to apply here.

> +static int max98925_boost_voltage_get(struct snd_kcontrol *kcontrol,
> +		struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +	int data;
> +
> +	regmap_read(max98925->regmap, MAX98925_CONFIGURATION, &data);
> +	ucontrol->value.integer.value[0] =
> +		(data & M98925_BST_VOUT_MASK) >> M98925_BST_VOUT_SHIFT;
> +	return 0;
> +}

Similarly for this control, why is this open coded?

> +static const struct snd_kcontrol_new max98925_snd_controls[] = {
> +	SOC_SINGLE_EXT_TLV("Speaker Gain", MAX98925_GAIN,
> +		M98925_SPK_GAIN_SHIFT, (1<<M98925_SPK_GAIN_WIDTH)-1, 0,
> +		max98925_spk_gain_get, max98925_spk_gain_put, max98925_spk_tlv),

All volume controls should be called ...Volume, see ControlNames.txt.

> +	SOC_SINGLE("Speaker Ramp", MAX98925_GAIN_RAMPING,
> +				M98925_SPK_RMP_EN_SHIFT, 1, 0),

Similarly on/off switches should be called ...Switch.

> +	pr_debug("%s: sample rate is %d, returning %d\n",
> +				__func__, rate_table[i].rate, *value);

Use dev_ print functions rather than pr_ where you have a device.

> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		max98925_set_slave(max98925);
> +		break;
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		max98925_set_master(max98925);
> +		break;

I don't really understand why we have these functions - they're small
enough just to have the code inline here aren't they?

> +	switch (params_format(params)) {
> +	case SNDRV_PCM_FORMAT_S16_LE:

Use params_width() rather than relying on the specific memory format.

> +
> +	dev_dbg(codec->dev, "%s: mute %d\n", __func__, mute);
> +	if (mute) {
> +		regmap_update_bits(max98925->regmap, MAX98925_GAIN,
> +			M98925_SPK_GAIN_MASK, 0x00);

This will collide with the volume control exposed to users, don't do
this - if you don't have a suitable mute control in the hardware just
don't implement this function.

> +static int max98925_probe(struct snd_soc_codec *codec)
> +{
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +	int ret = 0;
> +	int reg = 0;
> +
> +	dev_info(codec->dev, "build number %s\n", MAX98925_REVISION);

Don't print noise like this, it's not adding anything - the kernel
already displays it's own version.

> +
> +	max98925->codec = codec;
> +	codec->control_data = max98925->regmap;
> +	ret = regmap_read(max98925->regmap,
> +			MAX98925_REV_VERSION, &reg);
> +	if ((ret < 0) ||
> +		((reg != MAX98925_VERSION) &&
> +		(reg != MAX98925_VERSION1))) {
> +		dev_err(codec->dev,
> +			"device initialization error (%d 0x%02X)\n",
> +			ret, reg);
> +		goto err_access;
> +	}

Move all this basic I2C setup and version display stuff to the I2C level
probe, no need to defer it and it means that we confirm we can talk to
the CODEC before we start the sound card.

> +	if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
> +		if (value > M98925_DAI_VMON_SLOT_1E_1F) {
> +			dev_err(&i2c->dev, "vmon slot number is wrong:\n");
> +			return -EINVAL;
> +		}
> +		max98925->v_slot = value;
> +	}

All DT bindings need to be documented but there is no binding document
for this CODEC.

> +static int max98925_i2c_remove(struct i2c_client *client)
> +{
> +	snd_soc_unregister_codec(&client->dev);
> +	kfree(i2c_get_clientdata(client));

Use devm_kzalloc().

> +static const struct i2c_device_id max98925_i2c_id[] = {
> +	{ "max98925", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, max98925_i2c_id);
> +
> +static struct i2c_driver max98925_i2c_driver = {
> +	.driver = {
> +		.name = "max98925",
> +		.owner = THIS_MODULE,
> +		.pm = NULL,
> +	},
> +	.probe  = max98925_i2c_probe,
> +	.remove = max98925_i2c_remove,
> +	.id_table = max98925_i2c_id,
> +};

You have DT bindings but no of_match_table.

> +#define MAX98925_REVISION	"0.00.0333"

Remove this, for in-tree code the kernel is already well enough
versioned and nobody working in tree is going to care to update this.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] ASoC: Add max98925 codec driver
@ 2015-03-05 23:15 Anish Kumar
  2015-03-06 20:46 ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: Anish Kumar @ 2015-03-05 23:15 UTC (permalink / raw)
  To: broonie, perex, tiwai; +Cc: alsa-devel, Anish Kumar

changes since v1:
	- addressed mark brown comments regarding
	  open coding functions.
	- changed the mixer namings
	- added some dapm widgets
Signed-off-by: Anish Kumar <yesanishhere@gmail.com>
---
 sound/soc/codecs/Kconfig    |   4 +
 sound/soc/codecs/Makefile   |   2 +
 sound/soc/codecs/max98925.c | 737 +++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/max98925.h | 833 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1576 insertions(+)
 create mode 100644 sound/soc/codecs/max98925.c
 create mode 100644 sound/soc/codecs/max98925.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0bddd92..a7f44e3 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -68,6 +68,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_LM49453 if I2C
 	select SND_SOC_MAX98088 if I2C
 	select SND_SOC_MAX98090 if I2C
+	select SND_SOC_MAX98925 if I2C
 	select SND_SOC_MAX98095 if I2C
 	select SND_SOC_MAX98357A if GPIOLIB
 	select SND_SOC_MAX9850 if I2C
@@ -455,6 +456,9 @@ config SND_SOC_MAX98088
 config SND_SOC_MAX98090
        tristate
 
+config SND_SOC_MAX98925
+       tristate
+
 config SND_SOC_MAX98095
        tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 7acb6c1..1658d19 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -63,6 +63,7 @@ snd-soc-lm49453-objs := lm49453.o
 snd-soc-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98090-objs := max98090.o
+snd-soc-max98925-objs := max98925.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max98357a-objs := max98357a.o
 snd-soc-max9850-objs := max9850.o
@@ -247,6 +248,7 @@ obj-$(CONFIG_SND_SOC_LM49453)   += snd-soc-lm49453.o
 obj-$(CONFIG_SND_SOC_MAX9768)	+= snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98090)	+= snd-soc-max98090.o
+obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX98357A)	+= snd-soc-max98357a.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c
new file mode 100644
index 0000000..7831bc9
--- /dev/null
+++ b/sound/soc/codecs/max98925.c
@@ -0,0 +1,737 @@
+/*
+ * max98925.c -- ALSA SoC Stereo MAX98925 driver
+ * Copyright 2013-15 Maxim Integrated Products
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.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 <sound/tlv.h>
+#include "max98925.h"
+
+static const char *const dai_text[] = {
+	"Left", "Right", "LeftRight", "LeftRightDiv2",
+};
+
+static const char *const hpf_text[] = {
+	"Disable", "DC Block", "100Hz",	"200Hz", "400Hz", "800Hz",
+};
+
+static struct reg_default max98925_reg[] = {
+	{ 0x0B, 0x00 }, /* IRQ Enable0 */
+	{ 0x0C, 0x00 }, /* IRQ Enable1 */
+	{ 0x0D, 0x00 }, /* IRQ Enable2 */
+	{ 0x0E, 0x00 }, /* IRQ Clear0 */
+	{ 0x0F, 0x00 }, /* IRQ Clear1 */
+	{ 0x10, 0x00 }, /* IRQ Clear2 */
+	{ 0x11, 0xC0 }, /* Map0 */
+	{ 0x12, 0x00 }, /* Map1 */
+	{ 0x13, 0x00 }, /* Map2 */
+	{ 0x14, 0xF0 }, /* Map3 */
+	{ 0x15, 0x00 }, /* Map4 */
+	{ 0x16, 0xAB }, /* Map5 */
+	{ 0x17, 0x89 }, /* Map6 */
+	{ 0x18, 0x00 }, /* Map7 */
+	{ 0x19, 0x00 }, /* Map8 */
+	{ 0x1A, 0x06 }, /* DAI Clock Mode 1 */
+	{ 0x1B, 0xC0 }, /* DAI Clock Mode 2 */
+	{ 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */
+	{ 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */
+	{ 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */
+	{ 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */
+	{ 0x20, 0x50 }, /* Format */
+	{ 0x21, 0x00 }, /* TDM Slot Select */
+	{ 0x22, 0x00 }, /* DOUT Configuration VMON */
+	{ 0x23, 0x00 }, /* DOUT Configuration IMON */
+	{ 0x24, 0x00 }, /* DOUT Configuration VBAT */
+	{ 0x25, 0x00 }, /* DOUT Configuration VBST */
+	{ 0x26, 0x00 }, /* DOUT Configuration FLAG */
+	{ 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */
+	{ 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */
+	{ 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */
+	{ 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */
+	{ 0x2B, 0x02 }, /* DOUT Drive Strength */
+	{ 0x2C, 0x90 }, /* Filters */
+	{ 0x2D, 0x00 }, /* Gain */
+	{ 0x2E, 0x02 }, /* Gain Ramping */
+	{ 0x2F, 0x00 }, /* Speaker Amplifier */
+	{ 0x30, 0x0A }, /* Threshold */
+	{ 0x31, 0x00 }, /* ALC Attack */
+	{ 0x32, 0x80 }, /* ALC Atten and Release */
+	{ 0x33, 0x00 }, /* ALC Infinite Hold Release */
+	{ 0x34, 0x92 }, /* ALC Configuration */
+	{ 0x35, 0x01 }, /* Boost Converter */
+	{ 0x36, 0x00 }, /* Block Enable */
+	{ 0x37, 0x00 }, /* Configuration */
+	{ 0x38, 0x00 }, /* Global Enable */
+	{ 0x3A, 0x00 }, /* Boost Limiter */
+};
+
+static const struct soc_enum max98925_enum[] = {
+	SOC_ENUM_SINGLE(MAX98925_GAIN, 5, 4, dai_text),
+	SOC_ENUM_SINGLE(MAX98925_FILTERS, 0, 6, hpf_text),
+};
+
+static const struct snd_kcontrol_new max98925_dai_sel =
+	SOC_DAPM_ENUM("Route", max98925_enum[0]);
+
+static const struct snd_kcontrol_new max98925_hpf_sel =
+	SOC_DAPM_ENUM("Route", max98925_enum[1]);
+
+static int max98925_dac_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_BLOCK_ENABLE,
+			M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
+			M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_BLOCK_ENABLE, M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK, 0);
+		break;
+	default:
+		return 0;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget max98925_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_MUX("DAI_IN_MUX MUX", SND_SOC_NOPM, 0, 0,
+				&max98925_dai_sel),
+	SND_SOC_DAPM_MUX("Rc Filter Mux", SND_SOC_NOPM, 0, 0,
+				&max98925_hpf_sel),
+	SND_SOC_DAPM_DAC_E("Amp Enable", NULL, MAX98925_BLOCK_ENABLE,
+			M98925_SPK_EN_SHIFT, 0, max98925_dac_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("Global Enable", MAX98925_GLOBAL_ENABLE,
+			M98925_EN_SHIFT, 0, NULL, 0),
+	SND_SOC_DAPM_OUTPUT("BE_OUT"),
+};
+
+static const struct snd_soc_dapm_route max98925_audio_map[] = {
+	{"DAI_IN_MUX MUX", "Left", "DAI_OUT"},
+	{"DAI_IN_MUX MUX", "Right", "DAI_OUT"},
+	{"DAI_IN_MUX MUX", "LeftRight", "DAI_OUT"},
+	{"DAI_IN_MUX MUX", "LeftRightDiv2", "DAI_OUT"},
+	{"Rc Filter Mux", "Disable", "DAI_IN_MUX MUX"},
+	{"Rc Filter Mux", "DC Block", "DAI_IN_MUX MUX"},
+	{"Rc Filter Mux", "100Hz", "DAI_IN_MUX MUX"},
+	{"Rc Filter Mux", "200Hz", "DAI_IN_MUX MUX"},
+	{"Rc Filter Mux", "400Hz", "DAI_IN_MUX MUX"},
+	{"Rc Filter Mux", "800Hz", "DAI_IN_MUX MUX"},
+	{"Amp Enable", NULL, "Rc Filter Mux"},
+	{"BE_OUT", NULL, "Amp Enable"},
+	{"BE_OUT", NULL, "Global Enable"},
+};
+
+static bool max98925_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_VBAT_DATA:
+	case MAX98925_VBST_DATA:
+	case MAX98925_LIVE_STATUS0:
+	case MAX98925_LIVE_STATUS1:
+	case MAX98925_LIVE_STATUS2:
+	case MAX98925_STATE0:
+	case MAX98925_STATE1:
+	case MAX98925_STATE2:
+	case MAX98925_FLAG0:
+	case MAX98925_FLAG1:
+	case MAX98925_FLAG2:
+	case MAX98925_REV_VERSION:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max98925_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_IRQ_CLEAR0:
+	case MAX98925_IRQ_CLEAR1:
+	case MAX98925_IRQ_CLEAR2:
+	case MAX98925_ALC_HOLD_RLS:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static int max98925_spk_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = max98925->spk_gain;
+	dev_dbg(codec->dev, "%s: spk_gain setting returned %d\n", __func__,
+				(int) ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int max98925_spk_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int sel = ucontrol->value.integer.value[0];
+
+	if (sel < ((1 << M98925_SPK_GAIN_WIDTH) - 1)) {
+		regmap_update_bits(max98925->regmap, MAX98925_GAIN,
+			M98925_SPK_GAIN_MASK, sel << M98925_SPK_GAIN_SHIFT);
+		max98925->spk_gain = sel;
+
+		dev_dbg(codec->dev, "%s: spk_gain set to %d\n", __func__, sel);
+	} else {
+		dev_dbg(codec->dev, "%s: valid speaker gain settings: %d to %d\n",
+			__func__, 0,
+			((1 << M98925_SPK_GAIN_WIDTH) - 1));
+	}
+	return 0;
+}
+
+static const char * const max98925_boost_voltage_text[] = {
+	"8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V",
+	"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V",	"6.5V", "6.5V"
+};
+
+static const struct soc_enum max98925_boost_voltage_enum =
+	SOC_ENUM_SINGLE(MAX98925_CONFIGURATION, M98925_BST_VOUT_SHIFT,
+			ARRAY_SIZE(max98925_boost_voltage_text),
+			max98925_boost_voltage_text);
+
+static int max98925_boost_voltage_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	int data;
+
+	regmap_read(max98925->regmap, MAX98925_CONFIGURATION, &data);
+	ucontrol->value.integer.value[0] =
+		(data & M98925_BST_VOUT_MASK) >> M98925_BST_VOUT_SHIFT;
+	return 0;
+}
+
+static int max98925_boost_voltage_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int sel = ucontrol->value.integer.value[0];
+
+	regmap_update_bits(max98925->regmap, MAX98925_CONFIGURATION,
+		M98925_BST_VOUT_MASK, sel << M98925_BST_VOUT_SHIFT);
+	return 0;
+}
+
+DECLARE_TLV_DB_SCALE(max98925_spk_tlv, -600, 100, 0);
+
+static const struct snd_kcontrol_new max98925_snd_controls[] = {
+	SOC_SINGLE_EXT_TLV("Speaker Gain", MAX98925_GAIN,
+		M98925_SPK_GAIN_SHIFT, (1<<M98925_SPK_GAIN_WIDTH)-1, 0,
+		max98925_spk_gain_get, max98925_spk_gain_put, max98925_spk_tlv),
+	SOC_SINGLE("Speaker Ramp", MAX98925_GAIN_RAMPING,
+				M98925_SPK_RMP_EN_SHIFT, 1, 0),
+	SOC_SINGLE("Speaker ZCD", MAX98925_GAIN_RAMPING,
+				M98925_SPK_ZCD_EN_SHIFT, 1, 0),
+	SOC_SINGLE("ALC Enable", MAX98925_THRESHOLD,
+				M98925_ALC_EN_SHIFT, 1, 0),
+	SOC_SINGLE("ALC Threshold", MAX98925_THRESHOLD, M98925_ALC_TH_SHIFT,
+				(1<<M98925_ALC_TH_WIDTH)-1, 0),
+	SOC_ENUM_EXT("Boost Output Voltage", max98925_boost_voltage_enum,
+		max98925_boost_voltage_get, max98925_boost_voltage_put),
+};
+
+/* codec sample rate and n/m dividers parameter table */
+static const struct {
+	int rate;
+	int  sr;
+	int divisors[3][2];
+} rate_table[] = {
+	{
+		.rate = 8000,
+		.sr = 0,
+		.divisors = { {1, 375}, {5, 1764}, {1, 384} }
+	},
+	{
+		.rate = 11025,
+		.sr = 1,
+		.divisors = { {147, 40000}, {1, 256}, {147, 40960} }
+	},
+	{
+		.rate = 12000,
+		.sr = 2,
+		.divisors = { {1, 250}, {5, 1176}, {1, 256} }
+	},
+	{
+		.rate = 16000,
+		.sr = 3,
+		.divisors = { {2, 375}, {5, 882}, {1, 192} }
+	},
+	{
+		.rate = 22050,
+		.sr = 4,
+		.divisors = { {147, 20000}, {1, 128}, {147, 20480} }
+	},
+	{
+		.rate = 24000,
+		.sr = 5,
+		.divisors = { {1, 125}, {5, 588}, {1, 128} }
+	},
+	{
+		.rate = 32000,
+		.sr = 6,
+		.divisors = { {4, 375}, {5, 441}, {1, 96} }
+	},
+	{
+		.rate = 44100,
+		.sr = 7,
+		.divisors = { {147, 10000}, {1, 64}, {147, 10240} }
+	},
+	{
+		.rate = 48000,
+		.sr = 8,
+		.divisors = { {2, 125}, {5, 294}, {1, 64} }
+	},
+};
+
+static inline int max98925_rate_value(int rate,
+		int clock, int *value, int *n, int *m)
+{
+	int ret = -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+		if (rate_table[i].rate >= rate) {
+			*value = rate_table[i].sr;
+			*n = rate_table[i].divisors[clock][0];
+			*m = rate_table[i].divisors[clock][1];
+			ret = 0;
+			break;
+		}
+	}
+	pr_debug("%s: sample rate is %d, returning %d\n",
+				__func__, rate_table[i].rate, *value);
+	return ret;
+}
+
+static void max98925_set_sense_data(struct max98925_priv *max98925)
+{
+	/* set VMON slots */
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_VMON,
+		M98925_DAI_VMON_EN_MASK, M98925_DAI_VMON_EN_MASK);
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_VMON,
+		M98925_DAI_VMON_SLOT_MASK, max98925->v_slot);
+	/* set IMON slots */
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_IMON,
+		M98925_DAI_IMON_EN_MASK, M98925_DAI_IMON_EN_MASK);
+	regmap_update_bits(max98925->regmap,
+		MAX98925_DOUT_CFG_IMON,
+		M98925_DAI_IMON_SLOT_MASK, max98925->i_slot);
+}
+
+static void max98925_set_slave(struct max98925_priv *max98925)
+{
+	/* set DAI to slave mode */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, 0);
+	max98925_set_sense_data(max98925);
+}
+
+static void max98925_set_master(struct max98925_priv *max98925)
+{
+	/* set left channel DAI to master mode, right channel always slave */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, M98925_DAI_MAS_MASK);
+}
+
+static int max98925_dai_set_fmt(struct snd_soc_dai *codec_dai,
+				 unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int invert = 0;
+
+	dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		max98925_set_slave(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		max98925_set_master(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+	default:
+		dev_err(codec->dev, "DAI clock mode unsupported");
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		invert = M98925_DAI_WCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert = M98925_DAI_BCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		invert = M98925_DAI_BCI_MASK | M98925_DAI_WCI_MASK;
+		break;
+	default:
+		dev_err(codec->dev, "DAI invert mode unsupported");
+		return -EINVAL;
+	}
+
+	regmap_update_bits(max98925->regmap, MAX98925_FORMAT,
+			M98925_DAI_BCI_MASK | M98925_DAI_BCI_MASK, invert);
+	return 0;
+}
+
+static int max98925_set_clock(struct max98925_priv *max98925,
+		struct snd_pcm_hw_params *params)
+{
+	unsigned int dai_sr = 0, clock, mdll, n, m;
+	int rate = params_rate(params);
+	/* BCLK/LRCLK ratio calculation */
+	int blr_clk_ratio = params_channels(params) * max98925->ch_size;
+
+	switch (blr_clk_ratio) {
+	case 32:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_32);
+		break;
+	case 48:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_48);
+		break;
+	case 64:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (max98925->sysclk) {
+	case 6000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx16;
+		break;
+	case 11289600:
+		clock = 1;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12288000:
+		clock = 2;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	default:
+		dev_info(max98925->codec->dev, "unsupported sysclk %d\n",
+					max98925->sysclk);
+		return -EINVAL;
+	}
+
+	if (max98925_rate_value(rate, clock, &dai_sr, &n, &m))
+		return -EINVAL;
+
+	/* set DAI_SR to correct LRCLK frequency */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_DAI_CLK_MODE2,
+			M98925_DAI_SR_MASK, dai_sr << M98925_DAI_SR_SHIFT);
+	/* set DAI m divider */
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_M_MSBS, m >> 8);
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_M_LSBS, m & 0xFF);
+	/* set DAI n divider */
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_N_MSBS, n >> 8);
+	regmap_write(max98925->regmap,
+		MAX98925_DAI_CLK_DIV_N_LSBS, n & 0xFF);
+	/* set MDLL */
+	regmap_update_bits(max98925->regmap, MAX98925_DAI_CLK_MODE1,
+			M98925_MDLL_MULT_MASK, mdll << M98925_MDLL_MULT_SHIFT);
+	return 0;
+}
+
+static int max98925_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 max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_16);
+		max98925->ch_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		max98925->ch_size = 32;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		max98925->ch_size = 32;
+		break;
+	default:
+		pr_err("%s: format unsupported %d",
+				__func__, params_format(params));
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "%s: format supported %d",
+				__func__, params_format(params));
+	return max98925_set_clock(max98925, params);
+}
+
+static int max98925_dai_set_sysclk(struct snd_soc_dai *dai,
+				   int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case 0:
+		/* use MCLK for Left channel, right channel always BCLK */
+		regmap_update_bits(max98925->regmap,
+				MAX98925_DAI_CLK_MODE1,
+				M98925_DAI_CLK_SOURCE_MASK, 0);
+		break;
+	case 1:
+		/* configure dai clock source to BCLK instead of MCLK */
+		regmap_update_bits(max98925->regmap,
+				MAX98925_DAI_CLK_MODE1,
+				M98925_DAI_CLK_SOURCE_MASK,
+				M98925_DAI_CLK_SOURCE_MASK);
+		break;
+	default:
+		return -EINVAL;
+	}
+	max98925->sysclk = freq;
+	return 0;
+}
+
+static int max98925_dai_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+	struct max98925_priv *max98925 =
+				snd_soc_codec_get_drvdata(codec_dai->codec);
+	struct snd_soc_codec *codec = codec_dai->codec;
+
+	dev_dbg(codec->dev, "%s: mute %d\n", __func__, mute);
+	if (mute) {
+		regmap_update_bits(max98925->regmap, MAX98925_GAIN,
+			M98925_SPK_GAIN_MASK, 0x00);
+
+		regmap_update_bits(max98925->regmap,
+			MAX98925_GLOBAL_ENABLE,
+			M98925_EN_MASK, 0x0);
+	}
+	return 0;
+}
+
+#define MAX98925_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops max98925_dai_ops = {
+	.set_sysclk = max98925_dai_set_sysclk,
+	.set_fmt = max98925_dai_set_fmt,
+	.hw_params = max98925_dai_hw_params,
+	.digital_mute = max98925_dai_digital_mute,
+};
+
+static struct snd_soc_dai_driver max98925_dai[] = {
+	{
+		.name = "max98925-aif1",
+		.playback = {
+			.stream_name = "HiFi Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HiFi Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.ops = &max98925_dai_ops,
+	}
+};
+
+static int max98925_probe(struct snd_soc_codec *codec)
+{
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
+	int reg = 0;
+
+	dev_info(codec->dev, "build number %s\n", MAX98925_REVISION);
+
+	max98925->codec = codec;
+	codec->control_data = max98925->regmap;
+	ret = regmap_read(max98925->regmap,
+			MAX98925_REV_VERSION, &reg);
+	if ((ret < 0) ||
+		((reg != MAX98925_VERSION) &&
+		(reg != MAX98925_VERSION1))) {
+		dev_err(codec->dev,
+			"device initialization error (%d 0x%02X)\n",
+			ret, reg);
+		goto err_access;
+	}
+	regmap_write(max98925->regmap, MAX98925_GLOBAL_ENABLE, 0x00);
+	/* It's not the default but we need to set DAI_DLY */
+	regmap_write(max98925->regmap,
+			MAX98925_FORMAT, M98925_DAI_DLY_MASK);
+	regmap_write(max98925->regmap, MAX98925_TDM_SLOT_SELECT, 0xC8);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG1, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG2, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG3, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_DOUT_HIZ_CFG4, 0xF0);
+	regmap_write(max98925->regmap, MAX98925_FILTERS, 0xD8);
+	regmap_write(max98925->regmap, MAX98925_ALC_CONFIGURATION, 0xF8);
+	regmap_write(max98925->regmap, MAX98925_CONFIGURATION, 0xF0);
+
+	/* Disable ALC muting */
+	regmap_write(max98925->regmap, MAX98925_BOOST_LIMITER, 0xF8);
+	dev_info(codec->dev, "device version 0x%02X\n", reg);
+err_access:
+	return ret;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98925 = {
+	.probe            = max98925_probe,
+	.controls = max98925_snd_controls,
+	.num_controls = ARRAY_SIZE(max98925_snd_controls),
+	.dapm_routes = max98925_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(max98925_audio_map),
+	.dapm_widgets = max98925_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets),
+};
+
+static struct regmap_config max98925_regmap = {
+	.reg_bits         = 8,
+	.val_bits         = 8,
+	.max_register     = MAX98925_REV_VERSION,
+	.reg_defaults     = max98925_reg,
+	.num_reg_defaults = ARRAY_SIZE(max98925_reg),
+	.volatile_reg     = max98925_volatile_register,
+	.readable_reg     = max98925_readable_register,
+	.cache_type       = REGCACHE_RBTREE,
+};
+
+static int max98925_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	int ret = 0;
+	u32 value;
+	struct max98925_priv *max98925;
+
+	max98925 = devm_kzalloc(&i2c->dev,
+			sizeof(*max98925), GFP_KERNEL);
+	if (!max98925)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, max98925);
+	max98925->regmap = devm_regmap_init_i2c(i2c, &max98925_regmap);
+	if (IS_ERR(max98925->regmap)) {
+		ret = PTR_ERR(max98925->regmap);
+		dev_err(&i2c->dev,
+				"Failed to allocate regmap: %d\n", ret);
+		goto err_out;
+	}
+
+	if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
+		if (value > M98925_DAI_VMON_SLOT_1E_1F) {
+			dev_err(&i2c->dev, "vmon slot number is wrong:\n");
+			return -EINVAL;
+		}
+		max98925->v_slot = value;
+	}
+	if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) {
+		if (value > M98925_DAI_IMON_SLOT_1E_1F) {
+			dev_err(&i2c->dev, "imon slot number is wrong:\n");
+			return -EINVAL;
+		}
+		max98925->i_slot = value;
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925,
+			max98925_dai, ARRAY_SIZE(max98925_dai));
+	if (ret < 0)
+		dev_err(&i2c->dev,
+				"Failed to register codec: %d\n", ret);
+err_out:
+	return ret;
+}
+
+static int max98925_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id max98925_i2c_id[] = {
+	{ "max98925", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max98925_i2c_id);
+
+static struct i2c_driver max98925_i2c_driver = {
+	.driver = {
+		.name = "max98925",
+		.owner = THIS_MODULE,
+		.pm = NULL,
+	},
+	.probe  = max98925_i2c_probe,
+	.remove = max98925_i2c_remove,
+	.id_table = max98925_i2c_id,
+};
+
+module_i2c_driver(max98925_i2c_driver)
+
+MODULE_DESCRIPTION("ALSA SoC MAX98925 driver");
+MODULE_AUTHOR("Ralph Birt <rdbirt@gmail.com>, Anish kumar <anish.kumar@maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98925.h b/sound/soc/codecs/max98925.h
new file mode 100644
index 0000000..d7ac021
--- /dev/null
+++ b/sound/soc/codecs/max98925.h
@@ -0,0 +1,833 @@
+/*
+ * max98925.h -- MAX98925 ALSA SoC Audio driver
+ *
+ * Copyright 2013-2015 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX98925_H
+#define _MAX98925_H
+
+#define	MAX98925_VERSION	0x51
+#define	MAX98925_VERSION1	0x80
+#define MAX98925_REVISION	"0.00.0333"
+#define MAX98925_VBAT_DATA		0x00
+#define MAX98925_VBST_DATA		0x01
+#define MAX98925_LIVE_STATUS0		0x02
+#define MAX98925_LIVE_STATUS1		0x03
+#define MAX98925_LIVE_STATUS2		0x04
+#define MAX98925_STATE0			0x05
+#define MAX98925_STATE1			0x06
+#define MAX98925_STATE2			0x07
+#define MAX98925_FLAG0			0x08
+#define MAX98925_FLAG1			0x09
+#define MAX98925_FLAG2			0x0A
+#define MAX98925_IRQ_ENABLE0		0x0B
+#define MAX98925_IRQ_ENABLE1		0x0C
+#define MAX98925_IRQ_ENABLE2		0x0D
+#define MAX98925_IRQ_CLEAR0		0x0E
+#define MAX98925_IRQ_CLEAR1		0x0F
+#define MAX98925_IRQ_CLEAR2		0x10
+#define MAX98925_MAP0			0x11
+#define MAX98925_MAP1			0x12
+#define MAX98925_MAP2			0x13
+#define MAX98925_MAP3			0x14
+#define MAX98925_MAP4			0x15
+#define MAX98925_MAP5			0x16
+#define MAX98925_MAP6			0x17
+#define MAX98925_MAP7			0x18
+#define MAX98925_MAP8			0x19
+#define MAX98925_DAI_CLK_MODE1		0x1A
+#define MAX98925_DAI_CLK_MODE2		0x1B
+#define MAX98925_DAI_CLK_DIV_M_MSBS	0x1C
+#define MAX98925_DAI_CLK_DIV_M_LSBS	0x1D
+#define MAX98925_DAI_CLK_DIV_N_MSBS	0x1E
+#define MAX98925_DAI_CLK_DIV_N_LSBS	0x1F
+#define MAX98925_FORMAT			0x20
+#define MAX98925_TDM_SLOT_SELECT	0x21
+#define MAX98925_DOUT_CFG_VMON		0x22
+#define MAX98925_DOUT_CFG_IMON		0x23
+#define MAX98925_DOUT_CFG_VBAT		0x24
+#define MAX98925_DOUT_CFG_VBST		0x25
+#define MAX98925_DOUT_CFG_FLAG		0x26
+#define MAX98925_DOUT_HIZ_CFG1		0x27
+#define MAX98925_DOUT_HIZ_CFG2		0x28
+#define MAX98925_DOUT_HIZ_CFG3		0x29
+#define MAX98925_DOUT_HIZ_CFG4		0x2A
+#define MAX98925_DOUT_DRV_STRENGTH	0x2B
+#define MAX98925_FILTERS		0x2C
+#define MAX98925_GAIN			0x2D
+#define MAX98925_GAIN_RAMPING		0x2E
+#define MAX98925_SPK_AMP		0x2F
+#define MAX98925_THRESHOLD		0x30
+#define MAX98925_ALC_ATTACK		0x31
+#define MAX98925_ALC_ATTEN_RLS		0x32
+#define MAX98925_ALC_HOLD_RLS		0x33
+#define MAX98925_ALC_CONFIGURATION	0x34
+#define MAX98925_BOOST_CONVERTER	0x35
+#define MAX98925_BLOCK_ENABLE		0x36
+#define MAX98925_CONFIGURATION		0x37
+#define MAX98925_GLOBAL_ENABLE		0x38
+#define MAX98925_BOOST_LIMITER		0x3A
+#define MAX98925_REV_VERSION		0xFF
+
+#define MAX98925_REG_CNT               (MAX98925_R03A_BOOST_LIMITER+1)
+
+/* MAX98925 Register Bit Fields */
+
+/* MAX98925_R002_LIVE_STATUS0 */
+#define M98925_THERMWARN_STATUS_MASK			(1<<3)
+#define M98925_THERMWARN_STATUS_SHIFT			3
+#define M98925_THERMWARN_STATUS_WIDTH			1
+#define M98925_THERMSHDN_STATUS_MASK			(1<<1)
+#define M98925_THERMSHDN_STATUS_SHIFT			1
+#define M98925_THERMSHDN_STATUS_WIDTH			1
+
+/* MAX98925_R003_LIVE_STATUS1 */
+#define M98925_SPKCURNT_STATUS_MASK			(1<<5)
+#define M98925_SPKCURNT_STATUS_SHIFT			5
+#define M98925_SPKCURNT_STATUS_WIDTH			1
+#define M98925_WATCHFAIL_STATUS_MASK			(1<<4)
+#define M98925_WATCHFAIL_STATUS_SHIFT			4
+#define M98925_WATCHFAIL_STATUS_WIDTH			1
+#define M98925_ALCINFH_STATUS_MASK			(1<<3)
+#define M98925_ALCINFH_STATUS_SHIFT			3
+#define M98925_ALCINFH_STATUS_WIDTH			1
+#define M98925_ALCACT_STATUS_MASK			(1<<2)
+#define M98925_ALCACT_STATUS_SHIFT			2
+#define M98925_ALCACT_STATUS_WIDTH			1
+#define M98925_ALCMUT_STATUS_MASK			(1<<1)
+#define M98925_ALCMUT_STATUS_SHIFT			1
+#define M98925_ALCMUT_STATUS_WIDTH			1
+#define M98925_ACLP_STATUS_MASK				(1<<0)
+#define M98925_ACLP_STATUS_SHIFT			0
+#define M98925_ACLP_STATUS_WIDTH			1
+
+/* MAX98925_R004_LIVE_STATUS2 */
+#define M98925_SLOTOVRN_STATUS_MASK			(1<<6)
+#define M98925_SLOTOVRN_STATUS_SHIFT			6
+#define M98925_SLOTOVRN_STATUS_WIDTH			1
+#define M98925_INVALSLOT_STATUS_MASK			(1<<5)
+#define M98925_INVALSLOT_STATUS_SHIFT			5
+#define M98925_INVALSLOT_STATUS_WIDTH			1
+#define M98925_SLOTCNFLT_STATUS_MASK			(1<<4)
+#define M98925_SLOTCNFLT_STATUS_SHIFT			4
+#define M98925_SLOTCNFLT_STATUS_WIDTH			1
+#define M98925_VBSTOVFL_STATUS_MASK			(1<<3)
+#define M98925_VBSTOVFL_STATUS_SHIFT			3
+#define M98925_VBSTOVFL_STATUS_WIDTH			1
+#define M98925_VBATOVFL_STATUS_MASK			(1<<2)
+#define M98925_VBATOVFL_STATUS_SHIFT			2
+#define M98925_VBATOVFL_STATUS_WIDTH			1
+#define M98925_IMONOVFL_STATUS_MASK			(1<<1)
+#define M98925_IMONOVFL_STATUS_SHIFT			1
+#define M98925_IMONOVFL_STATUS_WIDTH			1
+#define M98925_VMONOVFL_STATUS_MASK			(1<<0)
+#define M98925_VMONOVFL_STATUS_SHIFT			0
+#define M98925_VMONOVFL_STATUS_WIDTH			1
+
+/* MAX98925_R005_STATE0 */
+#define M98925_THERMWARN_END_STATE_MASK			(1<<3)
+#define M98925_THERMWARN_END_STATE_SHIFT		3
+#define M98925_THERMWARN_END_STATE_WIDTH		1
+#define M98925_THERMWARN_BGN_STATE_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_STATE_SHIFT		1
+#define M98925_THERMWARN_BGN_STATE_WIDTH		1
+#define M98925_THERMSHDN_END_STATE_MASK			(1<<1)
+#define M98925_THERMSHDN_END_STATE_SHIFT		1
+#define M98925_THERMSHDN_END_STATE_WIDTH		1
+#define M98925_THERMSHDN_BGN_STATE_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_STATE_SHIFT		0
+#define M98925_THERMSHDN_BGN_STATE_WIDTH		1
+
+/* MAX98925_R006_STATE1 */
+#define M98925_SPRCURNT_STATE_MASK			(1<<5)
+#define M98925_SPRCURNT_STATE_SHIFT			5
+#define M98925_SPRCURNT_STATE_WIDTH			1
+#define M98925_WATCHFAIL_STATE_MASK			(1<<4)
+#define M98925_WATCHFAIL_STATE_SHIFT			4
+#define M98925_WATCHFAIL_STATE_WIDTH			1
+#define M98925_ALCINFH_STATE_MASK			(1<<3)
+#define M98925_ALCINFH_STATE_SHIFT			3
+#define M98925_ALCINFH_STATE_WIDTH			1
+#define M98925_ALCACT_STATE_MASK			(1<<2)
+#define M98925_ALCACT_STATE_SHIFT			2
+#define M98925_ALCACT_STATE_WIDTH			1
+#define M98925_ALCMUT_STATE_MASK			(1<<1)
+#define M98925_ALCMUT_STATE_SHIFT			1
+#define M98925_ALCMUT_STATE_WIDTH			1
+#define M98925_ALCP_STATE_MASK				(1<<0)
+#define M98925_ALCP_STATE_SHIFT				0
+#define M98925_ALCP_STATE_WIDTH				1
+
+/* MAX98925_R007_STATE2 */
+#define M98925_SLOTOVRN_STATE_MASK			(1<<6)
+#define M98925_SLOTOVRN_STATE_SHIFT			6
+#define M98925_SLOTOVRN_STATE_WIDTH			1
+#define M98925_INVALSLOT_STATE_MASK			(1<<5)
+#define M98925_INVALSLOT_STATE_SHIFT			5
+#define M98925_INVALSLOT_STATE_WIDTH			1
+#define M98925_SLOTCNFLT_STATE_MASK			(1<<4)
+#define M98925_SLOTCNFLT_STATE_SHIFT			4
+#define M98925_SLOTCNFLT_STATE_WIDTH			1
+#define M98925_VBSTOVFL_STATE_MASK			(1<<3)
+#define M98925_VBSTOVFL_STATE_SHIFT			3
+#define M98925_VBSTOVFL_STATE_WIDTH			1
+#define M98925_VBATOVFL_STATE_MASK			(1<<2)
+#define M98925_VBATOVFL_STATE_SHIFT			2
+#define M98925_VBATOVFL_STATE_WIDTH			1
+#define M98925_IMONOVFL_STATE_MASK			(1<<1)
+#define M98925_IMONOVFL_STATE_SHIFT			1
+#define M98925_IMONOVFL_STATE_WIDTH			1
+#define M98925_VMONOVFL_STATE_MASK			(1<<0)
+#define M98925_VMONOVFL_STATE_SHIFT			0
+#define M98925_VMONOVFL_STATE_WIDTH			1
+
+/* MAX98925_R008_FLAG0 */
+#define M98925_THERMWARN_END_FLAG_MASK			(1<<3)
+#define M98925_THERMWARN_END_FLAG_SHIFT			3
+#define M98925_THERMWARN_END_FLAG_WIDTH			1
+#define M98925_THERMWARN_BGN_FLAG_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_FLAG_SHIFT			2
+#define M98925_THERMWARN_BGN_FLAG_WIDTH			1
+#define M98925_THERMSHDN_END_FLAG_MASK			(1<<1)
+#define M98925_THERMSHDN_END_FLAG_SHIFT			1
+#define M98925_THERMSHDN_END_FLAG_WIDTH			1
+#define M98925_THERMSHDN_BGN_FLAG_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_FLAG_SHIFT			0
+#define M98925_THERMSHDN_BGN_FLAG_WIDTH			1
+
+/* MAX98925_R009_FLAG1 */
+#define M98925_SPKCURNT_FLAG_MASK			(1<<5)
+#define M98925_SPKCURNT_FLAG_SHIFT			5
+#define M98925_SPKCURNT_FLAG_WIDTH			1
+#define M98925_WATCHFAIL_FLAG_MASK			(1<<4)
+#define M98925_WATCHFAIL_FLAG_SHIFT			4
+#define M98925_WATCHFAIL_FLAG_WIDTH			1
+#define M98925_ALCINFH_FLAG_MASK			(1<<3)
+#define M98925_ALCINFH_FLAG_SHIFT			3
+#define M98925_ALCINFH_FLAG_WIDTH			1
+#define M98925_ALCACT_FLAG_MASK				(1<<2)
+#define M98925_ALCACT_FLAG_SHIFT			2
+#define M98925_ALCACT_FLAG_WIDTH			1
+#define M98925_ALCMUT_FLAG_MASK				(1<<1)
+#define M98925_ALCMUT_FLAG_SHIFT			1
+#define M98925_ALCMUT_FLAG_WIDTH			1
+#define M98925_ALCP_FLAG_MASK				(1<<0)
+#define M98925_ALCP_FLAG_SHIFT				0
+#define M98925_ALCP_FLAG_WIDTH				1
+
+/* MAX98925_R00A_FLAG2 */
+#define M98925_SLOTOVRN_FLAG_MASK			(1<<6)
+#define M98925_SLOTOVRN_FLAG_SHIFT			6
+#define M98925_SLOTOVRN_FLAG_WIDTH			1
+#define M98925_INVALSLOT_FLAG_MASK			(1<<5)
+#define M98925_INVALSLOT_FLAG_SHIFT			5
+#define M98925_INVALSLOT_FLAG_WIDTH			1
+#define M98925_SLOTCNFLT_FLAG_MASK			(1<<4)
+#define M98925_SLOTCNFLT_FLAG_SHIFT			4
+#define M98925_SLOTCNFLT_FLAG_WIDTH			1
+#define M98925_VBSTOVFL_FLAG_MASK			(1<<3)
+#define M98925_VBSTOVFL_FLAG_SHIFT			3
+#define M98925_VBSTOVFL_FLAG_WIDTH			1
+#define M98925_VBATOVFL_FLAG_MASK			(1<<2)
+#define M98925_VBATOVFL_FLAG_SHIFT			2
+#define M98925_VBATOVFL_FLAG_WIDTH			1
+#define M98925_IMONOVFL_FLAG_MASK			(1<<1)
+#define M98925_IMONOVFL_FLAG_SHIFT			1
+#define M98925_IMONOVFL_FLAG_WIDTH			1
+#define M98925_VMONOVFL_FLAG_MASK			(1<<0)
+#define M98925_VMONOVFL_FLAG_SHIFT			0
+#define M98925_VMONOVFL_FLAG_WIDTH			1
+
+/* MAX98925_R00B_IRQ_ENABLE0 */
+#define M98925_THERMWARN_END_EN_MASK			(1<<3)
+#define M98925_THERMWARN_END_EN_SHIFT			3
+#define M98925_THERMWARN_END_EN_WIDTH			1
+#define M98925_THERMWARN_BGN_EN_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_EN_SHIFT			2
+#define M98925_THERMWARN_BGN_EN_WIDTH			1
+#define M98925_THERMSHDN_END_EN_MASK			(1<<1)
+#define M98925_THERMSHDN_END_EN_SHIFT			1
+#define M98925_THERMSHDN_END_EN_WIDTH			1
+#define M98925_THERMSHDN_BGN_EN_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_EN_SHIFT			0
+#define M98925_THERMSHDN_BGN_EN_WIDTH			1
+
+/* MAX98925_R00C_IRQ_ENABLE1 */
+#define M98925_SPKCURNT_EN_MASK				(1<<5)
+#define M98925_SPKCURNT_EN_SHIFT			5
+#define M98925_SPKCURNT_EN_WIDTH			1
+#define M98925_WATCHFAIL_EN_MASK			(1<<4)
+#define M98925_WATCHFAIL_EN_SHIFT			4
+#define M98925_WATCHFAIL_EN_WIDTH			1
+#define M98925_ALCINFH_EN_MASK				(1<<3)
+#define M98925_ALCINFH_EN_SHIFT				3
+#define M98925_ALCINFH_EN_WIDTH				1
+#define M98925_ALCACT_EN_MASK				(1<<2)
+#define M98925_ALCACT_EN_SHIFT				2
+#define M98925_ALCACT_EN_WIDTH				1
+#define M98925_ALCMUT_EN_MASK				(1<<1)
+#define M98925_ALCMUT_EN_SHIFT				1
+#define M98925_ALCMUT_EN_WIDTH				1
+#define M98925_ALCP_EN_MASK					(1<<0)
+#define M98925_ALCP_EN_SHIFT				0
+#define M98925_ALCP_EN_WIDTH				1
+
+/* MAX98925_R00D_IRQ_ENABLE2 */
+#define M98925_SLOTOVRN_EN_MASK					(1<<6)
+#define M98925_SLOTOVRN_EN_SHIFT				6
+#define M98925_SLOTOVRN_EN_WIDTH				1
+#define M98925_INVALSLOT_EN_MASK				(1<<5)
+#define M98925_INVALSLOT_EN_SHIFT				5
+#define M98925_INVALSLOT_EN_WIDTH				1
+#define M98925_SLOTCNFLT_EN_MASK				(1<<4)
+#define M98925_SLOTCNFLT_EN_SHIFT				4
+#define M98925_SLOTCNFLT_EN_WIDTH				1
+#define M98925_VBSTOVFL_EN_MASK					(1<<3)
+#define M98925_VBSTOVFL_EN_SHIFT				3
+#define M98925_VBSTOVFL_EN_WIDTH				1
+#define M98925_VBATOVFL_EN_MASK					(1<<2)
+#define M98925_VBATOVFL_EN_SHIFT				2
+#define M98925_VBATOVFL_EN_WIDTH				1
+#define M98925_IMONOVFL_EN_MASK					(1<<1)
+#define M98925_IMONOVFL_EN_SHIFT				1
+#define M98925_IMONOVFL_EN_WIDTH				1
+#define M98925_VMONOVFL_EN_MASK					(1<<0)
+#define M98925_VMONOVFL_EN_SHIFT				0
+#define M98925_VMONOVFL_EN_WIDTH				1
+
+/* MAX98925_R00E_IRQ_CLEAR0 */
+#define M98925_THERMWARN_END_CLR_MASK			(1<<3)
+#define M98925_THERMWARN_END_CLR_SHIFT			3
+#define M98925_THERMWARN_END_CLR_WIDTH			1
+#define M98925_THERMWARN_BGN_CLR_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_CLR_SHIFT			2
+#define M98925_THERMWARN_BGN_CLR_WIDTH			1
+#define M98925_THERMSHDN_END_CLR_MASK			(1<<1)
+#define M98925_THERMSHDN_END_CLR_SHIFT			1
+#define M98925_THERMSHDN_END_CLR_WIDTH			1
+#define M98925_THERMSHDN_BGN_CLR_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_CLR_SHIFT			0
+#define M98925_THERMSHDN_BGN_CLR_WIDTH			1
+
+/* MAX98925_R00F_IRQ_CLEAR1 */
+#define M98925_SPKCURNT_CLR_MASK				(1<<5)
+#define M98925_SPKCURNT_CLR_SHIFT				5
+#define M98925_SPKCURNT_CLR_WIDTH				1
+#define M98925_WATCHFAIL_CLR_MASK				(1<<4)
+#define M98925_WATCHFAIL_CLR_SHIFT				4
+#define M98925_WATCHFAIL_CLR_WIDTH				1
+#define M98925_ALCINFH_CLR_MASK					(1<<3)
+#define M98925_ALCINFH_CLR_SHIFT				3
+#define M98925_ALCINFH_CLR_WIDTH				1
+#define M98925_ALCACT_CLR_MASK					(1<<2)
+#define M98925_ALCACT_CLR_SHIFT					2
+#define M98925_ALCACT_CLR_WIDTH					1
+#define M98925_ALCMUT_CLR_MASK					(1<<1)
+#define M98925_ALCMUT_CLR_SHIFT					1
+#define M98925_ALCMUT_CLR_WIDTH					1
+#define M98925_ALCP_CLR_MASK					(1<<0)
+#define M98925_ALCP_CLR_SHIFT					0
+#define M98925_ALCP_CLR_WIDTH					1
+
+/* MAX98925_R010_IRQ_CLEAR2 */
+#define M98925_SLOTOVRN_CLR_MASK				(1<<6)
+#define M98925_SLOTOVRN_CLR_SHIFT				6
+#define M98925_SLOTOVRN_CLR_WIDTH				1
+#define M98925_INVALSLOT_CLR_MASK				(1<<5)
+#define M98925_INVALSLOT_CLR_SHIFT				5
+#define M98925_INVALSLOT_CLR_WIDTH				1
+#define M98925_SLOTCNFLT_CLR_MASK				(1<<4)
+#define M98925_SLOTCNFLT_CLR_SHIFT				4
+#define M98925_SLOTCNFLT_CLR_WIDTH				1
+#define M98925_VBSTOVFL_CLR_MASK				(1<<3)
+#define M98925_VBSTOVFL_CLR_SHIFT				3
+#define M98925_VBSTOVFL_CLR_WIDTH				1
+#define M98925_VBATOVFL_CLR_MASK				(1<<2)
+#define M98925_VBATOVFL_CLR_SHIFT				2
+#define M98925_VBATOVFL_CLR_WIDTH				1
+#define M98925_IMONOVFL_CLR_MASK				(1<<1)
+#define M98925_IMONOVFL_CLR_SHIFT				1
+#define M98925_IMONOVFL_CLR_WIDTH				1
+#define M98925_VMONOVFL_CLR_MASK				(1<<0)
+#define M98925_VMONOVFL_CLR_SHIFT				0
+#define M98925_VMONOVFL_CLR_WIDTH				1
+
+/* MAX98925_R011_MAP0 */
+#define M98925_ER_THERMWARN_EN_MASK				(1<<7)
+#define M98925_ER_THERMWARN_EN_SHIFT			7
+#define M98925_ER_THERMWARN_EN_WIDTH			1
+#define M98925_ER_THERMWARN_MAP_MASK			(0x07<<4)
+#define M98925_ER_THERMWARN_MAP_SHIFT			4
+#define M98925_ER_THERMWARN_MAP_WIDTH			3
+
+/* MAX98925_R012_MAP1 */
+#define M98925_ER_ALCMUT_EN_MASK				(1<<7)
+#define M98925_ER_ALCMUT_EN_SHIFT				7
+#define M98925_ER_ALCMUT_EN_WIDTH				1
+#define M98925_ER_ALCMUT_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCMUT_MAP_SHIFT				4
+#define M98925_ER_ALCMUT_MAP_WIDTH				3
+#define M98925_ER_ALCP_EN_MASK					(1<<3)
+#define M98925_ER_ALCP_EN_SHIFT					3
+#define M98925_ER_ALCP_EN_WIDTH					1
+#define M98925_ER_ALCP_MAP_MASK					(0x07<<0)
+#define M98925_ER_ALCP_MAP_SHIFT				0
+#define M98925_ER_ALCP_MAP_WIDTH				3
+
+/* MAX98925_R013_MAP2 */
+#define M98925_ER_ALCINFH_EN_MASK				(1<<7)
+#define M98925_ER_ALCINFH_EN_SHIFT				7
+#define M98925_ER_ALCINFH_EN_WIDTH				1
+#define M98925_ER_ALCINFH_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCINFH_MAP_SHIFT				4
+#define M98925_ER_ALCINFH_MAP_WIDTH				3
+#define M98925_ER_ALCACT_EN_MASK				(1<<3)
+#define M98925_ER_ALCACT_EN_SHIFT				3
+#define M98925_ER_ALCACT_EN_WIDTH				1
+#define M98925_ER_ALCACT_MAP_MASK				(0x07<<0)
+#define M98925_ER_ALCACT_MAP_SHIFT				0
+#define M98925_ER_ALCACT_MAP_WIDTH				3
+
+/* MAX98925_R014_MAP3 */
+#define M98925_ER_SPKCURNT_EN_MASK				(1<<7)
+#define M98925_ER_SPKCURNT_EN_SHIFT				7
+#define M98925_ER_SPKCURNT_EN_WIDTH				1
+#define M98925_ER_SPKCURNT_MAP_MASK				(0x07<<4)
+#define M98925_ER_SPKCURNT_MAP_SHIFT			4
+#define M98925_ER_SPKCURNT_MAP_WIDTH			3
+
+/* MAX98925_R015_MAP4 */
+/* RESERVED */
+
+/* MAX98925_R016_MAP5 */
+#define M98925_ER_IMONOVFL_EN_MASK				(1<<7)
+#define M98925_ER_IMONOVFL_EN_SHIFT				7
+#define M98925_ER_IMONOVFL_EN_WIDTH				1
+#define M98925_ER_IMONOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_IMONOVFL_MAP_SHIFT			4
+#define M98925_ER_IMONOVFL_MAP_WIDTH			3
+#define M98925_ER_VMONOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VMONOVFL_EN_SHIFT				3
+#define M98925_ER_VMONOVFL_EN_WIDTH				1
+#define M98925_ER_VMONOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VMONOVFL_MAP_SHIFT			0
+#define M98925_ER_VMONOVFL_MAP_WIDTH			3
+
+/* MAX98925_R017_MAP6 */
+#define M98925_ER_VBSTOVFL_EN_MASK				(1<<7)
+#define M98925_ER_VBSTOVFL_EN_SHIFT				7
+#define M98925_ER_VBSTOVFL_EN_WIDTH				1
+#define M98925_ER_VBSTOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_VBSTOVFL_MAP_SHIFT			4
+#define M98925_ER_VBSTOVFL_MAP_WIDTH			3
+#define M98925_ER_VBATOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VBATOVFL_EN_SHIFT				3
+#define M98925_ER_VBATOVFL_EN_WIDTH				1
+#define M98925_ER_VBATOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VBATOVFL_MAP_SHIFT			0
+#define M98925_ER_VBATOVFL_MAP_WIDTH			3
+
+/* MAX98925_R018_MAP7 */
+#define M98925_ER_INVALSLOT_EN_MASK				(1<<7)
+#define M98925_ER_INVALSLOT_EN_SHIFT			7
+#define M98925_ER_INVALSLOT_EN_WIDTH			1
+#define M98925_ER_INVALSLOT_MAP_MASK			(0x07<<4)
+#define M98925_ER_INVALSLOT_MAP_SHIFT			4
+#define M98925_ER_INVALSLOT_MAP_WIDTH			3
+#define M98925_ER_SLOTCNFLT_EN_MASK				(1<<3)
+#define M98925_ER_SLOTCNFLT_EN_SHIFT			3
+#define M98925_ER_SLOTCNFLT_EN_WIDTH			1
+#define M98925_ER_SLOTCNFLT_MAP_MASK			(0x07<<0)
+#define M98925_ER_SLOTCNFLT_MAP_SHIFT			0
+#define M98925_ER_SLOTCNFLT_MAP_WIDTH			3
+
+/* MAX98925_R019_MAP8 */
+#define M98925_ER_SLOTOVRN_EN_MASK	(1<<3)
+#define M98925_ER_SLOTOVRN_EN_SHIFT	3
+#define M98925_ER_SLOTOVRN_EN_WIDTH	1
+#define M98925_ER_SLOTOVRN_MAP_MASK	(0x07<<0)
+#define M98925_ER_SLOTOVRN_MAP_SHIFT	0
+#define M98925_ER_SLOTOVRN_MAP_WIDTH	3
+
+/* MAX98925_R01A_DAI_CLK_MODE1 */
+#define M98925_DAI_CLK_SOURCE_MASK	(1<<6)
+#define M98925_DAI_CLK_SOURCE_SHIFT	6
+#define M98925_DAI_CLK_SOURCE_WIDTH	1
+#define M98925_MDLL_MULT_MASK		(0x0F<<0)
+#define M98925_MDLL_MULT_SHIFT		0
+#define M98925_MDLL_MULT_WIDTH		4
+
+#define M98925_MDLL_MULT_MCLKx8		6
+#define M98925_MDLL_MULT_MCLKx16	8
+
+/* MAX98925_R01B_DAI_CLK_MODE2 */
+#define M98925_DAI_SR_MASK			(0x0F<<4)
+#define M98925_DAI_SR_SHIFT			4
+#define M98925_DAI_SR_WIDTH			4
+#define M98925_DAI_MAS_MASK			(1<<3)
+#define M98925_DAI_MAS_SHIFT			3
+#define M98925_DAI_MAS_WIDTH			1
+#define M98925_DAI_BSEL_MASK			(0x07<<0)
+#define M98925_DAI_BSEL_SHIFT			0
+#define M98925_DAI_BSEL_WIDTH			3
+
+#define M98925_DAI_BSEL_32 (0 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_48 (1 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_64 (2 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_256 (6 << M98925_DAI_BSEL_SHIFT)
+
+/* MAX98925_R01C_DAI_CLK_DIV_M_MSBS */
+#define M98925_DAI_M_MSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_MSBS_SHIFT					0
+#define M98925_DAI_M_MSBS_WIDTH					8
+
+/* MAX98925_R01D_DAI_CLK_DIV_M_LSBS */
+#define M98925_DAI_M_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_LSBS_SHIFT					0
+#define M98925_DAI_M_LSBS_WIDTH					8
+
+/* MAX98925_R01E_DAI_CLK_DIV_N_MSBS */
+#define M98925_DAI_N_MSBS_MASK					(0x7F<<0)
+#define M98925_DAI_N_MSBS_SHIFT					0
+#define M98925_DAI_N_MSBS_WIDTH					7
+
+/* MAX98925_R01F_DAI_CLK_DIV_N_LSBS */
+#define M98925_DAI_N_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_N_LSBS_SHIFT					0
+#define M98925_DAI_N_LSBS_WIDTH					8
+
+/* MAX98925_R020_FORMAT */
+#define M98925_DAI_CHANSZ_MASK					(0x03<<6)
+#define M98925_DAI_CHANSZ_SHIFT					6
+#define M98925_DAI_CHANSZ_WIDTH					2
+#define M98925_DAI_EXTBCLK_HIZ_MASK				(1<<4)
+#define M98925_DAI_EXTBCLK_HIZ_SHIFT			4
+#define M98925_DAI_EXTBCLK_HIZ_WIDTH			1
+#define M98925_DAI_WCI_MASK						(1<<3)
+#define M98925_DAI_WCI_SHIFT					3
+#define M98925_DAI_WCI_WIDTH					1
+#define M98925_DAI_BCI_MASK						(1<<2)
+#define M98925_DAI_BCI_SHIFT					2
+#define M98925_DAI_BCI_WIDTH					1
+#define M98925_DAI_DLY_MASK						(1<<1)
+#define M98925_DAI_DLY_SHIFT					1
+#define M98925_DAI_DLY_WIDTH					1
+#define M98925_DAI_TDM_MASK						(1<<0)
+#define M98925_DAI_TDM_SHIFT					0
+#define M98925_DAI_TDM_WIDTH					1
+
+#define M98925_DAI_CHANSZ_16 (1 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_24 (2 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_32 (3 << M98925_DAI_CHANSZ_SHIFT)
+
+/* MAX98925_R021_TDM_SLOT_SELECT */
+#define M98925_DAI_DO_EN_MASK					(1<<7)
+#define M98925_DAI_DO_EN_SHIFT					7
+#define M98925_DAI_DO_EN_WIDTH					1
+#define M98925_DAI_DIN_EN_MASK					(1<<6)
+#define M98925_DAI_DIN_EN_SHIFT					6
+#define M98925_DAI_DIN_EN_WIDTH					1
+#define M98925_DAI_INR_SOURCE_MASK				(0x07<<3)
+#define M98925_DAI_INR_SOURCE_SHIFT				3
+#define M98925_DAI_INR_SOURCE_WIDTH				3
+#define M98925_DAI_INL_SOURCE_MASK				(0x07<<0)
+#define M98925_DAI_INL_SOURCE_SHIFT				0
+#define M98925_DAI_INL_SOURCE_WIDTH				3
+
+/* MAX98925_R022_DOUT_CFG_VMON */
+#define M98925_DAI_VMON_EN_MASK					(1<<5)
+#define M98925_DAI_VMON_EN_SHIFT				5
+#define M98925_DAI_VMON_EN_WIDTH				1
+#define M98925_DAI_VMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VMON_SLOT_SHIFT				0
+#define M98925_DAI_VMON_SLOT_WIDTH				5
+
+#define M98925_DAI_VMON_SLOT_00_01 (0 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_01_02 (1 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_02_03 (2 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_03_04 (3 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_04_05 (4 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_05_06 (5 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_06_07 (6 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_07_08 (7 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_08_09 (8 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_09_0A (9 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0A_0B (10 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0B_0C (11 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0C_0D (12 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0D_0E (13 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0E_0F (14 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0F_10 (15 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_10_11 (16 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_11_12 (17 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_12_13 (18 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_13_14 (19 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_14_15 (20 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_15_16 (21 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_16_17 (22 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_17_18 (23 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_18_19 (24 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_19_1A (25 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1A_1B (26 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1B_1C (27 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1C_1D (28 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1D_1E (29 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1E_1F (30 << M98925_DAI_VMON_SLOT_SHIFT)
+
+/* MAX98925_R023_DOUT_CFG_IMON */
+#define M98925_DAI_IMON_EN_MASK					(1<<5)
+#define M98925_DAI_IMON_EN_SHIFT				5
+#define M98925_DAI_IMON_EN_WIDTH				1
+#define M98925_DAI_IMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_IMON_SLOT_SHIFT				0
+#define M98925_DAI_IMON_SLOT_WIDTH				5
+
+#define M98925_DAI_IMON_SLOT_00_01 (0 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_01_02 (1 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_02_03 (2 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_03_04 (3 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_04_05 (4 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_05_06 (5 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_06_07 (6 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_07_08 (7 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_08_09 (8 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_09_0A (9 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0A_0B (10 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0B_0C (11 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0C_0D (12 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0D_0E (13 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0E_0F (14 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0F_10 (15 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_10_11 (16 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_11_12 (17 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_12_13 (18 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_13_14 (19 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_14_15 (20 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_15_16 (21 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_16_17 (22 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_17_18 (23 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_18_19 (24 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_19_1A (25 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1A_1B (26 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1B_1C (27 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1C_1D (28 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1D_1E (29 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1E_1F (30 << M98925_DAI_IMON_SLOT_SHIFT)
+
+/* MAX98925_R024_DOUT_CFG_VBAT */
+#define M98925_DAI_VBAT_EN_MASK					(1<<5)
+#define M98925_DAI_VBAT_EN_SHIFT				5
+#define M98925_DAI_VBAT_EN_WIDTH				1
+#define M98925_DAI_VBAT_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBAT_SLOT_SHIFT				0
+#define M98925_DAI_VBAT_SLOT_WIDTH				5
+
+/* MAX98925_R025_DOUT_CFG_VBST */
+#define M98925_DAI_VBST_EN_MASK					(1<<5)
+#define M98925_DAI_VBST_EN_SHIFT				5
+#define M98925_DAI_VBST_EN_WIDTH				1
+#define M98925_DAI_VBST_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBST_SLOT_SHIFT				0
+#define M98925_DAI_VBST_SLOT_WIDTH				5
+
+/* MAX98925_R026_DOUT_CFG_FLAG */
+#define M98925_DAI_FLAG_EN_MASK					(1<<5)
+#define M98925_DAI_FLAG_EN_SHIFT				5
+#define M98925_DAI_FLAG_EN_WIDTH				1
+#define M98925_DAI_FLAG_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_FLAG_SLOT_SHIFT				0
+#define M98925_DAI_FLAG_SLOT_WIDTH				5
+
+/* MAX98925_R027_DOUT_HIZ_CFG1 */
+#define M98925_DAI_SLOT_HIZ_CFG1_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG1_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG1_WIDTH			8
+
+/* MAX98925_R028_DOUT_HIZ_CFG2 */
+#define M98925_DAI_SLOT_HIZ_CFG2_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG2_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG2_WIDTH			8
+
+/* MAX98925_R029_DOUT_HIZ_CFG3 */
+#define M98925_DAI_SLOT_HIZ_CFG3_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG3_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG3_WIDTH			8
+
+/* MAX98925_R02A_DOUT_HIZ_CFG4 */
+#define M98925_DAI_SLOT_HIZ_CFG4_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG4_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG4_WIDTH			8
+
+/* MAX98925_R02B_DOUT_DRV_STRENGTH */
+#define M98925_DAI_OUT_DRIVE_MASK				(0x03<<0)
+#define M98925_DAI_OUT_DRIVE_SHIFT				0
+#define M98925_DAI_OUT_DRIVE_WIDTH				2
+
+/* MAX98925_R02C_FILTERS */
+#define M98925_ADC_DITHER_EN_MASK				(1<<7)
+#define M98925_ADC_DITHER_EN_SHIFT				7
+#define M98925_ADC_DITHER_EN_WIDTH				1
+#define M98925_IV_DCB_EN_MASK					(1<<6)
+#define M98925_IV_DCB_EN_SHIFT					6
+#define M98925_IV_DCB_EN_WIDTH					1
+#define M98925_DAC_DITHER_EN_MASK				(1<<4)
+#define M98925_DAC_DITHER_EN_SHIFT				4
+#define M98925_DAC_DITHER_EN_WIDTH				1
+#define M98925_DAC_FILTER_MODE_MASK				(1<<3)
+#define M98925_DAC_FILTER_MODE_SHIFT			3
+#define M98925_DAC_FILTER_MODE_WIDTH			1
+#define M98925_DAC_HPF_MASK				(0x07<<0)
+#define M98925_DAC_HPF_SHIFT					0
+#define M98925_DAC_HPF_WIDTH					3
+#define M98925_DAC_HPF_DISABLE		(0 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_DC_BLOCK		(1 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_100		(2 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_200		(3 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_400		(4 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_800		(5 << M98925_DAC_HPF_SHIFT)
+
+/* MAX98925_R02D_GAIN */
+#define M98925_DAC_IN_SEL_MASK					(0x03<<5)
+#define M98925_DAC_IN_SEL_SHIFT					5
+#define M98925_DAC_IN_SEL_WIDTH					2
+#define M98925_SPK_GAIN_MASK					(0x1F<<0)
+#define M98925_SPK_GAIN_SHIFT					0
+#define M98925_SPK_GAIN_WIDTH					5
+
+#define M98925_DAC_IN_SEL_LEFT_DAI (0 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_RIGHT_DAI (1 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_SUMMED_DAI (2 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << M98925_DAC_IN_SEL_SHIFT)
+
+/* MAX98925_R02E_GAIN_RAMPING */
+#define M98925_SPK_RMP_EN_MASK		(1<<1)
+#define M98925_SPK_RMP_EN_SHIFT		1
+#define M98925_SPK_RMP_EN_WIDTH		1
+#define M98925_SPK_ZCD_EN_MASK		(1<<0)
+#define M98925_SPK_ZCD_EN_SHIFT		0
+#define M98925_SPK_ZCD_EN_WIDTH		1
+
+/* MAX98925_R02F_SPK_AMP */
+#define M98925_SPK_MODE_MASK		(1<<0)
+#define M98925_SPK_MODE_SHIFT		0
+#define M98925_SPK_MODE_WIDTH		1
+
+/* MAX98925_R030_THRESHOLD */
+#define M98925_ALC_EN_MASK			(1<<5)
+#define M98925_ALC_EN_SHIFT			5
+#define M98925_ALC_EN_WIDTH			1
+#define M98925_ALC_TH_MASK			(0x1F<<0)
+#define M98925_ALC_TH_SHIFT			0
+#define M98925_ALC_TH_WIDTH			5
+
+/* MAX98925_R031_ALC_ATTACK */
+#define M98925_ALC_ATK_STEP_MASK	(0x0F<<4)
+#define M98925_ALC_ATK_STEP_SHIFT	4
+#define M98925_ALC_ATK_STEP_WIDTH	4
+#define M98925_ALC_ATK_RATE_MASK	(0x7<<0)
+#define M98925_ALC_ATK_RATE_SHIFT	0
+#define M98925_ALC_ATK_RATE_WIDTH	3
+
+/* MAX98925_R032_ALC_ATTEN_RLS */
+#define M98925_ALC_MAX_ATTEN_MASK	(0x0F<<4)
+#define M98925_ALC_MAX_ATTEN_SHIFT	4
+#define M98925_ALC_MAX_ATTEN_WIDTH	4
+#define M98925_ALC_RLS_RATE_MASK	(0x7<<0)
+#define M98925_ALC_RLS_RATE_SHIFT	0
+#define M98925_ALC_RLS_RATE_WIDTH	3
+
+/* MAX98925_R033_ALC_HOLD_RLS */
+#define M98925_ALC_RLS_TGR_MASK		(1<<0)
+#define M98925_ALC_RLS_TGR_SHIFT	0
+#define M98925_ALC_RLS_TGR_WIDTH	1
+
+/* MAX98925_R034_ALC_CONFIGURATION */
+#define M98925_ALC_MUTE_EN_MASK		(1<<7)
+#define M98925_ALC_MUTE_EN_SHIFT	7
+#define M98925_ALC_MUTE_EN_WIDTH	1
+#define M98925_ALC_MUTE_DLY_MASK	(0x07<<4)
+#define M98925_ALC_MUTE_DLY_SHIFT	4
+#define M98925_ALC_MUTE_DLY_WIDTH	3
+#define M98925_ALC_RLS_DBT_MASK		(0x07<<0)
+#define M98925_ALC_RLS_DBT_SHIFT	0
+#define M98925_ALC_RLS_DBT_WIDTH	3
+
+/* MAX98925_R035_BOOST_CONVERTER */
+#define M98925_BST_SYNC_MASK		(1<<7)
+#define M98925_BST_SYNC_SHIFT		7
+#define M98925_BST_SYNC_WIDTH		1
+#define M98925_BST_PHASE_MASK		(0x03<<4)
+#define M98925_BST_PHASE_SHIFT		4
+#define M98925_BST_PHASE_WIDTH		2
+#define M98925_BST_SKIP_MODE_MASK	(0x03<<0)
+#define M98925_BST_SKIP_MODE_SHIFT	0
+#define M98925_BST_SKIP_MODE_WIDTH	2
+
+/* MAX98925_R036_BLOCK_ENABLE */
+#define M98925_BST_EN_MASK			(1<<7)
+#define M98925_BST_EN_SHIFT			7
+#define M98925_BST_EN_WIDTH			1
+#define M98925_WATCH_EN_MASK		(1<<6)
+#define M98925_WATCH_EN_SHIFT		6
+#define M98925_WATCH_EN_WIDTH		1
+#define M98925_CLKMON_EN_MASK		(1<<5)
+#define M98925_CLKMON_EN_SHIFT		5
+#define M98925_CLKMON_EN_WIDTH		1
+#define M98925_SPK_EN_MASK			(1<<4)
+#define M98925_SPK_EN_SHIFT			4
+#define M98925_SPK_EN_WIDTH			1
+#define M98925_ADC_VBST_EN_MASK		(1<<3)
+#define M98925_ADC_VBST_EN_SHIFT	3
+#define M98925_ADC_VBST_EN_WIDTH	1
+#define M98925_ADC_VBAT_EN_MASK		(1<<2)
+#define M98925_ADC_VBAT_EN_SHIFT	2
+#define M98925_ADC_VBAT_EN_WIDTH	1
+#define M98925_ADC_IMON_EN_MASK		(1<<1)
+#define M98925_ADC_IMON_EN_SHIFT	1
+#define M98925_ADC_IMON_EN_WIDTH	1
+#define M98925_ADC_VMON_EN_MASK		(1<<0)
+#define M98925_ADC_VMON_EN_SHIFT	0
+#define M98925_ADC_VMON_EN_WIDTH	1
+
+/* MAX98925_R037_CONFIGURATION */
+#define M98925_BST_VOUT_MASK		(0x0F<<4)
+#define M98925_BST_VOUT_SHIFT		4
+#define M98925_BST_VOUT_WIDTH		4
+#define M98925_THERMWARN_LEVEL_MASK	(0x03<<2)
+#define M98925_THERMWARN_LEVEL_SHIFT			2
+#define M98925_THERMWARN_LEVEL_WIDTH			2
+#define M98925_WATCH_TIME_MASK			(0x03<<0)
+#define M98925_WATCH_TIME_SHIFT			0
+#define M98925_WATCH_TIME_WIDTH			2
+
+/* MAX98925_R038_GLOBAL_ENABLE */
+#define M98925_EN_MASK			(1<<7)
+#define M98925_EN_SHIFT			7
+#define M98925_EN_WIDTH			1
+
+/* MAX98925_R03A_BOOST_LIMITER */
+#define M98925_BST_ILIM_MASK	(0x1F<<3)
+#define M98925_BST_ILIM_SHIFT	3
+#define M98925_BST_ILIM_WIDTH	5
+
+/* MAX98925_R0FF_VERSION */
+#define M98925_REV_ID_MASK	(0xFF<<0)
+#define M98925_REV_ID_SHIFT	0
+#define M98925_REV_ID_WIDTH	8
+
+struct max98925_priv {
+	struct regmap *regmap;
+	struct snd_soc_codec *codec;
+	struct max98925_pdata *pdata;
+	unsigned int sysclk;
+	unsigned int v_slot;
+	unsigned int i_slot;
+	unsigned int spk_gain;
+	unsigned int ch_size;
+};
+#endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-24 14:50     ` Mark Brown
@ 2015-02-24 17:57       ` anish
  0 siblings, 0 replies; 15+ messages in thread
From: anish @ 2015-02-24 17:57 UTC (permalink / raw)
  To: Mark Brown
  Cc: liam.r.girdwood, Maxwell McKinnon, Linux-ALSA,
	Lars-Peter Clausen, Nitin Mittal

On Tue, Feb 24, 2015 at 6:50 AM, Mark Brown <broonie@kernel.org> wrote:
> On Fri, Feb 13, 2015 at 10:35:42PM -0800, anish wrote:
>> On Fri, Feb 13, 2015 at 9:14 PM, Mark Brown <broonie@kernel.org> wrote:
>
>> >> +     switch (reg) {
>> >> +     case MAX98925_R000_VBAT_DATA:
>
>> > Putting the register numbers in the define for the register name seems
>> > to defeat some of the point of the defines...
>
>> Looked at the other driver and everyone is using the same way.
>> Sorry but didn't get your point.
>
> Nobody else has the register numbers as part of the names defined for
> the registers which was what my point was.

Point well received.
>
>> >> +     max98925_regmap_update_bits_stereo(max98925,
>> >> +                     MAX98925_R01B_DAI_CLK_MODE2,
>> >> +                     M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
>
>> > This looks to be a mix of setting slave mode and setting some clocking
>> > configuration that ought to be configurable - for example I'd expect
>> > clock sources to be configured via set_sysclk().
>
>> Slave mode also should be configured in set_sysclk? I will move
>> bclk and lrclk setting to set_sysclk.
>
> Not slave mode but the other bits.

I did that.
>
>> >> +             max98925_regmap_update_bits_stereo(max98925,
>> >> +                     MAX98925_R036_BLOCK_ENABLE,
>> >> +                     M98925_BST_EN_MASK |
>> >> +                     M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
>> >> +                     M98925_BST_EN_MASK |
>> >> +                     M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
>> >> +
>> >> +             max98925_regmap_write_stereo(max98925,
>> >> +                     MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
>> >> +     }
>> >
>> > This doesn't look like it's muting, it looks like it's doing a whole
>> > bunch of other things.  The mute operation should mute and only mute
>> > (and then only if the device usefully supports it).
>
>> Coming to think of it, you are right. I am wondering if this(turning on voltage)
>> and current along with global audio enable bit) should
>> be dapm widget as it should always be turned on whenever
>> playback starts. I think i will make it a callback of
>> SND_SOC_DAPM_DAC_E
>
> If it's really a global enable used in all cases set_bias_level() is
> probably the place to do it - it's for chip wide stuff.  If there are
> some cases where it's not needed then DAPM widgets (normally a supply
> widget) are the best place.

As commented i will change this to supply widget.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-24  9:03 ` Mark Brown
@ 2015-02-24 17:56   ` anish
  0 siblings, 0 replies; 15+ messages in thread
From: anish @ 2015-02-24 17:56 UTC (permalink / raw)
  To: Mark Brown
  Cc: liam.r.girdwood, Maxwell McKinnon, Linux-ALSA,
	Lars-Peter Clausen, Nitin Mittal

On Tue, Feb 24, 2015 at 1:03 AM, Mark Brown <broonie@kernel.org> wrote:
> On Wed, Feb 18, 2015 at 08:09:46PM -0800, Anish Kumar wrote:
>
>> +config SND_SOC_MAX98925
>> +       tristate "Support MAX98925 audio codec"
>> +       depends on I2C
>> +       help
>> +       MAX98925 is a high-efficiency mono
>> +       Class DG audio amplifier. Use this
>> +       option to enable the codec.
>> +
>
> As I said in reply to an earlier version of this patch please format
> this using the normal style for Kconfig entries.
Sorry but i don't understand. I thought i copied the style.
Can you be specific as to the meaning?

>
>> +static const char *const dai_text[] = {
>> +     "left", "right", "leftright", "leftrightdiv2",
>> +};
>> +
>> +static const char *const hpf_text[] = {
>> +     "disable", "dc_block", "100Hz", "200Hz", "400Hz", "800Hz",
>> +};
>
> As I also said in reply to an earlier version please follow the normal
> style for enumeration entries with capitalization, use of spaces and so
> on.

I think the problem is only with "disable" and "dc_block". I will change
it as you said.
>
>> +static struct reg_default max98925_reg[] = {
>> +     { 0x00, 0x00 }, /* Battery Voltage Data */
>> +     { 0x01, 0x00 }, /* Boost Voltage Data */
>> +     { 0x02, 0x00 }, /* Live Status0 */
>> +     { 0x03, 0x00 }, /* Live Status1 */
>> +     { 0x04, 0x00 }, /* Live Status2 */
>
> As I said in reply to a previous version of this patch these seem like
> volatile registers so why do they have defaults defined?

overlooked this.Will remove it.
>
> I'm going to glance through the rest of this but not too closely given
> that a number of issues from the original review appear to remain
> unaddressed and (perhaps more importantly) I'm about to run out of
> batter).
>
>> +static int max98925_reg_put(struct snd_kcontrol *kcontrol,
>> +             struct snd_ctl_elem_value *ucontrol, unsigned int reg,
>> +             unsigned int mask, unsigned int shift)
>> +{
>> +     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
>> +     struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
>> +     unsigned int sel = ucontrol->value.integer.value[0];
>> +
>> +     regmap_update_bits(max98925->regmap, reg, mask, sel<<shift);
>> +     dev_dbg(codec->dev, "%s: register 0x%02X, value 0x%02X\n",
>> +                             __func__, reg, sel);
>> +     return 0;
>> +}
>
> This looks like a standard control, why is this open coded?  I'd also
> expect some bounds checking on the write.

We wanted mechanism to read/write any register so we used this control.
Is this functionality already available?
>
>> +static int max98925_dac_event(struct snd_soc_dapm_widget *w,
>> +             struct snd_kcontrol *kcontrol, int event)
>> +{
>> +     struct snd_soc_codec *codec = w->codec;
>> +     struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
>> +
>> +     regmap_update_bits(max98925->regmap,
>> +             MAX98925_R036_BLOCK_ENABLE,
>> +             M98925_BST_EN_MASK |
>> +             M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
>> +             M98925_BST_EN_MASK |
>> +             M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
>> +     regmap_write(max98925->regmap,
>> +     MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
>> +     return 0;
>> +}
>
> It's a bit surprising not to see any of these enables getting turned off
> when we power down - won't that waste power?  Looking at the names I'm
> wondering if these might make more sense as supply widgets.

will change it as supply widgets.
>
>> +static int max98925_spk_gain_put(struct snd_kcontrol *kcontrol,
>> +                             struct snd_ctl_elem_value *ucontrol)
>> +{
>> +     struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
>> +     struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
>> +     unsigned int sel = ucontrol->value.integer.value[0];
>> +
>> +     if (sel < ((1 << M98925_SPK_GAIN_WIDTH) - 1)) {
>> +             regmap_update_bits(max98925->regmap, MAX98925_R02D_GAIN,
>> +                     M98925_SPK_GAIN_MASK, sel << M98925_SPK_GAIN_SHIFT);
>> +             max98925->spk_gain = sel;
>
> Why is this not just a normal control?  I can't see any reference to
> spk_gain elsewhere...  similar things apply to a lot of these controls.

it is used in corresponding get function.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-14  6:35   ` anish
@ 2015-02-24 14:50     ` Mark Brown
  2015-02-24 17:57       ` anish
  0 siblings, 1 reply; 15+ messages in thread
From: Mark Brown @ 2015-02-24 14:50 UTC (permalink / raw)
  To: anish
  Cc: liam.r.girdwood, Maxwell McKinnon, Linux-ALSA,
	Lars-Peter Clausen, Nitin Mittal


[-- Attachment #1.1: Type: text/plain, Size: 2311 bytes --]

On Fri, Feb 13, 2015 at 10:35:42PM -0800, anish wrote:
> On Fri, Feb 13, 2015 at 9:14 PM, Mark Brown <broonie@kernel.org> wrote:

> >> +     switch (reg) {
> >> +     case MAX98925_R000_VBAT_DATA:

> > Putting the register numbers in the define for the register name seems
> > to defeat some of the point of the defines...

> Looked at the other driver and everyone is using the same way.
> Sorry but didn't get your point.

Nobody else has the register numbers as part of the names defined for
the registers which was what my point was.

> >> +     max98925_regmap_update_bits_stereo(max98925,
> >> +                     MAX98925_R01B_DAI_CLK_MODE2,
> >> +                     M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);

> > This looks to be a mix of setting slave mode and setting some clocking
> > configuration that ought to be configurable - for example I'd expect
> > clock sources to be configured via set_sysclk().

> Slave mode also should be configured in set_sysclk? I will move
> bclk and lrclk setting to set_sysclk.

Not slave mode but the other bits.

> >> +             max98925_regmap_update_bits_stereo(max98925,
> >> +                     MAX98925_R036_BLOCK_ENABLE,
> >> +                     M98925_BST_EN_MASK |
> >> +                     M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
> >> +                     M98925_BST_EN_MASK |
> >> +                     M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
> >> +
> >> +             max98925_regmap_write_stereo(max98925,
> >> +                     MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
> >> +     }
> >
> > This doesn't look like it's muting, it looks like it's doing a whole
> > bunch of other things.  The mute operation should mute and only mute
> > (and then only if the device usefully supports it).

> Coming to think of it, you are right. I am wondering if this(turning on voltage)
> and current along with global audio enable bit) should
> be dapm widget as it should always be turned on whenever
> playback starts. I think i will make it a callback of
> SND_SOC_DAPM_DAC_E

If it's really a global enable used in all cases set_bias_level() is
probably the place to do it - it's for chip wide stuff.  If there are
some cases where it's not needed then DAPM widgets (normally a supply
widget) are the best place.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-19  4:09 Anish Kumar
  2015-02-19  6:49 ` Tushar Behera
@ 2015-02-24  9:03 ` Mark Brown
  2015-02-24 17:56   ` anish
  1 sibling, 1 reply; 15+ messages in thread
From: Mark Brown @ 2015-02-24  9:03 UTC (permalink / raw)
  To: Anish Kumar
  Cc: liam.r.girdwood, Maxwell.McKinnon, alsa-devel, lars, nitin.mittal


[-- Attachment #1.1: Type: text/plain, Size: 3588 bytes --]

On Wed, Feb 18, 2015 at 08:09:46PM -0800, Anish Kumar wrote:

> +config SND_SOC_MAX98925
> +       tristate "Support MAX98925 audio codec"
> +       depends on I2C
> +       help
> +       MAX98925 is a high-efficiency mono
> +       Class DG audio amplifier. Use this
> +       option to enable the codec.
> +

As I said in reply to an earlier version of this patch please format
this using the normal style for Kconfig entries.

> +static const char *const dai_text[] = {
> +	"left", "right", "leftright", "leftrightdiv2",
> +};
> +
> +static const char *const hpf_text[] = {
> +	"disable", "dc_block", "100Hz",	"200Hz", "400Hz", "800Hz",
> +};

As I also said in reply to an earlier version please follow the normal
style for enumeration entries with capitalization, use of spaces and so
on.

> +static struct reg_default max98925_reg[] = {
> +	{ 0x00, 0x00 }, /* Battery Voltage Data */
> +	{ 0x01, 0x00 }, /* Boost Voltage Data */
> +	{ 0x02, 0x00 }, /* Live Status0 */
> +	{ 0x03, 0x00 }, /* Live Status1 */
> +	{ 0x04, 0x00 }, /* Live Status2 */

As I said in reply to a previous version of this patch these seem like
volatile registers so why do they have defaults defined?  

I'm going to glance through the rest of this but not too closely given
that a number of issues from the original review appear to remain
unaddressed and (perhaps more importantly) I'm about to run out of
batter).

> +static int max98925_reg_put(struct snd_kcontrol *kcontrol,
> +		struct snd_ctl_elem_value *ucontrol, unsigned int reg,
> +		unsigned int mask, unsigned int shift)
> +{
> +	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +	unsigned int sel = ucontrol->value.integer.value[0];
> +
> +	regmap_update_bits(max98925->regmap, reg, mask, sel<<shift);
> +	dev_dbg(codec->dev, "%s: register 0x%02X, value 0x%02X\n",
> +				__func__, reg, sel);
> +	return 0;
> +}

This looks like a standard control, why is this open coded?  I'd also
expect some bounds checking on the write.

> +static int max98925_dac_event(struct snd_soc_dapm_widget *w,
> +		struct snd_kcontrol *kcontrol, int event)
> +{
> +	struct snd_soc_codec *codec = w->codec;
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +
> +	regmap_update_bits(max98925->regmap,
> +		MAX98925_R036_BLOCK_ENABLE,
> +		M98925_BST_EN_MASK |
> +		M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
> +		M98925_BST_EN_MASK |
> +		M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
> +	regmap_write(max98925->regmap,
> +	MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
> +	return 0;
> +}

It's a bit surprising not to see any of these enables getting turned off
when we power down - won't that waste power?  Looking at the names I'm
wondering if these might make more sense as supply widgets.

> +static int max98925_spk_gain_put(struct snd_kcontrol *kcontrol,
> +				struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +	unsigned int sel = ucontrol->value.integer.value[0];
> +
> +	if (sel < ((1 << M98925_SPK_GAIN_WIDTH) - 1)) {
> +		regmap_update_bits(max98925->regmap, MAX98925_R02D_GAIN,
> +			M98925_SPK_GAIN_MASK, sel << M98925_SPK_GAIN_SHIFT);
> +		max98925->spk_gain = sel;

Why is this not just a normal control?  I can't see any reference to
spk_gain elsewhere...  similar things apply to a lot of these controls.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-20  7:47   ` anish
@ 2015-02-21  9:42     ` Mark Brown
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2015-02-21  9:42 UTC (permalink / raw)
  To: anish
  Cc: Linux-ALSA, Tushar Behera, liam.r.girdwood, Maxwell McKinnon,
	Lars-Peter Clausen, Nitin Mittal


[-- Attachment #1.1: Type: text/plain, Size: 454 bytes --]

On Thu, Feb 19, 2015 at 11:47:09PM -0800, anish wrote:

> will sure do it for the next revision. Can i get some comments
> for this?

Please allow a reasonable time for review - at least a week as a bare
minimum, normally longer and obviously larger changes like entire new
drivers can slow things down a bit.  If it's only been a week or two
then unless it's an urgent bugfix a mail chasing is just adding to the
amount of e-mail that needs to be read.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-19  6:49 ` Tushar Behera
@ 2015-02-20  7:47   ` anish
  2015-02-21  9:42     ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: anish @ 2015-02-20  7:47 UTC (permalink / raw)
  To: Tushar Behera
  Cc: Linux-ALSA, Lars-Peter Clausen, liam.r.girdwood,
	Maxwell McKinnon, broonie, Nitin Mittal

On Wed, Feb 18, 2015 at 10:49 PM, Tushar Behera <trblinux@gmail.com> wrote:
> On 02/19/2015 09:39 AM, Anish Kumar wrote:
>> Signed-off-by: Anish Kumar <yesanishhere@gmail.com>
>> ---
> For the revised patches, it is a good idea to add the version number in
> the subject line. You can do that with --subject-prefix flag while
> issuing git-format-patch command.
>
> Also please include changelog in the patch explaining the changes in
> subsequent revisions.

will sure do it for the next revision. Can i get some comments
for this?
>
>>  sound/soc/codecs/Kconfig    |   9 +
>>  sound/soc/codecs/Makefile   |   2 +
>>  sound/soc/codecs/max98925.c | 843 +++++++++++++++++++++++++++++++++++++++++++
>>  sound/soc/codecs/max98925.h | 845 ++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 1699 insertions(+)
>>  create mode 100644 sound/soc/codecs/max98925.c
>>  create mode 100644 sound/soc/codecs/max98925.h
>>
>
> --
> Tushar Behera

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-19  4:09 Anish Kumar
@ 2015-02-19  6:49 ` Tushar Behera
  2015-02-20  7:47   ` anish
  2015-02-24  9:03 ` Mark Brown
  1 sibling, 1 reply; 15+ messages in thread
From: Tushar Behera @ 2015-02-19  6:49 UTC (permalink / raw)
  To: Anish Kumar, broonie, Maxwell.McKinnon, liam.r.girdwood, lars
  Cc: alsa-devel, nitin.mittal

On 02/19/2015 09:39 AM, Anish Kumar wrote:
> Signed-off-by: Anish Kumar <yesanishhere@gmail.com>
> ---
For the revised patches, it is a good idea to add the version number in
the subject line. You can do that with --subject-prefix flag while
issuing git-format-patch command.

Also please include changelog in the patch explaining the changes in
subsequent revisions.

>  sound/soc/codecs/Kconfig    |   9 +
>  sound/soc/codecs/Makefile   |   2 +
>  sound/soc/codecs/max98925.c | 843 +++++++++++++++++++++++++++++++++++++++++++
>  sound/soc/codecs/max98925.h | 845 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 1699 insertions(+)
>  create mode 100644 sound/soc/codecs/max98925.c
>  create mode 100644 sound/soc/codecs/max98925.h
> 

-- 
Tushar Behera

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] ASoC: Add max98925 codec driver
@ 2015-02-19  4:09 Anish Kumar
  2015-02-19  6:49 ` Tushar Behera
  2015-02-24  9:03 ` Mark Brown
  0 siblings, 2 replies; 15+ messages in thread
From: Anish Kumar @ 2015-02-19  4:09 UTC (permalink / raw)
  To: broonie, Maxwell.McKinnon, liam.r.girdwood, lars
  Cc: alsa-devel, nitin.mittal, Anish Kumar

Signed-off-by: Anish Kumar <yesanishhere@gmail.com>
---
 sound/soc/codecs/Kconfig    |   9 +
 sound/soc/codecs/Makefile   |   2 +
 sound/soc/codecs/max98925.c | 843 +++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/max98925.h | 845 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1699 insertions(+)
 create mode 100644 sound/soc/codecs/max98925.c
 create mode 100644 sound/soc/codecs/max98925.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 45b7256..7d9002c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX98088 if I2C
 	select SND_SOC_MAX98090 if I2C
 	select SND_SOC_MAX98095 if I2C
+	select SND_SOC_MAX98925 if I2C
 	select SND_SOC_MAX9850 if I2C
 	select SND_SOC_MAX9768 if I2C
 	select SND_SOC_MAX9877 if I2C
@@ -285,6 +286,14 @@ config SND_SOC_MAX9850
 config SND_SOC_OMAP_HDMI_CODEC
        tristate
 
+config SND_SOC_MAX98925
+       tristate "Support MAX98925 audio codec"
+       depends on I2C
+       help
+       MAX98925 is a high-efficiency mono
+       Class DG audio amplifier. Use this
+       option to enable the codec.
+
 config SND_SOC_PCM3008
        tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 6a3b3c3..d439d47 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -38,6 +38,7 @@ snd-soc-max98088-objs := max98088.o
 snd-soc-max98090-objs := max98090.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
+snd-soc-max98925-objs := max98925.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-omap-hdmi-codec-objs := omap-hdmi.o
@@ -233,6 +234,7 @@ obj-$(CONFIG_SND_SOC_WM8994)	+= snd-soc-wm8994.o
 obj-$(CONFIG_SND_SOC_WM8995)	+= snd-soc-wm8995.o
 obj-$(CONFIG_SND_SOC_WM9081)	+= snd-soc-wm9081.o
 obj-$(CONFIG_SND_SOC_WM9090)	+= snd-soc-wm9090.o
+obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_WM9705)	+= snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c
new file mode 100644
index 0000000..35af23b
--- /dev/null
+++ b/sound/soc/codecs/max98925.c
@@ -0,0 +1,843 @@
+/*
+ * max98925.c -- ALSA SoC Stereo MAX98925 driver
+ * Copyright 2013-15 Maxim Integrated Products
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/regulator/consumer.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "max98925.h"
+
+static const char *const dai_text[] = {
+	"left", "right", "leftright", "leftrightdiv2",
+};
+
+static const char *const hpf_text[] = {
+	"disable", "dc_block", "100Hz",	"200Hz", "400Hz", "800Hz",
+};
+
+static struct reg_default max98925_reg[] = {
+	{ 0x00, 0x00 }, /* Battery Voltage Data */
+	{ 0x01, 0x00 }, /* Boost Voltage Data */
+	{ 0x02, 0x00 }, /* Live Status0 */
+	{ 0x03, 0x00 }, /* Live Status1 */
+	{ 0x04, 0x00 }, /* Live Status2 */
+	{ 0x05, 0x00 }, /* State0 */
+	{ 0x06, 0x00 }, /* State1 */
+	{ 0x07, 0x00 }, /* State2 */
+	{ 0x08, 0x00 }, /* Flag0 */
+	{ 0x09, 0x00 }, /* Flag1 */
+	{ 0x0A, 0x00 }, /* Flag2 */
+	{ 0x0B, 0x00 }, /* IRQ Enable0 */
+	{ 0x0C, 0x00 }, /* IRQ Enable1 */
+	{ 0x0D, 0x00 }, /* IRQ Enable2 */
+	{ 0x0E, 0x00 }, /* IRQ Clear0 */
+	{ 0x0F, 0x00 }, /* IRQ Clear1 */
+	{ 0x10, 0x00 }, /* IRQ Clear2 */
+	{ 0x11, 0xC0 }, /* Map0 */
+	{ 0x12, 0x00 }, /* Map1 */
+	{ 0x13, 0x00 }, /* Map2 */
+	{ 0x14, 0xF0 }, /* Map3 */
+	{ 0x15, 0x00 }, /* Map4 */
+	{ 0x16, 0xAB }, /* Map5 */
+	{ 0x17, 0x89 }, /* Map6 */
+	{ 0x18, 0x00 }, /* Map7 */
+	{ 0x19, 0x00 }, /* Map8 */
+	{ 0x1A, 0x06 }, /* DAI Clock Mode 1 */
+	{ 0x1B, 0xC0 }, /* DAI Clock Mode 2 */
+	{ 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */
+	{ 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */
+	{ 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */
+	{ 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */
+	{ 0x20, 0x50 }, /* Format */
+	{ 0x21, 0x00 }, /* TDM Slot Select */
+	{ 0x22, 0x00 }, /* DOUT Configuration VMON */
+	{ 0x23, 0x00 }, /* DOUT Configuration IMON */
+	{ 0x24, 0x00 }, /* DOUT Configuration VBAT */
+	{ 0x25, 0x00 }, /* DOUT Configuration VBST */
+	{ 0x26, 0x00 }, /* DOUT Configuration FLAG */
+	{ 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */
+	{ 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */
+	{ 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */
+	{ 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */
+	{ 0x2B, 0x02 }, /* DOUT Drive Strength */
+	{ 0x2C, 0x90 }, /* Filters */
+	{ 0x2D, 0x00 }, /* Gain */
+	{ 0x2E, 0x02 }, /* Gain Ramping */
+	{ 0x2F, 0x00 }, /* Speaker Amplifier */
+	{ 0x30, 0x0A }, /* Threshold */
+	{ 0x31, 0x00 }, /* ALC Attack */
+	{ 0x32, 0x80 }, /* ALC Atten and Release */
+	{ 0x33, 0x00 }, /* ALC Infinite Hold Release */
+	{ 0x34, 0x92 }, /* ALC Configuration */
+	{ 0x35, 0x01 }, /* Boost Converter */
+	{ 0x36, 0x00 }, /* Block Enable */
+	{ 0x37, 0x00 }, /* Configuration */
+	{ 0x38, 0x00 }, /* Global Enable */
+	{ 0x3A, 0x00 }, /* Boost Limiter */
+	{ 0xFF, 0x50 }, /* Revision ID */
+};
+
+static int max98925_reg_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol, unsigned int reg,
+		unsigned int mask, unsigned int shift)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int sel = ucontrol->value.integer.value[0];
+
+	regmap_update_bits(max98925->regmap, reg, mask, sel<<shift);
+	dev_dbg(codec->dev, "%s: register 0x%02X, value 0x%02X\n",
+				__func__, reg, sel);
+	return 0;
+}
+
+static const struct soc_enum max98925_enum[] = {
+	SOC_ENUM_SINGLE(MAX98925_R02D_GAIN, 5, 4, dai_text),
+	SOC_ENUM_SINGLE(MAX98925_R02C_FILTERS, 0, 6, hpf_text),
+};
+
+static const struct snd_kcontrol_new max98925_dai_sel =
+	SOC_DAPM_ENUM("Route", max98925_enum[0]);
+
+static const struct snd_kcontrol_new max98925_hpf_sel =
+	SOC_DAPM_ENUM("Route", max98925_enum[1]);
+
+static int max98925_dac_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	regmap_update_bits(max98925->regmap,
+		MAX98925_R036_BLOCK_ENABLE,
+		M98925_BST_EN_MASK |
+		M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
+		M98925_BST_EN_MASK |
+		M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
+	regmap_write(max98925->regmap,
+	MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget max98925_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_MUX("DAI_IN_MUX MUX", SND_SOC_NOPM, 0, 0,
+				&max98925_dai_sel),
+	SND_SOC_DAPM_MUX("R02C_FILTER MUX", SND_SOC_NOPM, 0, 0,
+				&max98925_hpf_sel),
+	SND_SOC_DAPM_DAC_E("amp_enable", NULL,
+			MAX98925_R036_BLOCK_ENABLE,
+			M98925_SPK_EN_SHIFT, 0,
+			max98925_dac_event, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_OUTPUT("BE_OUT"),
+};
+
+static const struct snd_soc_dapm_route max98925_audio_map[] = {
+	{"DAI_IN_MUX MUX", "left", "DAI_OUT"},
+	{"DAI_IN_MUX MUX", "right", "DAI_OUT"},
+	{"DAI_IN_MUX MUX", "leftright", "DAI_OUT"},
+	{"DAI_IN_MUX MUX", "leftrightdiv2", "DAI_OUT"},
+	{"R02C_FILTER MUX", "disable", "DAI_IN_MUX MUX"},
+	{"R02C_FILTER MUX", "dc_block", "DAI_IN_MUX MUX"},
+	{"R02C_FILTER MUX", "100Hz", "DAI_IN_MUX MUX"},
+	{"R02C_FILTER MUX", "200Hz", "DAI_IN_MUX MUX"},
+	{"R02C_FILTER MUX", "400Hz", "DAI_IN_MUX MUX"},
+	{"R02C_FILTER MUX", "800Hz", "DAI_IN_MUX MUX"},
+	{"amp_enable", NULL, "R02C_FILTER MUX"},
+	{"BE_OUT", NULL, "amp_enable"},
+};
+
+static bool max98925_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_R000_VBAT_DATA:
+	case MAX98925_R001_VBST_DATA:
+	case MAX98925_R002_LIVE_STATUS0:
+	case MAX98925_R003_LIVE_STATUS1:
+	case MAX98925_R004_LIVE_STATUS2:
+	case MAX98925_R005_STATE0:
+	case MAX98925_R006_STATE1:
+	case MAX98925_R007_STATE2:
+	case MAX98925_R008_FLAG0:
+	case MAX98925_R009_FLAG1:
+	case MAX98925_R00A_FLAG2:
+	case MAX98925_R0FF_VERSION:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max98925_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_R00E_IRQ_CLEAR0:
+	case MAX98925_R00F_IRQ_CLEAR1:
+	case MAX98925_R010_IRQ_CLEAR2:
+	case MAX98925_R033_ALC_HOLD_RLS:
+		return false;
+	default:
+		return true;
+	}
+}
+
+DECLARE_TLV_DB_SCALE(max98925_spk_tlv, -600, 100, 0);
+
+static int max98925_spk_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = max98925->spk_gain;
+	dev_dbg(codec->dev, "%s: spk_gain setting returned %d\n", __func__,
+				(int) ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int max98925_spk_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int sel = ucontrol->value.integer.value[0];
+
+	if (sel < ((1 << M98925_SPK_GAIN_WIDTH) - 1)) {
+		regmap_update_bits(max98925->regmap, MAX98925_R02D_GAIN,
+			M98925_SPK_GAIN_MASK, sel << M98925_SPK_GAIN_SHIFT);
+		max98925->spk_gain = sel;
+
+		dev_dbg(codec->dev, "%s: spk_gain set to %d\n", __func__, sel);
+	} else {
+		dev_dbg(codec->dev, "%s: valid speaker gain settings: %d to %d\n",
+			__func__, 0,
+			((1 << M98925_SPK_GAIN_WIDTH) - 1));
+	}
+	return 0;
+}
+
+static int max98925_reg_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol, unsigned int reg,
+		unsigned int mask, unsigned int shift)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	int data;
+
+	regmap_read(max98925->regmap, reg, &data);
+	ucontrol->value.integer.value[0] =
+		(data & mask) >> shift;
+	return 0;
+}
+
+static int max98925_spk_ramp_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_RMP_EN_MASK, M98925_SPK_RMP_EN_SHIFT);
+}
+
+static int max98925_spk_ramp_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_RMP_EN_MASK, M98925_SPK_RMP_EN_SHIFT);
+}
+
+static int max98925_spk_zcd_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_ZCD_EN_MASK, M98925_SPK_ZCD_EN_SHIFT);
+}
+
+static int max98925_spk_zcd_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_ZCD_EN_MASK, M98925_SPK_ZCD_EN_SHIFT);
+}
+
+static int max98925_alc_en_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_EN_MASK, M98925_ALC_EN_SHIFT);
+}
+
+static int max98925_alc_en_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_EN_MASK, M98925_ALC_EN_SHIFT);
+}
+
+static int max98925_alc_threshold_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_TH_MASK, M98925_ALC_TH_SHIFT);
+}
+
+static int max98925_alc_threshold_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_TH_MASK, M98925_ALC_TH_SHIFT);
+}
+
+static const char * const max98925_boost_voltage_text[] = {
+	"8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V",
+	"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V",	"6.5V", "6.5V"
+};
+
+static const struct soc_enum max98925_boost_voltage_enum =
+	SOC_ENUM_SINGLE(MAX98925_R037_CONFIGURATION, M98925_BST_VOUT_SHIFT, 15,
+			max98925_boost_voltage_text);
+
+static int max98925_boost_voltage_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R037_CONFIGURATION,
+			M98925_BST_VOUT_MASK, M98925_BST_VOUT_SHIFT);
+}
+
+static int max98925_boost_voltage_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R037_CONFIGURATION,
+			M98925_BST_VOUT_MASK, M98925_BST_VOUT_SHIFT);
+}
+
+static const struct snd_kcontrol_new max98925_snd_controls[] = {
+
+	SOC_SINGLE_EXT_TLV("Speaker Gain", MAX98925_R02D_GAIN,
+		M98925_SPK_GAIN_SHIFT, (1<<M98925_SPK_GAIN_WIDTH)-1, 0,
+		max98925_spk_gain_get, max98925_spk_gain_put, max98925_spk_tlv),
+
+	SOC_SINGLE_EXT("Speaker Ramp", 0, 0, 1, 0,
+		max98925_spk_ramp_get, max98925_spk_ramp_put),
+
+	SOC_SINGLE_EXT("Speaker ZCD", 0, 0, 1, 0,
+		max98925_spk_zcd_get, max98925_spk_zcd_put),
+
+	SOC_SINGLE_EXT("ALC Enable", 0, 0, 1, 0,
+		max98925_alc_en_get, max98925_alc_en_put),
+
+	SOC_SINGLE_EXT("ALC Threshold", 0, 0, (1<<M98925_ALC_TH_WIDTH)-1, 0,
+		max98925_alc_threshold_get, max98925_alc_threshold_put),
+
+	SOC_ENUM_EXT("Boost Output Voltage", max98925_boost_voltage_enum,
+		max98925_boost_voltage_get, max98925_boost_voltage_put),
+};
+
+/* codec sample rate and n/m dividers parameter table */
+static const struct {
+	int rate;
+	int  sr;
+	int divisors[3][2];
+} rate_table[] = {
+	{
+		.rate = 8000,
+		.sr = 0,
+		.divisors = { {1, 375}, {5, 1764}, {1, 384} }
+	},
+	{
+		.rate = 11025,
+		.sr = 1,
+		.divisors = { {147, 40000}, {1, 256}, {147, 40960} }
+	},
+	{
+		.rate = 12000,
+		.sr = 2,
+		.divisors = { {1, 250}, {5, 1176}, {1, 256} }
+	},
+	{
+		.rate = 16000,
+		.sr = 3,
+		.divisors = { {2, 375}, {5, 882}, {1, 192} }
+	},
+	{
+		.rate = 22050,
+		.sr = 4,
+		.divisors = { {147, 20000}, {1, 128}, {147, 20480} }
+	},
+	{
+		.rate = 24000,
+		.sr = 5,
+		.divisors = { {1, 125}, {5, 588}, {1, 128} }
+	},
+	{
+		.rate = 32000,
+		.sr = 6,
+		.divisors = { {4, 375}, {5, 441}, {1, 96} }
+	},
+	{
+		.rate = 44100,
+		.sr = 7,
+		.divisors = { {147, 10000}, {1, 64}, {147, 10240} }
+	},
+	{
+		.rate = 48000,
+		.sr = 8,
+		.divisors = { {2, 125}, {5, 294}, {1, 64} }
+	},
+};
+
+static inline int max98925_rate_value(int rate,
+		int clock, int *value, int *n, int *m)
+{
+	int ret = -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+		if (rate_table[i].rate >= rate) {
+			*value = rate_table[i].sr;
+			*n = rate_table[i].divisors[clock][0];
+			*m = rate_table[i].divisors[clock][1];
+			ret = 0;
+			break;
+		}
+	}
+	pr_debug("%s: sample rate is %d, returning %d\n",
+				__func__, rate_table[i].rate, *value);
+	return ret;
+}
+
+static void max98925_set_sense_data(struct max98925_priv *max98925)
+{
+	/*
+	 * 1. set VMON slots
+	 */
+	regmap_update_bits(max98925->regmap,
+		MAX98925_R022_DOUT_CFG_VMON,
+		M98925_DAI_VMON_EN_MASK, M98925_DAI_VMON_EN_MASK);
+	regmap_update_bits(max98925->regmap,
+		MAX98925_R022_DOUT_CFG_VMON,
+		M98925_DAI_VMON_SLOT_MASK, max98925->v_slot);
+	/*
+	 * 2. set IMON slots
+	 */
+	regmap_update_bits(max98925->regmap,
+		MAX98925_R023_DOUT_CFG_IMON,
+		M98925_DAI_IMON_EN_MASK, M98925_DAI_IMON_EN_MASK);
+	regmap_update_bits(max98925->regmap,
+		MAX98925_R023_DOUT_CFG_IMON,
+		M98925_DAI_IMON_SLOT_MASK, max98925->i_slot);
+}
+
+static void max98925_set_slave(struct max98925_priv *max98925)
+{
+	/*
+	 * 1. set DAI to slave mode
+	 */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, 0);
+	max98925_set_sense_data(max98925);
+}
+
+static void max98925_set_master(struct max98925_priv *max98925)
+{
+	/*
+	 * set left channel DAI to master mode, right channel always slave
+	 */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, M98925_DAI_MAS_MASK);
+}
+
+static int max98925_dai_set_fmt(struct snd_soc_dai *codec_dai,
+				 unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int invert = 0;
+
+	dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		max98925_set_slave(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		max98925_set_master(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+	default:
+		dev_err(codec->dev, "DAI clock mode unsupported");
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		invert = M98925_DAI_WCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert = M98925_DAI_BCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		invert = M98925_DAI_BCI_MASK | M98925_DAI_WCI_MASK;
+		break;
+	default:
+		dev_err(codec->dev, "DAI invert mode unsupported");
+		return -EINVAL;
+	}
+
+	regmap_update_bits(max98925->regmap, MAX98925_R020_FORMAT,
+			M98925_DAI_BCI_MASK | M98925_DAI_BCI_MASK, invert);
+	return 0;
+}
+
+static int max98925_set_clock(struct max98925_priv *max98925,
+		struct snd_pcm_hw_params *params)
+{
+	unsigned int dai_sr = 0;
+	unsigned int clock;
+	unsigned int mdll;
+	unsigned int n;
+	unsigned int m;
+	int rate = params_rate(params);
+
+	/* BCLK/LRCLK ratio calculation */
+	int blr_clk_ratio = params_channels(params) * max98925->ch_size;
+	switch (blr_clk_ratio) {
+	case 32:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_32);
+		break;
+	case 48:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_48);
+		break;
+	case 64:
+		regmap_update_bits(max98925->regmap,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (max98925->sysclk) {
+	case 6000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx16;
+		break;
+	case 11289600:
+		clock = 1;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12288000:
+		clock = 2;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	default:
+		dev_info(max98925->codec->dev, "unsupported sysclk %d\n",
+					max98925->sysclk);
+		return -EINVAL;
+	}
+
+	if (max98925_rate_value(rate, clock, &dai_sr, &n, &m))
+		return -EINVAL;
+
+	/*
+	 * 1. set DAI_SR to correct LRCLK frequency
+	 */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_SR_MASK, dai_sr << M98925_DAI_SR_SHIFT);
+	/*
+	 * 2. set DAI m divider
+	 */
+	regmap_write(max98925->regmap,
+		MAX98925_R01C_DAI_CLK_DIV_M_MSBS, m >> 8);
+	regmap_write(max98925->regmap,
+		MAX98925_R01D_DAI_CLK_DIV_M_LSBS, m & 0xFF);
+	/*
+	 * 3. set DAI n divider
+	 */
+	regmap_write(max98925->regmap,
+		MAX98925_R01E_DAI_CLK_DIV_N_MSBS, n >> 8);
+	regmap_write(max98925->regmap,
+		MAX98925_R01F_DAI_CLK_DIV_N_LSBS, n & 0xFF);
+	/*
+	 * 4. set MDLL
+	 */
+	regmap_update_bits(max98925->regmap,
+			MAX98925_R01A_DAI_CLK_MODE1,
+			M98925_MDLL_MULT_MASK, mdll << M98925_MDLL_MULT_SHIFT);
+	return 0;
+}
+
+static int max98925_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 max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_R020_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_16);
+		max98925->ch_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_R020_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		max98925->ch_size = 32;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		regmap_update_bits(max98925->regmap,
+				MAX98925_R020_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		max98925->ch_size = 32;
+		break;
+	default:
+		pr_err("%s: format unsupported %d",
+				__func__, params_format(params));
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "%s: format supported %d",
+				__func__, params_format(params));
+	return max98925_set_clock(max98925, params);
+}
+
+static int max98925_dai_set_sysclk(struct snd_soc_dai *dai,
+				   int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case 0:
+		/*
+		 * 1. use MCLK for Left channel, right channel always BCLK
+		 */
+		regmap_update_bits(max98925->regmap,
+				MAX98925_R01A_DAI_CLK_MODE1,
+				M98925_DAI_CLK_SOURCE_MASK, 0);
+		break;
+	case 1:
+		/*
+		 * configure dai clock source to BCLK instead of MCLK(default)
+		 */
+		regmap_update_bits(max98925->regmap,
+				MAX98925_R01A_DAI_CLK_MODE1,
+				M98925_DAI_CLK_SOURCE_MASK,
+				M98925_DAI_CLK_SOURCE_MASK);
+		break;
+	default:
+		return -EINVAL;
+	}
+	max98925->sysclk = freq;
+	return 0;
+}
+
+static int max98925_dai_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+	struct max98925_priv *max98925 =
+				snd_soc_codec_get_drvdata(codec_dai->codec);
+	struct snd_soc_codec *codec = codec_dai->codec;
+
+	dev_dbg(codec->dev, "%s: mute %d\n", __func__, mute);
+	if (mute) {
+		regmap_update_bits(max98925->regmap, MAX98925_R02D_GAIN,
+			M98925_SPK_GAIN_MASK, 0x00);
+
+		regmap_update_bits(max98925->regmap,
+			MAX98925_R038_GLOBAL_ENABLE,
+			M98925_EN_MASK, 0x0);
+	}
+	return 0;
+}
+
+#define MAX98925_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops max98925_dai_ops = {
+	.set_sysclk = max98925_dai_set_sysclk,
+	.set_fmt = max98925_dai_set_fmt,
+	.hw_params = max98925_dai_hw_params,
+	.digital_mute = max98925_dai_digital_mute,
+};
+
+static struct snd_soc_dai_driver max98925_dai[] = {
+	{
+		.name = "max98925-aif1",
+		.playback = {
+			.stream_name = "HiFi Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HiFi Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.ops = &max98925_dai_ops,
+	}
+};
+
+static int max98925_probe(struct snd_soc_codec *codec)
+{
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
+	int reg = 0;
+
+	dev_info(codec->dev, "build number %s\n", MAX98925_REVISION);
+
+	max98925->codec = codec;
+	codec->control_data = max98925->regmap;
+	ret = regmap_read(max98925->regmap,
+			MAX98925_R0FF_VERSION, &reg);
+	if ((ret < 0) ||
+		((reg != MAX98925_VERSION) &&
+		(reg != MAX98925_VERSION1))) {
+		dev_err(codec->dev,
+			"device initialization error (%d 0x%02X)\n",
+			ret, reg);
+		goto err_access;
+	}
+	regmap_write(max98925->regmap, MAX98925_R038_GLOBAL_ENABLE, 0x00);
+	/* It's not the default but we need to set DAI_DLY */
+	regmap_write(max98925->regmap,
+			MAX98925_R020_FORMAT, M98925_DAI_DLY_MASK);
+	regmap_write(max98925->regmap, MAX98925_R021_TDM_SLOT_SELECT, 0xC8);
+	regmap_write(max98925->regmap, MAX98925_R027_DOUT_HIZ_CFG1, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_R028_DOUT_HIZ_CFG2, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_R029_DOUT_HIZ_CFG3, 0xFF);
+	regmap_write(max98925->regmap, MAX98925_R02A_DOUT_HIZ_CFG4, 0xF0);
+	regmap_write(max98925->regmap, MAX98925_R02C_FILTERS, 0xD8);
+	regmap_write(max98925->regmap, MAX98925_R034_ALC_CONFIGURATION, 0xF8);
+	regmap_write(max98925->regmap, MAX98925_R037_CONFIGURATION, 0xF0);
+
+	/* Disable ALC muting */
+	regmap_write(max98925->regmap, MAX98925_R03A_BOOST_LIMITER, 0xF8);
+	dev_info(codec->dev, "device version 0x%02X\n", reg);
+err_access:
+	return ret;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98925 = {
+	.probe            = max98925_probe,
+	.controls = max98925_snd_controls,
+	.num_controls = ARRAY_SIZE(max98925_snd_controls),
+	.dapm_routes = max98925_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(max98925_audio_map),
+	.dapm_widgets = max98925_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets),
+};
+
+static struct regmap_config max98925_regmap = {
+	.reg_bits         = 8,
+	.val_bits         = 8,
+	.max_register     = MAX98925_R0FF_VERSION,
+	.reg_defaults     = max98925_reg,
+	.num_reg_defaults = ARRAY_SIZE(max98925_reg),
+	.volatile_reg     = max98925_volatile_register,
+	.readable_reg     = max98925_readable_register,
+	.cache_type       = REGCACHE_RBTREE,
+};
+
+static int max98925_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	int ret = 0;
+	u32 value;
+	struct max98925_priv *max98925;
+
+	dev_info(&i2c->dev, "%s: enter, device '%s'\n", __func__, id->name);
+	max98925 = devm_kzalloc(&i2c->dev,
+			sizeof(*max98925), GFP_KERNEL);
+	if (!max98925)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, max98925);
+	max98925->regmap = devm_regmap_init_i2c(i2c, &max98925_regmap);
+	if (IS_ERR(max98925->regmap)) {
+		ret = PTR_ERR(max98925->regmap);
+		dev_err(&i2c->dev,
+				"Failed to allocate regmap: %d\n", ret);
+		goto err_out;
+	}
+
+	if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
+		if (value > M98925_DAI_VMON_SLOT_1E_1F) {
+			dev_err(&i2c->dev, "vmon slot number is wrong:\n");
+			return -EINVAL;
+		}
+		max98925->v_slot = value;
+	}
+	if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) {
+		if (value > M98925_DAI_IMON_SLOT_1E_1F) {
+			dev_err(&i2c->dev, "imon slot number is wrong:\n");
+			return -EINVAL;
+		}
+		max98925->i_slot = value;
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925,
+			max98925_dai, ARRAY_SIZE(max98925_dai));
+	if (ret < 0)
+		dev_err(&i2c->dev,
+				"Failed to register codec: %d\n", ret);
+err_out:
+	return ret;
+}
+
+static int max98925_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id max98925_i2c_id[] = {
+	{ "max98925", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max98925_i2c_id);
+
+static struct i2c_driver max98925_i2c_driver = {
+	.driver = {
+		.name = "max98925",
+		.owner = THIS_MODULE,
+		.pm = NULL,
+	},
+	.probe  = max98925_i2c_probe,
+	.remove = max98925_i2c_remove,
+	.id_table = max98925_i2c_id,
+};
+
+module_i2c_driver(max98925_i2c_driver);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98925 driver");
+MODULE_AUTHOR("Ralph Birt <rdbirt@gmail.com>, Anish kumar <anish.kumar@maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98925.h b/sound/soc/codecs/max98925.h
new file mode 100644
index 0000000..1842c15
--- /dev/null
+++ b/sound/soc/codecs/max98925.h
@@ -0,0 +1,845 @@
+/*
+ * max98925.h -- MAX98925 ALSA SoC Audio driver
+ *
+ * Copyright 2013-2015 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX98925_H
+#define _MAX98925_H
+
+/* Maximum number of MAX98925 devices in the system this driver can support */
+#define MAX_NUM_MAX98925	2
+#define	MAX98925_VERSION	0x51
+#define	MAX98925_VERSION1	0x80
+
+#define MAX98925_REVISION	"0.00.0333"
+
+/*
+ * MAX98925 Register Definitions
+ */
+#define MAX98925_R000_VBAT_DATA			0x00
+#define MAX98925_R001_VBST_DATA			0x01
+#define MAX98925_R002_LIVE_STATUS0		0x02
+#define MAX98925_R003_LIVE_STATUS1		0x03
+#define MAX98925_R004_LIVE_STATUS2		0x04
+#define MAX98925_R005_STATE0			0x05
+#define MAX98925_R006_STATE1			0x06
+#define MAX98925_R007_STATE2			0x07
+#define MAX98925_R008_FLAG0			0x08
+#define MAX98925_R009_FLAG1			0x09
+#define MAX98925_R00A_FLAG2			0x0A
+#define MAX98925_R00B_IRQ_ENABLE0		0x0B
+#define MAX98925_R00C_IRQ_ENABLE1		0x0C
+#define MAX98925_R00D_IRQ_ENABLE2		0x0D
+#define MAX98925_R00E_IRQ_CLEAR0		0x0E
+#define MAX98925_R00F_IRQ_CLEAR1		0x0F
+#define MAX98925_R010_IRQ_CLEAR2		0x10
+#define MAX98925_R011_MAP0			0x11
+#define MAX98925_R012_MAP1			0x12
+#define MAX98925_R013_MAP2			0x13
+#define MAX98925_R014_MAP3			0x14
+#define MAX98925_R015_MAP4			0x15
+#define MAX98925_R016_MAP5			0x16
+#define MAX98925_R017_MAP6			0x17
+#define MAX98925_R018_MAP7			0x18
+#define MAX98925_R019_MAP8			0x19
+#define MAX98925_R01A_DAI_CLK_MODE1		0x1A
+#define MAX98925_R01B_DAI_CLK_MODE2		0x1B
+#define MAX98925_R01C_DAI_CLK_DIV_M_MSBS	0x1C
+#define MAX98925_R01D_DAI_CLK_DIV_M_LSBS	0x1D
+#define MAX98925_R01E_DAI_CLK_DIV_N_MSBS	0x1E
+#define MAX98925_R01F_DAI_CLK_DIV_N_LSBS	0x1F
+#define MAX98925_R020_FORMAT			0x20
+#define MAX98925_R021_TDM_SLOT_SELECT		0x21
+#define MAX98925_R022_DOUT_CFG_VMON		0x22
+#define MAX98925_R023_DOUT_CFG_IMON		0x23
+#define MAX98925_R024_DOUT_CFG_VBAT		0x24
+#define MAX98925_R025_DOUT_CFG_VBST		0x25
+#define MAX98925_R026_DOUT_CFG_FLAG		0x26
+#define MAX98925_R027_DOUT_HIZ_CFG1		0x27
+#define MAX98925_R028_DOUT_HIZ_CFG2		0x28
+#define MAX98925_R029_DOUT_HIZ_CFG3		0x29
+#define MAX98925_R02A_DOUT_HIZ_CFG4		0x2A
+#define MAX98925_R02B_DOUT_DRV_STRENGTH		0x2B
+#define MAX98925_R02C_FILTERS			0x2C
+#define MAX98925_R02D_GAIN			0x2D
+#define MAX98925_R02E_GAIN_RAMPING		0x2E
+#define MAX98925_R02F_SPK_AMP			0x2F
+#define MAX98925_R030_THRESHOLD			0x30
+#define MAX98925_R031_ALC_ATTACK		0x31
+#define MAX98925_R032_ALC_ATTEN_RLS		0x32
+#define MAX98925_R033_ALC_HOLD_RLS		0x33
+#define MAX98925_R034_ALC_CONFIGURATION		0x34
+#define MAX98925_R035_BOOST_CONVERTER		0x35
+#define MAX98925_R036_BLOCK_ENABLE		0x36
+#define MAX98925_R037_CONFIGURATION		0x37
+#define MAX98925_R038_GLOBAL_ENABLE		0x38
+#define MAX98925_R03A_BOOST_LIMITER		0x3A
+#define MAX98925_R0FF_VERSION			0xFF
+
+#define MAX98925_REG_CNT               (MAX98925_R03A_BOOST_LIMITER+1)
+
+/* MAX98925 Register Bit Fields */
+
+/* MAX98925_R002_LIVE_STATUS0 */
+#define M98925_THERMWARN_STATUS_MASK			(1<<3)
+#define M98925_THERMWARN_STATUS_SHIFT			3
+#define M98925_THERMWARN_STATUS_WIDTH			1
+#define M98925_THERMSHDN_STATUS_MASK			(1<<1)
+#define M98925_THERMSHDN_STATUS_SHIFT			1
+#define M98925_THERMSHDN_STATUS_WIDTH			1
+
+/* MAX98925_R003_LIVE_STATUS1 */
+#define M98925_SPKCURNT_STATUS_MASK				(1<<5)
+#define M98925_SPKCURNT_STATUS_SHIFT			5
+#define M98925_SPKCURNT_STATUS_WIDTH			1
+#define M98925_WATCHFAIL_STATUS_MASK			(1<<4)
+#define M98925_WATCHFAIL_STATUS_SHIFT			4
+#define M98925_WATCHFAIL_STATUS_WIDTH			1
+#define M98925_ALCINFH_STATUS_MASK				(1<<3)
+#define M98925_ALCINFH_STATUS_SHIFT				3
+#define M98925_ALCINFH_STATUS_WIDTH				1
+#define M98925_ALCACT_STATUS_MASK				(1<<2)
+#define M98925_ALCACT_STATUS_SHIFT				2
+#define M98925_ALCACT_STATUS_WIDTH				1
+#define M98925_ALCMUT_STATUS_MASK				(1<<1)
+#define M98925_ALCMUT_STATUS_SHIFT				1
+#define M98925_ALCMUT_STATUS_WIDTH				1
+#define M98925_ACLP_STATUS_MASK					(1<<0)
+#define M98925_ACLP_STATUS_SHIFT				0
+#define M98925_ACLP_STATUS_WIDTH				1
+
+/* MAX98925_R004_LIVE_STATUS2 */
+#define M98925_SLOTOVRN_STATUS_MASK				(1<<6)
+#define M98925_SLOTOVRN_STATUS_SHIFT			6
+#define M98925_SLOTOVRN_STATUS_WIDTH			1
+#define M98925_INVALSLOT_STATUS_MASK			(1<<5)
+#define M98925_INVALSLOT_STATUS_SHIFT			5
+#define M98925_INVALSLOT_STATUS_WIDTH			1
+#define M98925_SLOTCNFLT_STATUS_MASK			(1<<4)
+#define M98925_SLOTCNFLT_STATUS_SHIFT			4
+#define M98925_SLOTCNFLT_STATUS_WIDTH			1
+#define M98925_VBSTOVFL_STATUS_MASK				(1<<3)
+#define M98925_VBSTOVFL_STATUS_SHIFT			3
+#define M98925_VBSTOVFL_STATUS_WIDTH			1
+#define M98925_VBATOVFL_STATUS_MASK				(1<<2)
+#define M98925_VBATOVFL_STATUS_SHIFT			2
+#define M98925_VBATOVFL_STATUS_WIDTH			1
+#define M98925_IMONOVFL_STATUS_MASK				(1<<1)
+#define M98925_IMONOVFL_STATUS_SHIFT			1
+#define M98925_IMONOVFL_STATUS_WIDTH			1
+#define M98925_VMONOVFL_STATUS_MASK				(1<<0)
+#define M98925_VMONOVFL_STATUS_SHIFT			0
+#define M98925_VMONOVFL_STATUS_WIDTH			1
+
+/* MAX98925_R005_STATE0 */
+#define M98925_THERMWARN_END_STATE_MASK			(1<<3)
+#define M98925_THERMWARN_END_STATE_SHIFT		3
+#define M98925_THERMWARN_END_STATE_WIDTH		1
+#define M98925_THERMWARN_BGN_STATE_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_STATE_SHIFT		1
+#define M98925_THERMWARN_BGN_STATE_WIDTH		1
+#define M98925_THERMSHDN_END_STATE_MASK			(1<<1)
+#define M98925_THERMSHDN_END_STATE_SHIFT		1
+#define M98925_THERMSHDN_END_STATE_WIDTH		1
+#define M98925_THERMSHDN_BGN_STATE_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_STATE_SHIFT		0
+#define M98925_THERMSHDN_BGN_STATE_WIDTH		1
+
+/* MAX98925_R006_STATE1 */
+#define M98925_SPRCURNT_STATE_MASK				(1<<5)
+#define M98925_SPRCURNT_STATE_SHIFT				5
+#define M98925_SPRCURNT_STATE_WIDTH				1
+#define M98925_WATCHFAIL_STATE_MASK				(1<<4)
+#define M98925_WATCHFAIL_STATE_SHIFT			4
+#define M98925_WATCHFAIL_STATE_WIDTH			1
+#define M98925_ALCINFH_STATE_MASK				(1<<3)
+#define M98925_ALCINFH_STATE_SHIFT				3
+#define M98925_ALCINFH_STATE_WIDTH				1
+#define M98925_ALCACT_STATE_MASK				(1<<2)
+#define M98925_ALCACT_STATE_SHIFT				2
+#define M98925_ALCACT_STATE_WIDTH				1
+#define M98925_ALCMUT_STATE_MASK				(1<<1)
+#define M98925_ALCMUT_STATE_SHIFT				1
+#define M98925_ALCMUT_STATE_WIDTH				1
+#define M98925_ALCP_STATE_MASK					(1<<0)
+#define M98925_ALCP_STATE_SHIFT					0
+#define M98925_ALCP_STATE_WIDTH					1
+
+/* MAX98925_R007_STATE2 */
+#define M98925_SLOTOVRN_STATE_MASK				(1<<6)
+#define M98925_SLOTOVRN_STATE_SHIFT				6
+#define M98925_SLOTOVRN_STATE_WIDTH				1
+#define M98925_INVALSLOT_STATE_MASK				(1<<5)
+#define M98925_INVALSLOT_STATE_SHIFT			5
+#define M98925_INVALSLOT_STATE_WIDTH			1
+#define M98925_SLOTCNFLT_STATE_MASK				(1<<4)
+#define M98925_SLOTCNFLT_STATE_SHIFT			4
+#define M98925_SLOTCNFLT_STATE_WIDTH			1
+#define M98925_VBSTOVFL_STATE_MASK				(1<<3)
+#define M98925_VBSTOVFL_STATE_SHIFT				3
+#define M98925_VBSTOVFL_STATE_WIDTH				1
+#define M98925_VBATOVFL_STATE_MASK				(1<<2)
+#define M98925_VBATOVFL_STATE_SHIFT				2
+#define M98925_VBATOVFL_STATE_WIDTH				1
+#define M98925_IMONOVFL_STATE_MASK				(1<<1)
+#define M98925_IMONOVFL_STATE_SHIFT				1
+#define M98925_IMONOVFL_STATE_WIDTH				1
+#define M98925_VMONOVFL_STATE_MASK				(1<<0)
+#define M98925_VMONOVFL_STATE_SHIFT				0
+#define M98925_VMONOVFL_STATE_WIDTH				1
+
+/* MAX98925_R008_FLAG0 */
+#define M98925_THERMWARN_END_FLAG_MASK			(1<<3)
+#define M98925_THERMWARN_END_FLAG_SHIFT			3
+#define M98925_THERMWARN_END_FLAG_WIDTH			1
+#define M98925_THERMWARN_BGN_FLAG_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_FLAG_SHIFT			2
+#define M98925_THERMWARN_BGN_FLAG_WIDTH			1
+#define M98925_THERMSHDN_END_FLAG_MASK			(1<<1)
+#define M98925_THERMSHDN_END_FLAG_SHIFT			1
+#define M98925_THERMSHDN_END_FLAG_WIDTH			1
+#define M98925_THERMSHDN_BGN_FLAG_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_FLAG_SHIFT			0
+#define M98925_THERMSHDN_BGN_FLAG_WIDTH			1
+
+/* MAX98925_R009_FLAG1 */
+#define M98925_SPKCURNT_FLAG_MASK				(1<<5)
+#define M98925_SPKCURNT_FLAG_SHIFT				5
+#define M98925_SPKCURNT_FLAG_WIDTH				1
+#define M98925_WATCHFAIL_FLAG_MASK				(1<<4)
+#define M98925_WATCHFAIL_FLAG_SHIFT				4
+#define M98925_WATCHFAIL_FLAG_WIDTH				1
+#define M98925_ALCINFH_FLAG_MASK				(1<<3)
+#define M98925_ALCINFH_FLAG_SHIFT				3
+#define M98925_ALCINFH_FLAG_WIDTH				1
+#define M98925_ALCACT_FLAG_MASK					(1<<2)
+#define M98925_ALCACT_FLAG_SHIFT				2
+#define M98925_ALCACT_FLAG_WIDTH				1
+#define M98925_ALCMUT_FLAG_MASK					(1<<1)
+#define M98925_ALCMUT_FLAG_SHIFT				1
+#define M98925_ALCMUT_FLAG_WIDTH				1
+#define M98925_ALCP_FLAG_MASK					(1<<0)
+#define M98925_ALCP_FLAG_SHIFT					0
+#define M98925_ALCP_FLAG_WIDTH					1
+
+/* MAX98925_R00A_FLAG2 */
+#define M98925_SLOTOVRN_FLAG_MASK				(1<<6)
+#define M98925_SLOTOVRN_FLAG_SHIFT				6
+#define M98925_SLOTOVRN_FLAG_WIDTH				1
+#define M98925_INVALSLOT_FLAG_MASK				(1<<5)
+#define M98925_INVALSLOT_FLAG_SHIFT				5
+#define M98925_INVALSLOT_FLAG_WIDTH				1
+#define M98925_SLOTCNFLT_FLAG_MASK				(1<<4)
+#define M98925_SLOTCNFLT_FLAG_SHIFT				4
+#define M98925_SLOTCNFLT_FLAG_WIDTH				1
+#define M98925_VBSTOVFL_FLAG_MASK				(1<<3)
+#define M98925_VBSTOVFL_FLAG_SHIFT				3
+#define M98925_VBSTOVFL_FLAG_WIDTH				1
+#define M98925_VBATOVFL_FLAG_MASK				(1<<2)
+#define M98925_VBATOVFL_FLAG_SHIFT				2
+#define M98925_VBATOVFL_FLAG_WIDTH				1
+#define M98925_IMONOVFL_FLAG_MASK				(1<<1)
+#define M98925_IMONOVFL_FLAG_SHIFT				1
+#define M98925_IMONOVFL_FLAG_WIDTH				1
+#define M98925_VMONOVFL_FLAG_MASK				(1<<0)
+#define M98925_VMONOVFL_FLAG_SHIFT				0
+#define M98925_VMONOVFL_FLAG_WIDTH				1
+
+/* MAX98925_R00B_IRQ_ENABLE0 */
+#define M98925_THERMWARN_END_EN_MASK			(1<<3)
+#define M98925_THERMWARN_END_EN_SHIFT			3
+#define M98925_THERMWARN_END_EN_WIDTH			1
+#define M98925_THERMWARN_BGN_EN_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_EN_SHIFT			2
+#define M98925_THERMWARN_BGN_EN_WIDTH			1
+#define M98925_THERMSHDN_END_EN_MASK			(1<<1)
+#define M98925_THERMSHDN_END_EN_SHIFT			1
+#define M98925_THERMSHDN_END_EN_WIDTH			1
+#define M98925_THERMSHDN_BGN_EN_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_EN_SHIFT			0
+#define M98925_THERMSHDN_BGN_EN_WIDTH			1
+
+/* MAX98925_R00C_IRQ_ENABLE1 */
+#define M98925_SPKCURNT_EN_MASK					(1<<5)
+#define M98925_SPKCURNT_EN_SHIFT				5
+#define M98925_SPKCURNT_EN_WIDTH				1
+#define M98925_WATCHFAIL_EN_MASK				(1<<4)
+#define M98925_WATCHFAIL_EN_SHIFT				4
+#define M98925_WATCHFAIL_EN_WIDTH				1
+#define M98925_ALCINFH_EN_MASK					(1<<3)
+#define M98925_ALCINFH_EN_SHIFT					3
+#define M98925_ALCINFH_EN_WIDTH					1
+#define M98925_ALCACT_EN_MASK					(1<<2)
+#define M98925_ALCACT_EN_SHIFT					2
+#define M98925_ALCACT_EN_WIDTH					1
+#define M98925_ALCMUT_EN_MASK					(1<<1)
+#define M98925_ALCMUT_EN_SHIFT					1
+#define M98925_ALCMUT_EN_WIDTH					1
+#define M98925_ALCP_EN_MASK						(1<<0)
+#define M98925_ALCP_EN_SHIFT					0
+#define M98925_ALCP_EN_WIDTH					1
+
+/* MAX98925_R00D_IRQ_ENABLE2 */
+#define M98925_SLOTOVRN_EN_MASK					(1<<6)
+#define M98925_SLOTOVRN_EN_SHIFT				6
+#define M98925_SLOTOVRN_EN_WIDTH				1
+#define M98925_INVALSLOT_EN_MASK				(1<<5)
+#define M98925_INVALSLOT_EN_SHIFT				5
+#define M98925_INVALSLOT_EN_WIDTH				1
+#define M98925_SLOTCNFLT_EN_MASK				(1<<4)
+#define M98925_SLOTCNFLT_EN_SHIFT				4
+#define M98925_SLOTCNFLT_EN_WIDTH				1
+#define M98925_VBSTOVFL_EN_MASK					(1<<3)
+#define M98925_VBSTOVFL_EN_SHIFT				3
+#define M98925_VBSTOVFL_EN_WIDTH				1
+#define M98925_VBATOVFL_EN_MASK					(1<<2)
+#define M98925_VBATOVFL_EN_SHIFT				2
+#define M98925_VBATOVFL_EN_WIDTH				1
+#define M98925_IMONOVFL_EN_MASK					(1<<1)
+#define M98925_IMONOVFL_EN_SHIFT				1
+#define M98925_IMONOVFL_EN_WIDTH				1
+#define M98925_VMONOVFL_EN_MASK					(1<<0)
+#define M98925_VMONOVFL_EN_SHIFT				0
+#define M98925_VMONOVFL_EN_WIDTH				1
+
+/* MAX98925_R00E_IRQ_CLEAR0 */
+#define M98925_THERMWARN_END_CLR_MASK			(1<<3)
+#define M98925_THERMWARN_END_CLR_SHIFT			3
+#define M98925_THERMWARN_END_CLR_WIDTH			1
+#define M98925_THERMWARN_BGN_CLR_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_CLR_SHIFT			2
+#define M98925_THERMWARN_BGN_CLR_WIDTH			1
+#define M98925_THERMSHDN_END_CLR_MASK			(1<<1)
+#define M98925_THERMSHDN_END_CLR_SHIFT			1
+#define M98925_THERMSHDN_END_CLR_WIDTH			1
+#define M98925_THERMSHDN_BGN_CLR_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_CLR_SHIFT			0
+#define M98925_THERMSHDN_BGN_CLR_WIDTH			1
+
+/* MAX98925_R00F_IRQ_CLEAR1 */
+#define M98925_SPKCURNT_CLR_MASK				(1<<5)
+#define M98925_SPKCURNT_CLR_SHIFT				5
+#define M98925_SPKCURNT_CLR_WIDTH				1
+#define M98925_WATCHFAIL_CLR_MASK				(1<<4)
+#define M98925_WATCHFAIL_CLR_SHIFT				4
+#define M98925_WATCHFAIL_CLR_WIDTH				1
+#define M98925_ALCINFH_CLR_MASK					(1<<3)
+#define M98925_ALCINFH_CLR_SHIFT				3
+#define M98925_ALCINFH_CLR_WIDTH				1
+#define M98925_ALCACT_CLR_MASK					(1<<2)
+#define M98925_ALCACT_CLR_SHIFT					2
+#define M98925_ALCACT_CLR_WIDTH					1
+#define M98925_ALCMUT_CLR_MASK					(1<<1)
+#define M98925_ALCMUT_CLR_SHIFT					1
+#define M98925_ALCMUT_CLR_WIDTH					1
+#define M98925_ALCP_CLR_MASK					(1<<0)
+#define M98925_ALCP_CLR_SHIFT					0
+#define M98925_ALCP_CLR_WIDTH					1
+
+/* MAX98925_R010_IRQ_CLEAR2 */
+#define M98925_SLOTOVRN_CLR_MASK				(1<<6)
+#define M98925_SLOTOVRN_CLR_SHIFT				6
+#define M98925_SLOTOVRN_CLR_WIDTH				1
+#define M98925_INVALSLOT_CLR_MASK				(1<<5)
+#define M98925_INVALSLOT_CLR_SHIFT				5
+#define M98925_INVALSLOT_CLR_WIDTH				1
+#define M98925_SLOTCNFLT_CLR_MASK				(1<<4)
+#define M98925_SLOTCNFLT_CLR_SHIFT				4
+#define M98925_SLOTCNFLT_CLR_WIDTH				1
+#define M98925_VBSTOVFL_CLR_MASK				(1<<3)
+#define M98925_VBSTOVFL_CLR_SHIFT				3
+#define M98925_VBSTOVFL_CLR_WIDTH				1
+#define M98925_VBATOVFL_CLR_MASK				(1<<2)
+#define M98925_VBATOVFL_CLR_SHIFT				2
+#define M98925_VBATOVFL_CLR_WIDTH				1
+#define M98925_IMONOVFL_CLR_MASK				(1<<1)
+#define M98925_IMONOVFL_CLR_SHIFT				1
+#define M98925_IMONOVFL_CLR_WIDTH				1
+#define M98925_VMONOVFL_CLR_MASK				(1<<0)
+#define M98925_VMONOVFL_CLR_SHIFT				0
+#define M98925_VMONOVFL_CLR_WIDTH				1
+
+/* MAX98925_R011_MAP0 */
+#define M98925_ER_THERMWARN_EN_MASK				(1<<7)
+#define M98925_ER_THERMWARN_EN_SHIFT			7
+#define M98925_ER_THERMWARN_EN_WIDTH			1
+#define M98925_ER_THERMWARN_MAP_MASK			(0x07<<4)
+#define M98925_ER_THERMWARN_MAP_SHIFT			4
+#define M98925_ER_THERMWARN_MAP_WIDTH			3
+
+/* MAX98925_R012_MAP1 */
+#define M98925_ER_ALCMUT_EN_MASK				(1<<7)
+#define M98925_ER_ALCMUT_EN_SHIFT				7
+#define M98925_ER_ALCMUT_EN_WIDTH				1
+#define M98925_ER_ALCMUT_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCMUT_MAP_SHIFT				4
+#define M98925_ER_ALCMUT_MAP_WIDTH				3
+#define M98925_ER_ALCP_EN_MASK					(1<<3)
+#define M98925_ER_ALCP_EN_SHIFT					3
+#define M98925_ER_ALCP_EN_WIDTH					1
+#define M98925_ER_ALCP_MAP_MASK					(0x07<<0)
+#define M98925_ER_ALCP_MAP_SHIFT				0
+#define M98925_ER_ALCP_MAP_WIDTH				3
+
+/* MAX98925_R013_MAP2 */
+#define M98925_ER_ALCINFH_EN_MASK				(1<<7)
+#define M98925_ER_ALCINFH_EN_SHIFT				7
+#define M98925_ER_ALCINFH_EN_WIDTH				1
+#define M98925_ER_ALCINFH_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCINFH_MAP_SHIFT				4
+#define M98925_ER_ALCINFH_MAP_WIDTH				3
+#define M98925_ER_ALCACT_EN_MASK				(1<<3)
+#define M98925_ER_ALCACT_EN_SHIFT				3
+#define M98925_ER_ALCACT_EN_WIDTH				1
+#define M98925_ER_ALCACT_MAP_MASK				(0x07<<0)
+#define M98925_ER_ALCACT_MAP_SHIFT				0
+#define M98925_ER_ALCACT_MAP_WIDTH				3
+
+/* MAX98925_R014_MAP3 */
+#define M98925_ER_SPKCURNT_EN_MASK				(1<<7)
+#define M98925_ER_SPKCURNT_EN_SHIFT				7
+#define M98925_ER_SPKCURNT_EN_WIDTH				1
+#define M98925_ER_SPKCURNT_MAP_MASK				(0x07<<4)
+#define M98925_ER_SPKCURNT_MAP_SHIFT			4
+#define M98925_ER_SPKCURNT_MAP_WIDTH			3
+
+/* MAX98925_R015_MAP4 */
+/* RESERVED */
+
+/* MAX98925_R016_MAP5 */
+#define M98925_ER_IMONOVFL_EN_MASK				(1<<7)
+#define M98925_ER_IMONOVFL_EN_SHIFT				7
+#define M98925_ER_IMONOVFL_EN_WIDTH				1
+#define M98925_ER_IMONOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_IMONOVFL_MAP_SHIFT			4
+#define M98925_ER_IMONOVFL_MAP_WIDTH			3
+#define M98925_ER_VMONOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VMONOVFL_EN_SHIFT				3
+#define M98925_ER_VMONOVFL_EN_WIDTH				1
+#define M98925_ER_VMONOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VMONOVFL_MAP_SHIFT			0
+#define M98925_ER_VMONOVFL_MAP_WIDTH			3
+
+/* MAX98925_R017_MAP6 */
+#define M98925_ER_VBSTOVFL_EN_MASK				(1<<7)
+#define M98925_ER_VBSTOVFL_EN_SHIFT				7
+#define M98925_ER_VBSTOVFL_EN_WIDTH				1
+#define M98925_ER_VBSTOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_VBSTOVFL_MAP_SHIFT			4
+#define M98925_ER_VBSTOVFL_MAP_WIDTH			3
+#define M98925_ER_VBATOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VBATOVFL_EN_SHIFT				3
+#define M98925_ER_VBATOVFL_EN_WIDTH				1
+#define M98925_ER_VBATOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VBATOVFL_MAP_SHIFT			0
+#define M98925_ER_VBATOVFL_MAP_WIDTH			3
+
+/* MAX98925_R018_MAP7 */
+#define M98925_ER_INVALSLOT_EN_MASK				(1<<7)
+#define M98925_ER_INVALSLOT_EN_SHIFT			7
+#define M98925_ER_INVALSLOT_EN_WIDTH			1
+#define M98925_ER_INVALSLOT_MAP_MASK			(0x07<<4)
+#define M98925_ER_INVALSLOT_MAP_SHIFT			4
+#define M98925_ER_INVALSLOT_MAP_WIDTH			3
+#define M98925_ER_SLOTCNFLT_EN_MASK				(1<<3)
+#define M98925_ER_SLOTCNFLT_EN_SHIFT			3
+#define M98925_ER_SLOTCNFLT_EN_WIDTH			1
+#define M98925_ER_SLOTCNFLT_MAP_MASK			(0x07<<0)
+#define M98925_ER_SLOTCNFLT_MAP_SHIFT			0
+#define M98925_ER_SLOTCNFLT_MAP_WIDTH			3
+
+/* MAX98925_R019_MAP8 */
+#define M98925_ER_SLOTOVRN_EN_MASK	(1<<3)
+#define M98925_ER_SLOTOVRN_EN_SHIFT	3
+#define M98925_ER_SLOTOVRN_EN_WIDTH	1
+#define M98925_ER_SLOTOVRN_MAP_MASK	(0x07<<0)
+#define M98925_ER_SLOTOVRN_MAP_SHIFT	0
+#define M98925_ER_SLOTOVRN_MAP_WIDTH	3
+
+/* MAX98925_R01A_DAI_CLK_MODE1 */
+#define M98925_DAI_CLK_SOURCE_MASK	(1<<6)
+#define M98925_DAI_CLK_SOURCE_SHIFT	6
+#define M98925_DAI_CLK_SOURCE_WIDTH	1
+#define M98925_MDLL_MULT_MASK		(0x0F<<0)
+#define M98925_MDLL_MULT_SHIFT		0
+#define M98925_MDLL_MULT_WIDTH		4
+
+#define M98925_MDLL_MULT_MCLKx8		6
+#define M98925_MDLL_MULT_MCLKx16	8
+
+/* MAX98925_R01B_DAI_CLK_MODE2 */
+#define M98925_DAI_SR_MASK			(0x0F<<4)
+#define M98925_DAI_SR_SHIFT			4
+#define M98925_DAI_SR_WIDTH			4
+#define M98925_DAI_MAS_MASK			(1<<3)
+#define M98925_DAI_MAS_SHIFT			3
+#define M98925_DAI_MAS_WIDTH			1
+#define M98925_DAI_BSEL_MASK			(0x07<<0)
+#define M98925_DAI_BSEL_SHIFT			0
+#define M98925_DAI_BSEL_WIDTH			3
+
+#define M98925_DAI_BSEL_32 (0 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_48 (1 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_64 (2 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_256 (6 << M98925_DAI_BSEL_SHIFT)
+
+/* MAX98925_R01C_DAI_CLK_DIV_M_MSBS */
+#define M98925_DAI_M_MSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_MSBS_SHIFT					0
+#define M98925_DAI_M_MSBS_WIDTH					8
+
+/* MAX98925_R01D_DAI_CLK_DIV_M_LSBS */
+#define M98925_DAI_M_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_LSBS_SHIFT					0
+#define M98925_DAI_M_LSBS_WIDTH					8
+
+/* MAX98925_R01E_DAI_CLK_DIV_N_MSBS */
+#define M98925_DAI_N_MSBS_MASK					(0x7F<<0)
+#define M98925_DAI_N_MSBS_SHIFT					0
+#define M98925_DAI_N_MSBS_WIDTH					7
+
+/* MAX98925_R01F_DAI_CLK_DIV_N_LSBS */
+#define M98925_DAI_N_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_N_LSBS_SHIFT					0
+#define M98925_DAI_N_LSBS_WIDTH					8
+
+/* MAX98925_R020_FORMAT */
+#define M98925_DAI_CHANSZ_MASK					(0x03<<6)
+#define M98925_DAI_CHANSZ_SHIFT					6
+#define M98925_DAI_CHANSZ_WIDTH					2
+#define M98925_DAI_EXTBCLK_HIZ_MASK				(1<<4)
+#define M98925_DAI_EXTBCLK_HIZ_SHIFT			4
+#define M98925_DAI_EXTBCLK_HIZ_WIDTH			1
+#define M98925_DAI_WCI_MASK						(1<<3)
+#define M98925_DAI_WCI_SHIFT					3
+#define M98925_DAI_WCI_WIDTH					1
+#define M98925_DAI_BCI_MASK						(1<<2)
+#define M98925_DAI_BCI_SHIFT					2
+#define M98925_DAI_BCI_WIDTH					1
+#define M98925_DAI_DLY_MASK						(1<<1)
+#define M98925_DAI_DLY_SHIFT					1
+#define M98925_DAI_DLY_WIDTH					1
+#define M98925_DAI_TDM_MASK						(1<<0)
+#define M98925_DAI_TDM_SHIFT					0
+#define M98925_DAI_TDM_WIDTH					1
+
+#define M98925_DAI_CHANSZ_16 (1 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_24 (2 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_32 (3 << M98925_DAI_CHANSZ_SHIFT)
+
+/* MAX98925_R021_TDM_SLOT_SELECT */
+#define M98925_DAI_DO_EN_MASK					(1<<7)
+#define M98925_DAI_DO_EN_SHIFT					7
+#define M98925_DAI_DO_EN_WIDTH					1
+#define M98925_DAI_DIN_EN_MASK					(1<<6)
+#define M98925_DAI_DIN_EN_SHIFT					6
+#define M98925_DAI_DIN_EN_WIDTH					1
+#define M98925_DAI_INR_SOURCE_MASK				(0x07<<3)
+#define M98925_DAI_INR_SOURCE_SHIFT				3
+#define M98925_DAI_INR_SOURCE_WIDTH				3
+#define M98925_DAI_INL_SOURCE_MASK				(0x07<<0)
+#define M98925_DAI_INL_SOURCE_SHIFT				0
+#define M98925_DAI_INL_SOURCE_WIDTH				3
+
+/* MAX98925_R022_DOUT_CFG_VMON */
+#define M98925_DAI_VMON_EN_MASK					(1<<5)
+#define M98925_DAI_VMON_EN_SHIFT				5
+#define M98925_DAI_VMON_EN_WIDTH				1
+#define M98925_DAI_VMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VMON_SLOT_SHIFT				0
+#define M98925_DAI_VMON_SLOT_WIDTH				5
+
+#define M98925_DAI_VMON_SLOT_00_01 (0 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_01_02 (1 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_02_03 (2 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_03_04 (3 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_04_05 (4 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_05_06 (5 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_06_07 (6 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_07_08 (7 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_08_09 (8 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_09_0A (9 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0A_0B (10 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0B_0C (11 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0C_0D (12 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0D_0E (13 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0E_0F (14 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0F_10 (15 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_10_11 (16 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_11_12 (17 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_12_13 (18 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_13_14 (19 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_14_15 (20 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_15_16 (21 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_16_17 (22 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_17_18 (23 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_18_19 (24 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_19_1A (25 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1A_1B (26 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1B_1C (27 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1C_1D (28 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1D_1E (29 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1E_1F (30 << M98925_DAI_VMON_SLOT_SHIFT)
+
+/* MAX98925_R023_DOUT_CFG_IMON */
+#define M98925_DAI_IMON_EN_MASK					(1<<5)
+#define M98925_DAI_IMON_EN_SHIFT				5
+#define M98925_DAI_IMON_EN_WIDTH				1
+#define M98925_DAI_IMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_IMON_SLOT_SHIFT				0
+#define M98925_DAI_IMON_SLOT_WIDTH				5
+
+#define M98925_DAI_IMON_SLOT_00_01 (0 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_01_02 (1 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_02_03 (2 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_03_04 (3 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_04_05 (4 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_05_06 (5 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_06_07 (6 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_07_08 (7 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_08_09 (8 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_09_0A (9 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0A_0B (10 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0B_0C (11 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0C_0D (12 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0D_0E (13 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0E_0F (14 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0F_10 (15 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_10_11 (16 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_11_12 (17 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_12_13 (18 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_13_14 (19 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_14_15 (20 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_15_16 (21 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_16_17 (22 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_17_18 (23 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_18_19 (24 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_19_1A (25 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1A_1B (26 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1B_1C (27 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1C_1D (28 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1D_1E (29 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1E_1F (30 << M98925_DAI_IMON_SLOT_SHIFT)
+
+/* MAX98925_R024_DOUT_CFG_VBAT */
+#define M98925_DAI_VBAT_EN_MASK					(1<<5)
+#define M98925_DAI_VBAT_EN_SHIFT				5
+#define M98925_DAI_VBAT_EN_WIDTH				1
+#define M98925_DAI_VBAT_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBAT_SLOT_SHIFT				0
+#define M98925_DAI_VBAT_SLOT_WIDTH				5
+
+/* MAX98925_R025_DOUT_CFG_VBST */
+#define M98925_DAI_VBST_EN_MASK					(1<<5)
+#define M98925_DAI_VBST_EN_SHIFT				5
+#define M98925_DAI_VBST_EN_WIDTH				1
+#define M98925_DAI_VBST_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBST_SLOT_SHIFT				0
+#define M98925_DAI_VBST_SLOT_WIDTH				5
+
+/* MAX98925_R026_DOUT_CFG_FLAG */
+#define M98925_DAI_FLAG_EN_MASK					(1<<5)
+#define M98925_DAI_FLAG_EN_SHIFT				5
+#define M98925_DAI_FLAG_EN_WIDTH				1
+#define M98925_DAI_FLAG_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_FLAG_SLOT_SHIFT				0
+#define M98925_DAI_FLAG_SLOT_WIDTH				5
+
+/* MAX98925_R027_DOUT_HIZ_CFG1 */
+#define M98925_DAI_SLOT_HIZ_CFG1_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG1_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG1_WIDTH			8
+
+/* MAX98925_R028_DOUT_HIZ_CFG2 */
+#define M98925_DAI_SLOT_HIZ_CFG2_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG2_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG2_WIDTH			8
+
+/* MAX98925_R029_DOUT_HIZ_CFG3 */
+#define M98925_DAI_SLOT_HIZ_CFG3_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG3_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG3_WIDTH			8
+
+/* MAX98925_R02A_DOUT_HIZ_CFG4 */
+#define M98925_DAI_SLOT_HIZ_CFG4_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG4_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG4_WIDTH			8
+
+/* MAX98925_R02B_DOUT_DRV_STRENGTH */
+#define M98925_DAI_OUT_DRIVE_MASK				(0x03<<0)
+#define M98925_DAI_OUT_DRIVE_SHIFT				0
+#define M98925_DAI_OUT_DRIVE_WIDTH				2
+
+/* MAX98925_R02C_FILTERS */
+#define M98925_ADC_DITHER_EN_MASK				(1<<7)
+#define M98925_ADC_DITHER_EN_SHIFT				7
+#define M98925_ADC_DITHER_EN_WIDTH				1
+#define M98925_IV_DCB_EN_MASK					(1<<6)
+#define M98925_IV_DCB_EN_SHIFT					6
+#define M98925_IV_DCB_EN_WIDTH					1
+#define M98925_DAC_DITHER_EN_MASK				(1<<4)
+#define M98925_DAC_DITHER_EN_SHIFT				4
+#define M98925_DAC_DITHER_EN_WIDTH				1
+#define M98925_DAC_FILTER_MODE_MASK				(1<<3)
+#define M98925_DAC_FILTER_MODE_SHIFT			3
+#define M98925_DAC_FILTER_MODE_WIDTH			1
+#define M98925_DAC_HPF_MASK				(0x07<<0)
+#define M98925_DAC_HPF_SHIFT					0
+#define M98925_DAC_HPF_WIDTH					3
+#define M98925_DAC_HPF_DISABLE		(0 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_DC_BLOCK		(1 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_100		(2 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_200		(3 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_400		(4 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_800		(5 << M98925_DAC_HPF_SHIFT)
+
+/* MAX98925_R02D_GAIN */
+#define M98925_DAC_IN_SEL_MASK					(0x03<<5)
+#define M98925_DAC_IN_SEL_SHIFT					5
+#define M98925_DAC_IN_SEL_WIDTH					2
+#define M98925_SPK_GAIN_MASK					(0x1F<<0)
+#define M98925_SPK_GAIN_SHIFT					0
+#define M98925_SPK_GAIN_WIDTH					5
+
+#define M98925_DAC_IN_SEL_LEFT_DAI (0 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_RIGHT_DAI (1 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_SUMMED_DAI (2 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << M98925_DAC_IN_SEL_SHIFT)
+
+/* MAX98925_R02E_GAIN_RAMPING */
+#define M98925_SPK_RMP_EN_MASK		(1<<1)
+#define M98925_SPK_RMP_EN_SHIFT		1
+#define M98925_SPK_RMP_EN_WIDTH		1
+#define M98925_SPK_ZCD_EN_MASK		(1<<0)
+#define M98925_SPK_ZCD_EN_SHIFT		0
+#define M98925_SPK_ZCD_EN_WIDTH		1
+
+/* MAX98925_R02F_SPK_AMP */
+#define M98925_SPK_MODE_MASK		(1<<0)
+#define M98925_SPK_MODE_SHIFT		0
+#define M98925_SPK_MODE_WIDTH		1
+
+/* MAX98925_R030_THRESHOLD */
+#define M98925_ALC_EN_MASK			(1<<5)
+#define M98925_ALC_EN_SHIFT			5
+#define M98925_ALC_EN_WIDTH			1
+#define M98925_ALC_TH_MASK			(0x1F<<0)
+#define M98925_ALC_TH_SHIFT			0
+#define M98925_ALC_TH_WIDTH			5
+
+/* MAX98925_R031_ALC_ATTACK */
+#define M98925_ALC_ATK_STEP_MASK	(0x0F<<4)
+#define M98925_ALC_ATK_STEP_SHIFT	4
+#define M98925_ALC_ATK_STEP_WIDTH	4
+#define M98925_ALC_ATK_RATE_MASK	(0x7<<0)
+#define M98925_ALC_ATK_RATE_SHIFT	0
+#define M98925_ALC_ATK_RATE_WIDTH	3
+
+/* MAX98925_R032_ALC_ATTEN_RLS */
+#define M98925_ALC_MAX_ATTEN_MASK	(0x0F<<4)
+#define M98925_ALC_MAX_ATTEN_SHIFT	4
+#define M98925_ALC_MAX_ATTEN_WIDTH	4
+#define M98925_ALC_RLS_RATE_MASK	(0x7<<0)
+#define M98925_ALC_RLS_RATE_SHIFT	0
+#define M98925_ALC_RLS_RATE_WIDTH	3
+
+/* MAX98925_R033_ALC_HOLD_RLS */
+#define M98925_ALC_RLS_TGR_MASK		(1<<0)
+#define M98925_ALC_RLS_TGR_SHIFT	0
+#define M98925_ALC_RLS_TGR_WIDTH	1
+
+/* MAX98925_R034_ALC_CONFIGURATION */
+#define M98925_ALC_MUTE_EN_MASK		(1<<7)
+#define M98925_ALC_MUTE_EN_SHIFT	7
+#define M98925_ALC_MUTE_EN_WIDTH	1
+#define M98925_ALC_MUTE_DLY_MASK	(0x07<<4)
+#define M98925_ALC_MUTE_DLY_SHIFT	4
+#define M98925_ALC_MUTE_DLY_WIDTH	3
+#define M98925_ALC_RLS_DBT_MASK		(0x07<<0)
+#define M98925_ALC_RLS_DBT_SHIFT	0
+#define M98925_ALC_RLS_DBT_WIDTH	3
+
+/* MAX98925_R035_BOOST_CONVERTER */
+#define M98925_BST_SYNC_MASK		(1<<7)
+#define M98925_BST_SYNC_SHIFT		7
+#define M98925_BST_SYNC_WIDTH		1
+#define M98925_BST_PHASE_MASK		(0x03<<4)
+#define M98925_BST_PHASE_SHIFT		4
+#define M98925_BST_PHASE_WIDTH		2
+#define M98925_BST_SKIP_MODE_MASK	(0x03<<0)
+#define M98925_BST_SKIP_MODE_SHIFT	0
+#define M98925_BST_SKIP_MODE_WIDTH	2
+
+/* MAX98925_R036_BLOCK_ENABLE */
+#define M98925_BST_EN_MASK			(1<<7)
+#define M98925_BST_EN_SHIFT			7
+#define M98925_BST_EN_WIDTH			1
+#define M98925_WATCH_EN_MASK		(1<<6)
+#define M98925_WATCH_EN_SHIFT		6
+#define M98925_WATCH_EN_WIDTH		1
+#define M98925_CLKMON_EN_MASK		(1<<5)
+#define M98925_CLKMON_EN_SHIFT		5
+#define M98925_CLKMON_EN_WIDTH		1
+#define M98925_SPK_EN_MASK			(1<<4)
+#define M98925_SPK_EN_SHIFT			4
+#define M98925_SPK_EN_WIDTH			1
+#define M98925_ADC_VBST_EN_MASK		(1<<3)
+#define M98925_ADC_VBST_EN_SHIFT	3
+#define M98925_ADC_VBST_EN_WIDTH	1
+#define M98925_ADC_VBAT_EN_MASK		(1<<2)
+#define M98925_ADC_VBAT_EN_SHIFT	2
+#define M98925_ADC_VBAT_EN_WIDTH	1
+#define M98925_ADC_IMON_EN_MASK		(1<<1)
+#define M98925_ADC_IMON_EN_SHIFT	1
+#define M98925_ADC_IMON_EN_WIDTH	1
+#define M98925_ADC_VMON_EN_MASK		(1<<0)
+#define M98925_ADC_VMON_EN_SHIFT	0
+#define M98925_ADC_VMON_EN_WIDTH	1
+
+/* MAX98925_R037_CONFIGURATION */
+#define M98925_BST_VOUT_MASK		(0x0F<<4)
+#define M98925_BST_VOUT_SHIFT		4
+#define M98925_BST_VOUT_WIDTH		4
+#define M98925_THERMWARN_LEVEL_MASK	(0x03<<2)
+#define M98925_THERMWARN_LEVEL_SHIFT			2
+#define M98925_THERMWARN_LEVEL_WIDTH			2
+#define M98925_WATCH_TIME_MASK			(0x03<<0)
+#define M98925_WATCH_TIME_SHIFT			0
+#define M98925_WATCH_TIME_WIDTH			2
+
+/* MAX98925_R038_GLOBAL_ENABLE */
+#define M98925_EN_MASK			(1<<7)
+#define M98925_EN_SHIFT			7
+#define M98925_EN_WIDTH			1
+
+/* MAX98925_R03A_BOOST_LIMITER */
+#define M98925_BST_ILIM_MASK	(0x1F<<3)
+#define M98925_BST_ILIM_SHIFT	3
+#define M98925_BST_ILIM_WIDTH	5
+
+/* MAX98925_R0FF_VERSION */
+#define M98925_REV_ID_MASK	(0xFF<<0)
+#define M98925_REV_ID_SHIFT	0
+#define M98925_REV_ID_WIDTH	8
+
+struct max98925_cdata {
+	unsigned int rate;
+	unsigned int fmt;
+};
+
+struct max98925_priv {
+	struct regmap *regmap;
+	struct snd_soc_codec *codec;
+	struct max98925_pdata *pdata;
+	unsigned int sysclk;
+	unsigned int v_slot;
+	unsigned int i_slot;
+	unsigned int spk_gain;
+	unsigned int ch_size;
+};
+#endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-14  5:14 ` Mark Brown
@ 2015-02-14  6:35   ` anish
  2015-02-24 14:50     ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: anish @ 2015-02-14  6:35 UTC (permalink / raw)
  To: Mark Brown
  Cc: liam.r.girdwood, Maxwell McKinnon, Linux-ALSA,
	Lars-Peter Clausen, Nitin Mittal

On Fri, Feb 13, 2015 at 9:14 PM, Mark Brown <broonie@kernel.org> wrote:
> On Fri, Feb 13, 2015 at 07:25:01PM -0800, Anish Kumar wrote:
>
>> +config SND_SOC_MAX98925
>> +     bool "Support MAX98925 stereo system"
>
> Why bool?  Also "stereo system" should be "audio CODEC" or similar.
>
>> +     depends on I2C
>> +     help
>> +     MAX98925 is a high-efficiency mono
>> +     Class DG audio amplifier. Use this
>> +     option to enable the system consisting
>> +     of left and right power amplifier.
>> +
>
> Please fix the formatting to look like other Kconfig entries
> (indentation of the help text).

will do that.
>
>> +static int max98925_hpf_l;
>> +static int max98925_hpf_r;
>> +static int max98925_dai_sel_l;
>> +static int max98925_dai_sel_r;
>> +static struct max98925_priv *max98925;
>
> Why global variables not values in the private data structure for the
> device?

Will make it part of private data.
>
>> +static const char *const dai_text[] = {
>> +             "L_Data", "R_Data", "LR_Data", "LR_Data_Div2",
>> +};
>
>> +static const char *const hpf_text[] = {
>> +             "hpf_disable", "hpf_dc_block", "hpf_enable_100",
>> +             "hpf_enable_200", "hpf_enable_400", "hpf_enable_800",
>> +};
>
> These have strange indentation and the names should be more human
> readable - look at how the names are written for enums in other drivers.

Will make it much more readable.
>
>> +static struct reg_default max98925_reg[] = {
>> +     { 0x00, 0x00 }, /* Battery Voltage Data */
>> +     { 0x01, 0x00 }, /* Boost Voltage Data */
>> +     { 0x02, 0x00 }, /* Live Status0 */
>> +     { 0x03, 0x00 }, /* Live Status1 */
>> +     { 0x04, 0x00 }, /* Live Status2 */
>
> These look like they should be volatile registers, why do they have
> cache defaults defined?

This is default registers. Not cache defaults.
>
>> +     switch (ucontrol->value.integer.value[0]) {
>> +     case 0:
>> +             regmap_update_bits(max98925->regmap_l, reg, mask,
>> +                             M98925_DAC_HPF_DISABLE);
>> +             break;
>> +     case 1:
>> +             regmap_update_bits(max98925->regmap_l, reg, mask,
>> +                             M98925_DAC_HPF_DC_BLOCK);
>> +             break;
>
> These look like magic numbers from an enum - why not use the standard
> enum control?  In general a *lot* of the code around here looks like
> it's open coding core functionality.

We have two *exactly* same amplifiers on the board. Both are connected
to the same i2c line but having different addresses. We need to drive
both of this as left and right speaker.
This driver is basically to support both of this devices. However i think
i will go with your advice and remove "driving other device also".

Doing above will remove all the ugliness of this code and remove all the
open coding which is done here.

>
>> +static int max98925_dac_ev_r(struct snd_soc_dapm_widget *w,
>> +                             struct snd_kcontrol *kcontrol, int event)
>> +{
>> +     struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
>> +     struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
>> +
>> +     regmap_update_bits(max98925->regmap_r, MAX98925_R036_BLOCK_ENABLE,
>> +                     M98925_SPK_EN_MASK, M98925_SPK_EN_MASK);
>> +     return 0;
>> +}
>
> This should check the event or just be a normal DAPM widget.  Looking at
> where it's getting used it appears to be the latter.

Will make it a dapm widget.
>
>> +static const struct snd_kcontrol_new dai_sel_mux[2] = {
>
> No magic numbers, just let the compiler figure it out.

ok.
>
>> +void max98925_regmap_write_stereo(struct max98925_priv *max98925,
>> +     unsigned int reg, unsigned int val)
>> +{
>> +     regmap_write(max98925->regmap_l, reg, val);
>> +     regmap_write(max98925->regmap_r, reg, val);
>> +}
>
> You had another "stereo write" function further up - what's this all
> about?

Explained earlier. Will keep a single instance of this driver.
>
>> +     switch (reg) {
>> +     case MAX98925_R000_VBAT_DATA:
>
> Putting the register numbers in the define for the register name seems
> to defeat some of the point of the defines...

Looked at the other driver and everyone is using the same way.
Sorry but didn't get your point.
>
>> +static bool max98925_readable_register(struct device *dev, unsigned int reg)
>> +{
>> +     switch (reg) {
>> +     case MAX98925_R00E_IRQ_CLEAR0:
>> +     case MAX98925_R00F_IRQ_CLEAR1:
>> +     case MAX98925_R010_IRQ_CLEAR2:
>> +     case MAX98925_R033_ALC_HOLD_RLS:
>> +             return false;
>> +     default:
>> +             return true;
>> +     }
>> +};
>
> So the volatile registers aren't readable?

Will check the datasheet again.
>
>> +DECLARE_TLV_DB_SCALE(max98925_spk_tlv, -600, 100, 0);
>> +static int reg_set_optimum_mode_check(struct regulator *reg, int load_ua)
>> +{
>> +     return (regulator_count_voltages(reg) > 0) ?
>> +             regulator_set_optimum_mode(reg, load_ua) : 0;
>> +}
>
> I'm not 100% sure what this is intended to do but it it's not at all
> obvious that it's sensible...  it at least needs some documentation.

I will check with ralph on this and get back to you.
>
>> +     if (pullup) {
>> +             pr_info("%s: i2c pull up\n", __func__);
>
> If this were useful it should be a dev_ print, though I'm not convinced
> it isn't just noise.

will remove it.
>
>> +             max98925_vcc_i2c = regulator_get(&i2c->dev, "vcc_i2c");
>> +             if (IS_ERR(max98925_vcc_i2c)) {
>
> Why not devm_?

will change it.
>
>> +                     rc = PTR_ERR(max98925_vcc_i2c);
>> +                     pr_err("%s: regulator get failed rc=%d\n",
>> +                                             __func__, rc);
>
> Similarly here and for all the other error prints.

will change to dev_
>
>> +             if (regulator_count_voltages(max98925_vcc_i2c) > 0) {
>> +                     rc = regulator_set_voltage(max98925_vcc_i2c,
>> +                             VCC_I2C_MIN_UV, VCC_I2C_MAX_UV);
>> +                     if (rc) {
>
> All the stuff being done with regulator_count_voltages() looks broken,
> and the fact that the driver is setting a single specific I/O voltage
> is also highly unusual.  Normally the board would do that.
>
> If the regulator code doesn't look like the regulator code for other
> CODEC drivers it needs to be clear why, and it's *very* suspicious to
> see a driver with a single optional regulator called "vcc_i2c".

I will get back on this.
>
>> +static void max98925_set_sense_data(struct max98925_priv *max98925)
>> +{
>> +     /*
>> +      * 1. set VMON slots
>> +      */
>> +     regmap_update_bits(max98925->regmap_l,
>> +             MAX98925_R022_DOUT_CFG_VMON,
>> +             M98925_DAI_VMON_EN_MASK, M98925_DAI_VMON_EN_MASK);
>> +     regmap_update_bits(max98925->regmap_l,
>> +             MAX98925_R022_DOUT_CFG_VMON,
>> +             M98925_DAI_VMON_SLOT_MASK, M98925_DAI_VMON_SLOT_00_01);
>> +     /*
>> +      * 2. set IMON slots
>> +      */
>> +     regmap_update_bits(max98925->regmap_l,
>> +             MAX98925_R023_DOUT_CFG_IMON,
>> +             M98925_DAI_IMON_EN_MASK, M98925_DAI_IMON_EN_MASK);
>> +     regmap_update_bits(max98925->regmap_l,
>> +             MAX98925_R023_DOUT_CFG_IMON,
>> +             M98925_DAI_IMON_SLOT_MASK, M98925_DAI_IMON_SLOT_02_03);
>> +}
>
> Why is this hard coded in the driver and not platform data - if this is
> configurable presumably other boards might need it set differently?

Will check with our hardware guy on this.
>
>> +static void max98925_set_slave(struct max98925_priv *max98925)
>> +{
>> +     /*
>> +      * 1. use BCLK instead of MCLK
>> +      */
>> +     max98925_regmap_update_bits_stereo(max98925,
>> +                     MAX98925_R01A_DAI_CLK_MODE1,
>> +                     M98925_DAI_CLK_SOURCE_MASK, M98925_DAI_CLK_SOURCE_MASK);
>> +     /*
>> +      * 2. set DAI to slave mode
>> +      */
>> +     max98925_regmap_update_bits_stereo(max98925,
>> +                     MAX98925_R01B_DAI_CLK_MODE2,
>> +                     M98925_DAI_MAS_MASK, 0);
>> +     /*
>> +      * 3. set BLCKs to LRCLKs to 64
>> +      */
>> +     max98925_regmap_update_bits_stereo(max98925,
>> +                     MAX98925_R01B_DAI_CLK_MODE2,
>> +                     M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
>
> This looks to be a mix of setting slave mode and setting some clocking
> configuration that ought to be configurable - for example I'd expect
> clock sources to be configured via set_sysclk().

Slave mode also should be configured in set_sysclk? I will move
bclk and lrclk setting to set_sysclk.

>
>> +     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
>> +     case SND_SOC_DAIFMT_I2S:
>> +     case SND_SOC_DAIFMT_LEFT_J:
>> +             break;
>
> This is setting the same configuration for multiple formats, that can't
> be right.

this is unused code. Will remove it.
>
>> +     case SNDRV_PCM_FORMAT_S24_LE:
>> +             max98925_regmap_update_bits_stereo(max98925,
>> +                             MAX98925_R020_FORMAT,
>> +                             M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
>> +             dev_dbg(codec->dev, "%s: (really set to 32 bits)\n", __func__);
>> +             break;
>
> This looks broken...

Will have to check with ralph on this.
>
>> +     if (mute) {
>> +             max98925_regmap_update_bits_stereo(max98925, MAX98925_R02D_GAIN,
>> +                     M98925_SPK_GAIN_MASK, 0x00);
>> +
>> +             max98925_regmap_update_bits_stereo(max98925,
>> +                     MAX98925_R038_GLOBAL_ENABLE,
>> +                     M98925_EN_MASK, 0x0);
>> +     } else  {
>> +             max98925_regmap_update_bits_stereo(max98925,
>> +                     MAX98925_R036_BLOCK_ENABLE,
>> +                     M98925_BST_EN_MASK |
>> +                     M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
>> +                     M98925_BST_EN_MASK |
>> +                     M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
>> +
>> +             max98925_regmap_write_stereo(max98925,
>> +                     MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
>> +     }
>
> This doesn't look like it's muting, it looks like it's doing a whole
> bunch of other things.  The mute operation should mute and only mute
> (and then only if the device usefully supports it).

Coming to think of it, you are right. I am wondering if this(turning on voltage)
and current along with global audio enable bit) should
be dapm widget as it should always be turned on whenever
playback starts. I think i will make it a callback of
SND_SOC_DAPM_DAC_E
>
>> +     /* can be configured to any other value supported by this chip */
>> +     max98925->sysclk = 12288000;
>> +     max98925->spk_gain = 0x14;
>> +     cdata = &max98925->dai[0];
>> +     cdata->rate = (unsigned)-1;
>> +     cdata->fmt  = (unsigned)-1;
>
> Don't hard code board specific configuration in the driver.  Just let
> the user set it at runtime.

Will remove it.
>
>> +     ret = regmap_read(max98925->regmap_l,
>> +                     MAX98925_R0FF_VERSION, &reg);
>> +     if ((ret < 0) ||
>> +             ((reg != MAX98925_VERSION) &&
>> +             (reg != MAX98925_VERSION1))) {
>> +             dev_err(codec->dev,
>> +                     "L device initialization error (%d 0x%02X)\n",
>> +                     ret, reg);
>> +             goto err_access;
>> +     }
>> +     dev_info(codec->dev, "L device version 0x%02X\n", reg);
>> +
>> +     reg = 0;
>> +     ret = regmap_read(max98925->regmap_r,
>> +                     MAX98925_R0FF_VERSION, &reg);
>
> This looks like the driver is trying to support two physical devices in
> a single driver.  Don't do that, write a driver which controls one
> instance of the device and let the subsystem worry about how they're
> connected on the board.

Explained above.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH] ASoC: Add max98925 codec driver
  2015-02-14  3:25 Anish Kumar
@ 2015-02-14  5:14 ` Mark Brown
  2015-02-14  6:35   ` anish
  0 siblings, 1 reply; 15+ messages in thread
From: Mark Brown @ 2015-02-14  5:14 UTC (permalink / raw)
  To: Anish Kumar
  Cc: liam.r.girdwood, Maxwell.McKinnon, alsa-devel, lars, nitin.mittal


[-- Attachment #1.1: Type: text/plain, Size: 8738 bytes --]

On Fri, Feb 13, 2015 at 07:25:01PM -0800, Anish Kumar wrote:

> +config SND_SOC_MAX98925
> +	bool "Support MAX98925 stereo system"

Why bool?  Also "stereo system" should be "audio CODEC" or similar.

> +	depends on I2C
> +	help
> +	MAX98925 is a high-efficiency mono
> +	Class DG audio amplifier. Use this
> +	option to enable the system consisting
> +	of left and right power amplifier.
> +

Please fix the formatting to look like other Kconfig entries
(indentation of the help text).

> +static int max98925_hpf_l;
> +static int max98925_hpf_r;
> +static int max98925_dai_sel_l;
> +static int max98925_dai_sel_r;
> +static struct max98925_priv *max98925;

Why global variables not values in the private data structure for the
device?

> +static const char *const dai_text[] = {
> +		"L_Data", "R_Data", "LR_Data", "LR_Data_Div2",
> +};

> +static const char *const hpf_text[] = {
> +		"hpf_disable", "hpf_dc_block", "hpf_enable_100",
> +		"hpf_enable_200", "hpf_enable_400", "hpf_enable_800",
> +};

These have strange indentation and the names should be more human
readable - look at how the names are written for enums in other drivers.

> +static struct reg_default max98925_reg[] = {
> +	{ 0x00, 0x00 }, /* Battery Voltage Data */
> +	{ 0x01, 0x00 }, /* Boost Voltage Data */
> +	{ 0x02, 0x00 }, /* Live Status0 */
> +	{ 0x03, 0x00 }, /* Live Status1 */
> +	{ 0x04, 0x00 }, /* Live Status2 */

These look like they should be volatile registers, why do they have
cache defaults defined?

> +	switch (ucontrol->value.integer.value[0]) {
> +	case 0:
> +		regmap_update_bits(max98925->regmap_l, reg, mask,
> +				M98925_DAC_HPF_DISABLE);
> +		break;
> +	case 1:
> +		regmap_update_bits(max98925->regmap_l, reg, mask,
> +				M98925_DAC_HPF_DC_BLOCK);
> +		break;

These look like magic numbers from an enum - why not use the standard
enum control?  In general a *lot* of the code around here looks like
it's open coding core functionality.

> +static int max98925_dac_ev_r(struct snd_soc_dapm_widget *w,
> +				struct snd_kcontrol *kcontrol, int event)
> +{
> +	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
> +	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
> +
> +	regmap_update_bits(max98925->regmap_r, MAX98925_R036_BLOCK_ENABLE,
> +			M98925_SPK_EN_MASK, M98925_SPK_EN_MASK);
> +	return 0;
> +}

This should check the event or just be a normal DAPM widget.  Looking at
where it's getting used it appears to be the latter.

> +static const struct snd_kcontrol_new dai_sel_mux[2] = {

No magic numbers, just let the compiler figure it out.

> +void max98925_regmap_write_stereo(struct max98925_priv *max98925,
> +	unsigned int reg, unsigned int val)
> +{
> +	regmap_write(max98925->regmap_l, reg, val);
> +	regmap_write(max98925->regmap_r, reg, val);
> +}

You had another "stereo write" function further up - what's this all
about?

> +	switch (reg) {
> +	case MAX98925_R000_VBAT_DATA:

Putting the register numbers in the define for the register name seems
to defeat some of the point of the defines...

> +static bool max98925_readable_register(struct device *dev, unsigned int reg)
> +{
> +	switch (reg) {
> +	case MAX98925_R00E_IRQ_CLEAR0:
> +	case MAX98925_R00F_IRQ_CLEAR1:
> +	case MAX98925_R010_IRQ_CLEAR2:
> +	case MAX98925_R033_ALC_HOLD_RLS:
> +		return false;
> +	default:
> +		return true;
> +	}
> +};

So the volatile registers aren't readable?

> +DECLARE_TLV_DB_SCALE(max98925_spk_tlv, -600, 100, 0);
> +static int reg_set_optimum_mode_check(struct regulator *reg, int load_ua)
> +{
> +	return (regulator_count_voltages(reg) > 0) ?
> +		regulator_set_optimum_mode(reg, load_ua) : 0;
> +}

I'm not 100% sure what this is intended to do but it it's not at all
obvious that it's sensible...  it at least needs some documentation.

> +	if (pullup) {
> +		pr_info("%s: i2c pull up\n", __func__);

If this were useful it should be a dev_ print, though I'm not convinced
it isn't just noise.

> +		max98925_vcc_i2c = regulator_get(&i2c->dev, "vcc_i2c");
> +		if (IS_ERR(max98925_vcc_i2c)) {

Why not devm_?

> +			rc = PTR_ERR(max98925_vcc_i2c);
> +			pr_err("%s: regulator get failed rc=%d\n",
> +						__func__, rc);

Similarly here and for all the other error prints.

> +		if (regulator_count_voltages(max98925_vcc_i2c) > 0) {
> +			rc = regulator_set_voltage(max98925_vcc_i2c,
> +				VCC_I2C_MIN_UV, VCC_I2C_MAX_UV);
> +			if (rc) {

All the stuff being done with regulator_count_voltages() looks broken,
and the fact that the driver is setting a single specific I/O voltage
is also highly unusual.  Normally the board would do that.

If the regulator code doesn't look like the regulator code for other
CODEC drivers it needs to be clear why, and it's *very* suspicious to
see a driver with a single optional regulator called "vcc_i2c".

> +static void max98925_set_sense_data(struct max98925_priv *max98925)
> +{
> +	/*
> +	 * 1. set VMON slots
> +	 */
> +	regmap_update_bits(max98925->regmap_l,
> +		MAX98925_R022_DOUT_CFG_VMON,
> +		M98925_DAI_VMON_EN_MASK, M98925_DAI_VMON_EN_MASK);
> +	regmap_update_bits(max98925->regmap_l,
> +		MAX98925_R022_DOUT_CFG_VMON,
> +		M98925_DAI_VMON_SLOT_MASK, M98925_DAI_VMON_SLOT_00_01);
> +	/*
> +	 * 2. set IMON slots
> +	 */
> +	regmap_update_bits(max98925->regmap_l,
> +		MAX98925_R023_DOUT_CFG_IMON,
> +		M98925_DAI_IMON_EN_MASK, M98925_DAI_IMON_EN_MASK);
> +	regmap_update_bits(max98925->regmap_l,
> +		MAX98925_R023_DOUT_CFG_IMON,
> +		M98925_DAI_IMON_SLOT_MASK, M98925_DAI_IMON_SLOT_02_03);
> +}

Why is this hard coded in the driver and not platform data - if this is
configurable presumably other boards might need it set differently?

> +static void max98925_set_slave(struct max98925_priv *max98925)
> +{
> +	/*
> +	 * 1. use BCLK instead of MCLK
> +	 */
> +	max98925_regmap_update_bits_stereo(max98925,
> +			MAX98925_R01A_DAI_CLK_MODE1,
> +			M98925_DAI_CLK_SOURCE_MASK, M98925_DAI_CLK_SOURCE_MASK);
> +	/*
> +	 * 2. set DAI to slave mode
> +	 */
> +	max98925_regmap_update_bits_stereo(max98925,
> +			MAX98925_R01B_DAI_CLK_MODE2,
> +			M98925_DAI_MAS_MASK, 0);
> +	/*
> +	 * 3. set BLCKs to LRCLKs to 64
> +	 */
> +	max98925_regmap_update_bits_stereo(max98925,
> +			MAX98925_R01B_DAI_CLK_MODE2,
> +			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);

This looks to be a mix of setting slave mode and setting some clocking
configuration that ought to be configurable - for example I'd expect
clock sources to be configured via set_sysclk().

> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_I2S:
> +	case SND_SOC_DAIFMT_LEFT_J:
> +		break;

This is setting the same configuration for multiple formats, that can't
be right.

> +	case SNDRV_PCM_FORMAT_S24_LE:
> +		max98925_regmap_update_bits_stereo(max98925,
> +				MAX98925_R020_FORMAT,
> +				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
> +		dev_dbg(codec->dev, "%s: (really set to 32 bits)\n", __func__);
> +		break;

This looks broken...

> +	if (mute) {
> +		max98925_regmap_update_bits_stereo(max98925, MAX98925_R02D_GAIN,
> +			M98925_SPK_GAIN_MASK, 0x00);
> +
> +		max98925_regmap_update_bits_stereo(max98925,
> +			MAX98925_R038_GLOBAL_ENABLE,
> +			M98925_EN_MASK, 0x0);
> +	} else	{
> +		max98925_regmap_update_bits_stereo(max98925,
> +			MAX98925_R036_BLOCK_ENABLE,
> +			M98925_BST_EN_MASK |
> +			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
> +			M98925_BST_EN_MASK |
> +			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
> +
> +		max98925_regmap_write_stereo(max98925,
> +			MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
> +	}

This doesn't look like it's muting, it looks like it's doing a whole
bunch of other things.  The mute operation should mute and only mute
(and then only if the device usefully supports it).

> +	/* can be configured to any other value supported by this chip */
> +	max98925->sysclk = 12288000;
> +	max98925->spk_gain = 0x14;
> +	cdata = &max98925->dai[0];
> +	cdata->rate = (unsigned)-1;
> +	cdata->fmt  = (unsigned)-1;

Don't hard code board specific configuration in the driver.  Just let
the user set it at runtime.

> +	ret = regmap_read(max98925->regmap_l,
> +			MAX98925_R0FF_VERSION, &reg);
> +	if ((ret < 0) ||
> +		((reg != MAX98925_VERSION) &&
> +		(reg != MAX98925_VERSION1))) {
> +		dev_err(codec->dev,
> +			"L device initialization error (%d 0x%02X)\n",
> +			ret, reg);
> +		goto err_access;
> +	}
> +	dev_info(codec->dev, "L device version 0x%02X\n", reg);
> +
> +	reg = 0;
> +	ret = regmap_read(max98925->regmap_r,
> +			MAX98925_R0FF_VERSION, &reg);

This looks like the driver is trying to support two physical devices in
a single driver.  Don't do that, write a driver which controls one
instance of the device and let the subsystem worry about how they're
connected on the board.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH] ASoC: Add max98925 codec driver
@ 2015-02-14  3:25 Anish Kumar
  2015-02-14  5:14 ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: Anish Kumar @ 2015-02-14  3:25 UTC (permalink / raw)
  To: broonie, Maxwell.McKinnon, liam.r.girdwood, lars
  Cc: alsa-devel, nitin.mittal, Anish Kumar

Signed-off-by: Anish Kumar <yesanishhere@gmail.com>
---
 sound/soc/codecs/Kconfig    |   10 +
 sound/soc/codecs/Makefile   |    2 +
 sound/soc/codecs/max98925.c | 1229 +++++++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/max98925.h |  845 +++++++++++++++++++++++++++++
 4 files changed, 2086 insertions(+)
 create mode 100644 sound/soc/codecs/max98925.c
 create mode 100644 sound/soc/codecs/max98925.h

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 45b7256..a4ccae9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX98088 if I2C
 	select SND_SOC_MAX98090 if I2C
 	select SND_SOC_MAX98095 if I2C
+	select SND_SOC_MAX98925 if I2C
 	select SND_SOC_MAX9850 if I2C
 	select SND_SOC_MAX9768 if I2C
 	select SND_SOC_MAX9877 if I2C
@@ -285,6 +286,15 @@ config SND_SOC_MAX9850
 config SND_SOC_OMAP_HDMI_CODEC
        tristate
 
+config SND_SOC_MAX98925
+	bool "Support MAX98925 stereo system"
+	depends on I2C
+	help
+	MAX98925 is a high-efficiency mono
+	Class DG audio amplifier. Use this
+	option to enable the system consisting
+	of left and right power amplifier.
+
 config SND_SOC_PCM3008
        tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 6a3b3c3..313a7c4 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -37,6 +37,7 @@ snd-soc-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98090-objs := max98090.o
 snd-soc-max98095-objs := max98095.o
+snd-soc-max98925-objs := max98925.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
@@ -162,6 +163,7 @@ obj-$(CONFIG_SND_SOC_MAX9768)	+= snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98090)	+= snd-soc-max98090.o
 obj-$(CONFIG_SND_SOC_MAX98095)	+= snd-soc-max98095.o
+obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c
new file mode 100644
index 0000000..e3a1984
--- /dev/null
+++ b/sound/soc/codecs/max98925.c
@@ -0,0 +1,1229 @@
+/*
+ * max98925.c -- ALSA SoC Stereo MAX98925 driver
+ * Copyright 2013-15 Maxim Integrated Products
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/regulator/consumer.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include "max98925.h"
+
+#define VCC_I2C_MIN_UV	1800000
+#define VCC_I2C_MAX_UV	1800000
+#define I2C_LOAD_UA	300000
+
+enum max98925_type {
+	MAX98925L,
+	MAX98925R,
+};
+
+static int max98925_hpf_l;
+static int max98925_hpf_r;
+static int max98925_dai_sel_l;
+static int max98925_dai_sel_r;
+static struct max98925_priv *max98925;
+
+static const char *const dai_text[] = {
+		"L_Data", "R_Data", "LR_Data", "LR_Data_Div2",
+};
+
+static const char *const hpf_text[] = {
+		"hpf_disable", "hpf_dc_block", "hpf_enable_100",
+		"hpf_enable_200", "hpf_enable_400", "hpf_enable_800",
+};
+
+static const struct soc_enum max98925_dai_l_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dai_text), dai_text),
+};
+
+static const struct soc_enum max98925_dai_r_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dai_text), dai_text),
+};
+
+static const struct soc_enum max98925_hpfout_r_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(hpf_text), hpf_text),
+};
+
+static const struct soc_enum max98925_hpfout_l_enum[] = {
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(hpf_text), hpf_text),
+};
+
+static struct reg_default max98925_reg[] = {
+	{ 0x00, 0x00 }, /* Battery Voltage Data */
+	{ 0x01, 0x00 }, /* Boost Voltage Data */
+	{ 0x02, 0x00 }, /* Live Status0 */
+	{ 0x03, 0x00 }, /* Live Status1 */
+	{ 0x04, 0x00 }, /* Live Status2 */
+	{ 0x05, 0x00 }, /* State0 */
+	{ 0x06, 0x00 }, /* State1 */
+	{ 0x07, 0x00 }, /* State2 */
+	{ 0x08, 0x00 }, /* Flag0 */
+	{ 0x09, 0x00 }, /* Flag1 */
+	{ 0x0A, 0x00 }, /* Flag2 */
+	{ 0x0B, 0x00 }, /* IRQ Enable0 */
+	{ 0x0C, 0x00 }, /* IRQ Enable1 */
+	{ 0x0D, 0x00 }, /* IRQ Enable2 */
+	{ 0x0E, 0x00 }, /* IRQ Clear0 */
+	{ 0x0F, 0x00 }, /* IRQ Clear1 */
+	{ 0x10, 0x00 }, /* IRQ Clear2 */
+	{ 0x11, 0xC0 }, /* Map0 */
+	{ 0x12, 0x00 }, /* Map1 */
+	{ 0x13, 0x00 }, /* Map2 */
+	{ 0x14, 0xF0 }, /* Map3 */
+	{ 0x15, 0x00 }, /* Map4 */
+	{ 0x16, 0xAB }, /* Map5 */
+	{ 0x17, 0x89 }, /* Map6 */
+	{ 0x18, 0x00 }, /* Map7 */
+	{ 0x19, 0x00 }, /* Map8 */
+	{ 0x1A, 0x06 }, /* DAI Clock Mode 1 */
+	{ 0x1B, 0xC0 }, /* DAI Clock Mode 2 */
+	{ 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */
+	{ 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */
+	{ 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */
+	{ 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */
+	{ 0x20, 0x50 }, /* Format */
+	{ 0x21, 0x00 }, /* TDM Slot Select */
+	{ 0x22, 0x00 }, /* DOUT Configuration VMON */
+	{ 0x23, 0x00 }, /* DOUT Configuration IMON */
+	{ 0x24, 0x00 }, /* DOUT Configuration VBAT */
+	{ 0x25, 0x00 }, /* DOUT Configuration VBST */
+	{ 0x26, 0x00 }, /* DOUT Configuration FLAG */
+	{ 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */
+	{ 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */
+	{ 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */
+	{ 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */
+	{ 0x2B, 0x02 }, /* DOUT Drive Strength */
+	{ 0x2C, 0x90 }, /* Filters */
+	{ 0x2D, 0x00 }, /* Gain */
+	{ 0x2E, 0x02 }, /* Gain Ramping */
+	{ 0x2F, 0x00 }, /* Speaker Amplifier */
+	{ 0x30, 0x0A }, /* Threshold */
+	{ 0x31, 0x00 }, /* ALC Attack */
+	{ 0x32, 0x80 }, /* ALC Atten and Release */
+	{ 0x33, 0x00 }, /* ALC Infinite Hold Release */
+	{ 0x34, 0x92 }, /* ALC Configuration */
+	{ 0x35, 0x01 }, /* Boost Converter */
+	{ 0x36, 0x00 }, /* Block Enable */
+	{ 0x37, 0x00 }, /* Configuration */
+	{ 0x38, 0x00 }, /* Global Enable */
+	{ 0x3A, 0x00 }, /* Boost Limiter */
+	{ 0xFF, 0x50 }, /* Revision ID */
+};
+
+void max98925_regmap_update_bits_stereo(struct max98925_priv *max98925,
+		unsigned int reg, unsigned int mask, unsigned int val)
+{
+	regmap_update_bits(max98925->regmap_l, reg, mask, val);
+	regmap_update_bits(max98925->regmap_r, reg, mask, val);
+}
+
+static int max98925_get_hpf_l(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = max98925_hpf_l;
+	return 0;
+}
+
+static int max98925_put_hpf_l(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	struct snd_soc_dapm_update update;
+	unsigned int reg = MAX98925_R02C_FILTERS;
+	unsigned int mask = M98925_DAC_HPF_MASK;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		regmap_update_bits(max98925->regmap_l, reg, mask,
+				M98925_DAC_HPF_DISABLE);
+		break;
+	case 1:
+		regmap_update_bits(max98925->regmap_l, reg, mask,
+				M98925_DAC_HPF_DC_BLOCK);
+		break;
+	case 2:
+		regmap_update_bits(max98925->regmap_l, reg, mask,
+				M98925_DAC_HPF_EN_100);
+		break;
+	case 3:
+		regmap_update_bits(max98925->regmap_l, reg, mask,
+				M98925_DAC_HPF_EN_200);
+		break;
+	case 4:
+		regmap_update_bits(max98925->regmap_l, reg, mask,
+				M98925_DAC_HPF_EN_400);
+		break;
+	case 5:
+		regmap_update_bits(max98925->regmap_l, reg, mask,
+				M98925_DAC_HPF_EN_800);
+		break;
+	default:
+		return -EINVAL;
+	}
+	update.kcontrol = kcontrol;
+	update.reg = SND_SOC_NOPM;
+	max98925_hpf_l = ucontrol->value.integer.value[0];
+	snd_soc_dapm_mux_update_power(&codec->dapm,
+				kcontrol, max98925_hpf_l, e, &update);
+	return 0;
+}
+
+static int max98925_get_hpf_r(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = max98925_hpf_r;
+	return 0;
+}
+
+static int max98925_put_hpf_r(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	struct snd_soc_dapm_update update;
+	unsigned int reg = MAX98925_R02C_FILTERS;
+	unsigned int mask = M98925_DAC_HPF_MASK;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		regmap_update_bits(max98925->regmap_r, reg, mask,
+				M98925_DAC_HPF_DISABLE);
+		break;
+	case 1:
+		regmap_update_bits(max98925->regmap_r, reg, mask,
+				M98925_DAC_HPF_DC_BLOCK);
+		break;
+	case 2:
+		regmap_update_bits(max98925->regmap_r, reg, mask,
+				M98925_DAC_HPF_EN_100);
+		break;
+	case 3:
+		regmap_update_bits(max98925->regmap_r, reg, mask,
+				M98925_DAC_HPF_EN_200);
+		break;
+	case 4:
+		regmap_update_bits(max98925->regmap_r, reg, mask,
+				M98925_DAC_HPF_EN_400);
+		break;
+	case 5:
+		regmap_update_bits(max98925->regmap_r, reg, mask,
+				M98925_DAC_HPF_EN_800);
+		break;
+	default:
+		return -EINVAL;
+	}
+	max98925_hpf_r = ucontrol->value.integer.value[0];
+	update.kcontrol = kcontrol;
+	update.reg = SND_SOC_NOPM;
+	snd_soc_dapm_mux_update_power(&codec->dapm,
+				kcontrol, max98925_hpf_r, e, &update);
+	return 0;
+}
+
+static int max98925_get_dai_sel_l(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = max98925_dai_sel_l;
+	return 0;
+}
+
+static int max98925_put_dai_sel_l(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	struct snd_soc_dapm_update update;
+	unsigned int reg = MAX98925_R02D_GAIN;
+	unsigned int mask = M98925_DAC_IN_SEL_MASK;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		regmap_update_bits(max98925->regmap_l,
+			reg, mask, M98925_DAC_IN_SEL_LEFT_DAI);
+		break;
+	case 1:
+		regmap_update_bits(max98925->regmap_l,
+			reg, mask, M98925_DAC_IN_SEL_RIGHT_DAI);
+		break;
+	case 2:
+		regmap_update_bits(max98925->regmap_l,
+			reg, mask, M98925_DAC_IN_SEL_SUMMED_DAI);
+		break;
+	case 3:
+		regmap_update_bits(max98925->regmap_l,
+			reg, mask, M98925_DAC_IN_SEL_DIV2_SUMMED_DAI);
+		break;
+	default:
+		return -EINVAL;
+	}
+	max98925_dai_sel_l = ucontrol->value.integer.value[0];
+	update.kcontrol = kcontrol;
+	update.reg = SND_SOC_NOPM;
+	snd_soc_dapm_mux_update_power(&codec->dapm,
+				kcontrol, max98925_dai_sel_l, e, &update);
+	return 0;
+}
+
+static int max98925_get_dai_sel_r(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = max98925_dai_sel_r;
+	return 0;
+}
+
+static int max98925_put_dai_sel_r(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	struct snd_soc_dapm_update update;
+	unsigned int reg = MAX98925_R02D_GAIN;
+	unsigned int mask = M98925_DAC_IN_SEL_MASK;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		regmap_update_bits(max98925->regmap_r,
+			reg, mask, M98925_DAC_IN_SEL_LEFT_DAI);
+		break;
+	case 1:
+		regmap_update_bits(max98925->regmap_r,
+			reg, mask, M98925_DAC_IN_SEL_RIGHT_DAI);
+		break;
+	case 2:
+		regmap_update_bits(max98925->regmap_r,
+			reg, mask, M98925_DAC_IN_SEL_SUMMED_DAI);
+		break;
+	case 3:
+		regmap_update_bits(max98925->regmap_r,
+			reg, mask, M98925_DAC_IN_SEL_DIV2_SUMMED_DAI);
+		break;
+	default:
+		return -EINVAL;
+	}
+	max98925_dai_sel_r = ucontrol->value.integer.value[0];
+	update.kcontrol = kcontrol;
+	update.reg = SND_SOC_NOPM;
+	snd_soc_dapm_mux_update_power(&codec->dapm,
+				kcontrol, max98925_dai_sel_r, e, &update);
+	return 0;
+}
+
+static int max98925_reg_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol, unsigned int reg,
+		unsigned int mask, unsigned int shift)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int sel = ucontrol->value.integer.value[0];
+
+	max98925_regmap_update_bits_stereo(max98925, reg, mask, sel << shift);
+	dev_dbg(codec->dev, "%s: register 0x%02X, value 0x%02X\n",
+				__func__, reg, sel);
+	return 0;
+}
+
+static int max98925_dac_ev_l(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	regmap_update_bits(max98925->regmap_l, MAX98925_R036_BLOCK_ENABLE,
+			M98925_SPK_EN_MASK, M98925_SPK_EN_MASK);
+	return 0;
+}
+
+static int max98925_dac_ev_r(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	regmap_update_bits(max98925->regmap_r, MAX98925_R036_BLOCK_ENABLE,
+			M98925_SPK_EN_MASK, M98925_SPK_EN_MASK);
+	return 0;
+}
+
+static const struct snd_kcontrol_new dai_sel_mux[2] = {
+	SOC_DAPM_ENUM_EXT("DAI_IN_MUX_L Mux", max98925_dai_l_enum,
+			  max98925_get_dai_sel_l, max98925_put_dai_sel_l),
+	SOC_DAPM_ENUM_EXT("DAI_IN_MUX_R Mux", max98925_dai_r_enum,
+			  max98925_get_dai_sel_r, max98925_put_dai_sel_r),
+};
+
+static const struct snd_kcontrol_new hpf_mux[2] = {
+	SOC_ENUM_EXT("R02C_FILTER_R Mux", max98925_hpfout_r_enum,
+		max98925_get_hpf_r, max98925_put_hpf_r),
+	SOC_ENUM_EXT("R02C_FILTER_L Mux", max98925_hpfout_l_enum,
+		max98925_get_hpf_l, max98925_put_hpf_l),
+};
+
+static const struct snd_soc_dapm_widget max98925_dapm_widgets[] = {
+	SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_MUX("DAI_IN_MUX_L MUX", SND_SOC_NOPM, 0, 0,
+				&dai_sel_mux[0]),
+	SND_SOC_DAPM_MUX("DAI_IN_MUX_R MUX", SND_SOC_NOPM, 0, 0,
+				&dai_sel_mux[1]),
+	SND_SOC_DAPM_MUX("R02C_FILTER_L MUX", SND_SOC_NOPM, 0, 0,
+				&hpf_mux[0]),
+	SND_SOC_DAPM_MUX("R02C_FILTER_R MUX", SND_SOC_NOPM, 0, 0,
+				&hpf_mux[1]),
+	SND_SOC_DAPM_DAC_E("amp_enable_l", NULL,
+			SND_SOC_NOPM, 0, 0,
+			max98925_dac_ev_l, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_DAC_E("amp_enable_r", NULL,
+			SND_SOC_NOPM, 0, 0,
+			max98925_dac_ev_r, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_OUTPUT("BE_OUT"),
+};
+
+static const struct snd_soc_dapm_route max98925_audio_map[] = {
+	{"DAI_IN_MUX_L MUX", "L_Data", "DAI_OUT"},
+	{"DAI_IN_MUX_L MUX", "R_Data", "DAI_OUT"},
+	{"DAI_IN_MUX_L MUX", "LR_Data", "DAI_OUT"},
+	{"DAI_IN_MUX_L MUX", "LR_Data_Div2", "DAI_OUT"},
+	{"R02C_FILTER_L MUX", "hpf_disable", "DAI_IN_MUX_L MUX"},
+	{"R02C_FILTER_L MUX", "hpf_dc_block", "DAI_IN_MUX_L MUX"},
+	{"R02C_FILTER_L MUX", "hpf_enable_100", "DAI_IN_MUX_L MUX"},
+	{"R02C_FILTER_L MUX", "hpf_enable_200", "DAI_IN_MUX_L MUX"},
+	{"R02C_FILTER_L MUX", "hpf_enable_400", "DAI_IN_MUX_L MUX"},
+	{"R02C_FILTER_L MUX", "hpf_enable_800", "DAI_IN_MUX_L MUX"},
+	{"amp_enable_l", NULL, "R02C_FILTER_L MUX"},
+	{"BE_OUT", NULL, "amp_enable_l"},
+
+	{"DAI_IN_MUX_R MUX", "L_Data", "DAI_OUT"},
+	{"DAI_IN_MUX_R MUX", "R_Data", "DAI_OUT"},
+	{"DAI_IN_MUX_R MUX", "LR_Data", "DAI_OUT"},
+	{"DAI_IN_MUX_R MUX", "LR_Data_Div2", "DAI_OUT"},
+	{"R02C_FILTER_R MUX", "hpf_disable", "DAI_IN_MUX_R MUX"},
+	{"R02C_FILTER_R MUX", "hpf_dc_block", "DAI_IN_MUX_R MUX"},
+	{"R02C_FILTER_R MUX", "hpf_enable_100", "DAI_IN_MUX_R MUX"},
+	{"R02C_FILTER_R MUX", "hpf_enable_200", "DAI_IN_MUX_R MUX"},
+	{"R02C_FILTER_R MUX", "hpf_enable_400", "DAI_IN_MUX_R MUX"},
+	{"R02C_FILTER_R MUX", "hpf_enable_800", "DAI_IN_MUX_R MUX"},
+	{"amp_enable_r", NULL, "R02C_FILTER_R MUX"},
+	{"BE_OUT", NULL, "amp_enable_r"},
+};
+
+void max98925_regmap_write_stereo(struct max98925_priv *max98925,
+	unsigned int reg, unsigned int val)
+{
+	regmap_write(max98925->regmap_l, reg, val);
+	regmap_write(max98925->regmap_r, reg, val);
+}
+
+static bool max98925_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_R000_VBAT_DATA:
+	case MAX98925_R001_VBST_DATA:
+	case MAX98925_R002_LIVE_STATUS0:
+	case MAX98925_R003_LIVE_STATUS1:
+	case MAX98925_R004_LIVE_STATUS2:
+	case MAX98925_R005_STATE0:
+	case MAX98925_R006_STATE1:
+	case MAX98925_R007_STATE2:
+	case MAX98925_R008_FLAG0:
+	case MAX98925_R009_FLAG1:
+	case MAX98925_R00A_FLAG2:
+	case MAX98925_R0FF_VERSION:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max98925_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX98925_R00E_IRQ_CLEAR0:
+	case MAX98925_R00F_IRQ_CLEAR1:
+	case MAX98925_R010_IRQ_CLEAR2:
+	case MAX98925_R033_ALC_HOLD_RLS:
+		return false;
+	default:
+		return true;
+	}
+};
+
+DECLARE_TLV_DB_SCALE(max98925_spk_tlv, -600, 100, 0);
+static int reg_set_optimum_mode_check(struct regulator *reg, int load_ua)
+{
+	return (regulator_count_voltages(reg) > 0) ?
+		regulator_set_optimum_mode(reg, load_ua) : 0;
+}
+
+static int max98925_regulator_config(struct i2c_client *i2c,
+		bool pullup, bool on)
+{
+	struct regulator *max98925_vcc_i2c;
+	int rc;
+
+	if (pullup) {
+		pr_info("%s: i2c pull up\n", __func__);
+		max98925_vcc_i2c = regulator_get(&i2c->dev, "vcc_i2c");
+		if (IS_ERR(max98925_vcc_i2c)) {
+			rc = PTR_ERR(max98925_vcc_i2c);
+			pr_err("%s: regulator get failed rc=%d\n",
+						__func__, rc);
+			goto error_get_vtg_i2c;
+		}
+		if (regulator_count_voltages(max98925_vcc_i2c) > 0) {
+			rc = regulator_set_voltage(max98925_vcc_i2c,
+				VCC_I2C_MIN_UV, VCC_I2C_MAX_UV);
+			if (rc) {
+				pr_err("%s: regulator set_vtg failed rc=%d\n",
+						__func__, rc);
+				goto error_set_vtg_i2c;
+			}
+		}
+
+		rc = reg_set_optimum_mode_check(max98925_vcc_i2c, I2C_LOAD_UA);
+		if (rc < 0) {
+			pr_err("%s: regulator vcc_i2c set_opt failed rc=%d\n",
+						__func__, rc);
+			goto error_reg_opt_i2c;
+		}
+
+		rc = regulator_enable(max98925_vcc_i2c);
+		if (rc) {
+			pr_err("%s: regulator vcc_i2c enable failed rc=%d\n",
+						__func__, rc);
+			goto error_reg_en_vcc_i2c;
+		}
+
+	}
+	return 0;
+error_set_vtg_i2c:
+	regulator_put(max98925_vcc_i2c);
+error_get_vtg_i2c:
+	if (regulator_count_voltages(max98925_vcc_i2c) > 0)
+		regulator_set_voltage(max98925_vcc_i2c, 0,
+			VCC_I2C_MAX_UV);
+error_reg_en_vcc_i2c:
+	if (pullup)
+		reg_set_optimum_mode_check(max98925_vcc_i2c, 0);
+error_reg_opt_i2c:
+	regulator_disable(max98925_vcc_i2c);
+	return rc;
+}
+
+static int max98925_spk_gain_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = max98925->spk_gain;
+	dev_dbg(codec->dev, "%s: spk_gain setting returned %d\n", __func__,
+				(int) ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int max98925_spk_gain_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	unsigned int sel = ucontrol->value.integer.value[0];
+
+	if (sel < ((1 << M98925_SPK_GAIN_WIDTH) - 1)) {
+		max98925_regmap_update_bits_stereo(max98925, MAX98925_R02D_GAIN,
+			M98925_SPK_GAIN_MASK, sel << M98925_SPK_GAIN_SHIFT);
+		max98925->spk_gain = sel;
+
+		dev_dbg(codec->dev, "%s: spk_gain set to %d\n", __func__, sel);
+	} else {
+		dev_dbg(codec->dev, "%s: valid speaker gain settings: %d to %d\n",
+			__func__, 0,
+			((1 << M98925_SPK_GAIN_WIDTH) - 1));
+	}
+	return 0;
+}
+
+static int max98925_reg_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol, unsigned int reg,
+		unsigned int mask, unsigned int shift)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	int data;
+
+	regmap_read(max98925->regmap_l, reg, &data);
+	ucontrol->value.integer.value[0] =
+		(data & mask) >> shift;
+	return 0;
+}
+
+static int max98925_spk_ramp_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_RMP_EN_MASK, M98925_SPK_RMP_EN_SHIFT);
+}
+
+static int max98925_spk_ramp_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_RMP_EN_MASK, M98925_SPK_RMP_EN_SHIFT);
+}
+
+static int max98925_spk_zcd_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_ZCD_EN_MASK, M98925_SPK_ZCD_EN_SHIFT);
+}
+
+static int max98925_spk_zcd_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R02E_GAIN_RAMPING,
+			M98925_SPK_ZCD_EN_MASK, M98925_SPK_ZCD_EN_SHIFT);
+}
+
+static int max98925_alc_en_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_EN_MASK, M98925_ALC_EN_SHIFT);
+}
+
+static int max98925_alc_en_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_EN_MASK, M98925_ALC_EN_SHIFT);
+}
+
+static int max98925_alc_threshold_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_TH_MASK, M98925_ALC_TH_SHIFT);
+}
+
+static int max98925_alc_threshold_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R030_THRESHOLD,
+			M98925_ALC_TH_MASK, M98925_ALC_TH_SHIFT);
+}
+
+static const char * const max98925_boost_voltage_text[] = {"8.5V", "8.25V",
+		"8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V",
+		"6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V",
+		"6.5V", "6.5V"};
+
+static const struct soc_enum max98925_boost_voltage_enum =
+	SOC_ENUM_SINGLE(MAX98925_R037_CONFIGURATION, M98925_BST_VOUT_SHIFT, 15,
+			max98925_boost_voltage_text);
+
+static int max98925_boost_voltage_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_get(kcontrol, ucontrol, MAX98925_R037_CONFIGURATION,
+			M98925_BST_VOUT_MASK, M98925_BST_VOUT_SHIFT);
+}
+
+static int max98925_boost_voltage_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	return max98925_reg_put(kcontrol, ucontrol, MAX98925_R037_CONFIGURATION,
+			M98925_BST_VOUT_MASK, M98925_BST_VOUT_SHIFT);
+}
+
+static const struct snd_kcontrol_new max98925_snd_controls[] = {
+
+	SOC_SINGLE_EXT_TLV("Speaker Gain", MAX98925_R02D_GAIN,
+		M98925_SPK_GAIN_SHIFT, (1<<M98925_SPK_GAIN_WIDTH)-1, 0,
+		max98925_spk_gain_get, max98925_spk_gain_put, max98925_spk_tlv),
+
+	SOC_SINGLE_EXT("Speaker Ramp", 0, 0, 1, 0,
+		max98925_spk_ramp_get, max98925_spk_ramp_put),
+
+	SOC_SINGLE_EXT("Speaker ZCD", 0, 0, 1, 0,
+		max98925_spk_zcd_get, max98925_spk_zcd_put),
+
+	SOC_SINGLE_EXT("ALC Enable", 0, 0, 1, 0,
+		max98925_alc_en_get, max98925_alc_en_put),
+
+	SOC_SINGLE_EXT("ALC Threshold", 0, 0, (1<<M98925_ALC_TH_WIDTH)-1, 0,
+		max98925_alc_threshold_get, max98925_alc_threshold_put),
+
+	SOC_ENUM_EXT("Boost Output Voltage", max98925_boost_voltage_enum,
+		max98925_boost_voltage_get, max98925_boost_voltage_put),
+};
+
+/* codec sample rate and n/m dividers parameter table */
+static const struct {
+	int rate;
+	int  sr;
+	int divisors[3][2];
+} rate_table[] = {
+	{
+		.rate = 8000,
+		.sr = 0,
+		.divisors = { {1, 375}, {5, 1764}, {1, 384} }
+	},
+	{
+		.rate = 11025,
+		.sr = 1,
+		.divisors = { {147, 40000}, {1, 256}, {147, 40960} }
+	},
+	{
+		.rate = 12000,
+		.sr = 2,
+		.divisors = { {1, 250}, {5, 1176}, {1, 256} }
+	},
+	{
+		.rate = 16000,
+		.sr = 3,
+		.divisors = { {2, 375}, {5, 882}, {1, 192} }
+	},
+	{
+		.rate = 22050,
+		.sr = 4,
+		.divisors = { {147, 20000}, {1, 128}, {147, 20480} }
+	},
+	{
+		.rate = 24000,
+		.sr = 5,
+		.divisors = { {1, 125}, {5, 588}, {1, 128} }
+	},
+	{
+		.rate = 32000,
+		.sr = 6,
+		.divisors = { {4, 375}, {5, 441}, {1, 96} }
+	},
+	{
+		.rate = 44100,
+		.sr = 7,
+		.divisors = { {147, 10000}, {1, 64}, {147, 10240} }
+	},
+	{
+		.rate = 48000,
+		.sr = 8,
+		.divisors = { {2, 125}, {5, 294}, {1, 64} }
+	},
+};
+
+static inline int max98925_rate_value(int rate,
+		int clock, int *value, int *n, int *m)
+{
+	int ret = -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+		if (rate_table[i].rate >= rate) {
+			*value = rate_table[i].sr;
+			*n = rate_table[i].divisors[clock][0];
+			*m = rate_table[i].divisors[clock][1];
+			ret = 0;
+			break;
+		}
+	}
+	pr_debug("%s: sample rate is %d, returning %d\n",
+				__func__, rate_table[i].rate, *value);
+	return ret;
+}
+
+static void max98925_set_sense_data(struct max98925_priv *max98925)
+{
+	/*
+	 * 1. set VMON slots
+	 */
+	regmap_update_bits(max98925->regmap_l,
+		MAX98925_R022_DOUT_CFG_VMON,
+		M98925_DAI_VMON_EN_MASK, M98925_DAI_VMON_EN_MASK);
+	regmap_update_bits(max98925->regmap_l,
+		MAX98925_R022_DOUT_CFG_VMON,
+		M98925_DAI_VMON_SLOT_MASK, M98925_DAI_VMON_SLOT_00_01);
+	/*
+	 * 2. set IMON slots
+	 */
+	regmap_update_bits(max98925->regmap_l,
+		MAX98925_R023_DOUT_CFG_IMON,
+		M98925_DAI_IMON_EN_MASK, M98925_DAI_IMON_EN_MASK);
+	regmap_update_bits(max98925->regmap_l,
+		MAX98925_R023_DOUT_CFG_IMON,
+		M98925_DAI_IMON_SLOT_MASK, M98925_DAI_IMON_SLOT_02_03);
+}
+
+static void max98925_set_slave(struct max98925_priv *max98925)
+{
+	/*
+	 * 1. use BCLK instead of MCLK
+	 */
+	max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R01A_DAI_CLK_MODE1,
+			M98925_DAI_CLK_SOURCE_MASK, M98925_DAI_CLK_SOURCE_MASK);
+	/*
+	 * 2. set DAI to slave mode
+	 */
+	max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, 0);
+	/*
+	 * 3. set BLCKs to LRCLKs to 64
+	 */
+	max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
+
+	max98925_set_sense_data(max98925);
+}
+
+static void max98925_set_master(struct max98925_priv *max98925)
+{
+	/*
+	 * 1. use MCLK for Left channel, right channel always BCLK
+	 */
+	regmap_update_bits(max98925->regmap_l,
+			MAX98925_R01A_DAI_CLK_MODE1,
+			M98925_DAI_CLK_SOURCE_MASK, 0);
+	regmap_update_bits(max98925->regmap_r,
+			MAX98925_R01A_DAI_CLK_MODE1,
+			M98925_DAI_CLK_SOURCE_MASK,
+			M98925_DAI_CLK_SOURCE_MASK);
+	/*
+	 * 2. set left channel DAI to master mode, right channel always slave
+	 */
+	regmap_update_bits(max98925->regmap_l,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, M98925_DAI_MAS_MASK);
+	regmap_update_bits(max98925->regmap_r,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_MAS_MASK, 0);
+}
+
+static int max98925_dai_set_fmt(struct snd_soc_dai *codec_dai,
+				 unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct max98925_cdata *cdata;
+	unsigned int invert = 0;
+
+	dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
+	cdata = &max98925->dai[0];
+	cdata->fmt = fmt;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		max98925_set_slave(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		max98925_set_master(max98925);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFM:
+	case SND_SOC_DAIFMT_CBM_CFS:
+	default:
+		dev_err(codec->dev, "DAI clock mode unsupported");
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_LEFT_J:
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	default:
+		dev_err(codec->dev, "DAI format unsupported, fmt:0x%x", fmt);
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "DAI format supported, fmt:0x%x", fmt);
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		invert = M98925_DAI_WCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		invert = M98925_DAI_BCI_MASK;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		invert = M98925_DAI_BCI_MASK | M98925_DAI_WCI_MASK;
+		break;
+	default:
+		dev_err(codec->dev, "DAI invert mode unsupported");
+		return -EINVAL;
+	}
+
+	max98925_regmap_update_bits_stereo(max98925, MAX98925_R020_FORMAT,
+			M98925_DAI_BCI_MASK | M98925_DAI_BCI_MASK, invert);
+	return 0;
+}
+
+static int max98925_set_clock(struct max98925_priv *max98925,
+		unsigned int rate)
+{
+	unsigned int dai_sr = 0;
+	unsigned int clock;
+	unsigned int mdll;
+	unsigned int n;
+	unsigned int m;
+
+	switch (max98925->sysclk) {
+	case 6000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx16;
+		break;
+	case 11289600:
+		clock = 1;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12000000:
+		clock = 0;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	case 12288000:
+		clock = 2;
+		mdll  = M98925_MDLL_MULT_MCLKx8;
+		break;
+	default:
+		dev_info(max98925->codec->dev, "unsupported sysclk %d\n",
+					max98925->sysclk);
+		return -EINVAL;
+	}
+
+	if (max98925_rate_value(rate, clock, &dai_sr, &n, &m))
+		return -EINVAL;
+
+	/*
+	 * 1. set DAI_SR to correct LRCLK frequency
+	 */
+	max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R01B_DAI_CLK_MODE2,
+			M98925_DAI_SR_MASK, dai_sr << M98925_DAI_SR_SHIFT);
+	/*
+	 * 2. set DAI m divider
+	 */
+	regmap_write(max98925->regmap_l,
+		MAX98925_R01C_DAI_CLK_DIV_M_MSBS, m >> 8);
+	regmap_write(max98925->regmap_l,
+		MAX98925_R01D_DAI_CLK_DIV_M_LSBS, m & 0xFF);
+	/*
+	 * 3. set DAI n divider
+	 */
+	regmap_write(max98925->regmap_l,
+		MAX98925_R01E_DAI_CLK_DIV_N_MSBS, n >> 8);
+	regmap_write(max98925->regmap_l,
+		MAX98925_R01F_DAI_CLK_DIV_N_LSBS, n & 0xFF);
+	/*
+	 * 4. set MDLL
+	 */
+	max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R01A_DAI_CLK_MODE1,
+			M98925_MDLL_MULT_MASK, mdll << M98925_MDLL_MULT_SHIFT);
+	return 0;
+}
+
+static int max98925_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 max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct max98925_cdata *cdata;
+	unsigned int rate;
+
+	cdata = &max98925->dai[0];
+	rate = params_rate(params);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		max98925_regmap_update_bits_stereo(max98925,
+				MAX98925_R020_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_16);
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		max98925_regmap_update_bits_stereo(max98925,
+				MAX98925_R020_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		dev_dbg(codec->dev, "%s: (really set to 32 bits)\n", __func__);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		max98925_regmap_update_bits_stereo(max98925,
+				MAX98925_R020_FORMAT,
+				M98925_DAI_CHANSZ_MASK, M98925_DAI_CHANSZ_32);
+		break;
+	default:
+		pr_err("%s: format unsupported %d",
+				__func__, params_format(params));
+		return -EINVAL;
+	}
+	dev_dbg(codec->dev, "%s: format supported %d",
+				__func__, params_format(params));
+	return max98925_set_clock(max98925, rate);
+}
+
+static int max98925_dai_set_sysclk(struct snd_soc_dai *dai,
+				   int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+
+	dev_dbg(codec->dev, "%s: clk_id %d, freq %d, dir %d\n",
+				__func__, clk_id, freq, dir);
+	max98925->sysclk = freq;
+	return 0;
+}
+
+static int max98925_dai_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+	struct max98925_priv *max98925 =
+				snd_soc_codec_get_drvdata(codec_dai->codec);
+	struct snd_soc_codec *codec = codec_dai->codec;
+
+	dev_dbg(codec->dev, "%s: mute %d\n", __func__, mute);
+	if (mute) {
+		max98925_regmap_update_bits_stereo(max98925, MAX98925_R02D_GAIN,
+			M98925_SPK_GAIN_MASK, 0x00);
+
+		max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R038_GLOBAL_ENABLE,
+			M98925_EN_MASK, 0x0);
+	} else	{
+		max98925_regmap_update_bits_stereo(max98925,
+			MAX98925_R036_BLOCK_ENABLE,
+			M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK,
+			M98925_BST_EN_MASK |
+			M98925_ADC_IMON_EN_MASK | M98925_ADC_VMON_EN_MASK);
+
+		max98925_regmap_write_stereo(max98925,
+			MAX98925_R038_GLOBAL_ENABLE, M98925_EN_MASK);
+	}
+	return 0;
+}
+
+#define MAX98925_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops max98925_dai_ops = {
+	.set_sysclk = max98925_dai_set_sysclk,
+	.set_fmt = max98925_dai_set_fmt,
+	.hw_params = max98925_dai_hw_params,
+	.digital_mute = max98925_dai_digital_mute,
+};
+
+static struct snd_soc_dai_driver max98925_dai[] = {
+	{
+		.name = "max98925-aif1",
+		.playback = {
+			.stream_name = "HiFi Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.capture = {
+			.stream_name = "HiFi Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = MAX98925_FORMATS,
+		},
+		.ops = &max98925_dai_ops,
+	}
+};
+
+static int max98925_probe(struct snd_soc_codec *codec)
+{
+	struct max98925_priv *max98925 = snd_soc_codec_get_drvdata(codec);
+	struct max98925_cdata *cdata;
+	int ret = 0;
+	int reg = 0;
+
+	dev_info(codec->dev, "build number %s\n", MAX98925_REVISION);
+
+	max98925->codec = codec;
+	codec->control_data = max98925->regmap_l;
+	/* can be configured to any other value supported by this chip */
+	max98925->sysclk = 12288000;
+	max98925->spk_gain = 0x14;
+	cdata = &max98925->dai[0];
+	cdata->rate = (unsigned)-1;
+	cdata->fmt  = (unsigned)-1;
+
+	reg = 0;
+	ret = regmap_read(max98925->regmap_l,
+			MAX98925_R0FF_VERSION, &reg);
+	if ((ret < 0) ||
+		((reg != MAX98925_VERSION) &&
+		(reg != MAX98925_VERSION1))) {
+		dev_err(codec->dev,
+			"L device initialization error (%d 0x%02X)\n",
+			ret, reg);
+		goto err_access;
+	}
+	dev_info(codec->dev, "L device version 0x%02X\n", reg);
+
+	reg = 0;
+	ret = regmap_read(max98925->regmap_r,
+			MAX98925_R0FF_VERSION, &reg);
+	if ((ret < 0) || ((reg != MAX98925_VERSION)
+			&& (reg != MAX98925_VERSION1))) {
+		dev_err(codec->dev,
+			"R device initialization error (%d 0x%02X)\n",
+			ret, reg);
+		goto err_access;
+	}
+	dev_info(codec->dev, "R device version 0x%02X\n", reg);
+	max98925_regmap_write_stereo(max98925,
+				MAX98925_R038_GLOBAL_ENABLE, 0x00);
+
+	/* It's not the default but we need to set DAI_DLY */
+		max98925_regmap_write_stereo(max98925,
+				MAX98925_R020_FORMAT, M98925_DAI_DLY_MASK);
+		max98925_regmap_write_stereo(max98925,
+				MAX98925_R021_TDM_SLOT_SELECT, 0xC8);
+		max98925_regmap_write_stereo(max98925,
+				MAX98925_R027_DOUT_HIZ_CFG1, 0xFF);
+		max98925_regmap_write_stereo(max98925,
+				MAX98925_R028_DOUT_HIZ_CFG2, 0xFF);
+		max98925_regmap_write_stereo(max98925,
+				MAX98925_R029_DOUT_HIZ_CFG3, 0xFF);
+	regmap_write(max98925->regmap_l,
+				MAX98925_R02A_DOUT_HIZ_CFG4, 0xF0);
+	regmap_write(max98925->regmap_r,
+				MAX98925_R02A_DOUT_HIZ_CFG4, 0x0F);
+
+	max98925_regmap_write_stereo(max98925,
+			MAX98925_R02C_FILTERS, 0xD8);
+	max98925_regmap_write_stereo(max98925,
+			MAX98925_R034_ALC_CONFIGURATION, 0xF8);
+	max98925_regmap_write_stereo(max98925,
+			MAX98925_R037_CONFIGURATION, 0xF0);
+
+	/* Disable ALC muting */
+		max98925_regmap_write_stereo(max98925,
+		MAX98925_R03A_BOOST_LIMITER, 0xF8);
+
+	regmap_update_bits(max98925->regmap_l, MAX98925_R02D_GAIN,
+			M98925_DAC_IN_SEL_MASK, M98925_DAC_IN_SEL_LEFT_DAI);
+	regmap_update_bits(max98925->regmap_r, MAX98925_R02D_GAIN,
+			M98925_DAC_IN_SEL_MASK, M98925_DAC_IN_SEL_RIGHT_DAI);
+
+err_access:
+	return ret;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98925 = {
+	.probe            = max98925_probe,
+	.controls = max98925_snd_controls,
+	.num_controls = ARRAY_SIZE(max98925_snd_controls),
+	.dapm_routes = max98925_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(max98925_audio_map),
+	.dapm_widgets = max98925_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(max98925_dapm_widgets),
+};
+
+static struct regmap_config max98925_regmap = {
+	.reg_bits         = 8,
+	.val_bits         = 8,
+	.max_register     = MAX98925_R0FF_VERSION,
+	.reg_defaults     = max98925_reg,
+	.num_reg_defaults = ARRAY_SIZE(max98925_reg),
+	.volatile_reg     = max98925_volatile_register,
+	.readable_reg     = max98925_readable_register,
+	.cache_type       = REGCACHE_RBTREE,
+};
+
+static int max98925_i2c_probe(struct i2c_client *i2c,
+			     const struct i2c_device_id *id)
+{
+	int ret = 0;
+
+	dev_info(&i2c->dev, "%s: enter, device '%s'\n", __func__, id->name);
+	if (!max98925) {
+		max98925 = devm_kzalloc(&i2c->dev,
+				sizeof(*max98925), GFP_KERNEL);
+		if (!max98925)
+			return -ENOMEM;
+	}
+	i2c_set_clientdata(i2c, max98925);
+	if (id->driver_data == MAX98925L) {
+		max98925->regmap_l =
+				devm_regmap_init_i2c(i2c, &max98925_regmap);
+		if (IS_ERR(max98925->regmap_l)) {
+			ret = PTR_ERR(max98925->regmap_l);
+			dev_err(&i2c->dev,
+				"Failed to allocate regmap_l: %d\n", ret);
+			goto err_out;
+		}
+	}
+
+	/* Check for second MAX98925 */
+	if (id->driver_data == MAX98925R) {
+		max98925->regmap_r =
+				devm_regmap_init_i2c(i2c, &max98925_regmap);
+		if (IS_ERR(max98925->regmap_r)) {
+			ret = PTR_ERR(max98925->regmap_r);
+			dev_err(&i2c->dev,
+				"Failed to allocate regmap_r: %d\n", ret);
+			goto err_out;
+		}
+	}
+	if (max98925->regmap_r && max98925->regmap_l) {
+		max98925_regulator_config(i2c,
+			of_property_read_bool(i2c->dev.of_node,
+			"max98925,i2c-pull-up"), 1);
+		ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925,
+			max98925_dai, ARRAY_SIZE(max98925_dai));
+		if (ret < 0)
+			dev_err(&i2c->dev,
+				"Failed to register codec: %d\n", ret);
+	}
+err_out:
+	return ret;
+}
+
+static int max98925_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id max98925_i2c_id[] = {
+	{ "max98925L", MAX98925L },
+	{ "max98925R", MAX98925R },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, max98925_i2c_id);
+
+static struct i2c_driver max98925_i2c_driver = {
+	.driver = {
+		.name = "max98925",
+		.owner = THIS_MODULE,
+		.pm = NULL,
+	},
+	.probe  = max98925_i2c_probe,
+	.remove = max98925_i2c_remove,
+	.id_table = max98925_i2c_id,
+};
+
+module_i2c_driver(max98925_i2c_driver);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98925 Stereo driver");
+MODULE_AUTHOR("Ralph Birt <rdbirt@gmail.com>, Anish kumar <anish.kumar@maximintegrated.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98925.h b/sound/soc/codecs/max98925.h
new file mode 100644
index 0000000..36b42d4
--- /dev/null
+++ b/sound/soc/codecs/max98925.h
@@ -0,0 +1,845 @@
+/*
+ * max98925.h -- MAX98925 ALSA SoC Audio driver
+ *
+ * Copyright 2013-2015 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX98925_H
+#define _MAX98925_H
+
+/* Maximum number of MAX98925 devices in the system this driver can support */
+#define MAX_NUM_MAX98925	2
+#define	MAX98925_VERSION	0x51
+#define	MAX98925_VERSION1	0x80
+
+#define MAX98925_REVISION	"0.00.0333"
+
+/*
+ * MAX98925 Register Definitions
+ */
+#define MAX98925_R000_VBAT_DATA			0x00
+#define MAX98925_R001_VBST_DATA			0x01
+#define MAX98925_R002_LIVE_STATUS0		0x02
+#define MAX98925_R003_LIVE_STATUS1		0x03
+#define MAX98925_R004_LIVE_STATUS2		0x04
+#define MAX98925_R005_STATE0			0x05
+#define MAX98925_R006_STATE1			0x06
+#define MAX98925_R007_STATE2			0x07
+#define MAX98925_R008_FLAG0			0x08
+#define MAX98925_R009_FLAG1			0x09
+#define MAX98925_R00A_FLAG2			0x0A
+#define MAX98925_R00B_IRQ_ENABLE0		0x0B
+#define MAX98925_R00C_IRQ_ENABLE1		0x0C
+#define MAX98925_R00D_IRQ_ENABLE2		0x0D
+#define MAX98925_R00E_IRQ_CLEAR0		0x0E
+#define MAX98925_R00F_IRQ_CLEAR1		0x0F
+#define MAX98925_R010_IRQ_CLEAR2		0x10
+#define MAX98925_R011_MAP0			0x11
+#define MAX98925_R012_MAP1			0x12
+#define MAX98925_R013_MAP2			0x13
+#define MAX98925_R014_MAP3			0x14
+#define MAX98925_R015_MAP4			0x15
+#define MAX98925_R016_MAP5			0x16
+#define MAX98925_R017_MAP6			0x17
+#define MAX98925_R018_MAP7			0x18
+#define MAX98925_R019_MAP8			0x19
+#define MAX98925_R01A_DAI_CLK_MODE1		0x1A
+#define MAX98925_R01B_DAI_CLK_MODE2		0x1B
+#define MAX98925_R01C_DAI_CLK_DIV_M_MSBS	0x1C
+#define MAX98925_R01D_DAI_CLK_DIV_M_LSBS	0x1D
+#define MAX98925_R01E_DAI_CLK_DIV_N_MSBS	0x1E
+#define MAX98925_R01F_DAI_CLK_DIV_N_LSBS	0x1F
+#define MAX98925_R020_FORMAT			0x20
+#define MAX98925_R021_TDM_SLOT_SELECT		0x21
+#define MAX98925_R022_DOUT_CFG_VMON		0x22
+#define MAX98925_R023_DOUT_CFG_IMON		0x23
+#define MAX98925_R024_DOUT_CFG_VBAT		0x24
+#define MAX98925_R025_DOUT_CFG_VBST		0x25
+#define MAX98925_R026_DOUT_CFG_FLAG		0x26
+#define MAX98925_R027_DOUT_HIZ_CFG1		0x27
+#define MAX98925_R028_DOUT_HIZ_CFG2		0x28
+#define MAX98925_R029_DOUT_HIZ_CFG3		0x29
+#define MAX98925_R02A_DOUT_HIZ_CFG4		0x2A
+#define MAX98925_R02B_DOUT_DRV_STRENGTH		0x2B
+#define MAX98925_R02C_FILTERS			0x2C
+#define MAX98925_R02D_GAIN			0x2D
+#define MAX98925_R02E_GAIN_RAMPING		0x2E
+#define MAX98925_R02F_SPK_AMP			0x2F
+#define MAX98925_R030_THRESHOLD			0x30
+#define MAX98925_R031_ALC_ATTACK		0x31
+#define MAX98925_R032_ALC_ATTEN_RLS		0x32
+#define MAX98925_R033_ALC_HOLD_RLS		0x33
+#define MAX98925_R034_ALC_CONFIGURATION		0x34
+#define MAX98925_R035_BOOST_CONVERTER		0x35
+#define MAX98925_R036_BLOCK_ENABLE		0x36
+#define MAX98925_R037_CONFIGURATION		0x37
+#define MAX98925_R038_GLOBAL_ENABLE		0x38
+#define MAX98925_R03A_BOOST_LIMITER		0x3A
+#define MAX98925_R0FF_VERSION			0xFF
+
+#define MAX98925_REG_CNT               (MAX98925_R03A_BOOST_LIMITER+1)
+
+/* MAX98925 Register Bit Fields */
+
+/* MAX98925_R002_LIVE_STATUS0 */
+#define M98925_THERMWARN_STATUS_MASK			(1<<3)
+#define M98925_THERMWARN_STATUS_SHIFT			3
+#define M98925_THERMWARN_STATUS_WIDTH			1
+#define M98925_THERMSHDN_STATUS_MASK			(1<<1)
+#define M98925_THERMSHDN_STATUS_SHIFT			1
+#define M98925_THERMSHDN_STATUS_WIDTH			1
+
+/* MAX98925_R003_LIVE_STATUS1 */
+#define M98925_SPKCURNT_STATUS_MASK				(1<<5)
+#define M98925_SPKCURNT_STATUS_SHIFT			5
+#define M98925_SPKCURNT_STATUS_WIDTH			1
+#define M98925_WATCHFAIL_STATUS_MASK			(1<<4)
+#define M98925_WATCHFAIL_STATUS_SHIFT			4
+#define M98925_WATCHFAIL_STATUS_WIDTH			1
+#define M98925_ALCINFH_STATUS_MASK				(1<<3)
+#define M98925_ALCINFH_STATUS_SHIFT				3
+#define M98925_ALCINFH_STATUS_WIDTH				1
+#define M98925_ALCACT_STATUS_MASK				(1<<2)
+#define M98925_ALCACT_STATUS_SHIFT				2
+#define M98925_ALCACT_STATUS_WIDTH				1
+#define M98925_ALCMUT_STATUS_MASK				(1<<1)
+#define M98925_ALCMUT_STATUS_SHIFT				1
+#define M98925_ALCMUT_STATUS_WIDTH				1
+#define M98925_ACLP_STATUS_MASK					(1<<0)
+#define M98925_ACLP_STATUS_SHIFT				0
+#define M98925_ACLP_STATUS_WIDTH				1
+
+/* MAX98925_R004_LIVE_STATUS2 */
+#define M98925_SLOTOVRN_STATUS_MASK				(1<<6)
+#define M98925_SLOTOVRN_STATUS_SHIFT			6
+#define M98925_SLOTOVRN_STATUS_WIDTH			1
+#define M98925_INVALSLOT_STATUS_MASK			(1<<5)
+#define M98925_INVALSLOT_STATUS_SHIFT			5
+#define M98925_INVALSLOT_STATUS_WIDTH			1
+#define M98925_SLOTCNFLT_STATUS_MASK			(1<<4)
+#define M98925_SLOTCNFLT_STATUS_SHIFT			4
+#define M98925_SLOTCNFLT_STATUS_WIDTH			1
+#define M98925_VBSTOVFL_STATUS_MASK				(1<<3)
+#define M98925_VBSTOVFL_STATUS_SHIFT			3
+#define M98925_VBSTOVFL_STATUS_WIDTH			1
+#define M98925_VBATOVFL_STATUS_MASK				(1<<2)
+#define M98925_VBATOVFL_STATUS_SHIFT			2
+#define M98925_VBATOVFL_STATUS_WIDTH			1
+#define M98925_IMONOVFL_STATUS_MASK				(1<<1)
+#define M98925_IMONOVFL_STATUS_SHIFT			1
+#define M98925_IMONOVFL_STATUS_WIDTH			1
+#define M98925_VMONOVFL_STATUS_MASK				(1<<0)
+#define M98925_VMONOVFL_STATUS_SHIFT			0
+#define M98925_VMONOVFL_STATUS_WIDTH			1
+
+/* MAX98925_R005_STATE0 */
+#define M98925_THERMWARN_END_STATE_MASK			(1<<3)
+#define M98925_THERMWARN_END_STATE_SHIFT		3
+#define M98925_THERMWARN_END_STATE_WIDTH		1
+#define M98925_THERMWARN_BGN_STATE_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_STATE_SHIFT		1
+#define M98925_THERMWARN_BGN_STATE_WIDTH		1
+#define M98925_THERMSHDN_END_STATE_MASK			(1<<1)
+#define M98925_THERMSHDN_END_STATE_SHIFT		1
+#define M98925_THERMSHDN_END_STATE_WIDTH		1
+#define M98925_THERMSHDN_BGN_STATE_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_STATE_SHIFT		0
+#define M98925_THERMSHDN_BGN_STATE_WIDTH		1
+
+/* MAX98925_R006_STATE1 */
+#define M98925_SPRCURNT_STATE_MASK				(1<<5)
+#define M98925_SPRCURNT_STATE_SHIFT				5
+#define M98925_SPRCURNT_STATE_WIDTH				1
+#define M98925_WATCHFAIL_STATE_MASK				(1<<4)
+#define M98925_WATCHFAIL_STATE_SHIFT			4
+#define M98925_WATCHFAIL_STATE_WIDTH			1
+#define M98925_ALCINFH_STATE_MASK				(1<<3)
+#define M98925_ALCINFH_STATE_SHIFT				3
+#define M98925_ALCINFH_STATE_WIDTH				1
+#define M98925_ALCACT_STATE_MASK				(1<<2)
+#define M98925_ALCACT_STATE_SHIFT				2
+#define M98925_ALCACT_STATE_WIDTH				1
+#define M98925_ALCMUT_STATE_MASK				(1<<1)
+#define M98925_ALCMUT_STATE_SHIFT				1
+#define M98925_ALCMUT_STATE_WIDTH				1
+#define M98925_ALCP_STATE_MASK					(1<<0)
+#define M98925_ALCP_STATE_SHIFT					0
+#define M98925_ALCP_STATE_WIDTH					1
+
+/* MAX98925_R007_STATE2 */
+#define M98925_SLOTOVRN_STATE_MASK				(1<<6)
+#define M98925_SLOTOVRN_STATE_SHIFT				6
+#define M98925_SLOTOVRN_STATE_WIDTH				1
+#define M98925_INVALSLOT_STATE_MASK				(1<<5)
+#define M98925_INVALSLOT_STATE_SHIFT			5
+#define M98925_INVALSLOT_STATE_WIDTH			1
+#define M98925_SLOTCNFLT_STATE_MASK				(1<<4)
+#define M98925_SLOTCNFLT_STATE_SHIFT			4
+#define M98925_SLOTCNFLT_STATE_WIDTH			1
+#define M98925_VBSTOVFL_STATE_MASK				(1<<3)
+#define M98925_VBSTOVFL_STATE_SHIFT				3
+#define M98925_VBSTOVFL_STATE_WIDTH				1
+#define M98925_VBATOVFL_STATE_MASK				(1<<2)
+#define M98925_VBATOVFL_STATE_SHIFT				2
+#define M98925_VBATOVFL_STATE_WIDTH				1
+#define M98925_IMONOVFL_STATE_MASK				(1<<1)
+#define M98925_IMONOVFL_STATE_SHIFT				1
+#define M98925_IMONOVFL_STATE_WIDTH				1
+#define M98925_VMONOVFL_STATE_MASK				(1<<0)
+#define M98925_VMONOVFL_STATE_SHIFT				0
+#define M98925_VMONOVFL_STATE_WIDTH				1
+
+/* MAX98925_R008_FLAG0 */
+#define M98925_THERMWARN_END_FLAG_MASK			(1<<3)
+#define M98925_THERMWARN_END_FLAG_SHIFT			3
+#define M98925_THERMWARN_END_FLAG_WIDTH			1
+#define M98925_THERMWARN_BGN_FLAG_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_FLAG_SHIFT			2
+#define M98925_THERMWARN_BGN_FLAG_WIDTH			1
+#define M98925_THERMSHDN_END_FLAG_MASK			(1<<1)
+#define M98925_THERMSHDN_END_FLAG_SHIFT			1
+#define M98925_THERMSHDN_END_FLAG_WIDTH			1
+#define M98925_THERMSHDN_BGN_FLAG_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_FLAG_SHIFT			0
+#define M98925_THERMSHDN_BGN_FLAG_WIDTH			1
+
+/* MAX98925_R009_FLAG1 */
+#define M98925_SPKCURNT_FLAG_MASK				(1<<5)
+#define M98925_SPKCURNT_FLAG_SHIFT				5
+#define M98925_SPKCURNT_FLAG_WIDTH				1
+#define M98925_WATCHFAIL_FLAG_MASK				(1<<4)
+#define M98925_WATCHFAIL_FLAG_SHIFT				4
+#define M98925_WATCHFAIL_FLAG_WIDTH				1
+#define M98925_ALCINFH_FLAG_MASK				(1<<3)
+#define M98925_ALCINFH_FLAG_SHIFT				3
+#define M98925_ALCINFH_FLAG_WIDTH				1
+#define M98925_ALCACT_FLAG_MASK					(1<<2)
+#define M98925_ALCACT_FLAG_SHIFT				2
+#define M98925_ALCACT_FLAG_WIDTH				1
+#define M98925_ALCMUT_FLAG_MASK					(1<<1)
+#define M98925_ALCMUT_FLAG_SHIFT				1
+#define M98925_ALCMUT_FLAG_WIDTH				1
+#define M98925_ALCP_FLAG_MASK					(1<<0)
+#define M98925_ALCP_FLAG_SHIFT					0
+#define M98925_ALCP_FLAG_WIDTH					1
+
+/* MAX98925_R00A_FLAG2 */
+#define M98925_SLOTOVRN_FLAG_MASK				(1<<6)
+#define M98925_SLOTOVRN_FLAG_SHIFT				6
+#define M98925_SLOTOVRN_FLAG_WIDTH				1
+#define M98925_INVALSLOT_FLAG_MASK				(1<<5)
+#define M98925_INVALSLOT_FLAG_SHIFT				5
+#define M98925_INVALSLOT_FLAG_WIDTH				1
+#define M98925_SLOTCNFLT_FLAG_MASK				(1<<4)
+#define M98925_SLOTCNFLT_FLAG_SHIFT				4
+#define M98925_SLOTCNFLT_FLAG_WIDTH				1
+#define M98925_VBSTOVFL_FLAG_MASK				(1<<3)
+#define M98925_VBSTOVFL_FLAG_SHIFT				3
+#define M98925_VBSTOVFL_FLAG_WIDTH				1
+#define M98925_VBATOVFL_FLAG_MASK				(1<<2)
+#define M98925_VBATOVFL_FLAG_SHIFT				2
+#define M98925_VBATOVFL_FLAG_WIDTH				1
+#define M98925_IMONOVFL_FLAG_MASK				(1<<1)
+#define M98925_IMONOVFL_FLAG_SHIFT				1
+#define M98925_IMONOVFL_FLAG_WIDTH				1
+#define M98925_VMONOVFL_FLAG_MASK				(1<<0)
+#define M98925_VMONOVFL_FLAG_SHIFT				0
+#define M98925_VMONOVFL_FLAG_WIDTH				1
+
+/* MAX98925_R00B_IRQ_ENABLE0 */
+#define M98925_THERMWARN_END_EN_MASK			(1<<3)
+#define M98925_THERMWARN_END_EN_SHIFT			3
+#define M98925_THERMWARN_END_EN_WIDTH			1
+#define M98925_THERMWARN_BGN_EN_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_EN_SHIFT			2
+#define M98925_THERMWARN_BGN_EN_WIDTH			1
+#define M98925_THERMSHDN_END_EN_MASK			(1<<1)
+#define M98925_THERMSHDN_END_EN_SHIFT			1
+#define M98925_THERMSHDN_END_EN_WIDTH			1
+#define M98925_THERMSHDN_BGN_EN_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_EN_SHIFT			0
+#define M98925_THERMSHDN_BGN_EN_WIDTH			1
+
+/* MAX98925_R00C_IRQ_ENABLE1 */
+#define M98925_SPKCURNT_EN_MASK					(1<<5)
+#define M98925_SPKCURNT_EN_SHIFT				5
+#define M98925_SPKCURNT_EN_WIDTH				1
+#define M98925_WATCHFAIL_EN_MASK				(1<<4)
+#define M98925_WATCHFAIL_EN_SHIFT				4
+#define M98925_WATCHFAIL_EN_WIDTH				1
+#define M98925_ALCINFH_EN_MASK					(1<<3)
+#define M98925_ALCINFH_EN_SHIFT					3
+#define M98925_ALCINFH_EN_WIDTH					1
+#define M98925_ALCACT_EN_MASK					(1<<2)
+#define M98925_ALCACT_EN_SHIFT					2
+#define M98925_ALCACT_EN_WIDTH					1
+#define M98925_ALCMUT_EN_MASK					(1<<1)
+#define M98925_ALCMUT_EN_SHIFT					1
+#define M98925_ALCMUT_EN_WIDTH					1
+#define M98925_ALCP_EN_MASK						(1<<0)
+#define M98925_ALCP_EN_SHIFT					0
+#define M98925_ALCP_EN_WIDTH					1
+
+/* MAX98925_R00D_IRQ_ENABLE2 */
+#define M98925_SLOTOVRN_EN_MASK					(1<<6)
+#define M98925_SLOTOVRN_EN_SHIFT				6
+#define M98925_SLOTOVRN_EN_WIDTH				1
+#define M98925_INVALSLOT_EN_MASK				(1<<5)
+#define M98925_INVALSLOT_EN_SHIFT				5
+#define M98925_INVALSLOT_EN_WIDTH				1
+#define M98925_SLOTCNFLT_EN_MASK				(1<<4)
+#define M98925_SLOTCNFLT_EN_SHIFT				4
+#define M98925_SLOTCNFLT_EN_WIDTH				1
+#define M98925_VBSTOVFL_EN_MASK					(1<<3)
+#define M98925_VBSTOVFL_EN_SHIFT				3
+#define M98925_VBSTOVFL_EN_WIDTH				1
+#define M98925_VBATOVFL_EN_MASK					(1<<2)
+#define M98925_VBATOVFL_EN_SHIFT				2
+#define M98925_VBATOVFL_EN_WIDTH				1
+#define M98925_IMONOVFL_EN_MASK					(1<<1)
+#define M98925_IMONOVFL_EN_SHIFT				1
+#define M98925_IMONOVFL_EN_WIDTH				1
+#define M98925_VMONOVFL_EN_MASK					(1<<0)
+#define M98925_VMONOVFL_EN_SHIFT				0
+#define M98925_VMONOVFL_EN_WIDTH				1
+
+/* MAX98925_R00E_IRQ_CLEAR0 */
+#define M98925_THERMWARN_END_CLR_MASK			(1<<3)
+#define M98925_THERMWARN_END_CLR_SHIFT			3
+#define M98925_THERMWARN_END_CLR_WIDTH			1
+#define M98925_THERMWARN_BGN_CLR_MASK			(1<<2)
+#define M98925_THERMWARN_BGN_CLR_SHIFT			2
+#define M98925_THERMWARN_BGN_CLR_WIDTH			1
+#define M98925_THERMSHDN_END_CLR_MASK			(1<<1)
+#define M98925_THERMSHDN_END_CLR_SHIFT			1
+#define M98925_THERMSHDN_END_CLR_WIDTH			1
+#define M98925_THERMSHDN_BGN_CLR_MASK			(1<<0)
+#define M98925_THERMSHDN_BGN_CLR_SHIFT			0
+#define M98925_THERMSHDN_BGN_CLR_WIDTH			1
+
+/* MAX98925_R00F_IRQ_CLEAR1 */
+#define M98925_SPKCURNT_CLR_MASK				(1<<5)
+#define M98925_SPKCURNT_CLR_SHIFT				5
+#define M98925_SPKCURNT_CLR_WIDTH				1
+#define M98925_WATCHFAIL_CLR_MASK				(1<<4)
+#define M98925_WATCHFAIL_CLR_SHIFT				4
+#define M98925_WATCHFAIL_CLR_WIDTH				1
+#define M98925_ALCINFH_CLR_MASK					(1<<3)
+#define M98925_ALCINFH_CLR_SHIFT				3
+#define M98925_ALCINFH_CLR_WIDTH				1
+#define M98925_ALCACT_CLR_MASK					(1<<2)
+#define M98925_ALCACT_CLR_SHIFT					2
+#define M98925_ALCACT_CLR_WIDTH					1
+#define M98925_ALCMUT_CLR_MASK					(1<<1)
+#define M98925_ALCMUT_CLR_SHIFT					1
+#define M98925_ALCMUT_CLR_WIDTH					1
+#define M98925_ALCP_CLR_MASK					(1<<0)
+#define M98925_ALCP_CLR_SHIFT					0
+#define M98925_ALCP_CLR_WIDTH					1
+
+/* MAX98925_R010_IRQ_CLEAR2 */
+#define M98925_SLOTOVRN_CLR_MASK				(1<<6)
+#define M98925_SLOTOVRN_CLR_SHIFT				6
+#define M98925_SLOTOVRN_CLR_WIDTH				1
+#define M98925_INVALSLOT_CLR_MASK				(1<<5)
+#define M98925_INVALSLOT_CLR_SHIFT				5
+#define M98925_INVALSLOT_CLR_WIDTH				1
+#define M98925_SLOTCNFLT_CLR_MASK				(1<<4)
+#define M98925_SLOTCNFLT_CLR_SHIFT				4
+#define M98925_SLOTCNFLT_CLR_WIDTH				1
+#define M98925_VBSTOVFL_CLR_MASK				(1<<3)
+#define M98925_VBSTOVFL_CLR_SHIFT				3
+#define M98925_VBSTOVFL_CLR_WIDTH				1
+#define M98925_VBATOVFL_CLR_MASK				(1<<2)
+#define M98925_VBATOVFL_CLR_SHIFT				2
+#define M98925_VBATOVFL_CLR_WIDTH				1
+#define M98925_IMONOVFL_CLR_MASK				(1<<1)
+#define M98925_IMONOVFL_CLR_SHIFT				1
+#define M98925_IMONOVFL_CLR_WIDTH				1
+#define M98925_VMONOVFL_CLR_MASK				(1<<0)
+#define M98925_VMONOVFL_CLR_SHIFT				0
+#define M98925_VMONOVFL_CLR_WIDTH				1
+
+/* MAX98925_R011_MAP0 */
+#define M98925_ER_THERMWARN_EN_MASK				(1<<7)
+#define M98925_ER_THERMWARN_EN_SHIFT			7
+#define M98925_ER_THERMWARN_EN_WIDTH			1
+#define M98925_ER_THERMWARN_MAP_MASK			(0x07<<4)
+#define M98925_ER_THERMWARN_MAP_SHIFT			4
+#define M98925_ER_THERMWARN_MAP_WIDTH			3
+
+/* MAX98925_R012_MAP1 */
+#define M98925_ER_ALCMUT_EN_MASK				(1<<7)
+#define M98925_ER_ALCMUT_EN_SHIFT				7
+#define M98925_ER_ALCMUT_EN_WIDTH				1
+#define M98925_ER_ALCMUT_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCMUT_MAP_SHIFT				4
+#define M98925_ER_ALCMUT_MAP_WIDTH				3
+#define M98925_ER_ALCP_EN_MASK					(1<<3)
+#define M98925_ER_ALCP_EN_SHIFT					3
+#define M98925_ER_ALCP_EN_WIDTH					1
+#define M98925_ER_ALCP_MAP_MASK					(0x07<<0)
+#define M98925_ER_ALCP_MAP_SHIFT				0
+#define M98925_ER_ALCP_MAP_WIDTH				3
+
+/* MAX98925_R013_MAP2 */
+#define M98925_ER_ALCINFH_EN_MASK				(1<<7)
+#define M98925_ER_ALCINFH_EN_SHIFT				7
+#define M98925_ER_ALCINFH_EN_WIDTH				1
+#define M98925_ER_ALCINFH_MAP_MASK				(0x07<<4)
+#define M98925_ER_ALCINFH_MAP_SHIFT				4
+#define M98925_ER_ALCINFH_MAP_WIDTH				3
+#define M98925_ER_ALCACT_EN_MASK				(1<<3)
+#define M98925_ER_ALCACT_EN_SHIFT				3
+#define M98925_ER_ALCACT_EN_WIDTH				1
+#define M98925_ER_ALCACT_MAP_MASK				(0x07<<0)
+#define M98925_ER_ALCACT_MAP_SHIFT				0
+#define M98925_ER_ALCACT_MAP_WIDTH				3
+
+/* MAX98925_R014_MAP3 */
+#define M98925_ER_SPKCURNT_EN_MASK				(1<<7)
+#define M98925_ER_SPKCURNT_EN_SHIFT				7
+#define M98925_ER_SPKCURNT_EN_WIDTH				1
+#define M98925_ER_SPKCURNT_MAP_MASK				(0x07<<4)
+#define M98925_ER_SPKCURNT_MAP_SHIFT			4
+#define M98925_ER_SPKCURNT_MAP_WIDTH			3
+
+/* MAX98925_R015_MAP4 */
+/* RESERVED */
+
+/* MAX98925_R016_MAP5 */
+#define M98925_ER_IMONOVFL_EN_MASK				(1<<7)
+#define M98925_ER_IMONOVFL_EN_SHIFT				7
+#define M98925_ER_IMONOVFL_EN_WIDTH				1
+#define M98925_ER_IMONOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_IMONOVFL_MAP_SHIFT			4
+#define M98925_ER_IMONOVFL_MAP_WIDTH			3
+#define M98925_ER_VMONOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VMONOVFL_EN_SHIFT				3
+#define M98925_ER_VMONOVFL_EN_WIDTH				1
+#define M98925_ER_VMONOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VMONOVFL_MAP_SHIFT			0
+#define M98925_ER_VMONOVFL_MAP_WIDTH			3
+
+/* MAX98925_R017_MAP6 */
+#define M98925_ER_VBSTOVFL_EN_MASK				(1<<7)
+#define M98925_ER_VBSTOVFL_EN_SHIFT				7
+#define M98925_ER_VBSTOVFL_EN_WIDTH				1
+#define M98925_ER_VBSTOVFL_MAP_MASK				(0x07<<4)
+#define M98925_ER_VBSTOVFL_MAP_SHIFT			4
+#define M98925_ER_VBSTOVFL_MAP_WIDTH			3
+#define M98925_ER_VBATOVFL_EN_MASK				(1<<3)
+#define M98925_ER_VBATOVFL_EN_SHIFT				3
+#define M98925_ER_VBATOVFL_EN_WIDTH				1
+#define M98925_ER_VBATOVFL_MAP_MASK				(0x07<<0)
+#define M98925_ER_VBATOVFL_MAP_SHIFT			0
+#define M98925_ER_VBATOVFL_MAP_WIDTH			3
+
+/* MAX98925_R018_MAP7 */
+#define M98925_ER_INVALSLOT_EN_MASK				(1<<7)
+#define M98925_ER_INVALSLOT_EN_SHIFT			7
+#define M98925_ER_INVALSLOT_EN_WIDTH			1
+#define M98925_ER_INVALSLOT_MAP_MASK			(0x07<<4)
+#define M98925_ER_INVALSLOT_MAP_SHIFT			4
+#define M98925_ER_INVALSLOT_MAP_WIDTH			3
+#define M98925_ER_SLOTCNFLT_EN_MASK				(1<<3)
+#define M98925_ER_SLOTCNFLT_EN_SHIFT			3
+#define M98925_ER_SLOTCNFLT_EN_WIDTH			1
+#define M98925_ER_SLOTCNFLT_MAP_MASK			(0x07<<0)
+#define M98925_ER_SLOTCNFLT_MAP_SHIFT			0
+#define M98925_ER_SLOTCNFLT_MAP_WIDTH			3
+
+/* MAX98925_R019_MAP8 */
+#define M98925_ER_SLOTOVRN_EN_MASK	(1<<3)
+#define M98925_ER_SLOTOVRN_EN_SHIFT	3
+#define M98925_ER_SLOTOVRN_EN_WIDTH	1
+#define M98925_ER_SLOTOVRN_MAP_MASK	(0x07<<0)
+#define M98925_ER_SLOTOVRN_MAP_SHIFT	0
+#define M98925_ER_SLOTOVRN_MAP_WIDTH	3
+
+/* MAX98925_R01A_DAI_CLK_MODE1 */
+#define M98925_DAI_CLK_SOURCE_MASK	(1<<6)
+#define M98925_DAI_CLK_SOURCE_SHIFT	6
+#define M98925_DAI_CLK_SOURCE_WIDTH	1
+#define M98925_MDLL_MULT_MASK		(0x0F<<0)
+#define M98925_MDLL_MULT_SHIFT		0
+#define M98925_MDLL_MULT_WIDTH		4
+
+#define M98925_MDLL_MULT_MCLKx8		6
+#define M98925_MDLL_MULT_MCLKx16	8
+
+/* MAX98925_R01B_DAI_CLK_MODE2 */
+#define M98925_DAI_SR_MASK			(0x0F<<4)
+#define M98925_DAI_SR_SHIFT			4
+#define M98925_DAI_SR_WIDTH			4
+#define M98925_DAI_MAS_MASK			(1<<3)
+#define M98925_DAI_MAS_SHIFT			3
+#define M98925_DAI_MAS_WIDTH			1
+#define M98925_DAI_BSEL_MASK			(0x07<<0)
+#define M98925_DAI_BSEL_SHIFT			0
+#define M98925_DAI_BSEL_WIDTH			3
+
+#define M98925_DAI_BSEL_32 (0 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_48 (1 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_64 (2 << M98925_DAI_BSEL_SHIFT)
+#define M98925_DAI_BSEL_256 (6 << M98925_DAI_BSEL_SHIFT)
+
+/* MAX98925_R01C_DAI_CLK_DIV_M_MSBS */
+#define M98925_DAI_M_MSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_MSBS_SHIFT					0
+#define M98925_DAI_M_MSBS_WIDTH					8
+
+/* MAX98925_R01D_DAI_CLK_DIV_M_LSBS */
+#define M98925_DAI_M_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_M_LSBS_SHIFT					0
+#define M98925_DAI_M_LSBS_WIDTH					8
+
+/* MAX98925_R01E_DAI_CLK_DIV_N_MSBS */
+#define M98925_DAI_N_MSBS_MASK					(0x7F<<0)
+#define M98925_DAI_N_MSBS_SHIFT					0
+#define M98925_DAI_N_MSBS_WIDTH					7
+
+/* MAX98925_R01F_DAI_CLK_DIV_N_LSBS */
+#define M98925_DAI_N_LSBS_MASK					(0xFF<<0)
+#define M98925_DAI_N_LSBS_SHIFT					0
+#define M98925_DAI_N_LSBS_WIDTH					8
+
+/* MAX98925_R020_FORMAT */
+#define M98925_DAI_CHANSZ_MASK					(0x03<<6)
+#define M98925_DAI_CHANSZ_SHIFT					6
+#define M98925_DAI_CHANSZ_WIDTH					2
+#define M98925_DAI_EXTBCLK_HIZ_MASK				(1<<4)
+#define M98925_DAI_EXTBCLK_HIZ_SHIFT			4
+#define M98925_DAI_EXTBCLK_HIZ_WIDTH			1
+#define M98925_DAI_WCI_MASK						(1<<3)
+#define M98925_DAI_WCI_SHIFT					3
+#define M98925_DAI_WCI_WIDTH					1
+#define M98925_DAI_BCI_MASK						(1<<2)
+#define M98925_DAI_BCI_SHIFT					2
+#define M98925_DAI_BCI_WIDTH					1
+#define M98925_DAI_DLY_MASK						(1<<1)
+#define M98925_DAI_DLY_SHIFT					1
+#define M98925_DAI_DLY_WIDTH					1
+#define M98925_DAI_TDM_MASK						(1<<0)
+#define M98925_DAI_TDM_SHIFT					0
+#define M98925_DAI_TDM_WIDTH					1
+
+#define M98925_DAI_CHANSZ_16 (1 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_24 (2 << M98925_DAI_CHANSZ_SHIFT)
+#define M98925_DAI_CHANSZ_32 (3 << M98925_DAI_CHANSZ_SHIFT)
+
+/* MAX98925_R021_TDM_SLOT_SELECT */
+#define M98925_DAI_DO_EN_MASK					(1<<7)
+#define M98925_DAI_DO_EN_SHIFT					7
+#define M98925_DAI_DO_EN_WIDTH					1
+#define M98925_DAI_DIN_EN_MASK					(1<<6)
+#define M98925_DAI_DIN_EN_SHIFT					6
+#define M98925_DAI_DIN_EN_WIDTH					1
+#define M98925_DAI_INR_SOURCE_MASK				(0x07<<3)
+#define M98925_DAI_INR_SOURCE_SHIFT				3
+#define M98925_DAI_INR_SOURCE_WIDTH				3
+#define M98925_DAI_INL_SOURCE_MASK				(0x07<<0)
+#define M98925_DAI_INL_SOURCE_SHIFT				0
+#define M98925_DAI_INL_SOURCE_WIDTH				3
+
+/* MAX98925_R022_DOUT_CFG_VMON */
+#define M98925_DAI_VMON_EN_MASK					(1<<5)
+#define M98925_DAI_VMON_EN_SHIFT				5
+#define M98925_DAI_VMON_EN_WIDTH				1
+#define M98925_DAI_VMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VMON_SLOT_SHIFT				0
+#define M98925_DAI_VMON_SLOT_WIDTH				5
+
+#define M98925_DAI_VMON_SLOT_00_01 (0 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_01_02 (1 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_02_03 (2 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_03_04 (3 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_04_05 (4 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_05_06 (5 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_06_07 (6 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_07_08 (7 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_08_09 (8 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_09_0A (9 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0A_0B (10 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0B_0C (11 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0C_0D (12 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0D_0E (13 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0E_0F (14 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_0F_10 (15 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_10_11 (16 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_11_12 (17 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_12_13 (18 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_13_14 (19 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_14_15 (20 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_15_16 (21 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_16_17 (22 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_17_18 (23 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_18_19 (24 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_19_1A (25 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1A_1B (26 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1B_1C (27 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1C_1D (28 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1D_1E (29 << M98925_DAI_VMON_SLOT_SHIFT)
+#define M98925_DAI_VMON_SLOT_1E_1F (30 << M98925_DAI_VMON_SLOT_SHIFT)
+
+/* MAX98925_R023_DOUT_CFG_IMON */
+#define M98925_DAI_IMON_EN_MASK					(1<<5)
+#define M98925_DAI_IMON_EN_SHIFT				5
+#define M98925_DAI_IMON_EN_WIDTH				1
+#define M98925_DAI_IMON_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_IMON_SLOT_SHIFT				0
+#define M98925_DAI_IMON_SLOT_WIDTH				5
+
+#define M98925_DAI_IMON_SLOT_00_01 (0 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_01_02 (1 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_02_03 (2 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_03_04 (3 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_04_05 (4 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_05_06 (5 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_06_07 (6 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_07_08 (7 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_08_09 (8 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_09_0A (9 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0A_0B (10 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0B_0C (11 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0C_0D (12 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0D_0E (13 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0E_0F (14 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_0F_10 (15 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_10_11 (16 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_11_12 (17 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_12_13 (18 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_13_14 (19 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_14_15 (20 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_15_16 (21 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_16_17 (22 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_17_18 (23 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_18_19 (24 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_19_1A (25 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1A_1B (26 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1B_1C (27 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1C_1D (28 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1D_1E (29 << M98925_DAI_IMON_SLOT_SHIFT)
+#define M98925_DAI_IMON_SLOT_1E_1F (30 << M98925_DAI_IMON_SLOT_SHIFT)
+
+/* MAX98925_R024_DOUT_CFG_VBAT */
+#define M98925_DAI_VBAT_EN_MASK					(1<<5)
+#define M98925_DAI_VBAT_EN_SHIFT				5
+#define M98925_DAI_VBAT_EN_WIDTH				1
+#define M98925_DAI_VBAT_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBAT_SLOT_SHIFT				0
+#define M98925_DAI_VBAT_SLOT_WIDTH				5
+
+/* MAX98925_R025_DOUT_CFG_VBST */
+#define M98925_DAI_VBST_EN_MASK					(1<<5)
+#define M98925_DAI_VBST_EN_SHIFT				5
+#define M98925_DAI_VBST_EN_WIDTH				1
+#define M98925_DAI_VBST_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_VBST_SLOT_SHIFT				0
+#define M98925_DAI_VBST_SLOT_WIDTH				5
+
+/* MAX98925_R026_DOUT_CFG_FLAG */
+#define M98925_DAI_FLAG_EN_MASK					(1<<5)
+#define M98925_DAI_FLAG_EN_SHIFT				5
+#define M98925_DAI_FLAG_EN_WIDTH				1
+#define M98925_DAI_FLAG_SLOT_MASK				(0x1F<<0)
+#define M98925_DAI_FLAG_SLOT_SHIFT				0
+#define M98925_DAI_FLAG_SLOT_WIDTH				5
+
+/* MAX98925_R027_DOUT_HIZ_CFG1 */
+#define M98925_DAI_SLOT_HIZ_CFG1_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG1_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG1_WIDTH			8
+
+/* MAX98925_R028_DOUT_HIZ_CFG2 */
+#define M98925_DAI_SLOT_HIZ_CFG2_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG2_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG2_WIDTH			8
+
+/* MAX98925_R029_DOUT_HIZ_CFG3 */
+#define M98925_DAI_SLOT_HIZ_CFG3_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG3_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG3_WIDTH			8
+
+/* MAX98925_R02A_DOUT_HIZ_CFG4 */
+#define M98925_DAI_SLOT_HIZ_CFG4_MASK			(0xFF<<0)
+#define M98925_DAI_SLOT_HIZ_CFG4_SHIFT			0
+#define M98925_DAI_SLOT_HIZ_CFG4_WIDTH			8
+
+/* MAX98925_R02B_DOUT_DRV_STRENGTH */
+#define M98925_DAI_OUT_DRIVE_MASK				(0x03<<0)
+#define M98925_DAI_OUT_DRIVE_SHIFT				0
+#define M98925_DAI_OUT_DRIVE_WIDTH				2
+
+/* MAX98925_R02C_FILTERS */
+#define M98925_ADC_DITHER_EN_MASK				(1<<7)
+#define M98925_ADC_DITHER_EN_SHIFT				7
+#define M98925_ADC_DITHER_EN_WIDTH				1
+#define M98925_IV_DCB_EN_MASK					(1<<6)
+#define M98925_IV_DCB_EN_SHIFT					6
+#define M98925_IV_DCB_EN_WIDTH					1
+#define M98925_DAC_DITHER_EN_MASK				(1<<4)
+#define M98925_DAC_DITHER_EN_SHIFT				4
+#define M98925_DAC_DITHER_EN_WIDTH				1
+#define M98925_DAC_FILTER_MODE_MASK				(1<<3)
+#define M98925_DAC_FILTER_MODE_SHIFT			3
+#define M98925_DAC_FILTER_MODE_WIDTH			1
+#define M98925_DAC_HPF_MASK				(0x07<<0)
+#define M98925_DAC_HPF_SHIFT					0
+#define M98925_DAC_HPF_WIDTH					3
+#define M98925_DAC_HPF_DISABLE		(0 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_DC_BLOCK		(1 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_100		(2 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_200		(3 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_400		(4 << M98925_DAC_HPF_SHIFT)
+#define M98925_DAC_HPF_EN_800		(5 << M98925_DAC_HPF_SHIFT)
+
+/* MAX98925_R02D_GAIN */
+#define M98925_DAC_IN_SEL_MASK					(0x03<<5)
+#define M98925_DAC_IN_SEL_SHIFT					5
+#define M98925_DAC_IN_SEL_WIDTH					2
+#define M98925_SPK_GAIN_MASK					(0x1F<<0)
+#define M98925_SPK_GAIN_SHIFT					0
+#define M98925_SPK_GAIN_WIDTH					5
+
+#define M98925_DAC_IN_SEL_LEFT_DAI (0 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_RIGHT_DAI (1 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_SUMMED_DAI (2 << M98925_DAC_IN_SEL_SHIFT)
+#define M98925_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << M98925_DAC_IN_SEL_SHIFT)
+
+/* MAX98925_R02E_GAIN_RAMPING */
+#define M98925_SPK_RMP_EN_MASK		(1<<1)
+#define M98925_SPK_RMP_EN_SHIFT		1
+#define M98925_SPK_RMP_EN_WIDTH		1
+#define M98925_SPK_ZCD_EN_MASK		(1<<0)
+#define M98925_SPK_ZCD_EN_SHIFT		0
+#define M98925_SPK_ZCD_EN_WIDTH		1
+
+/* MAX98925_R02F_SPK_AMP */
+#define M98925_SPK_MODE_MASK		(1<<0)
+#define M98925_SPK_MODE_SHIFT		0
+#define M98925_SPK_MODE_WIDTH		1
+
+/* MAX98925_R030_THRESHOLD */
+#define M98925_ALC_EN_MASK			(1<<5)
+#define M98925_ALC_EN_SHIFT			5
+#define M98925_ALC_EN_WIDTH			1
+#define M98925_ALC_TH_MASK			(0x1F<<0)
+#define M98925_ALC_TH_SHIFT			0
+#define M98925_ALC_TH_WIDTH			5
+
+/* MAX98925_R031_ALC_ATTACK */
+#define M98925_ALC_ATK_STEP_MASK	(0x0F<<4)
+#define M98925_ALC_ATK_STEP_SHIFT	4
+#define M98925_ALC_ATK_STEP_WIDTH	4
+#define M98925_ALC_ATK_RATE_MASK	(0x7<<0)
+#define M98925_ALC_ATK_RATE_SHIFT	0
+#define M98925_ALC_ATK_RATE_WIDTH	3
+
+/* MAX98925_R032_ALC_ATTEN_RLS */
+#define M98925_ALC_MAX_ATTEN_MASK	(0x0F<<4)
+#define M98925_ALC_MAX_ATTEN_SHIFT	4
+#define M98925_ALC_MAX_ATTEN_WIDTH	4
+#define M98925_ALC_RLS_RATE_MASK	(0x7<<0)
+#define M98925_ALC_RLS_RATE_SHIFT	0
+#define M98925_ALC_RLS_RATE_WIDTH	3
+
+/* MAX98925_R033_ALC_HOLD_RLS */
+#define M98925_ALC_RLS_TGR_MASK		(1<<0)
+#define M98925_ALC_RLS_TGR_SHIFT	0
+#define M98925_ALC_RLS_TGR_WIDTH	1
+
+/* MAX98925_R034_ALC_CONFIGURATION */
+#define M98925_ALC_MUTE_EN_MASK		(1<<7)
+#define M98925_ALC_MUTE_EN_SHIFT	7
+#define M98925_ALC_MUTE_EN_WIDTH	1
+#define M98925_ALC_MUTE_DLY_MASK	(0x07<<4)
+#define M98925_ALC_MUTE_DLY_SHIFT	4
+#define M98925_ALC_MUTE_DLY_WIDTH	3
+#define M98925_ALC_RLS_DBT_MASK		(0x07<<0)
+#define M98925_ALC_RLS_DBT_SHIFT	0
+#define M98925_ALC_RLS_DBT_WIDTH	3
+
+/* MAX98925_R035_BOOST_CONVERTER */
+#define M98925_BST_SYNC_MASK		(1<<7)
+#define M98925_BST_SYNC_SHIFT		7
+#define M98925_BST_SYNC_WIDTH		1
+#define M98925_BST_PHASE_MASK		(0x03<<4)
+#define M98925_BST_PHASE_SHIFT		4
+#define M98925_BST_PHASE_WIDTH		2
+#define M98925_BST_SKIP_MODE_MASK	(0x03<<0)
+#define M98925_BST_SKIP_MODE_SHIFT	0
+#define M98925_BST_SKIP_MODE_WIDTH	2
+
+/* MAX98925_R036_BLOCK_ENABLE */
+#define M98925_BST_EN_MASK			(1<<7)
+#define M98925_BST_EN_SHIFT			7
+#define M98925_BST_EN_WIDTH			1
+#define M98925_WATCH_EN_MASK		(1<<6)
+#define M98925_WATCH_EN_SHIFT		6
+#define M98925_WATCH_EN_WIDTH		1
+#define M98925_CLKMON_EN_MASK		(1<<5)
+#define M98925_CLKMON_EN_SHIFT		5
+#define M98925_CLKMON_EN_WIDTH		1
+#define M98925_SPK_EN_MASK			(1<<4)
+#define M98925_SPK_EN_SHIFT			4
+#define M98925_SPK_EN_WIDTH			1
+#define M98925_ADC_VBST_EN_MASK		(1<<3)
+#define M98925_ADC_VBST_EN_SHIFT	3
+#define M98925_ADC_VBST_EN_WIDTH	1
+#define M98925_ADC_VBAT_EN_MASK		(1<<2)
+#define M98925_ADC_VBAT_EN_SHIFT	2
+#define M98925_ADC_VBAT_EN_WIDTH	1
+#define M98925_ADC_IMON_EN_MASK		(1<<1)
+#define M98925_ADC_IMON_EN_SHIFT	1
+#define M98925_ADC_IMON_EN_WIDTH	1
+#define M98925_ADC_VMON_EN_MASK		(1<<0)
+#define M98925_ADC_VMON_EN_SHIFT	0
+#define M98925_ADC_VMON_EN_WIDTH	1
+
+/* MAX98925_R037_CONFIGURATION */
+#define M98925_BST_VOUT_MASK		(0x0F<<4)
+#define M98925_BST_VOUT_SHIFT		4
+#define M98925_BST_VOUT_WIDTH		4
+#define M98925_THERMWARN_LEVEL_MASK	(0x03<<2)
+#define M98925_THERMWARN_LEVEL_SHIFT			2
+#define M98925_THERMWARN_LEVEL_WIDTH			2
+#define M98925_WATCH_TIME_MASK			(0x03<<0)
+#define M98925_WATCH_TIME_SHIFT			0
+#define M98925_WATCH_TIME_WIDTH			2
+
+/* MAX98925_R038_GLOBAL_ENABLE */
+#define M98925_EN_MASK			(1<<7)
+#define M98925_EN_SHIFT			7
+#define M98925_EN_WIDTH			1
+
+/* MAX98925_R03A_BOOST_LIMITER */
+#define M98925_BST_ILIM_MASK	(0x1F<<3)
+#define M98925_BST_ILIM_SHIFT	3
+#define M98925_BST_ILIM_WIDTH	5
+
+/* MAX98925_R0FF_VERSION */
+#define M98925_REV_ID_MASK	(0xFF<<0)
+#define M98925_REV_ID_SHIFT	0
+#define M98925_REV_ID_WIDTH	8
+
+struct max98925_cdata {
+	unsigned int rate;
+	unsigned int fmt;
+};
+
+struct max98925_priv {
+	struct regmap *regmap_l;
+	struct regmap *regmap_r;
+	struct snd_soc_codec *codec;
+	struct max98925_pdata *pdata;
+	unsigned int spk_gain;
+	unsigned int sysclk;
+	unsigned int iv_status;
+	struct max98925_cdata dai[1];
+};
+#endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2015-03-11 18:27 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-09 22:50 [PATCH] ASoC: Add max98925 codec driver Anish Kumar
2015-03-11 18:27 ` Mark Brown
  -- strict thread matches above, loose matches on Subject: below --
2015-03-05 23:15 Anish Kumar
2015-03-06 20:46 ` Mark Brown
2015-02-19  4:09 Anish Kumar
2015-02-19  6:49 ` Tushar Behera
2015-02-20  7:47   ` anish
2015-02-21  9:42     ` Mark Brown
2015-02-24  9:03 ` Mark Brown
2015-02-24 17:56   ` anish
2015-02-14  3:25 Anish Kumar
2015-02-14  5:14 ` Mark Brown
2015-02-14  6:35   ` anish
2015-02-24 14:50     ` Mark Brown
2015-02-24 17:57       ` anish

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.