// SPDX-License-Identifier: GPL-2.0
/*
 * ALSA SoC tlv320adc3101 codec driver
 *
 * Copyright (C) 2019 Amlogic,inc
 *
 * Based on sound/soc/codecs/tlv320aic320x and
 * TI driver for kernel 2.6.27.
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/slab.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>

#include "tlv320adc3101.h"

#define DRV_NAME "tlv320adc3101"

struct adc3101_rate_divs {
	u32 mclk;
	u32 rate;
	u8 p_val;
	u8 pll_j;
	u16 pll_d;
	u16 dosr;
	u8 ndac;
	u8 mdac;
	u8 aosr;
	u8 nadc;
	u8 madc;
	u8 blck_N;
};

struct adc3101_priv {
	struct regmap *regmap;
	u32 sysclk;
	u32 power_cfg;
	u32 micpga_routing;
	bool swapdacs;
	int rstn_gpio;
	struct snd_soc_component *component;
	/* for more control */
	int codec_cnt;
	int codec_mask;
	unsigned int slot_number;
	struct i2c_client *client[4];
	u8 page_no;
	/* differential_pair
	 * 0: Single-ended;
	 * 1: Differential Pair;
	 */
	unsigned int differential_pair;
};

enum{
	MASK_1 = 1 << 0,
	MASK_2 = 1 << 1,
	MASK_3 = 1 << 2,
	MASK_4 = 1 << 3
};

static int	lr_gain = 0x20;
module_param(lr_gain, int, 0664);
MODULE_PARM_DESC(lr_gain, "PGA Level Volume");

/* 0dB min, 1dB steps */
static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0);
/* 0dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0);

static const struct snd_kcontrol_new adc3101_snd_controls[] = {
	SOC_DOUBLE_R_TLV("PCM Playback Volume", ADC3101_LDACVOL,
			 ADC3101_RDACVOL, 0, 0x30, 0, tlv_step_0_5),
	SOC_DOUBLE_R_TLV("HP Driver Gain Volume", ADC3101_HPLGAIN,
			 ADC3101_HPRGAIN, 0, 0x1D, 0, tlv_step_1),
	SOC_DOUBLE_R_TLV("LO Driver Gain Volume", ADC3101_LOLGAIN,
			 ADC3101_LORGAIN, 0, 0x1D, 0, tlv_step_1),
	SOC_DOUBLE_R("HP DAC Playback Switch", ADC3101_HPLGAIN,
		     ADC3101_HPRGAIN, 6, 0x01, 1),
	SOC_DOUBLE_R("LO DAC Playback Switch", ADC3101_LOLGAIN,
		     ADC3101_LORGAIN, 6, 0x01, 1),
	SOC_DOUBLE_R("Mic PGA Switch", ADC3101_LMICPGAVOL,
		     ADC3101_RMICPGAVOL, 7, 0x01, 1),

	SOC_SINGLE("ADCFGA Left Mute Switch", ADC3101_ADCFGA, 7, 1, 0),
	SOC_SINGLE("ADCFGA Right Mute Switch", ADC3101_ADCFGA, 3, 1, 0),

	SOC_DOUBLE_R_TLV("ADC Level Volume", ADC3101_LADCVOL,
			 ADC3101_RADCVOL, 0, 0x28, 0, tlv_step_0_5),
	SOC_DOUBLE_R_TLV("PGA Level Volume", ADC3101_LMICPGAVOL,
			 ADC3101_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5),

	SOC_SINGLE("Auto-mute Switch", ADC3101_DACMUTE, 4, 7, 0),

	SOC_SINGLE("AGC Left Switch", ADC3101_LAGC1, 7, 1, 0),
	SOC_SINGLE("AGC Right Switch", ADC3101_RAGC1, 7, 1, 0),
	SOC_DOUBLE_R("AGC Target Level", ADC3101_LAGC1, ADC3101_RAGC1,
		     4, 0x07, 0),
	SOC_DOUBLE_R("AGC Gain Hysteresis", ADC3101_LAGC1, ADC3101_RAGC1,
		     0, 0x03, 0),
	SOC_DOUBLE_R("AGC Hysteresis", ADC3101_LAGC2, ADC3101_RAGC2,
		     6, 0x03, 0),
	SOC_DOUBLE_R("AGC Noise Threshold", ADC3101_LAGC2, ADC3101_RAGC2,
		     1, 0x1F, 0),
	SOC_DOUBLE_R("AGC Max PGA", ADC3101_LAGC3, ADC3101_RAGC3,
		     0, 0x7F, 0),
	SOC_DOUBLE_R("AGC Attack Time", ADC3101_LAGC4, ADC3101_RAGC4,
		     3, 0x1F, 0),
	SOC_DOUBLE_R("AGC Decay Time", ADC3101_LAGC5, ADC3101_RAGC5,
		     3, 0x1F, 0),
	SOC_DOUBLE_R("AGC Noise Debounce", ADC3101_LAGC6, ADC3101_RAGC6,
		     0, 0x1F, 0),
	SOC_DOUBLE_R("AGC Signal Debounce", ADC3101_LAGC7, ADC3101_RAGC7,
		     0, 0x0F, 0),
};

static const struct adc3101_rate_divs adc3101_divs[] = {
	/* mclk	rate p  j  d	dosr ndac mdac  aosr nadc  madc	blk_N */

	/* 8k rate */
	{ADC3101_FREQ_12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
	{ADC3101_FREQ_24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
	{ADC3101_FREQ_25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
	/* 11.025k rate */
	{ADC3101_FREQ_12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
	{ADC3101_FREQ_24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
	/* 16k rate */
	{ADC3101_FREQ_12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
	{ADC3101_FREQ_24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
	{ADC3101_FREQ_25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
	/* 22.05k rate */
	{ADC3101_FREQ_12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
	{ADC3101_FREQ_24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
	{ADC3101_FREQ_25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
	/* 32k rate */
	{ADC3101_FREQ_12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
	{ADC3101_FREQ_24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
	/* 44.1k rate */
	{ADC3101_FREQ_12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
	{ADC3101_FREQ_24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
	{ADC3101_FREQ_25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
	/* 48k rate */
	{ADC3101_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
	{ADC3101_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
	{ADC3101_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4},

	{ADC3101_FREQ_2048000, 8000, 1, 4, 0, 128, 1, 1, 128, 1, 2, 1},
	{ADC3101_FREQ_4096000, 16000, 1, 4, 0, 128, 1, 1, 128, 1, 2, 1},
	{ADC3101_FREQ_8192000, 32000, 1, 4, 0, 128, 1, 1, 128, 1, 2, 1},
	{ADC3101_FREQ_11289600, 44100, 1, 4, 0, 128, 1, 1, 128, 1, 2, 1},
	{ADC3101_FREQ_12288000, 48000, 1, 4, 0, 128, 2, 1, 128, 1, 2, 1},
};

static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
	SOC_DAPM_SINGLE("L_DAC Switch", ADC3101_HPLROUTE, 3, 1, 0),
	SOC_DAPM_SINGLE("IN1_L Switch", ADC3101_HPLROUTE, 2, 1, 0),
};

static const struct snd_kcontrol_new hpr_output_mixer_controls[] = {
	SOC_DAPM_SINGLE("R_DAC Switch", ADC3101_HPRROUTE, 3, 1, 0),
	SOC_DAPM_SINGLE("IN1_R Switch", ADC3101_HPRROUTE, 2, 1, 0),
};

static const struct snd_kcontrol_new lol_output_mixer_controls[] = {
	SOC_DAPM_SINGLE("L_DAC Switch", ADC3101_LOLROUTE, 3, 1, 0),
};

static const struct snd_kcontrol_new lor_output_mixer_controls[] = {
	SOC_DAPM_SINGLE("R_DAC Switch", ADC3101_LORROUTE, 3, 1, 0),
};

static const struct snd_kcontrol_new left_input_mixer_controls[] = {
	SOC_DAPM_SINGLE("IN1_L P Switch", ADC3101_LMICPGAPIN, 6, 1, 0),
	SOC_DAPM_SINGLE("IN2_L P Switch", ADC3101_LMICPGAPIN, 4, 1, 0),
	SOC_DAPM_SINGLE("IN3_L P Switch", ADC3101_LMICPGAPIN, 2, 1, 0),
};

static const struct snd_kcontrol_new right_input_mixer_controls[] = {
	SOC_DAPM_SINGLE("IN1_R P Switch", ADC3101_RMICPGAPIN, 6, 1, 0),
	SOC_DAPM_SINGLE("IN2_R P Switch", ADC3101_RMICPGAPIN, 4, 1, 0),
	SOC_DAPM_SINGLE("IN3_R P Switch", ADC3101_RMICPGAPIN, 2, 1, 0),
};

static const struct snd_soc_dapm_widget adc3101_dapm_widgets[] = {
	SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
			   &left_input_mixer_controls[0],
			   ARRAY_SIZE(left_input_mixer_controls)),
	SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
			   &right_input_mixer_controls[0],
			   ARRAY_SIZE(right_input_mixer_controls)),
	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ADC3101_ADCSETUP, 7, 0),
	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", ADC3101_ADCSETUP, 6, 0),
	SND_SOC_DAPM_MICBIAS("Mic Bias", ADC3101_MICBIAS, 6, 0),

	SND_SOC_DAPM_INPUT("IN1_L"),
	SND_SOC_DAPM_INPUT("IN1_R"),
	SND_SOC_DAPM_INPUT("IN2_L"),
	SND_SOC_DAPM_INPUT("IN2_R"),
	SND_SOC_DAPM_INPUT("IN3_L"),
	SND_SOC_DAPM_INPUT("IN3_R"),
};

static const struct snd_soc_dapm_route adc3101_dapm_routes[] = {
	/* Left input */
	{"Left Input Mixer", "IN1_L P Switch", "IN1_L"},
	{"Left Input Mixer", "IN2_L P Switch", "IN2_L"},
	{"Left Input Mixer", "IN3_L P Switch", "IN3_L"},

	{"Left ADC", NULL, "Left Input Mixer"},

	/* Right Input */
	{"Right Input Mixer", "IN1_R P Switch", "IN1_R"},
	{"Right Input Mixer", "IN2_R P Switch", "IN2_R"},
	{"Right Input Mixer", "IN3_R P Switch", "IN3_R"},

	{"Right ADC", NULL, "Right Input Mixer"},
};

static const struct regmap_range_cfg adc3101_regmap_pages[] = {
	{
		.range_min      = 0,
		.range_max      = ADC3101_RMICPGAVOL,
		.selector_reg   = ADC3101_PSEL,
		.selector_mask  = 0xff,
		.selector_shift = 0,
		.window_start   = 0,
		.window_len      = 128,
	},
};

static const struct regmap_config adc3101_i2c_regmap = {
	.reg_bits     = 8,
	.val_bits     = 8,
	.ranges       = adc3101_regmap_pages,
	.num_ranges   = ARRAY_SIZE(adc3101_regmap_pages),
	.max_register = ADC3101_RMICPGAVOL,
};

static inline int adc3101_get_divs(int mclk, int rate)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(adc3101_divs); i++) {
		if (adc3101_divs[i].rate == rate &&
		    adc3101_divs[i].mclk == mclk) {
			return i;
		}
	}

	pr_err("adc3101: master clock and sample rate is not supported\n");

	return -EINVAL;
}

static int adc3101_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				  int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_component *component = codec_dai->component;
	struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);

	pr_info("%s freq:%d\n", __func__, freq);
	switch (freq) {
	case ADC3101_FREQ_12000000:
	case ADC3101_FREQ_24000000:
	case ADC3101_FREQ_25000000:
	case ADC3101_FREQ_11289600:
	case ADC3101_FREQ_12288000:
	case ADC3101_FREQ_2048000:
	case ADC3101_FREQ_4096000:
	case ADC3101_FREQ_8192000:
		adc3101->sysclk = freq;
		return 0;
	}

	pr_err("adc3101: invalid frequency to set DAI system clock\n");
	return -1;
}

static int adc3101_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
	struct snd_soc_component *component = codec_dai->component;
	struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);
	u8 iface_reg_1;
	u8 dsp_a_val;
	u8 iface_reg_2;

	if (!adc3101)
		return -EINVAL;

	pr_info("[%s]:slot_number=%d\n", __func__, adc3101->slot_number);

	iface_reg_1 = snd_soc_component_read(component, ADC3101_IFACE1);
	iface_reg_1 = iface_reg_1 & ~(3 << 6 | 3 << 2);
	dsp_a_val = snd_soc_component_read(component,
					   ADC3101_DATASLOTOFFSETCTL);
	dsp_a_val = 0;
	iface_reg_2 = snd_soc_component_read(component, ADC3101_IFACE3);
	iface_reg_2 = iface_reg_2 & ~(1 << 3);

	/* set master/slave audio interface */
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBM_CFM:
		iface_reg_1 |= ADC3101_BCLKMASTER | ADC3101_WCLKMASTER;
		pr_info("%s DAIFMT_CBM_CFM\n", __func__);
		break;
	case SND_SOC_DAIFMT_CBS_CFS:
		break;
	default:
		pr_err("adc3101: invalid DAI master/slave interface\n");
		return -EINVAL;
	}
	/* set lrclk/bclk invertion */
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_IB_IF:
	case SND_SOC_DAIFMT_IB_NF:
		iface_reg_2 |= (1 << 3); /* invert bit clock */
		break;
	case SND_SOC_DAIFMT_NB_IF:
	case SND_SOC_DAIFMT_NB_NF:
		break;
	default:
		break;
	}

	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		break;
	case SND_SOC_DAIFMT_DSP_A:
		iface_reg_1 |= (ADC3101_DSP_MODE << ADC3101_PLLJ_SHIFT);
		iface_reg_2 |= (1 << 3); /* invert bit clock */

		/* set bclk offset according to different adc */
		if (adc3101->slot_number == 0)
			dsp_a_val = 0;
		else if (adc3101->slot_number == 1)
			dsp_a_val = 64;
		else if (adc3101->slot_number == 2)
			dsp_a_val = 128;
		else if (adc3101->slot_number == 3)
			dsp_a_val = 192;
		else
			dsp_a_val = 0x01; /* default add offset 1 */
		break;
	case SND_SOC_DAIFMT_DSP_B:
		iface_reg_1 |= (ADC3101_DSP_MODE << ADC3101_PLLJ_SHIFT);
		iface_reg_2 |= (1 << 3); /* invert bit clock */
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		iface_reg_1 |=
			(ADC3101_RIGHT_JUSTIFIED_MODE << ADC3101_PLLJ_SHIFT);
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		iface_reg_1 |=
			(ADC3101_LEFT_JUSTIFIED_MODE << ADC3101_PLLJ_SHIFT);
		break;
	default:
		pr_err("adc3101: invalid DAI interface format\n");
		return -EINVAL;
	}

	snd_soc_component_write(component, ADC3101_IFACE1, iface_reg_1);
	snd_soc_component_write(component, ADC3101_DATASLOTOFFSETCTL,
				dsp_a_val);
	snd_soc_component_write(component, ADC3101_IFACE3, iface_reg_2);

	return 0;
}

static int adc3101_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params,
			     struct snd_soc_dai *codec_dai)
{
	struct snd_soc_component *component = codec_dai->component;
	struct adc3101_priv *adc3101 = snd_soc_component_get_drvdata(component);

	u8 data;
	int i;

	i = adc3101_get_divs(adc3101->sysclk, params_rate(params));
	if (i < 0) {
		pr_err("adc3101: sampling rate not supported\n");
		return i;
	}

	/* Use PLL as CODEC_CLKIN and DAC_MOD_CLK as BDIV_CLKIN */
	snd_soc_component_write(component, ADC3101_CLKMUX, 0);

	/* We will fix R value to 1 and will make P & J=K.D as variable */
	data = snd_soc_component_read(component, ADC3101_PLLPR);
	data &= ~(7 << 4);

	snd_soc_component_write(component, ADC3101_PLLPR,
				(data | (adc3101_divs[i].p_val << 4) | 0x01));

	snd_soc_component_write(component, ADC3101_PLLJ, adc3101_divs[i].pll_j);

	snd_soc_component_write(component, ADC3101_PLLDMSB,
				(adc3101_divs[i].pll_d >> 8));
	snd_soc_component_write(component, ADC3101_PLLDLSB,
				(adc3101_divs[i].pll_d & 0xff));
	/* NADC divider value */
	data = snd_soc_component_read(component, ADC3101_NADC);
	data &= ~(0x7f);
	data |= 0x80;
	snd_soc_component_write(component, ADC3101_NADC,
				data | adc3101_divs[i].nadc);

	pr_info("%s NADC = 0x%02x\n",
		__func__,
		snd_soc_component_read(component, ADC3101_NADC));

	/* MADC divider value */
	data = snd_soc_component_read(component, ADC3101_MADC);
	data &= ~(0x7f);
	data |= 0x80;
	snd_soc_component_write(component, ADC3101_MADC,
				data | adc3101_divs[i].madc);

	pr_info("%s MADC = 0x%02x\n",
		__func__,
		snd_soc_component_read(component, ADC3101_MADC));

	/* AOSR value */
	snd_soc_component_write(component,
				ADC3101_AOSR, adc3101_divs[i].aosr);
	pr_info("%s AOSR=%02x\n",
		__func__,
		snd_soc_component_read(component, ADC3101_AOSR));

	data = snd_soc_component_read(component, ADC3101_IFACE1);
	data = data & ~(3 << 4);
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		break;
	case SNDRV_PCM_FORMAT_S20_3LE:
		data |= (ADC3101_WORD_LEN_20BITS << ADC3101_DOSRMSB_SHIFT);
		break;
	case SNDRV_PCM_FORMAT_S24_3LE:
	case SNDRV_PCM_FORMAT_S24_LE:
		data |= (ADC3101_WORD_LEN_24BITS << ADC3101_DOSRMSB_SHIFT);
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		data |= (ADC3101_WORD_LEN_32BITS << ADC3101_DOSRMSB_SHIFT);
		break;
	}
	snd_soc_component_write(component, ADC3101_IFACE1, data);
	pr_info("%s iface1 = %02x\n", __func__, data);

	snd_soc_component_write(component, ADC3101_MICBIAS, 0x50);

	if (adc3101->differential_pair == 1) {
		pr_info("%s differential pair\n", __func__);
		snd_soc_component_write(component,
					ADC3101_LMICPGANIN, 0x33); /* 54 */
		snd_soc_component_write(component,
					ADC3101_RMICPGANIN, 0x33); /* 57 */
		snd_soc_component_write(component,
					ADC3101_LMICPGAPIN, 0x3F); /* 52 */
		snd_soc_component_write(component,
					ADC3101_RMICPGAPIN, 0x3F); /* 55 */
	} else {
		pr_info("%s single end\n", __func__);
		snd_soc_component_write(component,
					ADC3101_LMICPGANIN, 0x3F); /* 54 */
		snd_soc_component_write(component,
					ADC3101_RMICPGANIN, 0x3F); /* 57 */
		snd_soc_component_write(component,
					ADC3101_LMICPGAPIN, 0xCF); /* 52 */
		snd_soc_component_write(component,
					ADC3101_RMICPGAPIN, 0xCF); /* 55 */
	}
	snd_soc_component_write(component, ADC3101_LMICPGAVOL, lr_gain);
	snd_soc_component_write(component, ADC3101_RMICPGAVOL, lr_gain);
	snd_soc_component_write(component, ADC3101_ADCSETUP, 0xc2);
	snd_soc_component_write(component, ADC3101_ADCFGA, 0);

	pr_info("%s ADCSETUP = %02x\n",
		__func__,
		snd_soc_component_read(component, ADC3101_ADCSETUP));
	pr_info("%s DOUTCTL=%02x\n",
		__func__,
		snd_soc_component_read(component, ADC3101_DOUTCTL));
	pr_info("%s MICBIAS=%02x\n",
		__func__,
		snd_soc_component_read(component, ADC3101_MICBIAS));

	return 0;
}

static int adc3101_mute(struct snd_soc_dai *dai, int mute)
{
	struct snd_soc_component *component = dai->component;
	u8 dac_reg;

	dac_reg = snd_soc_component_read(component, ADC3101_DACMUTE)
		& ~ADC3101_MUTEON;
	if (mute)
		snd_soc_component_write(component, ADC3101_DACMUTE,
					dac_reg | ADC3101_MUTEON);
	else
		snd_soc_component_write(component, ADC3101_DACMUTE, dac_reg);

	return 0;
}

static int adc3101_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
{
	return adc3101_mute(dai, mute); // ignore stream
}

static int adc3101_set_bias_level(struct snd_soc_component *component,
				  enum snd_soc_bias_level level)
{
	pr_debug("%s ..\n", __func__);

	switch (level) {
	case SND_SOC_BIAS_ON:
		/* Switch on PLL */
		snd_soc_component_update_bits(component, ADC3101_PLLPR,
					      ADC3101_PLLEN, ADC3101_PLLEN);

		/* Switch on NDAC Divider */
		snd_soc_component_update_bits(component, ADC3101_NDAC,
					      ADC3101_NDACEN, ADC3101_NDACEN);

		/* Switch on MDAC Divider */
		snd_soc_component_update_bits(component, ADC3101_MDAC,
					      ADC3101_MDACEN, ADC3101_MDACEN);

		/* Switch on NADC Divider */
		snd_soc_component_update_bits(component, ADC3101_NADC,
					      ADC3101_NADCEN, ADC3101_NADCEN);

		/* Switch on MADC Divider */
		snd_soc_component_update_bits(component, ADC3101_MADC,
					      ADC3101_MADCEN, ADC3101_MADCEN);

		/* Switch on BCLK_N Divider */
		snd_soc_component_update_bits(component, ADC3101_BCLKN,
					      ADC3101_BCLKEN, ADC3101_BCLKEN);

		break;
	case SND_SOC_BIAS_PREPARE:
		break;
	case SND_SOC_BIAS_STANDBY:
		/* Switch off PLL */
		snd_soc_component_update_bits(component, ADC3101_PLLPR,
					      ADC3101_PLLEN, 0);

		/* Switch off NDAC Divider */
		snd_soc_component_update_bits(component, ADC3101_NDAC,
					      ADC3101_NDACEN, 0);

		/* Switch off MDAC Divider */
		snd_soc_component_update_bits(component, ADC3101_MDAC,
					      ADC3101_MDACEN, 0);

		/* Switch off NADC Divider */
		snd_soc_component_update_bits(component, ADC3101_NADC,
					      ADC3101_NADCEN, 0);

		/* Switch off MADC Divider */
		snd_soc_component_update_bits(component, ADC3101_MADC,
					      ADC3101_MADCEN, 0);

		/* Switch off BCLK_N Divider */
		snd_soc_component_update_bits(component, ADC3101_BCLKN,
					      ADC3101_BCLKEN, 0);
		break;
	case SND_SOC_BIAS_OFF:
		break;
	}
	component->dapm.bias_level = level;

	return 0;
}

#define ADC3101_RATES	SNDRV_PCM_RATE_8000_96000
#define ADC3101_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE \
			 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)

static const struct snd_soc_dai_ops adc3101_ops = {
	.hw_params    = adc3101_hw_params,
	.mute_stream  = adc3101_mute_stream,
	.set_fmt      = adc3101_set_dai_fmt,
	.set_sysclk   = adc3101_set_dai_sysclk,
};

static struct snd_soc_dai_driver adc3101_dai[] = {
	{
		.name     = "tlv320adc3101-hifi",
		.playback = {
			.stream_name  = "Playback",
			.channels_min = 1,
			.channels_max = 2,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.capture  = {
			.stream_name  = "Capture",
			.channels_min = 1,
			.channels_max = 8,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.ops      = &adc3101_ops,
		.symmetric_rate = 1,
	},
	{
		.name     = "tlv320adc3101-hifi@19",
		.playback = {
			.stream_name  = "Playback",
			.channels_min = 1,
			.channels_max = 2,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.capture   = {
			.stream_name  = "Capture",
			.channels_min = 1,
			.channels_max = 8,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.ops       = &adc3101_ops,
		.symmetric_rate = 1,
	},
	{
		.name     = "tlv320adc3101-hifi@1a",
		.playback = {
			.stream_name  = "Playback",
			.channels_min = 1,
			.channels_max = 2,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.capture = {
			.stream_name  = "Capture",
			.channels_min = 1,
			.channels_max = 8,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.ops     = &adc3101_ops,
		.symmetric_rate = 1,
	},
	{
		.name     = "tlv320adc3101-hifi@1b",
		.playback = {
			.stream_name  = "Playback",
			.channels_min = 1,
			.channels_max = 2,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.capture  = {
			.stream_name  = "Capture",
			.channels_min = 1,
			.channels_max = 8,
			.rates        = ADC3101_RATES,
			.formats      = ADC3101_FORMATS,
		},
		.ops      = &adc3101_ops,
		.symmetric_rate = 1,
	},
};

static int adc3101_suspend(struct snd_soc_component *component)
{
	adc3101_set_bias_level(component, SND_SOC_BIAS_OFF);

	return 0;
}

static int adc3101_resume(struct snd_soc_component *component)
{
	adc3101_set_bias_level(component, SND_SOC_BIAS_STANDBY);

	return 0;
}

static int adc3101_codec_probe(struct snd_soc_component *component)
{
	u32 tmp_reg;

	snd_soc_component_write(component, ADC3101_RESET, 0x01);

	/*
	 * Workaround: for an unknown reason, the ADC needs to be powered up
	 * and down for the first capture to work properly. It seems related to
	 * a HW BUG or some kind of behavior not documented in the datasheet.
	 */
	tmp_reg = snd_soc_component_read(component, ADC3101_ADCSETUP);
	snd_soc_component_write(component, ADC3101_ADCSETUP, tmp_reg |
				ADC3101_LADC_EN | ADC3101_RADC_EN);
	snd_soc_component_write(component, ADC3101_ADCSETUP, tmp_reg);

	pr_info("%s done...\n", __func__);

	return 0;
}

static void adc3101_remove(struct snd_soc_component *component)
{
	adc3101_set_bias_level(component, SND_SOC_BIAS_OFF);
}

static const struct snd_soc_component_driver soc_codec_dev_adc3101 = {
	.probe            = adc3101_codec_probe,
	.remove           = adc3101_remove,
	.suspend          = adc3101_suspend,
	.resume           = adc3101_resume,
	.set_bias_level   = adc3101_set_bias_level,

	.controls         = adc3101_snd_controls,
	.num_controls     = ARRAY_SIZE(adc3101_snd_controls),
	.dapm_widgets     = adc3101_dapm_widgets,
	.num_dapm_widgets = ARRAY_SIZE(adc3101_dapm_widgets),
	.dapm_routes      = adc3101_dapm_routes,
	.num_dapm_routes  = ARRAY_SIZE(adc3101_dapm_routes),
};

static int adc3101_i2c_probe(struct i2c_client *i2c,
			     const struct i2c_device_id *id)
{
	struct adc3101_priv *adc3101 = NULL;
	int ret = 0;

	adc3101 = devm_kzalloc(&i2c->dev,
			       sizeof(struct adc3101_priv),
			       GFP_KERNEL);
	if (!adc3101)
		return -ENOMEM;

	adc3101->codec_cnt = 0;

	adc3101->regmap = devm_regmap_init_i2c(i2c, &adc3101_i2c_regmap);
	if (IS_ERR(adc3101->regmap)) {
		pr_info("%s failed devm_regmap_init_i2c\n", __func__);
		return PTR_ERR(adc3101->regmap);
	}
	i2c_set_clientdata(i2c, adc3101);

	adc3101->power_cfg = 0;
	adc3101->swapdacs = false;
	adc3101->micpga_routing = 0;
	adc3101->rstn_gpio = -1;

	ret = of_get_named_gpio(i2c->dev.of_node, "gpio-reset", 0);
	if (ret > 0)
		adc3101->rstn_gpio = ret;

	if (adc3101->rstn_gpio > 0) {
		ret = devm_gpio_request_one(&i2c->dev,
					    adc3101->rstn_gpio,
					    GPIOF_OUT_INIT_HIGH,
					    "adc3101-reset-pin");
		if (ret < 0) {
			dev_err(&i2c->dev, "not able to acquire gpio\n");
			return ret;
		}
	}
	ret = of_property_read_u32(i2c->dev.of_node, "differential_pair",
				   &adc3101->differential_pair);
	if (ret) {
		pr_warn("failed to get differential_pair, set it default:0\n");
		adc3101->differential_pair = 0;
	}

	ret = of_property_read_u32(i2c->dev.of_node, "slot_number",
				   &adc3101->slot_number);
	if (ret) {
		pr_warn("failed to get slot_number, set it default:0\n");
		adc3101->slot_number = 0;
	}
	ret = devm_snd_soc_register_component(&i2c->dev,
					      &soc_codec_dev_adc3101, adc3101_dai, 1);

	pr_info("%s %x done\n", __func__, i2c->addr);

	return ret;
}

static const struct of_device_id tlv320adc3101_of_match[] = {
	{.compatible = "ti,tlv320adc3101"},
	{},
};
MODULE_DEVICE_TABLE(of, tlv320adc3101_of_match);

static const struct i2c_device_id adc3101_i2c_id[] = {
	{ "tlv320adc3101", 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, adc3101_i2c_id);

static struct i2c_driver adc3101_i2c_driver = {
	.driver   = {
		.name           = DRV_NAME,
		.owner          = THIS_MODULE,
		.of_match_table = of_match_ptr(tlv320adc3101_of_match),
	},
	.probe    = adc3101_i2c_probe,
	.id_table = adc3101_i2c_id,
};

module_i2c_driver(adc3101_i2c_driver);

MODULE_DESCRIPTION("ASoC tlv320adc3101 codec driver");
MODULE_AUTHOR("alex.deng <alex.deng@amlogic.com>");
MODULE_LICENSE("GPL");
