Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c5ff908 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branch 'asoc/topic/adau1373' into asoc-next

parents de3bb2de 729485f6
Loading
Loading
Loading
Loading
+237 −61
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct adau1373_dai {
};

struct adau1373 {
	struct regmap *regmap;
	struct adau1373_dai dais[3];
};

@@ -73,7 +74,6 @@ struct adau1373 {
#define ADAU1373_PLL_CTRL4(x)	(0x2c + (x) * 7)
#define ADAU1373_PLL_CTRL5(x)	(0x2d + (x) * 7)
#define ADAU1373_PLL_CTRL6(x)	(0x2e + (x) * 7)
#define ADAU1373_PLL_CTRL7(x)	(0x2f + (x) * 7)
#define ADAU1373_HEADDECT	0x36
#define ADAU1373_ADC_DAC_STATUS	0x37
#define ADAU1373_ADC_CTRL	0x3c
@@ -152,37 +152,172 @@ struct adau1373 {
#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4
#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2

static const uint8_t adau1373_default_regs[] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */
	0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */
	0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
	0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */
	0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
	0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */
	0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
	0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
	0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */
	0x00, 0x1f, 0x0f, 0x00, 0x00,
static const struct reg_default adau1373_reg_defaults[] = {
	{ ADAU1373_INPUT_MODE,		0x00 },
	{ ADAU1373_AINL_CTRL(0),	0x00 },
	{ ADAU1373_AINR_CTRL(0),	0x00 },
	{ ADAU1373_AINL_CTRL(1),	0x00 },
	{ ADAU1373_AINR_CTRL(1),	0x00 },
	{ ADAU1373_AINL_CTRL(2),	0x00 },
	{ ADAU1373_AINR_CTRL(2),	0x00 },
	{ ADAU1373_AINL_CTRL(3),	0x00 },
	{ ADAU1373_AINR_CTRL(3),	0x00 },
	{ ADAU1373_LLINE_OUT(0),	0x00 },
	{ ADAU1373_RLINE_OUT(0),	0x00 },
	{ ADAU1373_LLINE_OUT(1),	0x00 },
	{ ADAU1373_RLINE_OUT(1),	0x00 },
	{ ADAU1373_LSPK_OUT,		0x00 },
	{ ADAU1373_RSPK_OUT,		0x00 },
	{ ADAU1373_LHP_OUT,		0x00 },
	{ ADAU1373_RHP_OUT,		0x00 },
	{ ADAU1373_ADC_GAIN,		0x00 },
	{ ADAU1373_LADC_MIXER,		0x00 },
	{ ADAU1373_RADC_MIXER,		0x00 },
	{ ADAU1373_LLINE1_MIX,		0x00 },
	{ ADAU1373_RLINE1_MIX,		0x00 },
	{ ADAU1373_LLINE2_MIX,		0x00 },
	{ ADAU1373_RLINE2_MIX,		0x00 },
	{ ADAU1373_LSPK_MIX,		0x00 },
	{ ADAU1373_RSPK_MIX,		0x00 },
	{ ADAU1373_LHP_MIX,		0x00 },
	{ ADAU1373_RHP_MIX,		0x00 },
	{ ADAU1373_EP_MIX,		0x00 },
	{ ADAU1373_HP_CTRL,		0x00 },
	{ ADAU1373_HP_CTRL2,		0x00 },
	{ ADAU1373_LS_CTRL,		0x00 },
	{ ADAU1373_EP_CTRL,		0x00 },
	{ ADAU1373_MICBIAS_CTRL1,	0x00 },
	{ ADAU1373_MICBIAS_CTRL2,	0x00 },
	{ ADAU1373_OUTPUT_CTRL,		0x00 },
	{ ADAU1373_PWDN_CTRL1,		0x00 },
	{ ADAU1373_PWDN_CTRL2,		0x00 },
	{ ADAU1373_PWDN_CTRL3,		0x00 },
	{ ADAU1373_DPLL_CTRL(0),	0x00 },
	{ ADAU1373_PLL_CTRL1(0),	0x00 },
	{ ADAU1373_PLL_CTRL2(0),	0x00 },
	{ ADAU1373_PLL_CTRL3(0),	0x00 },
	{ ADAU1373_PLL_CTRL4(0),	0x00 },
	{ ADAU1373_PLL_CTRL5(0),	0x00 },
	{ ADAU1373_PLL_CTRL6(0),	0x02 },
	{ ADAU1373_DPLL_CTRL(1),	0x00 },
	{ ADAU1373_PLL_CTRL1(1),	0x00 },
	{ ADAU1373_PLL_CTRL2(1),	0x00 },
	{ ADAU1373_PLL_CTRL3(1),	0x00 },
	{ ADAU1373_PLL_CTRL4(1),	0x00 },
	{ ADAU1373_PLL_CTRL5(1),	0x00 },
	{ ADAU1373_PLL_CTRL6(1),	0x02 },
	{ ADAU1373_HEADDECT,		0x00 },
	{ ADAU1373_ADC_CTRL,		0x00 },
	{ ADAU1373_CLK_SRC_DIV(0),	0x00 },
	{ ADAU1373_CLK_SRC_DIV(1),	0x00 },
	{ ADAU1373_DAI(0),		0x0a },
	{ ADAU1373_DAI(1),		0x0a },
	{ ADAU1373_DAI(2),		0x0a },
	{ ADAU1373_BCLKDIV(0),		0x00 },
	{ ADAU1373_BCLKDIV(1),		0x00 },
	{ ADAU1373_BCLKDIV(2),		0x00 },
	{ ADAU1373_SRC_RATIOA(0),	0x00 },
	{ ADAU1373_SRC_RATIOB(0),	0x00 },
	{ ADAU1373_SRC_RATIOA(1),	0x00 },
	{ ADAU1373_SRC_RATIOB(1),	0x00 },
	{ ADAU1373_SRC_RATIOA(2),	0x00 },
	{ ADAU1373_SRC_RATIOB(2),	0x00 },
	{ ADAU1373_DEEMP_CTRL,		0x00 },
	{ ADAU1373_SRC_DAI_CTRL(0),	0x08 },
	{ ADAU1373_SRC_DAI_CTRL(1),	0x08 },
	{ ADAU1373_SRC_DAI_CTRL(2),	0x08 },
	{ ADAU1373_DIN_MIX_CTRL(0),	0x00 },
	{ ADAU1373_DIN_MIX_CTRL(1),	0x00 },
	{ ADAU1373_DIN_MIX_CTRL(2),	0x00 },
	{ ADAU1373_DIN_MIX_CTRL(3),	0x00 },
	{ ADAU1373_DIN_MIX_CTRL(4),	0x00 },
	{ ADAU1373_DOUT_MIX_CTRL(0),	0x00 },
	{ ADAU1373_DOUT_MIX_CTRL(1),	0x00 },
	{ ADAU1373_DOUT_MIX_CTRL(2),	0x00 },
	{ ADAU1373_DOUT_MIX_CTRL(3),	0x00 },
	{ ADAU1373_DOUT_MIX_CTRL(4),	0x00 },
	{ ADAU1373_DAI_PBL_VOL(0),	0x00 },
	{ ADAU1373_DAI_PBR_VOL(0),	0x00 },
	{ ADAU1373_DAI_PBL_VOL(1),	0x00 },
	{ ADAU1373_DAI_PBR_VOL(1),	0x00 },
	{ ADAU1373_DAI_PBL_VOL(2),	0x00 },
	{ ADAU1373_DAI_PBR_VOL(2),	0x00 },
	{ ADAU1373_DAI_RECL_VOL(0),	0x00 },
	{ ADAU1373_DAI_RECR_VOL(0),	0x00 },
	{ ADAU1373_DAI_RECL_VOL(1),	0x00 },
	{ ADAU1373_DAI_RECR_VOL(1),	0x00 },
	{ ADAU1373_DAI_RECL_VOL(2),	0x00 },
	{ ADAU1373_DAI_RECR_VOL(2),	0x00 },
	{ ADAU1373_DAC1_PBL_VOL,	0x00 },
	{ ADAU1373_DAC1_PBR_VOL,	0x00 },
	{ ADAU1373_DAC2_PBL_VOL,	0x00 },
	{ ADAU1373_DAC2_PBR_VOL,	0x00 },
	{ ADAU1373_ADC_RECL_VOL,	0x00 },
	{ ADAU1373_ADC_RECR_VOL,	0x00 },
	{ ADAU1373_DMIC_RECL_VOL,	0x00 },
	{ ADAU1373_DMIC_RECR_VOL,	0x00 },
	{ ADAU1373_VOL_GAIN1,		0x00 },
	{ ADAU1373_VOL_GAIN2,		0x00 },
	{ ADAU1373_VOL_GAIN3,		0x00 },
	{ ADAU1373_HPF_CTRL,		0x00 },
	{ ADAU1373_BASS1,		0x00 },
	{ ADAU1373_BASS2,		0x00 },
	{ ADAU1373_DRC(0) + 0x0,	0x78 },
	{ ADAU1373_DRC(0) + 0x1,	0x18 },
	{ ADAU1373_DRC(0) + 0x2,	0x00 },
	{ ADAU1373_DRC(0) + 0x3,	0x00 },
	{ ADAU1373_DRC(0) + 0x4,	0x00 },
	{ ADAU1373_DRC(0) + 0x5,	0xc0 },
	{ ADAU1373_DRC(0) + 0x6,	0x00 },
	{ ADAU1373_DRC(0) + 0x7,	0x00 },
	{ ADAU1373_DRC(0) + 0x8,	0x00 },
	{ ADAU1373_DRC(0) + 0x9,	0xc0 },
	{ ADAU1373_DRC(0) + 0xa,	0x88 },
	{ ADAU1373_DRC(0) + 0xb,	0x7a },
	{ ADAU1373_DRC(0) + 0xc,	0xdf },
	{ ADAU1373_DRC(0) + 0xd,	0x20 },
	{ ADAU1373_DRC(0) + 0xe,	0x00 },
	{ ADAU1373_DRC(0) + 0xf,	0x00 },
	{ ADAU1373_DRC(1) + 0x0,	0x78 },
	{ ADAU1373_DRC(1) + 0x1,	0x18 },
	{ ADAU1373_DRC(1) + 0x2,	0x00 },
	{ ADAU1373_DRC(1) + 0x3,	0x00 },
	{ ADAU1373_DRC(1) + 0x4,	0x00 },
	{ ADAU1373_DRC(1) + 0x5,	0xc0 },
	{ ADAU1373_DRC(1) + 0x6,	0x00 },
	{ ADAU1373_DRC(1) + 0x7,	0x00 },
	{ ADAU1373_DRC(1) + 0x8,	0x00 },
	{ ADAU1373_DRC(1) + 0x9,	0xc0 },
	{ ADAU1373_DRC(1) + 0xa,	0x88 },
	{ ADAU1373_DRC(1) + 0xb,	0x7a },
	{ ADAU1373_DRC(1) + 0xc,	0xdf },
	{ ADAU1373_DRC(1) + 0xd,	0x20 },
	{ ADAU1373_DRC(1) + 0xe,	0x00 },
	{ ADAU1373_DRC(1) + 0xf,	0x00 },
	{ ADAU1373_DRC(2) + 0x0,	0x78 },
	{ ADAU1373_DRC(2) + 0x1,	0x18 },
	{ ADAU1373_DRC(2) + 0x2,	0x00 },
	{ ADAU1373_DRC(2) + 0x3,	0x00 },
	{ ADAU1373_DRC(2) + 0x4,	0x00 },
	{ ADAU1373_DRC(2) + 0x5,	0xc0 },
	{ ADAU1373_DRC(2) + 0x6,	0x00 },
	{ ADAU1373_DRC(2) + 0x7,	0x00 },
	{ ADAU1373_DRC(2) + 0x8,	0x00 },
	{ ADAU1373_DRC(2) + 0x9,	0xc0 },
	{ ADAU1373_DRC(2) + 0xa,	0x88 },
	{ ADAU1373_DRC(2) + 0xb,	0x7a },
	{ ADAU1373_DRC(2) + 0xc,	0xdf },
	{ ADAU1373_DRC(2) + 0xd,	0x20 },
	{ ADAU1373_DRC(2) + 0xe,	0x00 },
	{ ADAU1373_DRC(2) + 0xf,	0x00 },
	{ ADAU1373_3D_CTRL1,		0x00 },
	{ ADAU1373_3D_CTRL2,		0x00 },
	{ ADAU1373_FDSP_SEL1,		0x00 },
	{ ADAU1373_FDSP_SEL2,		0x00 },
	{ ADAU1373_FDSP_SEL2,		0x00 },
	{ ADAU1373_FDSP_SEL4,		0x00 },
	{ ADAU1373_DIGMICCTRL,		0x00 },
	{ ADAU1373_DIGEN,		0x00 },
};

static const unsigned int adau1373_out_tlv[] = {
@@ -418,6 +553,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_codec *codec = w->codec;
	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
	unsigned int pll_id = w->name[3] - '1';
	unsigned int val;

@@ -426,7 +562,7 @@ static int adau1373_pll_event(struct snd_soc_dapm_widget *w,
	else
		val = 0;

	snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
	regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
		ADAU1373_PLL_CTRL6_PLL_EN, val);

	if (SND_SOC_DAPM_EVENT_ON(event))
@@ -938,7 +1074,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,

	adau1373_dai->enable_src = (div != 0);

	snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
	regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id),
		ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
		(div << 2) | ADAU1373_BCLKDIV_64);

@@ -959,7 +1095,7 @@ static int adau1373_hw_params(struct snd_pcm_substream *substream,
		return -EINVAL;
	}

	return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
	return regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id),
			ADAU1373_DAI_WLEN_MASK, ctrl);
}

@@ -1016,7 +1152,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
		return -EINVAL;
	}

	snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
	regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id),
		~ADAU1373_DAI_WLEN_MASK, ctrl);

	return 0;
@@ -1039,7 +1175,7 @@ static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai,
	adau1373_dai->sysclk = freq;
	adau1373_dai->clk_src = clk_id;

	snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id),
	regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id),
		ADAU1373_BCLKDIV_SOURCE, clk_id << 5);

	return 0;
@@ -1120,6 +1256,7 @@ static struct snd_soc_dai_driver adau1373_dai_driver[] = {
static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
	int source, unsigned int freq_in, unsigned int freq_out)
{
	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
	unsigned int dpll_div = 0;
	unsigned int x, r, n, m, i, j, mode;

@@ -1187,36 +1324,36 @@ static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,

	if (dpll_div) {
		dpll_div = 11 - dpll_div;
		snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
		regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
			ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0);
	} else {
		snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
		regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
			ADAU1373_PLL_CTRL6_DPLL_BYPASS,
			ADAU1373_PLL_CTRL6_DPLL_BYPASS);
	}

	snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id),
	regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id),
		(source << 4) | dpll_div);
	snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
	snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
	snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
	snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
	snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id),
	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id),
		(r << 3) | (x << 1) | mode);

	/* Set sysclk to pll_rate / 4 */
	snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
	regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);

	return 0;
}

static void adau1373_load_drc_settings(struct snd_soc_codec *codec,
static void adau1373_load_drc_settings(struct adau1373 *adau1373,
	unsigned int nr, uint8_t *drc)
{
	unsigned int i;

	for (i = 0; i < ADAU1373_DRC_SIZE; ++i)
		snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]);
		regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]);
}

static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
@@ -1235,13 +1372,14 @@ static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)

static int adau1373_probe(struct snd_soc_codec *codec)
{
	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
	struct adau1373_platform_data *pdata = codec->dev->platform_data;
	bool lineout_differential = false;
	unsigned int val;
	int ret;
	int i;

	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
	ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
	if (ret) {
		dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
		return ret;
@@ -1256,7 +1394,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
			return -EINVAL;

		for (i = 0; i < pdata->num_drc; ++i) {
			adau1373_load_drc_settings(codec, i,
			adau1373_load_drc_settings(adau1373, i,
				pdata->drc_setting[i]);
		}

@@ -1268,18 +1406,18 @@ static int adau1373_probe(struct snd_soc_codec *codec)
			if (pdata->input_differential[i])
				val |= BIT(i);
		}
		snd_soc_write(codec, ADAU1373_INPUT_MODE, val);
		regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val);

		val = 0;
		if (pdata->lineout_differential)
			val |= ADAU1373_OUTPUT_CTRL_LDIFF;
		if (pdata->lineout_ground_sense)
			val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
		snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val);
		regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val);

		lineout_differential = pdata->lineout_differential;

		snd_soc_write(codec, ADAU1373_EP_CTRL,
		regmap_write(adau1373->regmap, ADAU1373_EP_CTRL,
			(pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
			(pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
	}
@@ -1289,7 +1427,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
			ARRAY_SIZE(adau1373_lineout2_controls));
	}

	snd_soc_write(codec, ADAU1373_ADC_CTRL,
	regmap_write(adau1373->regmap, ADAU1373_ADC_CTRL,
	    ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT);

	return 0;
@@ -1298,17 +1436,19 @@ static int adau1373_probe(struct snd_soc_codec *codec)
static int adau1373_set_bias_level(struct snd_soc_codec *codec,
	enum snd_soc_bias_level level)
{
	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);

	switch (level) {
	case SND_SOC_BIAS_ON:
		break;
	case SND_SOC_BIAS_PREPARE:
		break;
	case SND_SOC_BIAS_STANDBY:
		snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
		regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3,
			ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN);
		break;
	case SND_SOC_BIAS_OFF:
		snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
		regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3,
			ADAU1373_PWDN_CTRL3_PWR_EN, 0);
		break;
	}
@@ -1324,17 +1464,49 @@ static int adau1373_remove(struct snd_soc_codec *codec)

static int adau1373_suspend(struct snd_soc_codec *codec)
{
	return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
	int ret;

	ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
	regcache_cache_only(adau1373->regmap, true);

	return ret;
}

static int adau1373_resume(struct snd_soc_codec *codec)
{
	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);

	regcache_cache_only(adau1373->regmap, false);
	adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	snd_soc_cache_sync(codec);
	regcache_sync(adau1373->regmap);

	return 0;
}

static bool adau1373_register_volatile(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case ADAU1373_SOFT_RESET:
	case ADAU1373_ADC_DAC_STATUS:
		return true;
	default:
		return false;
	}
}

static const struct regmap_config adau1373_regmap_config = {
	.val_bits = 8,
	.reg_bits = 8,

	.volatile_reg = adau1373_register_volatile,
	.max_register = ADAU1373_SOFT_RESET,

	.cache_type = REGCACHE_RBTREE,
	.reg_defaults = adau1373_reg_defaults,
	.num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults),
};

static struct snd_soc_codec_driver adau1373_codec_driver = {
	.probe =	adau1373_probe,
	.remove =	adau1373_remove,
@@ -1342,9 +1514,6 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
	.resume =	adau1373_resume,
	.set_bias_level = adau1373_set_bias_level,
	.idle_bias_off = true,
	.reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
	.reg_cache_default = adau1373_default_regs,
	.reg_word_size = sizeof(uint8_t),

	.set_pll = adau1373_set_pll,

@@ -1366,6 +1535,13 @@ static int adau1373_i2c_probe(struct i2c_client *client,
	if (!adau1373)
		return -ENOMEM;

	adau1373->regmap = devm_regmap_init_i2c(client,
		&adau1373_regmap_config);
	if (IS_ERR(adau1373->regmap))
		return PTR_ERR(adau1373->regmap);

	regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00);

	dev_set_drvdata(&client->dev, adau1373);

	ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver,