From 5a2779fa42a67fdb49aae81b1cf7b050e1140f6e Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 26 Sep 2022 17:44:40 +0800 Subject: [PATCH] ASoC: codecs: Add driver support for rk730 This patch add support for RK730 audio codec. Signed-off-by: Sugar Zhang Change-Id: Ia3d883d10cb8a0418f5f4313154f593cc90a1700 --- sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rk730.c | 971 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rk730.h | 239 ++++++++++ 4 files changed, 1217 insertions(+) create mode 100644 sound/soc/codecs/rk730.c create mode 100644 sound/soc/codecs/rk730.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 06107337b377..6f53c96779ff 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -161,6 +161,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RK3228 imply SND_SOC_RK3308 imply SND_SOC_RK3328 + imply SND_SOC_RK730 imply SND_SOC_RK817 imply SND_SOC_RT274 imply SND_SOC_RT286 @@ -1101,6 +1102,10 @@ config SND_SOC_RK3328 tristate "Rockchip RK3328 audio CODEC" select REGMAP_MMIO +config SND_SOC_RK730 + tristate "Rockchip RK730 CODEC" + select REGMAP_I2C + config SND_SOC_RK817 tristate "Rockchip RK817 CODEC" depends on MFD_RK808 diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 66305fddd99d..d7e238d7091d 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -168,6 +168,7 @@ snd-soc-rk312x-objs := rk312x_codec.o snd-soc-rk3228-objs := rk3228_codec.o snd-soc-rk3308-objs := rk3308_codec.o snd-soc-rk3328-objs := rk3328_codec.o +snd-soc-rk730-objs := rk730.o snd-soc-rk817-objs := rk817_codec.o snd-soc-rk-codec-digital-objs := rk_codec_digital.o snd-soc-rl6231-objs := rl6231.o @@ -492,6 +493,7 @@ obj-$(CONFIG_SND_SOC_RK312X) += snd-soc-rk312x.o obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o +obj-$(CONFIG_SND_SOC_RK730) += snd-soc-rk730.o obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o obj-$(CONFIG_SND_SOC_RK_CODEC_DIGITAL) += snd-soc-rk-codec-digital.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o diff --git a/sound/soc/codecs/rk730.c b/sound/soc/codecs/rk730.c new file mode 100644 index 000000000000..db25d092d2b3 --- /dev/null +++ b/sound/soc/codecs/rk730.c @@ -0,0 +1,971 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * rk730.c -- RK730 ALSA SoC Audio driver + * + * Copyright (C) 2022 Rockchip Electronics Co.,Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rk730.h" + +enum rk730_mix_mode { + RK730_MIX_MODE_1_PATH, + RK730_MIX_MODE_2_PATHS, + RK730_MIX_MODE_3_PATHS, +}; + +enum rk730_chop_freq { + RK730_CHOP_FREQ_NONE, + RK730_CHOP_FREQ_200KHZ, + RK730_CHOP_FREQ_400KHZ, + RK730_CHOP_FREQ_800KHZ, +}; + +struct rk730_priv { + struct regmap *regmap; + struct clk *mclk; + atomic_t mix_mode; +}; + +/* ADC Digital Volume */ +static const DECLARE_TLV_DB_SCALE(adc_dig_tlv, -95625, 375, 0); +/* DAC Digital Volume */ +static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -95625, 375, 0); +/* D2S Volume */ +static const DECLARE_TLV_DB_SCALE(d2s_tlv, -1800, 300, 0); +/* ADC Volume */ +static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 300, 0); +/* MUX Volume */ +static const DECLARE_TLV_DB_SCALE(mux_tlv, -600, 600, 0); +/* MIX Buf Volume */ +static const DECLARE_TLV_DB_SCALE(mix_buf_tlv, -1800, 300, 0); +/* HP Volume */ +static const DECLARE_TLV_DB_SCALE(hp_tlv, 0, 300, 0); +/* LINEOUT Volume */ +static const DECLARE_TLV_DB_SCALE(lineout_tlv, 0, 300, 0); +/* MIC Boost Volume */ +static const DECLARE_TLV_DB_RANGE(micboost_tlv, + 0, 2, TLV_DB_SCALE_ITEM(0, 600, 0), + 3, 4, TLV_DB_SCALE_ITEM(2400, 1200, 0), + 5, 7, TLV_DB_SCALE_ITEM(4200, 600, 0), + 8, 8, TLV_DB_SCALE_ITEM(-300, 0, 0), + 16, 16, TLV_DB_SCALE_ITEM(-600, 0, 0), + 24, 24, TLV_DB_SCALE_ITEM(-900, 0, 0) +); + +static const char * const mux_out_l_text[] = { "DIFF", "MIC1N", "MIC2N" }; +static const char * const mux_out_r_text[] = { "DIFF", "MIC2P", "MIC1P" }; +static const char * const mux_input_l_text[] = { "DIFF", "VINP1", "VINN1" }; +static const char * const mux_input_r_text[] = { "DIFF", "VINP2", "VINN2" }; + +static SOC_ENUM_SINGLE_DECL(mux_out_l_enum, RK730_MUXER_0, 2, mux_out_l_text); +static SOC_ENUM_SINGLE_DECL(mux_out_r_enum, RK730_MUXER_0, 6, mux_out_r_text); +static SOC_ENUM_SINGLE_DECL(mux_input_l_enum, RK730_ADC_PGA_BLOCK_0, + 4, mux_input_l_text); +static SOC_ENUM_SINGLE_DECL(mux_input_r_enum, RK730_ADC_PGA_BLOCK_1, + 4, mux_input_r_text); + +static const struct snd_kcontrol_new mux_out_l = + SOC_DAPM_ENUM("Left Out Mux", mux_out_l_enum); +static const struct snd_kcontrol_new mux_out_r = + SOC_DAPM_ENUM("Right Out Mux", mux_out_r_enum); +static const struct snd_kcontrol_new mux_input_l = + SOC_DAPM_ENUM("Left Input Mux", mux_input_l_enum); +static const struct snd_kcontrol_new mux_input_r = + SOC_DAPM_ENUM("Right Input Mux", mux_input_r_enum); + +static const struct snd_kcontrol_new mix_ctls[] = { + SOC_DAPM_SINGLE("Left Out Mux Switch", RK730_MUXER_0, 0, 1, 1), + SOC_DAPM_SINGLE("Right Out Mux Switch", RK730_MUXER_0, 4, 1, 1), +}; + +static const char * const adc_hpf_cutoff_text[] = { + "3.79Hz", "60Hz", "243Hz", "493Hz", +}; + +static const char * const dac_hpf_cutoff_text[] = { + "80Hz", "100Hz", "120Hz", "140Hz", +}; + +static SOC_ENUM_SINGLE_DECL(adc_hpf_cutoff_enum, RK730_DADC_HPF, + 4, adc_hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(dac_hpf_cutoff_enum, RK730_DDAC_MUTE_MIXCTL, + 5, dac_hpf_cutoff_text); + +static const char * const chop_freq_text[] = { + "Disabled", "200kHz", "400kHz", "800kHz", +}; + +static SOC_ENUM_SINGLE_DECL(dac_ref_buf_chop_freq_enum, RK730_HK_TOP_1, + 6, chop_freq_text); +static SOC_ENUM_SINGLE_DECL(mic_chop_freq_enum, RK730_MIC_BOOST_3, + 6, chop_freq_text); +static SOC_ENUM_SINGLE_DECL(adc_pga_chop_freq_enum, RK730_ADC_PGA_BLOCK_1, + 6, chop_freq_text); +static SOC_ENUM_SINGLE_DECL(mux_out_chop_freq_enum, RK730_MUXER_1, + 0, chop_freq_text); +static SOC_ENUM_SINGLE_DECL(mix_chop_freq_enum, RK730_MIXER_2, + 6, chop_freq_text); +static SOC_ENUM_SINGLE_DECL(hp_lo_chop_freq_enum, RK730_HP_1, + 5, chop_freq_text); + +static const char * const micbias_volt_text[] = { + "2.0v", "2.2v", "2.5v", "2.8v", +}; + +static const char * const charge_pump_volt_text[] = { + "2.1v", "2.3v", "2.5v", "2.7v", +}; + +static SOC_ENUM_SINGLE_DECL(micbias_volt_enum, RK730_MIC_BIAS, + 2, micbias_volt_text); +static SOC_ENUM_SINGLE_DECL(charge_pump_volt_enum, RK730_CHARGE_PUMP, + 1, charge_pump_volt_text); + +static int rk730_adc_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int val = snd_soc_component_read(component, mc->reg); + unsigned int sign = snd_soc_component_read(component, RK730_DADC_SR_ACL); + unsigned int mask = (1 << fls(mc->max)) - 1; + unsigned int shift = mc->shift; + int mid = mc->max / 2; + int uv; + + uv = (val >> shift) & mask; + sign &= RK730_DADC_SR_ACL_VOLL_POL_MASK; + if (sign) + uv = mid + uv; + else + uv = mid - uv; + + ucontrol->value.integer.value[0] = uv; + ucontrol->value.integer.value[1] = uv; + + return 0; +} + +static int rk730_adc_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int reg = mc->reg; + unsigned int rreg = mc->rreg; + unsigned int shift = mc->shift; + unsigned int mask = (1 << fls(mc->max)) - 1; + unsigned int val, val_mask, sign, sign_mask; + int uv = ucontrol->value.integer.value[0]; + int min = mc->min; + int mid = mc->max / 2; + + sign_mask = RK730_DADC_SR_ACL_VOLL_POL_MASK | RK730_DADC_SR_ACL_VOLR_POL_MASK; + + if (uv > mid) { + sign = RK730_DADC_SR_ACL_VOLL_POS | RK730_DADC_SR_ACL_VOLR_POS; + uv = uv - mid; + } else { + sign = RK730_DADC_SR_ACL_VOLL_NEG | RK730_DADC_SR_ACL_VOLR_NEG; + uv = mid - uv; + } + + val = ((uv + min) & mask); + val_mask = mask << shift; + val = val << shift; + + snd_soc_component_update_bits(component, reg, val_mask, val); + snd_soc_component_update_bits(component, rreg, val_mask, val); + snd_soc_component_update_bits(component, RK730_DADC_SR_ACL, sign_mask, sign); + + return 1; +} + +static int rk730_dac_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int val = snd_soc_component_read(component, mc->reg); + unsigned int sign = snd_soc_component_read(component, RK730_DDAC_SR_LMT); + unsigned int mask = (1 << fls(mc->max)) - 1; + unsigned int shift = mc->shift; + int mid = mc->max / 2; + int uv; + + uv = (val >> shift) & mask; + sign &= RK730_DDAC_SR_LMT_VOLL_POL_MASK; + if (sign) + uv = mid + uv; + else + uv = mid - uv; + + ucontrol->value.integer.value[0] = uv; + ucontrol->value.integer.value[1] = uv; + + return 0; +} + +static int rk730_dac_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int reg = mc->reg; + unsigned int rreg = mc->rreg; + unsigned int shift = mc->shift; + unsigned int mask = (1 << fls(mc->max)) - 1; + unsigned int val, val_mask, sign, sign_mask; + int uv = ucontrol->value.integer.value[0]; + int min = mc->min; + int mid = mc->max / 2; + + sign_mask = RK730_DDAC_SR_LMT_VOLL_POL_MASK | RK730_DDAC_SR_LMT_VOLR_POL_MASK; + + if (uv > mid) { + sign = RK730_DDAC_SR_LMT_VOLL_POS | RK730_DDAC_SR_LMT_VOLR_POS; + uv = uv - mid; + } else { + sign = RK730_DDAC_SR_LMT_VOLL_NEG | RK730_DDAC_SR_LMT_VOLR_NEG; + uv = mid - uv; + } + + val = ((uv + min) & mask); + val_mask = mask << shift; + val = val << shift; + + snd_soc_component_update_bits(component, reg, val_mask, val); + snd_soc_component_update_bits(component, rreg, val_mask, val); + snd_soc_component_update_bits(component, RK730_DDAC_SR_LMT, sign_mask, sign); + + return 1; +} + +static int rk730_cp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (SND_SOC_DAPM_EVENT_ON(event)) + usleep_range(5000, 5100); + + return 0; +} + +static int rk730_pll_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + if (SND_SOC_DAPM_EVENT_ON(event)) + snd_soc_component_write(component, RK730_SYSPLL_0, 0x00); + else + snd_soc_component_write(component, RK730_SYSPLL_0, 0xff); + + return 0; +} + +static int rk730_adc_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_component_update_bits(component, RK730_ADC_0, + RK730_ADC_0_DEM_EN_MASK, + RK730_ADC_0_DEM_EN); + snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE, + RK730_DTOP_DIGEN_CLKE_ADC_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_I2STX_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_ADC_EN_MASK | + RK730_DTOP_DIGEN_CLKE_I2STX_EN_MASK, + RK730_DTOP_DIGEN_CLKE_ADC_CKE_EN | + RK730_DTOP_DIGEN_CLKE_I2STX_CKE_EN | + RK730_DTOP_DIGEN_CLKE_ADC_EN | + RK730_DTOP_DIGEN_CLKE_I2STX_EN); + usleep_range(20000, 21000); + snd_soc_component_update_bits(component, RK730_DI2S_TXCR_3_TXCMD, + RK730_DI2S_TXCR_3_TXCMD_TXS_MASK, + RK730_DI2S_TXCR_3_TXCMD_TXS_EN); + } else { + snd_soc_component_update_bits(component, RK730_DI2S_TXCR_3_TXCMD, + RK730_DI2S_TXCR_3_TXCMD_TXS_MASK, + RK730_DI2S_TXCR_3_TXCMD_TXS_DIS); + snd_soc_component_update_bits(component, RK730_ADC_0, + RK730_ADC_0_DEM_EN_MASK, + RK730_ADC_0_DEM_DIS); + snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE, + RK730_DTOP_DIGEN_CLKE_ADC_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_I2STX_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_ADC_EN_MASK | + RK730_DTOP_DIGEN_CLKE_I2STX_EN_MASK, + RK730_DTOP_DIGEN_CLKE_ADC_CKE_DIS | + RK730_DTOP_DIGEN_CLKE_I2STX_CKE_DIS | + RK730_DTOP_DIGEN_CLKE_ADC_DIS | + RK730_DTOP_DIGEN_CLKE_I2STX_DIS); + } + + return 0; +} + +static int rk730_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + if (SND_SOC_DAPM_EVENT_ON(event)) { + snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE, + RK730_DTOP_DIGEN_CLKE_DAC_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_DAC_EN_MASK | + RK730_DTOP_DIGEN_CLKE_I2SRX_EN_MASK, + RK730_DTOP_DIGEN_CLKE_DAC_CKE_EN | + RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_EN | + RK730_DTOP_DIGEN_CLKE_DAC_EN | + RK730_DTOP_DIGEN_CLKE_I2SRX_EN); + snd_soc_component_update_bits(component, RK730_DI2S_RXCMD_TSD, + RK730_DI2S_RXCMD_TSD_RXS_MASK, + RK730_DI2S_RXCMD_TSD_RXS_EN); + } else { + snd_soc_component_update_bits(component, RK730_DI2S_RXCMD_TSD, + RK730_DI2S_RXCMD_TSD_RXS_MASK, + RK730_DI2S_RXCMD_TSD_RXS_DIS); + snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE, + RK730_DTOP_DIGEN_CLKE_DAC_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_MASK | + RK730_DTOP_DIGEN_CLKE_DAC_EN_MASK | + RK730_DTOP_DIGEN_CLKE_I2SRX_EN_MASK, + RK730_DTOP_DIGEN_CLKE_DAC_CKE_DIS | + RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_DIS | + RK730_DTOP_DIGEN_CLKE_DAC_DIS | + RK730_DTOP_DIGEN_CLKE_I2SRX_DIS); + } + + return 0; +} + +static int rk730_mux_out_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component); + unsigned int val; + + if (SND_SOC_DAPM_EVENT_ON(event)) + val = atomic_inc_return(&rk730->mix_mode); + else + val = atomic_dec_return(&rk730->mix_mode); + + snd_soc_component_update_bits(component, RK730_MIXER_2, + RK730_MIXER_2_MIX_R_MODE_MASK | + RK730_MIXER_2_MIX_L_MODE_MASK, + RK730_MIXER_2_MIX_R_MODE(val) | + RK730_MIXER_2_MIX_L_MODE(val)); + return 0; +} + +static const struct snd_kcontrol_new rk730_snd_controls[] = { + SOC_DOUBLE_R_TLV("ADC Volume", RK730_ADC_PGA_BLOCK_0, RK730_ADC_PGA_BLOCK_1, + 1, 0x7, 1, adc_tlv), + SOC_DOUBLE_R_TLV("D2S Volume", RK730_DAC_1, RK730_DAC_2, + 1, 0x6, 1, d2s_tlv), + + SOC_DOUBLE_R_TLV("MIC1 Boost Volume", RK730_MIC_BOOST_0, RK730_MIC_BOOST_1, + 1, 0x18, 0, micboost_tlv), + SOC_DOUBLE_R_TLV("MIC2 Boost Volume", RK730_MIC_BOOST_2, RK730_MIC_BOOST_3, + 1, 0x18, 0, micboost_tlv), + + SOC_DOUBLE_TLV("Out Mux Volume", RK730_MUXER_0, 1, 5, 0x1, 0, mux_tlv), + + SOC_SINGLE_TLV("Left Out Mux -> Left Out Mixer Volume", + RK730_MIXER_0, 1, 0x6, 1, mix_buf_tlv), + SOC_SINGLE_TLV("Left Out Mux -> Right Out Mixer Volume", + RK730_MIXER_0, 5, 0x6, 1, mix_buf_tlv), + SOC_SINGLE_TLV("Right Out Mux -> Left Out Mixer Volume", + RK730_MIXER_1, 1, 0x6, 1, mix_buf_tlv), + SOC_SINGLE_TLV("Right Out Mux -> Right Out Mixer Volume", + RK730_MIXER_1, 5, 0x6, 1, mix_buf_tlv), + + SOC_SINGLE_TLV("HP Volume", RK730_HP_0, 6, 0x3, 0, hp_tlv), + SOC_SINGLE_TLV("Line Out Volume", RK730_LINEOUT_1, 2, 0x3, 0, lineout_tlv), + + SOC_DOUBLE_R_EXT_TLV("ADC Digital Volume", + RK730_DADC_VOLL, RK730_DADC_VOLR, 0, 0x1fe, 0, + rk730_adc_vol_get, + rk730_adc_vol_put, + adc_dig_tlv), + SOC_DOUBLE_R_EXT_TLV("DAC Digital Volume", + RK730_DDAC_VOLL, RK730_DDAC_VOLR, 0, 0x1fe, 0, + rk730_dac_vol_get, + rk730_dac_vol_put, + dac_dig_tlv), + + SOC_ENUM("ADC HPF Cutoff", adc_hpf_cutoff_enum), + SOC_ENUM("DAC HPF Cutoff", dac_hpf_cutoff_enum), + SOC_ENUM("DAC Ref Buf Chop Freq", dac_ref_buf_chop_freq_enum), + SOC_ENUM("MIC Chop Freq", mic_chop_freq_enum), + SOC_ENUM("ADC PGA Chop Freq", adc_pga_chop_freq_enum), + SOC_ENUM("Out Mux Chop Freq", mux_out_chop_freq_enum), + SOC_ENUM("Mixer Chop Freq", mix_chop_freq_enum), + SOC_ENUM("HP / Lineout Chop Freq", hp_lo_chop_freq_enum), + SOC_ENUM("Mic Bias Volt", micbias_volt_enum), + SOC_ENUM("Charge Pump Volt", charge_pump_volt_enum), + + SOC_SINGLE("ADCL HPF Switch", RK730_DADC_HPF, 7, 1, 0), + SOC_SINGLE("ADCR HPF Switch", RK730_DADC_HPF, 6, 1, 0), + SOC_SINGLE("DAC HPF Switch", RK730_DDAC_MUTE_MIXCTL, 7, 1, 0), + SOC_SINGLE("ADC Volume Bypass Switch", RK730_DTOP_VUCTL, 7, 1, 0), + SOC_SINGLE("DAC Volume Bypass Switch", RK730_DTOP_VUCTL, 6, 1, 0), + SOC_SINGLE("ADC Fade Switch", RK730_DTOP_VUCTL, 5, 1, 0), + SOC_SINGLE("DAC Fade Switch", RK730_DTOP_VUCTL, 4, 1, 0), + SOC_SINGLE("ADC Zero Crossing Switch", RK730_DTOP_VUCTL, 1, 1, 0), + SOC_SINGLE("DAC Zero Crossing Switch", RK730_DTOP_VUCTL, 0, 1, 0), + SOC_SINGLE("MIC1N / MIC2P Exchanged Switch", RK730_MIC_BOOST_2, 7, 1, 0), +}; + +static const struct snd_soc_dapm_widget rk730_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY_S("ANA LDO", 0, RK730_LDO, 7, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("OSC CLK", 1, RK730_HK_TOP_2, 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("VAG BUF", 1, RK730_HK_TOP_2, 2, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADC BUF", 1, RK730_HK_TOP_2, 1, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DAC BUF", 1, RK730_HK_TOP_2, 0, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("MICBIAS", 1, RK730_MIC_BIAS, 0, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, RK730_CHARGE_PUMP, 0, 0, + rk730_cp_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY_S("PLL", 2, SND_SOC_NOPM, 0, 0, rk730_pll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("DAC Bias", 2, RK730_DAC_0, 2, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("HP Bias", 2, RK730_HP_0, 5, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("Line Out Bias", 2, RK730_LINEOUT_1, 7, 1, NULL, 0), + + SND_SOC_DAPM_ADC_E("ADCL", "HiFi Capture", RK730_ADC_0, 0, 1, + rk730_adc_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADCR", "HiFi Capture", RK730_ADC_0, 1, 1, + rk730_adc_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_DAC_E("DACL", "HiFi Playback", RK730_DAC_0, 0, 1, + rk730_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_DAC_E("DACR", "HiFi Playback", RK730_DAC_0, 1, 1, + rk730_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_PGA("ADCL PGA", RK730_ADC_PGA_BLOCK_0, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("ADCR PGA", RK730_ADC_PGA_BLOCK_1, 0, 1, NULL, 0), + + SND_SOC_DAPM_PGA("D2SL", RK730_DAC_1, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("D2SR", RK730_DAC_2, 0, 1, NULL, 0), + + SND_SOC_DAPM_PGA("MIC1P", RK730_MIC_BOOST_0, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("MIC1N", RK730_MIC_BOOST_1, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("MIC2P", RK730_MIC_BOOST_2, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("MIC2N", RK730_MIC_BOOST_3, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("DIFFL", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DIFFR", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_PGA("HP Out", RK730_HP_0, 2, 1, NULL, 0), + SND_SOC_DAPM_PGA("HP Out Stage", RK730_HP_0, 3, 1, NULL, 0), + SND_SOC_DAPM_PGA("Line Out", RK730_LINEOUT_0, 2, 1, NULL, 0), + SND_SOC_DAPM_PGA("Line Out Stage", RK730_LINEOUT_0, 3, 1, NULL, 0), + + SND_SOC_DAPM_MUX_E("Left Out Mux", SND_SOC_NOPM, 0, 0, &mux_out_l, + rk730_mux_out_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX_E("Right Out Mux", SND_SOC_NOPM, 0, 0, &mux_out_r, + rk730_mux_out_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &mux_input_l), + SND_SOC_DAPM_MUX("Right Input Mux", SND_SOC_NOPM, 0, 0, &mux_input_r), + + SND_SOC_DAPM_MIXER("Left Out Mixer", RK730_MIXER_2, 0, 1, + mix_ctls, ARRAY_SIZE(mix_ctls)), + SND_SOC_DAPM_MIXER("Right Out Mixer", RK730_MIXER_2, 3, 1, + mix_ctls, ARRAY_SIZE(mix_ctls)), + + SND_SOC_DAPM_OUTPUT("HPL"), + SND_SOC_DAPM_OUTPUT("HPR"), + SND_SOC_DAPM_OUTPUT("LINEOUTL"), + SND_SOC_DAPM_OUTPUT("LINEOUTR"), + + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), +}; + +static const struct snd_soc_dapm_route rk730_dapm_routes[] = { + { "DACL", NULL, "ANA LDO" }, + { "DACR", NULL, "ANA LDO" }, + { "DACL", NULL, "OSC CLK" }, + { "DACR", NULL, "OSC CLK" }, + { "DACL", NULL, "VAG BUF" }, + { "DACR", NULL, "VAG BUF" }, + { "DACL", NULL, "DAC BUF" }, + { "DACR", NULL, "DAC BUF" }, + { "DACL", NULL, "PLL" }, + { "DACR", NULL, "PLL" }, + { "DACL", NULL, "DAC Bias" }, + { "DACR", NULL, "DAC Bias" }, + + { "D2SL", NULL, "DACL" }, + { "D2SR", NULL, "DACR" }, + + { "Left Out Mixer", NULL, "D2SL" }, + { "Left Out Mixer", "Left Out Mux Switch", "Left Out Mux" }, + { "Left Out Mixer", "Right Out Mux Switch", "Right Out Mux" }, + { "Right Out Mixer", NULL, "D2SR" }, + { "Right Out Mixer", "Left Out Mux Switch", "Left Out Mux" }, + { "Right Out Mixer", "Right Out Mux Switch", "Right Out Mux" }, + + { "Left Out Mux", "DIFF", "DIFFL" }, + { "Left Out Mux", "MIC1N", "MIC1N" }, + { "Left Out Mux", "MIC2N", "MIC2N" }, + + { "Right Out Mux", "DIFF", "DIFFR" }, + { "Right Out Mux", "MIC1P", "MIC1P" }, + { "Right Out Mux", "MIC2P", "MIC2P" }, + + { "HP Out", NULL, "HP Bias" }, + { "HP Out", NULL, "HP Bias" }, + { "Line Out", NULL, "Line Out Bias" }, + + { "HP Out", NULL, "Left Out Mixer" }, + { "HP Out", NULL, "Right Out Mixer" }, + { "Line Out", NULL, "Left Out Mixer" }, + { "Line Out", NULL, "Right Out Mixer" }, + + { "HP Out Stage", NULL, "HP Out" }, + { "Line Out Stage", NULL, "Line Out" }, + + { "HPL", NULL, "HP Out Stage" }, + { "HPR", NULL, "HP Out Stage" }, + { "HPL", NULL, "Charge Pump" }, + { "HPR", NULL, "Charge Pump" }, + + { "LINEOUTL", NULL, "Line Out Stage" }, + { "LINEOUTR", NULL, "Line Out Stage" }, + { "LINEOUTL", NULL, "Charge Pump" }, + { "LINEOUTR", NULL, "Charge Pump" }, + + { "ADCL", NULL, "ANA LDO" }, + { "ADCR", NULL, "ANA LDO" }, + { "ADCL", NULL, "OSC CLK" }, + { "ADCR", NULL, "OSC CLK" }, + { "ADCL", NULL, "ADC BUF" }, + { "ADCR", NULL, "ADC BUF" }, + { "ADCL", NULL, "VAG BUF" }, + { "ADCR", NULL, "VAG BUF" }, + { "ADCL", NULL, "PLL" }, + { "ADCR", NULL, "PLL" }, + + { "ADCL", NULL, "ADCL PGA" }, + { "ADCR", NULL, "ADCR PGA" }, + { "ADCL PGA", NULL, "Left Input Mux" }, + { "ADCR PGA", NULL, "Right Input Mux" }, + + { "Left Input Mux", "DIFF", "DIFFL" }, + { "Left Input Mux", "VINP1", "MIC1P" }, + { "Left Input Mux", "VINN1", "MIC1N" }, + { "Right Input Mux", "DIFF", "DIFFR" }, + { "Right Input Mux", "VINP2", "MIC2P" }, + { "Right Input Mux", "VINN2", "MIC2N" }, + + { "DIFFL", NULL, "MIC1P" }, + { "DIFFL", NULL, "MIC1N" }, + { "DIFFR", NULL, "MIC2P" }, + { "DIFFR", NULL, "MIC2N" }, + + { "MIC1P", NULL, "MIC1" }, + { "MIC1N", NULL, "MIC1" }, + { "MIC2P", NULL, "MIC2" }, + { "MIC2N", NULL, "MIC2" }, + + { "MIC1", NULL, "MICBIAS" }, + { "MIC2", NULL, "MICBIAS" }, +}; + +static unsigned int samplerate_to_bit(unsigned int samplerate) +{ + switch (samplerate) { + case 8000: + case 11025: + case 12000: + return 0; + case 16000: + case 22050: + case 24000: + return 1; + case 32000: + case 44100: + case 48000: + return 2; + case 64000: + case 88200: + case 96000: + return 3; + case 128000: + case 176400: + case 192000: + return 4; + default: + return 2; + } +} + +static int rk730_dai_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; + unsigned int width, rate; + + width = min(params_width(params), 24); + rate = samplerate_to_bit(params_rate(params)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_component_update_bits(component, RK730_DI2S_RXCR_2, + RK730_DI2S_XCR2_VDW_MASK, + RK730_DI2S_XCR2_VDW(width)); + snd_soc_component_update_bits(component, RK730_DDAC_SR_LMT, + RK730_DDAC_SR_LMT_SRT_MASK, + RK730_DDAC_SR_LMT_SRT(rate)); + } else { + snd_soc_component_update_bits(component, RK730_DI2S_TXCR_2, + RK730_DI2S_XCR2_VDW_MASK, + RK730_DI2S_XCR2_VDW(width)); + snd_soc_component_update_bits(component, RK730_DADC_SR_ACL, + RK730_DADC_SR_ACL_SRT_MASK, + RK730_DADC_SR_ACL_SRT(rate)); + } + + return 0; +} + +static int rk730_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + snd_soc_component_update_bits(component, RK730_DI2S_CKM, + RK730_DI2S_CKM_MST_MASK, + RK730_DI2S_CKM_MST_SLAVE); + break; + case SND_SOC_DAIFMT_CBM_CFM: + snd_soc_component_update_bits(component, RK730_DI2S_CKM, + RK730_DI2S_CKM_MST_MASK, + RK730_DI2S_CKM_MST_MASTER); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk730_dai_mute(struct snd_soc_dai *codec_dai, int mute, int direction) +{ + struct snd_soc_component *component = codec_dai->component; + + if (mute) + snd_soc_component_update_bits(component, RK730_DDAC_MUTE_MIXCTL, + RK730_DDAC_MUTE_MIXCTL_MUTE_MASK, + RK730_DDAC_MUTE_MIXCTL_MUTE); + else + snd_soc_component_update_bits(component, RK730_DDAC_MUTE_MIXCTL, + RK730_DDAC_MUTE_MIXCTL_MUTE_MASK, + RK730_DDAC_MUTE_MIXCTL_UNMUTE); + + return 0; +} + +static int rk730_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* + * SND_SOC_BIAS_PREPARE is called while preparing for a + * transition to ON or away from ON. If current bias_level + * is SND_SOC_BIAS_ON, then it is preparing for a transition + * away from ON. Disable the clock in that case, otherwise + * enable it. + */ + if (!IS_ERR(rk730->mclk)) { + if (snd_soc_component_get_bias_level(component) == + SND_SOC_BIAS_ON) + clk_disable_unprepare(rk730->mclk); + else + clk_prepare_enable(rk730->mclk); + } + break; + + case SND_SOC_BIAS_STANDBY: + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) + regcache_sync(rk730->regmap); + break; + + case SND_SOC_BIAS_OFF: + regcache_mark_dirty(rk730->regmap); + break; + } + return 0; +} + +#define RK730_RATES SNDRV_PCM_RATE_8000_192000 +#define RK730_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static const struct snd_soc_dai_ops rk730_dai_ops = { + .set_fmt = rk730_dai_set_fmt, + .hw_params = rk730_dai_hw_params, + .mute_stream = rk730_dai_mute, + .no_capture_mute = 1, +}; + +static struct snd_soc_dai_driver rk730_dai = { + .name = "HiFi", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RK730_RATES, + .formats = RK730_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RK730_RATES, + .formats = RK730_FORMATS, + }, + .ops = &rk730_dai_ops, +}; + +static int rk730_reset(struct snd_soc_component *component) +{ + struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component); + + clk_prepare_enable(rk730->mclk); + snd_soc_component_write(component, RK730_DTOP_LPT_SRST, 0x40); + udelay(10); + /* WA: Initial micbias default, ADC stopped with micbias(>2.5v) */ + snd_soc_component_update_bits(component, RK730_MIC_BIAS, + RK730_MIC_BIAS_VOLT_MASK, + RK730_MIC_BIAS_VOLT_2_2V); + /* PF: Use the maximum bias current for better performance */ + snd_soc_component_update_bits(component, RK730_HK_TOP_1, + RK730_HK_TOP_1_IBIAS_STD_SEL_MASK | + RK730_HK_TOP_1_IBIAS_GAIN_SEL_MASK, + RK730_HK_TOP_1_IBIAS_STD_SEL_27_5UA | + RK730_HK_TOP_1_IBIAS_GAIN_SEL_200); + /* PF: Use the chop 400kHz for better ADC noise performance */ + snd_soc_component_update_bits(component, RK730_MIC_BOOST_3, + RK730_MIC_BOOST_3_MIC_CHOP_MASK, + RK730_MIC_BOOST_3_MIC_CHOP(RK730_CHOP_FREQ_400KHZ)); + snd_soc_component_update_bits(component, RK730_ADC_PGA_BLOCK_1, + RK730_ADC_PGA_BLOCK_1_PGA_CHOP_MASK, + RK730_ADC_PGA_BLOCK_1_PGA_CHOP(RK730_CHOP_FREQ_400KHZ)); + + clk_disable_unprepare(rk730->mclk); + + return 0; +} + +static int rk730_probe(struct snd_soc_component *component) +{ + struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component); + int ret = 0; + + regcache_mark_dirty(rk730->regmap); + + /* initialize private data */ + atomic_set(&rk730->mix_mode, RK730_MIX_MODE_1_PATH); + + ret = snd_soc_component_read(component, RK730_HK_TOP_0); + if (ret < 0) { + dev_err(component->dev, "Failed to read register: %d\n", ret); + return ret; + } + + rk730_reset(component); + + return ret; +} + +static const struct snd_soc_component_driver rk730_component_driver = { + .probe = rk730_probe, + .set_bias_level = rk730_set_bias_level, + .controls = rk730_snd_controls, + .num_controls = ARRAY_SIZE(rk730_snd_controls), + .dapm_widgets = rk730_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk730_dapm_widgets), + .dapm_routes = rk730_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rk730_dapm_routes), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + +static const struct reg_default rk730_reg_defaults[] = { + { 0x00, 0x40 }, + { 0x02, 0x17 }, + { 0x05, 0x03 }, + { 0x06, 0x22 }, + { 0x07, 0x02 }, + { 0x08, 0x07 }, + { 0x09, 0x01 }, + { 0x0a, 0x01 }, + { 0x0b, 0x01 }, + { 0x0c, 0x01 }, + { 0x0d, 0x01 }, + { 0x0e, 0x01 }, + { 0x0f, 0x07 }, + { 0x10, 0x07 }, + { 0x11, 0xff }, + { 0x12, 0x07 }, + { 0x13, 0x54 }, + { 0x14, 0x04 }, + { 0x15, 0x23 }, + { 0x16, 0x35 }, + { 0x17, 0x67 }, + { 0x18, 0x1e }, + { 0x19, 0xc0 }, + { 0x1a, 0x13 }, + { 0x1b, 0x04 }, + { 0x1c, 0x20 }, + { 0x1f, 0x90 }, + { 0x20, 0x11 }, + { 0x21, 0x09 }, + { 0x22, 0x33 }, + { 0x24, 0x11 }, + { 0x25, 0x11 }, + { 0x26, 0x09 }, + { 0x27, 0x02 }, + { 0x28, 0x2c }, + { 0x2a, 0x0c }, + { 0x2b, 0x80 }, + { 0x40, 0x03 }, + { 0x42, 0x20 }, + { 0x47, 0xe6 }, + { 0x48, 0xd0 }, + { 0x49, 0x17 }, + { 0x4a, 0x26 }, + { 0x4b, 0x01 }, + { 0x4c, 0x05 }, + { 0x4d, 0x0e }, + { 0x4e, 0x09 }, + { 0x4f, 0x02 }, + { 0x5b, 0xe6 }, + { 0x5c, 0xd0 }, + { 0x5d, 0x17 }, + { 0x5e, 0x26 }, + { 0x5f, 0x01 }, + { 0x60, 0x05 }, + { 0x61, 0x0e }, + { 0x62, 0x09 }, + { 0x63, 0x20 }, + { 0x66, 0x01 }, + { 0x69, 0x17 }, + { 0x6c, 0x17 }, +}; + +static bool rk730_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RK730_DTOP_LPT_SRST: + return true; + default: + return false; + } +} + +static const struct regmap_config rk730_regmap = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = rk730_volatile_register, + .max_register = RK730_DAC_ATTN, + .reg_defaults = rk730_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rk730_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + +static int rk730_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rk730_priv *rk730; + int ret; + + rk730 = devm_kzalloc(&i2c->dev, sizeof(struct rk730_priv), GFP_KERNEL); + if (!rk730) + return -ENOMEM; + + rk730->regmap = devm_regmap_init_i2c(i2c, &rk730_regmap); + if (IS_ERR(rk730->regmap)) + return PTR_ERR(rk730->regmap); + + rk730->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(rk730->mclk)) + return PTR_ERR(rk730->mclk); + + i2c_set_clientdata(i2c, rk730); + + ret = devm_snd_soc_register_component(&i2c->dev, + &rk730_component_driver, &rk730_dai, 1); + return ret; +} + +static const struct i2c_device_id rk730_i2c_id[] = { + { "rk730", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rk730_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id rk730_of_match[] = { + { .compatible = "rockchip,rk730" }, + { } +}; +MODULE_DEVICE_TABLE(of, rk730_of_match); +#endif + +static struct i2c_driver rk730_i2c_driver = { + .driver = { + .name = "rk730", + .of_match_table = of_match_ptr(rk730_of_match), + }, + .probe = rk730_i2c_probe, + .id_table = rk730_i2c_id, +}; + +module_i2c_driver(rk730_i2c_driver); + +MODULE_DESCRIPTION("ASoC RK730 driver"); +MODULE_AUTHOR("Sugar Zhang "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rk730.h b/sound/soc/codecs/rk730.h new file mode 100644 index 000000000000..b06f81828bb4 --- /dev/null +++ b/sound/soc/codecs/rk730.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * rk730.h -- RK730 ALSA SoC Audio driver + * + * Copyright (C) 2022 Rockchip Electronics Co.,Ltd + */ + +#ifndef _RK730_H +#define _RK730_H + +/* RK730 Analog Registers Definition */ +#define RK730_HK_TOP_0 0x00 +#define RK730_HK_TOP_1 0x01 +#define RK730_HK_TOP_2 0x02 +#define RK730_HK_TRIM_0 0x03 +#define RK730_HK_TRIM_1 0x04 +#define RK730_ADC_0 0x05 +#define RK730_ADC_1 0x06 +#define RK730_ADC_2 0x07 +#define RK730_DAC_0 0x08 +#define RK730_DAC_1 0x09 +#define RK730_DAC_2 0x0a +#define RK730_MIC_BOOST_0 0x0b +#define RK730_MIC_BOOST_1 0x0c +#define RK730_MIC_BOOST_2 0x0d +#define RK730_MIC_BOOST_3 0x0e +#define RK730_ADC_PGA_BLOCK_0 0x0f +#define RK730_ADC_PGA_BLOCK_1 0x10 +#define RK730_SYSPLL_0 0x11 +#define RK730_SYSPLL_1 0x12 +#define RK730_SYSPLL_2 0x13 +#define RK730_SYSPLL_3 0x14 +#define RK730_SYSPLL_LOOP_0 0x15 +#define RK730_SYSPLL_LOOP_1 0x16 +#define RK730_SYSPLL_LOOP_2 0x17 +#define RK730_SYSPLL_LOOP_3 0x18 +#define RK730_SYSPLL_RVCO_0 0x19 +#define RK730_SYSPLL_RVCO_1 0x1a +#define RK730_SYSPLL_RVCO_2 0x1b +#define RK730_SYSPLL_RVCO_3 0x1c +#define RK730_SYSPLL_FRACT_0 0x1d +#define RK730_SYSPLL_FRACT_1 0x1e +#define RK730_SYSPLL_FRACT_2 0x1f +#define RK730_LDO 0x20 +#define RK730_MIC_BIAS 0x21 +#define RK730_MUXER_0 0x22 +#define RK730_MUXER_1 0x23 +#define RK730_MIXER_0 0x24 +#define RK730_MIXER_1 0x25 +#define RK730_MIXER_2 0x26 +#define RK730_CHARGE_PUMP 0x27 +#define RK730_HP_0 0x28 +#define RK730_HP_1 0x29 +#define RK730_LINEOUT_0 0x2a +#define RK730_LINEOUT_1 0x2b + +/* RK730 Digital Registers Definition */ +#define RK730_DTOP_VUCTL 0x40 +#define RK730_DTOP_VUCTIME 0x41 +#define RK730_DTOP_LPT_SRST 0x42 +#define RK730_DTOP_DIGEN_CLKE 0x43 +#define RK730_DADC_VOLL 0x44 +#define RK730_DADC_VOLR 0x45 +#define RK730_DADC_SR_ACL 0x46 +#define RK730_DADC_PR_0 0x47 +#define RK730_DADC_PR_1 0x48 +#define RK730_DADC_PR_2 0x49 +#define RK730_DADC_PR_3 0x4a +#define RK730_DADC_NG_0 0x4b +#define RK730_DADC_NG_1 0x4c +#define RK730_DADC_NG_2 0x4d +#define RK730_DADC_NG_3 0x4e +#define RK730_DADC_CICCOMP 0x4f +#define RK730_DADC_HPF 0x50 +#define RK730_DADC_RVOLL 0x51 +#define RK730_DADC_RVOLR 0x52 +#define RK730_DMIC_LMT_1 0x53 +#define RK730_DMIC_LMT_2 0x54 +#define RK730_DMIC_NG_1 0x55 +#define RK730_DMIC_NG_2 0x56 +#define RK730_DDAC_POPD_DACST 0x57 +#define RK730_DDAC_VOLL 0x58 +#define RK730_DDAC_VOLR 0x59 +#define RK730_DDAC_SR_LMT 0x5a +#define RK730_DDAC_PR_0 0x5b +#define RK730_DDAC_PR_1 0x5c +#define RK730_DDAC_PR_2 0x5d +#define RK730_DDAC_PR_3 0x5e +#define RK730_DDAC_NG_0 0x5f +#define RK730_DDAC_NG_1 0x60 +#define RK730_DDAC_NG_2 0x61 +#define RK730_DDAC_NG_3 0x62 +#define RK730_DDAC_MUTE_MIXCTL 0x63 +#define RK730_DDAC_RVOLL 0x64 +#define RK730_DDAC_RVOLR 0x65 +#define RK730_DI2S_CKM 0x66 +#define RK730_DI2S_RSD 0x67 +#define RK730_DI2S_RXCR_1 0x68 +#define RK730_DI2S_RXCR_2 0x69 +#define RK730_DI2S_RXCMD_TSD 0x6a +#define RK730_DI2S_TXCR_1 0x6b +#define RK730_DI2S_TXCR_2 0x6c +#define RK730_DI2S_TXCR_3_TXCMD 0x6d +#define RK730_DAC_ATTN 0x6e + +/* RK730_HK_TOP_1 */ +#define RK730_HK_TOP_1_DAC_REF_BUF_CHOP_MASK GENMASK(7, 6) +#define RK730_HK_TOP_1_DAC_REF_BUF_CHOP(x) ((x) << 6) +#define RK730_HK_TOP_1_IBIAS_STD_SEL_MASK GENMASK(5, 4) +#define RK730_HK_TOP_1_IBIAS_STD_SEL_27_5UA (3 << 4) +#define RK730_HK_TOP_1_IBIAS_STD_SEL_23_5UA (2 << 4) +#define RK730_HK_TOP_1_IBIAS_STD_SEL_20UA (1 << 4) +#define RK730_HK_TOP_1_IBIAS_STD_SEL_16_5UA (0 << 4) +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_MASK GENMASK(3, 0) +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_200 8 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_143 9 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_120 10 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_100 0 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_71_5 1 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_62_5 2 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_50 3 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_38_2 6 +#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_32 7 + +/* RK730_ADC_0 */ +#define RK730_ADC_0_DEM_EN_MASK BIT(3) +#define RK730_ADC_0_DEM_EN BIT(3) +#define RK730_ADC_0_DEM_DIS 0 + +/* RK730_MIC_BOOST_3 */ +#define RK730_MIC_BOOST_3_MIC_CHOP_MASK GENMASK(7, 6) +#define RK730_MIC_BOOST_3_MIC_CHOP(x) ((x) << 6) + +/* RK730_ADC_PGA_BLOCK_1 */ +#define RK730_ADC_PGA_BLOCK_1_PGA_CHOP_MASK GENMASK(7, 6) +#define RK730_ADC_PGA_BLOCK_1_PGA_CHOP(x) ((x) << 6) + +/* RK730_MIC_BIAS */ +#define RK730_MIC_BIAS_VOLT_MASK GENMASK(3, 2) +#define RK730_MIC_BIAS_VOLT_2_8V (3 << 2) +#define RK730_MIC_BIAS_VOLT_2_5V (2 << 2) +#define RK730_MIC_BIAS_VOLT_2_2V (1 << 2) +#define RK730_MIC_BIAS_VOLT_2_0V (0 << 2) + +/* RK730_MUXER_1 */ +#define RK730_MUXER_1_MUX_OUT_CHOP_MASK GENMASK(1, 0) +#define RK730_MUXER_1_MUX_OUT_CHOP(x) ((x) << 0) + +/* RK730_MIXER_2 */ +#define RK730_MIXER_2_MIX_CHOP_MASK GENMASK(7, 6) +#define RK730_MIXER_2_MIX_CHOP(x) ((x) << 6) +#define RK730_MIXER_2_MIX_R_MODE_MASK GENMASK(5, 4) +#define RK730_MIXER_2_MIX_R_MODE(x) ((x) << 4) +#define RK730_MIXER_2_MIX_L_MODE_MASK GENMASK(2, 1) +#define RK730_MIXER_2_MIX_L_MODE(x) ((x) << 1) + +/* RK730_HP_1 */ +#define RK730_HP_1_HP_LO_CHOP_MASK GENMASK(6, 5) +#define RK730_HP_1_HP_LO_CHOP(x) ((x) << 5) + +/* RK730_DTOP_DIGEN_CLKE */ +#define RK730_DTOP_DIGEN_CLKE_ADC_CKE_MASK BIT(7) +#define RK730_DTOP_DIGEN_CLKE_ADC_CKE_EN BIT(7) +#define RK730_DTOP_DIGEN_CLKE_ADC_CKE_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_I2STX_CKE_MASK BIT(6) +#define RK730_DTOP_DIGEN_CLKE_I2STX_CKE_EN BIT(6) +#define RK730_DTOP_DIGEN_CLKE_I2STX_CKE_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_ADC_EN_MASK BIT(5) +#define RK730_DTOP_DIGEN_CLKE_ADC_EN BIT(5) +#define RK730_DTOP_DIGEN_CLKE_ADC_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_I2STX_EN_MASK BIT(4) +#define RK730_DTOP_DIGEN_CLKE_I2STX_EN BIT(4) +#define RK730_DTOP_DIGEN_CLKE_I2STX_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_DAC_CKE_MASK BIT(3) +#define RK730_DTOP_DIGEN_CLKE_DAC_CKE_EN BIT(3) +#define RK730_DTOP_DIGEN_CLKE_DAC_CKE_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_MASK BIT(2) +#define RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_EN BIT(2) +#define RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_DAC_EN_MASK BIT(1) +#define RK730_DTOP_DIGEN_CLKE_DAC_EN BIT(1) +#define RK730_DTOP_DIGEN_CLKE_DAC_DIS 0 +#define RK730_DTOP_DIGEN_CLKE_I2SRX_EN_MASK BIT(0) +#define RK730_DTOP_DIGEN_CLKE_I2SRX_EN BIT(0) +#define RK730_DTOP_DIGEN_CLKE_I2SRX_DIS 0 + +/* RK730_DADC_SR_ACL */ +#define RK730_DADC_SR_ACL_VOLL_POL_MASK BIT(5) +#define RK730_DADC_SR_ACL_VOLL_POS BIT(5) +#define RK730_DADC_SR_ACL_VOLL_NEG 0 +#define RK730_DADC_SR_ACL_VOLR_POL_MASK BIT(4) +#define RK730_DADC_SR_ACL_VOLR_POS BIT(4) +#define RK730_DADC_SR_ACL_VOLR_NEG 0 +#define RK730_DADC_SR_ACL_SRT_MASK GENMASK(2, 0) +#define RK730_DADC_SR_ACL_SRT(x) (x) + +/* RK730_DDAC_SR_LMT */ +#define RK730_DDAC_SR_LMT_VOLL_POL_MASK BIT(5) +#define RK730_DDAC_SR_LMT_VOLL_POS BIT(5) +#define RK730_DDAC_SR_LMT_VOLL_NEG 0 +#define RK730_DDAC_SR_LMT_VOLR_POL_MASK BIT(4) +#define RK730_DDAC_SR_LMT_VOLR_POS BIT(4) +#define RK730_DDAC_SR_LMT_VOLR_NEG 0 +#define RK730_DDAC_SR_LMT_SRT_MASK GENMASK(2, 0) +#define RK730_DDAC_SR_LMT_SRT(x) (x) + +/* RK730_DDAC_MUTE_MIXCTL */ +#define RK730_DDAC_MUTE_MIXCTL_MUTE_MASK BIT(0) +#define RK730_DDAC_MUTE_MIXCTL_MUTE BIT(0) +#define RK730_DDAC_MUTE_MIXCTL_UNMUTE 0 + +/* RK730_DI2S_CKM */ +#define RK730_DI2S_CKM_SCLK_DIV_MASK GENMASK(7, 4) +#define RK730_DI2S_CKM_SCLK_DIV(x) ((x - 1) << 4) +#define RK730_DI2S_CKM_SCLK_EN_MASK BIT(2) +#define RK730_DI2S_CKM_SCLK_EN BIT(2) +#define RK730_DI2S_CKM_SCLK_DIS 0 +#define RK730_DI2S_CKM_SCLK_POL_MASK BIT(1) +#define RK730_DI2S_CKM_SCLK_INVERTED BIT(1) +#define RK730_DI2S_CKM_SCLK_NORMAL 0 +#define RK730_DI2S_CKM_MST_MASK BIT(0) +#define RK730_DI2S_CKM_MST_MASTER BIT(0) +#define RK730_DI2S_CKM_MST_SLAVE 0 + +/* RK730_DI2S_XCR2 */ +#define RK730_DI2S_XCR2_VDW_MASK GENMASK(4, 0) +#define RK730_DI2S_XCR2_VDW(x) (x - 1) + +/* RK730_DI2S_RXCMD_TSD */ +#define RK730_DI2S_RXCMD_TSD_RXS_MASK BIT(5) +#define RK730_DI2S_RXCMD_TSD_RXS_EN BIT(5) +#define RK730_DI2S_RXCMD_TSD_RXS_DIS 0 + +/* RK730_DI2S_TXCR_3_TXCMD */ +#define RK730_DI2S_TXCR_3_TXCMD_TXS_MASK BIT(7) +#define RK730_DI2S_TXCR_3_TXCMD_TXS_EN BIT(7) +#define RK730_DI2S_TXCR_3_TXCMD_TXS_DIS 0 + +#endif