From c444c94de10f280fdae6a6d83d3ca1be97ad6f77 Mon Sep 17 00:00:00 2001 From: amazingfate Date: Tue, 24 Dec 2024 00:47:45 +0800 Subject: [PATCH] rockchip64-6.13: revert rk3308 analog codec to vendor code --- .../rk3308-acodec-vendor-driver.patch | 7159 +++++++++++++++++ .../rk3308-enable-acodec-verb.patch | 13 - 2 files changed, 7159 insertions(+), 13 deletions(-) create mode 100644 patch/kernel/archive/rockchip64-6.13/rk3308-acodec-vendor-driver.patch delete mode 100644 patch/kernel/archive/rockchip64-6.13/rk3308-enable-acodec-verb.patch diff --git a/patch/kernel/archive/rockchip64-6.13/rk3308-acodec-vendor-driver.patch b/patch/kernel/archive/rockchip64-6.13/rk3308-acodec-vendor-driver.patch new file mode 100644 index 000000000..93b301012 --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.13/rk3308-acodec-vendor-driver.patch @@ -0,0 +1,7159 @@ +From 919c736d71b5c7d311b41e96e67985d34f1937f7 Mon Sep 17 00:00:00 2001 +From: Paolo Sabatino +Date: Fri, 20 Dec 2024 11:48:31 +0100 +Subject: [PATCH] revert rk3308 analog codec to vendor code + +--- + arch/arm64/boot/dts/rockchip/rk3308.dtsi | 146 +- + sound/soc/codecs/rk3308_codec.c | 5681 +++++++++++++++++++--- + sound/soc/codecs/rk3308_codec.h | 892 +++- + sound/soc/codecs/rk3308_codec_provider.h | 28 + + 4 files changed, 5804 insertions(+), 943 deletions(-) + create mode 100644 sound/soc/codecs/rk3308_codec_provider.h + +diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +index 31c25de2d689..1e9a82423d28 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi +@@ -836,11 +975,14 @@ codec: codec@ff560000 { + compatible = "rockchip,rk3308-codec"; + reg = <0x0 0xff560000 0x0 0x10000>; + rockchip,grf = <&grf>; +- clock-names = "mclk_tx", "mclk_rx", "hclk"; ++ rockchip,detect-grf = <&detect_grf>; ++ clock-names = "mclk_tx", "mclk_rx", "acodec"; + clocks = <&cru SCLK_I2S2_8CH_TX_OUT>, + <&cru SCLK_I2S2_8CH_RX_OUT>, + <&cru PCLK_ACODEC>; +- reset-names = "codec"; ++ interrupts = <&gic 114 IRQ_TYPE_LEVEL_HIGH>, ++ <&gic 115 IRQ_TYPE_LEVEL_HIGH>; ++ reset-names = "acodec-reset"; + resets = <&cru SRST_ACODEC_P>; + #sound-dai-cells = <0>; + status = "disabled"; +diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c +index 8b51e87a1711..e918b4e3cb48 100644 +--- a/sound/soc/codecs/rk3308_codec.c ++++ b/sound/soc/codecs/rk3308_codec.c +@@ -1,9 +1,20 @@ +-// SPDX-License-Identifier: GPL-2.0-only + /* +- * Rockchip RK3308 internal audio codec driver ++ * rk3308_codec.c -- RK3308 ALSA Soc Audio Driver + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. +- * Copyright (c) 2024, Vivax-Metrotech Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * + */ + + #include +@@ -14,961 +25,5151 @@ + #include + #include + #include ++#include + #include ++#include + #include ++#include + #include +-#include ++// #include ++#include + #include ++#include ++#include ++#include + #include + #include ++#include + #include + #include + + #include "rk3308_codec.h" ++#include "rk3308_codec_provider.h" + ++#if defined(CONFIG_DEBUG_FS) ++#include ++#include ++#include ++#endif ++ ++#define CODEC_DRV_NAME "rk3308-acodec" ++ ++#define ADC_GRP_SKIP_MAGIC 0x1001 + #define ADC_LR_GROUP_MAX 4 ++#define ADC_STABLE_MS 200 ++#define DEBUG_POP_ALWAYS 0 ++#define HPDET_POLL_MS 2000 ++#define NOT_USED 255 ++#define LOOPBACK_HANDLE_MS 100 ++#define PA_DRV_MS 5 + ++#define GRF_SOC_CON1 0x304 + #define GRF_CHIP_ID 0x800 ++#define GRF_I2S2_8CH_SDI_SFT 0 ++#define GRF_I2S3_4CH_SDI_SFT 8 ++#define GRF_I2S1_2CH_SDI_SFT 12 ++ ++#define GRF_I2S2_8CH_SDI_R_MSK(i, v) ((v >> (i * 2 + GRF_I2S2_8CH_SDI_SFT)) & 0x3) ++#define GRF_I2S2_8CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S2_8CH_SDI_SFT + 16)) ++#define GRF_I2S2_8CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S2_8CH_SDI_SFT)) |\ ++ GRF_I2S2_8CH_SDI_W_MSK(i)) ++ ++#define GRF_I2S3_4CH_SDI_W_MSK(i) (0x3 << (i * 2 + GRF_I2S3_4CH_SDI_SFT + 16)) ++#define GRF_I2S3_4CH_SDI(i, v) (((v & 0x3) << (i * 2 + GRF_I2S3_4CH_SDI_SFT)) |\ ++ GRF_I2S3_4CH_SDI_W_MSK(i)) ++ ++#define GRF_I2S1_2CH_SDI_W_MSK (0x3 << (GRF_I2S1_2CH_SDI_SFT + 16)) ++#define GRF_I2S1_2CH_SDI(v) (((v & 0x3) << GRF_I2S1_2CH_SDI_SFT) |\ ++ GRF_I2S1_2CH_SDI_W_MSK) ++ ++#define DETECT_GRF_ACODEC_HPDET_COUNTER 0x0030 ++#define DETECT_GRF_ACODEC_HPDET_CON 0x0034 ++#define DETECT_GRF_ACODEC_HPDET_STATUS 0x0038 ++#define DETECT_GRF_ACODEC_HPDET_STATUS_CLR 0x003c ++ ++/* 200ms based on pclk is 100MHz */ ++#define DEFAULT_HPDET_COUNT 20000000 ++#define HPDET_NEG_IRQ_SFT 1 ++#define HPDET_POS_IRQ_SFT 0 ++#define HPDET_BOTH_NEG_POS ((1 << HPDET_NEG_IRQ_SFT) |\ ++ (1 << HPDET_POS_IRQ_SFT)) ++ ++#define ACODEC_VERSION_A 0xa ++#define ACODEC_VERSION_B 0xb ++ ++enum { ++ ACODEC_TO_I2S2_8CH = 0, ++ ACODEC_TO_I2S3_4CH, ++ ACODEC_TO_I2S1_2CH, ++}; ++ ++enum { ++ ADC_GRP0_MICIN = 0, ++ ADC_GRP0_LINEIN ++}; ++ ++enum { ++ ADC_TYPE_NORMAL = 0, ++ ADC_TYPE_LOOPBACK, ++ ADC_TYPE_DBG, ++ ADC_TYPE_ALL, ++}; ++ ++enum { ++ DAC_LINEOUT = 0, ++ DAC_HPOUT = 1, ++ DAC_LINEOUT_HPOUT = 11, ++}; + + enum { +- ACODEC_VERSION_A = 'A', +- ACODEC_VERSION_B, +- ACODEC_VERSION_C, ++ EXT_MICBIAS_NONE = 0, ++ EXT_MICBIAS_FUNC1, /* enable external micbias via GPIO */ ++ EXT_MICBIAS_FUNC2, /* enable external micbias via regulator */ ++}; ++ ++enum { ++ PATH_IDLE = 0, ++ PATH_BUSY, ++}; ++ ++enum { ++ PM_NORMAL = 0, ++ PM_LLP_DOWN, /* light low power down */ ++ PM_LLP_UP, ++ PM_DLP_DOWN, /* deep low power down */ ++ PM_DLP_UP, ++ PM_DLP_DOWN2, ++ PM_DLP_UP2, + }; + + struct rk3308_codec_priv { +- const struct device *dev; ++ const struct device *plat_dev; ++ struct device dev; ++ struct reset_control *reset; + struct regmap *regmap; + struct regmap *grf; +- struct reset_control *reset; +- struct clk *hclk; ++ struct regmap *detect_grf; ++ struct clk *pclk; + struct clk *mclk_rx; + struct clk *mclk_tx; ++ struct gpio_desc *micbias_en_gpio; ++ struct gpio_desc *hp_ctl_gpio; ++ struct gpio_desc *spk_ctl_gpio; ++ struct gpio_desc *pa_drv_gpio; + struct snd_soc_component *component; +- unsigned char codec_ver; +-}; ++ struct snd_soc_jack *hpdet_jack; ++ struct regulator *vcc_micbias; ++ u32 codec_ver; ++ ++ /* ++ * To select ADCs for groups: ++ * ++ * grp 0 -- select ADC1 / ADC2 ++ * grp 1 -- select ADC3 / ADC4 ++ * grp 2 -- select ADC5 / ADC6 ++ * grp 3 -- select ADC7 / ADC8 ++ */ ++ u32 used_adc_grps; ++ /* The ADC group which is used for loop back */ ++ u32 loopback_grp; ++ u32 cur_dbg_grp; ++ u32 en_always_grps[ADC_LR_GROUP_MAX]; ++ u32 en_always_grps_num; ++ u32 skip_grps[ADC_LR_GROUP_MAX]; ++ u32 i2s_sdis[ADC_LR_GROUP_MAX]; ++ u32 to_i2s_grps; ++ u32 delay_loopback_handle_ms; ++ u32 delay_start_play_ms; ++ u32 delay_pa_drv_ms; ++ u32 micbias_num; ++ u32 micbias_volt; ++ int which_i2s; ++ int irq; ++ int adc_grp0_using_linein; ++ int adc_zerocross; ++ /* 0: line out, 1: hp out, 11: lineout and hpout */ ++ int dac_output; ++ int dac_path_state; ++ ++ int ext_micbias; ++ int pm_state; ++ ++ /* AGC L/R Off/on */ ++ unsigned int agc_l[ADC_LR_GROUP_MAX]; ++ unsigned int agc_r[ADC_LR_GROUP_MAX]; + +-static struct clk_bulk_data rk3308_codec_clocks[] = { +- { .id = "hclk" }, +- { .id = "mclk_rx" }, +- { .id = "mclk_tx" }, ++ /* AGC L/R Approximate Sample Rate */ ++ unsigned int agc_asr_l[ADC_LR_GROUP_MAX]; ++ unsigned int agc_asr_r[ADC_LR_GROUP_MAX]; ++ ++ /* ADC MIC Mute/Work */ ++ unsigned int mic_mute_l[ADC_LR_GROUP_MAX]; ++ unsigned int mic_mute_r[ADC_LR_GROUP_MAX]; ++ ++ /* For the high pass filter */ ++ unsigned int hpf_cutoff[ADC_LR_GROUP_MAX]; ++ ++ /* Only hpout do fade-in and fade-out */ ++ unsigned int hpout_l_dgain; ++ unsigned int hpout_r_dgain; ++ ++ bool adc_grps_endisable[ADC_LR_GROUP_MAX]; ++ bool dac_endisable; ++ bool enable_all_adcs; ++ bool enable_micbias; ++ bool micbias1; ++ bool micbias2; ++ bool hp_jack_reversed; ++ bool hp_plugged; ++ bool loopback_dacs_enabled; ++ bool no_deep_low_power; ++ bool no_hp_det; ++ struct delayed_work hpdet_work; ++ struct delayed_work loopback_work; ++ ++#if defined(CONFIG_DEBUG_FS) ++ struct dentry *dbg_codec; ++#endif + }; + +-static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, -1800, 150, 0); +-static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, -3900, 150, 0); +-static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, -600, 600, 0); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_gain_tlv, ++ -1800, 150, 2850); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_max_gain_tlv, ++ -1350, 600, 2850); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_alc_agc_grp_min_gain_tlv, ++ -1800, 600, 2400); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, ++ -1800, 150, 2850); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_lineout_gain_tlv, ++ -600, 150, 0); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, ++ -3900, 150, 600); ++static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, ++ -600, 600, 0); ++ ++static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_a, ++ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), ++ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), ++); + +-static const DECLARE_TLV_DB_RANGE(rk3308_codec_dac_lineout_gain_tlv, +- 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), +- 1, 1, TLV_DB_SCALE_ITEM(-300, 0, 0), +- 2, 2, TLV_DB_SCALE_ITEM(-150, 0, 0), +- 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), ++static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_b, ++ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), ++ 1, 1, TLV_DB_SCALE_ITEM(660, 0, 0), ++ 2, 2, TLV_DB_SCALE_ITEM(1300, 0, 0), ++ 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), + ); + +-static const char * const rk3308_codec_hpf_cutoff_text[] = { +- "20 Hz", "245 Hz", "612 Hz" ++static bool handle_loopback(struct rk3308_codec_priv *rk3308); ++ ++static int check_micbias(int micbias); ++ ++static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, ++ int micbias); ++static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308); ++ ++static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol); ++ ++static const char *offon_text[2] = { ++ [0] = "Off", ++ [1] = "On", ++}; ++ ++static const char *mute_text[2] = { ++ [0] = "Work", ++ [1] = "Mute", ++}; ++ ++/* ADC MICBIAS Volt */ ++#define MICBIAS_VOLT_NUM 8 ++ ++#define MICBIAS_VREFx0_5 0 ++#define MICBIAS_VREFx0_55 1 ++#define MICBIAS_VREFx0_6 2 ++#define MICBIAS_VREFx0_65 3 ++#define MICBIAS_VREFx0_7 4 ++#define MICBIAS_VREFx0_75 5 ++#define MICBIAS_VREFx0_8 6 ++#define MICBIAS_VREFx0_85 7 ++ ++static const char *micbias_volts_enum_array[MICBIAS_VOLT_NUM] = { ++ [MICBIAS_VREFx0_5] = "VREFx0_5", ++ [MICBIAS_VREFx0_55] = "VREFx0_55", ++ [MICBIAS_VREFx0_6] = "VREFx0_6", ++ [MICBIAS_VREFx0_65] = "VREFx0_65", ++ [MICBIAS_VREFx0_7] = "VREFx0_7", ++ [MICBIAS_VREFx0_75] = "VREFx0_75", ++ [MICBIAS_VREFx0_8] = "VREFx0_8", ++ [MICBIAS_VREFx0_85] = "VREFx0_85", ++}; ++ ++static const struct soc_enum rk3308_micbias_volts_enum_array[] = { ++ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(micbias_volts_enum_array), micbias_volts_enum_array), ++}; ++ ++/* ADC MICBIAS1 and MICBIAS2 Main Switch */ ++static const struct soc_enum rk3308_main_micbias_enum_array[] = { ++ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), ++}; ++ ++static const struct soc_enum rk3308_hpf_enum_array[] = { ++ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text), ++}; ++ ++/* ALC AGC Switch */ ++static const struct soc_enum rk3308_agc_enum_array[] = { ++ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(offon_text), offon_text), ++ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(offon_text), offon_text), ++}; ++ ++/* ADC MIC Mute/Work Switch */ ++static const struct soc_enum rk3308_mic_mute_enum_array[] = { ++ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(mute_text), mute_text), ++ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(mute_text), mute_text), ++}; ++ ++/* ALC AGC Approximate Sample Rate */ ++#define AGC_ASR_NUM 8 ++ ++#define AGC_ASR_96KHZ 0 ++#define AGC_ASR_48KHZ 1 ++#define AGC_ASR_44_1KHZ 2 ++#define AGC_ASR_32KHZ 3 ++#define AGC_ASR_24KHZ 4 ++#define AGC_ASR_16KHZ 5 ++#define AGC_ASR_12KHZ 6 ++#define AGC_ASR_8KHZ 7 ++ ++static const char *agc_asr_text[AGC_ASR_NUM] = { ++ [AGC_ASR_96KHZ] = "96KHz", ++ [AGC_ASR_48KHZ] = "48KHz", ++ [AGC_ASR_44_1KHZ] = "44.1KHz", ++ [AGC_ASR_32KHZ] = "32KHz", ++ [AGC_ASR_24KHZ] = "24KHz", ++ [AGC_ASR_16KHZ] = "16KHz", ++ [AGC_ASR_12KHZ] = "12KHz", ++ [AGC_ASR_8KHZ] = "8KHz", ++}; ++ ++static const struct soc_enum rk3308_agc_asr_enum_array[] = { ++ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++ SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(agc_asr_text), agc_asr_text), ++}; ++ ++static const struct snd_kcontrol_new mic_gains_a[] = { ++ /* ADC MIC */ ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Volume", ++ RK3308_ADC_ANA_CON01(0), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Volume", ++ RK3308_ADC_ANA_CON01(0), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Volume", ++ RK3308_ADC_ANA_CON01(1), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Volume", ++ RK3308_ADC_ANA_CON01(1), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Volume", ++ RK3308_ADC_ANA_CON01(2), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Volume", ++ RK3308_ADC_ANA_CON01(2), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Volume", ++ RK3308_ADC_ANA_CON01(3), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Volume", ++ RK3308_ADC_ANA_CON01(3), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_a), ++}; ++ ++static const struct snd_kcontrol_new mic_gains_b[] = { ++ /* ADC MIC */ ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Left Volume", ++ RK3308_ADC_ANA_CON01(0), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 0 Right Volume", ++ RK3308_ADC_ANA_CON01(0), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Left Volume", ++ RK3308_ADC_ANA_CON01(1), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 1 Right Volume", ++ RK3308_ADC_ANA_CON01(1), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Left Volume", ++ RK3308_ADC_ANA_CON01(2), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 2 Right Volume", ++ RK3308_ADC_ANA_CON01(2), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Left Volume", ++ RK3308_ADC_ANA_CON01(3), ++ RK3308_ADC_CH1_MIC_GAIN_SFT, ++ RK3308_ADC_CH1_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), ++ SOC_SINGLE_EXT_TLV("ADC MIC Group 3 Right Volume", ++ RK3308_ADC_ANA_CON01(3), ++ RK3308_ADC_CH2_MIC_GAIN_SFT, ++ RK3308_ADC_CH2_MIC_GAIN_MAX, ++ 0, ++ rk3308_codec_mic_gain_get, ++ rk3308_codec_mic_gain_put, ++ rk3308_codec_adc_mic_gain_tlv_b), + }; + +-static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum12, RK3308_ADC_DIG_CON04(0), 0, +- rk3308_codec_hpf_cutoff_text); +-static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum34, RK3308_ADC_DIG_CON04(1), 0, +- rk3308_codec_hpf_cutoff_text); +-static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum56, RK3308_ADC_DIG_CON04(2), 0, +- rk3308_codec_hpf_cutoff_text); +-static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum78, RK3308_ADC_DIG_CON04(3), 0, +- rk3308_codec_hpf_cutoff_text); +- +-static const struct snd_kcontrol_new rk3308_codec_controls[] = { +- /* Despite the register names, these set the gain when AGC is OFF */ +- SOC_SINGLE_RANGE_TLV("MIC1 Capture Volume", ++static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = { ++ /* ALC AGC Group */ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Volume", ++ RK3308_ALC_L_DIG_CON03(0), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Volume", ++ RK3308_ALC_R_DIG_CON03(0), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Volume", ++ RK3308_ALC_L_DIG_CON03(1), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Volume", ++ RK3308_ALC_R_DIG_CON03(1), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Volume", ++ RK3308_ALC_L_DIG_CON03(2), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Volume", ++ RK3308_ALC_R_DIG_CON03(2), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Volume", ++ RK3308_ALC_L_DIG_CON03(3), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Volume", ++ RK3308_ALC_R_DIG_CON03(3), ++ RK3308_AGC_PGA_GAIN_SFT, ++ RK3308_AGC_PGA_GAIN_MIN, ++ RK3308_AGC_PGA_GAIN_MAX, ++ 0, rk3308_codec_alc_agc_grp_gain_tlv), ++ ++ /* ALC AGC MAX */ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Max Volume", ++ RK3308_ALC_L_DIG_CON09(0), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Max Volume", ++ RK3308_ALC_R_DIG_CON09(0), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Max Volume", ++ RK3308_ALC_L_DIG_CON09(1), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Max Volume", ++ RK3308_ALC_R_DIG_CON09(1), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Max Volume", ++ RK3308_ALC_L_DIG_CON09(2), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Max Volume", ++ RK3308_ALC_R_DIG_CON09(2), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Max Volume", ++ RK3308_ALC_L_DIG_CON09(3), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Max Volume", ++ RK3308_ALC_R_DIG_CON09(3), ++ RK3308_AGC_MAX_GAIN_PGA_SFT, ++ RK3308_AGC_MAX_GAIN_PGA_MIN, ++ RK3308_AGC_MAX_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_max_gain_tlv), ++ ++ /* ALC AGC MIN */ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Left Min Volume", ++ RK3308_ALC_L_DIG_CON09(0), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 0 Right Min Volume", ++ RK3308_ALC_R_DIG_CON09(0), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Left Min Volume", ++ RK3308_ALC_L_DIG_CON09(1), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 1 Right Min Volume", ++ RK3308_ALC_R_DIG_CON09(1), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Left Min Volume", ++ RK3308_ALC_L_DIG_CON09(2), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 2 Right Min Volume", ++ RK3308_ALC_R_DIG_CON09(2), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Left Min Volume", ++ RK3308_ALC_L_DIG_CON09(3), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("ALC AGC Group 3 Right Min Volume", ++ RK3308_ALC_R_DIG_CON09(3), ++ RK3308_AGC_MIN_GAIN_PGA_SFT, ++ RK3308_AGC_MIN_GAIN_PGA_MIN, ++ RK3308_AGC_MIN_GAIN_PGA_MAX, ++ 0, rk3308_codec_alc_agc_grp_min_gain_tlv), ++ ++ /* ALC AGC Switch */ ++ SOC_ENUM_EXT("ALC AGC Group 0 Left Switch", rk3308_agc_enum_array[0], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 0 Right Switch", rk3308_agc_enum_array[1], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 1 Left Switch", rk3308_agc_enum_array[2], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 1 Right Switch", rk3308_agc_enum_array[3], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 2 Left Switch", rk3308_agc_enum_array[4], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 2 Right Switch", rk3308_agc_enum_array[5], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 3 Left Switch", rk3308_agc_enum_array[6], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ SOC_ENUM_EXT("ALC AGC Group 3 Right Switch", rk3308_agc_enum_array[7], ++ rk3308_codec_agc_get, rk3308_codec_agc_put), ++ ++ /* ALC AGC Approximate Sample Rate */ ++ SOC_ENUM_EXT("AGC Group 0 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[0], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 0 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[1], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 1 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[2], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 1 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[3], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 2 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[4], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 2 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[5], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 3 Left Approximate Sample Rate", rk3308_agc_asr_enum_array[6], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ SOC_ENUM_EXT("AGC Group 3 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[7], ++ rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put), ++ ++ /* ADC MICBIAS Voltage */ ++ SOC_ENUM_EXT("ADC MICBIAS Voltage", rk3308_micbias_volts_enum_array[0], ++ rk3308_codec_micbias_volts_get, rk3308_codec_micbias_volts_put), ++ ++ /* ADC Main MICBIAS Switch */ ++ SOC_ENUM_EXT("ADC Main MICBIAS", rk3308_main_micbias_enum_array[0], ++ rk3308_codec_main_micbias_get, rk3308_codec_main_micbias_put), ++ ++ /* ADC MICBIAS1 and MICBIAS2 Switch */ ++ SOC_SINGLE("ADC MICBIAS1", RK3308_ADC_ANA_CON07(1), ++ RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0), ++ SOC_SINGLE("ADC MICBIAS2", RK3308_ADC_ANA_CON07(2), ++ RK3308_ADC_MIC_BIAS_BUF_SFT, 1, 0), ++ ++ /* ADC MIC Mute/Work Switch */ ++ SOC_ENUM_EXT("ADC MIC Group 0 Left Switch", rk3308_mic_mute_enum_array[0], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 0 Right Switch", rk3308_mic_mute_enum_array[1], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 1 Left Switch", rk3308_mic_mute_enum_array[2], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 1 Right Switch", rk3308_mic_mute_enum_array[3], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 2 Left Switch", rk3308_mic_mute_enum_array[4], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 2 Right Switch", rk3308_mic_mute_enum_array[5], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 3 Left Switch", rk3308_mic_mute_enum_array[6], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ SOC_ENUM_EXT("ADC MIC Group 3 Right Switch", rk3308_mic_mute_enum_array[7], ++ rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put), ++ ++ /* ADC ALC */ ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Left Volume", + RK3308_ADC_ANA_CON03(0), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC2 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 0 Right Volume", + RK3308_ADC_ANA_CON04(0), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC3 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Left Volume", + RK3308_ADC_ANA_CON03(1), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC4 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 1 Right Volume", + RK3308_ADC_ANA_CON04(1), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC5 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Left Volume", + RK3308_ADC_ANA_CON03(2), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC6 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 2 Right Volume", + RK3308_ADC_ANA_CON04(2), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC7 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Left Volume", + RK3308_ADC_ANA_CON03(3), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), +- SOC_SINGLE_RANGE_TLV("MIC8 Capture Volume", ++ SOC_SINGLE_RANGE_TLV("ADC ALC Group 3 Right Volume", + RK3308_ADC_ANA_CON04(3), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + +- SOC_SINGLE("MIC1 Capture Switch", RK3308_ADC_ANA_CON00(0), 3, 1, 0), +- SOC_SINGLE("MIC2 Capture Switch", RK3308_ADC_ANA_CON00(0), 7, 1, 0), +- SOC_SINGLE("MIC3 Capture Switch", RK3308_ADC_ANA_CON00(1), 3, 1, 0), +- SOC_SINGLE("MIC4 Capture Switch", RK3308_ADC_ANA_CON00(1), 7, 1, 0), +- SOC_SINGLE("MIC5 Capture Switch", RK3308_ADC_ANA_CON00(2), 3, 1, 0), +- SOC_SINGLE("MIC6 Capture Switch", RK3308_ADC_ANA_CON00(2), 7, 1, 0), +- SOC_SINGLE("MIC7 Capture Switch", RK3308_ADC_ANA_CON00(3), 3, 1, 0), +- SOC_SINGLE("MIC8 Capture Switch", RK3308_ADC_ANA_CON00(3), 7, 1, 0), +- +- SOC_SINGLE("MIC12 HPF Capture Switch", RK3308_ADC_DIG_CON04(0), 2, 1, 1), +- SOC_SINGLE("MIC34 HPF Capture Switch", RK3308_ADC_DIG_CON04(1), 2, 1, 1), +- SOC_SINGLE("MIC56 HPF Capture Switch", RK3308_ADC_DIG_CON04(2), 2, 1, 1), +- SOC_SINGLE("MIC78 HPF Capture Switch", RK3308_ADC_DIG_CON04(3), 2, 1, 1), +- +- SOC_ENUM("MIC12 HPF Cutoff", rk3308_codec_hpf_cutoff_enum12), +- SOC_ENUM("MIC34 HPF Cutoff", rk3308_codec_hpf_cutoff_enum34), +- SOC_ENUM("MIC56 HPF Cutoff", rk3308_codec_hpf_cutoff_enum56), +- SOC_ENUM("MIC78 HPF Cutoff", rk3308_codec_hpf_cutoff_enum78), +- +- SOC_DOUBLE_TLV("Line Out Playback Volume", ++ /* ADC High Pass Filter */ ++ SOC_ENUM_EXT("ADC Group 0 HPF Cut-off", rk3308_hpf_enum_array[0], ++ rk3308_codec_hpf_get, rk3308_codec_hpf_put), ++ SOC_ENUM_EXT("ADC Group 1 HPF Cut-off", rk3308_hpf_enum_array[1], ++ rk3308_codec_hpf_get, rk3308_codec_hpf_put), ++ SOC_ENUM_EXT("ADC Group 2 HPF Cut-off", rk3308_hpf_enum_array[2], ++ rk3308_codec_hpf_get, rk3308_codec_hpf_put), ++ SOC_ENUM_EXT("ADC Group 3 HPF Cut-off", rk3308_hpf_enum_array[3], ++ rk3308_codec_hpf_get, rk3308_codec_hpf_put), ++ ++ /* DAC LINEOUT */ ++ SOC_SINGLE_TLV("DAC LINEOUT Left Volume", + RK3308_DAC_ANA_CON04, + RK3308_DAC_L_LINEOUT_GAIN_SFT, ++ RK3308_DAC_L_LINEOUT_GAIN_MAX, ++ 0, rk3308_codec_dac_lineout_gain_tlv), ++ SOC_SINGLE_TLV("DAC LINEOUT Right Volume", ++ RK3308_DAC_ANA_CON04, + RK3308_DAC_R_LINEOUT_GAIN_SFT, +- RK3308_DAC_x_LINEOUT_GAIN_MAX, ++ RK3308_DAC_R_LINEOUT_GAIN_MAX, + 0, rk3308_codec_dac_lineout_gain_tlv), +- SOC_DOUBLE("Line Out Playback Switch", +- RK3308_DAC_ANA_CON04, +- RK3308_DAC_L_LINEOUT_MUTE_SFT, +- RK3308_DAC_R_LINEOUT_MUTE_SFT, 1, 0), +- SOC_DOUBLE_R_TLV("Headphone Playback Volume", +- RK3308_DAC_ANA_CON05, +- RK3308_DAC_ANA_CON06, +- RK3308_DAC_x_HPOUT_GAIN_SFT, +- RK3308_DAC_x_HPOUT_GAIN_MAX, +- 0, rk3308_codec_dac_hpout_gain_tlv), +- SOC_DOUBLE("Headphone Playback Switch", +- RK3308_DAC_ANA_CON03, +- RK3308_DAC_L_HPOUT_MUTE_SFT, +- RK3308_DAC_R_HPOUT_MUTE_SFT, 1, 0), +- SOC_DOUBLE_RANGE_TLV("DAC HPMIX Playback Volume", ++ ++ /* DAC HPOUT */ ++ SOC_SINGLE_EXT_TLV("DAC HPOUT Left Volume", ++ RK3308_DAC_ANA_CON05, ++ RK3308_DAC_L_HPOUT_GAIN_SFT, ++ RK3308_DAC_L_HPOUT_GAIN_MAX, ++ 0, ++ rk3308_codec_hpout_l_get_tlv, ++ rk3308_codec_hpout_l_put_tlv, ++ rk3308_codec_dac_hpout_gain_tlv), ++ SOC_SINGLE_EXT_TLV("DAC HPOUT Right Volume", ++ RK3308_DAC_ANA_CON06, ++ RK3308_DAC_R_HPOUT_GAIN_SFT, ++ RK3308_DAC_R_HPOUT_GAIN_MAX, ++ 0, ++ rk3308_codec_hpout_r_get_tlv, ++ rk3308_codec_hpout_r_put_tlv, ++ rk3308_codec_dac_hpout_gain_tlv), ++ ++ /* DAC HPMIX */ ++ SOC_SINGLE_RANGE_TLV("DAC HPMIX Left Volume", + RK3308_DAC_ANA_CON12, + RK3308_DAC_L_HPMIX_GAIN_SFT, ++ RK3308_DAC_L_HPMIX_GAIN_MIN, ++ RK3308_DAC_L_HPMIX_GAIN_MAX, ++ 0, rk3308_codec_dac_hpmix_gain_tlv), ++ SOC_SINGLE_RANGE_TLV("DAC HPMIX Right Volume", ++ RK3308_DAC_ANA_CON12, + RK3308_DAC_R_HPMIX_GAIN_SFT, +- 1, 2, 0, rk3308_codec_dac_hpmix_gain_tlv), ++ RK3308_DAC_R_HPMIX_GAIN_MIN, ++ RK3308_DAC_R_HPMIX_GAIN_MAX, ++ 0, rk3308_codec_dac_hpmix_gain_tlv), + }; + +-static int rk3308_codec_pop_sound_set(struct snd_soc_dapm_widget *w, +- struct snd_kcontrol *kcontrol, +- int event) ++static int rk3308_codec_agc_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); +- unsigned int val = (event == SND_SOC_DAPM_POST_PMU) ? +- RK3308_DAC_HPOUT_POP_SOUND_x_WORK : +- RK3308_DAC_HPOUT_POP_SOUND_x_INIT; +- unsigned int mask = RK3308_DAC_HPOUT_POP_SOUND_x_MSK; ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + +- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, +- mask << w->shift, val << w->shift); +- +- return 0; +-} +- +-static const struct snd_soc_dapm_widget rk3308_codec_dapm_widgets[] = { +- SND_SOC_DAPM_INPUT("MIC1"), +- SND_SOC_DAPM_INPUT("MIC2"), +- SND_SOC_DAPM_INPUT("MIC3"), +- SND_SOC_DAPM_INPUT("MIC4"), +- SND_SOC_DAPM_INPUT("MIC5"), +- SND_SOC_DAPM_INPUT("MIC6"), +- SND_SOC_DAPM_INPUT("MIC7"), +- SND_SOC_DAPM_INPUT("MIC8"), +- +- SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN12", RK3308_ADC_ANA_CON06(0), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN34", RK3308_ADC_ANA_CON06(1), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN56", RK3308_ADC_ANA_CON06(2), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN78", RK3308_ADC_ANA_CON06(3), 0, 0, NULL, 0), +- +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC1_EN", RK3308_ADC_ANA_CON00(0), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC2_EN", RK3308_ADC_ANA_CON00(0), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC3_EN", RK3308_ADC_ANA_CON00(1), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC4_EN", RK3308_ADC_ANA_CON00(1), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC5_EN", RK3308_ADC_ANA_CON00(2), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC6_EN", RK3308_ADC_ANA_CON00(2), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC7_EN", RK3308_ADC_ANA_CON00(3), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC8_EN", RK3308_ADC_ANA_CON00(3), 5, 1, 1, 0), +- +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC1_WORK", RK3308_ADC_ANA_CON00(0), 2, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC2_WORK", RK3308_ADC_ANA_CON00(0), 6, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC3_WORK", RK3308_ADC_ANA_CON00(1), 2, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC4_WORK", RK3308_ADC_ANA_CON00(1), 6, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC5_WORK", RK3308_ADC_ANA_CON00(2), 2, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC6_WORK", RK3308_ADC_ANA_CON00(2), 6, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC7_WORK", RK3308_ADC_ANA_CON00(3), 2, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC8_WORK", RK3308_ADC_ANA_CON00(3), 6, 1, 1, 0), +- +- /* +- * In theory MIC1 and MIC2 can switch to LINE IN, but this is not +- * supported so all we can do is enabling the MIC input. +- */ +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "CH1_IN_SEL", RK3308_ADC_ANA_CON07(0), 4, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "CH2_IN_SEL", RK3308_ADC_ANA_CON07(0), 6, 1, 1, 0), +- +- SND_SOC_DAPM_SUPPLY("ADC1_BUF_REF_EN", RK3308_ADC_ANA_CON00(0), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC2_BUF_REF_EN", RK3308_ADC_ANA_CON00(0), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC3_BUF_REF_EN", RK3308_ADC_ANA_CON00(1), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC4_BUF_REF_EN", RK3308_ADC_ANA_CON00(1), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC5_BUF_REF_EN", RK3308_ADC_ANA_CON00(2), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC6_BUF_REF_EN", RK3308_ADC_ANA_CON00(2), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC7_BUF_REF_EN", RK3308_ADC_ANA_CON00(3), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC8_BUF_REF_EN", RK3308_ADC_ANA_CON00(3), 4, 0, NULL, 0), +- +- SND_SOC_DAPM_SUPPLY("ADC_MCLK_GATE", RK3308_GLB_CON, 5, 1, NULL, 0), +- +- SND_SOC_DAPM_SUPPLY("ADC1_CLK_EN", RK3308_ADC_ANA_CON05(0), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC2_CLK_EN", RK3308_ADC_ANA_CON05(0), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC3_CLK_EN", RK3308_ADC_ANA_CON05(1), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC4_CLK_EN", RK3308_ADC_ANA_CON05(1), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC5_CLK_EN", RK3308_ADC_ANA_CON05(2), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC6_CLK_EN", RK3308_ADC_ANA_CON05(2), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC7_CLK_EN", RK3308_ADC_ANA_CON05(3), 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("ADC8_CLK_EN", RK3308_ADC_ANA_CON05(3), 4, 0, NULL, 0), +- +- /* The "ALC" name from the TRM is misleading, these are needed even without ALC/AGC */ +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC1_EN", RK3308_ADC_ANA_CON02(0), 0, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC2_EN", RK3308_ADC_ANA_CON02(0), 4, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC3_EN", RK3308_ADC_ANA_CON02(1), 0, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC4_EN", RK3308_ADC_ANA_CON02(1), 4, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC5_EN", RK3308_ADC_ANA_CON02(2), 0, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC6_EN", RK3308_ADC_ANA_CON02(2), 4, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC7_EN", RK3308_ADC_ANA_CON02(3), 0, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC8_EN", RK3308_ADC_ANA_CON02(3), 4, 1, 1, 0), +- +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC1_EN", RK3308_ADC_ANA_CON05(0), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC2_EN", RK3308_ADC_ANA_CON05(0), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC3_EN", RK3308_ADC_ANA_CON05(1), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC4_EN", RK3308_ADC_ANA_CON05(1), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC5_EN", RK3308_ADC_ANA_CON05(2), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC6_EN", RK3308_ADC_ANA_CON05(2), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC7_EN", RK3308_ADC_ANA_CON05(3), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC8_EN", RK3308_ADC_ANA_CON05(3), 5, 1, 1, 0), +- +- SND_SOC_DAPM_ADC("ADC1_WORK", "Capture", RK3308_ADC_ANA_CON05(0), 2, 0), +- SND_SOC_DAPM_ADC("ADC2_WORK", "Capture", RK3308_ADC_ANA_CON05(0), 6, 0), +- SND_SOC_DAPM_ADC("ADC3_WORK", "Capture", RK3308_ADC_ANA_CON05(1), 2, 0), +- SND_SOC_DAPM_ADC("ADC4_WORK", "Capture", RK3308_ADC_ANA_CON05(1), 6, 0), +- SND_SOC_DAPM_ADC("ADC5_WORK", "Capture", RK3308_ADC_ANA_CON05(2), 2, 0), +- SND_SOC_DAPM_ADC("ADC6_WORK", "Capture", RK3308_ADC_ANA_CON05(2), 6, 0), +- SND_SOC_DAPM_ADC("ADC7_WORK", "Capture", RK3308_ADC_ANA_CON05(3), 2, 0), +- SND_SOC_DAPM_ADC("ADC8_WORK", "Capture", RK3308_ADC_ANA_CON05(3), 6, 0), +- +- /* The "ALC" name from the TRM is misleading, these are needed even without ALC/AGC */ +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC1_WORK", RK3308_ADC_ANA_CON02(0), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC2_WORK", RK3308_ADC_ANA_CON02(0), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC3_WORK", RK3308_ADC_ANA_CON02(1), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC4_WORK", RK3308_ADC_ANA_CON02(1), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC5_WORK", RK3308_ADC_ANA_CON02(2), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC6_WORK", RK3308_ADC_ANA_CON02(2), 5, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC7_WORK", RK3308_ADC_ANA_CON02(3), 1, 1, 1, 0), +- SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC8_WORK", RK3308_ADC_ANA_CON02(3), 5, 1, 1, 0), +- +- SND_SOC_DAPM_SUPPLY("MICBIAS Current", RK3308_ADC_ANA_CON08(0), 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("MICBIAS1", RK3308_ADC_ANA_CON07(1), 3, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("MICBIAS2", RK3308_ADC_ANA_CON07(2), 3, 0, NULL, 0), +- +- SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_EN", RK3308_DAC_ANA_CON13, 0, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_EN", RK3308_DAC_ANA_CON13, 4, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_WORK", RK3308_DAC_ANA_CON13, 1, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_WORK", RK3308_DAC_ANA_CON13, 5, 0, NULL, 0), +- /* HPMIX is not actually acting as a mixer as the only supported input is I2S */ +- SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_SEL", RK3308_DAC_ANA_CON12, 2, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_SEL", RK3308_DAC_ANA_CON12, 6, 0, NULL, 0), +- SND_SOC_DAPM_MIXER("DAC HPMIX Left", RK3308_DAC_ANA_CON13, 2, 0, NULL, 0), +- SND_SOC_DAPM_MIXER("DAC HPMIX Right", RK3308_DAC_ANA_CON13, 6, 0, NULL, 0), +- +- SND_SOC_DAPM_SUPPLY("DAC_MCLK_GATE", RK3308_GLB_CON, 4, 1, NULL, 0), +- +- SND_SOC_DAPM_SUPPLY("DAC_CURRENT_EN", RK3308_DAC_ANA_CON00, 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("DAC_L_REF_EN", RK3308_DAC_ANA_CON02, 0, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("DAC_R_REF_EN", RK3308_DAC_ANA_CON02, 4, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("DAC_L_CLK_EN", RK3308_DAC_ANA_CON02, 1, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("DAC_R_CLK_EN", RK3308_DAC_ANA_CON02, 5, 0, NULL, 0), +- SND_SOC_DAPM_DAC("DAC_L_DAC_WORK", NULL, RK3308_DAC_ANA_CON02, 3, 0), +- SND_SOC_DAPM_DAC("DAC_R_DAC_WORK", NULL, RK3308_DAC_ANA_CON02, 7, 0), +- +- SND_SOC_DAPM_SUPPLY("DAC_BUF_REF_L", RK3308_DAC_ANA_CON01, 2, 0, NULL, 0), +- SND_SOC_DAPM_SUPPLY("DAC_BUF_REF_R", RK3308_DAC_ANA_CON01, 6, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_L", SND_SOC_NOPM, 0, 0, NULL, 0, +- rk3308_codec_pop_sound_set, +- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +- SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_R", SND_SOC_NOPM, 4, 0, NULL, 0, +- rk3308_codec_pop_sound_set, +- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), +- SND_SOC_DAPM_OUT_DRV("L_HPOUT_EN", RK3308_DAC_ANA_CON03, 1, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("R_HPOUT_EN", RK3308_DAC_ANA_CON03, 5, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("L_HPOUT_WORK", RK3308_DAC_ANA_CON03, 2, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("R_HPOUT_WORK", RK3308_DAC_ANA_CON03, 6, 0, NULL, 0), +- SND_SOC_DAPM_OUTPUT("HPOUT_L"), +- SND_SOC_DAPM_OUTPUT("HPOUT_R"), +- +- SND_SOC_DAPM_OUT_DRV("L_LINEOUT_EN", RK3308_DAC_ANA_CON04, 0, 0, NULL, 0), +- SND_SOC_DAPM_OUT_DRV("R_LINEOUT_EN", RK3308_DAC_ANA_CON04, 4, 0, NULL, 0), +- SND_SOC_DAPM_OUTPUT("LINEOUT_L"), +- SND_SOC_DAPM_OUTPUT("LINEOUT_R"), +-}; ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); ++ return -EINVAL; ++ } + +-static const struct snd_soc_dapm_route rk3308_codec_dapm_routes[] = { +- { "MICBIAS1", NULL, "MICBIAS Current" }, +- { "MICBIAS2", NULL, "MICBIAS Current" }, +- +- { "MIC1_EN", NULL, "MIC1" }, +- { "MIC2_EN", NULL, "MIC2" }, +- { "MIC3_EN", NULL, "MIC3" }, +- { "MIC4_EN", NULL, "MIC4" }, +- { "MIC5_EN", NULL, "MIC5" }, +- { "MIC6_EN", NULL, "MIC6" }, +- { "MIC7_EN", NULL, "MIC7" }, +- { "MIC8_EN", NULL, "MIC8" }, +- +- { "MIC1_WORK", NULL, "MIC1_EN" }, +- { "MIC2_WORK", NULL, "MIC2_EN" }, +- { "MIC3_WORK", NULL, "MIC3_EN" }, +- { "MIC4_WORK", NULL, "MIC4_EN" }, +- { "MIC5_WORK", NULL, "MIC5_EN" }, +- { "MIC6_WORK", NULL, "MIC6_EN" }, +- { "MIC7_WORK", NULL, "MIC7_EN" }, +- { "MIC8_WORK", NULL, "MIC8_EN" }, +- +- { "CH1_IN_SEL", NULL, "MIC1_WORK" }, +- { "CH2_IN_SEL", NULL, "MIC2_WORK" }, +- +- { "ALC1_EN", NULL, "CH1_IN_SEL" }, +- { "ALC2_EN", NULL, "CH2_IN_SEL" }, +- { "ALC3_EN", NULL, "MIC3_WORK" }, +- { "ALC4_EN", NULL, "MIC4_WORK" }, +- { "ALC5_EN", NULL, "MIC5_WORK" }, +- { "ALC6_EN", NULL, "MIC6_WORK" }, +- { "ALC7_EN", NULL, "MIC7_WORK" }, +- { "ALC8_EN", NULL, "MIC8_WORK" }, +- +- { "ADC1_EN", NULL, "ALC1_EN" }, +- { "ADC2_EN", NULL, "ALC2_EN" }, +- { "ADC3_EN", NULL, "ALC3_EN" }, +- { "ADC4_EN", NULL, "ALC4_EN" }, +- { "ADC5_EN", NULL, "ALC5_EN" }, +- { "ADC6_EN", NULL, "ALC6_EN" }, +- { "ADC7_EN", NULL, "ALC7_EN" }, +- { "ADC8_EN", NULL, "ALC8_EN" }, +- +- { "ADC1_WORK", NULL, "ADC1_EN" }, +- { "ADC2_WORK", NULL, "ADC2_EN" }, +- { "ADC3_WORK", NULL, "ADC3_EN" }, +- { "ADC4_WORK", NULL, "ADC4_EN" }, +- { "ADC5_WORK", NULL, "ADC5_EN" }, +- { "ADC6_WORK", NULL, "ADC6_EN" }, +- { "ADC7_WORK", NULL, "ADC7_EN" }, +- { "ADC8_WORK", NULL, "ADC8_EN" }, +- +- { "ADC1_BUF_REF_EN", NULL, "ADC_CURRENT_EN12" }, +- { "ADC2_BUF_REF_EN", NULL, "ADC_CURRENT_EN12" }, +- { "ADC3_BUF_REF_EN", NULL, "ADC_CURRENT_EN34" }, +- { "ADC4_BUF_REF_EN", NULL, "ADC_CURRENT_EN34" }, +- { "ADC5_BUF_REF_EN", NULL, "ADC_CURRENT_EN56" }, +- { "ADC6_BUF_REF_EN", NULL, "ADC_CURRENT_EN56" }, +- { "ADC7_BUF_REF_EN", NULL, "ADC_CURRENT_EN78" }, +- { "ADC8_BUF_REF_EN", NULL, "ADC_CURRENT_EN78" }, +- +- { "ADC1_WORK", NULL, "ADC1_BUF_REF_EN" }, +- { "ADC2_WORK", NULL, "ADC2_BUF_REF_EN" }, +- { "ADC3_WORK", NULL, "ADC3_BUF_REF_EN" }, +- { "ADC4_WORK", NULL, "ADC4_BUF_REF_EN" }, +- { "ADC5_WORK", NULL, "ADC5_BUF_REF_EN" }, +- { "ADC6_WORK", NULL, "ADC6_BUF_REF_EN" }, +- { "ADC7_WORK", NULL, "ADC7_BUF_REF_EN" }, +- { "ADC8_WORK", NULL, "ADC8_BUF_REF_EN" }, +- +- { "ADC1_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC2_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC3_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC4_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC5_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC6_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC7_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- { "ADC8_CLK_EN", NULL, "ADC_MCLK_GATE" }, +- +- { "ADC1_WORK", NULL, "ADC1_CLK_EN" }, +- { "ADC2_WORK", NULL, "ADC2_CLK_EN" }, +- { "ADC3_WORK", NULL, "ADC3_CLK_EN" }, +- { "ADC4_WORK", NULL, "ADC4_CLK_EN" }, +- { "ADC5_WORK", NULL, "ADC5_CLK_EN" }, +- { "ADC6_WORK", NULL, "ADC6_CLK_EN" }, +- { "ADC7_WORK", NULL, "ADC7_CLK_EN" }, +- { "ADC8_WORK", NULL, "ADC8_CLK_EN" }, +- +- { "ALC1_WORK", NULL, "ADC1_WORK" }, +- { "ALC2_WORK", NULL, "ADC2_WORK" }, +- { "ALC3_WORK", NULL, "ADC3_WORK" }, +- { "ALC4_WORK", NULL, "ADC4_WORK" }, +- { "ALC5_WORK", NULL, "ADC5_WORK" }, +- { "ALC6_WORK", NULL, "ADC6_WORK" }, +- { "ALC7_WORK", NULL, "ADC7_WORK" }, +- { "ALC8_WORK", NULL, "ADC8_WORK" }, +- +- { "HiFi Capture", NULL, "ALC1_WORK" }, +- { "HiFi Capture", NULL, "ALC2_WORK" }, +- { "HiFi Capture", NULL, "ALC3_WORK" }, +- { "HiFi Capture", NULL, "ALC4_WORK" }, +- { "HiFi Capture", NULL, "ALC5_WORK" }, +- { "HiFi Capture", NULL, "ALC6_WORK" }, +- { "HiFi Capture", NULL, "ALC7_WORK" }, +- { "HiFi Capture", NULL, "ALC8_WORK" }, +- +- { "DAC_L_HPMIX_EN", NULL, "HiFi Playback" }, +- { "DAC_R_HPMIX_EN", NULL, "HiFi Playback" }, +- { "DAC_L_HPMIX_WORK", NULL, "DAC_L_HPMIX_EN" }, +- { "DAC_R_HPMIX_WORK", NULL, "DAC_R_HPMIX_EN" }, +- { "DAC HPMIX Left", NULL, "DAC_L_HPMIX_WORK" }, +- { "DAC HPMIX Right", NULL, "DAC_R_HPMIX_WORK" }, +- +- { "DAC_L_DAC_WORK", NULL, "DAC HPMIX Left" }, +- { "DAC_R_DAC_WORK", NULL, "DAC HPMIX Right" }, +- +- { "DAC_L_REF_EN", NULL, "DAC_CURRENT_EN" }, +- { "DAC_R_REF_EN", NULL, "DAC_CURRENT_EN" }, +- { "DAC_L_CLK_EN", NULL, "DAC_L_REF_EN" }, +- { "DAC_R_CLK_EN", NULL, "DAC_R_REF_EN" }, +- { "DAC_L_CLK_EN", NULL, "DAC_MCLK_GATE" }, +- { "DAC_R_CLK_EN", NULL, "DAC_MCLK_GATE" }, +- { "DAC_L_DAC_WORK", NULL, "DAC_L_CLK_EN" }, +- { "DAC_R_DAC_WORK", NULL, "DAC_R_CLK_EN" }, +- { "DAC_L_HPMIX_SEL", NULL, "DAC_L_DAC_WORK" }, +- { "DAC_R_HPMIX_SEL", NULL, "DAC_R_DAC_WORK" }, +- +- { "HPOUT_L", NULL, "DAC_BUF_REF_L" }, +- { "HPOUT_R", NULL, "DAC_BUF_REF_R" }, +- { "L_HPOUT_EN", NULL, "DAC_L_HPMIX_SEL" }, +- { "R_HPOUT_EN", NULL, "DAC_R_HPMIX_SEL" }, +- { "L_HPOUT_WORK", NULL, "L_HPOUT_EN" }, +- { "R_HPOUT_WORK", NULL, "R_HPOUT_EN" }, +- { "HPOUT_POP_SOUND_L", NULL, "L_HPOUT_WORK" }, +- { "HPOUT_POP_SOUND_R", NULL, "R_HPOUT_WORK" }, +- { "HPOUT_L", NULL, "HPOUT_POP_SOUND_L" }, +- { "HPOUT_R", NULL, "HPOUT_POP_SOUND_R" }, +- +- { "L_LINEOUT_EN", NULL, "DAC_L_HPMIX_SEL" }, +- { "R_LINEOUT_EN", NULL, "DAC_R_HPMIX_SEL" }, +- { "LINEOUT_L", NULL, "L_LINEOUT_EN" }, +- { "LINEOUT_R", NULL, "R_LINEOUT_EN" }, +-}; ++ if (e->shift_l) ++ ucontrol->value.integer.value[0] = rk3308->agc_r[e->reg]; ++ else ++ ucontrol->value.integer.value[0] = rk3308->agc_l[e->reg]; ++ ++ return 0; ++} + +-static int rk3308_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, +- unsigned int fmt) ++static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- struct snd_soc_component *component = codec_dai->component; ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); +- const unsigned int inv_bits = fmt & SND_SOC_DAIFMT_INV_MASK; +- const bool inv_bitclk = +- (inv_bits & SND_SOC_DAIFMT_IB_IF) || +- (inv_bits & SND_SOC_DAIFMT_IB_NF); +- const bool inv_frmclk = +- (inv_bits & SND_SOC_DAIFMT_IB_IF) || +- (inv_bits & SND_SOC_DAIFMT_NB_IF); +- const unsigned int dac_master_bits = rk3308->codec_ver < ACODEC_VERSION_C ? +- RK3308_DAC_IO_MODE_MASTER | RK3308_DAC_MODE_MASTER : +- RK3308BS_DAC_IO_MODE_MASTER | RK3308BS_DAC_MODE_MASTER; +- unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; +- bool is_master = false; +- int grp; ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value = ucontrol->value.integer.value[0]; ++ int grp = e->reg; + +- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { +- case SND_SOC_DAIFMT_CBC_CFC: +- break; +- case SND_SOC_DAIFMT_CBP_CFP: +- adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; +- adc_aif2 |= RK3308_ADC_MODE_MASTER; +- dac_aif2 |= dac_master_bits; +- is_master = true; +- break; +- default: ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); + return -EINVAL; + } + +- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { +- case SND_SOC_DAIFMT_DSP_A: +- adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; +- dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; +- break; +- case SND_SOC_DAIFMT_I2S: +- adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; +- dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; +- break; +- case SND_SOC_DAIFMT_RIGHT_J: +- adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; +- dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; +- break; +- case SND_SOC_DAIFMT_LEFT_J: +- adc_aif1 |= RK3308_ADC_I2S_MODE_LJ; +- dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; +- break; +- default: +- return -EINVAL; +- } ++ if (value) { ++ /* ALC AGC On */ ++ if (e->shift_l) { ++ /* ALC AGC Right On */ ++ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), ++ RK3308_AGC_FUNC_SEL_MSK, ++ RK3308_AGC_FUNC_SEL_EN); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), ++ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, ++ RK3308_ADC_ALCR_CON_GAIN_PGAR_EN); + +- if (inv_bitclk) { +- adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; +- dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; +- } ++ rk3308->agc_r[e->reg] = 1; ++ } else { ++ /* ALC AGC Left On */ ++ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), ++ RK3308_AGC_FUNC_SEL_MSK, ++ RK3308_AGC_FUNC_SEL_EN); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), ++ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK, ++ RK3308_ADC_ALCL_CON_GAIN_PGAL_EN); + +- if (inv_frmclk) { +- adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; +- dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; +- } ++ rk3308->agc_l[e->reg] = 1; ++ } ++ } else { ++ /* ALC AGC Off */ ++ if (e->shift_l) { ++ /* ALC AGC Right Off */ ++ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), ++ RK3308_AGC_FUNC_SEL_MSK, ++ RK3308_AGC_FUNC_SEL_DIS); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), ++ RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK, ++ RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS); + +- /* +- * Hold ADC Digital registers start at master mode +- * +- * There are 8 ADCs which use the same internal SCLK and LRCK for +- * master mode. We need to make sure that they are in effect at the +- * same time, otherwise they will cause abnormal clocks. +- */ +- if (is_master) +- regmap_clear_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK); ++ rk3308->agc_r[e->reg] = 0; ++ } else { ++ /* ALC AGC Left Off */ ++ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), ++ RK3308_AGC_FUNC_SEL_MSK, ++ RK3308_AGC_FUNC_SEL_DIS); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON11(grp), ++ RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK, ++ RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS); + +- for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { +- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), +- RK3308_ADC_I2S_LRC_POL_REVERSAL | +- RK3308_ADC_I2S_MODE_MSK, +- adc_aif1); +- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), +- RK3308_ADC_IO_MODE_MASTER | +- RK3308_ADC_MODE_MASTER | +- RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL, +- adc_aif2); ++ rk3308->agc_l[e->reg] = 0; ++ } + } + +- /* Hold ADC Digital registers end at master mode */ +- if (is_master) +- regmap_set_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK); +- +- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, +- RK3308_DAC_I2S_LRC_POL_REVERSAL | +- RK3308_DAC_I2S_MODE_MSK, +- dac_aif1); +- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, +- dac_master_bits | RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL, +- dac_aif2); +- + return 0; + } + +-static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308, +- struct snd_pcm_hw_params *params) ++static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- unsigned int dac_aif1 = 0; ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value; ++ int grp = e->reg; + +- switch (params_format(params)) { +- case SNDRV_PCM_FORMAT_S16_LE: +- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; +- break; +- case SNDRV_PCM_FORMAT_S20_3LE: +- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; +- break; +- case SNDRV_PCM_FORMAT_S24_LE: +- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; +- break; +- case SNDRV_PCM_FORMAT_S32_LE: +- dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; +- break; +- default: ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); + return -EINVAL; + } + +- regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, +- RK3308_DAC_I2S_VALID_LEN_MSK, dac_aif1); +- regmap_set_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, RK3308_DAC_I2S_WORK); ++ if (e->shift_l) { ++ regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON04(grp), &value); ++ rk3308->agc_asr_r[e->reg] = value >> RK3308_AGC_APPROX_RATE_SFT; ++ ucontrol->value.integer.value[0] = rk3308->agc_asr_r[e->reg]; ++ } else { ++ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp), &value); ++ rk3308->agc_asr_l[e->reg] = value >> RK3308_AGC_APPROX_RATE_SFT; ++ ucontrol->value.integer.value[0] = rk3308->agc_asr_l[e->reg]; ++ } + + return 0; + } + +-static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308, +- struct snd_pcm_hw_params *params) ++static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- unsigned int adc_aif1 = 0; +- /* +- * grp 0 = ADC1 and ADC2 +- * grp 1 = ADC3 and ADC4 +- * grp 2 = ADC5 and ADC6 +- * grp 3 = ADC7 and ADC8 +- */ +- u32 used_adc_grps; +- int grp; ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value; ++ int grp = e->reg; + +- switch (params_channels(params)) { +- case 1: +- adc_aif1 |= RK3308_ADC_I2S_MONO; +- used_adc_grps = 1; +- break; +- case 2: +- case 4: +- case 6: +- case 8: +- used_adc_grps = params_channels(params) / 2; +- break; +- default: +- dev_err(rk3308->dev, "Invalid channel number %d\n", params_channels(params)); ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); + return -EINVAL; + } + +- switch (params_format(params)) { +- case SNDRV_PCM_FORMAT_S16_LE: +- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; +- break; +- case SNDRV_PCM_FORMAT_S20_3LE: +- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; +- break; +- case SNDRV_PCM_FORMAT_S24_LE: +- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; +- break; +- case SNDRV_PCM_FORMAT_S32_LE: +- adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; +- break; +- default: ++ value = ucontrol->value.integer.value[0] << RK3308_AGC_APPROX_RATE_SFT; ++ ++ if (e->shift_l) { ++ /* ALC AGC Right Approximate Sample Rate */ ++ regmap_update_bits(rk3308->regmap, RK3308_ALC_R_DIG_CON04(grp), ++ RK3308_AGC_APPROX_RATE_MSK, ++ value); ++ rk3308->agc_asr_r[e->reg] = ucontrol->value.integer.value[0]; ++ } else { ++ /* ALC AGC Left Approximate Sample Rate */ ++ regmap_update_bits(rk3308->regmap, RK3308_ALC_L_DIG_CON04(grp), ++ RK3308_AGC_APPROX_RATE_MSK, ++ value); ++ rk3308->agc_asr_l[e->reg] = ucontrol->value.integer.value[0]; ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value; ++ int grp = e->reg; ++ ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); + return -EINVAL; + } + +- for (grp = 0; grp < used_adc_grps; grp++) { +- regmap_update_bits(rk3308->regmap, +- RK3308_ADC_DIG_CON03(grp), +- RK3308_ADC_L_CH_BIST_MSK | RK3308_ADC_R_CH_BIST_MSK, +- RK3308_ADC_L_CH_NORMAL_LEFT | RK3308_ADC_R_CH_NORMAL_RIGHT); +- regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), +- RK3308_ADC_I2S_VALID_LEN_MSK | RK3308_ADC_I2S_MONO, adc_aif1); +- regmap_set_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), RK3308_ADC_I2S_WORK); ++ if (e->shift_l) { ++ /* ADC MIC Right Mute/Work Infos */ ++ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value); ++ rk3308->mic_mute_r[e->reg] = (value & RK3308_ADC_R_CH_BIST_SINE) >> ++ RK3308_ADC_R_CH_BIST_SFT; ++ ucontrol->value.integer.value[0] = rk3308->mic_mute_r[e->reg]; ++ } else { ++ /* ADC MIC Left Mute/Work Infos */ ++ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value); ++ rk3308->mic_mute_l[e->reg] = (value & RK3308_ADC_L_CH_BIST_SINE) >> ++ RK3308_ADC_L_CH_BIST_SFT; ++ ucontrol->value.integer.value[0] = rk3308->mic_mute_l[e->reg]; + } + + return 0; + } + +-static int rk3308_codec_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai) ++static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- struct snd_soc_component *component = dai->component; ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value; ++ int grp = e->reg; + +- return (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? +- rk3308_codec_dac_dig_config(rk3308, params) : +- rk3308_codec_adc_dig_config(rk3308, params); +-} ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); ++ return -EINVAL; ++ } + +-static const struct snd_soc_dai_ops rk3308_codec_dai_ops = { +- .hw_params = rk3308_codec_hw_params, +- .set_fmt = rk3308_codec_set_dai_fmt, +-}; ++ if (e->shift_l) { ++ /* ADC MIC Right Mute/Work Configuration */ ++ value = ucontrol->value.integer.value[0] << RK3308_ADC_R_CH_BIST_SFT; ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_R_CH_BIST_SINE, ++ value); ++ rk3308->mic_mute_r[e->reg] = ucontrol->value.integer.value[0]; ++ } else { ++ /* ADC MIC Left Mute/Work Configuration */ ++ value = ucontrol->value.integer.value[0] << RK3308_ADC_L_CH_BIST_SFT; ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_L_CH_BIST_SINE, ++ value); ++ rk3308->mic_mute_l[e->reg] = ucontrol->value.integer.value[0]; ++ } + +-static struct snd_soc_dai_driver rk3308_codec_dai_driver = { +- .name = "rk3308-hifi", +- .playback = { +- .stream_name = "HiFi Playback", +- .channels_min = 2, +- .channels_max = 2, +- .rates = SNDRV_PCM_RATE_8000_192000, +- .formats = (SNDRV_PCM_FMTBIT_S16_LE | +- SNDRV_PCM_FMTBIT_S20_3LE | +- SNDRV_PCM_FMTBIT_S24_LE | +- SNDRV_PCM_FMTBIT_S32_LE), +- }, +- .capture = { +- .stream_name = "HiFi Capture", +- .channels_min = 1, +- .channels_max = 8, +- .rates = SNDRV_PCM_RATE_8000_192000, +- .formats = (SNDRV_PCM_FMTBIT_S16_LE | +- SNDRV_PCM_FMTBIT_S20_3LE | +- SNDRV_PCM_FMTBIT_S24_LE | +- SNDRV_PCM_FMTBIT_S32_LE), +- }, +- .ops = &rk3308_codec_dai_ops, +-}; ++ return 0; ++} + +-static void rk3308_codec_reset(struct snd_soc_component *component) ++static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + +- reset_control_assert(rk3308->reset); +- usleep_range(10000, 11000); /* estimated value */ +- reset_control_deassert(rk3308->reset); ++ ucontrol->value.integer.value[0] = rk3308->micbias_volt; + +- regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); +- usleep_range(10000, 11000); /* estimated value */ +- regmap_write(rk3308->regmap, RK3308_GLB_CON, +- RK3308_SYS_WORK | +- RK3308_DAC_DIG_WORK | +- RK3308_ADC_DIG_WORK); ++ return 0; + } + +-/* +- * Initialize register whose default after HW reset is problematic or which +- * are never modified. +- */ +-static int rk3308_codec_initialize(struct rk3308_codec_priv *rk3308) ++static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) + { +- int grp; ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ unsigned int volt = ucontrol->value.integer.value[0]; ++ int ret; + +- /* +- * Init ADC digital vol to 0 dB (reset value is 0xff, undocumented). +- * Range: -97dB ~ +32dB. +- */ +- if (rk3308->codec_ver == ACODEC_VERSION_C) { +- for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { +- regmap_write(rk3308->regmap, RK3308_ADC_DIG_CON05(grp), +- RK3308_ADC_DIG_VOL_CON_x_0DB); +- regmap_write(rk3308->regmap, RK3308_ADC_DIG_CON06(grp), +- RK3308_ADC_DIG_VOL_CON_x_0DB); +- } ++ ret = check_micbias(volt); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, "The invalid micbias volt: %d\n", ++ volt); ++ return ret; + } + +- /* set HPMIX default gains (reset value is 0, which is illegal) */ +- regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, +- RK3308_DAC_L_HPMIX_GAIN_MSK | ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), ++ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, ++ volt); ++ ++ rk3308->micbias_volt = volt; ++ ++ return 0; ++} ++ ++static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ ucontrol->value.integer.value[0] = rk3308->enable_micbias; ++ ++ return 0; ++} ++ ++static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ unsigned int on = ucontrol->value.integer.value[0]; ++ ++ if (on) { ++ if (!rk3308->enable_micbias) ++ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); ++ } else { ++ if (rk3308->enable_micbias) ++ rk3308_codec_micbias_disable(rk3308); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ return snd_soc_get_volsw_range(kcontrol, ucontrol); ++} ++ ++static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ unsigned int gain = ucontrol->value.integer.value[0]; ++ ++ if (gain > RK3308_ADC_CH1_MIC_GAIN_MAX) { ++ dev_err(rk3308->plat_dev, "%s: invalid mic gain: %d\n", ++ __func__, gain); ++ return -EINVAL; ++ } ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_A) { ++ /* ++ * From the TRM, there are only suupport 0dB(gain==0) and ++ * 20dB(gain==3) on the codec version A. ++ */ ++ if (!(gain == 0 || gain == RK3308_ADC_CH1_MIC_GAIN_MAX)) { ++ dev_err(rk3308->plat_dev, ++ "version A doesn't supported: %d, expect: 0,%d\n", ++ gain, RK3308_ADC_CH1_MIC_GAIN_MAX); ++ return 0; ++ } ++ } ++ ++ return snd_soc_put_volsw_range(kcontrol, ucontrol); ++} ++ ++static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value; ++ ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); ++ return -EINVAL; ++ } ++ ++ regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), &value); ++ if (value & RK3308_ADC_HPF_PATH_MSK) ++ rk3308->hpf_cutoff[e->reg] = 0; ++ else ++ rk3308->hpf_cutoff[e->reg] = 1; ++ ++ ucontrol->value.integer.value[0] = rk3308->hpf_cutoff[e->reg]; ++ ++ return 0; ++} ++ ++static int rk3308_codec_hpf_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; ++ unsigned int value = ucontrol->value.integer.value[0]; ++ ++ if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "%s: Invalid ADC grp: %d\n", __func__, e->reg); ++ return -EINVAL; ++ } ++ ++ if (value) { ++ /* Enable high pass filter for ADCs */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), ++ RK3308_ADC_HPF_PATH_MSK, ++ RK3308_ADC_HPF_PATH_EN); ++ } else { ++ /* Disable high pass filter for ADCs. */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON04(e->reg), ++ RK3308_ADC_HPF_PATH_MSK, ++ RK3308_ADC_HPF_PATH_DIS); ++ } ++ ++ rk3308->hpf_cutoff[e->reg] = value; ++ ++ return 0; ++} ++ ++static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ return snd_soc_get_volsw_range(kcontrol, ucontrol); ++} ++ ++static int rk3308_codec_hpout_l_put_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ unsigned int dgain = ucontrol->value.integer.value[0]; ++ ++ if (dgain > RK3308_DAC_L_HPOUT_GAIN_MAX) { ++ dev_err(rk3308->plat_dev, "%s: invalid l_dgain: %d\n", ++ __func__, dgain); ++ return -EINVAL; ++ } ++ ++ rk3308->hpout_l_dgain = dgain; ++ ++ return snd_soc_put_volsw_range(kcontrol, ucontrol); ++} ++ ++static int rk3308_codec_hpout_r_get_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ return snd_soc_get_volsw_range(kcontrol, ucontrol); ++} ++ ++static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ unsigned int dgain = ucontrol->value.integer.value[0]; ++ ++ if (dgain > RK3308_DAC_R_HPOUT_GAIN_MAX) { ++ dev_err(rk3308->plat_dev, "%s: invalid r_dgain: %d\n", ++ __func__, dgain); ++ return -EINVAL; ++ } ++ ++ rk3308->hpout_r_dgain = dgain; ++ ++ return snd_soc_put_volsw_range(kcontrol, ucontrol); ++} ++ ++static u32 to_mapped_grp(struct rk3308_codec_priv *rk3308, int idx) ++{ ++ return rk3308->i2s_sdis[idx]; ++} ++ ++static bool adc_for_each_grp(struct rk3308_codec_priv *rk3308, ++ int type, int idx, u32 *grp) ++{ ++ if (type == ADC_TYPE_NORMAL) { ++ u32 mapped_grp = to_mapped_grp(rk3308, idx); ++ int max_grps; ++ ++ if (rk3308->enable_all_adcs) ++ max_grps = ADC_LR_GROUP_MAX; ++ else ++ max_grps = rk3308->used_adc_grps; ++ ++ if (idx >= max_grps) ++ return false; ++ ++ if ((!rk3308->loopback_dacs_enabled) && ++ handle_loopback(rk3308) && ++ rk3308->loopback_grp == mapped_grp) { ++ /* ++ * Ths loopback DACs are closed, and specify the ++ * loopback ADCs. ++ */ ++ *grp = ADC_GRP_SKIP_MAGIC; ++ } else if (rk3308->en_always_grps_num && ++ rk3308->skip_grps[mapped_grp]) { ++ /* To set the skip flag if the ADC GRP is enabled. */ ++ *grp = ADC_GRP_SKIP_MAGIC; ++ } else { ++ *grp = mapped_grp; ++ } ++ ++ dev_dbg(rk3308->plat_dev, ++ "ADC_TYPE_NORMAL, idx: %d, mapped_grp: %d, get grp: %d,\n", ++ idx, mapped_grp, *grp); ++ } else if (type == ADC_TYPE_ALL) { ++ if (idx >= ADC_LR_GROUP_MAX) ++ return false; ++ ++ *grp = idx; ++ dev_dbg(rk3308->plat_dev, ++ "ADC_TYPE_ALL, idx: %d, get grp: %d\n", ++ idx, *grp); ++ } else if (type == ADC_TYPE_DBG) { ++ if (idx >= ADC_LR_GROUP_MAX) ++ return false; ++ ++ if (idx == (int)rk3308->cur_dbg_grp) ++ *grp = idx; ++ else ++ *grp = ADC_GRP_SKIP_MAGIC; ++ ++ dev_dbg(rk3308->plat_dev, ++ "ADC_TYPE_DBG, idx: %d, get grp: %d\n", ++ idx, *grp); ++ } else { ++ if (idx >= 1) ++ return false; ++ ++ *grp = rk3308->loopback_grp; ++ dev_dbg(rk3308->plat_dev, ++ "ADC_TYPE_LOOPBACK, idx: %d, get grp: %d\n", ++ idx, *grp); ++ } ++ ++ return true; ++} ++ ++static int rk3308_codec_get_dac_path_state(struct rk3308_codec_priv *rk3308) ++{ ++ return rk3308->dac_path_state; ++} ++ ++static void rk3308_codec_set_dac_path_state(struct rk3308_codec_priv *rk3308, ++ int state) ++{ ++ rk3308->dac_path_state = state; ++} ++ ++static void rk3308_headphone_ctl(struct rk3308_codec_priv *rk3308, int on) ++{ ++ if (rk3308->hp_ctl_gpio) ++ gpiod_direction_output(rk3308->hp_ctl_gpio, on); ++} ++ ++static void rk3308_speaker_ctl(struct rk3308_codec_priv *rk3308, int on) ++{ ++ if (on) { ++ if (rk3308->pa_drv_gpio) { ++ gpiod_direction_output(rk3308->pa_drv_gpio, on); ++ msleep(rk3308->delay_pa_drv_ms); ++ } ++ ++ if (rk3308->spk_ctl_gpio) ++ gpiod_direction_output(rk3308->spk_ctl_gpio, on); ++ } else { ++ if (rk3308->spk_ctl_gpio) ++ gpiod_direction_output(rk3308->spk_ctl_gpio, on); ++ ++ if (rk3308->pa_drv_gpio) { ++ msleep(rk3308->delay_pa_drv_ms); ++ gpiod_direction_output(rk3308->pa_drv_gpio, on); ++ } ++ } ++} ++ ++static int rk3308_codec_reset(struct snd_soc_component *component) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ reset_control_assert(rk3308->reset); ++ usleep_range(2000, 2500); /* estimated value */ ++ reset_control_deassert(rk3308->reset); ++ ++ regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); ++ usleep_range(200, 300); /* estimated value */ ++ regmap_write(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_SYS_WORK | ++ RK3308_DAC_DIG_WORK | ++ RK3308_ADC_DIG_WORK); ++ ++ return 0; ++} ++ ++static int rk3308_codec_adc_dig_reset(struct rk3308_codec_priv *rk3308) ++{ ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_ADC_DIG_WORK, ++ RK3308_ADC_DIG_RESET); ++ udelay(50); ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_ADC_DIG_WORK, ++ RK3308_ADC_DIG_WORK); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308) ++{ ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_DAC_DIG_WORK, ++ RK3308_DAC_DIG_RESET); ++ udelay(50); ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_DAC_DIG_WORK, ++ RK3308_DAC_DIG_WORK); ++ ++ return 0; ++} ++ ++static int rk3308_set_bias_level(struct snd_soc_component *component, ++ enum snd_soc_bias_level level) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ switch (level) { ++ case SND_SOC_BIAS_ON: ++ break; ++ case SND_SOC_BIAS_PREPARE: ++ break; ++ case SND_SOC_BIAS_STANDBY: ++ regcache_cache_only(rk3308->regmap, false); ++ regcache_sync(rk3308->regmap); ++ break; ++ case SND_SOC_BIAS_OFF: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int rk3308_set_dai_fmt(struct snd_soc_dai *dai, ++ unsigned int fmt) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; ++ int idx, grp, is_master; ++ int type = ADC_TYPE_ALL; ++ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ adc_aif2 |= RK3308_ADC_IO_MODE_SLAVE; ++ adc_aif2 |= RK3308_ADC_MODE_SLAVE; ++ dac_aif2 |= RK3308_DAC_IO_MODE_SLAVE; ++ dac_aif2 |= RK3308_DAC_MODE_SLAVE; ++ is_master = 0; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; ++ adc_aif2 |= RK3308_ADC_MODE_MASTER; ++ dac_aif2 |= RK3308_DAC_IO_MODE_MASTER; ++ dac_aif2 |= RK3308_DAC_MODE_MASTER; ++ is_master = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_DSP_A: ++ adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; ++ dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; ++ break; ++ case SND_SOC_DAIFMT_I2S: ++ adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; ++ dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; ++ break; ++ case SND_SOC_DAIFMT_RIGHT_J: ++ adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; ++ dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; ++ break; ++ case SND_SOC_DAIFMT_LEFT_J: ++ adc_aif1 |= RK3308_ADC_I2S_MODE_LJ; ++ dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; ++ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; ++ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; ++ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; ++ break; ++ case SND_SOC_DAIFMT_IB_IF: ++ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; ++ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; ++ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; ++ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; ++ break; ++ case SND_SOC_DAIFMT_IB_NF: ++ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_NORMAL; ++ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; ++ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_NORMAL; ++ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; ++ break; ++ case SND_SOC_DAIFMT_NB_IF: ++ adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; ++ adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_NORMAL; ++ dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; ++ dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_NORMAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* ++ * Hold ADC Digital registers start at master mode ++ * ++ * There are 8 ADCs and use the same SCLK and LRCK internal for master ++ * mode, We need to make sure that they are in effect at the same time, ++ * otherwise they will cause the abnormal clocks. ++ */ ++ if (is_master) ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_ADC_DIG_WORK, ++ RK3308_ADC_DIG_RESET); ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), ++ RK3308_ADC_I2S_LRC_POL_MSK | ++ RK3308_ADC_I2S_MODE_MSK, ++ adc_aif1); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), ++ RK3308_ADC_IO_MODE_MSK | ++ RK3308_ADC_MODE_MSK | ++ RK3308_ADC_I2S_BIT_CLK_POL_MSK, ++ adc_aif2); ++ } ++ ++ /* Hold ADC Digital registers end at master mode */ ++ if (is_master) ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_ADC_DIG_WORK, ++ RK3308_ADC_DIG_WORK); ++ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, ++ RK3308_DAC_I2S_LRC_POL_MSK | ++ RK3308_DAC_I2S_MODE_MSK, ++ dac_aif1); ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, ++ RK3308_DAC_IO_MODE_MSK | ++ RK3308_DAC_MODE_MSK | ++ RK3308_DAC_I2S_BIT_CLK_POL_MSK, ++ dac_aif2); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308, ++ struct snd_pcm_hw_params *params) ++{ ++ unsigned int dac_aif1 = 0, dac_aif2 = 0; ++ ++ /* Clear the status of DAC DIG Digital reigisters */ ++ rk3308_codec_dac_dig_reset(rk3308); ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ dac_aif1 |= RK3308_DAC_I2S_LR_NORMAL; ++ dac_aif2 |= RK3308_DAC_I2S_WORK; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, ++ RK3308_DAC_I2S_VALID_LEN_MSK | ++ RK3308_DAC_I2S_LR_MSK, ++ dac_aif1); ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, ++ RK3308_DAC_I2S_MSK, ++ dac_aif2); ++ ++ return 0; ++} ++ ++static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308, ++ struct snd_pcm_hw_params *params) ++{ ++ unsigned int adc_aif1 = 0, adc_aif2 = 0; ++ int type = ADC_TYPE_NORMAL; ++ int idx, grp; ++ ++ /* Clear the status of ADC DIG Digital reigisters */ ++ rk3308_codec_adc_dig_reset(rk3308); ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (params_channels(params)) { ++ case 1: ++ adc_aif1 |= RK3308_ADC_I2S_MONO; ++ break; ++ case 2: ++ case 4: ++ case 6: ++ case 8: ++ adc_aif1 |= RK3308_ADC_I2S_STEREO; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ adc_aif1 |= RK3308_ADC_I2S_LR_NORMAL; ++ adc_aif2 |= RK3308_ADC_I2S_WORK; ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), ++ RK3308_ADC_I2S_VALID_LEN_MSK | ++ RK3308_ADC_I2S_LR_MSK | ++ RK3308_ADC_I2S_TYPE_MSK, ++ adc_aif1); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), ++ RK3308_ADC_I2S_MSK, ++ adc_aif2); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_update_adc_grps(struct rk3308_codec_priv *rk3308, ++ struct snd_pcm_hw_params *params) ++{ ++ switch (params_channels(params)) { ++ case 1: ++ rk3308->used_adc_grps = 1; ++ break; ++ case 2: ++ case 4: ++ case 6: ++ case 8: ++ rk3308->used_adc_grps = params_channels(params) / 2; ++ break; ++ default: ++ dev_err(rk3308->plat_dev, "Invalid channels: %d\n", ++ params_channels(params)); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ if (stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ int dgain; ++ ++ if (mute) { ++ for (dgain = 0x2; dgain <= 0x7; dgain++) { ++ /* ++ * Keep the max -> min digital CIC interpolation ++ * filter gain step by step. ++ * ++ * loud: 0x2; whisper: 0x7 ++ */ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_DAC_DIG_CON04, ++ RK3308_DAC_CIC_IF_GAIN_MSK, ++ dgain); ++ usleep_range(200, 300); /* estimated value */ ++ } ++ ++#if !DEBUG_POP_ALWAYS ++ rk3308_headphone_ctl(rk3308, 0); ++ rk3308_speaker_ctl(rk3308, 0); ++#endif ++ } else { ++#if !DEBUG_POP_ALWAYS ++ if (rk3308->dac_output == DAC_LINEOUT) ++ rk3308_speaker_ctl(rk3308, 1); ++ else if (rk3308->dac_output == DAC_HPOUT) ++ rk3308_headphone_ctl(rk3308, 1); ++ ++ if (rk3308->delay_start_play_ms) ++ msleep(rk3308->delay_start_play_ms); ++#endif ++ for (dgain = 0x7; dgain >= 0x2; dgain--) { ++ /* ++ * Keep the min -> max digital CIC interpolation ++ * filter gain step by step ++ * ++ * loud: 0x2; whisper: 0x7 ++ */ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_DAC_DIG_CON04, ++ RK3308_DAC_CIC_IF_GAIN_MSK, ++ dgain); ++ usleep_range(200, 300); /* estimated value */ ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_digital_fadein(struct rk3308_codec_priv *rk3308) ++{ ++ unsigned int dgain, dgain_ref; ++ ++ if (rk3308->hpout_l_dgain != rk3308->hpout_r_dgain) { ++ pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n", ++ rk3308->hpout_l_dgain, rk3308->hpout_r_dgain); ++ dgain_ref = min(rk3308->hpout_l_dgain, rk3308->hpout_r_dgain); ++ } else { ++ dgain_ref = rk3308->hpout_l_dgain; ++ } ++ ++ /* ++ * We'd better change the gain of the left and right channels ++ * at the same time to avoid different listening ++ */ ++ for (dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39; ++ dgain <= dgain_ref; dgain++) { ++ /* Step 02 decrease dgains for de-pop */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, ++ RK3308_DAC_L_HPOUT_GAIN_MSK, ++ dgain); ++ ++ /* Step 02 decrease dgains for de-pop */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, ++ RK3308_DAC_R_HPOUT_GAIN_MSK, ++ dgain); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_digital_fadeout(struct rk3308_codec_priv *rk3308) ++{ ++ unsigned int l_dgain, r_dgain; ++ ++ /* ++ * Note. In the step2, adjusting the register step by step to ++ * the appropriate value and taking 20ms as time step ++ */ ++ regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON05, &l_dgain); ++ l_dgain &= RK3308_DAC_L_HPOUT_GAIN_MSK; ++ ++ regmap_read(rk3308->regmap, RK3308_DAC_ANA_CON06, &r_dgain); ++ r_dgain &= RK3308_DAC_R_HPOUT_GAIN_MSK; ++ ++ if (l_dgain != r_dgain) { ++ pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n", ++ l_dgain, r_dgain); ++ l_dgain = min(l_dgain, r_dgain); ++ } ++ ++ /* ++ * We'd better change the gain of the left and right channels ++ * at the same time to avoid different listening ++ */ ++ while (l_dgain >= RK3308_DAC_L_HPOUT_GAIN_NDB_39) { ++ /* Step 02 decrease dgains for de-pop */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, ++ RK3308_DAC_L_HPOUT_GAIN_MSK, ++ l_dgain); ++ ++ /* Step 02 decrease dgains for de-pop */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, ++ RK3308_DAC_R_HPOUT_GAIN_MSK, ++ l_dgain); ++ ++ usleep_range(200, 300); /* estimated value */ ++ ++ if (l_dgain == RK3308_DAC_L_HPOUT_GAIN_NDB_39) ++ break; ++ ++ l_dgain--; ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_lineout_enable(struct rk3308_codec_priv *rk3308) ++{ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* Step 04 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_L_SEL_DC_FROM_INTERNAL | ++ RK3308_DAC_R_SEL_DC_FROM_INTERNAL); ++ } ++ ++ /* Step 07 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_EN | ++ RK3308_DAC_R_LINEOUT_EN, ++ RK3308_DAC_L_LINEOUT_EN | ++ RK3308_DAC_R_LINEOUT_EN); ++ ++ udelay(20); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* Step 10 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL | ++ RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL); ++ ++ udelay(20); ++ } ++ ++ /* Step 19 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_UNMUTE | ++ RK3308_DAC_R_LINEOUT_UNMUTE, ++ RK3308_DAC_L_LINEOUT_UNMUTE | ++ RK3308_DAC_R_LINEOUT_UNMUTE); ++ udelay(20); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_lineout_disable(struct rk3308_codec_priv *rk3308) ++{ ++ /* Step 08 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_UNMUTE | ++ RK3308_DAC_R_LINEOUT_UNMUTE, ++ RK3308_DAC_L_LINEOUT_MUTE | ++ RK3308_DAC_R_LINEOUT_MUTE); ++ ++ /* Step 09 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_EN | ++ RK3308_DAC_R_LINEOUT_EN, ++ RK3308_DAC_L_LINEOUT_DIS | ++ RK3308_DAC_R_LINEOUT_DIS); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_hpout_enable(struct rk3308_codec_priv *rk3308) ++{ ++ /* Step 03 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_HPOUT_POP_SOUND_L_WORK | ++ RK3308_DAC_HPOUT_POP_SOUND_R_WORK); ++ ++ udelay(20); ++ ++ /* Step 07 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_EN | ++ RK3308_DAC_R_HPOUT_EN, ++ RK3308_DAC_L_HPOUT_EN | ++ RK3308_DAC_R_HPOUT_EN); ++ ++ udelay(20); ++ ++ /* Step 08 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_WORK | ++ RK3308_DAC_R_HPOUT_WORK, ++ RK3308_DAC_L_HPOUT_WORK | ++ RK3308_DAC_R_HPOUT_WORK); ++ ++ udelay(20); ++ ++ /* Step 16 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_UNMUTE | ++ RK3308_DAC_R_HPOUT_UNMUTE, ++ RK3308_DAC_L_HPOUT_UNMUTE | ++ RK3308_DAC_R_HPOUT_UNMUTE); ++ ++ udelay(20); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_hpout_disable(struct rk3308_codec_priv *rk3308) ++{ ++ /* Step 03 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_HPOUT_POP_SOUND_L_INIT | ++ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); ++ ++ /* Step 07 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_EN | ++ RK3308_DAC_R_HPOUT_EN, ++ RK3308_DAC_L_HPOUT_DIS | ++ RK3308_DAC_R_HPOUT_DIS); ++ ++ /* Step 08 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_WORK | ++ RK3308_DAC_R_HPOUT_WORK, ++ RK3308_DAC_L_HPOUT_INIT | ++ RK3308_DAC_R_HPOUT_INIT); ++ ++ /* Step 16 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_UNMUTE | ++ RK3308_DAC_R_HPOUT_UNMUTE, ++ RK3308_DAC_L_HPOUT_MUTE | ++ RK3308_DAC_R_HPOUT_MUTE); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_switch(struct rk3308_codec_priv *rk3308, ++ int dac_output) ++{ int ret = 0; ++ ++ if (rk3308->dac_output == dac_output) { ++ dev_info(rk3308->plat_dev, ++ "Don't need to change dac_output: %d\n", dac_output); ++ goto out; ++ } ++ ++ switch (dac_output) { ++ case DAC_LINEOUT: ++ case DAC_HPOUT: ++ case DAC_LINEOUT_HPOUT: ++ break; ++ default: ++ dev_err(rk3308->plat_dev, "Unknown value: %d\n", dac_output); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (rk3308_codec_get_dac_path_state(rk3308) == PATH_BUSY) { ++ /* ++ * We can only switch the audio path to LINEOUT or HPOUT on ++ * codec during playbacking, otherwise, just update the ++ * dac_output flag. ++ */ ++ switch (dac_output) { ++ case DAC_LINEOUT: ++ rk3308_headphone_ctl(rk3308, 0); ++ rk3308_speaker_ctl(rk3308, 1); ++ rk3308_codec_dac_hpout_disable(rk3308); ++ rk3308_codec_dac_lineout_enable(rk3308); ++ break; ++ case DAC_HPOUT: ++ rk3308_speaker_ctl(rk3308, 0); ++ rk3308_headphone_ctl(rk3308, 1); ++ rk3308_codec_dac_lineout_disable(rk3308); ++ rk3308_codec_dac_hpout_enable(rk3308); ++ break; ++ case DAC_LINEOUT_HPOUT: ++ rk3308_speaker_ctl(rk3308, 1); ++ rk3308_headphone_ctl(rk3308, 1); ++ rk3308_codec_dac_lineout_enable(rk3308); ++ rk3308_codec_dac_hpout_enable(rk3308); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ rk3308->dac_output = dac_output; ++out: ++ dev_dbg(rk3308->plat_dev, "switch dac_output to: %d\n", ++ rk3308->dac_output); ++ ++ return ret; ++} ++ ++static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308) ++{ ++ /* ++ * Note1. If the ACODEC_DAC_ANA_CON12[6] or ACODEC_DAC_ANA_CON12[2] ++ * is set to 0x1, ignoring the step9~12. ++ */ ++ ++ /* ++ * Note2. If the ACODEC_ DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] ++ * is set to 0x1, the ADC0 or ADC1 should be enabled firstly, and ++ * please refer to Enable ADC Configuration Standard Usage Flow(expect ++ * step7~step9,step14). ++ */ ++ ++ /* ++ * Note3. If no opening the line out, ignoring the step6, step17 and ++ * step19. ++ */ ++ ++ /* ++ * Note4. If no opening the headphone out, ignoring the step3,step7~8, ++ * step16 and step18. ++ */ ++ ++ /* ++ * Note5. In the step18, adjust the register step by step to the ++ * appropriate value and taking 10ms as one time step ++ */ ++ ++ /* ++ * 1. Set the ACODEC_DAC_ANA_CON0[0] to 0x1, to enable the current ++ * source of DAC ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, ++ RK3308_DAC_CURRENT_MSK, ++ RK3308_DAC_CURRENT_EN); ++ ++ udelay(20); ++ ++ /* ++ * 2. Set the ACODEC_DAC_ANA_CON1[6] and ACODEC_DAC_ANA_CON1[2] to 0x1, ++ * to enable the reference voltage buffer ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_BUF_REF_L_MSK | ++ RK3308_DAC_BUF_REF_R_MSK, ++ RK3308_DAC_BUF_REF_L_EN | ++ RK3308_DAC_BUF_REF_R_EN); ++ ++ /* Waiting the stable reference voltage */ ++ mdelay(1); ++ ++ if (rk3308->dac_output == DAC_HPOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Step 03 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_HPOUT_POP_SOUND_L_WORK | ++ RK3308_DAC_HPOUT_POP_SOUND_R_WORK); ++ ++ udelay(20); ++ } ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B && ++ (rk3308->dac_output == DAC_LINEOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT)) { ++ /* Step 04 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_L_SEL_DC_FROM_INTERNAL | ++ RK3308_DAC_R_SEL_DC_FROM_INTERNAL); ++ ++ udelay(20); ++ } ++ ++ /* Step 05 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_EN | ++ RK3308_DAC_R_HPMIX_EN, ++ RK3308_DAC_L_HPMIX_EN | ++ RK3308_DAC_R_HPMIX_EN); ++ ++ /* Waiting the stable HPMIX */ ++ mdelay(1); ++ ++ /* Step 06. Reset HPMIX and recover HPMIX gains */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_WORK | ++ RK3308_DAC_R_HPMIX_WORK, ++ RK3308_DAC_L_HPMIX_INIT | ++ RK3308_DAC_R_HPMIX_INIT); ++ udelay(50); ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_WORK | ++ RK3308_DAC_R_HPMIX_WORK, ++ RK3308_DAC_L_HPMIX_WORK | ++ RK3308_DAC_R_HPMIX_WORK); ++ ++ udelay(20); ++ ++ if (rk3308->dac_output == DAC_LINEOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Step 07 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_EN | ++ RK3308_DAC_R_LINEOUT_EN, ++ RK3308_DAC_L_LINEOUT_EN | ++ RK3308_DAC_R_LINEOUT_EN); ++ ++ udelay(20); ++ } ++ ++ if (rk3308->dac_output == DAC_HPOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Step 08 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_EN | ++ RK3308_DAC_R_HPOUT_EN, ++ RK3308_DAC_L_HPOUT_EN | ++ RK3308_DAC_R_HPOUT_EN); ++ ++ udelay(20); ++ ++ /* Step 09 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_WORK | ++ RK3308_DAC_R_HPOUT_WORK, ++ RK3308_DAC_L_HPOUT_WORK | ++ RK3308_DAC_R_HPOUT_WORK); ++ ++ udelay(20); ++ } ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* Step 10 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL | ++ RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL); ++ ++ udelay(20); ++ } ++ ++ /* Step 11 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_REF_EN | ++ RK3308_DAC_R_REF_EN, ++ RK3308_DAC_L_REF_EN | ++ RK3308_DAC_R_REF_EN); ++ ++ udelay(20); ++ ++ /* Step 12 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_CLK_EN | ++ RK3308_DAC_R_CLK_EN, ++ RK3308_DAC_L_CLK_EN | ++ RK3308_DAC_R_CLK_EN); ++ ++ udelay(20); ++ ++ /* Step 13 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_DAC_EN | ++ RK3308_DAC_R_DAC_EN, ++ RK3308_DAC_L_DAC_EN | ++ RK3308_DAC_R_DAC_EN); ++ ++ udelay(20); ++ ++ /* Step 14 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_DAC_WORK | ++ RK3308_DAC_R_DAC_WORK, ++ RK3308_DAC_L_DAC_WORK | ++ RK3308_DAC_R_DAC_WORK); ++ ++ udelay(20); ++ ++ /* Step 15 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, ++ RK3308_DAC_L_HPMIX_SEL_MSK | ++ RK3308_DAC_R_HPMIX_SEL_MSK, ++ RK3308_DAC_L_HPMIX_I2S | ++ RK3308_DAC_R_HPMIX_I2S); ++ ++ udelay(20); ++ ++ /* Step 16 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_UNMUTE | ++ RK3308_DAC_R_HPMIX_UNMUTE, ++ RK3308_DAC_L_HPMIX_UNMUTE | ++ RK3308_DAC_R_HPMIX_UNMUTE); ++ ++ udelay(20); ++ ++ /* Step 17: Put configuration HPMIX Gain to DAPM */ ++ ++ if (rk3308->dac_output == DAC_HPOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Step 18 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_UNMUTE | ++ RK3308_DAC_R_HPOUT_UNMUTE, ++ RK3308_DAC_L_HPOUT_UNMUTE | ++ RK3308_DAC_R_HPOUT_UNMUTE); ++ ++ udelay(20); ++ } ++ ++ if (rk3308->dac_output == DAC_LINEOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Step 19 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_UNMUTE | ++ RK3308_DAC_R_LINEOUT_UNMUTE, ++ RK3308_DAC_L_LINEOUT_UNMUTE | ++ RK3308_DAC_R_LINEOUT_UNMUTE); ++ udelay(20); ++ } ++ ++ /* Step 20, put configuration HPOUT gain to DAPM control */ ++ /* Step 21, put configuration LINEOUT gain to DAPM control */ ++ ++ if (rk3308->dac_output == DAC_HPOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Just for HPOUT */ ++ rk3308_codec_digital_fadein(rk3308); ++ } ++ ++ rk3308->dac_endisable = true; ++ ++ /* TODO: TRY TO TEST DRIVE STRENGTH */ ++ ++ return 0; ++} ++ ++static int rk3308_codec_dac_disable(struct rk3308_codec_priv *rk3308) ++{ ++ /* ++ * Step 00 skipped. Keep the DAC channel work and input the mute signal. ++ */ ++ ++ /* Step 01 skipped. May set the min gain for LINEOUT. */ ++ ++ /* Step 02 skipped. May set the min gain for HPOUT. */ ++ ++ if (rk3308->dac_output == DAC_HPOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT) { ++ /* Just for HPOUT */ ++ rk3308_codec_digital_fadeout(rk3308); ++ } ++ ++ /* Step 03 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_UNMUTE | ++ RK3308_DAC_R_HPMIX_UNMUTE, ++ RK3308_DAC_L_HPMIX_UNMUTE | ++ RK3308_DAC_R_HPMIX_UNMUTE); ++ ++ /* Step 04 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, ++ RK3308_DAC_L_HPMIX_SEL_MSK | ++ RK3308_DAC_R_HPMIX_SEL_MSK, ++ RK3308_DAC_L_HPMIX_NONE | ++ RK3308_DAC_R_HPMIX_NONE); ++ /* Step 05 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_UNMUTE | ++ RK3308_DAC_R_HPOUT_UNMUTE, ++ RK3308_DAC_L_HPOUT_MUTE | ++ RK3308_DAC_R_HPOUT_MUTE); ++ ++ /* Step 06 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_DAC_WORK | ++ RK3308_DAC_R_DAC_WORK, ++ RK3308_DAC_L_DAC_INIT | ++ RK3308_DAC_R_DAC_INIT); ++ ++ /* Step 07 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_EN | ++ RK3308_DAC_R_HPOUT_EN, ++ RK3308_DAC_L_HPOUT_DIS | ++ RK3308_DAC_R_HPOUT_DIS); ++ ++ /* Step 08 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_UNMUTE | ++ RK3308_DAC_R_LINEOUT_UNMUTE, ++ RK3308_DAC_L_LINEOUT_MUTE | ++ RK3308_DAC_R_LINEOUT_MUTE); ++ ++ /* Step 09 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_EN | ++ RK3308_DAC_R_LINEOUT_EN, ++ RK3308_DAC_L_LINEOUT_DIS | ++ RK3308_DAC_R_LINEOUT_DIS); ++ ++ /* Step 10 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_EN | ++ RK3308_DAC_R_HPMIX_EN, ++ RK3308_DAC_L_HPMIX_DIS | ++ RK3308_DAC_R_HPMIX_DIS); ++ ++ /* Step 11 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_DAC_EN | ++ RK3308_DAC_R_DAC_EN, ++ RK3308_DAC_L_DAC_DIS | ++ RK3308_DAC_R_DAC_DIS); ++ ++ /* Step 12 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_CLK_EN | ++ RK3308_DAC_R_CLK_EN, ++ RK3308_DAC_L_CLK_DIS | ++ RK3308_DAC_R_CLK_DIS); ++ ++ /* Step 13 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, ++ RK3308_DAC_L_REF_EN | ++ RK3308_DAC_R_REF_EN, ++ RK3308_DAC_L_REF_DIS | ++ RK3308_DAC_R_REF_DIS); ++ ++ /* Step 14 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_HPOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_HPOUT_POP_SOUND_L_INIT | ++ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); ++ ++ /* Step 15 */ ++ if (rk3308->codec_ver == ACODEC_VERSION_B && ++ (rk3308->dac_output == DAC_LINEOUT || ++ rk3308->dac_output == DAC_LINEOUT_HPOUT)) { ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | ++ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_L_SEL_DC_FROM_VCM | ++ RK3308_DAC_R_SEL_DC_FROM_VCM); ++ } ++ ++ /* Step 16 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_BUF_REF_L_EN | ++ RK3308_DAC_BUF_REF_R_EN, ++ RK3308_DAC_BUF_REF_L_DIS | ++ RK3308_DAC_BUF_REF_R_DIS); ++ ++ /* Step 17 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, ++ RK3308_DAC_CURRENT_EN, ++ RK3308_DAC_CURRENT_DIS); ++ ++ /* Step 18 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON03, ++ RK3308_DAC_L_HPOUT_WORK | ++ RK3308_DAC_R_HPOUT_WORK, ++ RK3308_DAC_L_HPOUT_INIT | ++ RK3308_DAC_R_HPOUT_INIT); ++ ++ /* Step 19 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON13, ++ RK3308_DAC_L_HPMIX_WORK | ++ RK3308_DAC_R_HPMIX_WORK, ++ RK3308_DAC_L_HPMIX_WORK | ++ RK3308_DAC_R_HPMIX_WORK); ++ ++ /* Step 20 skipped, may set the min gain for HPOUT. */ ++ ++ /* ++ * Note2. If the ACODEC_DAC_ANA_CON12[7] or ACODEC_DAC_ANA_CON12[3] ++ * is set to 0x1, add the steps from the section Disable ADC ++ * Configuration Standard Usage Flow after complete the step 19 ++ * ++ * IF USING LINE-IN ++ * rk3308_codec_adc_ana_disable(rk3308, type); ++ */ ++ ++ rk3308->dac_endisable = false; ++ ++ return 0; ++} ++ ++static int rk3308_codec_power_on(struct rk3308_codec_priv *rk3308) ++{ ++ unsigned int v; ++ ++ /* 0. Supply the power of digital part and reset the Audio Codec */ ++ /* Do nothing */ ++ ++ /* ++ * 1. Configure ACODEC_DAC_ANA_CON1[1:0] and ACODEC_DAC_ANA_CON1[5:4] ++ * to 0x1, to setup dc voltage of the DAC channel output. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_HPOUT_POP_SOUND_L_MSK, ++ RK3308_DAC_HPOUT_POP_SOUND_L_INIT); ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, ++ RK3308_DAC_HPOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_HPOUT_POP_SOUND_R_INIT); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 2. Configure ACODEC_DAC_ANA_CON15[1:0] and ++ * ACODEC_DAC_ANA_CON15[5:4] to 0x1, to setup dc voltage of ++ * the DAC channel output. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK, ++ RK3308_DAC_L_SEL_DC_FROM_VCM); ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, ++ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, ++ RK3308_DAC_R_SEL_DC_FROM_VCM); ++ } ++ ++ /* ++ * 3. Configure the register ACODEC_ADC_ANA_CON10[3:0] to 7’b000_0001. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_CURRENT_CHARGE_MSK, ++ RK3308_ADC_SEL_I(0x1)); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 4. Configure the register ACODEC_ADC_ANA_CON14[3:0] to ++ * 4’b0001. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, ++ RK3308_DAC_CURRENT_CHARGE_MSK, ++ RK3308_DAC_SEL_I(0x1)); ++ } ++ ++ /* 5. Supply the power of the analog part(AVDD,AVDDRV) */ ++ ++ /* ++ * 6. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x1 to setup ++ * reference voltage ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_REF_EN, RK3308_ADC_REF_EN); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 7. Configure the register ACODEC_ADC_ANA_CON14[4] to 0x1 to ++ * setup reference voltage ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, ++ RK3308_DAC_VCM_LINEOUT_EN, ++ RK3308_DAC_VCM_LINEOUT_EN); ++ } ++ ++ /* ++ * 8. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to ++ * 0x7f step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to ++ * 0x7f directly. Here the slot time of the step is 200us. ++ */ ++ for (v = 0x1; v <= 0x7f; v++) { ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_CURRENT_CHARGE_MSK, ++ v); ++ udelay(200); ++ } ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 9. Change the register ACODEC_ADC_ANA_CON14[3:0] from the 0x1 ++ * to 0xf step by step or configure the ++ * ACODEC_ADC_ANA_CON14[3:0] to 0xf directly. Here the slot ++ * time of the step is 200us. ++ */ ++ for (v = 0x1; v <= 0xf; v++) { ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, ++ RK3308_DAC_CURRENT_CHARGE_MSK, ++ v); ++ udelay(200); ++ } ++ } ++ ++ /* 10. Wait until the voltage of VCM keeps stable at the AVDD/2 */ ++ msleep(20); /* estimated value */ ++ ++ /* ++ * 11. Configure the register ACODEC_ADC_ANA_CON10[6:0] to the ++ * appropriate value(expect 0x0) for reducing power. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_CURRENT_CHARGE_MSK, 0x7c); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 12. Configure the register ACODEC_DAC_ANA_CON14[6:0] to the ++ * appropriate value(expect 0x0) for reducing power. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, ++ RK3308_DAC_CURRENT_CHARGE_MSK, 0xf); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_power_off(struct rk3308_codec_priv *rk3308) ++{ ++ unsigned int v; ++ ++ /* ++ * 0. Keep the power on and disable the DAC and ADC path according to ++ * the section power on configuration standard usage flow. ++ */ ++ ++ /* ++ * 1. Configure the register ACODEC_ADC_ANA_CON10[6:0] to 7’b000_0001. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_CURRENT_CHARGE_MSK, ++ RK3308_ADC_SEL_I(0x1)); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 2. Configure the register ACODEC_DAC_ANA_CON14[3:0] to ++ * 4’b0001. ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, ++ RK3308_DAC_CURRENT_CHARGE_MSK, ++ RK3308_DAC_SEL_I(0x1)); ++ } ++ ++ /* 3. Configure the register ACODEC_ADC_ANA_CON10[7] to 0x0 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_REF_EN, ++ RK3308_ADC_REF_DIS); ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* 4. Configure the register ACODEC_DAC_ANA_CON14[7] to 0x0 */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, ++ RK3308_DAC_VCM_LINEOUT_EN, ++ RK3308_DAC_VCM_LINEOUT_DIS); ++ } ++ ++ /* ++ * 5. Change the register ACODEC_ADC_ANA_CON10[6:0] from the 0x1 to 0x7f ++ * step by step or configure the ACODEC_ADC_ANA_CON10[6:0] to 0x7f ++ * directly. Here the slot time of the step is 200us. ++ */ ++ for (v = 0x1; v <= 0x7f; v++) { ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_CURRENT_CHARGE_MSK, ++ v); ++ udelay(200); ++ } ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* ++ * 6. Change the register ACODEC_DAC_ANA_CON14[3:0] from the 0x1 ++ * to 0xf step by step or configure the ++ * ACODEC_DAC_ANA_CON14[3:0] to 0xf directly. Here the slot ++ * time of the step is 200us. ++ */ ++ for (v = 0x1; v <= 0x7f; v++) { ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_ANA_CON10(0), ++ RK3308_ADC_CURRENT_CHARGE_MSK, ++ v); ++ udelay(200); ++ } ++ } ++ ++ /* 7. Wait until the voltage of VCM keeps stable at the AGND */ ++ msleep(20); /* estimated value */ ++ ++ /* 8. Power off the analog power supply */ ++ /* 9. Power off the digital power supply */ ++ ++ /* Do something via hardware */ ++ ++ return 0; ++} ++ ++static int rk3308_codec_headset_detect_enable(struct rk3308_codec_priv *rk3308) ++{ ++ /* ++ * Set ACODEC_DAC_ANA_CON0[1] to 0x1, to enable the headset insert ++ * detection ++ * ++ * Note. When the voltage of PAD HPDET> 8*AVDD/9, the output value of ++ * the pin_hpdet will be set to 0x1 and assert a interrupt ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, ++ RK3308_DAC_HEADPHONE_DET_MSK, ++ RK3308_DAC_HEADPHONE_DET_EN); ++ ++ return 0; ++} ++ ++static int rk3308_codec_headset_detect_disable(struct rk3308_codec_priv *rk3308) ++{ ++ /* ++ * Set ACODEC_DAC_ANA_CON0[1] to 0x0, to disable the headset insert ++ * detection ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON00, ++ RK3308_DAC_HEADPHONE_DET_MSK, ++ RK3308_DAC_HEADPHONE_DET_DIS); ++ ++ return 0; ++} ++ ++static int rk3308_codec_check_i2s_sdis(struct rk3308_codec_priv *rk3308, ++ int num) ++{ ++ int i, j, ret = 0; ++ ++ switch (num) { ++ case 1: ++ rk3308->which_i2s = ACODEC_TO_I2S1_2CH; ++ break; ++ case 2: ++ rk3308->which_i2s = ACODEC_TO_I2S3_4CH; ++ break; ++ case 4: ++ rk3308->which_i2s = ACODEC_TO_I2S2_8CH; ++ break; ++ default: ++ dev_err(rk3308->plat_dev, "Invalid i2s sdis num: %d\n", num); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ for (i = 0; i < num; i++) { ++ if (rk3308->i2s_sdis[i] > ADC_LR_GROUP_MAX - 1) { ++ dev_err(rk3308->plat_dev, ++ "i2s_sdis[%d]: %d is overflow\n", ++ i, rk3308->i2s_sdis[i]); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ for (j = 0; j < num; j++) { ++ if (i == j) ++ continue; ++ ++ if (rk3308->i2s_sdis[i] == rk3308->i2s_sdis[j]) { ++ dev_err(rk3308->plat_dev, ++ "Invalid i2s_sdis: [%d]%d == [%d]%d\n", ++ i, rk3308->i2s_sdis[i], ++ j, rk3308->i2s_sdis[j]); ++ ret = -EINVAL; ++ goto err; ++ } ++ } ++ } ++ ++err: ++ return ret; ++} ++ ++static int rk3308_codec_adc_grps_route_config(struct rk3308_codec_priv *rk3308) ++{ ++ int idx = 0; ++ ++ if (rk3308->which_i2s == ACODEC_TO_I2S2_8CH) { ++ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) { ++ regmap_write(rk3308->grf, GRF_SOC_CON1, ++ GRF_I2S2_8CH_SDI(idx, rk3308->i2s_sdis[idx])); ++ } ++ } else if (rk3308->which_i2s == ACODEC_TO_I2S3_4CH) { ++ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) { ++ regmap_write(rk3308->grf, GRF_SOC_CON1, ++ GRF_I2S3_4CH_SDI(idx, rk3308->i2s_sdis[idx])); ++ } ++ } else if (rk3308->which_i2s == ACODEC_TO_I2S1_2CH) { ++ regmap_write(rk3308->grf, GRF_SOC_CON1, ++ GRF_I2S1_2CH_SDI(rk3308->i2s_sdis[idx])); ++ } ++ ++ return 0; ++} ++ ++/* Put default one-to-one mapping */ ++static int rk3308_codec_adc_grps_route_default(struct rk3308_codec_priv *rk3308) ++{ ++ unsigned int idx; ++ ++ /* ++ * The GRF values may be kept the previous status after hot reboot, ++ * if the property 'rockchip,adc-grps-route' is not set, we need to ++ * recover default the order of sdi/sdo for i2s2_8ch/i2s3_8ch/i2s1_2ch. ++ */ ++ regmap_write(rk3308->grf, GRF_SOC_CON1, ++ GRF_I2S1_2CH_SDI(0)); ++ ++ for (idx = 0; idx < 2; idx++) { ++ regmap_write(rk3308->grf, GRF_SOC_CON1, ++ GRF_I2S3_4CH_SDI(idx, idx)); ++ } ++ ++ /* Using i2s2_8ch by default. */ ++ rk3308->which_i2s = ACODEC_TO_I2S2_8CH; ++ rk3308->to_i2s_grps = ADC_LR_GROUP_MAX; ++ ++ for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) { ++ rk3308->i2s_sdis[idx] = idx; ++ regmap_write(rk3308->grf, GRF_SOC_CON1, ++ GRF_I2S2_8CH_SDI(idx, idx)); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_adc_grps_route(struct rk3308_codec_priv *rk3308, ++ struct device_node *np) ++{ ++ int num, ret; ++ ++ num = of_count_phandle_with_args(np, "rockchip,adc-grps-route", NULL); ++ if (num < 0) { ++ if (num == -ENOENT) { ++ /* Not use 'rockchip,adc-grps-route' property here */ ++ rk3308_codec_adc_grps_route_default(rk3308); ++ ret = 0; ++ } else { ++ dev_err(rk3308->plat_dev, ++ "Failed to read 'rockchip,adc-grps-route' num: %d\n", ++ num); ++ ret = num; ++ } ++ return ret; ++ } ++ ++ ret = of_property_read_u32_array(np, "rockchip,adc-grps-route", ++ rk3308->i2s_sdis, num); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to read 'rockchip,adc-grps-route': %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = rk3308_codec_check_i2s_sdis(rk3308, num); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to check i2s_sdis: %d\n", ret); ++ return ret; ++ } ++ ++ rk3308->to_i2s_grps = num; ++ ++ rk3308_codec_adc_grps_route_config(rk3308); ++ ++ return 0; ++} ++ ++static int check_micbias(int micbias) ++{ ++ switch (micbias) { ++ case RK3308_ADC_MICBIAS_VOLT_0_85: ++ case RK3308_ADC_MICBIAS_VOLT_0_8: ++ case RK3308_ADC_MICBIAS_VOLT_0_75: ++ case RK3308_ADC_MICBIAS_VOLT_0_7: ++ case RK3308_ADC_MICBIAS_VOLT_0_65: ++ case RK3308_ADC_MICBIAS_VOLT_0_6: ++ case RK3308_ADC_MICBIAS_VOLT_0_55: ++ case RK3308_ADC_MICBIAS_VOLT_0_5: ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static bool handle_loopback(struct rk3308_codec_priv *rk3308) ++{ ++ /* The version B doesn't need to handle loopback. */ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) ++ return false; ++ ++ switch (rk3308->loopback_grp) { ++ case 0: ++ case 1: ++ case 2: ++ case 3: ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool has_en_always_grps(struct rk3308_codec_priv *rk3308) ++{ ++ int idx; ++ ++ if (rk3308->en_always_grps_num) { ++ for (idx = 0; idx < ADC_LR_GROUP_MAX; idx++) { ++ if (rk3308->en_always_grps[idx] >= 0 && ++ rk3308->en_always_grps[idx] <= ADC_LR_GROUP_MAX - 1) ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, ++ int micbias) ++{ ++ int ret; ++ ++ if (rk3308->ext_micbias != EXT_MICBIAS_NONE) ++ return 0; ++ ++ /* 0. Power up the ACODEC and keep the AVDDH stable */ ++ ++ /* Step 1. Configure ACODEC_ADC_ANA_CON7[2:0] to the certain value */ ++ ret = check_micbias(micbias); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, "This is an invalid micbias: %d\n", ++ micbias); ++ return ret; ++ } ++ ++ /* ++ * Note: Only the reg (ADC_ANA_CON7+0x0)[2:0] represent the level range ++ * control signal of MICBIAS voltage ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), ++ RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, ++ micbias); ++ ++ /* Step 2. Wait until the VCMH keep stable */ ++ msleep(20); /* estimated value */ ++ ++ /* ++ * Step 3. Configure ACODEC_ADC_ANA_CON8[4] to 0x1 ++ * ++ * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable ++ * signal of current source for MICBIAS ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0), ++ RK3308_ADC_MICBIAS_CURRENT_MSK, ++ RK3308_ADC_MICBIAS_CURRENT_EN); ++ ++ /* ++ * Step 4. Configure the (ADC_ANA_CON7+0x40)[3] or ++ * (ADC_ANA_CON7+0x80)[3] to 0x1. ++ * ++ * (ADC_ANA_CON7+0x40)[3] used to control the MICBIAS1, and ++ * (ADC_ANA_CON7+0x80)[3] used to control the MICBIAS2 ++ */ ++ if (rk3308->micbias1) ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1), ++ RK3308_ADC_MIC_BIAS_BUF_EN, ++ RK3308_ADC_MIC_BIAS_BUF_EN); ++ ++ if (rk3308->micbias2) ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2), ++ RK3308_ADC_MIC_BIAS_BUF_EN, ++ RK3308_ADC_MIC_BIAS_BUF_EN); ++ ++ /* waiting micbias stabled*/ ++ mdelay(50); ++ ++ rk3308->enable_micbias = true; ++ ++ return 0; ++} ++ ++static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308) ++{ ++ if (rk3308->ext_micbias != EXT_MICBIAS_NONE) ++ return 0; ++ ++ /* Step 0. Enable the MICBIAS and keep the Audio Codec stable */ ++ /* Do nothing */ ++ ++ /* ++ * Step 1. Configure the (ADC_ANA_CON7+0x40)[3] or ++ * (ADC_ANA_CON7+0x80)[3] to 0x0 ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(1), ++ RK3308_ADC_MIC_BIAS_BUF_EN, ++ RK3308_ADC_MIC_BIAS_BUF_DIS); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(2), ++ RK3308_ADC_MIC_BIAS_BUF_EN, ++ RK3308_ADC_MIC_BIAS_BUF_DIS); ++ ++ /* ++ * Step 2. Configure ACODEC_ADC_ANA_CON8[4] to 0x0 ++ * ++ * Note: Only the reg (ADC_ANA_CON8+0x0)[4] represent the enable ++ * signal of current source for MICBIAS ++ */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0), ++ RK3308_ADC_MICBIAS_CURRENT_MSK, ++ RK3308_ADC_MICBIAS_CURRENT_DIS); ++ ++ rk3308->enable_micbias = false; ++ ++ return 0; ++} ++ ++static int rk3308_codec_adc_reinit_mics(struct rk3308_codec_priv *rk3308, ++ int type) ++{ ++ int idx, grp; ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 1 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_ADC_WORK | ++ RK3308_ADC_CH2_ADC_WORK, ++ RK3308_ADC_CH1_ADC_INIT | ++ RK3308_ADC_CH2_ADC_INIT); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 2 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ALC_WORK | ++ RK3308_ADC_CH2_ALC_WORK, ++ RK3308_ADC_CH1_ALC_INIT | ++ RK3308_ADC_CH2_ALC_INIT); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 3 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_WORK | ++ RK3308_ADC_CH2_MIC_WORK, ++ RK3308_ADC_CH1_MIC_INIT | ++ RK3308_ADC_CH2_MIC_INIT); ++ } ++ ++ usleep_range(200, 250); /* estimated value */ ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 1 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_ADC_WORK | ++ RK3308_ADC_CH2_ADC_WORK, ++ RK3308_ADC_CH1_ADC_WORK | ++ RK3308_ADC_CH2_ADC_WORK); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 2 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ALC_WORK | ++ RK3308_ADC_CH2_ALC_WORK, ++ RK3308_ADC_CH1_ALC_WORK | ++ RK3308_ADC_CH2_ALC_WORK); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 3 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_WORK | ++ RK3308_ADC_CH2_MIC_WORK, ++ RK3308_ADC_CH1_MIC_WORK | ++ RK3308_ADC_CH2_MIC_WORK); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_adc_ana_enable(struct rk3308_codec_priv *rk3308, ++ int type) ++{ ++ unsigned int agc_func_en; ++ int idx, grp; ++ ++ /* ++ * 1. Set the ACODEC_ADC_ANA_CON7[7:6] and ACODEC_ADC_ANA_CON7[5:4], ++ * to select the line-in or microphone as input of ADC ++ * ++ * Note1. Please ignore the step1 for enabling ADC3, ADC4, ADC5, ++ * ADC6, ADC7, and ADC8 ++ */ ++ if (rk3308->adc_grp0_using_linein) { ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), ++ RK3308_ADC_CH1_IN_SEL_MSK | ++ RK3308_ADC_CH2_IN_SEL_MSK, ++ RK3308_ADC_CH1_IN_LINEIN | ++ RK3308_ADC_CH2_IN_LINEIN); ++ ++ /* Keep other ADCs as MIC-IN */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ /* The groups without line-in are >= 1 */ ++ if (grp < 1 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_ANA_CON07(grp), ++ RK3308_ADC_CH1_IN_SEL_MSK | ++ RK3308_ADC_CH2_IN_SEL_MSK, ++ RK3308_ADC_CH1_IN_MIC | ++ RK3308_ADC_CH2_IN_MIC); ++ } ++ } else { ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_ANA_CON07(grp), ++ RK3308_ADC_CH1_IN_SEL_MSK | ++ RK3308_ADC_CH2_IN_SEL_MSK, ++ RK3308_ADC_CH1_IN_MIC | ++ RK3308_ADC_CH2_IN_MIC); ++ } ++ } ++ ++ /* ++ * 2. Set ACODEC_ADC_ANA_CON0[7] and [3] to 0x1, to end the mute station ++ * of ADC, to enable the MIC module, to enable the reference voltage ++ * buffer, and to end the initialization of MIC ++ */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_UNMUTE | ++ RK3308_ADC_CH2_MIC_UNMUTE, ++ RK3308_ADC_CH1_MIC_UNMUTE | ++ RK3308_ADC_CH2_MIC_UNMUTE); ++ } ++ ++ /* ++ * 3. Set ACODEC_ADC_ANA_CON6[0] to 0x1, to enable the current source ++ * of audio ++ */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp), ++ RK3308_ADC_CURRENT_MSK, ++ RK3308_ADC_CURRENT_EN); ++ } ++ ++ /* ++ * This is mainly used for BIST mode that wait ADCs are stable. ++ * ++ * By tested results, the type delay is >40us, but we need to leave ++ * enough delay margin. ++ */ ++ usleep_range(400, 500); ++ ++ /* vendor step 4*/ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_BUF_REF_EN | ++ RK3308_ADC_CH2_BUF_REF_EN, ++ RK3308_ADC_CH1_BUF_REF_EN | ++ RK3308_ADC_CH2_BUF_REF_EN); ++ } ++ ++ /* vendor step 5 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_EN | ++ RK3308_ADC_CH2_MIC_EN, ++ RK3308_ADC_CH1_MIC_EN | ++ RK3308_ADC_CH2_MIC_EN); ++ } ++ ++ /* vendor step 6 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ALC_EN | ++ RK3308_ADC_CH2_ALC_EN, ++ RK3308_ADC_CH1_ALC_EN | ++ RK3308_ADC_CH2_ALC_EN); ++ } ++ ++ /* vendor step 7 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_CLK_EN | ++ RK3308_ADC_CH2_CLK_EN, ++ RK3308_ADC_CH1_CLK_EN | ++ RK3308_ADC_CH2_CLK_EN); ++ } ++ ++ /* vendor step 8 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_ADC_EN | ++ RK3308_ADC_CH2_ADC_EN, ++ RK3308_ADC_CH1_ADC_EN | ++ RK3308_ADC_CH2_ADC_EN); ++ } ++ ++ /* vendor step 9 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_ADC_WORK | ++ RK3308_ADC_CH2_ADC_WORK, ++ RK3308_ADC_CH1_ADC_WORK | ++ RK3308_ADC_CH2_ADC_WORK); ++ } ++ ++ /* vendor step 10 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ALC_WORK | ++ RK3308_ADC_CH2_ALC_WORK, ++ RK3308_ADC_CH1_ALC_WORK | ++ RK3308_ADC_CH2_ALC_WORK); ++ } ++ ++ /* vendor step 11 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_WORK | ++ RK3308_ADC_CH2_MIC_WORK, ++ RK3308_ADC_CH1_MIC_WORK | ++ RK3308_ADC_CH2_MIC_WORK); ++ } ++ ++ /* vendor step 12 */ ++ ++ /* vendor step 13 */ ++ ++ /* vendor step 14 */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_read(rk3308->regmap, RK3308_ALC_L_DIG_CON09(grp), ++ &agc_func_en); ++ if (rk3308->adc_zerocross || ++ agc_func_en & RK3308_AGC_FUNC_SEL_EN) { ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ZEROCROSS_DET_EN, ++ RK3308_ADC_CH1_ZEROCROSS_DET_EN); ++ } ++ regmap_read(rk3308->regmap, RK3308_ALC_R_DIG_CON09(grp), ++ &agc_func_en); ++ if (rk3308->adc_zerocross || ++ agc_func_en & RK3308_AGC_FUNC_SEL_EN) { ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH2_ZEROCROSS_DET_EN, ++ RK3308_ADC_CH2_ZEROCROSS_DET_EN); ++ } ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ rk3308->adc_grps_endisable[grp] = true; ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_adc_ana_disable(struct rk3308_codec_priv *rk3308, ++ int type) ++{ ++ int idx, grp; ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 1 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ZEROCROSS_DET_EN | ++ RK3308_ADC_CH2_ZEROCROSS_DET_EN, ++ RK3308_ADC_CH1_ZEROCROSS_DET_DIS | ++ RK3308_ADC_CH2_ZEROCROSS_DET_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 2 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_ADC_EN | ++ RK3308_ADC_CH2_ADC_EN, ++ RK3308_ADC_CH1_ADC_DIS | ++ RK3308_ADC_CH2_ADC_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 3 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_CLK_EN | ++ RK3308_ADC_CH2_CLK_EN, ++ RK3308_ADC_CH1_CLK_DIS | ++ RK3308_ADC_CH2_CLK_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 4 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ALC_EN | ++ RK3308_ADC_CH2_ALC_EN, ++ RK3308_ADC_CH1_ALC_DIS | ++ RK3308_ADC_CH2_ALC_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 5 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_EN | ++ RK3308_ADC_CH2_MIC_EN, ++ RK3308_ADC_CH1_MIC_DIS | ++ RK3308_ADC_CH2_MIC_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 6 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_BUF_REF_EN | ++ RK3308_ADC_CH2_BUF_REF_EN, ++ RK3308_ADC_CH1_BUF_REF_DIS | ++ RK3308_ADC_CH2_BUF_REF_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 7 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON06(grp), ++ RK3308_ADC_CURRENT_MSK, ++ RK3308_ADC_CURRENT_DIS); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 8 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON05(grp), ++ RK3308_ADC_CH1_ADC_WORK | ++ RK3308_ADC_CH2_ADC_WORK, ++ RK3308_ADC_CH1_ADC_INIT | ++ RK3308_ADC_CH2_ADC_INIT); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 9 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), ++ RK3308_ADC_CH1_ALC_WORK | ++ RK3308_ADC_CH2_ALC_WORK, ++ RK3308_ADC_CH1_ALC_INIT | ++ RK3308_ADC_CH2_ALC_INIT); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ /* vendor step 10 */ ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp), ++ RK3308_ADC_CH1_MIC_WORK | ++ RK3308_ADC_CH2_MIC_WORK, ++ RK3308_ADC_CH1_MIC_INIT | ++ RK3308_ADC_CH2_MIC_INIT); ++ } ++ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ rk3308->adc_grps_endisable[grp] = false; ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_open_capture(struct rk3308_codec_priv *rk3308) ++{ ++ int idx, grp = 0; ++ int type = ADC_TYPE_NORMAL; ++ ++ rk3308_codec_adc_ana_enable(rk3308, type); ++ rk3308_codec_adc_reinit_mics(rk3308, type); ++ ++ if (rk3308->adc_grp0_using_linein) { ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_NORMAL_RIGHT); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(0), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_NORMAL_LEFT); ++ } else { ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (handle_loopback(rk3308) && ++ idx == rk3308->loopback_grp && ++ grp == ADC_GRP_SKIP_MAGIC) { ++ /* ++ * Switch to dummy BIST mode (BIST keep reset ++ * now) to keep the zero input data in I2S bus. ++ * ++ * It may cause the glitch if we hold the ADC ++ * digtital i2s module in codec. ++ * ++ * Then, the grp which is set from loopback_grp. ++ */ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(rk3308->loopback_grp), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_BIST_SINE); ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(rk3308->loopback_grp), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_BIST_SINE); ++ } else { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_NORMAL_LEFT); ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_NORMAL_RIGHT); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static void rk3308_codec_adc_mclk_disable(struct rk3308_codec_priv *rk3308) ++{ ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_ADC_MCLK_MSK, ++ RK3308_ADC_MCLK_DIS); ++} ++ ++static void rk3308_codec_adc_mclk_enable(struct rk3308_codec_priv *rk3308) ++{ ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_ADC_MCLK_MSK, ++ RK3308_ADC_MCLK_EN); ++ udelay(20); ++} ++ ++static void rk3308_codec_dac_mclk_disable(struct rk3308_codec_priv *rk3308) ++{ ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_DAC_MCLK_MSK, ++ RK3308_DAC_MCLK_DIS); ++} ++ ++static void rk3308_codec_dac_mclk_enable(struct rk3308_codec_priv *rk3308) ++{ ++ regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, ++ RK3308_DAC_MCLK_MSK, ++ RK3308_DAC_MCLK_EN); ++ udelay(20); ++} ++ ++static int rk3308_codec_open_dbg_capture(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_adc_ana_enable(rk3308, ADC_TYPE_DBG); ++ ++ return 0; ++} ++ ++static int rk3308_codec_close_dbg_capture(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_DBG); ++ ++ return 0; ++} ++ ++static int rk3308_codec_close_all_capture(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_ALL); ++ ++ return 0; ++} ++ ++static int rk3308_codec_close_capture(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_NORMAL); ++ ++ return 0; ++} ++ ++static int rk3308_codec_open_playback(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_dac_enable(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_codec_close_playback(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_dac_disable(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_codec_llp_down(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_adc_mclk_disable(rk3308); ++ rk3308_codec_dac_mclk_disable(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_codec_llp_up(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_adc_mclk_enable(rk3308); ++ rk3308_codec_dac_mclk_enable(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dlp_down(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_micbias_disable(rk3308); ++ rk3308_codec_power_off(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dlp_up(struct rk3308_codec_priv *rk3308) ++{ ++ rk3308_codec_power_on(rk3308); ++ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); ++ ++ return 0; ++} ++ ++/* Just used for debug and trace power state */ ++static void rk3308_codec_set_pm_state(struct rk3308_codec_priv *rk3308, ++ int pm_state) ++{ ++ int ret; ++ ++ switch (pm_state) { ++ case PM_LLP_DOWN: ++ rk3308_codec_llp_down(rk3308); ++ break; ++ case PM_LLP_UP: ++ rk3308_codec_llp_up(rk3308); ++ break; ++ case PM_DLP_DOWN: ++ rk3308_codec_dlp_down(rk3308); ++ break; ++ case PM_DLP_UP: ++ rk3308_codec_dlp_up(rk3308); ++ break; ++ case PM_DLP_DOWN2: ++ clk_disable_unprepare(rk3308->mclk_rx); ++ clk_disable_unprepare(rk3308->mclk_tx); ++ clk_disable_unprepare(rk3308->pclk); ++ break; ++ case PM_DLP_UP2: ++ ret = clk_prepare_enable(rk3308->pclk); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to enable acodec pclk: %d\n", ret); ++ goto err; ++ } ++ ++ ret = clk_prepare_enable(rk3308->mclk_rx); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to enable i2s mclk_rx: %d\n", ret); ++ goto err; ++ } ++ ++ ret = clk_prepare_enable(rk3308->mclk_tx); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to enable i2s mclk_tx: %d\n", ret); ++ goto err; ++ } ++ break; ++ default: ++ dev_err(rk3308->plat_dev, "Invalid pm_state: %d\n", pm_state); ++ goto err; ++ } ++ ++ rk3308->pm_state = pm_state; ++ ++err: ++ return; ++} ++ ++static void rk3308_codec_update_adcs_status(struct rk3308_codec_priv *rk3308, ++ int state) ++{ ++ int idx, grp; ++ ++ /* Update skip_grps flags if the ADCs need to be enabled always. */ ++ if (state == PATH_BUSY) { ++ for (idx = 0; idx < rk3308->used_adc_grps; idx++) { ++ u32 mapped_grp = to_mapped_grp(rk3308, idx); ++ ++ for (grp = 0; grp < rk3308->en_always_grps_num; grp++) { ++ u32 en_always_grp = rk3308->en_always_grps[grp]; ++ ++ if (mapped_grp == en_always_grp) ++ rk3308->skip_grps[en_always_grp] = 1; ++ } ++ } ++ } ++} ++ ++static int rk3308_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct snd_pcm_str *playback_str = ++ &substream->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]; ++ int type = ADC_TYPE_LOOPBACK; ++ int idx, grp; ++ int ret; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ /* DAC only supports 2 channels */ ++ rk3308_codec_dac_mclk_enable(rk3308); ++ rk3308_codec_open_playback(rk3308); ++ rk3308_codec_dac_dig_config(rk3308, params); ++ rk3308_codec_set_dac_path_state(rk3308, PATH_BUSY); ++ } else { ++ if (rk3308->micbias_num && ++ !rk3308->enable_micbias) ++ rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); ++ ++ rk3308_codec_adc_mclk_enable(rk3308); ++ ret = rk3308_codec_update_adc_grps(rk3308, params); ++ if (ret < 0) ++ return ret; ++ ++ if (handle_loopback(rk3308)) { ++ if (rk3308->micbias_num && ++ (params_channels(params) == 2) && ++ to_mapped_grp(rk3308, 0) == rk3308->loopback_grp) ++ rk3308_codec_micbias_disable(rk3308); ++ ++ /* Check the DACs are opened */ ++ if (playback_str->substream_opened) { ++ rk3308->loopback_dacs_enabled = true; ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_NORMAL_LEFT); ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_NORMAL_RIGHT); ++ } ++ } else { ++ rk3308->loopback_dacs_enabled = false; ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_BIST_SINE); ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_BIST_SINE); ++ } ++ } ++ } ++ ++ rk3308_codec_open_capture(rk3308); ++ rk3308_codec_adc_dig_config(rk3308, params); ++ rk3308_codec_update_adcs_status(rk3308, PATH_BUSY); ++ } ++ ++ return 0; ++} ++ ++static int rk3308_pcm_trigger(struct snd_pcm_substream *substream, ++ int cmd, struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ int type = ADC_TYPE_LOOPBACK; ++ int idx, grp; ++ ++ if (handle_loopback(rk3308) && ++ rk3308->dac_output == DAC_LINEOUT && ++ substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ if (cmd == SNDRV_PCM_TRIGGER_START) { ++ struct snd_pcm_str *capture_str = ++ &substream->pcm->streams[SNDRV_PCM_STREAM_CAPTURE]; ++ ++ if (capture_str->substream_opened) ++ queue_delayed_work(system_power_efficient_wq, ++ &rk3308->loopback_work, ++ msecs_to_jiffies(rk3308->delay_loopback_handle_ms)); ++ } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { ++ /* ++ * Switch to dummy bist mode to kick the glitch during disable ++ * ADCs and keep zero input data ++ */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_BIST_SINE); ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_BIST_SINE); ++ } ++ rk3308_codec_adc_ana_disable(rk3308, ADC_TYPE_LOOPBACK); ++ } ++ } ++ ++ return 0; ++} ++ ++static void rk3308_pcm_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ rk3308_codec_close_playback(rk3308); ++ rk3308_codec_dac_mclk_disable(rk3308); ++ regcache_cache_only(rk3308->regmap, false); ++ regcache_sync(rk3308->regmap); ++ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); ++ } else { ++ rk3308_codec_close_capture(rk3308); ++ if (!has_en_always_grps(rk3308)) { ++ rk3308_codec_adc_mclk_disable(rk3308); ++ rk3308_codec_update_adcs_status(rk3308, PATH_IDLE); ++ if (rk3308->micbias_num && ++ rk3308->enable_micbias) ++ rk3308_codec_micbias_disable(rk3308); ++ } ++ ++ regcache_cache_only(rk3308->regmap, false); ++ regcache_sync(rk3308->regmap); ++ } ++} ++ ++static struct snd_soc_dai_ops rk3308_dai_ops = { ++ .hw_params = rk3308_hw_params, ++ .set_fmt = rk3308_set_dai_fmt, ++ .mute_stream = rk3308_mute_stream, ++ .trigger = rk3308_pcm_trigger, ++ .shutdown = rk3308_pcm_shutdown, ++}; ++ ++static struct snd_soc_dai_driver rk3308_dai[] = { ++ { ++ .name = "rk3308-hifi", ++ .id = RK3308_HIFI, ++ .playback = { ++ .stream_name = "HiFi Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S20_3LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE), ++ }, ++ .capture = { ++ .stream_name = "HiFi Capture", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S20_3LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE), ++ }, ++ .ops = &rk3308_dai_ops, ++ }, ++}; ++ ++static int rk3308_suspend(struct snd_soc_component *component) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ if (rk3308->no_deep_low_power) ++ goto out; ++ ++ rk3308_codec_dlp_down(rk3308); ++ clk_disable_unprepare(rk3308->mclk_rx); ++ clk_disable_unprepare(rk3308->mclk_tx); ++ clk_disable_unprepare(rk3308->pclk); ++ ++out: ++ rk3308_set_bias_level(component, SND_SOC_BIAS_OFF); ++ return 0; ++} ++ ++static int rk3308_resume(struct snd_soc_component *component) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ int ret = 0; ++ ++ if (rk3308->no_deep_low_power) ++ goto out; ++ ++ ret = clk_prepare_enable(rk3308->pclk); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to enable acodec pclk: %d\n", ret); ++ goto out; ++ } ++ ++ ret = clk_prepare_enable(rk3308->mclk_rx); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to enable i2s mclk_rx: %d\n", ret); ++ goto out; ++ } ++ ++ ret = clk_prepare_enable(rk3308->mclk_tx); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to enable i2s mclk_tx: %d\n", ret); ++ goto out; ++ } ++ ++ rk3308_codec_dlp_up(rk3308); ++out: ++ rk3308_set_bias_level(component, SND_SOC_BIAS_STANDBY); ++ return ret; ++} ++ ++static int rk3308_codec_default_gains(struct rk3308_codec_priv *rk3308) ++{ ++ int grp; ++ ++ /* Prepare ADC gains */ ++ /* vendor step 12, set MIC PGA default gains */ ++ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON01(grp), ++ RK3308_ADC_CH1_MIC_GAIN_MSK | ++ RK3308_ADC_CH2_MIC_GAIN_MSK, ++ RK3308_ADC_CH1_MIC_GAIN_0DB | ++ RK3308_ADC_CH2_MIC_GAIN_0DB); ++ } ++ ++ /* vendor step 13, set ALC default gains */ ++ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON03(grp), ++ RK3308_ADC_CH1_ALC_GAIN_MSK, ++ RK3308_ADC_CH1_ALC_GAIN_0DB); ++ regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON04(grp), ++ RK3308_ADC_CH2_ALC_GAIN_MSK, ++ RK3308_ADC_CH2_ALC_GAIN_0DB); ++ } ++ ++ /* Prepare DAC gains */ ++ /* Step 15, set HPMIX default gains */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, ++ RK3308_DAC_L_HPMIX_GAIN_MSK | + RK3308_DAC_R_HPMIX_GAIN_MSK, + RK3308_DAC_L_HPMIX_GAIN_NDB_6 | + RK3308_DAC_R_HPMIX_GAIN_NDB_6); + +- /* recover DAC digital gain to 0 dB (reset value is 0xff, undocumented) */ +- if (rk3308->codec_ver == ACODEC_VERSION_C) +- regmap_write(rk3308->regmap, RK3308_DAC_DIG_CON04, +- RK3308BS_DAC_DIG_GAIN_0DB); ++ /* Step 18, set HPOUT default gains */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON05, ++ RK3308_DAC_L_HPOUT_GAIN_MSK, ++ RK3308_DAC_L_HPOUT_GAIN_NDB_39); ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON06, ++ RK3308_DAC_R_HPOUT_GAIN_MSK, ++ RK3308_DAC_R_HPOUT_GAIN_NDB_39); ++ ++ /* Using the same gain to HPOUT LR channels */ ++ rk3308->hpout_l_dgain = RK3308_DAC_L_HPOUT_GAIN_NDB_39; ++ ++ /* Step 19, set LINEOUT default gains */ ++ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON04, ++ RK3308_DAC_L_LINEOUT_GAIN_MSK | ++ RK3308_DAC_R_LINEOUT_GAIN_MSK, ++ RK3308_DAC_L_LINEOUT_GAIN_NDB_6 | ++ RK3308_DAC_R_LINEOUT_GAIN_NDB_6); ++ ++ return 0; ++} ++ ++static int rk3308_codec_setup_en_always_adcs(struct rk3308_codec_priv *rk3308, ++ struct device_node *np) ++{ ++ int num, ret; ++ ++ num = of_count_phandle_with_args(np, "rockchip,en-always-grps", NULL); ++ if (num < 0) { ++ if (num == -ENOENT) { ++ /* ++ * If there is note use 'rockchip,en-always-grps' ++ * property, return 0 is also right. ++ */ ++ ret = 0; ++ } else { ++ dev_err(rk3308->plat_dev, ++ "Failed to read 'rockchip,adc-grps-route' num: %d\n", ++ num); ++ ret = num; ++ } ++ ++ rk3308->en_always_grps_num = 0; ++ return ret; ++ } ++ ++ rk3308->en_always_grps_num = num; ++ ++ ret = of_property_read_u32_array(np, "rockchip,en-always-grps", ++ rk3308->en_always_grps, num); ++ if (ret < 0) { ++ dev_err(rk3308->plat_dev, ++ "Failed to read 'rockchip,en-always-grps': %d\n", ++ ret); ++ return ret; ++ } ++ ++ /* Clear all of skip_grps flags. */ ++ for (num = 0; num < ADC_LR_GROUP_MAX; num++) ++ rk3308->skip_grps[num] = 0; ++ ++ /* The loopback grp should not be enabled always. */ ++ for (num = 0; num < rk3308->en_always_grps_num; num++) { ++ if (rk3308->en_always_grps[num] == rk3308->loopback_grp) { ++ dev_err(rk3308->plat_dev, ++ "loopback_grp: %d should not be enabled always!\n", ++ rk3308->loopback_grp); ++ ret = -EINVAL; ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_dapm_mic_gains(struct rk3308_codec_priv *rk3308) ++{ ++ int ret; ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ ret = snd_soc_add_component_controls(rk3308->component, ++ mic_gains_b, ++ ARRAY_SIZE(mic_gains_b)); ++ if (ret) { ++ dev_err(rk3308->plat_dev, ++ "%s: add mic_gains_b failed: %d\n", ++ __func__, ret); ++ return ret; ++ } ++ } else { ++ ret = snd_soc_add_component_controls(rk3308->component, ++ mic_gains_a, ++ ARRAY_SIZE(mic_gains_a)); ++ if (ret) { ++ dev_err(rk3308->plat_dev, ++ "%s: add mic_gains_a failed: %d\n", ++ __func__, ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rk3308_codec_check_micbias(struct rk3308_codec_priv *rk3308, ++ struct device_node *np) ++{ ++ struct device *dev = (struct device *)rk3308->plat_dev; ++ int num = 0, ret; ++ ++ /* Check internal micbias */ ++ rk3308->micbias1 = ++ of_property_read_bool(np, "rockchip,micbias1"); ++ if (rk3308->micbias1) ++ num++; ++ ++ rk3308->micbias2 = ++ of_property_read_bool(np, "rockchip,micbias2"); ++ if (rk3308->micbias2) ++ num++; ++ ++ rk3308->micbias_volt = RK3308_ADC_MICBIAS_VOLT_0_85; /* by default */ ++ rk3308->micbias_num = num; ++ ++ /* Check external micbias */ ++ rk3308->ext_micbias = EXT_MICBIAS_NONE; ++ ++ rk3308->micbias_en_gpio = devm_gpiod_get_optional(dev, ++ "micbias-en", ++ GPIOD_IN); ++ if (!rk3308->micbias_en_gpio) { ++ dev_info(dev, "Don't need micbias-en gpio\n"); ++ } else if (IS_ERR(rk3308->micbias_en_gpio)) { ++ ret = PTR_ERR(rk3308->micbias_en_gpio); ++ dev_err(dev, "Unable to claim gpio micbias-en\n"); ++ return ret; ++ } else if (gpiod_get_value(rk3308->micbias_en_gpio)) { ++ rk3308->ext_micbias = EXT_MICBIAS_FUNC1; ++ } ++ ++ rk3308->vcc_micbias = devm_regulator_get_optional(dev, ++ "vmicbias"); ++ if (IS_ERR(rk3308->vcc_micbias)) { ++ if (PTR_ERR(rk3308->vcc_micbias) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "no vmicbias regulator found\n"); ++ } else { ++ ret = regulator_enable(rk3308->vcc_micbias); ++ if (ret) { ++ dev_err(dev, "Can't enable vmicbias: %d\n", ret); ++ return ret; ++ } ++ rk3308->ext_micbias = EXT_MICBIAS_FUNC2; ++ } ++ ++ dev_info(dev, "Check ext_micbias: %d\n", rk3308->ext_micbias); ++ ++ return 0; ++} ++ ++static int rk3308_codec_dapm_controls_prepare(struct rk3308_codec_priv *rk3308) ++{ ++ int grp; ++ ++ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { ++ rk3308->hpf_cutoff[grp] = 0; ++ rk3308->agc_l[grp] = 0; ++ rk3308->agc_r[grp] = 0; ++ rk3308->agc_asr_l[grp] = AGC_ASR_96KHZ; ++ rk3308->agc_asr_r[grp] = AGC_ASR_96KHZ; ++ } ++ ++ rk3308_codec_dapm_mic_gains(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308) ++{ ++ /* Clear registers for ADC and DAC */ ++ rk3308_codec_close_playback(rk3308); ++ rk3308_codec_close_all_capture(rk3308); ++ rk3308_codec_default_gains(rk3308); ++ rk3308_codec_llp_down(rk3308); ++ rk3308_codec_dapm_controls_prepare(rk3308); ++ ++ return 0; ++} ++ ++static int rk3308_probe(struct snd_soc_component *component) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ int ext_micbias; ++ ++ rk3308->component = component; ++ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); ++ ++ rk3308_codec_reset(component); ++ rk3308_codec_power_on(rk3308); ++ ++ /* From vendor recommend, disable micbias at first. */ ++ ext_micbias = rk3308->ext_micbias; ++ rk3308->ext_micbias = EXT_MICBIAS_NONE; ++ rk3308_codec_micbias_disable(rk3308); ++ rk3308->ext_micbias = ext_micbias; ++ ++ rk3308_codec_prepare(rk3308); ++ if (!rk3308->no_hp_det) ++ rk3308_codec_headset_detect_enable(rk3308); ++ ++ regcache_cache_only(rk3308->regmap, false); ++ regcache_sync(rk3308->regmap); ++ ++ return 0; ++} ++ ++static void rk3308_remove(struct snd_soc_component *component) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ rk3308_headphone_ctl(rk3308, 0); ++ rk3308_speaker_ctl(rk3308, 0); ++ if (!rk3308->no_hp_det) ++ rk3308_codec_headset_detect_disable(rk3308); ++ rk3308_codec_micbias_disable(rk3308); ++ rk3308_codec_power_off(rk3308); ++ ++ rk3308_codec_set_dac_path_state(rk3308, PATH_IDLE); ++ ++ regcache_cache_only(rk3308->regmap, false); ++ regcache_sync(rk3308->regmap); ++ ++ return; ++} ++ ++static const struct snd_soc_component_driver soc_codec_dev_rk3308_component = { ++ .probe = rk3308_probe, ++ .remove = rk3308_remove, ++ .resume = rk3308_resume, ++ .suspend = rk3308_suspend, ++ .set_bias_level = rk3308_set_bias_level, ++ .controls = rk3308_codec_dapm_controls, ++ .num_controls = ARRAY_SIZE(rk3308_codec_dapm_controls), ++ // .dapm_widgets = rk3308_dapm_widgets, ++ // .num_dapm_widgets = ARRAY_SIZE(rk3308_dapm_widgets), ++ // .dapm_routes = rk3308_dapm_routes, ++ // .num_dapm_routes = ARRAY_SIZE(rk3308_dapm_routes), ++ // .suspend_bias_off = 1, ++ // .idle_bias_on = 1, ++ // .use_pmdown_time = 1, ++ .endianness = 1, ++ .legacy_dai_naming = 1, ++}; ++ ++static const struct reg_default rk3308_codec_reg_defaults[] = { ++ { RK3308_GLB_CON, 0x07 }, ++}; ++ ++static bool rk3308_codec_write_read_reg(struct device *dev, unsigned int reg) ++{ ++ /* All registers can be read / write */ ++ return true; ++} ++ ++static bool rk3308_codec_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ return true; ++} ++ ++static void rk3308_codec_hpdetect_work(struct work_struct *work) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(work, struct rk3308_codec_priv, hpdet_work.work); ++ unsigned int val; ++ int need_poll = 0, need_irq = 0; ++ int need_report = 0, report_type = 0; ++ int dac_output = DAC_LINEOUT; ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ /* Check headphone plugged/unplugged directly. */ ++ regmap_read(rk3308->detect_grf, ++ DETECT_GRF_ACODEC_HPDET_STATUS, &val); ++ regmap_write(rk3308->detect_grf, ++ DETECT_GRF_ACODEC_HPDET_STATUS_CLR, val); ++ ++ if (rk3308->hp_jack_reversed) { ++ switch (val) { ++ case 0x0: ++ case 0x2: ++ dac_output = DAC_HPOUT; ++ report_type = SND_JACK_HEADPHONE; ++ break; ++ default: ++ break; ++ } ++ } else { ++ switch (val) { ++ case 0x1: ++ dac_output = DAC_HPOUT; ++ report_type = SND_JACK_HEADPHONE; ++ break; ++ default: ++ /* Includes val == 2 or others. */ ++ break; ++ } ++ } ++ ++ rk3308_codec_dac_switch(rk3308, dac_output); ++ if (rk3308->hpdet_jack) ++ snd_soc_jack_report(rk3308->hpdet_jack, ++ report_type, ++ SND_JACK_HEADPHONE); ++ ++ enable_irq(rk3308->irq); ++ ++ return; ++ } ++ ++ /* Check headphone unplugged via poll. */ ++ regmap_read(rk3308->regmap, RK3308_DAC_DIG_CON14, &val); ++ ++ if (rk3308->hp_jack_reversed) { ++ if (!val) { ++ rk3308->hp_plugged = true; ++ report_type = SND_JACK_HEADPHONE; ++ ++ need_report = 1; ++ need_irq = 1; ++ } else { ++ if (rk3308->hp_plugged) { ++ rk3308->hp_plugged = false; ++ need_report = 1; ++ } ++ need_poll = 1; ++ } ++ } else { ++ if (!val) { ++ rk3308->hp_plugged = false; ++ ++ need_report = 1; ++ need_irq = 1; ++ } else { ++ if (!rk3308->hp_plugged) { ++ rk3308->hp_plugged = true; ++ report_type = SND_JACK_HEADPHONE; ++ need_report = 1; ++ } ++ need_poll = 1; ++ } ++ } ++ ++ if (need_poll) ++ queue_delayed_work(system_power_efficient_wq, ++ &rk3308->hpdet_work, ++ msecs_to_jiffies(HPDET_POLL_MS)); ++ ++ if (need_report) { ++ if (report_type) ++ dac_output = DAC_HPOUT; ++ ++ rk3308_codec_dac_switch(rk3308, dac_output); ++ ++ if (rk3308->hpdet_jack) ++ snd_soc_jack_report(rk3308->hpdet_jack, ++ report_type, ++ SND_JACK_HEADPHONE); ++ } ++ ++ if (need_irq) ++ enable_irq(rk3308->irq); ++} ++ ++static void rk3308_codec_loopback_work(struct work_struct *work) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(work, struct rk3308_codec_priv, loopback_work.work); ++ int type = ADC_TYPE_LOOPBACK; ++ int idx, grp; ++ ++ /* Prepare loopback ADCs */ ++ rk3308_codec_adc_ana_enable(rk3308, type); ++ ++ /* Waiting ADCs are stable */ ++ msleep(ADC_STABLE_MS); ++ ++ /* Recover normal mode after enable ADCs */ ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) { ++ if (grp < 0 || grp > ADC_LR_GROUP_MAX - 1) ++ continue; ++ ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_L_CH_BIST_MSK, ++ RK3308_ADC_L_CH_NORMAL_LEFT); ++ regmap_update_bits(rk3308->regmap, ++ RK3308_ADC_DIG_CON03(grp), ++ RK3308_ADC_R_CH_BIST_MSK, ++ RK3308_ADC_R_CH_NORMAL_RIGHT); ++ } ++} ++ ++static irqreturn_t rk3308_codec_hpdet_isr(int irq, void *data) ++{ ++ struct rk3308_codec_priv *rk3308 = data; ++ ++ /* ++ * For the high level irq trigger, disable irq and avoid a lot of ++ * repeated irq handlers entry. ++ */ ++ disable_irq_nosync(rk3308->irq); ++ queue_delayed_work(system_power_efficient_wq, ++ &rk3308->hpdet_work, msecs_to_jiffies(10)); ++ ++ return IRQ_HANDLED; ++} ++ ++void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_component *component, ++ struct snd_soc_jack *hpdet_jack); ++EXPORT_SYMBOL_GPL(rk3308_codec_set_jack_detect_cb); ++ ++static void rk3308_codec_set_jack_detect(struct snd_soc_component *component, ++ struct snd_soc_jack *hpdet_jack) ++{ ++ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ ++ rk3308->hpdet_jack = hpdet_jack; ++ ++ /* To detect jack once during startup */ ++ disable_irq_nosync(rk3308->irq); ++ queue_delayed_work(system_power_efficient_wq, ++ &rk3308->hpdet_work, msecs_to_jiffies(10)); ++ ++ dev_info(rk3308->plat_dev, "%s: Request detect hp jack once\n", ++ __func__); ++} ++ ++static const struct regmap_config rk3308_codec_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = RK3308_DAC_ANA_CON15, ++ .writeable_reg = rk3308_codec_write_read_reg, ++ .readable_reg = rk3308_codec_write_read_reg, ++ .volatile_reg = rk3308_codec_volatile_reg, ++ .reg_defaults = rk3308_codec_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(rk3308_codec_reg_defaults), ++ .cache_type = REGCACHE_FLAT, ++}; ++ ++static ssize_t pm_state_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ ++ return sprintf(buf, "pm_state: %d\n", rk3308->pm_state); ++} + +- /* +- * Unconditionally enable zero-cross detection (needed for AGC, +- * harmless without AGC) +- */ +- for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) +- regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), +- RK3308_ADC_CH1_ZEROCROSS_DET_EN | +- RK3308_ADC_CH2_ZEROCROSS_DET_EN); ++static ssize_t pm_state_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ unsigned long pm_state; ++ int ret = kstrtoul(buf, 10, &pm_state); + +- return 0; ++ if (ret < 0) { ++ dev_err(dev, "Invalid pm_state: %ld, ret: %d\n", ++ pm_state, ret); ++ return -EINVAL; ++ } ++ ++ rk3308_codec_set_pm_state(rk3308, pm_state); ++ ++ dev_info(dev, "Store pm_state: %d\n", rk3308->pm_state); ++ ++ return count; + } + +-static int rk3308_codec_probe(struct snd_soc_component *component) ++static ssize_t adc_grps_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) + { +- struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ u32 grp; ++ int type = ADC_TYPE_NORMAL, count = 0; ++ int idx; + +- rk3308->component = component; ++ count += sprintf(buf + count, "current used adc_grps:\n"); ++ count += sprintf(buf + count, "- normal:"); ++ for (idx = 0; adc_for_each_grp(rk3308, type, idx, &grp); idx++) ++ count += sprintf(buf + count, " %d", grp); ++ count += sprintf(buf + count, "\n"); ++ count += sprintf(buf + count, "- loopback: %d\n", ++ rk3308->loopback_grp); + +- rk3308_codec_reset(component); +- rk3308_codec_initialize(rk3308); ++ return count; ++} + +- return 0; ++static ssize_t adc_grps_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ char adc_type; ++ int grps, ret; ++ ++ ret = sscanf(buf, "%c,%d", &adc_type, &grps); ++ if (ret != 2) { ++ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } ++ ++ if (adc_type == 'n') ++ rk3308->used_adc_grps = grps; ++ else if (adc_type == 'l') ++ rk3308->loopback_grp = grps; ++ ++ return count; + } + +-static int rk3308_codec_set_bias_level(struct snd_soc_component *component, +- enum snd_soc_bias_level level) ++static ssize_t adc_grps_route_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) + { +- struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ char which_i2s[32] = {0}; ++ int count = 0; ++ u32 grp; + +- switch (level) { +- case SND_SOC_BIAS_ON: ++ switch (rk3308->which_i2s) { ++ case ACODEC_TO_I2S1_2CH: ++ strcpy(which_i2s, "i2s1_2ch"); + break; +- case SND_SOC_BIAS_PREPARE: ++ case ACODEC_TO_I2S3_4CH: ++ strcpy(which_i2s, "i2s3_4ch"); + break; +- case SND_SOC_BIAS_STANDBY: +- if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_OFF) +- break; ++ default: ++ strcpy(which_i2s, "i2s2_8ch"); ++ break; ++ } + +- /* Sequence from TRM Section 8.6.3 "Power Up" */ +- regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, +- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); +- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), +- RK3308_ADC_CURRENT_CHARGE_MSK, 1); +- regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), +- RK3308_ADC_REF_EN); +- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), +- RK3308_ADC_CURRENT_CHARGE_MSK, 0x7f); +- msleep(20); /* estimated value */ ++ count += sprintf(buf + count, "%s from acodec route mapping:\n", ++ which_i2s); ++ for (grp = 0; grp < rk3308->to_i2s_grps; grp++) { ++ count += sprintf(buf + count, "* sdi_%d <-- sdo_%d\n", ++ grp, rk3308->i2s_sdis[grp]); ++ } ++ ++ return count; ++} ++ ++static ssize_t adc_grps_route_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ int which_i2s, idx, i2s_sdis[ADC_LR_GROUP_MAX]; ++ int ret; ++ ++ ret = sscanf(buf, "%d,%d,%d,%d,%d", &which_i2s, ++ &i2s_sdis[0], &i2s_sdis[1], &i2s_sdis[2], &i2s_sdis[3]); ++ if (ret != 5) { ++ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", ++ __func__, ret); ++ goto err; ++ } ++ ++ if (which_i2s < ACODEC_TO_I2S2_8CH || ++ which_i2s > ACODEC_TO_I2S1_2CH) { ++ dev_err(rk3308->plat_dev, "Invalid i2s type: %d\n", which_i2s); ++ goto err; ++ } ++ ++ rk3308->which_i2s = which_i2s; ++ ++ switch (rk3308->which_i2s) { ++ case ACODEC_TO_I2S1_2CH: ++ rk3308->to_i2s_grps = 1; + break; +- case SND_SOC_BIAS_OFF: +- /* Sequence from TRM Section 8.6.4 "Power Down" */ +- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), +- RK3308_ADC_CURRENT_CHARGE_MSK, 1); +- regmap_clear_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), +- RK3308_ADC_REF_EN); +- regmap_clear_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, +- RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); +- msleep(20); /* estimated value */ ++ case ACODEC_TO_I2S3_4CH: ++ rk3308->to_i2s_grps = 2; ++ break; ++ default: ++ rk3308->to_i2s_grps = 4; + break; + } +- return 0; ++ ++ for (idx = 0; idx < rk3308->to_i2s_grps; idx++) ++ rk3308->i2s_sdis[idx] = i2s_sdis[idx]; ++ ++ rk3308_codec_adc_grps_route_config(rk3308); ++ ++err: ++ return count; + } + +-static const struct snd_soc_component_driver rk3308_codec_component_driver = { +- .probe = rk3308_codec_probe, +- .set_bias_level = rk3308_codec_set_bias_level, +- .controls = rk3308_codec_controls, +- .num_controls = ARRAY_SIZE(rk3308_codec_controls), +- .dapm_widgets = rk3308_codec_dapm_widgets, +- .num_dapm_widgets = ARRAY_SIZE(rk3308_codec_dapm_widgets), +- .dapm_routes = rk3308_codec_dapm_routes, +- .num_dapm_routes = ARRAY_SIZE(rk3308_codec_dapm_routes), +-}; ++static ssize_t adc_grp0_in_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); + +-static const struct regmap_config rk3308_codec_regmap_config = { +- .reg_bits = 32, +- .reg_stride = 4, +- .val_bits = 32, +- .max_register = RK3308_DAC_ANA_CON15, +-}; ++ return sprintf(buf, "adc ch0 using: %s\n", ++ rk3308->adc_grp0_using_linein ? "line in" : "mic in"); ++} + +-static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) ++static ssize_t adc_grp0_in_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) + { +- unsigned int chip_id; +- int err; ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ unsigned long using_linein; ++ int ret = kstrtoul(buf, 10, &using_linein); + +- err = regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id); +- if (err) +- return err; ++ if (ret < 0 || using_linein > 1) { ++ dev_err(dev, "Invalid input status: %ld, ret: %d\n", ++ using_linein, ret); ++ return -EINVAL; ++ } + +- switch (chip_id) { +- case 3306: +- rk3308->codec_ver = ACODEC_VERSION_A; ++ rk3308->adc_grp0_using_linein = using_linein; ++ ++ dev_info(dev, "store using_linein: %d\n", ++ rk3308->adc_grp0_using_linein); ++ ++ return count; ++} ++ ++static ssize_t adc_zerocross_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ ++ return sprintf(buf, "adc zerocross: %s\n", ++ rk3308->adc_zerocross ? "enabled" : "disabled"); ++} ++ ++static ssize_t adc_zerocross_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ unsigned long zerocross; ++ int ret = kstrtoul(buf, 10, &zerocross); ++ ++ if (ret < 0 || zerocross > 1) { ++ dev_err(dev, "Invalid zerocross: %ld, ret: %d\n", ++ zerocross, ret); ++ return -EINVAL; ++ } ++ ++ rk3308->adc_zerocross = zerocross; ++ ++ dev_info(dev, "store adc zerocross: %d\n", rk3308->adc_zerocross); ++ ++ return count; ++} ++ ++static ssize_t adc_grps_endisable_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ int count = 0, i; ++ ++ count += sprintf(buf + count, "enabled adc grps:"); ++ for (i = 0; i < ADC_LR_GROUP_MAX; i++) ++ count += sprintf(buf + count, "%d ", ++ rk3308->adc_grps_endisable[i]); ++ ++ count += sprintf(buf + count, "\n"); ++ return count; ++} ++ ++static ssize_t adc_grps_endisable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ int grp, endisable, ret; ++ ++ ret = sscanf(buf, "%d,%d", &grp, &endisable); ++ if (ret != 2) { ++ dev_err(rk3308->plat_dev, "%s sscanf failed: %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } ++ ++ rk3308->cur_dbg_grp = grp; ++ ++ if (endisable) ++ rk3308_codec_open_dbg_capture(rk3308); ++ else ++ rk3308_codec_close_dbg_capture(rk3308); ++ ++ dev_info(dev, "ADC grp %d endisable: %d\n", grp, endisable); ++ ++ return count; ++} ++ ++static ssize_t dac_endisable_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ ++ return sprintf(buf, "%d\n", rk3308->dac_endisable); ++} ++ ++static ssize_t dac_endisable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ unsigned long endisable; ++ int ret = kstrtoul(buf, 10, &endisable); ++ ++ if (ret < 0) { ++ dev_err(dev, "Invalid endisable: %ld, ret: %d\n", ++ endisable, ret); ++ return -EINVAL; ++ } ++ ++ if (endisable) ++ rk3308_codec_open_playback(rk3308); ++ else ++ rk3308_codec_close_playback(rk3308); ++ ++ dev_info(dev, "DAC endisable: %ld\n", endisable); ++ ++ return count; ++} ++ ++static ssize_t dac_output_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ ssize_t ret = 0; ++ ++ switch (rk3308->dac_output) { ++ case DAC_LINEOUT: ++ ret = sprintf(buf, "dac path: %s\n", "line out"); + break; +- case 0x3308: +- rk3308->codec_ver = ACODEC_VERSION_B; +- return dev_err_probe(rk3308->dev, -EINVAL, "Chip version B not supported\n"); +- case 0x3308c: +- rk3308->codec_ver = ACODEC_VERSION_C; ++ case DAC_HPOUT: ++ ret = sprintf(buf, "dac path: %s\n", "hp out"); ++ break; ++ case DAC_LINEOUT_HPOUT: ++ ret = sprintf(buf, "dac path: %s\n", ++ "both line out and hp out"); + break; + default: +- return dev_err_probe(rk3308->dev, -EINVAL, "Unknown chip_id: 0x%x\n", chip_id); ++ pr_err("Invalid dac path: %d ?\n", rk3308->dac_output); ++ break; ++ } ++ ++ return ret; ++} ++ ++static ssize_t dac_output_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ unsigned long dac_output; ++ int ret = kstrtoul(buf, 10, &dac_output); ++ ++ if (ret < 0) { ++ dev_err(dev, "Invalid input status: %ld, ret: %d\n", ++ dac_output, ret); ++ return -EINVAL; ++ } ++ ++ rk3308_codec_dac_switch(rk3308, dac_output); ++ ++ dev_info(dev, "Store dac_output: %d\n", rk3308->dac_output); ++ ++ return count; ++} ++ ++static ssize_t enable_all_adcs_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ ++ return sprintf(buf, "%d\n", rk3308->enable_all_adcs); ++} ++ ++static ssize_t enable_all_adcs_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ container_of(dev, struct rk3308_codec_priv, dev); ++ unsigned long enable; ++ int ret = kstrtoul(buf, 10, &enable); ++ ++ if (ret < 0) { ++ dev_err(dev, "Invalid enable value: %ld, ret: %d\n", ++ enable, ret); ++ return -EINVAL; ++ } ++ ++ rk3308->enable_all_adcs = enable; ++ ++ return count; ++} ++ ++static const struct device_attribute acodec_attrs[] = { ++ __ATTR_RW(adc_grps), ++ __ATTR_RW(adc_grps_endisable), ++ __ATTR_RW(adc_grps_route), ++ __ATTR_RW(adc_grp0_in), ++ __ATTR_RW(adc_zerocross), ++ __ATTR_RW(dac_endisable), ++ __ATTR_RW(dac_output), ++ __ATTR_RW(enable_all_adcs), ++ __ATTR_RW(pm_state), ++}; ++ ++static void rk3308_codec_device_release(struct device *dev) ++{ ++ /* Do nothing */ ++} ++ ++static int rk3308_codec_sysfs_init(struct platform_device *pdev, ++ struct rk3308_codec_priv *rk3308) ++{ ++ struct device *dev = &rk3308->dev; ++ int i; ++ ++ dev->release = rk3308_codec_device_release; ++ dev->parent = &pdev->dev; ++ set_dev_node(dev, dev_to_node(&pdev->dev)); ++ dev_set_name(dev, "rk3308-acodec-dev"); ++ ++ if (device_register(dev)) { ++ dev_err(&pdev->dev, ++ "Register 'rk3308-acodec-dev' failed\n"); ++ dev->parent = NULL; ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++) { ++ if (device_create_file(dev, &acodec_attrs[i])) { ++ dev_err(&pdev->dev, ++ "Create 'rk3308-acodec-dev' attr failed\n"); ++ device_unregister(dev); ++ return -ENOMEM; ++ } + } + +- dev_info(rk3308->dev, "Found codec version %c\n", rk3308->codec_ver); + return 0; + } + +-static int rk3308_codec_set_micbias_level(struct rk3308_codec_priv *rk3308) ++#if defined(CONFIG_DEBUG_FS) ++static int rk3308_codec_debugfs_reg_show(struct seq_file *s, void *v) + { +- struct device_node *np = rk3308->dev->of_node; +- u32 percent; +- u32 mult; +- int err; ++ struct rk3308_codec_priv *rk3308 = s->private; ++ unsigned int i; ++ unsigned int val; + +- err = of_property_read_u32(np, "rockchip,micbias-avdd-percent", &percent); +- if (err == -EINVAL) +- return 0; +- if (err) +- return dev_err_probe(rk3308->dev, err, +- "Error reading 'rockchip,micbias-avdd-percent'\n"); ++ for (i = RK3308_GLB_CON; i <= RK3308_DAC_ANA_CON13; i += 4) { ++ regmap_read(rk3308->regmap, i, &val); ++ if (!(i % 16)) ++ seq_printf(s, "\nR:%04x: ", i); ++ seq_printf(s, "%08x ", val); ++ } + +- /* Convert percent to register value, linerarly (50% -> 0, 5% step = +1) */ +- mult = (percent - 50) / 5; ++ seq_puts(s, "\n"); + +- /* Check range and that the percent was an exact value allowed */ +- if (mult > RK3308_ADC_LEVEL_RANGE_MICBIAS_MAX || mult * 5 + 50 != percent) +- return dev_err_probe(rk3308->dev, -EINVAL, +- "Invalid value %u for 'rockchip,micbias-avdd-percent'\n", +- percent); ++ return 0; ++} + +- regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), +- RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, +- mult << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT); ++static ssize_t rk3308_codec_debugfs_reg_operate(struct file *file, ++ const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ ((struct seq_file *)file->private_data)->private; ++ unsigned int reg, val; ++ char op; ++ char kbuf[32]; ++ int ret; + ++ if (count >= sizeof(kbuf)) ++ return -EINVAL; ++ ++ if (copy_from_user(kbuf, buf, count)) ++ return -EFAULT; ++ kbuf[count] = '\0'; ++ ++ ret = sscanf(kbuf, "%c,%x,%x", &op, ®, &val); ++ if (ret != 3) { ++ pr_err("sscanf failed: %d\n", ret); ++ return -EFAULT; ++ } ++ ++ if (op == 'w') { ++ pr_info("Write reg: 0x%04x with val: 0x%08x\n", reg, val); ++ regmap_write(rk3308->regmap, reg, val); ++ regcache_cache_only(rk3308->regmap, false); ++ regcache_sync(rk3308->regmap); ++ pr_info("Read back reg: 0x%04x with val: 0x%08x\n", reg, val); ++ } else if (op == 'r') { ++ regmap_read(rk3308->regmap, reg, &val); ++ pr_info("Read reg: 0x%04x with val: 0x%08x\n", reg, val); ++ } else { ++ pr_err("This is an invalid operation: %c\n", op); ++ } ++ ++ return count; ++} ++ ++static int rk3308_codec_debugfs_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ++ rk3308_codec_debugfs_reg_show, inode->i_private); ++} ++ ++static const struct file_operations rk3308_codec_reg_debugfs_fops = { ++ .owner = THIS_MODULE, ++ .open = rk3308_codec_debugfs_open, ++ .read = seq_read, ++ .write = rk3308_codec_debugfs_reg_operate, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif /* CONFIG_DEBUG_FS */ ++ ++static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) ++{ ++ unsigned int chip_id; ++ ++ regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id); ++ switch (chip_id) { ++ case 3306: ++ rk3308->codec_ver = ACODEC_VERSION_A; ++ break; ++ case 0x3308: ++ rk3308->codec_ver = ACODEC_VERSION_B; ++ break; ++ default: ++ pr_err("Unknown chip_id: %d / 0x%x\n", chip_id, chip_id); ++ return -EFAULT; ++ } ++ ++ pr_info("The acodec version is: %x\n", rk3308->codec_ver); + return 0; + } + +-static int rk3308_codec_platform_probe(struct platform_device *pdev) ++static int rk3308_platform_probe(struct platform_device *pdev) + { + struct device_node *np = pdev->dev.of_node; +- struct device *dev = &pdev->dev; + struct rk3308_codec_priv *rk3308; ++ struct resource *res; + void __iomem *base; +- int err; ++ int ret; + + rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); + if (!rk3308) + return -ENOMEM; + +- rk3308->dev = dev; +- + rk3308->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); +- if (IS_ERR(rk3308->grf)) +- return dev_err_probe(dev, PTR_ERR(rk3308->grf), "Error getting GRF\n"); ++ if (IS_ERR(rk3308->grf)) { ++ dev_err(&pdev->dev, ++ "Missing 'rockchip,grf' property\n"); ++ return PTR_ERR(rk3308->grf); ++ } ++ ++ ret = rk3308_codec_sysfs_init(pdev, rk3308); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Sysfs init failed\n"); ++ return ret; ++ } + +- rk3308->reset = devm_reset_control_get_optional_exclusive(dev, "codec"); +- if (IS_ERR(rk3308->reset)) +- return dev_err_probe(dev, PTR_ERR(rk3308->reset), "Failed to get reset control\n"); ++#if defined(CONFIG_DEBUG_FS) ++ rk3308->dbg_codec = debugfs_create_dir(CODEC_DRV_NAME, NULL); ++ if (IS_ERR(rk3308->dbg_codec)) ++ dev_err(&pdev->dev, ++ "Failed to create debugfs dir for rk3308!\n"); ++ else ++ debugfs_create_file("reg", 0644, rk3308->dbg_codec, ++ rk3308, &rk3308_codec_reg_debugfs_fops); ++#endif ++ rk3308->plat_dev = &pdev->dev; + +- err = devm_clk_bulk_get(dev, ARRAY_SIZE(rk3308_codec_clocks), rk3308_codec_clocks); +- if (err) +- return dev_err_probe(dev, err, "Failed to get clocks\n"); ++ rk3308->reset = devm_reset_control_get(&pdev->dev, "acodec-reset"); ++ if (IS_ERR(rk3308->reset)) { ++ ret = PTR_ERR(rk3308->reset); ++ if (ret != -ENOENT) ++ return ret; + +- err = clk_bulk_prepare_enable(ARRAY_SIZE(rk3308_codec_clocks), rk3308_codec_clocks); +- if (err) +- return dev_err_probe(dev, err, "Failed to enable clocks\n"); ++ dev_dbg(&pdev->dev, "No reset control found\n"); ++ rk3308->reset = NULL; ++ } ++ ++ rk3308->hp_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "hp-ctl", ++ GPIOD_OUT_LOW); ++ if (!rk3308->hp_ctl_gpio) { ++ dev_info(&pdev->dev, "Don't need hp-ctl gpio\n"); ++ } else if (IS_ERR(rk3308->hp_ctl_gpio)) { ++ ret = PTR_ERR(rk3308->hp_ctl_gpio); ++ dev_err(&pdev->dev, "Unable to claim gpio hp-ctl\n"); ++ return ret; ++ } ++ ++ rk3308->spk_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "spk-ctl", ++ GPIOD_OUT_LOW); ++ ++ if (!rk3308->spk_ctl_gpio) { ++ dev_info(&pdev->dev, "Don't need spk-ctl gpio\n"); ++ } else if (IS_ERR(rk3308->spk_ctl_gpio)) { ++ ret = PTR_ERR(rk3308->spk_ctl_gpio); ++ dev_err(&pdev->dev, "Unable to claim gpio spk-ctl\n"); ++ return ret; ++ } ++ ++ rk3308->pa_drv_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-drv", ++ GPIOD_OUT_LOW); ++ ++ if (!rk3308->pa_drv_gpio) { ++ dev_info(&pdev->dev, "Don't need pa-drv gpio\n"); ++ } else if (IS_ERR(rk3308->pa_drv_gpio)) { ++ ret = PTR_ERR(rk3308->pa_drv_gpio); ++ dev_err(&pdev->dev, "Unable to claim gpio pa-drv\n"); ++ return ret; ++ } ++ ++ if (rk3308->pa_drv_gpio) { ++ rk3308->delay_pa_drv_ms = PA_DRV_MS; ++ ret = of_property_read_u32(np, "rockchip,delay-pa-drv-ms", ++ &rk3308->delay_pa_drv_ms); ++ } ++ ++#if DEBUG_POP_ALWAYS ++ dev_info(&pdev->dev, "Enable all ctl gpios always for debugging pop\n"); ++ rk3308_headphone_ctl(rk3308, 1); ++ rk3308_speaker_ctl(rk3308, 1); ++#else ++ dev_info(&pdev->dev, "De-pop as much as possible\n"); ++ rk3308_headphone_ctl(rk3308, 0); ++ rk3308_speaker_ctl(rk3308, 0); ++#endif ++ ++ rk3308->pclk = devm_clk_get(&pdev->dev, "acodec"); ++ if (IS_ERR(rk3308->pclk)) { ++ dev_err(&pdev->dev, "Can't get acodec pclk\n"); ++ return PTR_ERR(rk3308->pclk); ++ } ++ ++ rk3308->mclk_rx = devm_clk_get(&pdev->dev, "mclk_rx"); ++ if (IS_ERR(rk3308->mclk_rx)) { ++ dev_err(&pdev->dev, "Can't get acodec mclk_rx\n"); ++ return PTR_ERR(rk3308->mclk_rx); ++ } ++ ++ rk3308->mclk_tx = devm_clk_get(&pdev->dev, "mclk_tx"); ++ if (IS_ERR(rk3308->mclk_tx)) { ++ dev_err(&pdev->dev, "Can't get acodec mclk_tx\n"); ++ return PTR_ERR(rk3308->mclk_tx); ++ } ++ ++ ret = clk_prepare_enable(rk3308->pclk); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(rk3308->mclk_rx); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to enable i2s mclk_rx: %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(rk3308->mclk_tx); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to enable i2s mclk_tx: %d\n", ret); ++ return ret; ++ } ++ ++ rk3308_codec_check_micbias(rk3308, np); ++ ++ rk3308->enable_all_adcs = ++ of_property_read_bool(np, "rockchip,enable-all-adcs"); ++ ++ rk3308->hp_jack_reversed = ++ of_property_read_bool(np, "rockchip,hp-jack-reversed"); ++ ++ rk3308->no_deep_low_power = ++ of_property_read_bool(np, "rockchip,no-deep-low-power"); ++ ++ rk3308->no_hp_det = ++ of_property_read_bool(np, "rockchip,no-hp-det"); ++ ++ rk3308->delay_loopback_handle_ms = LOOPBACK_HANDLE_MS; ++ ret = of_property_read_u32(np, "rockchip,delay-loopback-handle-ms", ++ &rk3308->delay_loopback_handle_ms); ++ ++ rk3308->delay_start_play_ms = 0; ++ ret = of_property_read_u32(np, "rockchip,delay-start-play-ms", ++ &rk3308->delay_start_play_ms); ++ ++ rk3308->loopback_grp = NOT_USED; ++ ret = of_property_read_u32(np, "rockchip,loopback-grp", ++ &rk3308->loopback_grp); ++ /* ++ * If there is no loopback on some board, the -EINVAL indicates that ++ * we don't need add the node, and it is not an error. ++ */ ++ if (ret < 0 && ret != -EINVAL) { ++ dev_err(&pdev->dev, "Failed to read loopback property: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = rk3308_codec_adc_grps_route(rk3308, np); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to route ADC groups: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = rk3308_codec_setup_en_always_adcs(rk3308, np); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to setup enabled always ADCs: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = rk3308_codec_get_version(rk3308); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to get acodec version: %d\n", ++ ret); ++ return ret; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) { ++ ret = PTR_ERR(base); ++ dev_err(&pdev->dev, "Failed to ioremap resource\n"); ++ goto failed; ++ } ++ ++ rk3308->regmap = devm_regmap_init_mmio(&pdev->dev, base, ++ &rk3308_codec_regmap_config); ++ if (IS_ERR(rk3308->regmap)) { ++ ret = PTR_ERR(rk3308->regmap); ++ dev_err(&pdev->dev, "Failed to regmap mmio\n"); ++ goto failed; ++ } ++ ++ if (!rk3308->no_hp_det) { ++ int index = 0; ++ ++ if (rk3308->codec_ver == ACODEC_VERSION_B) ++ index = 1; ++ ++ rk3308->irq = platform_get_irq(pdev, index); ++ if (rk3308->irq < 0) { ++ dev_err(&pdev->dev, "Can not get codec irq\n"); ++ goto failed; ++ } ++ ++ INIT_DELAYED_WORK(&rk3308->hpdet_work, rk3308_codec_hpdetect_work); ++ ++ ret = devm_request_irq(&pdev->dev, rk3308->irq, ++ rk3308_codec_hpdet_isr, ++ 0, ++ "acodec-hpdet", ++ rk3308); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret); ++ goto failed; ++ } + +- err = rk3308_codec_get_version(rk3308); +- if (err) +- return err; ++ if (rk3308->codec_ver == ACODEC_VERSION_B) { ++ rk3308->detect_grf = ++ syscon_regmap_lookup_by_phandle(np, "rockchip,detect-grf"); ++ if (IS_ERR(rk3308->detect_grf)) { ++ dev_err(&pdev->dev, ++ "Missing 'rockchip,detect-grf' property\n"); ++ return PTR_ERR(rk3308->detect_grf); ++ } ++ ++ /* Configure filter count and enable hpdet irq. */ ++ regmap_write(rk3308->detect_grf, ++ DETECT_GRF_ACODEC_HPDET_COUNTER, ++ DEFAULT_HPDET_COUNT); ++ regmap_write(rk3308->detect_grf, ++ DETECT_GRF_ACODEC_HPDET_CON, ++ (HPDET_BOTH_NEG_POS << 16) | ++ HPDET_BOTH_NEG_POS); ++ } ++ ++ rk3308_codec_set_jack_detect_cb = rk3308_codec_set_jack_detect; ++ } + +- base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(base)) +- return PTR_ERR(base); ++ if (rk3308->codec_ver == ACODEC_VERSION_A) ++ INIT_DELAYED_WORK(&rk3308->loopback_work, ++ rk3308_codec_loopback_work); + +- rk3308->regmap = devm_regmap_init_mmio(dev, base, &rk3308_codec_regmap_config); +- if (IS_ERR(rk3308->regmap)) +- return dev_err_probe(dev, PTR_ERR(rk3308->regmap), +- "Failed to init regmap\n"); ++ rk3308->adc_grp0_using_linein = ADC_GRP0_MICIN; ++ rk3308->dac_output = DAC_LINEOUT; ++ rk3308->adc_zerocross = 1; ++ rk3308->pm_state = PM_NORMAL; + + platform_set_drvdata(pdev, rk3308); + +- err = rk3308_codec_set_micbias_level(rk3308); +- if (err) +- return err; ++ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3308_component, ++ rk3308_dai, ARRAY_SIZE(rk3308_dai)); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Failed to register component: %d\n", ret); ++ goto failed; ++ } + +- err = devm_snd_soc_register_component(dev, &rk3308_codec_component_driver, +- &rk3308_codec_dai_driver, 1); +- if (err) +- return dev_err_probe(dev, err, "Failed to register codec\n"); ++ return ret; + +- return 0; ++failed: ++ clk_disable_unprepare(rk3308->mclk_rx); ++ clk_disable_unprepare(rk3308->mclk_tx); ++ clk_disable_unprepare(rk3308->pclk); ++ device_unregister(&rk3308->dev); ++ ++ return ret; ++} ++ ++static void rk3308_platform_remove(struct platform_device *pdev) ++{ ++ struct rk3308_codec_priv *rk3308 = ++ (struct rk3308_codec_priv *)platform_get_drvdata(pdev); ++ ++ clk_disable_unprepare(rk3308->mclk_rx); ++ clk_disable_unprepare(rk3308->mclk_tx); ++ clk_disable_unprepare(rk3308->pclk); ++ device_unregister(&rk3308->dev); ++ ++ return; + } + +-static const struct of_device_id __maybe_unused rk3308_codec_of_match[] = { ++static const struct of_device_id rk3308codec_of_match[] = { + { .compatible = "rockchip,rk3308-codec", }, + {}, + }; +-MODULE_DEVICE_TABLE(of, rk3308_codec_of_match); ++MODULE_DEVICE_TABLE(of, rk3308codec_of_match); + + static struct platform_driver rk3308_codec_driver = { + .driver = { +- .name = "rk3308-acodec", +- .of_match_table = rk3308_codec_of_match, ++ .name = CODEC_DRV_NAME, ++ .of_match_table = of_match_ptr(rk3308codec_of_match), + }, +- .probe = rk3308_codec_platform_probe, ++ .probe = rk3308_platform_probe, ++ .remove = rk3308_platform_remove, + }; + module_platform_driver(rk3308_codec_driver); + + MODULE_AUTHOR("Xing Zheng "); +-MODULE_AUTHOR("Luca Ceresoli "); + MODULE_DESCRIPTION("ASoC RK3308 Codec Driver"); +-MODULE_LICENSE("GPL"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h +index a4226b235ab7..93e089dae081 100644 +--- a/sound/soc/codecs/rk3308_codec.h ++++ b/sound/soc/codecs/rk3308_codec.h +@@ -1,15 +1,114 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Rockchip RK3308 internal audio codec driver -- register definitions ++ * rk3308_codec.h -- RK3308 ALSA Soc Audio Driver + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. +- * Copyright (c) 2022, Vivax-Metrotech Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * + */ + + #ifndef __RK3308_CODEC_H__ + #define __RK3308_CODEC_H__ + +-#define RK3308_GLB_CON 0x00 ++#define ACODEC_RESET_CTL 0x00 /* REG 0x00 */ ++ ++/* ADC DIGITAL REGISTERS */ ++#define ACODEC_ADC_I2S_CTL0 0x04 /* REG 0x01 */ ++#define ACODEC_ADC_I2S_CTL1 0x08 /* REG 0x02 */ ++#define ACODEC_ADC_BIST_MODE_SEL 0x0c /* REG 0x03 */ ++#define ACODEC_ADC_HPF_PATH 0x10 /* REG 0x04 */ ++/* Resevred REG 0x05 ~ 0x06 */ ++#define ACODEC_ADC_DATA_PATH 0x1c /* REG 0x07 */ ++/* Resevred REG 0x08 ~ 0x0f */ ++ ++/* REG 0x10 ~ 0x1c are used to configure AGC of Left channel (ALC1) */ ++#define ACODEC_ADC_PGA_AGC_L_CTL0 0x40 /* REG 0x10 */ ++#define ACODEC_ADC_PGA_AGC_L_CTL1 0x44 /* REG 0x11 */ ++#define ACODEC_ADC_PGA_AGC_L_CTL2 0x48 /* REG 0x12 */ ++#define ACODEC_ADC_PGA_AGC_L_CTL3 0x4c /* REG 0x13 */ ++#define ACODEC_ADC_PGA_AGC_L_CTL4 0x50 /* REG 0x14 */ ++#define ACODEC_ADC_PGA_AGC_L_LO_MAX 0x54 /* REG 0x15 */ ++#define ACODEC_ADC_PGA_AGC_L_HI_MAX 0x58 /* REG 0x16 */ ++#define ACODEC_ADC_PGA_AGC_L_LO_MIN 0x5c /* REG 0x17 */ ++#define ACODEC_ADC_PGA_AGC_L_HI_MIN 0x60 /* REG 0x18 */ ++#define ACODEC_ADC_PGA_AGC_L_CTL5 0x64 /* REG 0x19 */ ++/* Resevred REG 0x1a ~ 0x1b */ ++#define ACODEC_ADC_AGC_L_RO_GAIN 0x70 /* REG 0x1c */ ++ ++/* REG 0x20 ~ 0x2c are used to configure AGC of Right channel (ALC2) */ ++#define ACODEC_ADC_PGA_AGC_R_CTL0 0x80 /* REG 0x20 */ ++#define ACODEC_ADC_PGA_AGC_R_CTL1 0x84 /* REG 0x21 */ ++#define ACODEC_ADC_PGA_AGC_R_CTL2 0x88 /* REG 0x22 */ ++#define ACODEC_ADC_PGA_AGC_R_CTL3 0x8c /* REG 0x23 */ ++#define ACODEC_ADC_PGA_AGC_R_CTL4 0x90 /* REG 0x24 */ ++#define ACODEC_ADC_PGA_AGC_R_LO_MAX 0x94 /* REG 0x25 */ ++#define ACODEC_ADC_PGA_AGC_R_HI_MAX 0x98 /* REG 0x26 */ ++#define ACODEC_ADC_PGA_AGC_R_LO_MIN 0x9c /* REG 0x27 */ ++#define ACODEC_ADC_PGA_AGC_R_HI_MIN 0xa0 /* REG 0x28 */ ++#define ACODEC_ADC_PGA_AGC_R_CTL5 0xa4 /* REG 0x29 */ ++/* Resevred REG 0x2a ~ 0x2b */ ++#define ACODEC_ADC_AGC_R_RO_GAIN 0xb0 /* REG 0x2c */ ++ ++/* DAC DIGITAL REGISTERS */ ++#define ACODEC_DAC_I2S_CTL0 0x04 /* REG 0x01 */ ++#define ACODEC_DAC_I2S_CTL1 0x08 /* REG 0x02 */ ++#define ACODEC_DAC_BIST_MODE_SEL 0x0c /* REG 0x03 */ ++#define ACODEC_DAC_DIGITAL_GAIN 0x10 /* REG 0x04 */ ++#define ACODEC_DAC_DATA_SEL 0x14 /* REG 0x05 */ ++/* Resevred REG 0x06 ~ 0x09 */ ++#define ACODEC_DAC_DATA_HI 0x28 /* REG 0x0a */ ++#define ACODEC_DAC_DATA_LO 0x2c /* REG 0x0b */ ++/* Resevred REG 0x0c */ ++#define ACODEC_DAC_HPDET_DELAYTIME 0x34 /* REG 0x0d */ ++#define ACODEC_DAC_HPDET_STATUS 0x38 /* REG 0x0e, Read-only */ ++/* Resevred REG 0x0f */ ++ ++/* ADC ANALOG REGISTERS */ ++#define ACODEC_ADC_ANA_MIC_CTL 0x00 /* REG 0x00 */ ++#define ACODEC_ADC_ANA_MIC_GAIN 0x04 /* REG 0x01 */ ++#define ACODEC_ADC_ANA_ALC_CTL 0x08 /* REG 0x02 */ ++#define ACODEC_ADC_ANA_ALC_GAIN1 0x0c /* REG 0x03 */ ++#define ACODEC_ADC_ANA_ALC_GAIN2 0x10 /* REG 0x04 */ ++#define ACODEC_ADC_ANA_CTL0 0x14 /* REG 0x05 */ ++#define ACODEC_ADC_ANA_CTL1 0x18 /* REG 0x06 */ ++#define ACODEC_ADC_ANA_CTL2 0x1c /* REG 0x07 */ ++#define ACODEC_ADC_ANA_CTL3 0x20 /* REG 0x08 */ ++/* Resevred REG 0x09 */ ++#define ACODEC_ADC_ANA_CTL4 0x28 /* REG 0x0a */ ++#define ACODEC_ADC_ANA_ALC_PGA 0x2c /* REG 0x0b */ ++/* Resevred REG 0x0c ~ 0x0f */ ++ ++/* DAC ANALOG REGISTERS */ ++#define ACODEC_DAC_ANA_CTL0 0x00 /* REG 0x00 */ ++#define ACODEC_DAC_ANA_POP_VOLT 0x04 /* REG 0x01 */ ++#define ACODEC_DAC_ANA_CTL1 0x08 /* REG 0x02 */ ++#define ACODEC_DAC_ANA_HPOUT 0x0c /* REG 0x03 */ ++#define ACODEC_DAC_ANA_LINEOUT 0x10 /* REG 0x04 */ ++#define ACODEC_DAC_ANA_L_HPOUT_GAIN 0x14 /* REG 0x05 */ ++#define ACODEC_DAC_ANA_R_HPOUT_GAIN 0x18 /* REG 0x06 */ ++#define ACODEC_DAC_ANA_DRV_HPOUT 0x1c /* REG 0x07 */ ++#define ACODEC_DAC_ANA_DRV_LINEOUT 0x20 /* REG 0x08 */ ++/* Resevred REG 0x07 ~ 0x0b */ ++#define ACODEC_DAC_ANA_HPMIX_CTL0 0x30 /* REG 0x0c */ ++#define ACODEC_DAC_ANA_HPMIX_CTL1 0x34 /* REG 0x0d */ ++#define ACODEC_DAC_ANA_LINEOUT_CTL0 0x38 /* REG 0x0e */ ++#define ACODEC_DAC_ANA_LINEOUT_CTL1 0x3c /* REG 0x0f */ ++ ++/* ++ * These registers are referenced by codec driver ++ */ ++ ++#define RK3308_GLB_CON ACODEC_RESET_CTL + + /* ADC DIGITAL REGISTERS */ + +@@ -21,51 +120,50 @@ + * CH2: left_2(ADC5) and right_2(ADC6) + * CH3: left_3(ADC7) and right_3(ADC8) + */ +-#define RK3308_ADC_DIG_OFFSET(ch) (((ch) & 0x3) * 0xc0 + 0x0) +- +-#define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x04) +-#define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x08) +-#define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x0c) +-#define RK3308_ADC_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x10) +-#define RK3308_ADC_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x14) // ver.C only +-#define RK3308_ADC_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x18) // ver.C only +-#define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x1c) +- +-#define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x40) +-#define RK3308_ALC_L_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x44) +-#define RK3308_ALC_L_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x48) +-#define RK3308_ALC_L_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x4c) +-#define RK3308_ALC_L_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x50) +-#define RK3308_ALC_L_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x54) +-#define RK3308_ALC_L_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x58) +-#define RK3308_ALC_L_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x5c) +-#define RK3308_ALC_L_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x60) +-#define RK3308_ALC_L_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x64) +-#define RK3308_ALC_L_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x70) +- +-#define RK3308_ALC_R_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x80) +-#define RK3308_ALC_R_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x84) +-#define RK3308_ALC_R_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x88) +-#define RK3308_ALC_R_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x8c) +-#define RK3308_ALC_R_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x90) +-#define RK3308_ALC_R_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x94) +-#define RK3308_ALC_R_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x98) +-#define RK3308_ALC_R_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x9c) +-#define RK3308_ALC_R_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0xa0) +-#define RK3308_ALC_R_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0xa4) +-#define RK3308_ALC_R_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0xb0) ++#define RK3308_ADC_DIG_OFFSET(ch) ((ch & 0x3) * 0xc0 + 0x0) ++ ++#define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL0) ++#define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_I2S_CTL1) ++#define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_BIST_MODE_SEL) ++#define RK3308_ADC_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_HPF_PATH) ++#define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_DATA_PATH) ++ ++#define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL0) ++#define RK3308_ALC_L_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL1) ++#define RK3308_ALC_L_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL2) ++#define RK3308_ALC_L_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL3) ++#define RK3308_ALC_L_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL4) ++#define RK3308_ALC_L_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_LO_MAX) ++#define RK3308_ALC_L_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_HI_MAX) ++#define RK3308_ALC_L_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_LO_MIN) ++#define RK3308_ALC_L_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_HI_MIN) ++#define RK3308_ALC_L_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_L_CTL5) ++#define RK3308_ALC_L_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_AGC_L_RO_GAIN) ++ ++#define RK3308_ALC_R_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL0) ++#define RK3308_ALC_R_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL1) ++#define RK3308_ALC_R_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL2) ++#define RK3308_ALC_R_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL3) ++#define RK3308_ALC_R_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL4) ++#define RK3308_ALC_R_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_LO_MAX) ++#define RK3308_ALC_R_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_HI_MAX) ++#define RK3308_ALC_R_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_LO_MIN) ++#define RK3308_ALC_R_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_HI_MIN) ++#define RK3308_ALC_R_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_PGA_AGC_R_CTL5) ++#define RK3308_ALC_R_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET(ch) + ACODEC_ADC_AGC_R_RO_GAIN) + + /* DAC DIGITAL REGISTERS */ + #define RK3308_DAC_DIG_OFFSET 0x300 +-#define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + 0x04) +-#define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + 0x08) +-#define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + 0x0c) +-#define RK3308_DAC_DIG_CON04 (RK3308_DAC_DIG_OFFSET + 0x10) +-#define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + 0x14) +-#define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + 0x28) +-#define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + 0x2c) +-#define RK3308_DAC_DIG_CON13 (RK3308_DAC_DIG_OFFSET + 0x34) +-#define RK3308_DAC_DIG_CON14 (RK3308_DAC_DIG_OFFSET + 0x38) ++ ++#define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL0) ++#define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_I2S_CTL1) ++#define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_BIST_MODE_SEL) ++#define RK3308_DAC_DIG_CON04 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DIGITAL_GAIN) ++#define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_SEL) ++#define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_HI) ++#define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_DATA_LO) ++#define RK3308_DAC_DIG_CON13 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_DELAYTIME) ++#define RK3308_DAC_DIG_CON14 (RK3308_DAC_DIG_OFFSET + ACODEC_DAC_HPDET_STATUS) + + /* ADC ANALOG REGISTERS */ + /* +@@ -76,50 +174,63 @@ + * CH2: left_2(ADC5) and right_2(ADC6) + * CH3: left_3(ADC7) and right_3(ADC8) + */ +-#define RK3308_ADC_ANA_OFFSET(ch) (((ch) & 0x3) * 0x40 + 0x340) +-#define RK3308_ADC_ANA_CON00(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x00) +-#define RK3308_ADC_ANA_CON01(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x04) +-#define RK3308_ADC_ANA_CON02(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x08) +-#define RK3308_ADC_ANA_CON03(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x0c) +-#define RK3308_ADC_ANA_CON04(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x10) +-#define RK3308_ADC_ANA_CON05(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x14) +-#define RK3308_ADC_ANA_CON06(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x18) +-#define RK3308_ADC_ANA_CON07(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x1c) +-#define RK3308_ADC_ANA_CON08(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x20) +-#define RK3308_ADC_ANA_CON10(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x28) +-#define RK3308_ADC_ANA_CON11(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x2c) ++#define RK3308_ADC_ANA_OFFSET(ch) ((ch & 0x3) * 0x40 + 0x340) ++ ++#define RK3308_ADC_ANA_CON00(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_MIC_CTL) ++#define RK3308_ADC_ANA_CON01(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_MIC_GAIN) ++#define RK3308_ADC_ANA_CON02(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_CTL) ++#define RK3308_ADC_ANA_CON03(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_GAIN1) ++#define RK3308_ADC_ANA_CON04(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_GAIN2) ++#define RK3308_ADC_ANA_CON05(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL0) ++#define RK3308_ADC_ANA_CON06(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL1) ++#define RK3308_ADC_ANA_CON07(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL2) ++#define RK3308_ADC_ANA_CON08(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL3) ++#define RK3308_ADC_ANA_CON10(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_CTL4) ++#define RK3308_ADC_ANA_CON11(ch) (RK3308_ADC_ANA_OFFSET(ch) + ACODEC_ADC_ANA_ALC_PGA) + + /* DAC ANALOG REGISTERS */ + #define RK3308_DAC_ANA_OFFSET 0x440 +-#define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + 0x00) +-#define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + 0x04) +-#define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + 0x08) +-#define RK3308_DAC_ANA_CON03 (RK3308_DAC_ANA_OFFSET + 0x0c) +-#define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + 0x10) +-#define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + 0x14) +-#define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + 0x18) +-#define RK3308_DAC_ANA_CON07 (RK3308_DAC_ANA_OFFSET + 0x1c) +-#define RK3308_DAC_ANA_CON08 (RK3308_DAC_ANA_OFFSET + 0x20) +-#define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + 0x30) +-#define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + 0x34) +-#define RK3308_DAC_ANA_CON14 (RK3308_DAC_ANA_OFFSET + 0x38) +-#define RK3308_DAC_ANA_CON15 (RK3308_DAC_ANA_OFFSET + 0x3c) ++#define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL0) ++#define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_POP_VOLT) ++#define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_CTL1) ++#define RK3308_DAC_ANA_CON03 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPOUT) ++#define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT) ++#define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_L_HPOUT_GAIN) ++#define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_R_HPOUT_GAIN) ++#define RK3308_DAC_ANA_CON07 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_DRV_HPOUT) ++#define RK3308_DAC_ANA_CON08 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_DRV_LINEOUT) ++#define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL0) ++#define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_HPMIX_CTL1) ++#define RK3308_DAC_ANA_CON14 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT_CTL0) ++#define RK3308_DAC_ANA_CON15 (RK3308_DAC_ANA_OFFSET + ACODEC_DAC_ANA_LINEOUT_CTL1) + + /* + * These are the bits for registers + */ + + /* RK3308_GLB_CON - REG: 0x0000 */ +-#define RK3308_ADC_BIST_WORK BIT(7) +-#define RK3308_DAC_BIST_WORK BIT(6) +-#define RK3308_ADC_MCLK_GATING BIT(5) +-#define RK3308_DAC_MCLK_GATING BIT(4) +-#define RK3308_ADC_DIG_WORK BIT(2) +-#define RK3308_DAC_DIG_WORK BIT(1) +-#define RK3308_SYS_WORK BIT(0) ++#define RK3308_ADC_BIST_WORK (1 << 7) ++#define RK3308_ADC_BIST_RESET (0 << 7) ++#define RK3308_DAC_BIST_WORK (1 << 6) ++#define RK3308_DAC_BIST_RESET (0 << 6) ++#define RK3308_ADC_MCLK_MSK (1 << 5) ++#define RK3308_ADC_MCLK_DIS (1 << 5) ++#define RK3308_ADC_MCLK_EN (0 << 5) ++#define RK3308_DAC_MCLK_MSK (1 << 4) ++#define RK3308_DAC_MCLK_DIS (1 << 4) ++#define RK3308_DAC_MCLK_EN (0 << 4) ++#define RK3308_CODEC_RST_MSK (0x7 << 0) ++#define RK3308_ADC_DIG_WORK (1 << 2) ++#define RK3308_ADC_DIG_RESET (0 << 2) ++#define RK3308_DAC_DIG_WORK (1 << 1) ++#define RK3308_DAC_DIG_RESET (0 << 1) ++#define RK3308_SYS_WORK (1 << 0) ++#define RK3308_SYS_RESET (0 << 0) + + /* RK3308_ADC_DIG_CON01 - REG: 0x0004 */ +-#define RK3308_ADC_I2S_LRC_POL_REVERSAL BIT(7) ++#define RK3308_ADC_I2S_LRC_POL_MSK (1 << 0) ++#define RK3308_ADC_I2S_LRC_POL_REVERSAL (1 << 0) ++#define RK3308_ADC_I2S_LRC_POL_NORMAL (0 << 0) + #define RK3308_ADC_I2S_VALID_LEN_SFT 5 + #define RK3308_ADC_I2S_VALID_LEN_MSK (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) + #define RK3308_ADC_I2S_VALID_LEN_32BITS (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) +@@ -132,20 +243,32 @@ + #define RK3308_ADC_I2S_MODE_I2S (0x2 << RK3308_ADC_I2S_MODE_SFT) + #define RK3308_ADC_I2S_MODE_LJ (0x1 << RK3308_ADC_I2S_MODE_SFT) + #define RK3308_ADC_I2S_MODE_RJ (0x0 << RK3308_ADC_I2S_MODE_SFT) +-#define RK3308_ADC_I2S_LR_SWAP BIT(1) +-#define RK3308_ADC_I2S_MONO BIT(0) ++#define RK3308_ADC_I2S_LR_MSK (1 << 1) ++#define RK3308_ADC_I2S_LR_SWAP (1 << 1) ++#define RK3308_ADC_I2S_LR_NORMAL (0 << 1) ++#define RK3308_ADC_I2S_TYPE_MSK (1 << 0) ++#define RK3308_ADC_I2S_MONO (1 << 0) ++#define RK3308_ADC_I2S_STEREO (0 << 0) + + /* RK3308_ADC_DIG_CON02 - REG: 0x0008 */ +-#define RK3308_ADC_IO_MODE_MASTER BIT(5) +-#define RK3308_ADC_MODE_MASTER BIT(4) ++#define RK3308_ADC_IO_MODE_MSK (1 << 5) ++#define RK3308_ADC_IO_MODE_MASTER (1 << 5) ++#define RK3308_ADC_IO_MODE_SLAVE (0 << 5) ++#define RK3308_ADC_MODE_MSK (1 << 4) ++#define RK3308_ADC_MODE_MASTER (1 << 4) ++#define RK3308_ADC_MODE_SLAVE (0 << 4) + #define RK3308_ADC_I2S_FRAME_LEN_SFT 2 + #define RK3308_ADC_I2S_FRAME_LEN_MSK (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) + #define RK3308_ADC_I2S_FRAME_32BITS (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) + #define RK3308_ADC_I2S_FRAME_24BITS (0x2 << RK3308_ADC_I2S_FRAME_LEN_SFT) + #define RK3308_ADC_I2S_FRAME_20BITS (0x1 << RK3308_ADC_I2S_FRAME_LEN_SFT) + #define RK3308_ADC_I2S_FRAME_16BITS (0x0 << RK3308_ADC_I2S_FRAME_LEN_SFT) +-#define RK3308_ADC_I2S_WORK BIT(1) +-#define RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL BIT(0) ++#define RK3308_ADC_I2S_MSK (0x1 << 1) ++#define RK3308_ADC_I2S_WORK (0x1 << 1) ++#define RK3308_ADC_I2S_RESET (0x0 << 1) ++#define RK3308_ADC_I2S_BIT_CLK_POL_MSK (0x1 << 0) ++#define RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0) ++#define RK3308_ADC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0) + + /* RK3308_ADC_DIG_CON03 - REG: 0x000c */ + #define RK3308_ADC_L_CH_BIST_SFT 2 +@@ -162,7 +285,10 @@ + #define RK3308_ADC_R_CH_NORMAL_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ + + /* RK3308_ADC_DIG_CON04 - REG: 0x0010 */ +-#define RK3308_ADC_HPF_PATH_DIS BIT(2) ++#define RK3308_ADC_HPF_PATH_SFT 2 ++#define RK3308_ADC_HPF_PATH_MSK (1 << RK3308_ADC_HPF_PATH_SFT) ++#define RK3308_ADC_HPF_PATH_DIS (1 << RK3308_ADC_HPF_PATH_SFT) ++#define RK3308_ADC_HPF_PATH_EN (0 << RK3308_ADC_HPF_PATH_SFT) + #define RK3308_ADC_HPF_CUTOFF_SFT 0 + #define RK3308_ADC_HPF_CUTOFF_MSK (0x3 << RK3308_ADC_HPF_CUTOFF_SFT) + #define RK3308_ADC_HPF_CUTOFF_612HZ (0x2 << RK3308_ADC_HPF_CUTOFF_SFT) +@@ -171,15 +297,20 @@ + + /* RK3308_ADC_DIG_CON07 - REG: 0x001c */ + #define RK3308_ADCL_DATA_SFT 4 ++#define RK3308_ADCL_DATA(x) (x << RK3308_ADCL_DATA_SFT) + #define RK3308_ADCR_DATA_SFT 2 +-#define RK3308_ADCL_DATA_SEL_ADCL BIT(1) +-#define RK3308_ADCR_DATA_SEL_ADCR BIT(0) ++#define RK3308_ADCR_DATA(x) (x << RK3308_ADCR_DATA_SFT) ++#define RK3308_ADCL_DATA_SEL_ADCL (0x1 << 1) ++#define RK3308_ADCL_DATA_SEL_NORMAL (0x0 << 1) ++#define RK3308_ADCR_DATA_SEL_ADCR (0x1 << 0) ++#define RK3308_ADCR_DATA_SEL_NORMAL (0x0 << 0) + + /* + * RK3308_ALC_L_DIG_CON00 - REG: 0x0040 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON00 - REG: 0x0080 + ch * 0xc0 + */ +-#define RK3308_GAIN_ATTACK_JACK BIT(6) ++#define RK3308_GAIN_ATTACK_JACK (0x1 << 6) ++#define RK3308_GAIN_ATTACK_NORMAL (0x0 << 6) + #define RK3308_CTRL_GEN_SFT 4 + #define RK3308_CTRL_GEN_MSK (0x3 << RK3308_ALC_CTRL_GEN_SFT) + #define RK3308_CTRL_GEN_JACK3 (0x3 << RK3308_ALC_CTRL_GEN_SFT) +@@ -205,36 +336,145 @@ + * RK3308_ALC_R_DIG_CON01 - REG: 0x0084 + ch * 0xc0 + */ + #define RK3308_AGC_DECAY_TIME_SFT 4 ++/* Normal mode (reg_agc_mode = 0) */ ++#define RK3308_AGC_DECAY_NORMAL_MSK (0xf << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_512MS (0xa << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_256MS (0x9 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_128MS (0x8 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_64MS (0x7 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_32MS (0x6 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_16MS (0x5 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_8MS (0x4 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_4MS (0x3 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_2MS (0x2 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_1MS (0x1 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_NORMAL_0MS (0x0 << RK3308_AGC_DECAY_TIME_SFT) ++/* Limiter mode (reg_agc_mode = 1) */ ++#define RK3308_AGC_DECAY_LIMITER_MSK (0xf << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_128MS (0xa << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_64MS (0x9 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_32MS (0x8 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_16MS (0x7 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_8MS (0x6 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_4MS (0x5 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_2MS (0x4 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_1MS (0x3 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_500US (0x2 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_250US (0x1 << RK3308_AGC_DECAY_TIME_SFT) ++#define RK3308_AGC_DECAY_LIMITER_125US (0x0 << RK3308_AGC_DECAY_TIME_SFT) ++ + #define RK3308_AGC_ATTACK_TIME_SFT 0 ++/* Normal mode (reg_agc_mode = 0) */ ++#define RK3308_AGC_ATTACK_NORMAL_MSK (0xf << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_128MS (0xa << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_64MS (0x9 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_32MS (0x8 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_16MS (0x7 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_8MS (0x6 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_4MS (0x5 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_2MS (0x4 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_1MS (0x3 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_500US (0x2 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_250US (0x1 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_NORMAL_125US (0x0 << RK3308_AGC_ATTACK_TIME_SFT) ++/* Limiter mode (reg_agc_mode = 1) */ ++#define RK3308_AGC_ATTACK_LIMITER_MSK (0xf << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_32MS (0xa << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_16MS (0x9 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_8MS (0x8 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_4MS (0x7 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_2MS (0x6 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_1MS (0x5 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_500US (0x4 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_250US (0x3 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_125US (0x2 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_64US (0x1 << RK3308_AGC_ATTACK_TIME_SFT) ++#define RK3308_AGC_ATTACK_LIMITER_32US (0x0 << RK3308_AGC_ATTACK_TIME_SFT) + + /* + * RK3308_ALC_L_DIG_CON02 - REG: 0x0048 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON02 - REG: 0x0088 + ch * 0xc0 + */ +-#define RK3308_AGC_MODE_LIMITER BIT(7) +-#define RK3308_AGC_ZERO_CRO_EN BIT(6) +-#define RK3308_AGC_AMP_RECOVER_GAIN BIT(5) +-#define RK3308_AGC_FAST_DEC_EN BIT(4) +-#define RK3308_AGC_NOISE_GATE_EN BIT(3) ++#define RK3308_AGC_MODE_LIMITER (0x1 << 7) ++#define RK3308_AGC_MODE_NORMAL (0x0 << 7) ++#define RK3308_AGC_ZERO_CRO_EN (0x1 << 6) ++#define RK3308_AGC_ZERO_CRO_DIS (0x0 << 6) ++#define RK3308_AGC_AMP_RECOVER_GAIN (0x1 << 5) ++#define RK3308_AGC_AMP_RECOVER_LVOL (0x0 << 5) ++#define RK3308_AGC_FAST_DEC_EN (0x1 << 4) ++#define RK3308_AGC_FAST_DEC_DIS (0x0 << 4) ++#define RK3308_AGC_NOISE_GATE_EN (0x1 << 3) ++#define RK3308_AGC_NOISE_GATE_DIS (0x0 << 3) + #define RK3308_AGC_NOISE_GATE_THRESH_SFT 0 + #define RK3308_AGC_NOISE_GATE_THRESH_MSK (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N81DB (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N75DB (0x6 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N69DB (0x5 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N63DB (0x4 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N57DB (0x3 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N51DB (0x2 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N45DB (0x1 << RK3308_AGC_NOISE_GATE_THRESH_SFT) ++#define RK3308_AGC_NOISE_GATE_THRESH_N39DB (0x0 << RK3308_AGC_NOISE_GATE_THRESH_SFT) + + /* + * RK3308_ALC_L_DIG_CON03 - REG: 0x004c + ch * 0xc0 + * RK3308_ALC_R_DIG_CON03 - REG: 0x008c + ch * 0xc0 + */ +-#define RK3308_AGC_PGA_ZERO_CRO_EN BIT(5) ++#define RK3308_AGC_PGA_ZERO_CRO_EN (0x1 << 5) ++#define RK3308_AGC_PGA_ZERO_CRO_DIS (0x0 << 5) + #define RK3308_AGC_PGA_GAIN_MAX 0x1f + #define RK3308_AGC_PGA_GAIN_MIN 0 + #define RK3308_AGC_PGA_GAIN_SFT 0 ++#define RK3308_AGC_PGA_GAIN_MSK (0x1f << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_28_5 (0x1f << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_27 (0x1e << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_25_5 (0x1d << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_24 (0x1c << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_22_5 (0x1b << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_21 (0x1a << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_19_5 (0x19 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_18 (0x18 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_16_5 (0x17 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_15 (0x16 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_13_5 (0x15 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_12 (0x14 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_10_5 (0x13 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_9 (0x12 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_7_5 (0x11 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_6 (0x10 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_4_5 (0x0f << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_3 (0x0e << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_PDB_1_5 (0x0d << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_0DB (0x0c << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_1_5 (0x0b << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_3 (0x0a << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_4_5 (0x09 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_6 (0x08 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_7_5 (0x07 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_9 (0x06 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_10_5 (0x05 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_12 (0x04 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_13_5 (0x03 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_15 (0x02 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_16_5 (0x01 << RK3308_AGC_PGA_GAIN_SFT) ++#define RK3308_AGC_PGA_GAIN_NDB_18 (0x00 << RK3308_AGC_PGA_GAIN_SFT) + + /* + * RK3308_ALC_L_DIG_CON04 - REG: 0x0050 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON04 - REG: 0x0090 + ch * 0xc0 + */ +-#define RK3308_AGC_SLOW_CLK_EN BIT(3) ++#define RK3308_AGC_SLOW_CLK_EN (0x1 << 3) ++#define RK3308_AGC_SLOW_CLK_DIS (0x0 << 3) + #define RK3308_AGC_APPROX_RATE_SFT 0 + #define RK3308_AGC_APPROX_RATE_MSK (0x7 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_8K (0x7 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_12K (0x6 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_16K (0x5 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_24K (0x4 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_32K (0x3 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_44_1K (0x2 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_48K (0x1 << RK3308_AGC_APPROX_RATE_SFT) ++#define RK3308_AGC_APPROX_RATE_96K (0x0 << RK3308_AGC_APPROX_RATE_SFT) + + /* + * RK3308_ALC_L_DIG_CON05 - REG: 0x0054 + ch * 0xc0 +@@ -264,15 +504,33 @@ + * RK3308_ALC_L_DIG_CON09 - REG: 0x0064 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON09 - REG: 0x00a4 + ch * 0xc0 + */ +-#define RK3308_AGC_FUNC_SEL BIT(6) ++#define RK3308_AGC_FUNC_SEL_MSK (0x1 << 6) ++#define RK3308_AGC_FUNC_SEL_EN (0x1 << 6) ++#define RK3308_AGC_FUNC_SEL_DIS (0x0 << 6) + #define RK3308_AGC_MAX_GAIN_PGA_MAX 0x7 + #define RK3308_AGC_MAX_GAIN_PGA_MIN 0 + #define RK3308_AGC_MAX_GAIN_PGA_SFT 3 + #define RK3308_AGC_MAX_GAIN_PGA_MSK (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_PDB_28_5 (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_PDB_22_5 (0x6 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_PDB_16_5 (0x5 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_PDB_10_5 (0x4 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_PDB_4_5 (0x3 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_NDB_1_5 (0x2 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_NDB_7_5 (0x1 << RK3308_AGC_MAX_GAIN_PGA_SFT) ++#define RK3308_AGC_MAX_GAIN_PGA_NDB_13_5 (0x0 << RK3308_AGC_MAX_GAIN_PGA_SFT) + #define RK3308_AGC_MIN_GAIN_PGA_MAX 0x7 + #define RK3308_AGC_MIN_GAIN_PGA_MIN 0 + #define RK3308_AGC_MIN_GAIN_PGA_SFT 0 + #define RK3308_AGC_MIN_GAIN_PGA_MSK (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_PDB_24 (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_PDB_18 (0x6 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_PDB_12 (0x5 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_PDB_6 (0x4 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_0DB (0x3 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_NDB_6 (0x2 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_NDB_12 (0x1 << RK3308_AGC_MIN_GAIN_PGA_SFT) ++#define RK3308_AGC_MIN_GAIN_PGA_NDB_18 (0x0 << RK3308_AGC_MIN_GAIN_PGA_SFT) + + /* + * RK3308_ALC_L_DIG_CON12 - REG: 0x0068 + ch * 0xc0 +@@ -281,7 +539,9 @@ + #define RK3308_AGC_GAIN_MSK 0x1f + + /* RK3308_DAC_DIG_CON01 - REG: 0x0304 */ +-#define RK3308_DAC_I2S_LRC_POL_REVERSAL BIT(7) ++#define RK3308_DAC_I2S_LRC_POL_MSK (0x1 << 7) ++#define RK3308_DAC_I2S_LRC_POL_REVERSAL (0x1 << 7) ++#define RK3308_DAC_I2S_LRC_POL_NORMAL (0x0 << 7) + #define RK3308_DAC_I2S_VALID_LEN_SFT 5 + #define RK3308_DAC_I2S_VALID_LEN_MSK (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) + #define RK3308_DAC_I2S_VALID_LEN_32BITS (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) +@@ -294,21 +554,29 @@ + #define RK3308_DAC_I2S_MODE_I2S (0x2 << RK3308_DAC_I2S_MODE_SFT) + #define RK3308_DAC_I2S_MODE_LJ (0x1 << RK3308_DAC_I2S_MODE_SFT) + #define RK3308_DAC_I2S_MODE_RJ (0x0 << RK3308_DAC_I2S_MODE_SFT) +-#define RK3308_DAC_I2S_LR_SWAP BIT(2) ++#define RK3308_DAC_I2S_LR_MSK (0x1 << 2) ++#define RK3308_DAC_I2S_LR_SWAP (0x1 << 2) ++#define RK3308_DAC_I2S_LR_NORMAL (0x0 << 2) + + /* RK3308_DAC_DIG_CON02 - REG: 0x0308 */ +-#define RK3308BS_DAC_IO_MODE_MASTER BIT(7) +-#define RK3308BS_DAC_MODE_MASTER BIT(6) +-#define RK3308_DAC_IO_MODE_MASTER BIT(5) +-#define RK3308_DAC_MODE_MASTER BIT(4) ++#define RK3308_DAC_IO_MODE_MSK (0x1 << 5) ++#define RK3308_DAC_IO_MODE_MASTER (0x1 << 5) ++#define RK3308_DAC_IO_MODE_SLAVE (0x0 << 5) ++#define RK3308_DAC_MODE_MSK (0x1 << 4) ++#define RK3308_DAC_MODE_MASTER (0x1 << 4) ++#define RK3308_DAC_MODE_SLAVE (0x0 << 4) + #define RK3308_DAC_I2S_FRAME_LEN_SFT 2 + #define RK3308_DAC_I2S_FRAME_LEN_MSK (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) + #define RK3308_DAC_I2S_FRAME_32BITS (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) + #define RK3308_DAC_I2S_FRAME_24BITS (0x2 << RK3308_DAC_I2S_FRAME_LEN_SFT) + #define RK3308_DAC_I2S_FRAME_20BITS (0x1 << RK3308_DAC_I2S_FRAME_LEN_SFT) + #define RK3308_DAC_I2S_FRAME_16BITS (0x0 << RK3308_DAC_I2S_FRAME_LEN_SFT) +-#define RK3308_DAC_I2S_WORK BIT(1) +-#define RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL BIT(0) ++#define RK3308_DAC_I2S_MSK (0x1 << 1) ++#define RK3308_DAC_I2S_WORK (0x1 << 1) ++#define RK3308_DAC_I2S_RESET (0x0 << 1) ++#define RK3308_DAC_I2S_BIT_CLK_POL_MSK (0x1 << 0) ++#define RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0) ++#define RK3308_DAC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0) + + /* RK3308_DAC_DIG_CON03 - REG: 0x030C */ + #define RK3308_DAC_L_CH_BIST_SFT 2 +@@ -325,62 +593,64 @@ + #define RK3308_DAC_R_CH_BIST_RIGHT (0x0 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ + + /* RK3308_DAC_DIG_CON04 - REG: 0x0310 */ +-/* Versions up to B: */ + #define RK3308_DAC_MODULATOR_GAIN_SFT 4 + #define RK3308_DAC_MODULATOR_GAIN_MSK (0x7 << RK3308_DAC_MODULATOR_GAIN_SFT) ++#define RK3308_DAC_MODULATOR_GAIN_4_8DB (0x5 << RK3308_DAC_MODULATOR_GAIN_SFT) ++#define RK3308_DAC_MODULATOR_GAIN_4_2DB (0x4 << RK3308_DAC_MODULATOR_GAIN_SFT) ++#define RK3308_DAC_MODULATOR_GAIN_3_5DB (0x3 << RK3308_DAC_MODULATOR_GAIN_SFT) ++#define RK3308_DAC_MODULATOR_GAIN_2_8DB (0x2 << RK3308_DAC_MODULATOR_GAIN_SFT) ++#define RK3308_DAC_MODULATOR_GAIN_2DB (0x1 << RK3308_DAC_MODULATOR_GAIN_SFT) ++#define RK3308_DAC_MODULATOR_GAIN_0DB (0x0 << RK3308_DAC_MODULATOR_GAIN_SFT) + #define RK3308_DAC_CIC_IF_GAIN_SFT 0 + #define RK3308_DAC_CIC_IF_GAIN_MSK (0x7 << RK3308_DAC_CIC_IF_GAIN_SFT) +-/* Version C: */ +-#define RK3308BS_DAC_DIG_GAIN_SFT 0 +-#define RK3308BS_DAC_DIG_GAIN_MSK (0xff << RK3308BS_DAC_DIG_GAIN_SFT) +-#define RK3308BS_DAC_DIG_GAIN_0DB (0xed << RK3308BS_DAC_DIG_GAIN_SFT) +- +-/* RK3308BS_ADC_DIG_CON05..06 (Version C only) */ +-#define RK3308_ADC_DIG_VOL_CON_x_SFT 0 +-#define RK3308_ADC_DIG_VOL_CON_x_MSK (0xff << RK3308_ADC_DIG_VOL_CON_x_SFT) +-#define RK3308_ADC_DIG_VOL_CON_x_0DB (0xc2 << RK3308_ADC_DIG_VOL_CON_x_SFT) + + /* RK3308_DAC_DIG_CON05 - REG: 0x0314 */ +-#define RK3308_DAC_L_REG_CTL_INDATA BIT(2) +-#define RK3308_DAC_R_REG_CTL_INDATA BIT(1) ++#define RK3308_DAC_L_REG_CTL_INDATA (0x1 << 2) ++#define RK3308_DAC_L_NORMAL_DATA (0x0 << 2) ++#define RK3308_DAC_R_REG_CTL_INDATA (0x1 << 1) ++#define RK3308_DAC_R_NORMAL_DATA (0x0 << 1) + + /* RK3308_DAC_DIG_CON10 - REG: 0x0328 */ +-#define RK3308_DAC_DATA_HI4(x) ((x) & 0xf) ++#define RK3308_DAC_DATA_HI4(x) (x & 0xf) /* Need to RK3308_DAC_x_REG_CTL_INDATA */ + + /* RK3308_DAC_DIG_CON11 - REG: 0x032c */ +-#define RK3308_DAC_DATA_LO8(x) ((x) & 0xff) ++#define RK3308_DAC_DATA_LO8(x) (x & 0xff) /* Need to RK3308_DAC_x_REG_CTL_INDATA */ + + /* RK3308_ADC_ANA_CON00 - REG: 0x0340 */ + #define RK3308_ADC_CH1_CH2_MIC_ALL_MSK (0xff << 0) + #define RK3308_ADC_CH1_CH2_MIC_ALL 0xff +-#define RK3308_ADC_CH2_MIC_UNMUTE BIT(7) +-#define RK3308_ADC_CH2_MIC_WORK BIT(6) +-#define RK3308_ADC_CH2_MIC_EN BIT(5) +-#define RK3308_ADC_CH2_BUF_REF_EN BIT(4) +-#define RK3308_ADC_CH1_MIC_UNMUTE BIT(3) +-#define RK3308_ADC_CH1_MIC_WORK BIT(2) +-#define RK3308_ADC_CH1_MIC_EN BIT(1) +-#define RK3308_ADC_CH1_BUF_REF_EN BIT(0) ++#define RK3308_ADC_CH2_MIC_UNMUTE (0x1 << 7) ++#define RK3308_ADC_CH2_MIC_MUTE (0x0 << 7) ++#define RK3308_ADC_CH2_MIC_WORK (0x1 << 6) ++#define RK3308_ADC_CH2_MIC_INIT (0x0 << 6) ++#define RK3308_ADC_CH2_MIC_EN (0x1 << 5) ++#define RK3308_ADC_CH2_MIC_DIS (0x0 << 5) ++#define RK3308_ADC_CH2_BUF_REF_EN (0x1 << 4) ++#define RK3308_ADC_CH2_BUF_REF_DIS (0x0 << 4) ++#define RK3308_ADC_CH1_MIC_UNMUTE (0x1 << 3) ++#define RK3308_ADC_CH1_MIC_MUTE (0x0 << 3) ++#define RK3308_ADC_CH1_MIC_WORK (0x1 << 2) ++#define RK3308_ADC_CH1_MIC_INIT (0x0 << 2) ++#define RK3308_ADC_CH1_MIC_EN (0x1 << 1) ++#define RK3308_ADC_CH1_MIC_DIS (0x0 << 1) ++#define RK3308_ADC_CH1_BUF_REF_EN (0x1 << 0) ++#define RK3308_ADC_CH1_BUF_REF_DIS (0x0 << 0) + + /* RK3308_ADC_ANA_CON01 - REG: 0x0344 + * + * The PGA of MIC-INs: +- * - HW version A: +- * 0x0 - MIC1~MIC8 0 dB (recommended when ADC used as loopback) +- * 0x3 - MIC1~MIC8 20 dB (recommended when ADC used as MIC input) +- * - HW version B: +- * 0x0 - MIC1~MIC8 0 dB +- * 0x1 - MIC1~MIC8 6.6 dB +- * 0x2 - MIC1~MIC8 13 dB +- * 0x3 - MIC1~MIC8 20 dB ++ * 0x0 - MIC1~MIC8 0dB ++ * 0x1 - MIC1~MIC8 6.6dB ++ * 0x2 - MIC1~MIC8 13dB ++ * 0x3 - MIC1~MIC8 20dB + */ + #define RK3308_ADC_CH2_MIC_GAIN_MAX 0x3 + #define RK3308_ADC_CH2_MIC_GAIN_MIN 0 + #define RK3308_ADC_CH2_MIC_GAIN_SFT 4 + #define RK3308_ADC_CH2_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) + #define RK3308_ADC_CH2_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) +-#define RK3308_ADC_CH2_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) +-#define RK3308_ADC_CH2_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) ++#define RK3308_ADC_CH2_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) /* TRM: only used for version B */ ++#define RK3308_ADC_CH2_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) /* TRM: only used for version B */ + #define RK3308_ADC_CH2_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH2_MIC_GAIN_SFT) + + #define RK3308_ADC_CH1_MIC_GAIN_MAX 0x3 +@@ -388,42 +658,124 @@ + #define RK3308_ADC_CH1_MIC_GAIN_SFT 0 + #define RK3308_ADC_CH1_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) + #define RK3308_ADC_CH1_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) +-#define RK3308_ADC_CH1_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) +-#define RK3308_ADC_CH1_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) ++#define RK3308_ADC_CH1_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) /* TRM: only used for version B */ ++#define RK3308_ADC_CH1_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) /* TRM: only used for version B */ + #define RK3308_ADC_CH1_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH1_MIC_GAIN_SFT) + + /* RK3308_ADC_ANA_CON02 - REG: 0x0348 */ +-#define RK3308_ADC_CH2_ZEROCROSS_DET_EN BIT(6) +-#define RK3308_ADC_CH2_ALC_WORK BIT(5) +-#define RK3308_ADC_CH2_ALC_EN BIT(4) +-#define RK3308_ADC_CH1_ZEROCROSS_DET_EN BIT(2) +-#define RK3308_ADC_CH1_ALC_WORK BIT(1) +-#define RK3308_ADC_CH1_ALC_EN BIT(0) ++#define RK3308_ADC_CH2_ALC_ZC_MSK (0x7 << 4) ++#define RK3308_ADC_CH2_ZEROCROSS_DET_EN (0x1 << 6) ++#define RK3308_ADC_CH2_ZEROCROSS_DET_DIS (0x0 << 6) ++#define RK3308_ADC_CH2_ALC_WORK (0x1 << 5) ++#define RK3308_ADC_CH2_ALC_INIT (0x0 << 5) ++#define RK3308_ADC_CH2_ALC_EN (0x1 << 4) ++#define RK3308_ADC_CH2_ALC_DIS (0x0 << 4) ++ ++#define RK3308_ADC_CH1_ALC_ZC_MSK (0x7 << 0) ++#define RK3308_ADC_CH1_ZEROCROSS_DET_EN (0x1 << 2) ++#define RK3308_ADC_CH1_ZEROCROSS_DET_DIS (0x0 << 2) ++#define RK3308_ADC_CH1_ALC_WORK (0x1 << 1) ++#define RK3308_ADC_CH1_ALC_INIT (0x0 << 1) ++#define RK3308_ADC_CH1_ALC_EN (0x1 << 0) ++#define RK3308_ADC_CH1_ALC_DIS (0x0 << 0) + + /* RK3308_ADC_ANA_CON03 - REG: 0x034c */ + #define RK3308_ADC_CH1_ALC_GAIN_MAX 0x1f + #define RK3308_ADC_CH1_ALC_GAIN_MIN 0 + #define RK3308_ADC_CH1_ALC_GAIN_SFT 0 + #define RK3308_ADC_CH1_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_27 (0x1e << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_25_5 (0x1d << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_24 (0x1c << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_22_5 (0x1b << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_21 (0x1a << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_19_5 (0x19 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_18 (0x18 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_16_5 (0x17 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_15 (0x16 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_13_5 (0x15 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_12 (0x14 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_10_5 (0x13 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_9 (0x12 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_7_5 (0x11 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_6 (0x10 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_4_5 (0x0f << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_3 (0x0e << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_PDB_1_5 (0x0d << RK3308_ADC_CH1_ALC_GAIN_SFT) + #define RK3308_ADC_CH1_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_1_5 (0x0b << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_3 (0x0a << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_4_5 (0x09 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_6 (0x08 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_7_5 (0x07 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_9 (0x06 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_10_5 (0x05 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_12 (0x04 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_13_5 (0x03 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_15 (0x02 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_16_5 (0x01 << RK3308_ADC_CH1_ALC_GAIN_SFT) ++#define RK3308_ADC_CH1_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH1_ALC_GAIN_SFT) + + /* RK3308_ADC_ANA_CON04 - REG: 0x0350 */ + #define RK3308_ADC_CH2_ALC_GAIN_MAX 0x1f + #define RK3308_ADC_CH2_ALC_GAIN_MIN 0 + #define RK3308_ADC_CH2_ALC_GAIN_SFT 0 + #define RK3308_ADC_CH2_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_28_5 (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_27 (0x1e << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_25_5 (0x1d << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_24 (0x1c << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_22_5 (0x1b << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_21 (0x1a << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_19_5 (0x19 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_18 (0x18 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_16_5 (0x17 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_15 (0x16 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_13_5 (0x15 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_12 (0x14 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_10_5 (0x13 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_9 (0x12 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_7_5 (0x11 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_6 (0x10 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_4_5 (0x0f << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_3 (0x0e << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_PDB_1_5 (0x0d << RK3308_ADC_CH2_ALC_GAIN_SFT) + #define RK3308_ADC_CH2_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_1_5 (0x0b << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_3 (0x0a << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_4_5 (0x09 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_6 (0x08 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_7_5 (0x07 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_9 (0x06 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_10_5 (0x05 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_12 (0x04 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_13_5 (0x03 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_15 (0x02 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_16_5 (0x01 << RK3308_ADC_CH2_ALC_GAIN_SFT) ++#define RK3308_ADC_CH2_ALC_GAIN_NDB_18 (0x00 << RK3308_ADC_CH2_ALC_GAIN_SFT) + + /* RK3308_ADC_ANA_CON05 - REG: 0x0354 */ +-#define RK3308_ADC_CH2_ADC_WORK BIT(6) +-#define RK3308_ADC_CH2_ADC_EN BIT(5) +-#define RK3308_ADC_CH2_CLK_EN BIT(4) +-#define RK3308_ADC_CH1_ADC_WORK BIT(2) +-#define RK3308_ADC_CH1_ADC_EN BIT(1) +-#define RK3308_ADC_CH1_CLK_EN BIT(0) ++#define RK3308_ADC_CH2_ADC_CLK_MSK (0x7 << 4) ++#define RK3308_ADC_CH2_ADC_WORK (0x1 << 6) ++#define RK3308_ADC_CH2_ADC_INIT (0x0 << 6) ++#define RK3308_ADC_CH2_ADC_EN (0x1 << 5) ++#define RK3308_ADC_CH2_ADC_DIS (0x0 << 5) ++#define RK3308_ADC_CH2_CLK_EN (0x1 << 4) ++#define RK3308_ADC_CH2_CLK_DIS (0x0 << 4) ++ ++#define RK3308_ADC_CH1_ADC_CLK_MSK (0x7 << 0) ++#define RK3308_ADC_CH1_ADC_WORK (0x1 << 2) ++#define RK3308_ADC_CH1_ADC_INIT (0x0 << 2) ++#define RK3308_ADC_CH1_ADC_EN (0x1 << 1) ++#define RK3308_ADC_CH1_ADC_DIS (0x0 << 1) ++#define RK3308_ADC_CH1_CLK_EN (0x1 << 0) ++#define RK3308_ADC_CH1_CLK_DIS (0x0 << 0) + + /* RK3308_ADC_ANA_CON06 - REG: 0x0358 */ +-#define RK3308_ADC_CURRENT_EN BIT(0) ++#define RK3308_ADC_CURRENT_MSK (0x1 << 0) ++#define RK3308_ADC_CURRENT_EN (0x1 << 0) ++#define RK3308_ADC_CURRENT_DIS (0x0 << 0) + + /* RK3308_ADC_ANA_CON07 - REG: 0x035c */ + /* Note: The register configuration is only valid for ADC2 */ +@@ -440,80 +792,201 @@ + #define RK3308_ADC_CH1_IN_LINEIN (0x2 << RK3308_ADC_CH1_IN_SEL_SFT) + #define RK3308_ADC_CH1_IN_MIC (0x1 << RK3308_ADC_CH1_IN_SEL_SFT) + #define RK3308_ADC_CH1_IN_NONE (0x0 << RK3308_ADC_CH1_IN_SEL_SFT) +-#define RK3308_ADC_MIC_BIAS_BUF_EN BIT(3) +-#define RK3308_ADC_LEVEL_RANGE_MICBIAS_MAX 7 ++ ++#define RK3308_ADC_MIC_BIAS_BUF_SFT 3 ++#define RK3308_ADC_MIC_BIAS_BUF_EN (0x1 << RK3308_ADC_MIC_BIAS_BUF_SFT) ++#define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << RK3308_ADC_MIC_BIAS_BUF_SFT) + #define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 + #define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++/* ++ * The follow MICBIAS_VOLTs are based on the external reference voltage(Vref). ++ * For example, the Vref == 3.3V, the MICBIAS_VOLT_0_85 is equal: ++ * 3.3V * 0.85 = 2.805V. ++ */ ++#define RK3308_ADC_MICBIAS_VOLT_0_85 (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_8 (0x6 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_75 (0x5 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_7 (0x4 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_65 (0x3 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_6 (0x2 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_55 (0x1 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) ++#define RK3308_ADC_MICBIAS_VOLT_0_5 (0x0 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) + + /* RK3308_ADC_ANA_CON08 - REG: 0x0360 */ +-#define RK3308_ADC_MICBIAS_CURRENT_EN BIT(4) ++#define RK3308_ADC_MICBIAS_CURRENT_MSK (0x1 << 4) ++#define RK3308_ADC_MICBIAS_CURRENT_EN (0x1 << 4) ++#define RK3308_ADC_MICBIAS_CURRENT_DIS (0x0 << 4) + + /* RK3308_ADC_ANA_CON10 - REG: 0x0368 */ +-#define RK3308_ADC_REF_EN BIT(7) ++#define RK3308_ADC_REF_EN (0x1 << 7) ++#define RK3308_ADC_REF_DIS (0x0 << 7) + #define RK3308_ADC_CURRENT_CHARGE_SFT 0 + #define RK3308_ADC_CURRENT_CHARGE_MSK (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) ++/* ++ * 1: Choose the current I ++ * 0: Don't choose the current I ++ */ ++#define RK3308_ADC_SEL_I(x) (x & 0x7f) + + /* RK3308_ADC_ANA_CON11 - REG: 0x036c */ +-#define RK3308_ADC_ALCR_CON_GAIN_PGAR_EN BIT(1) +-#define RK3308_ADC_ALCL_CON_GAIN_PGAL_EN BIT(0) ++#define RK3308_ADC_ALCR_CON_GAIN_PGAR_MSK (0x1 << 1) ++#define RK3308_ADC_ALCR_CON_GAIN_PGAR_EN (0x1 << 1) ++#define RK3308_ADC_ALCR_CON_GAIN_PGAR_DIS (0x0 << 1) ++#define RK3308_ADC_ALCL_CON_GAIN_PGAL_MSK (0x1 << 0) ++#define RK3308_ADC_ALCL_CON_GAIN_PGAL_EN (0x1 << 0) ++#define RK3308_ADC_ALCL_CON_GAIN_PGAL_DIS (0x0 << 0) + + /* RK3308_DAC_ANA_CON00 - REG: 0x0440 */ +-#define RK3308_DAC_HEADPHONE_DET_EN BIT(1) +-#define RK3308_DAC_CURRENT_EN BIT(0) ++#define RK3308_DAC_HEADPHONE_DET_MSK (0x1 << 1) ++#define RK3308_DAC_HEADPHONE_DET_EN (0x1 << 1) ++#define RK3308_DAC_HEADPHONE_DET_DIS (0x0 << 1) ++#define RK3308_DAC_CURRENT_MSK (0x1 << 0) ++#define RK3308_DAC_CURRENT_EN (0x1 << 0) ++#define RK3308_DAC_CURRENT_DIS (0x0 << 0) + + /* RK3308_DAC_ANA_CON01 - REG: 0x0444 */ +-#define RK3308_DAC_BUF_REF_R_EN BIT(6) +-#define RK3308_DAC_BUF_REF_L_EN BIT(2) ++#define RK3308_DAC_BUF_REF_R_MSK (0x1 << 6) ++#define RK3308_DAC_BUF_REF_R_EN (0x1 << 6) ++#define RK3308_DAC_BUF_REF_R_DIS (0x0 << 6) + #define RK3308_DAC_HPOUT_POP_SOUND_R_SFT 4 ++#define RK3308_DAC_HPOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) ++#define RK3308_DAC_HPOUT_POP_SOUND_R_WORK (0x2 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) ++#define RK3308_DAC_HPOUT_POP_SOUND_R_INIT (0x1 << RK3308_DAC_HPOUT_POP_SOUND_R_SFT) ++#define RK3308_DAC_BUF_REF_L_MSK (0x1 << 2) ++#define RK3308_DAC_BUF_REF_L_EN (0x1 << 2) ++#define RK3308_DAC_BUF_REF_L_DIS (0x0 << 2) + #define RK3308_DAC_HPOUT_POP_SOUND_L_SFT 0 +-// unshifted values for both L and R: +-#define RK3308_DAC_HPOUT_POP_SOUND_x_MSK 0x3 +-#define RK3308_DAC_HPOUT_POP_SOUND_x_WORK 0x2 +-#define RK3308_DAC_HPOUT_POP_SOUND_x_INIT 0x1 ++#define RK3308_DAC_HPOUT_POP_SOUND_L_MSK (0x3 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) ++#define RK3308_DAC_HPOUT_POP_SOUND_L_WORK (0x2 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) ++#define RK3308_DAC_HPOUT_POP_SOUND_L_INIT (0x1 << RK3308_DAC_HPOUT_POP_SOUND_L_SFT) + + /* RK3308_DAC_ANA_CON02 - REG: 0x0448 */ +-#define RK3308_DAC_R_DAC_WORK BIT(7) +-#define RK3308_DAC_R_DAC_EN BIT(6) +-#define RK3308_DAC_R_CLK_EN BIT(5) +-#define RK3308_DAC_R_REF_EN BIT(4) +-#define RK3308_DAC_L_DAC_WORK BIT(3) +-#define RK3308_DAC_L_DAC_EN BIT(2) +-#define RK3308_DAC_L_CLK_EN BIT(1) +-#define RK3308_DAC_L_REF_EN BIT(0) ++#define RK3308_DAC_R_DAC_WORK (0x1 << 7) ++#define RK3308_DAC_R_DAC_INIT (0x0 << 7) ++#define RK3308_DAC_R_DAC_EN (0x1 << 6) ++#define RK3308_DAC_R_DAC_DIS (0x0 << 6) ++#define RK3308_DAC_R_CLK_EN (0x1 << 5) ++#define RK3308_DAC_R_CLK_DIS (0x0 << 5) ++#define RK3308_DAC_R_REF_EN (0x1 << 4) ++#define RK3308_DAC_R_REF_DIS (0x0 << 4) ++#define RK3308_DAC_L_DAC_WORK (0x1 << 3) ++#define RK3308_DAC_L_DAC_INIT (0x0 << 3) ++#define RK3308_DAC_L_DAC_EN (0x1 << 2) ++#define RK3308_DAC_L_DAC_DIS (0x0 << 2) ++#define RK3308_DAC_L_CLK_EN (0x1 << 1) ++#define RK3308_DAC_L_CLK_DIS (0x0 << 1) ++#define RK3308_DAC_L_REF_EN (0x1 << 0) ++#define RK3308_DAC_L_REF_DIS (0x0 << 0) + + /* RK3308_DAC_ANA_CON03 - REG: 0x044c */ +-#define RK3308_DAC_R_HPOUT_WORK BIT(6) +-#define RK3308_DAC_R_HPOUT_EN BIT(5) +-#define RK3308_DAC_R_HPOUT_MUTE_SFT 4 +-#define RK3308_DAC_L_HPOUT_WORK BIT(2) +-#define RK3308_DAC_L_HPOUT_EN BIT(1) +-#define RK3308_DAC_L_HPOUT_MUTE_SFT 0 ++#define RK3308_DAC_R_HPOUT_WORK (0x1 << 6) ++#define RK3308_DAC_R_HPOUT_INIT (0x0 << 6) ++#define RK3308_DAC_R_HPOUT_EN (0x1 << 5) ++#define RK3308_DAC_R_HPOUT_DIS (0x0 << 5) ++#define RK3308_DAC_R_HPOUT_UNMUTE (0x1 << 4) ++#define RK3308_DAC_R_HPOUT_MUTE (0x0 << 4) ++#define RK3308_DAC_L_HPOUT_WORK (0x1 << 2) ++#define RK3308_DAC_L_HPOUT_INIT (0x0 << 2) ++#define RK3308_DAC_L_HPOUT_EN (0x1 << 1) ++#define RK3308_DAC_L_HPOUT_DIS (0x0 << 1) ++#define RK3308_DAC_L_HPOUT_UNMUTE (0x1 << 0) ++#define RK3308_DAC_L_HPOUT_MUTE (0x0 << 0) + + /* RK3308_DAC_ANA_CON04 - REG: 0x0450 */ +-#define RK3308_DAC_x_LINEOUT_GAIN_MAX 0x3 ++#define RK3308_DAC_R_LINEOUT_GAIN_MAX 0x3 + #define RK3308_DAC_R_LINEOUT_GAIN_SFT 6 + #define RK3308_DAC_R_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) + #define RK3308_DAC_R_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) + #define RK3308_DAC_R_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_R_LINEOUT_GAIN_SFT) + #define RK3308_DAC_R_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_R_LINEOUT_GAIN_SFT) + #define RK3308_DAC_R_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_R_LINEOUT_GAIN_SFT) +-#define RK3308_DAC_R_LINEOUT_MUTE_SFT 5 +-#define RK3308_DAC_R_LINEOUT_EN BIT(4) ++#define RK3308_DAC_R_LINEOUT_UNMUTE (0x1 << 5) ++#define RK3308_DAC_R_LINEOUT_MUTE (0x0 << 5) ++#define RK3308_DAC_R_LINEOUT_EN (0x1 << 4) ++#define RK3308_DAC_R_LINEOUT_DIS (0x0 << 4) ++#define RK3308_DAC_L_LINEOUT_GAIN_MAX 0x3 + #define RK3308_DAC_L_LINEOUT_GAIN_SFT 2 + #define RK3308_DAC_L_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) + #define RK3308_DAC_L_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) + #define RK3308_DAC_L_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_L_LINEOUT_GAIN_SFT) + #define RK3308_DAC_L_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_L_LINEOUT_GAIN_SFT) + #define RK3308_DAC_L_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_L_LINEOUT_GAIN_SFT) +-#define RK3308_DAC_L_LINEOUT_MUTE_SFT 1 +-#define RK3308_DAC_L_LINEOUT_EN BIT(0) ++#define RK3308_DAC_L_LINEOUT_UNMUTE (0x1 << 1) ++#define RK3308_DAC_L_LINEOUT_MUTE (0x0 << 1) ++#define RK3308_DAC_L_LINEOUT_EN (0x1 << 0) ++#define RK3308_DAC_L_LINEOUT_DIS (0x0 << 0) + + /* RK3308_DAC_ANA_CON05 - REG: 0x0454, step is 1.5db */ ++#define RK3308_DAC_L_HPOUT_GAIN_MAX 0x1e ++#define RK3308_DAC_L_HPOUT_GAIN_SFT 0 ++#define RK3308_DAC_L_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_PDB_4_5 (0x1d << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_PDB_3 (0x1c << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_PDB_1_5 (0x1b << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_0DB (0x1a << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_1_5 (0x19 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_3 (0x18 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_4_5 (0x17 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_6 (0x16 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_7_5 (0x15 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_9 (0x14 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_10_5 (0x13 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_12 (0x12 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_13_5 (0x11 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_15 (0x10 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_16_5 (0x0f << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_18 (0x0e << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_19_5 (0x0d << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_21 (0x0c << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_22_5 (0x0b << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_24 (0x0a << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_25_5 (0x09 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_27 (0x08 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_28_5 (0x07 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_30 (0x06 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_31_5 (0x05 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_33 (0x04 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_34_5 (0x03 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_36 (0x02 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++#define RK3308_DAC_L_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_L_HPOUT_GAIN_SFT) ++ + /* RK3308_DAC_ANA_CON06 - REG: 0x0458, step is 1.5db */ +-#define RK3308_DAC_x_HPOUT_GAIN_MAX 0x1e +-#define RK3308_DAC_x_HPOUT_GAIN_SFT 0 +-#define RK3308_DAC_x_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_x_HPOUT_GAIN_SFT) +-#define RK3308_DAC_x_HPOUT_GAIN_MIN (0x00 << RK3308_DAC_x_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_MAX 0x1e ++#define RK3308_DAC_R_HPOUT_GAIN_SFT 0 ++#define RK3308_DAC_R_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_PDB_6 (0x1e << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_PDB_4_5 (0x1d << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_PDB_3 (0x1c << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_PDB_1_5 (0x1b << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_0DB (0x1a << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_1_5 (0x19 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_3 (0x18 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_4_5 (0x17 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_6 (0x16 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_7_5 (0x15 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_9 (0x14 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_10_5 (0x13 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_12 (0x12 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_13_5 (0x11 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_15 (0x10 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_16_5 (0x0f << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_18 (0x0e << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_19_5 (0x0d << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_21 (0x0c << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_22_5 (0x0b << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_24 (0x0a << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_25_5 (0x09 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_27 (0x08 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_28_5 (0x07 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_30 (0x06 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_31_5 (0x05 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_33 (0x04 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_34_5 (0x03 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_36 (0x02 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_37_5 (0x01 << RK3308_DAC_R_HPOUT_GAIN_SFT) ++#define RK3308_DAC_R_HPOUT_GAIN_NDB_39 (0x00 << RK3308_DAC_R_HPOUT_GAIN_SFT) + + /* RK3308_DAC_ANA_CON07 - REG: 0x045c */ + #define RK3308_DAC_R_HPOUT_DRV_SFT 4 +@@ -534,36 +1007,51 @@ + #define RK3308_DAC_R_HPMIX_LINEIN (0x2 << RK3308_DAC_R_HPMIX_SEL_SFT) + #define RK3308_DAC_R_HPMIX_I2S (0x1 << RK3308_DAC_R_HPMIX_SEL_SFT) + #define RK3308_DAC_R_HPMIX_NONE (0x0 << RK3308_DAC_R_HPMIX_SEL_SFT) ++#define RK3308_DAC_R_HPMIX_GAIN_MIN 0x1 ++#define RK3308_DAC_R_HPMIX_GAIN_MAX 0x2 ++#define RK3308_DAC_R_HPMIX_GAIN_SFT 4 ++#define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) ++#define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) ++#define RK3308_DAC_R_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_R_HPMIX_GAIN_SFT) + #define RK3308_DAC_L_HPMIX_SEL_SFT 2 + #define RK3308_DAC_L_HPMIX_SEL_MSK (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) + #define RK3308_DAC_L_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) + #define RK3308_DAC_L_HPMIX_LINEIN (0x2 << RK3308_DAC_L_HPMIX_SEL_SFT) + #define RK3308_DAC_L_HPMIX_I2S (0x1 << RK3308_DAC_L_HPMIX_SEL_SFT) + #define RK3308_DAC_L_HPMIX_NONE (0x0 << RK3308_DAC_L_HPMIX_SEL_SFT) +-#define RK3308_DAC_x_HPMIX_GAIN_MIN 0x1 /* 0x0 and 0x3 are reserved */ +-#define RK3308_DAC_x_HPMIX_GAIN_MAX 0x2 +-#define RK3308_DAC_R_HPMIX_GAIN_SFT 4 +-#define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) +-#define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) +-#define RK3308_DAC_R_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_R_HPMIX_GAIN_SFT) ++#define RK3308_DAC_L_HPMIX_GAIN_MIN 0x1 ++#define RK3308_DAC_L_HPMIX_GAIN_MAX 0x2 + #define RK3308_DAC_L_HPMIX_GAIN_SFT 0 + #define RK3308_DAC_L_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_L_HPMIX_GAIN_SFT) + #define RK3308_DAC_L_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_L_HPMIX_GAIN_SFT) + #define RK3308_DAC_L_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_L_HPMIX_GAIN_SFT) + + /* RK3308_DAC_ANA_CON13 - REG: 0x0474 */ +-#define RK3308_DAC_R_HPMIX_UNMUTE BIT(6) +-#define RK3308_DAC_R_HPMIX_WORK BIT(5) +-#define RK3308_DAC_R_HPMIX_EN BIT(4) +-#define RK3308_DAC_L_HPMIX_UNMUTE BIT(2) +-#define RK3308_DAC_L_HPMIX_WORK BIT(1) +-#define RK3308_DAC_L_HPMIX_EN BIT(0) ++#define RK3308_DAC_R_HPMIX_UNMUTE (0x1 << 6) ++#define RK3308_DAC_R_HPMIX_MUTE (0x0 << 6) ++#define RK3308_DAC_R_HPMIX_WORK (0x1 << 5) ++#define RK3308_DAC_R_HPMIX_INIT (0x0 << 5) ++#define RK3308_DAC_R_HPMIX_EN (0x1 << 4) ++#define RK3308_DAC_R_HPMIX_DIS (0x0 << 4) ++#define RK3308_DAC_L_HPMIX_UNMUTE (0x1 << 2) ++#define RK3308_DAC_L_HPMIX_MUTE (0x0 << 2) ++#define RK3308_DAC_L_HPMIX_WORK (0x1 << 1) ++#define RK3308_DAC_L_HPMIX_INIT (0x0 << 1) ++#define RK3308_DAC_L_HPMIX_EN (0x1 << 0) ++#define RK3308_DAC_L_HPMIX_DIS (0x0 << 0) + + /* RK3308_DAC_ANA_CON14 - REG: 0x0478 */ + #define RK3308_DAC_VCM_LINEOUT_EN (0x1 << 4) ++#define RK3308_DAC_VCM_LINEOUT_DIS (0x0 << 4) + #define RK3308_DAC_CURRENT_CHARGE_SFT 0 + #define RK3308_DAC_CURRENT_CHARGE_MSK (0xf << RK3308_DAC_CURRENT_CHARGE_SFT) + ++/* ++ * 1: Choose the current I ++ * 0: Don't choose the current I ++ */ ++#define RK3308_DAC_SEL_I(x) (x & 0xf) ++ + /* RK3308_DAC_ANA_CON15 - REG: 0x047C */ + #define RK3308_DAC_LINEOUT_POP_SOUND_R_SFT 4 + #define RK3308_DAC_LINEOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) +@@ -576,4 +1064,6 @@ + #define RK3308_DAC_L_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) + #define RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) + ++#define RK3308_HIFI 0x0 ++ + #endif /* __RK3308_CODEC_H__ */ +diff --git a/sound/soc/codecs/rk3308_codec_provider.h b/sound/soc/codecs/rk3308_codec_provider.h +new file mode 100644 +index 000000000000..34c1ef86a507 +--- /dev/null ++++ b/sound/soc/codecs/rk3308_codec_provider.h +@@ -0,0 +1,28 @@ ++/* ++ * rk3308_codec_provider.h -- RK3308 ALSA Soc Audio Driver ++ * ++ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++#ifndef __RK3308_CODEC_PROVIDER_H__ ++#define __RK3308_CODEC_PROVIDER_H__ ++ ++#ifdef CONFIG_SND_SOC_RK3308 ++extern void (*rk3308_codec_set_jack_detect_cb)(struct snd_soc_component *component, ++ struct snd_soc_jack *hpdet_jack); ++#endif ++ ++#endif /* __RK3308_CODEC_PROVIDER_H__ */ +-- +2.43.0 + diff --git a/patch/kernel/archive/rockchip64-6.13/rk3308-enable-acodec-verb.patch b/patch/kernel/archive/rockchip64-6.13/rk3308-enable-acodec-verb.patch deleted file mode 100644 index e2a7c4562..000000000 --- a/patch/kernel/archive/rockchip64-6.13/rk3308-enable-acodec-verb.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c -index 8b51e87a1711..f3c8716215a8 100644 ---- a/sound/soc/codecs/rk3308_codec.c -+++ b/sound/soc/codecs/rk3308_codec.c -@@ -854,7 +854,7 @@ static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) - break; - case 0x3308: - rk3308->codec_ver = ACODEC_VERSION_B; -- return dev_err_probe(rk3308->dev, -EINVAL, "Chip version B not supported\n"); -+ break; - case 0x3308c: - rk3308->codec_ver = ACODEC_VERSION_C; - break;