- patches/: the pristine-6.18.46 -> WardenOS delta as a 13-patch, subsystem-split series (223 files, ~136K lines: clk, pinctrl, DTs/mach, usb-phy, VOP/panel/rgb, mailbox, pvtm, rknpu, rga, aic8800 wifi, audio codec, thermal/rtc/adc/gmac/touch). Verified: every patch applies cleanly onto pristine (git apply --check), the full series reproduces the hardware-verified tree, and the applied source configures + builds the warden dtb + rockchip DRM drivers (rc=0). - build/build-kernel.sh: fetch+verify pristine (sha256-pinned) -> apply series -> warden_defconfig -> zImage + rv1106-warden.dtb. build/warden_defconfig captured. - CI: `patches-apply` (GitHub-hosted, cached tarball) enforces the series applies; `kernel-build` (self-hosted warden-sdk runner, dispatch-gated until registered) runs the full build and uploads the image. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
4000 lines
134 KiB
Diff
4000 lines
134 KiB
Diff
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
|
|
index 91ac99bc3..bbc83867a 100644
|
|
--- a/sound/soc/codecs/Kconfig
|
|
+++ b/sound/soc/codecs/Kconfig
|
|
@@ -1604,6 +1604,14 @@ config SND_SOC_RK817
|
|
tristate "Rockchip RK817 audio CODEC"
|
|
depends on MFD_RK8XX || COMPILE_TEST
|
|
|
|
+config SND_SOC_RK_DSM
|
|
+ tristate "Rockchip Delta-sigma Digital Converter Interface"
|
|
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
|
|
+ help
|
|
+ This is a device driver for the digital speaker modulator (DSM)
|
|
+ embedded in some Rockchip SoCs (e.g. RV1106), used to drive a
|
|
+ Class-D speaker output alongside the analog acodec.
|
|
+
|
|
config SND_SOC_RL6231
|
|
tristate
|
|
default y if SND_SOC_RT5514=y
|
|
@@ -1919,6 +1927,15 @@ config SND_SOC_RTQ9128
|
|
To compile this driver as a module, choose M here: the module
|
|
will be called snd-soc-rtq9128.
|
|
|
|
+config SND_SOC_RV1106
|
|
+ tristate "Rockchip RV1106 CODEC"
|
|
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
|
|
+ select REGMAP_MMIO
|
|
+ help
|
|
+ This is a device driver for the analog audio codec (acodec)
|
|
+ embedded in the Rockchip RV1106 SoC, used for speaker/headphone
|
|
+ output and microphone input (e.g. on the Luckfox Pico 86-Panel).
|
|
+
|
|
config SND_SOC_SDW_MOCKUP
|
|
tristate "SoundWire mockup codec"
|
|
depends on EXPERT
|
|
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
|
|
index da4077463..ae15009e0 100644
|
|
--- a/sound/soc/codecs/Makefile
|
|
+++ b/sound/soc/codecs/Makefile
|
|
@@ -231,6 +231,7 @@ snd-soc-pm4125-sdw-y := pm4125-sdw.o
|
|
snd-soc-rk3308-y := rk3308_codec.o
|
|
snd-soc-rk3328-y := rk3328_codec.o
|
|
snd-soc-rk817-y := rk817_codec.o
|
|
+snd-soc-rk-dsm-y := rk_dsm.o
|
|
snd-soc-rl6231-y := rl6231.o
|
|
snd-soc-rt-sdw-common-y := rt-sdw-common.o
|
|
snd-soc-rl6347a-y := rl6347a.o
|
|
@@ -283,6 +284,7 @@ snd-soc-rt9123-y := rt9123.o
|
|
snd-soc-rt9123p-y := rt9123p.o
|
|
snd-soc-rtq9124-y := rtq9124.o
|
|
snd-soc-rtq9128-y := rtq9128.o
|
|
+snd-soc-rv1106-y := rv1106_codec.o
|
|
snd-soc-sdw-mockup-y := sdw-mockup.o
|
|
snd-soc-sgtl5000-y := sgtl5000.o
|
|
snd-soc-alc5623-y := alc5623.o
|
|
@@ -662,6 +664,7 @@ endif
|
|
obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o
|
|
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
|
|
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
|
|
+obj-$(CONFIG_SND_SOC_RK_DSM) += snd-soc-rk-dsm.o
|
|
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
|
|
obj-$(CONFIG_SND_SOC_RT_SDW_COMMON) += snd-soc-rt-sdw-common.o
|
|
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
|
|
@@ -715,6 +718,7 @@ obj-$(CONFIG_SND_SOC_RT9123) += snd-soc-rt9123.o
|
|
obj-$(CONFIG_SND_SOC_RT9123P) += snd-soc-rt9123p.o
|
|
obj-$(CONFIG_SND_SOC_RTQ9124) += snd-soc-rtq9124.o
|
|
obj-$(CONFIG_SND_SOC_RTQ9128) += snd-soc-rtq9128.o
|
|
+obj-$(CONFIG_SND_SOC_RV1106) += snd-soc-rv1106.o
|
|
obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o
|
|
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
|
|
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
|
|
diff --git a/sound/soc/codecs/rk_dsm.c b/sound/soc/codecs/rk_dsm.c
|
|
new file mode 100644
|
|
index 000000000..4bcbcbaf5
|
|
--- /dev/null
|
|
+++ b/sound/soc/codecs/rk_dsm.c
|
|
@@ -0,0 +1,651 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
|
+/*
|
|
+ * Rockchip Audio Delta-sigma Digital Converter Interface
|
|
+ *
|
|
+ * Copyright (C) 2023 Rockchip Electronics Co.,Ltd
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/of_gpio.h>
|
|
+#include <linux/of_platform.h>
|
|
+#include <linux/clk.h>
|
|
+#include <linux/mfd/syscon.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/pm_runtime.h>
|
|
+#include <linux/regmap.h>
|
|
+#include <linux/reset.h>
|
|
+#include <sound/pcm_params.h>
|
|
+#include <sound/dmaengine_pcm.h>
|
|
+#include <sound/tlv.h>
|
|
+#include "rk_dsm.h"
|
|
+
|
|
+#define RK3562_GRF_PERI_AUDIO_CON (0x0070)
|
|
+
|
|
+struct rk_dsm_soc_data {
|
|
+ int (*init)(struct device *dev);
|
|
+ void (*deinit)(struct device *dev);
|
|
+};
|
|
+
|
|
+struct rk_dsm_priv {
|
|
+ struct regmap *grf;
|
|
+ struct regmap *regmap;
|
|
+ struct clk *clk_dac;
|
|
+ struct clk *pclk;
|
|
+ unsigned int pa_ctl_delay_ms;
|
|
+ struct gpio_desc *pa_ctl;
|
|
+ struct reset_control *rc;
|
|
+ const struct rk_dsm_soc_data *data;
|
|
+};
|
|
+
|
|
+/* DAC digital gain */
|
|
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -95625, 375, 0);
|
|
+
|
|
+/* DAC Cutoff for High Pass Filter */
|
|
+static const char * const dac_hpf_cutoff_text[] = {
|
|
+ "80Hz", "100Hz", "120Hz", "140Hz",
|
|
+};
|
|
+
|
|
+static SOC_ENUM_SINGLE_DECL(dac_hpf_cutoff_enum, DACHPF, 4,
|
|
+ dac_hpf_cutoff_text);
|
|
+
|
|
+static const char * const pa_ctl[] = {"Off", "On"};
|
|
+
|
|
+static const struct soc_enum pa_enum =
|
|
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(pa_ctl), pa_ctl);
|
|
+
|
|
+static int rk_dsm_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, DACVOGP);
|
|
+ unsigned int mask = (1 << fls(mc->max)) - 1;
|
|
+ unsigned int shift = mc->shift;
|
|
+ int mid = mc->max / 2;
|
|
+ int uv;
|
|
+
|
|
+ uv = (val >> shift) & 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 rk_dsm_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;
|
|
+ int uv = ucontrol->value.integer.value[0];
|
|
+ int min = mc->min;
|
|
+ int mid = mc->max / 2;
|
|
+
|
|
+ if (uv > mid) {
|
|
+ sign = DSM_DACVOGP_VOLGPL0_POS | DSM_DACVOGP_VOLGPR0_POS;
|
|
+ uv = uv - mid;
|
|
+ } else {
|
|
+ sign = DSM_DACVOGP_VOLGPL0_NEG | DSM_DACVOGP_VOLGPR0_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_write(component, DACVOGP, sign);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk_dsm_dac_pa_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rk_dsm_priv *rd = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ if (!rd->pa_ctl)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ucontrol->value.enumerated.item[0] = gpiod_get_value(rd->pa_ctl);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk_dsm_dac_pa_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rk_dsm_priv *rd = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ if (!rd->pa_ctl)
|
|
+ return -EINVAL;
|
|
+
|
|
+ gpiod_set_value(rd->pa_ctl, ucontrol->value.enumerated.item[0]);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct snd_kcontrol_new rk_dsm_snd_controls[] = {
|
|
+ SOC_DOUBLE_R_EXT_TLV("DAC Digital Volume",
|
|
+ DACVOLL0, DACVOLR0, 0, 0x1fe, 0,
|
|
+ rk_dsm_dac_vol_get,
|
|
+ rk_dsm_dac_vol_put,
|
|
+ dac_tlv),
|
|
+
|
|
+ SOC_ENUM("DAC HPF Cutoff", dac_hpf_cutoff_enum),
|
|
+ SOC_SINGLE("DAC HPF Switch", DACHPF, 0, 1, 0),
|
|
+ SOC_ENUM_EXT("Power Amplifier", pa_enum,
|
|
+ rk_dsm_dac_pa_get,
|
|
+ rk_dsm_dac_pa_put),
|
|
+};
|
|
+
|
|
+/*
|
|
+ * ACDC_CLK D2A_CLK D2A_SYNC Sample rates supported
|
|
+ * 49.152MHz 49.152MHz 6.144MHz 12/24/48/96/192kHz
|
|
+ * 45.154MHz 45.154MHz 5.644MHz 11.025/22.05/44.1/88.2/176.4kHz
|
|
+ * 32.768MHz 32.768MHz 4.096MHz 8/16/32/64/128kHz
|
|
+ */
|
|
+static void rk_dsm_get_clk(unsigned int samplerate,
|
|
+ unsigned int *mclk,
|
|
+ unsigned int *sclk)
|
|
+{
|
|
+ switch (samplerate) {
|
|
+ case 12000:
|
|
+ case 24000:
|
|
+ case 48000:
|
|
+ case 96000:
|
|
+ case 192000:
|
|
+ *mclk = 49152000;
|
|
+ *sclk = 6144000;
|
|
+ break;
|
|
+ case 11025:
|
|
+ case 22050:
|
|
+ case 44100:
|
|
+ case 88200:
|
|
+ case 176400:
|
|
+ *mclk = 45158400;
|
|
+ *sclk = 5644800;
|
|
+ break;
|
|
+ case 8000:
|
|
+ case 16000:
|
|
+ case 32000:
|
|
+ case 64000:
|
|
+ case 128000:
|
|
+ *mclk = 32768000;
|
|
+ *sclk = 4096000;
|
|
+ break;
|
|
+ default:
|
|
+ *mclk = 0;
|
|
+ *sclk = 0;
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void rk_dsm_enable_clk_dac(struct rk_dsm_priv *rd)
|
|
+{
|
|
+ regmap_update_bits(rd->regmap, DACCLKCTRL,
|
|
+ DSM_DACCLKCTRL_DAC_CKE_MASK |
|
|
+ DSM_DACCLKCTRL_I2SRX_CKE_MASK |
|
|
+ DSM_DACCLKCTRL_CKE_BCLKRX_MASK |
|
|
+ DSM_DACCLKCTRL_DAC_SYNC_ENA_MASK |
|
|
+ DSM_DACCLKCTRL_DAC_MODE_ATTENU_MASK,
|
|
+ DSM_DACCLKCTRL_DAC_CKE_EN |
|
|
+ DSM_DACCLKCTRL_I2SRX_CKE_EN |
|
|
+ DSM_DACCLKCTRL_CKE_BCLKRX_EN |
|
|
+ DSM_DACCLKCTRL_DAC_SYNC_ENA_EN |
|
|
+ DSM_DACCLKCTRL_DAC_MODE_ATTENU_EN);
|
|
+}
|
|
+
|
|
+static int rk_dsm_set_clk(struct rk_dsm_priv *rd,
|
|
+ struct snd_pcm_substream *substream,
|
|
+ unsigned int samplerate)
|
|
+{
|
|
+ unsigned int mclk, sclk, bclk;
|
|
+ unsigned int div_bclk;
|
|
+
|
|
+ rk_dsm_get_clk(samplerate, &mclk, &sclk);
|
|
+ if (!mclk || !sclk)
|
|
+ return -EINVAL;
|
|
+
|
|
+ bclk = 64 * samplerate;
|
|
+ div_bclk = DIV_ROUND_CLOSEST(mclk, bclk);
|
|
+
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ clk_set_rate(rd->clk_dac, mclk);
|
|
+
|
|
+ rk_dsm_enable_clk_dac(rd);
|
|
+
|
|
+ regmap_update_bits(rd->regmap, DACSCLKRXINT_DIV,
|
|
+ DSM_DACSCLKRXINT_DIV_SCKRXDIV_MASK,
|
|
+ DSM_DACSCLKRXINT_DIV_SCKRXDIV(div_bclk));
|
|
+ regmap_update_bits(rd->regmap, I2S_CKR0,
|
|
+ DSM_I2S_CKR0_RSD_MASK,
|
|
+ DSM_I2S_CKR0_RSD_64);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk_dsm_set_dai_fmt(struct snd_soc_dai *dai,
|
|
+ unsigned int fmt)
|
|
+{
|
|
+ struct rk_dsm_priv *rd =
|
|
+ snd_soc_component_get_drvdata(dai->component);
|
|
+ unsigned int mask = 0, val = 0;
|
|
+
|
|
+ /* master mode only */
|
|
+ regmap_update_bits(rd->regmap, I2S_CKR1,
|
|
+ DSM_I2S_CKR1_MSS_MASK,
|
|
+ DSM_I2S_CKR1_MSS_MASTER);
|
|
+
|
|
+ mask = DSM_I2S_CKR1_CKP_MASK |
|
|
+ DSM_I2S_CKR1_RLP_MASK;
|
|
+
|
|
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
|
+ case SND_SOC_DAIFMT_NB_NF:
|
|
+ val = DSM_I2S_CKR1_CKP_NORMAL |
|
|
+ DSM_I2S_CKR1_RLP_NORMAL;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_IB_IF:
|
|
+ val = DSM_I2S_CKR1_CKP_INVERTED |
|
|
+ DSM_I2S_CKR1_RLP_INVERTED;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_IB_NF:
|
|
+ val = DSM_I2S_CKR1_CKP_INVERTED |
|
|
+ DSM_I2S_CKR1_RLP_NORMAL;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_NB_IF:
|
|
+ val = DSM_I2S_CKR1_CKP_NORMAL |
|
|
+ DSM_I2S_CKR1_RLP_INVERTED;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rd->regmap, I2S_CKR1, mask, val);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk_dsm_hw_params(struct snd_pcm_substream *substream,
|
|
+ struct snd_pcm_hw_params *params,
|
|
+ struct snd_soc_dai *dai)
|
|
+{
|
|
+ struct rk_dsm_priv *rd =
|
|
+ snd_soc_component_get_drvdata(dai->component);
|
|
+ unsigned int srt = 0, val = 0;
|
|
+
|
|
+ rk_dsm_set_clk(rd, substream, params_rate(params));
|
|
+
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ switch (params_rate(params)) {
|
|
+ case 8000:
|
|
+ case 11025:
|
|
+ case 12000:
|
|
+ srt = 0;
|
|
+ break;
|
|
+ case 16000:
|
|
+ case 22050:
|
|
+ case 24000:
|
|
+ srt = 1;
|
|
+ break;
|
|
+ case 32000:
|
|
+ case 44100:
|
|
+ case 48000:
|
|
+ srt = 2;
|
|
+ break;
|
|
+ case 64000:
|
|
+ case 88200:
|
|
+ case 96000:
|
|
+ srt = 3;
|
|
+ break;
|
|
+ case 128000:
|
|
+ case 176400:
|
|
+ case 192000:
|
|
+ srt = 4;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rd->regmap, DACCFG1,
|
|
+ DSM_DACCFG1_DACSRT_MASK,
|
|
+ DSM_DACCFG1_DACSRT(srt));
|
|
+
|
|
+ switch (params_format(params)) {
|
|
+ case SNDRV_PCM_FORMAT_S16_LE:
|
|
+ val = 16;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S24_LE:
|
|
+ case SNDRV_PCM_FORMAT_S32_LE:
|
|
+ val = 24;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rd->regmap, I2S_RXCR0,
|
|
+ DSM_I2S_RXCR0_VDW_MASK,
|
|
+ DSM_I2S_RXCR0_VDW(val));
|
|
+ regmap_update_bits(rd->regmap, DACPWM_CTRL,
|
|
+ DSM_DACPWM_CTRL_PWM_MODE_CKE_MASK |
|
|
+ DSM_DACPWM_CTRL_PWM_EN_MASK,
|
|
+ DSM_DACPWM_CTRL_PWM_MODE_CKE_EN |
|
|
+ DSM_DACPWM_CTRL_PWM_EN);
|
|
+ }
|
|
+
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ regmap_update_bits(rd->regmap, I2S_XFER,
|
|
+ DSM_I2S_XFER_RXS_MASK,
|
|
+ DSM_I2S_XFER_RXS_START);
|
|
+ regmap_update_bits(rd->regmap, DACDIGEN,
|
|
+ DSM_DACDIGEN_DAC_GLBEN_MASK |
|
|
+ DSM_DACDIGEN_DACEN_L0R1_MASK,
|
|
+ DSM_DACDIGEN_DAC_GLBEN_EN |
|
|
+ DSM_DACDIGEN_DACEN_L0R1_EN);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk_dsm_pcm_startup(struct snd_pcm_substream *substream,
|
|
+ struct snd_soc_dai *dai)
|
|
+{
|
|
+ struct rk_dsm_priv *rd =
|
|
+ snd_soc_component_get_drvdata(dai->component);
|
|
+
|
|
+ gpiod_set_value(rd->pa_ctl, 1);
|
|
+ if (rd->pa_ctl_delay_ms)
|
|
+ msleep(rd->pa_ctl_delay_ms);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void rk_dsm_reset(struct rk_dsm_priv *rd)
|
|
+{
|
|
+ if (IS_ERR(rd->rc))
|
|
+ return;
|
|
+
|
|
+ reset_control_assert(rd->rc);
|
|
+ udelay(5);
|
|
+ reset_control_deassert(rd->rc);
|
|
+ udelay(5);
|
|
+}
|
|
+
|
|
+static void rk_dsm_pcm_shutdown(struct snd_pcm_substream *substream,
|
|
+ struct snd_soc_dai *dai)
|
|
+{
|
|
+ struct rk_dsm_priv *rd =
|
|
+ snd_soc_component_get_drvdata(dai->component);
|
|
+
|
|
+ gpiod_set_value(rd->pa_ctl, 0);
|
|
+
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ regmap_update_bits(rd->regmap, DACPWM_CTRL,
|
|
+ DSM_DACPWM_CTRL_PWM_MODE_CKE_MASK |
|
|
+ DSM_DACPWM_CTRL_PWM_EN_MASK,
|
|
+ DSM_DACPWM_CTRL_PWM_MODE_CKE_DIS |
|
|
+ DSM_DACPWM_CTRL_PWM_DIS);
|
|
+ regmap_update_bits(rd->regmap, I2S_XFER,
|
|
+ DSM_I2S_XFER_RXS_MASK,
|
|
+ DSM_I2S_XFER_RXS_STOP);
|
|
+ regmap_update_bits(rd->regmap, I2S_CLR,
|
|
+ DSM_I2S_CLR_RXC_MASK,
|
|
+ DSM_I2S_CLR_RXC_CLR);
|
|
+ regmap_update_bits(rd->regmap, DACDIGEN,
|
|
+ DSM_DACDIGEN_DAC_GLBEN_MASK |
|
|
+ DSM_DACDIGEN_DACEN_L0R1_MASK,
|
|
+ DSM_DACDIGEN_DAC_GLBEN_DIS |
|
|
+ DSM_DACDIGEN_DACEN_L0R1_DIS);
|
|
+ }
|
|
+
|
|
+ rk_dsm_reset(rd);
|
|
+}
|
|
+
|
|
+static const struct snd_soc_dai_ops rd_dai_ops = {
|
|
+ .hw_params = rk_dsm_hw_params,
|
|
+ .set_fmt = rk_dsm_set_dai_fmt,
|
|
+ .startup = rk_dsm_pcm_startup,
|
|
+ .shutdown = rk_dsm_pcm_shutdown,
|
|
+};
|
|
+
|
|
+static struct snd_soc_dai_driver rd_dai[] = {
|
|
+ {
|
|
+ .name = "rk_dsm",
|
|
+ .id = 0,
|
|
+ .playback = {
|
|
+ .stream_name = "Playback",
|
|
+ .channels_min = 2,
|
|
+ .channels_max = 2,
|
|
+ .rates = SNDRV_PCM_RATE_8000_192000,
|
|
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
|
+ SNDRV_PCM_FMTBIT_S24_LE |
|
|
+ SNDRV_PCM_FMTBIT_S32_LE),
|
|
+ },
|
|
+ .ops = &rd_dai_ops,
|
|
+ },
|
|
+};
|
|
+
|
|
+static const struct snd_soc_component_driver soc_codec_dev_rd = {
|
|
+ .controls = rk_dsm_snd_controls,
|
|
+ .num_controls = ARRAY_SIZE(rk_dsm_snd_controls),
|
|
+};
|
|
+
|
|
+static const struct regmap_config rd_regmap_config = {
|
|
+ .reg_bits = 32,
|
|
+ .reg_stride = 4,
|
|
+ .val_bits = 32,
|
|
+ .max_register = VERSION,
|
|
+ .cache_type = REGCACHE_FLAT,
|
|
+};
|
|
+
|
|
+static int rk3562_soc_init(struct device *dev)
|
|
+{
|
|
+ struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
|
+
|
|
+ if (IS_ERR(rd->grf))
|
|
+ return PTR_ERR(rd->grf);
|
|
+
|
|
+ /* enable internal codec to i2s1 */
|
|
+ return regmap_write(rd->grf, RK3562_GRF_PERI_AUDIO_CON,
|
|
+ (BIT(14) << 16 | BIT(14) | 0x0a100a10));
|
|
+}
|
|
+
|
|
+static void rk3562_soc_deinit(struct device *dev)
|
|
+{
|
|
+ struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
|
+
|
|
+ if (IS_ERR(rd->grf))
|
|
+ return;
|
|
+
|
|
+ regmap_write(rd->grf, RK3562_GRF_PERI_AUDIO_CON, (BIT(14) << 16) | 0x0a100a10);
|
|
+}
|
|
+
|
|
+static const struct rk_dsm_soc_data rk3562_data = {
|
|
+ .init = rk3562_soc_init,
|
|
+ .deinit = rk3562_soc_deinit,
|
|
+};
|
|
+
|
|
+#ifdef CONFIG_OF
|
|
+static const struct of_device_id rd_of_match[] = {
|
|
+ { .compatible = "rockchip,rk3562-dsm", .data = &rk3562_data },
|
|
+ {},
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, rd_of_match);
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_PM
|
|
+static int rk_dsm_runtime_resume(struct device *dev)
|
|
+{
|
|
+ struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = clk_prepare_enable(rd->pclk);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ regcache_cache_only(rd->regmap, false);
|
|
+ regcache_mark_dirty(rd->regmap);
|
|
+
|
|
+ ret = clk_prepare_enable(rd->clk_dac);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ return 0;
|
|
+err:
|
|
+ clk_disable_unprepare(rd->pclk);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int rk_dsm_runtime_suspend(struct device *dev)
|
|
+{
|
|
+ struct rk_dsm_priv *rd = dev_get_drvdata(dev);
|
|
+
|
|
+ regcache_cache_only(rd->regmap, true);
|
|
+ clk_disable_unprepare(rd->clk_dac);
|
|
+ clk_disable_unprepare(rd->pclk);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static int rk_dsm_platform_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct device_node *np = pdev->dev.of_node;
|
|
+ struct rk_dsm_priv *rd;
|
|
+ void __iomem *base;
|
|
+ int ret = 0;
|
|
+
|
|
+ rd = devm_kzalloc(&pdev->dev, sizeof(*rd), GFP_KERNEL);
|
|
+ if (!rd)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ rd->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
|
+ if (IS_ERR(rd->grf))
|
|
+ return PTR_ERR(rd->grf);
|
|
+
|
|
+ if (device_property_read_u32(&pdev->dev, "rockchip,pa-ctl-delay-ms",
|
|
+ &rd->pa_ctl_delay_ms))
|
|
+ rd->pa_ctl_delay_ms = 0;
|
|
+
|
|
+ rd->rc = devm_reset_control_get(&pdev->dev, "reset");
|
|
+
|
|
+ rd->clk_dac = devm_clk_get(&pdev->dev, "dac");
|
|
+ if (IS_ERR(rd->clk_dac))
|
|
+ return PTR_ERR(rd->clk_dac);
|
|
+
|
|
+ rd->pclk = devm_clk_get(&pdev->dev, "pclk");
|
|
+ if (IS_ERR(rd->pclk))
|
|
+ return PTR_ERR(rd->pclk);
|
|
+
|
|
+ base = devm_platform_ioremap_resource(pdev, 0);
|
|
+ if (IS_ERR(base))
|
|
+ return PTR_ERR(base);
|
|
+
|
|
+ rd->regmap =
|
|
+ devm_regmap_init_mmio(&pdev->dev, base, &rd_regmap_config);
|
|
+ if (IS_ERR(rd->regmap))
|
|
+ return PTR_ERR(rd->regmap);
|
|
+
|
|
+ platform_set_drvdata(pdev, rd);
|
|
+
|
|
+ rd->data = device_get_match_data(&pdev->dev);
|
|
+ if (rd->data && rd->data->init) {
|
|
+ ret = rd->data->init(&pdev->dev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ pm_runtime_enable(&pdev->dev);
|
|
+ if (!pm_runtime_enabled(&pdev->dev)) {
|
|
+ ret = rk_dsm_runtime_resume(&pdev->dev);
|
|
+ if (ret)
|
|
+ goto err_pm_disable;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rd->regmap, DACPWM_CTRL,
|
|
+ DSM_DACPWM_CTRL_PWM_MODE_MASK,
|
|
+ DSM_DACPWM_CTRL_PWM_MODE_0);
|
|
+
|
|
+ rd->pa_ctl = devm_gpiod_get_optional(&pdev->dev, "pa-ctl",
|
|
+ GPIOD_OUT_LOW);
|
|
+
|
|
+ if (!rd->pa_ctl) {
|
|
+ dev_info(&pdev->dev, "no need pa-ctl gpio\n");
|
|
+ } else if (IS_ERR(rd->pa_ctl)) {
|
|
+ ret = PTR_ERR(rd->pa_ctl);
|
|
+ dev_err(&pdev->dev, "fail to request gpio pa-ctl\n");
|
|
+ goto err_suspend;
|
|
+ }
|
|
+
|
|
+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rd,
|
|
+ rd_dai, ARRAY_SIZE(rd_dai));
|
|
+
|
|
+ if (ret)
|
|
+ goto err_suspend;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_suspend:
|
|
+ if (!pm_runtime_status_suspended(&pdev->dev))
|
|
+ rk_dsm_runtime_suspend(&pdev->dev);
|
|
+err_pm_disable:
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
+
|
|
+ if (rd->data && rd->data->deinit)
|
|
+ rd->data->deinit(&pdev->dev);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void rk_dsm_platform_remove(struct platform_device *pdev)
|
|
+{
|
|
+ struct rk_dsm_priv *rd = dev_get_drvdata(&pdev->dev);
|
|
+
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
+ if (!pm_runtime_status_suspended(&pdev->dev))
|
|
+ rk_dsm_runtime_suspend(&pdev->dev);
|
|
+
|
|
+ if (rd->data && rd->data->deinit)
|
|
+ rd->data->deinit(&pdev->dev);
|
|
+}
|
|
+
|
|
+static const struct dev_pm_ops rd_pm = {
|
|
+ SET_RUNTIME_PM_OPS(rk_dsm_runtime_suspend,
|
|
+ rk_dsm_runtime_resume, NULL)
|
|
+};
|
|
+
|
|
+static struct platform_driver rk_dsm_driver = {
|
|
+ .driver = {
|
|
+ .name = "rk_dsm",
|
|
+ .of_match_table = of_match_ptr(rd_of_match),
|
|
+ .pm = &rd_pm,
|
|
+ },
|
|
+ .probe = rk_dsm_platform_probe,
|
|
+ .remove = rk_dsm_platform_remove,
|
|
+};
|
|
+module_platform_driver(rk_dsm_driver);
|
|
+
|
|
+MODULE_AUTHOR("Jason Zhu <jason.zhu@rock-chips.com>");
|
|
+MODULE_DESCRIPTION("ASoC Rockchip Delta-sigma Digital Converter Driver");
|
|
+MODULE_LICENSE("GPL");
|
|
diff --git a/sound/soc/codecs/rk_dsm.h b/sound/soc/codecs/rk_dsm.h
|
|
new file mode 100644
|
|
index 000000000..553b1c490
|
|
--- /dev/null
|
|
+++ b/sound/soc/codecs/rk_dsm.h
|
|
@@ -0,0 +1,168 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
+/*
|
|
+ * Rockchip Audio Delta-sigma Digital Converter driver
|
|
+ *
|
|
+ * Copyright (C) 2023 Rockchip Electronics Co., Ltd
|
|
+ *
|
|
+ */
|
|
+
|
|
+#ifndef _RK_DSM_H
|
|
+#define _RK_DSM_H
|
|
+
|
|
+#define DACVUCTL 0x0000
|
|
+#define DACVUCTIME 0x0004
|
|
+#define DACDIGEN 0x0008
|
|
+#define DACCLKCTRL 0x000c
|
|
+#define DACINT_DIV 0x0014
|
|
+#define DACSCLKRXINT_DIV 0x0020
|
|
+#define DACPWM_DIV 0x0024
|
|
+#define DACPWM_CTRL 0x0028
|
|
+#define DACCFG1 0x0044
|
|
+#define DACMUTE 0x0048
|
|
+#define DACMUTEST 0x004c
|
|
+#define DACVOLL0 0x0050
|
|
+#define DACVOLL1 0x0054
|
|
+#define DACVOLL2 0x0058
|
|
+#define DACVOLL3 0x005c
|
|
+#define DACVOLR0 0x0060
|
|
+#define DACVOLR1 0x0064
|
|
+#define DACVOLR2 0x0068
|
|
+#define DACVOLR3 0x006c
|
|
+#define DACVOGP 0x0070
|
|
+#define DACRVOLL0 0x0074
|
|
+#define DACRVOLL1 0x0078
|
|
+#define DACRVOLL2 0x007c
|
|
+#define DACRVOLL3 0x0080
|
|
+#define DACRVOLR0 0x0084
|
|
+#define DACRVOLR1 0x0088
|
|
+#define DACRVOLR2 0x008c
|
|
+#define DACRVOLR3 0x0090
|
|
+#define DACLMT0 0x0094
|
|
+#define DACLMT1 0x0098
|
|
+#define DACLMT2 0x009c
|
|
+#define DACMIXCTRLL 0x00a0
|
|
+#define DACMIXCTRLR 0x00a4
|
|
+#define DACHPF 0x00a8
|
|
+#define I2S_RXCR0 0x010c
|
|
+#define I2S_RXCR1 0x0110
|
|
+#define I2S_CKR0 0x0114
|
|
+#define I2S_CKR1 0x0118
|
|
+#define I2S_XFER 0x011c
|
|
+#define I2S_CLR 0x0120
|
|
+#define VERSION 0x0140
|
|
+
|
|
+/* DACDIGEN */
|
|
+#define DSM_DACDIGEN_DACEN_L0R1_MASK BIT(0)
|
|
+#define DSM_DACDIGEN_DACEN_L0R1_EN BIT(0)
|
|
+#define DSM_DACDIGEN_DACEN_L0R1_DIS 0
|
|
+#define DSM_DACDIGEN_DAC_GLBEN_MASK BIT(4)
|
|
+#define DSM_DACDIGEN_DAC_GLBEN_EN BIT(4)
|
|
+#define DSM_DACDIGEN_DAC_GLBEN_DIS 0
|
|
+/* DACCLKCTRL */
|
|
+#define DSM_DACCLKCTRL_DAC_MODE_ATTENU_MASK BIT(0)
|
|
+#define DSM_DACCLKCTRL_DAC_MODE_ATTENU_EN BIT(0)
|
|
+#define DSM_DACCLKCTRL_DAC_MODE_ATTENU_DIS 0
|
|
+#define DSM_DACCLKCTRL_DAC_SYNC_STATUS_MASK BIT(1)
|
|
+#define DSM_DACCLKCTRL_DAC_SYNC_STATUS_DONE 0
|
|
+#define DSM_DACCLKCTRL_DAC_SYNC_ENA_MASK BIT(2)
|
|
+#define DSM_DACCLKCTRL_DAC_SYNC_ENA_EN BIT(2)
|
|
+#define DSM_DACCLKCTRL_DAC_SYNC_ENA_DIS 0
|
|
+#define DSM_DACCLKCTRL_CKE_BCLKRX_MASK BIT(3)
|
|
+#define DSM_DACCLKCTRL_CKE_BCLKRX_EN BIT(3)
|
|
+#define DSM_DACCLKCTRL_CKE_BCLKRX_DIS 0
|
|
+#define DSM_DACCLKCTRL_I2SRX_CKE_MASK BIT(4)
|
|
+#define DSM_DACCLKCTRL_I2SRX_CKE_EN BIT(4)
|
|
+#define DSM_DACCLKCTRL_I2SRX_CKE_DIS 0
|
|
+#define DSM_DACCLKCTRL_DAC_CKE_MASK BIT(5)
|
|
+#define DSM_DACCLKCTRL_DAC_CKE_EN BIT(5)
|
|
+#define DSM_DACCLKCTRL_DAC_CKE_DIS 0
|
|
+/* DACINT_DIV */
|
|
+#define DSM_DACINT_DIV_INT_DIV_CON_MASK GENMASK(7, 0)
|
|
+#define DSM_DACINT_DIV_INT_DIV_CON(x) ((x) - 1)
|
|
+/* DACSCLKRXINT_DIV */
|
|
+#define DSM_DACSCLKRXINT_DIV_SCKRXDIV_MASK GENMASK(7, 0)
|
|
+#define DSM_DACSCLKRXINT_DIV_SCKRXDIV(x) ((x) - 1)
|
|
+/* DACPWM_DIV */
|
|
+#define DSM_DACPWM_DIV_AUDIO_PWM_DIV_MASK GENMASK(7, 0)
|
|
+#define DSM_DACPWM_DIV_AUDIO_PWM_DIV(x) ((x) - 1)
|
|
+/* DACPWM_CTRL */
|
|
+#define DSM_DACPWM_CTRL_DITH_SEL_MASK GENMASK(2, 0)
|
|
+#define DSM_DACPWM_CTRL_DITH_SEL(x) (x)
|
|
+#define DSM_DACPWM_CTRL_PWM_EN_MASK BIT(3)
|
|
+#define DSM_DACPWM_CTRL_PWM_EN BIT(3)
|
|
+#define DSM_DACPWM_CTRL_PWM_DIS 0
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_MASK GENMASK(5, 4)
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_1 (0x2 << 4)
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_0 (0x1 << 4)
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_DAC (0x0 << 4)
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_CKE_MASK BIT(6)
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_CKE_EN BIT(6)
|
|
+#define DSM_DACPWM_CTRL_PWM_MODE_CKE_DIS 0
|
|
+/* DACCFG1 */
|
|
+#define DSM_DACCFG1_DACSRT_MASK GENMASK(4, 2)
|
|
+#define DSM_DACCFG1_DACSRT(x) ((x) << 2)
|
|
+/* DACMUTE */
|
|
+#define DSM_DACMUTE_DACMT_MASK BIT(0)
|
|
+#define DSM_DACMUTE_DACUNMT_MASK BIT(1)
|
|
+/* DACVOLL0 */
|
|
+#define DSM_DACVOLL0_DACLV0_MASK GENMASK(7, 0)
|
|
+#define DSM_DACVOLL0_DACLV0(x) (x)
|
|
+/* DACVOLR0 */
|
|
+#define DSM_DACVOLR0_DACRV0_MASK GENMASK(7, 0)
|
|
+#define DSM_DACVOLR0_DACRV0(x) (x)
|
|
+/* DACVOGP */
|
|
+#define DSM_DACVOGP_VOLGPL0_MASK BIT(0)
|
|
+#define DSM_DACVOGP_VOLGPL0_POS BIT(0)
|
|
+#define DSM_DACVOGP_VOLGPL0_NEG 0
|
|
+#define DSM_DACVOGP_VOLGPR0_MASK BIT(1)
|
|
+#define DSM_DACVOGP_VOLGPR0_POS BIT(1)
|
|
+#define DSM_DACVOGP_VOLGPR0_NEG 0
|
|
+/* DACMIXCTRLL */
|
|
+#define DSM_DACMIXCTRLL_MIXMODE_L0_MASK GENMASK(1, 0)
|
|
+#define DSM_DACMIXCTRLL_MIXMODE_L0_LR 2
|
|
+#define DSM_DACMIXCTRLL_MIXMODE_L0_R 1
|
|
+#define DSM_DACMIXCTRLL_MIXMODE_L0_L 0
|
|
+/* DACMIXCTRLR */
|
|
+#define DSM_DACMIXCTRLR_MIXMODE_R0_MASK GENMASK(1, 0)
|
|
+#define DSM_DACMIXCTRLR_MIXMODE_R0_LR 2
|
|
+#define DSM_DACMIXCTRLR_MIXMODE_R0_L 1
|
|
+#define DSM_DACMIXCTRLR_MIXMODE_R0_R 0
|
|
+/* DACHPF */
|
|
+#define DSM_DACHPF_HPFEN_L0R0_MASK BIT(0)
|
|
+#define DSM_DACHPF_HPFEN_L0R0_EN BIT(0)
|
|
+#define DSM_DACHPF_HPFCF_MASK GENMASK(5, 4)
|
|
+#define DSM_DACHPF_HPFCF_140HZ (0x3 << 4)
|
|
+#define DSM_DACHPF_HPFCF_120HZ (0x2 << 4)
|
|
+#define DSM_DACHPF_HPFCF_100HZ (0x1 << 4)
|
|
+#define DSM_DACHPF_HPFCF_80HZ (0x0 << 4)
|
|
+/* I2S_RXCR0 */
|
|
+#define DSM_I2S_RXCR0_VDW_MASK GENMASK(4, 0)
|
|
+#define DSM_I2S_RXCR0_VDW(x) ((x) - 1)
|
|
+/* I2S_RXCR1 */
|
|
+#define DSM_I2S_RXCR1_CEX_MASK BIT(4)
|
|
+#define DSM_I2S_RXCR1_CEX_EXCHANGE BIT(4)
|
|
+#define DSM_I2S_RXCR1_RCSR_MASK GENMASK(7, 6)
|
|
+#define DSM_I2S_RXCR1_RCSR_2CH (0x0 << 6)
|
|
+/* I2S_CKR0 */
|
|
+#define DSM_I2S_CKR0_RSD_MASK GENMASK(3, 2)
|
|
+#define DSM_I2S_CKR0_RSD_64 (0 << 2)
|
|
+#define DSM_I2S_CKR0_RSD_128 (1 << 2)
|
|
+#define DSM_I2S_CKR0_RSD_256 (2 << 2)
|
|
+/* I2S_CKR1 */
|
|
+#define DSM_I2S_CKR1_RLP_MASK BIT(1)
|
|
+#define DSM_I2S_CKR1_RLP_INVERTED BIT(1)
|
|
+#define DSM_I2S_CKR1_RLP_NORMAL 0
|
|
+#define DSM_I2S_CKR1_CKP_MASK BIT(2)
|
|
+#define DSM_I2S_CKR1_CKP_INVERTED BIT(2)
|
|
+#define DSM_I2S_CKR1_CKP_NORMAL 0
|
|
+#define DSM_I2S_CKR1_MSS_MASK BIT(3)
|
|
+#define DSM_I2S_CKR1_MSS_MASTER 0
|
|
+/* I2S_XFER */
|
|
+#define DSM_I2S_XFER_RXS_MASK BIT(1)
|
|
+#define DSM_I2S_XFER_RXS_START BIT(1)
|
|
+#define DSM_I2S_XFER_RXS_STOP 0
|
|
+/* I2S_CLR */
|
|
+#define DSM_I2S_CLR_RXC_MASK BIT(1)
|
|
+#define DSM_I2S_CLR_RXC_CLR BIT(1)
|
|
+
|
|
+#endif
|
|
diff --git a/sound/soc/codecs/rv1106_codec.c b/sound/soc/codecs/rv1106_codec.c
|
|
new file mode 100644
|
|
index 000000000..32d5acc0c
|
|
--- /dev/null
|
|
+++ b/sound/soc/codecs/rv1106_codec.c
|
|
@@ -0,0 +1,2332 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * rv1106_codec.c - Rockchip RV1106 SoC Codec Driver
|
|
+ *
|
|
+ * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
|
+ */
|
|
+
|
|
+#include <linux/clk.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/gpio/consumer.h>
|
|
+#include <linux/mfd/syscon.h>
|
|
+#include <linux/of_device.h>
|
|
+#include <linux/of_platform.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/pm_runtime.h>
|
|
+#include <linux/regmap.h>
|
|
+#include <linux/regulator/consumer.h>
|
|
+#include <linux/reset.h>
|
|
+#include <sound/pcm_params.h>
|
|
+#include <sound/soc.h>
|
|
+#include <sound/tlv.h>
|
|
+
|
|
+/*
|
|
+ * 6.18 port note: <linux/rockchip/grf.h> is a vendor-BSP-only header not
|
|
+ * present in mainline. Nothing in this file actually uses symbols from it
|
|
+ * (PERI_GRF_PERI_CON1 is defined locally below and the GRF is accessed via
|
|
+ * the generic syscon/regmap API), so the include is simply dropped.
|
|
+ * <linux/of_gpio.h> is replaced with <linux/gpio/consumer.h>, which is
|
|
+ * where gpiod_direction_output()/devm_gpiod_get_optional() actually live.
|
|
+ */
|
|
+
|
|
+#include "rv1106_codec.h"
|
|
+
|
|
+#if defined(CONFIG_DEBUG_FS)
|
|
+#include <linux/fs.h>
|
|
+#include <linux/debugfs.h>
|
|
+#include <linux/seq_file.h>
|
|
+#endif
|
|
+
|
|
+#define CODEC_DRV_NAME "rv1106-acodec"
|
|
+
|
|
+#define PERI_GRF_PERI_CON1 0x004
|
|
+#define ACODEC_AD2DA_LOOP_MSK (1 << 23)
|
|
+#define ACODEC_AD2DA_LOOP_EN (1 << 7)
|
|
+#define ACODEC_AD2DA_LOOP_DIS (1 << 7)
|
|
+/* Control the i2s sdo sdi interface that connect to internal acodec
|
|
+ * 1: connect to internal acodec
|
|
+ * 0: connect to external acodec
|
|
+ */
|
|
+#define ACODEC_MSK (1 << 22)
|
|
+#define ACODEC_EN (1 << 6)
|
|
+#define ACODEC_DIS (0 << 6)
|
|
+
|
|
+#define LR(b, x, v) (((1 << b) & x) ? v : 0)
|
|
+#define L(x, v) LR(0, x, v)
|
|
+#define R(x, v) LR(1, x, v)
|
|
+
|
|
+#define ADCL (1 << 0)
|
|
+#define ADCR (1 << 1)
|
|
+
|
|
+#define NOT_SPECIFIED (-1)
|
|
+
|
|
+enum soc_id_e {
|
|
+ SOC_RV1103 = 0x1103,
|
|
+ SOC_RV1106 = 0x1106,
|
|
+};
|
|
+
|
|
+enum adc_mode_e {
|
|
+ DIFF_ADCL = 0, /* Differential ADCL, the ADCR is not used */
|
|
+ SING_ADCL, /* Single-end ADCL, the ADCR is not used */
|
|
+ DIFF_ADCR, /* Differential ADCR, the ADCL is not used */
|
|
+ SING_ADCR, /* Single-end ADCR, the ADCL is not used */
|
|
+ SING_ADCLR, /* Single-end ADCL and ADCR */
|
|
+ DIFF_ADCLR, /* Differential ADCL and ADCR (Not supported on rv1103 codec) */
|
|
+ ADC_MODE_NUM,
|
|
+};
|
|
+
|
|
+struct rv1106_codec_priv {
|
|
+ const struct device *plat_dev;
|
|
+ struct device dev;
|
|
+ struct reset_control *reset;
|
|
+ struct regmap *regmap;
|
|
+ struct regmap *grf;
|
|
+ struct clk *pclk_acodec;
|
|
+ struct clk *mclk_acodec;
|
|
+ struct clk *mclk_cpu;
|
|
+ struct gpio_desc *pa_ctl_gpio;
|
|
+ struct snd_soc_component *component;
|
|
+
|
|
+ enum adc_mode_e adc_mode;
|
|
+ enum soc_id_e soc_id;
|
|
+
|
|
+ u32 pa_ctl_delay_ms;
|
|
+ u32 micbias_volt;
|
|
+
|
|
+ /* AGC L/R Off/on */
|
|
+ unsigned int agc_l;
|
|
+ unsigned int agc_r;
|
|
+
|
|
+ /* AGC L/R Approximate Sample Rate */
|
|
+ unsigned int agc_asr_l;
|
|
+ unsigned int agc_asr_r;
|
|
+
|
|
+ /* ADC MIC Mute/Work */
|
|
+ unsigned int mic_mute_l;
|
|
+ unsigned int mic_mute_r;
|
|
+
|
|
+ /* DAC Control Manually */
|
|
+ unsigned int dac_ctrl_manual;
|
|
+
|
|
+ /* For the high pass filter */
|
|
+ unsigned int hpf_cutoff;
|
|
+
|
|
+ /* Specify init gains after codec startup */
|
|
+ unsigned int init_mic_gain;
|
|
+ unsigned int init_alc_gain;
|
|
+ unsigned int init_lineout_gain;
|
|
+
|
|
+ bool adc_enable;
|
|
+ bool dac_enable;
|
|
+ bool micbias_enable;
|
|
+ bool micbias_used;
|
|
+
|
|
+#if defined(CONFIG_DEBUG_FS)
|
|
+ struct dentry *dbg_codec;
|
|
+#endif
|
|
+};
|
|
+
|
|
+static const DECLARE_TLV_DB_SCALE(rv1106_codec_alc_agc_gain_tlv,
|
|
+ -1800, 150, 2850);
|
|
+static const DECLARE_TLV_DB_SCALE(rv1106_codec_alc_agc_max_gain_tlv,
|
|
+ -1350, 600, 2850);
|
|
+static const DECLARE_TLV_DB_SCALE(rv1106_codec_alc_agc_min_gain_tlv,
|
|
+ -1800, 600, 2400);
|
|
+static const DECLARE_TLV_DB_SCALE(rv1106_codec_adc_alc_gain_tlv,
|
|
+ -900, 150, 3750);
|
|
+static const DECLARE_TLV_DB_SCALE(rv1106_codec_adc_dig_gain_tlv,
|
|
+ -9750, 50, 3000);
|
|
+static const DECLARE_TLV_DB_SCALE(rv1106_codec_dac_lineout_gain_tlv,
|
|
+ -3900, 150, 600);
|
|
+
|
|
+static const DECLARE_TLV_DB_RANGE(rv1106_codec_adc_mic_gain_tlv,
|
|
+ 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0),
|
|
+ 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
|
|
+ 3, 3, TLV_DB_SCALE_ITEM(1200, 0, 0),
|
|
+);
|
|
+
|
|
+static const DECLARE_TLV_DB_RANGE(rv1106_codec_dac_hpmix_gain_tlv,
|
|
+ 1, 2, TLV_DB_SCALE_ITEM(0, 600, 0),
|
|
+);
|
|
+
|
|
+static int check_micbias(int volt);
|
|
+
|
|
+static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106);
|
|
+static int rv1106_codec_adc_disable(struct rv1106_codec_priv *rv1106);
|
|
+
|
|
+static int rv1106_codec_micbias_enable(struct rv1106_codec_priv *rv1106,
|
|
+ int micbias_volt);
|
|
+static int rv1106_codec_hpmix_gain_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_hpmix_gain_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_micbias_disable(struct rv1106_codec_priv *rv1106);
|
|
+static int rv1106_codec_hpf_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_hpf_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_adc_mode_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_adc_mode_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_agc_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_agc_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_agc_asr_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_agc_asr_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_mic_mute_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_mic_mute_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_mic_gain_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_mic_gain_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_micbias_volts_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_micbias_volts_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_main_micbias_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_main_micbias_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_dac_ctrl_manual_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+static int rv1106_codec_dac_ctrl_manual_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol);
|
|
+
|
|
+static const char *offon_text[2] = {
|
|
+ [0] = "Off",
|
|
+ [1] = "On",
|
|
+};
|
|
+
|
|
+static const char *noneoffon_text[3] = {
|
|
+ [0] = "None",
|
|
+ [1] = "Off",
|
|
+ [2] = "On",
|
|
+};
|
|
+
|
|
+static const char *mute_text[2] = {
|
|
+ [0] = "Work",
|
|
+ [1] = "Mute",
|
|
+};
|
|
+
|
|
+/* ADC MICBIAS Volt */
|
|
+#define MICBIAS_VOLT_NUM 8
|
|
+
|
|
+#define MICBIAS_VREFx0_8 0
|
|
+#define MICBIAS_VREFx0_825 1
|
|
+#define MICBIAS_VREFx0_85 2
|
|
+#define MICBIAS_VREFx0_875 3
|
|
+#define MICBIAS_VREFx0_9 4
|
|
+#define MICBIAS_VREFx0_925 5
|
|
+#define MICBIAS_VREFx0_95 6
|
|
+#define MICBIAS_VREFx0_975 7
|
|
+
|
|
+static const char *micbias_volts_enum_array[MICBIAS_VOLT_NUM] = {
|
|
+ [MICBIAS_VREFx0_8] = "VREFx0_8",
|
|
+ [MICBIAS_VREFx0_825] = "VREFx0_825",
|
|
+ [MICBIAS_VREFx0_85] = "VREFx0_85",
|
|
+ [MICBIAS_VREFx0_875] = "VREFx0_875",
|
|
+ [MICBIAS_VREFx0_9] = "VREFx0_9",
|
|
+ [MICBIAS_VREFx0_925] = "VREFx0_925",
|
|
+ [MICBIAS_VREFx0_95] = "VREFx0_95",
|
|
+ [MICBIAS_VREFx0_975] = "VREFx0_975",
|
|
+};
|
|
+
|
|
+static const char *adc_mode_enum_array[ADC_MODE_NUM] = {
|
|
+ [DIFF_ADCL] = "DiffadcL",
|
|
+ [SING_ADCL] = "SingadcL",
|
|
+ [DIFF_ADCR] = "DiffadcR",
|
|
+ [SING_ADCR] = "SingadcR",
|
|
+ [SING_ADCLR] = "SingadcLR",
|
|
+ [DIFF_ADCLR] = "DiffadcLR",
|
|
+};
|
|
+
|
|
+static const struct soc_enum rv1106_adc_mode_enum_array[] = {
|
|
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adc_mode_enum_array), adc_mode_enum_array),
|
|
+};
|
|
+
|
|
+static const struct soc_enum rv1106_micbias_volts_enum_array[] = {
|
|
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(micbias_volts_enum_array), micbias_volts_enum_array),
|
|
+};
|
|
+
|
|
+/* ADC MICBIAS Main Switch */
|
|
+static const struct soc_enum rv1106_main_micbias_enum_array[] = {
|
|
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text),
|
|
+};
|
|
+
|
|
+static const struct soc_enum rv1106_hpf_enum_array[] = {
|
|
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text),
|
|
+};
|
|
+
|
|
+/* ALC AGC Switch */
|
|
+static const struct soc_enum rv1106_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),
|
|
+};
|
|
+
|
|
+/* ADC MIC Mute/Work Switch */
|
|
+static const struct soc_enum rv1106_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),
|
|
+};
|
|
+
|
|
+/* DAC Control Manually */
|
|
+static const struct soc_enum rv1106_dac_pa_ctrl_maunal_enum_array[] = {
|
|
+ SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(noneoffon_text), noneoffon_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 rv1106_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),
|
|
+};
|
|
+
|
|
+static const struct snd_kcontrol_new rv1106_codec_dapm_controls[] = {
|
|
+ /* ADC MIC */
|
|
+ SOC_SINGLE_EXT_TLV("ADC MIC Left Gain",
|
|
+ ACODEC_ADC_ANA_CTL2,
|
|
+ ACODEC_ADC_L_MIC_GAIN_SFT,
|
|
+ ACODEC_ADC_MIC_GAIN_MAX,
|
|
+ 0,
|
|
+ rv1106_codec_mic_gain_get,
|
|
+ rv1106_codec_mic_gain_put,
|
|
+ rv1106_codec_adc_mic_gain_tlv),
|
|
+ SOC_SINGLE_EXT_TLV("ADC MIC Right Gain",
|
|
+ ACODEC_ADC_ANA_CTL2,
|
|
+ ACODEC_ADC_R_MIC_GAIN_SFT,
|
|
+ ACODEC_ADC_MIC_GAIN_MAX,
|
|
+ 0,
|
|
+ rv1106_codec_mic_gain_get,
|
|
+ rv1106_codec_mic_gain_put,
|
|
+ rv1106_codec_adc_mic_gain_tlv),
|
|
+
|
|
+ /* ADC ALC */
|
|
+ SOC_SINGLE_RANGE_TLV("ADC ALC Left Volume",
|
|
+ ACODEC_ADC_ANA_CTL4,
|
|
+ ACODEC_ADC_L_ALC_GAIN_SFT,
|
|
+ ACODEC_ADC_L_ALC_GAIN_MIN,
|
|
+ ACODEC_ADC_L_ALC_GAIN_MAX,
|
|
+ 0, rv1106_codec_adc_alc_gain_tlv),
|
|
+ SOC_SINGLE_RANGE_TLV("ADC ALC Right Volume",
|
|
+ ACODEC_ADC_ANA_CTL5,
|
|
+ ACODEC_ADC_R_ALC_GAIN_SFT,
|
|
+ ACODEC_ADC_R_ALC_GAIN_MIN,
|
|
+ ACODEC_ADC_R_ALC_GAIN_MAX,
|
|
+ 0, rv1106_codec_adc_alc_gain_tlv),
|
|
+
|
|
+ /* ADC Digital Volume */
|
|
+ SOC_SINGLE_RANGE_TLV("ADC Digital Left Volume",
|
|
+ ACODEC_ADC_L_DIG_VOL,
|
|
+ ACODEC_ADC_L_DIG_VOL_SFT,
|
|
+ ACODEC_ADC_L_DIG_VOL_MIN,
|
|
+ ACODEC_ADC_L_DIG_VOL_MAX,
|
|
+ 0, rv1106_codec_adc_dig_gain_tlv),
|
|
+ SOC_SINGLE_RANGE_TLV("ADC Digital Right Volume",
|
|
+ ACODEC_ADC_R_DIG_VOL,
|
|
+ ACODEC_ADC_R_DIG_VOL_SFT,
|
|
+ ACODEC_ADC_R_DIG_VOL_MIN,
|
|
+ ACODEC_ADC_R_DIG_VOL_MAX,
|
|
+ 0, rv1106_codec_adc_dig_gain_tlv),
|
|
+
|
|
+ /* ADC High Pass Filter */
|
|
+ SOC_ENUM_EXT("ADC HPF Cut-off", rv1106_hpf_enum_array[0],
|
|
+ rv1106_codec_hpf_get, rv1106_codec_hpf_put),
|
|
+
|
|
+ /* ALC AGC Group */
|
|
+ SOC_SINGLE_RANGE_TLV("ALC AGC Left Volume",
|
|
+ ACODEC_ADC_PGA_AGC_L_CTL3,
|
|
+ ACODEC_AGC_PGA_GAIN_SFT,
|
|
+ ACODEC_AGC_PGA_GAIN_MIN,
|
|
+ ACODEC_AGC_PGA_GAIN_MAX,
|
|
+ 0, rv1106_codec_alc_agc_gain_tlv),
|
|
+ SOC_SINGLE_RANGE_TLV("ALC AGC Right Volume",
|
|
+ ACODEC_ADC_PGA_AGC_R_CTL3,
|
|
+ ACODEC_AGC_PGA_GAIN_SFT,
|
|
+ ACODEC_AGC_PGA_GAIN_MIN,
|
|
+ ACODEC_AGC_PGA_GAIN_MAX,
|
|
+ 0, rv1106_codec_alc_agc_gain_tlv),
|
|
+
|
|
+ /* ALC AGC MAX */
|
|
+ SOC_SINGLE_RANGE_TLV("ALC AGC Left Max Volume",
|
|
+ ACODEC_ADC_PGA_AGC_L_CTL9,
|
|
+ ACODEC_AGC_MAX_GAIN_PGA_SFT,
|
|
+ ACODEC_AGC_MAX_GAIN_PGA_MIN,
|
|
+ ACODEC_AGC_MAX_GAIN_PGA_MAX,
|
|
+ 0, rv1106_codec_alc_agc_max_gain_tlv),
|
|
+ SOC_SINGLE_RANGE_TLV("ALC AGC Right Max Volume",
|
|
+ ACODEC_ADC_PGA_AGC_R_CTL9,
|
|
+ ACODEC_AGC_MAX_GAIN_PGA_SFT,
|
|
+ ACODEC_AGC_MAX_GAIN_PGA_MIN,
|
|
+ ACODEC_AGC_MAX_GAIN_PGA_MAX,
|
|
+ 0, rv1106_codec_alc_agc_max_gain_tlv),
|
|
+
|
|
+ /* ALC AGC MIN */
|
|
+ SOC_SINGLE_RANGE_TLV("ALC AGC Left Min Volume",
|
|
+ ACODEC_ADC_PGA_AGC_L_CTL9,
|
|
+ ACODEC_AGC_MIN_GAIN_PGA_SFT,
|
|
+ ACODEC_AGC_MIN_GAIN_PGA_MIN,
|
|
+ ACODEC_AGC_MIN_GAIN_PGA_MAX,
|
|
+ 0, rv1106_codec_alc_agc_min_gain_tlv),
|
|
+ SOC_SINGLE_RANGE_TLV("ALC AGC Right Min Volume",
|
|
+ ACODEC_ADC_PGA_AGC_R_CTL9,
|
|
+ ACODEC_AGC_MIN_GAIN_PGA_SFT,
|
|
+ ACODEC_AGC_MIN_GAIN_PGA_MIN,
|
|
+ ACODEC_AGC_MIN_GAIN_PGA_MAX,
|
|
+ 0, rv1106_codec_alc_agc_min_gain_tlv),
|
|
+
|
|
+ /* ALC AGC Switch */
|
|
+ SOC_ENUM_EXT("ALC AGC Left Switch", rv1106_agc_enum_array[0],
|
|
+ rv1106_codec_agc_get, rv1106_codec_agc_put),
|
|
+ SOC_ENUM_EXT("ALC AGC Right Switch", rv1106_agc_enum_array[1],
|
|
+ rv1106_codec_agc_get, rv1106_codec_agc_put),
|
|
+
|
|
+ /* ALC AGC Approximate Sample Rate */
|
|
+ SOC_ENUM_EXT("AGC Left Approximate Sample Rate", rv1106_agc_asr_enum_array[0],
|
|
+ rv1106_codec_agc_asr_get, rv1106_codec_agc_asr_put),
|
|
+ SOC_ENUM_EXT("AGC Right Approximate Sample Rate", rv1106_agc_asr_enum_array[1],
|
|
+ rv1106_codec_agc_asr_get, rv1106_codec_agc_asr_put),
|
|
+
|
|
+ /* ADC Mode */
|
|
+ SOC_ENUM_EXT("ADC Mode", rv1106_adc_mode_enum_array[0],
|
|
+ rv1106_codec_adc_mode_get, rv1106_codec_adc_mode_put),
|
|
+
|
|
+ /* ADC MICBIAS Voltage */
|
|
+ SOC_ENUM_EXT("ADC MICBIAS Voltage", rv1106_micbias_volts_enum_array[0],
|
|
+ rv1106_codec_micbias_volts_get, rv1106_codec_micbias_volts_put),
|
|
+
|
|
+ /* ADC Main MICBIAS Switch */
|
|
+ SOC_ENUM_EXT("ADC Main MICBIAS", rv1106_main_micbias_enum_array[0],
|
|
+ rv1106_codec_main_micbias_get, rv1106_codec_main_micbias_put),
|
|
+
|
|
+ /* ADC MIC Mute/Work Switch */
|
|
+ SOC_ENUM_EXT("ADC MIC Left Switch", rv1106_mic_mute_enum_array[0],
|
|
+ rv1106_codec_mic_mute_get, rv1106_codec_mic_mute_put),
|
|
+ SOC_ENUM_EXT("ADC MIC Right Switch", rv1106_mic_mute_enum_array[1],
|
|
+ rv1106_codec_mic_mute_get, rv1106_codec_mic_mute_put),
|
|
+
|
|
+ /* DAC LINEOUT */
|
|
+ SOC_SINGLE_RANGE_TLV("DAC LINEOUT Volume",
|
|
+ ACODEC_DAC_ANA_CTL2,
|
|
+ ACODEC_DAC_LINEOUT_GAIN_SFT,
|
|
+ ACODEC_DAC_LINEOUT_GAIN_MIN,
|
|
+ ACODEC_DAC_LINEOUT_GAIN_MAX,
|
|
+ 0, rv1106_codec_dac_lineout_gain_tlv),
|
|
+
|
|
+ /* DAC HPMIX */
|
|
+ SOC_SINGLE_EXT_TLV("DAC HPMIX Volume",
|
|
+ ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_GAIN_SFT,
|
|
+ ACODEC_DAC_HPMIX_GAIN_MAX,
|
|
+ 0,
|
|
+ rv1106_codec_hpmix_gain_get,
|
|
+ rv1106_codec_hpmix_gain_put,
|
|
+ rv1106_codec_dac_hpmix_gain_tlv),
|
|
+
|
|
+ /* DAC Control Manually */
|
|
+ SOC_ENUM_EXT("DAC Control Manually", rv1106_dac_pa_ctrl_maunal_enum_array[0],
|
|
+ rv1106_codec_dac_ctrl_manual_get, rv1106_codec_dac_ctrl_manual_put),
|
|
+};
|
|
+
|
|
+static unsigned int using_adc_lr(enum adc_mode_e adc_mode)
|
|
+{
|
|
+ if (adc_mode >= SING_ADCLR && adc_mode <= DIFF_ADCLR)
|
|
+ return (ADCL | ADCR);
|
|
+ else if (adc_mode >= DIFF_ADCR && adc_mode <= SING_ADCR)
|
|
+ return ADCR;
|
|
+ else
|
|
+ return ADCL;
|
|
+}
|
|
+
|
|
+static bool using_adc_diff(enum adc_mode_e adc_mode)
|
|
+{
|
|
+ if (adc_mode == DIFF_ADCL ||
|
|
+ adc_mode == DIFF_ADCR ||
|
|
+ adc_mode == DIFF_ADCLR)
|
|
+ return true;
|
|
+ else
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static int check_adc_mode(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ if (rv1106->soc_id == SOC_RV1103 &&
|
|
+ (rv1106->adc_mode == DIFF_ADCLR ||
|
|
+ rv1106->adc_mode == DIFF_ADCR)) {
|
|
+ dev_err(rv1106->plat_dev,
|
|
+ "%s: Differential mode rv1103 only supports 'DiffadcL'\n", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_adc_mode_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ ucontrol->value.integer.value[0] = rv1106->adc_mode;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_adc_mode_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int last_mode = rv1106->adc_mode;
|
|
+
|
|
+ rv1106->adc_mode = ucontrol->value.integer.value[0];
|
|
+ if (check_adc_mode(rv1106)) {
|
|
+ dev_err(rv1106->plat_dev,
|
|
+ "%s - something error checking ADC mode\n", __func__);
|
|
+ rv1106->adc_mode = last_mode;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_agc_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+
|
|
+ if (e->shift_l)
|
|
+ ucontrol->value.integer.value[0] = rv1106->agc_r;
|
|
+ else
|
|
+ ucontrol->value.integer.value[0] = rv1106->agc_l;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_agc_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = 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 (value) {
|
|
+ /* ALC AGC On */
|
|
+ if (e->shift_l) {
|
|
+ /* ALC AGC Right On */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_PGA_AGC_R_CTL9,
|
|
+ ACODEC_AGC_FUNC_SEL_MSK,
|
|
+ ACODEC_AGC_FUNC_SEL_EN);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL,
|
|
+ ACODEC_ADC_R_PGA_MSK,
|
|
+ ACODEC_ADC_PGA_ALCR_EN);
|
|
+
|
|
+ rv1106->agc_r = 1;
|
|
+ } else {
|
|
+ /* ALC AGC Left On */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_PGA_AGC_L_CTL9,
|
|
+ ACODEC_AGC_FUNC_SEL_MSK,
|
|
+ ACODEC_AGC_FUNC_SEL_EN);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL,
|
|
+ ACODEC_ADC_L_PGA_MSK,
|
|
+ ACODEC_ADC_PGA_ALCL_EN);
|
|
+
|
|
+ rv1106->agc_l = 1;
|
|
+ }
|
|
+ } else {
|
|
+ /* ALC AGC Off */
|
|
+ if (e->shift_l) {
|
|
+ /* ALC AGC Right Off */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_PGA_AGC_R_CTL9,
|
|
+ ACODEC_AGC_FUNC_SEL_MSK,
|
|
+ ACODEC_AGC_FUNC_SEL_DIS);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL,
|
|
+ ACODEC_ADC_R_PGA_MSK,
|
|
+ ACODEC_ADC_PGA_ALCR_DIS);
|
|
+
|
|
+ rv1106->agc_r = 0;
|
|
+ } else {
|
|
+ /* ALC AGC Left Off */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_PGA_AGC_L_CTL9,
|
|
+ ACODEC_AGC_FUNC_SEL_MSK,
|
|
+ ACODEC_AGC_FUNC_SEL_DIS);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL,
|
|
+ ACODEC_ADC_L_PGA_MSK,
|
|
+ ACODEC_ADC_PGA_ALCL_DIS);
|
|
+
|
|
+ rv1106->agc_l = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_agc_asr_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+ unsigned int value;
|
|
+
|
|
+ if (e->shift_l) {
|
|
+ regmap_read(rv1106->regmap, ACODEC_ADC_PGA_AGC_R_CTL4, &value);
|
|
+ rv1106->agc_asr_r = value >> ACODEC_AGC_APPROX_RATE_SFT;
|
|
+ ucontrol->value.integer.value[0] = rv1106->agc_asr_r;
|
|
+ } else {
|
|
+ regmap_read(rv1106->regmap, ACODEC_ADC_PGA_AGC_L_CTL4, &value);
|
|
+ rv1106->agc_asr_l = value >> ACODEC_AGC_APPROX_RATE_SFT;
|
|
+ ucontrol->value.integer.value[0] = rv1106->agc_asr_l;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_agc_asr_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+ unsigned int value;
|
|
+
|
|
+ value = ucontrol->value.integer.value[0] << ACODEC_AGC_APPROX_RATE_SFT;
|
|
+
|
|
+ if (e->shift_l) {
|
|
+ /* ALC AGC Right Approximate Sample Rate */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_PGA_AGC_R_CTL4,
|
|
+ ACODEC_AGC_APPROX_RATE_MSK,
|
|
+ value);
|
|
+ rv1106->agc_asr_r = ucontrol->value.integer.value[0];
|
|
+ } else {
|
|
+ /* ALC AGC Left Approximate Sample Rate */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_PGA_AGC_L_CTL4,
|
|
+ ACODEC_AGC_APPROX_RATE_MSK,
|
|
+ value);
|
|
+ rv1106->agc_asr_l = ucontrol->value.integer.value[0];
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_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 rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+ unsigned int value;
|
|
+
|
|
+ if (e->shift_l) {
|
|
+ /* ADC MIC Right Mute/Work Infos */
|
|
+ regmap_read(rv1106->regmap, ACODEC_ADC_BIST_MODE_SEL, &value);
|
|
+ rv1106->mic_mute_r = (value & ACODEC_ADC_R_BIST_SINE) >>
|
|
+ ACODEC_ADC_R_BIST_SFT;
|
|
+ ucontrol->value.integer.value[0] = rv1106->mic_mute_r;
|
|
+ } else {
|
|
+ /* ADC MIC Left Mute/Work Infos */
|
|
+ regmap_read(rv1106->regmap, ACODEC_ADC_BIST_MODE_SEL, &value);
|
|
+ rv1106->mic_mute_l = (value & ACODEC_ADC_L_BIST_SINE) >>
|
|
+ ACODEC_ADC_L_BIST_SFT;
|
|
+ ucontrol->value.integer.value[0] = rv1106->mic_mute_l;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_mic_mute_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
|
|
+ unsigned int value;
|
|
+
|
|
+ if (e->shift_l) {
|
|
+ /* ADC MIC Right Mute/Work Configuration */
|
|
+ value = ucontrol->value.integer.value[0] << ACODEC_ADC_R_BIST_SFT;
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_BIST_MODE_SEL,
|
|
+ ACODEC_ADC_R_BIST_SINE,
|
|
+ value);
|
|
+ rv1106->mic_mute_r = ucontrol->value.integer.value[0];
|
|
+ } else {
|
|
+ /* ADC MIC Left Mute/Work Configuration */
|
|
+ value = ucontrol->value.integer.value[0] << ACODEC_ADC_L_BIST_SFT;
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_BIST_MODE_SEL,
|
|
+ ACODEC_ADC_L_BIST_SINE,
|
|
+ value);
|
|
+ rv1106->mic_mute_l = ucontrol->value.integer.value[0];
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_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 rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ ucontrol->value.integer.value[0] = rv1106->micbias_volt;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_micbias_volts_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int volt = ucontrol->value.integer.value[0];
|
|
+ int ret;
|
|
+
|
|
+ ret = check_micbias(volt);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rv1106->plat_dev, "Invalid micbias volt: %d\n",
|
|
+ volt);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_ADC_LEVEL_RANGE_MICBIAS_MSK,
|
|
+ volt);
|
|
+
|
|
+ rv1106->micbias_volt = volt;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_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 rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ ucontrol->value.integer.value[0] = rv1106->micbias_enable;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_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 rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int on = ucontrol->value.integer.value[0];
|
|
+
|
|
+ if (on) {
|
|
+ if (!rv1106->micbias_enable)
|
|
+ rv1106_codec_micbias_enable(rv1106, rv1106->micbias_volt);
|
|
+ } else {
|
|
+ if (rv1106->micbias_enable)
|
|
+ rv1106_codec_micbias_disable(rv1106);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_mic_gain_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ /*
|
|
+ * 6.18 port note: snd_soc_get_volsw_range()/snd_soc_put_volsw_range()
|
|
+ * no longer exist as separate mainline entry points -- the unified
|
|
+ * snd_soc_get_volsw()/snd_soc_put_volsw() already honour the xmin
|
|
+ * field of struct soc_mixer_control (populated via SOC_SINGLE_VALUE),
|
|
+ * so they are a drop-in replacement here.
|
|
+ */
|
|
+ return snd_soc_get_volsw(kcontrol, ucontrol);
|
|
+}
|
|
+
|
|
+static int rv1106_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 rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int index = ucontrol->value.integer.value[0];
|
|
+
|
|
+ /*
|
|
+ * From the TRM, the gain of MIC Boost only supports:
|
|
+ * 0dB (index == 1)
|
|
+ * 20dB(index == 2)
|
|
+ * 12dB(index == 3)
|
|
+ */
|
|
+ if ((index < ACODEC_ADC_MIC_GAIN_MIN) ||
|
|
+ (index > ACODEC_ADC_MIC_GAIN_MAX)) {
|
|
+ dev_err(rv1106->plat_dev, "%s: invalid mic gain index: %d\n",
|
|
+ __func__, index);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return snd_soc_put_volsw(kcontrol, ucontrol);
|
|
+}
|
|
+
|
|
+static int rv1106_codec_hpf_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int value;
|
|
+
|
|
+ regmap_read(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL, &value);
|
|
+ if (value & ACODEC_ADC_HPF_MSK)
|
|
+ rv1106->hpf_cutoff = 1;
|
|
+ else
|
|
+ rv1106->hpf_cutoff = 0;
|
|
+
|
|
+ ucontrol->value.integer.value[0] = rv1106->hpf_cutoff;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_hpf_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int value = ucontrol->value.integer.value[0];
|
|
+
|
|
+ if (value) {
|
|
+ /* Enable high pass filter for ADCs */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL,
|
|
+ ACODEC_ADC_HPF_MSK,
|
|
+ ACODEC_ADC_HPF_EN);
|
|
+ } else {
|
|
+ /* Disable high pass filter for ADCs. */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_HPF_PGA_CTL,
|
|
+ ACODEC_ADC_HPF_MSK,
|
|
+ ACODEC_ADC_HPF_DIS);
|
|
+ }
|
|
+
|
|
+ rv1106->hpf_cutoff = value;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void rv1106_codec_pa_ctrl(struct rv1106_codec_priv *rv1106, bool on)
|
|
+{
|
|
+ if (!rv1106->pa_ctl_gpio)
|
|
+ return;
|
|
+
|
|
+ if (on) {
|
|
+ gpiod_direction_output(rv1106->pa_ctl_gpio, on);
|
|
+ msleep(rv1106->pa_ctl_delay_ms);
|
|
+ } else {
|
|
+ gpiod_direction_output(rv1106->pa_ctl_gpio, on);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int rv1106_codec_reset(struct snd_soc_component *component)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ reset_control_assert(rv1106->reset);
|
|
+ usleep_range(10000, 11000); /* estimated value */
|
|
+ reset_control_deassert(rv1106->reset);
|
|
+
|
|
+ regmap_write(rv1106->regmap, ACODEC_GLB_CON, 0x00);
|
|
+ usleep_range(10000, 11000); /* estimated value */
|
|
+ regmap_write(rv1106->regmap, ACODEC_GLB_CON,
|
|
+ ACODEC_CODEC_SYS_WORK |
|
|
+ ACODEC_CODEC_CORE_WORK);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_set_bias_level(struct snd_soc_component *component,
|
|
+ enum snd_soc_bias_level level)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = 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(rv1106->regmap, false);
|
|
+ regcache_sync(rv1106->regmap);
|
|
+ break;
|
|
+ case SND_SOC_BIAS_OFF:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
|
+ unsigned int fmt)
|
|
+{
|
|
+ struct snd_soc_component *component = codec_dai->component;
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0;
|
|
+
|
|
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
|
+ case SND_SOC_DAIFMT_CBC_CFC: /* 6.18: was SND_SOC_DAIFMT_CBS_CFS */
|
|
+ adc_aif2 |= ACODEC_ADC_IO_MODE_SLAVE;
|
|
+ adc_aif2 |= ACODEC_ADC_MODE_SLAVE;
|
|
+ dac_aif2 |= ACODEC_DAC_IO_MODE_SLAVE;
|
|
+ dac_aif2 |= ACODEC_DAC_MODE_SLAVE;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_CBP_CFP: /* 6.18: was SND_SOC_DAIFMT_CBM_CFM */
|
|
+ adc_aif2 |= ACODEC_ADC_IO_MODE_MASTER;
|
|
+ adc_aif2 |= ACODEC_ADC_MODE_MASTER;
|
|
+ dac_aif2 |= ACODEC_DAC_IO_MODE_MASTER;
|
|
+ dac_aif2 |= ACODEC_DAC_MODE_MASTER;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
|
+ case SND_SOC_DAIFMT_DSP_A:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_MODE_PCM;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_MODE_PCM;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_I2S:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_MODE_I2S;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_MODE_I2S;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_RIGHT_J:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_MODE_RJ;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_MODE_RJ;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_LEFT_J:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_MODE_LJ;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_MODE_LJ;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
|
|
+ case SND_SOC_DAIFMT_NB_NF:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_LRC_POL_NORMAL;
|
|
+ adc_aif2 |= ACODEC_ADC_I2S_BIT_CLK_POL_NORMAL;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_LRC_POL_NORMAL;
|
|
+ dac_aif2 |= ACODEC_DAC_I2S_BIT_CLK_POL_NORMAL;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_IB_IF:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_LRC_POL_REVERSAL;
|
|
+ adc_aif2 |= ACODEC_ADC_I2S_BIT_CLK_POL_REVERSAL;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_LRC_POL_REVERSAL;
|
|
+ dac_aif2 |= ACODEC_DAC_I2S_BIT_CLK_POL_REVERSAL;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_IB_NF:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_LRC_POL_NORMAL;
|
|
+ adc_aif2 |= ACODEC_ADC_I2S_BIT_CLK_POL_REVERSAL;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_LRC_POL_NORMAL;
|
|
+ dac_aif2 |= ACODEC_DAC_I2S_BIT_CLK_POL_REVERSAL;
|
|
+ break;
|
|
+ case SND_SOC_DAIFMT_NB_IF:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_LRC_POL_REVERSAL;
|
|
+ adc_aif2 |= ACODEC_ADC_I2S_BIT_CLK_POL_NORMAL;
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_LRC_POL_REVERSAL;
|
|
+ dac_aif2 |= ACODEC_DAC_I2S_BIT_CLK_POL_NORMAL;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_I2S_CTL0,
|
|
+ ACODEC_ADC_I2S_LRC_POL_MSK |
|
|
+ ACODEC_ADC_I2S_MODE_MSK,
|
|
+ adc_aif1);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_I2S_CTL1,
|
|
+ ACODEC_ADC_IO_MODE_MSK |
|
|
+ ACODEC_ADC_MODE_MSK |
|
|
+ ACODEC_ADC_I2S_BIT_CLK_POL_MSK,
|
|
+ adc_aif2);
|
|
+
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_I2S_CTL0,
|
|
+ ACODEC_DAC_I2S_LRC_POL_MSK |
|
|
+ ACODEC_DAC_I2S_MODE_MSK,
|
|
+ dac_aif1);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_I2S_CTL1,
|
|
+ ACODEC_DAC_IO_MODE_MSK |
|
|
+ ACODEC_DAC_MODE_MSK |
|
|
+ ACODEC_DAC_I2S_BIT_CLK_POL_MSK,
|
|
+ dac_aif2);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dac_dig_config(struct rv1106_codec_priv *rv1106,
|
|
+ struct snd_pcm_hw_params *params)
|
|
+{
|
|
+ unsigned int dac_aif1 = 0, dac_aif2 = 0;
|
|
+
|
|
+ switch (params_format(params)) {
|
|
+ case SNDRV_PCM_FORMAT_S16_LE:
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_VALID_LEN_16BITS;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S20_3LE:
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_VALID_LEN_20BITS;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S24_LE:
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_VALID_LEN_24BITS;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S32_LE:
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_VALID_LEN_32BITS;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ dac_aif1 |= ACODEC_DAC_I2S_LR_NORMAL;
|
|
+ dac_aif2 |= ACODEC_DAC_I2S_WORK;
|
|
+
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_I2S_CTL0,
|
|
+ ACODEC_DAC_I2S_VALID_LEN_MSK |
|
|
+ ACODEC_DAC_I2S_LR_MSK,
|
|
+ dac_aif1);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_I2S_CTL1,
|
|
+ ACODEC_DAC_I2S_MSK,
|
|
+ dac_aif2);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_adc_dig_config(struct rv1106_codec_priv *rv1106,
|
|
+ struct snd_pcm_hw_params *params)
|
|
+{
|
|
+ unsigned int adc_aif1 = 0, adc_aif2 = 0;
|
|
+
|
|
+ switch (params_format(params)) {
|
|
+ case SNDRV_PCM_FORMAT_S16_LE:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_VALID_LEN_16BITS;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S20_3LE:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_VALID_LEN_20BITS;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S24_LE:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_VALID_LEN_24BITS;
|
|
+ break;
|
|
+ case SNDRV_PCM_FORMAT_S32_LE:
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_VALID_LEN_32BITS;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ adc_aif1 |= ACODEC_ADC_I2S_DATA_SEL_NORMAL;
|
|
+ adc_aif2 |= ACODEC_ADC_I2S_WORK;
|
|
+
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_I2S_CTL0,
|
|
+ ACODEC_ADC_I2S_VALID_LEN_MSK |
|
|
+ ACODEC_ADC_I2S_DATA_SEL_MSK,
|
|
+ adc_aif1);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_I2S_CTL1,
|
|
+ ACODEC_ADC_I2S_MSK,
|
|
+ adc_aif2);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dac_mute(struct rv1106_codec_priv *rv1106, int mute)
|
|
+{
|
|
+ if (mute) {
|
|
+ /* Mute DAC HPMIX/LINEOUT */
|
|
+ regmap_update_bits(rv1106->regmap,
|
|
+ ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_MUTE_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_MUTE);
|
|
+ regmap_update_bits(rv1106->regmap,
|
|
+ ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MUTE_MSK,
|
|
+ ACODEC_DAC_HPMIX_MUTE);
|
|
+ rv1106_codec_pa_ctrl(rv1106, false);
|
|
+ } else {
|
|
+ /* Unmute DAC HPMIX/LINEOUT */
|
|
+ regmap_update_bits(rv1106->regmap,
|
|
+ ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MUTE_MSK,
|
|
+ ACODEC_DAC_HPMIX_WORK);
|
|
+ regmap_update_bits(rv1106->regmap,
|
|
+ ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_MUTE_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_WORK);
|
|
+ rv1106_codec_pa_ctrl(rv1106, true);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
|
+{
|
|
+ struct snd_soc_component *component = dai->component;
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ if (rv1106->dac_ctrl_manual == 1)
|
|
+ mute = 1; /* Force DAC control off manually */
|
|
+ else if (rv1106->dac_ctrl_manual == 2)
|
|
+ mute = 0; /* Force DAC control on manually */
|
|
+
|
|
+ rv1106_codec_dac_mute(rv1106, mute);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dac_enable(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ /* Step 01 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_IBIAS_MSK,
|
|
+ ACODEC_DAC_IBIAS_EN);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 02 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_REF_VOL_BUF_MSK,
|
|
+ ACODEC_DAC_L_REF_VOL_BUF_EN);
|
|
+ /* Waiting the stable reference voltage */
|
|
+ usleep_range(1000, 2000);
|
|
+
|
|
+ /* Step 03 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_EN);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 04 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_SIGNAL_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_SIGNAL_WORK);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 05 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MSK,
|
|
+ ACODEC_DAC_HPMIX_EN);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 06 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MDL_MSK,
|
|
+ ACODEC_DAC_HPMIX_MDL_WORK);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 07 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_SEL_MSK,
|
|
+ ACODEC_DAC_HPMIX_I2S);
|
|
+ /* Waiting HPMIX be stable */
|
|
+ usleep_range(18000, 20000);
|
|
+
|
|
+ /* Step 08 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_REF_VOL_MSK,
|
|
+ ACODEC_DAC_L_REF_VOL_EN);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 09 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_CLK_MSK,
|
|
+ ACODEC_DAC_L_CLK_EN);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 10 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_SRC_SIGNAL_MSK,
|
|
+ ACODEC_DAC_SRC_SIGNAL_EN);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 11 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_SIGNAL_MSK,
|
|
+ ACODEC_DAC_L_SIGNAL_WORK);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 12 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MUTE_MSK,
|
|
+ ACODEC_DAC_HPMIX_WORK);
|
|
+ udelay(20);
|
|
+
|
|
+ /* Step 13 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_MUTE_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_WORK);
|
|
+
|
|
+ /* Skip setting gains that Step 14/15 */
|
|
+
|
|
+ rv1106->dac_enable = true;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dac_disable(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ /* Step 01 */
|
|
+ /* Skip cleaning the gain to GAIN_LINEOUTL */
|
|
+
|
|
+ /* Step 02 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_MUTE_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_MUTE);
|
|
+
|
|
+ /* Step 03 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_SIGNAL_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_SIGNAL_INIT);
|
|
+ /* Step 04 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL1,
|
|
+ ACODEC_DAC_L_LINEOUT_MSK,
|
|
+ ACODEC_DAC_L_LINEOUT_DIS);
|
|
+ /* Step 05 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MUTE_MSK,
|
|
+ ACODEC_DAC_HPMIX_MUTE);
|
|
+ /* Step 06 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MDL_MSK,
|
|
+ ACODEC_DAC_HPMIX_MDL_INIT);
|
|
+ /* Step 07 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_HPMIX_CTL,
|
|
+ ACODEC_DAC_HPMIX_MSK,
|
|
+ ACODEC_DAC_HPMIX_DIS);
|
|
+ /* Step 08 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_SRC_SIGNAL_MSK,
|
|
+ ACODEC_DAC_SRC_SIGNAL_DIS);
|
|
+ /* Step 09 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_CLK_MSK,
|
|
+ ACODEC_DAC_L_CLK_DIS);
|
|
+
|
|
+ /* Step 10 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_REF_VOL_MSK,
|
|
+ ACODEC_DAC_L_REF_VOL_DIS);
|
|
+ /* Step 11 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_REF_VOL_BUF_MSK,
|
|
+ ACODEC_DAC_L_REF_VOL_BUF_DIS);
|
|
+
|
|
+ /* Step 12 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_IBIAS_MSK,
|
|
+ ACODEC_DAC_IBIAS_DIS);
|
|
+
|
|
+ /* Step 13 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_SIGNAL_MSK,
|
|
+ ACODEC_DAC_L_SIGNAL_INIT);
|
|
+
|
|
+
|
|
+ rv1106->dac_enable = false;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_power_on(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ /* vendor step 1 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL0,
|
|
+ ACODEC_DAC_L_REF_POP_SOUND_MSK,
|
|
+ ACODEC_DAC_L_REF_POP_SOUND_WORK);
|
|
+ /* vendor step 2. Charging */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_CURRENT_CHARGE_CTL,
|
|
+ ACODEC_ADC_CURRENT_CHARGE_MSK,
|
|
+ ACODEC_ADC_SEL_I(0xff));
|
|
+ /* vendor step 3. Supply the power of the analog part. */
|
|
+ /* vendor step 4 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_ADC_REF_VOL_MSK, ACODEC_ADC_REF_VOL_EN);
|
|
+ /* vendor step 5. Wait charging completed */
|
|
+ msleep(20);
|
|
+ /* vendor step 6 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_CURRENT_CHARGE_CTL,
|
|
+ ACODEC_ADC_CURRENT_CHARGE_MSK,
|
|
+ ACODEC_ADC_SEL_I(0x02));
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_power_off(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ /*
|
|
+ * 0. Keep the power on and disable the DAC and ADC path.
|
|
+ */
|
|
+
|
|
+ /* vendor step 1 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_CURRENT_CHARGE_CTL,
|
|
+ ACODEC_ADC_CURRENT_CHARGE_MSK,
|
|
+ ACODEC_ADC_SEL_I(0xff));
|
|
+ /* vendor step 3 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_ADC_REF_VOL_MSK,
|
|
+ ACODEC_ADC_REF_VOL_DIS);
|
|
+ /* vendor step 3. Wait until the voltage of VCM keep stable at AGND. */
|
|
+ msleep(20);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_adc_i2s_route(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ regmap_write(rv1106->grf, PERI_GRF_PERI_CON1,
|
|
+ ACODEC_MSK | ACODEC_EN);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int check_micbias(int volt)
|
|
+{
|
|
+ switch (volt) {
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_975:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_95:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_925:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_9:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_875:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_85:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_825:
|
|
+ case ACODEC_ADC_MICBIAS_VOLT_0_8:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_micbias_enable(struct rv1106_codec_priv *rv1106,
|
|
+ int volt)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (!rv1106->micbias_used)
|
|
+ return 0;
|
|
+
|
|
+ /* 0. Power up the ACODEC and keep the AVDDH stable */
|
|
+
|
|
+ /* vendor step 1 */
|
|
+ ret = check_micbias(volt);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rv1106->plat_dev, "This is an invalid volt: %d\n",
|
|
+ volt);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_ADC_LEVEL_RANGE_MICBIAS_MSK,
|
|
+ volt);
|
|
+
|
|
+ /* vendor step 4 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_MICBIAS_MSK,
|
|
+ ACODEC_MICBIAS_WORK);
|
|
+
|
|
+ /* waiting micbias stabled*/
|
|
+ mdelay(20);
|
|
+
|
|
+ rv1106->micbias_enable = true;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_micbias_disable(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ if (!rv1106->micbias_used)
|
|
+ return 0;
|
|
+
|
|
+ /* Step 0. Enable the MICBIAS and keep the Audio Codec stable */
|
|
+ /* Do nothing */
|
|
+
|
|
+ /* vendor step 1 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_MICBIAS_MSK,
|
|
+ ACODEC_MICBIAS_RST);
|
|
+
|
|
+ rv1106->micbias_enable = false;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_hpmix_gain_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ /* 6.18 port note: see rv1106_codec_mic_gain_get() above. */
|
|
+ return snd_soc_get_volsw(kcontrol, ucontrol);
|
|
+}
|
|
+
|
|
+static int rv1106_codec_hpmix_gain_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ unsigned int index = ucontrol->value.integer.value[0];
|
|
+
|
|
+ if ((index < ACODEC_DAC_HPMIX_GAIN_MIN) ||
|
|
+ (index > ACODEC_DAC_HPMIX_GAIN_MAX)) {
|
|
+ dev_err(rv1106->plat_dev, "%s: invalid gain index: %d\n",
|
|
+ __func__, index);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return snd_soc_put_volsw(kcontrol, ucontrol);
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dac_ctrl_manual_get(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ ucontrol->value.integer.value[0] = rv1106->dac_ctrl_manual;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dac_ctrl_manual_put(struct snd_kcontrol *kcontrol,
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ rv1106->dac_ctrl_manual = ucontrol->value.integer.value[0];
|
|
+
|
|
+ if (rv1106->dac_ctrl_manual == 0)
|
|
+ return 0;
|
|
+
|
|
+ if (rv1106->dac_ctrl_manual == 1)
|
|
+ rv1106_codec_dac_mute(rv1106, 1); /* Force DAC control off manually */
|
|
+ else if (rv1106->dac_ctrl_manual == 2)
|
|
+ rv1106_codec_dac_mute(rv1106, 0); /* Force DAC control on manually */
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_adc_enable(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ unsigned int lr = using_adc_lr(rv1106->adc_mode);
|
|
+ bool is_diff = using_adc_diff(rv1106->adc_mode);
|
|
+ unsigned int agc_func_en;
|
|
+ int ret;
|
|
+
|
|
+ dev_dbg(rv1106->plat_dev, "%s: soc_id: 0x%x lr: %d is_diff: %d\n",
|
|
+ __func__, rv1106->soc_id, lr, is_diff);
|
|
+
|
|
+ ret = check_adc_mode(rv1106);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rv1106->plat_dev,
|
|
+ "%s - something error checking ADC mode: %d\n",
|
|
+ __func__, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /* vendor step 00 */
|
|
+ if (rv1106->soc_id == SOC_RV1103 && rv1106->adc_mode == DIFF_ADCL) {
|
|
+ /* The ADCL is differential mode on rv1103 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ ACODEC_ADC_L_MODE_SEL_MSK,
|
|
+ ACODEC_ADC_L_FULL_DIFFER2);
|
|
+ } else if (rv1106->soc_id == SOC_RV1106 && is_diff) {
|
|
+ /* The differential mode on rv1106 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ L(lr, ACODEC_ADC_L_MODE_SEL_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_MODE_SEL_MSK),
|
|
+ L(lr, ACODEC_ADC_L_FULL_DIFFER) |
|
|
+ R(lr, ACODEC_ADC_R_FULL_DIFFER));
|
|
+ } else {
|
|
+ /* The single-end mode */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ L(lr, ACODEC_ADC_L_MODE_SEL_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_MODE_SEL_MSK),
|
|
+ L(lr, ACODEC_ADC_L_SINGLE_END) |
|
|
+ R(lr, ACODEC_ADC_R_SINGLE_END));
|
|
+ }
|
|
+
|
|
+ /* vendor step 01 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1,
|
|
+ L(lr, ACODEC_ADC_L_MIC_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_MIC_MSK),
|
|
+ L(lr, ACODEC_ADC_L_MIC_WORK) |
|
|
+ R(lr, ACODEC_ADC_R_MIC_WORK));
|
|
+
|
|
+ /* vendor step 02 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_ADC_IBIAS_MSK,
|
|
+ ACODEC_ADC_IBIAS_EN);
|
|
+
|
|
+ /* vendor step 03 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1,
|
|
+ L(lr, ACODEC_ADC_L_REF_VOL_BUF_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_REF_VOL_BUF_MSK),
|
|
+ L(lr, ACODEC_ADC_L_REF_VOL_BUF_EN) |
|
|
+ R(lr, ACODEC_ADC_R_REF_VOL_BUF_EN));
|
|
+ /* waiting VREF be stable */
|
|
+ msleep(100);
|
|
+
|
|
+ /* vendor step 04 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ L(lr, ACODEC_MIC_L_MSK) |
|
|
+ R(lr, ACODEC_MIC_R_MSK),
|
|
+ L(lr, ACODEC_MIC_L_EN) |
|
|
+ R(lr, ACODEC_MIC_R_EN));
|
|
+
|
|
+ /* vendor step 05 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ L(lr, ACODEC_ADC_L_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_MSK),
|
|
+ L(lr, ACODEC_ADC_L_EN) |
|
|
+ R(lr, ACODEC_ADC_R_EN));
|
|
+
|
|
+ /* vendor step 06 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ L(lr, ACODEC_ADC_L_CLK_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_CLK_MSK),
|
|
+ L(lr, ACODEC_ADC_L_CLK_WORK) |
|
|
+ R(lr, ACODEC_ADC_R_CLK_WORK));
|
|
+
|
|
+ /* vendor step 07 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ L(lr, ACODEC_ADC_L_WORK) |
|
|
+ R(lr, ACODEC_ADC_R_WORK),
|
|
+ L(lr, ACODEC_ADC_L_WORK) |
|
|
+ R(lr, ACODEC_ADC_R_WORK));
|
|
+
|
|
+ /* vendor step 08 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ L(lr, ACODEC_ADC_L_SIGNAL_EN) |
|
|
+ R(lr, ACODEC_ADC_R_SIGNAL_EN),
|
|
+ L(lr, ACODEC_ADC_L_SIGNAL_EN) |
|
|
+ R(lr, ACODEC_ADC_R_SIGNAL_EN));
|
|
+
|
|
+ /* vendor step 09 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ L(lr, ACODEC_ADC_L_ALC_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_ALC_MSK),
|
|
+ L(lr, ACODEC_ADC_L_ALC_WORK) |
|
|
+ R(lr, ACODEC_ADC_R_ALC_WORK));
|
|
+
|
|
+ /* vendor step 10 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1,
|
|
+ L(lr, ACODEC_ADC_L_MIC_SIGNAL_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_MIC_SIGNAL_MSK),
|
|
+ L(lr, ACODEC_ADC_L_MIC_SIGNAL_WORK) |
|
|
+ R(lr, ACODEC_ADC_R_MIC_SIGNAL_WORK));
|
|
+
|
|
+ /* vendor step 11, configure GAIN_MICL/R by user */
|
|
+
|
|
+ /* vendor step 12, configure GAIN_ALCL/R by user */
|
|
+
|
|
+ /* vendor step 13 */
|
|
+ regmap_read(rv1106->regmap, ACODEC_ADC_ANA_CTL1, &agc_func_en);
|
|
+ if (agc_func_en & ACODEC_AGC_FUNC_SEL_EN) {
|
|
+ regmap_update_bits(rv1106->regmap,
|
|
+ ACODEC_ADC_ANA_CTL1,
|
|
+ L(lr, ACODEC_ADC_L_ZERO_CROSS_DET_MSK) |
|
|
+ R(lr, ACODEC_ADC_R_ZERO_CROSS_DET_MSK),
|
|
+ L(lr, ACODEC_ADC_L_ZERO_CROSS_DET_EN) |
|
|
+ R(lr, ACODEC_ADC_R_ZERO_CROSS_DET_EN));
|
|
+ }
|
|
+
|
|
+ rv1106->adc_enable = true;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_adc_disable(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ /* vendor step 1 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1,
|
|
+ ACODEC_ADC_L_ZERO_CROSS_DET_MSK |
|
|
+ ACODEC_ADC_R_ZERO_CROSS_DET_MSK,
|
|
+ ACODEC_ADC_L_ZERO_CROSS_DET_DIS |
|
|
+ ACODEC_ADC_R_ZERO_CROSS_DET_DIS);
|
|
+
|
|
+ /* vendor step 2 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ ACODEC_ADC_L_WORK |
|
|
+ ACODEC_ADC_R_WORK,
|
|
+ ACODEC_ADC_L_INIT |
|
|
+ ACODEC_ADC_R_INIT);
|
|
+
|
|
+ /* vendor step 3 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ ACODEC_ADC_L_CLK_WORK |
|
|
+ ACODEC_ADC_R_CLK_WORK,
|
|
+ ACODEC_ADC_L_CLK_RST |
|
|
+ ACODEC_ADC_R_CLK_RST);
|
|
+
|
|
+ /* vendor step 4 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ ACODEC_ADC_L_MSK |
|
|
+ ACODEC_ADC_R_MSK,
|
|
+ ACODEC_ADC_L_DIS |
|
|
+ ACODEC_ADC_R_DIS);
|
|
+
|
|
+ /* vendor step 5 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL3,
|
|
+ ACODEC_MIC_L_MSK |
|
|
+ ACODEC_MIC_R_MSK,
|
|
+ ACODEC_MIC_L_DIS |
|
|
+ ACODEC_MIC_R_DIS);
|
|
+
|
|
+ /* vendor step 6 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1,
|
|
+ ACODEC_ADC_L_REF_VOL_BUF_MSK |
|
|
+ ACODEC_ADC_R_REF_VOL_BUF_MSK,
|
|
+ ACODEC_ADC_L_REF_VOL_BUF_DIS |
|
|
+ ACODEC_ADC_R_REF_VOL_BUF_DIS);
|
|
+
|
|
+ /* vendor step 7 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL0,
|
|
+ ACODEC_ADC_IBIAS_MSK,
|
|
+ ACODEC_ADC_IBIAS_DIS);
|
|
+
|
|
+ /* vendor step 8 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ ACODEC_ADC_L_SIGNAL_EN |
|
|
+ ACODEC_ADC_R_SIGNAL_EN,
|
|
+ ACODEC_ADC_L_SIGNAL_DIS |
|
|
+ ACODEC_ADC_R_SIGNAL_DIS);
|
|
+
|
|
+ /* vendor step 9 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL6,
|
|
+ ACODEC_ADC_L_ALC_MSK |
|
|
+ ACODEC_ADC_R_ALC_MSK,
|
|
+ ACODEC_ADC_L_ALC_INIT |
|
|
+ ACODEC_ADC_R_ALC_INIT);
|
|
+
|
|
+ /* vendor step 10 */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL1,
|
|
+ ACODEC_ADC_L_MIC_SIGNAL_MSK |
|
|
+ ACODEC_ADC_R_MIC_SIGNAL_MSK,
|
|
+ ACODEC_ADC_L_MIC_SIGNAL_INIT |
|
|
+ ACODEC_ADC_R_MIC_SIGNAL_INIT);
|
|
+
|
|
+ rv1106->adc_enable = false;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_open_capture(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106_codec_adc_enable(rv1106);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_close_capture(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106_codec_adc_disable(rv1106);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_open_playback(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106_codec_dac_enable(rv1106);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_close_playback(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106_codec_dac_disable(rv1106);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dlp_down(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106_codec_micbias_disable(rv1106);
|
|
+ rv1106_codec_power_off(rv1106);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dlp_up(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106_codec_power_on(rv1106);
|
|
+ rv1106_codec_micbias_enable(rv1106, rv1106->micbias_volt);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_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 rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ rv1106_codec_open_playback(rv1106);
|
|
+ rv1106_codec_dac_dig_config(rv1106, params);
|
|
+ } else {
|
|
+ rv1106_codec_open_capture(rv1106);
|
|
+ rv1106_codec_adc_dig_config(rv1106, params);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void rv1106_pcm_shutdown(struct snd_pcm_substream *substream,
|
|
+ struct snd_soc_dai *dai)
|
|
+{
|
|
+ struct snd_soc_component *component = dai->component;
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
|
+ rv1106_codec_close_playback(rv1106);
|
|
+ else
|
|
+ rv1106_codec_close_capture(rv1106);
|
|
+
|
|
+ regcache_cache_only(rv1106->regmap, false);
|
|
+ regcache_sync(rv1106->regmap);
|
|
+}
|
|
+
|
|
+static const struct snd_soc_dai_ops rv1106_dai_ops = {
|
|
+ .hw_params = rv1106_hw_params,
|
|
+ .set_fmt = rv1106_set_dai_fmt,
|
|
+ .mute_stream = rv1106_mute_stream,
|
|
+ .shutdown = rv1106_pcm_shutdown,
|
|
+};
|
|
+
|
|
+static struct snd_soc_dai_driver rv1106_dai[] = {
|
|
+ {
|
|
+ .name = "rv1106-hifi",
|
|
+ .id = ACODEC_HIFI,
|
|
+ .playback = {
|
|
+ .stream_name = "HiFi Playback",
|
|
+ .channels_min = 1,
|
|
+ .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 = 4,
|
|
+ .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 = &rv1106_dai_ops,
|
|
+ },
|
|
+};
|
|
+
|
|
+static int rv1106_suspend(struct snd_soc_component *component)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ rv1106_codec_dlp_down(rv1106);
|
|
+ clk_disable_unprepare(rv1106->mclk_acodec);
|
|
+ clk_disable_unprepare(rv1106->pclk_acodec);
|
|
+ rv1106_set_bias_level(component, SND_SOC_BIAS_OFF);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_resume(struct snd_soc_component *component)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = clk_prepare_enable(rv1106->pclk_acodec);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rv1106->plat_dev,
|
|
+ "Failed to enable acodec pclk_acodec: %d\n", ret);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = clk_prepare_enable(rv1106->mclk_acodec);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rv1106->plat_dev,
|
|
+ "Failed to enable acodec mclk_acodec: %d\n", ret);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ rv1106_codec_dlp_up(rv1106);
|
|
+out:
|
|
+ rv1106_set_bias_level(component, SND_SOC_BIAS_STANDBY);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_default_gains(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ int gainl, gainr;
|
|
+
|
|
+ /**
|
|
+ * MIC Gain
|
|
+ * 0dB (0x01)
|
|
+ * 20dB (0x02)
|
|
+ * 12dB (0x03)
|
|
+ */
|
|
+ if (rv1106->init_mic_gain == NOT_SPECIFIED) {
|
|
+ gainl = ACODEC_ADC_L_MIC_GAIN_0DB;
|
|
+ gainr = ACODEC_ADC_R_MIC_GAIN_0DB;
|
|
+ } else {
|
|
+ gainl = ((rv1106->init_mic_gain >> 4) & 0x03) << ACODEC_ADC_L_MIC_GAIN_SFT;
|
|
+ gainr = ((rv1106->init_mic_gain >> 0) & 0x03) << ACODEC_ADC_R_MIC_GAIN_SFT;
|
|
+ }
|
|
+
|
|
+ /* Prepare ADC gains */
|
|
+ /* vendor step 12, set MIC PGA default gains */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL2,
|
|
+ ACODEC_ADC_L_MIC_GAIN_MSK |
|
|
+ ACODEC_ADC_R_MIC_GAIN_MSK,
|
|
+ gainl | gainr);
|
|
+
|
|
+ /**
|
|
+ * ALC Gain (0dB: 0x06)
|
|
+ * min: -9.0dB (0x00)
|
|
+ * max: +37.5dB (0x1f)
|
|
+ * step: +1.5dB
|
|
+ */
|
|
+ if (rv1106->init_alc_gain == NOT_SPECIFIED) {
|
|
+ gainl = ACODEC_ADC_L_ALC_GAIN_0DB;
|
|
+ gainr = ACODEC_ADC_R_ALC_GAIN_0DB;
|
|
+ } else {
|
|
+ gainl = ((rv1106->init_alc_gain >> 4) & 0x1f);
|
|
+ gainr = ((rv1106->init_alc_gain >> 0) & 0x1f);
|
|
+ }
|
|
+ /* vendor step 13, set ALC default gains */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL4,
|
|
+ ACODEC_ADC_L_ALC_GAIN_MSK,
|
|
+ gainl);
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_ADC_ANA_CTL5,
|
|
+ ACODEC_ADC_R_ALC_GAIN_MSK,
|
|
+ gainr);
|
|
+
|
|
+ /* Prepare DAC gains */
|
|
+ /* Step 19, set LINEOUT default gains */
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_GAIN_SEL,
|
|
+ ACODEC_DAC_DIG_GAIN_MSK,
|
|
+ ACODEC_DAC_DIG_GAIN(ACODEC_DAC_DIG_0DB)); /* The calibrated fixed gain */
|
|
+ /**
|
|
+ * Lineout Gain (0dB: 0x1a)
|
|
+ * min: -39.0dB (0x00)
|
|
+ * max: +6.0dB (0x1f)
|
|
+ * step: +1.5dB
|
|
+ */
|
|
+ if (rv1106->init_lineout_gain == NOT_SPECIFIED)
|
|
+ gainl = ACODEC_DAC_LINEOUT_GAIN_0DB;
|
|
+ else
|
|
+ gainl = rv1106->init_lineout_gain & 0x1f;
|
|
+ regmap_update_bits(rv1106->regmap, ACODEC_DAC_ANA_CTL2,
|
|
+ ACODEC_DAC_LINEOUT_GAIN_MSK,
|
|
+ gainl);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_check_micbias(struct rv1106_codec_priv *rv1106,
|
|
+ struct device_node *np)
|
|
+{
|
|
+ /* Check internal of acodec micbias */
|
|
+ rv1106->micbias_used =
|
|
+ of_property_read_bool(np, "acodec,micbias");
|
|
+
|
|
+ /* Using 0.9*AVDD by default */
|
|
+ rv1106->micbias_volt = ACODEC_ADC_MICBIAS_VOLT_0_9;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_dapm_controls_prepare(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ rv1106->adc_mode = DIFF_ADCL;
|
|
+ rv1106->dac_ctrl_manual = 0;
|
|
+ rv1106->hpf_cutoff = 0;
|
|
+ rv1106->agc_l = 0;
|
|
+ rv1106->agc_r = 0;
|
|
+ rv1106->agc_asr_l = AGC_ASR_96KHZ;
|
|
+ rv1106->agc_asr_r = AGC_ASR_96KHZ;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_prepare(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ /* Clear registers for ADC and DAC */
|
|
+ rv1106_codec_close_playback(rv1106);
|
|
+ rv1106_codec_close_capture(rv1106);
|
|
+ rv1106_codec_default_gains(rv1106);
|
|
+ rv1106_codec_dapm_controls_prepare(rv1106);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_probe(struct snd_soc_component *component)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ rv1106->component = component;
|
|
+ rv1106_codec_reset(component);
|
|
+ rv1106_codec_dlp_up(rv1106);
|
|
+ rv1106_codec_prepare(rv1106);
|
|
+
|
|
+ regcache_cache_only(rv1106->regmap, false);
|
|
+ regcache_sync(rv1106->regmap);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void rv1106_remove(struct snd_soc_component *component)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ rv1106_codec_pa_ctrl(rv1106, false);
|
|
+ rv1106_codec_micbias_disable(rv1106);
|
|
+ rv1106_codec_power_off(rv1106);
|
|
+ regcache_cache_only(rv1106->regmap, false);
|
|
+ regcache_sync(rv1106->regmap);
|
|
+}
|
|
+
|
|
+static const struct snd_soc_component_driver soc_codec_dev_rv1106 = {
|
|
+ .probe = rv1106_probe,
|
|
+ .remove = rv1106_remove,
|
|
+ .suspend = rv1106_suspend,
|
|
+ .resume = rv1106_resume,
|
|
+ .set_bias_level = rv1106_set_bias_level,
|
|
+ .controls = rv1106_codec_dapm_controls,
|
|
+ .num_controls = ARRAY_SIZE(rv1106_codec_dapm_controls),
|
|
+};
|
|
+
|
|
+/* Set the default value or reset value */
|
|
+static const struct reg_default rv1106_codec_reg_defaults[] = {
|
|
+ { ACODEC_RESET_CTL, 0x03 },
|
|
+};
|
|
+
|
|
+static bool rv1106_codec_write_read_reg(struct device *dev, unsigned int reg)
|
|
+{
|
|
+ /* All registers can be read / write */
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool rv1106_codec_volatile_reg(struct device *dev, unsigned int reg)
|
|
+{
|
|
+ /* All registers can be read / write */
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static const struct regmap_config rv1106_codec_regmap_config = {
|
|
+ .reg_bits = 32,
|
|
+ .reg_stride = 4,
|
|
+ .val_bits = 32,
|
|
+ .max_register = ACODEC_REG_MAX,
|
|
+ .writeable_reg = rv1106_codec_write_read_reg,
|
|
+ .readable_reg = rv1106_codec_write_read_reg,
|
|
+ .volatile_reg = rv1106_codec_volatile_reg,
|
|
+ .reg_defaults = rv1106_codec_reg_defaults,
|
|
+ .num_reg_defaults = ARRAY_SIZE(rv1106_codec_reg_defaults),
|
|
+ .cache_type = REGCACHE_FLAT,
|
|
+};
|
|
+
|
|
+static ssize_t adc_enable_show(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ char *buf)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 =
|
|
+ container_of(dev, struct rv1106_codec_priv, dev);
|
|
+
|
|
+ return sprintf(buf, "%d\n", rv1106->adc_enable);
|
|
+}
|
|
+
|
|
+static ssize_t adc_enable_store(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 =
|
|
+ container_of(dev, struct rv1106_codec_priv, dev);
|
|
+ unsigned long enable;
|
|
+ int ret = kstrtoul(buf, 10, &enable);
|
|
+
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "Invalid enable: %ld, ret: %d\n",
|
|
+ enable, ret);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (enable)
|
|
+ rv1106_codec_open_capture(rv1106);
|
|
+ else
|
|
+ rv1106_codec_close_capture(rv1106);
|
|
+
|
|
+ dev_info(dev, "ADC enable: %ld\n", enable);
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static ssize_t dac_enable_show(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ char *buf)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 =
|
|
+ container_of(dev, struct rv1106_codec_priv, dev);
|
|
+
|
|
+ return sprintf(buf, "%d\n", rv1106->dac_enable);
|
|
+}
|
|
+
|
|
+static ssize_t dac_enable_store(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 =
|
|
+ container_of(dev, struct rv1106_codec_priv, dev);
|
|
+ unsigned long enable;
|
|
+ int ret = kstrtoul(buf, 10, &enable);
|
|
+
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "Invalid enable: %ld, ret: %d\n",
|
|
+ enable, ret);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (enable)
|
|
+ rv1106_codec_open_playback(rv1106);
|
|
+ else
|
|
+ rv1106_codec_close_playback(rv1106);
|
|
+
|
|
+ dev_info(dev, "DAC enable: %ld\n", enable);
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+static const struct device_attribute acodec_attrs[] = {
|
|
+ __ATTR_RW(adc_enable),
|
|
+ __ATTR_RW(dac_enable),
|
|
+};
|
|
+
|
|
+static void rv1106_codec_device_release(struct device *dev)
|
|
+{
|
|
+ /* Do nothing */
|
|
+}
|
|
+
|
|
+static int rv1106_codec_sysfs_init(struct platform_device *pdev,
|
|
+ struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ struct device *dev = &rv1106->dev;
|
|
+ int i;
|
|
+
|
|
+ dev->release = rv1106_codec_device_release;
|
|
+ dev->parent = &pdev->dev;
|
|
+ set_dev_node(dev, dev_to_node(&pdev->dev));
|
|
+ dev_set_name(dev, "acodec_attrs");
|
|
+
|
|
+ if (device_register(dev)) {
|
|
+ dev_err(&pdev->dev,
|
|
+ "Register 'acodec_attrs' 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 'acodec_attrs' failed\n");
|
|
+ device_unregister(dev);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rv1106_codec_sysfs_exit(struct rv1106_codec_priv *rv1106)
|
|
+{
|
|
+ struct device *dev = &rv1106->dev;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(acodec_attrs); i++)
|
|
+ device_remove_file(dev, &acodec_attrs[i]);
|
|
+
|
|
+ device_unregister(dev);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#if defined(CONFIG_DEBUG_FS)
|
|
+static int rv1106_codec_debugfs_reg_show(struct seq_file *s, void *v)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 = s->private;
|
|
+ unsigned int i;
|
|
+ unsigned int val;
|
|
+
|
|
+ for (i = ACODEC_RESET_CTL; i <= ACODEC_ADC_PGA_AGC_R_CTL9; i += 4) {
|
|
+ regmap_read(rv1106->regmap, i, &val);
|
|
+ if (!(i % 16))
|
|
+ seq_printf(s, "\nR:%04x: ", i);
|
|
+ seq_printf(s, "%08x ", val);
|
|
+ }
|
|
+
|
|
+ seq_puts(s, "\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static ssize_t rv1106_codec_debugfs_reg_operate(struct file *file,
|
|
+ const char __user *buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 =
|
|
+ ((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(rv1106->regmap, reg, val);
|
|
+ regcache_cache_only(rv1106->regmap, false);
|
|
+ regcache_sync(rv1106->regmap);
|
|
+ pr_info("Read back reg: 0x%04x with val: 0x%08x\n", reg, val);
|
|
+ } else if (op == 'r') {
|
|
+ regmap_read(rv1106->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 rv1106_codec_debugfs_open(struct inode *inode, struct file *file)
|
|
+{
|
|
+ return single_open(file,
|
|
+ rv1106_codec_debugfs_reg_show, inode->i_private);
|
|
+}
|
|
+
|
|
+static const struct file_operations rv1106_codec_reg_debugfs_fops = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .open = rv1106_codec_debugfs_open,
|
|
+ .read = seq_read,
|
|
+ .write = rv1106_codec_debugfs_reg_operate,
|
|
+ .llseek = seq_lseek,
|
|
+ .release = single_release,
|
|
+};
|
|
+#endif /* CONFIG_DEBUG_FS */
|
|
+
|
|
+static const struct of_device_id rv1106_codec_of_match[] = {
|
|
+ { .compatible = "rockchip,rv1103-codec", .data = (void *)SOC_RV1103},
|
|
+ { .compatible = "rockchip,rv1106-codec", .data = (void *)SOC_RV1106},
|
|
+ {},
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, rv1106_codec_of_match);
|
|
+
|
|
+static int rv1106_platform_probe(struct platform_device *pdev)
|
|
+{
|
|
+ const struct of_device_id *of_id;
|
|
+ struct device_node *np = pdev->dev.of_node;
|
|
+ struct rv1106_codec_priv *rv1106;
|
|
+ struct resource *res;
|
|
+ void __iomem *base;
|
|
+ int ret;
|
|
+
|
|
+ rv1106 = devm_kzalloc(&pdev->dev, sizeof(*rv1106), GFP_KERNEL);
|
|
+ if (!rv1106)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ of_id = of_match_device(rv1106_codec_of_match, &pdev->dev);
|
|
+ if (of_id)
|
|
+ rv1106->soc_id = (enum soc_id_e)of_id->data;
|
|
+ dev_info(&pdev->dev, "current soc_id: rv%x\n", rv1106->soc_id);
|
|
+
|
|
+ rv1106->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
|
+ if (IS_ERR(rv1106->grf))
|
|
+ return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->grf),
|
|
+ "Missing 'rockchip,grf' property\n");
|
|
+
|
|
+ rv1106->plat_dev = &pdev->dev;
|
|
+ rv1106->reset = devm_reset_control_get(&pdev->dev, "acodec-reset");
|
|
+ if (IS_ERR(rv1106->reset)) {
|
|
+ ret = PTR_ERR(rv1106->reset);
|
|
+ if (ret != -ENOENT)
|
|
+ return ret;
|
|
+
|
|
+ dev_dbg(&pdev->dev, "No reset control found\n");
|
|
+ rv1106->reset = NULL;
|
|
+ }
|
|
+
|
|
+ rv1106->init_mic_gain = NOT_SPECIFIED;
|
|
+ of_property_read_u32(np, "init-mic-gain", &rv1106->init_mic_gain);
|
|
+
|
|
+ rv1106->init_alc_gain = NOT_SPECIFIED;
|
|
+ of_property_read_u32(np, "init-alc-gain", &rv1106->init_alc_gain);
|
|
+
|
|
+ rv1106->init_lineout_gain = NOT_SPECIFIED;
|
|
+ of_property_read_u32(np, "init-lineout-gain", &rv1106->init_lineout_gain);
|
|
+
|
|
+ rv1106->pa_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-ctl",
|
|
+ GPIOD_OUT_LOW);
|
|
+ if (IS_ERR(rv1106->pa_ctl_gpio))
|
|
+ return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->pa_ctl_gpio),
|
|
+ "Unable to claim gpio pa-ctl\n");
|
|
+
|
|
+ if (rv1106->pa_ctl_gpio)
|
|
+ of_property_read_u32(np, "pa-ctl-delay-ms",
|
|
+ &rv1106->pa_ctl_delay_ms);
|
|
+
|
|
+ dev_info(&pdev->dev, "%s pa_ctl_gpio and pa_ctl_delay_ms: %d\n",
|
|
+ rv1106->pa_ctl_gpio ? "Use" : "No use",
|
|
+ rv1106->pa_ctl_delay_ms);
|
|
+
|
|
+ /* Close external PA during startup. */
|
|
+ rv1106_codec_pa_ctrl(rv1106, false);
|
|
+
|
|
+ rv1106->pclk_acodec = devm_clk_get(&pdev->dev, "pclk_acodec");
|
|
+ if (IS_ERR(rv1106->pclk_acodec))
|
|
+ return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->pclk_acodec),
|
|
+ "Can't get acodec pclk_acodec\n");
|
|
+
|
|
+ rv1106->mclk_acodec = devm_clk_get(&pdev->dev, "mclk_acodec");
|
|
+ if (IS_ERR(rv1106->mclk_acodec))
|
|
+ return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->mclk_acodec),
|
|
+ "Can't get acodec mclk_acodec\n");
|
|
+
|
|
+ rv1106->mclk_cpu = devm_clk_get(&pdev->dev, "mclk_cpu");
|
|
+ if (IS_ERR(rv1106->mclk_cpu))
|
|
+ return dev_err_probe(&pdev->dev, PTR_ERR(rv1106->mclk_cpu),
|
|
+ "Can't get acodec mclk_cpu\n");
|
|
+
|
|
+ ret = rv1106_codec_sysfs_init(pdev, rv1106);
|
|
+ if (ret < 0)
|
|
+ return dev_err_probe(&pdev->dev, ret, "Sysfs init failed\n");
|
|
+
|
|
+#if defined(CONFIG_DEBUG_FS)
|
|
+ rv1106->dbg_codec = debugfs_create_dir(CODEC_DRV_NAME, NULL);
|
|
+ if (IS_ERR(rv1106->dbg_codec))
|
|
+ dev_err(&pdev->dev,
|
|
+ "Failed to create debugfs dir for rv1106!\n");
|
|
+ else
|
|
+ debugfs_create_file("reg", 0644, rv1106->dbg_codec,
|
|
+ rv1106, &rv1106_codec_reg_debugfs_fops);
|
|
+#endif
|
|
+
|
|
+ ret = clk_prepare_enable(rv1106->pclk_acodec);
|
|
+ if (ret < 0) {
|
|
+ dev_err(&pdev->dev, "Failed to enable acodec pclk_acodec: %d\n", ret);
|
|
+ goto failed_2;
|
|
+ }
|
|
+
|
|
+ ret = clk_prepare_enable(rv1106->mclk_acodec);
|
|
+ if (ret < 0) {
|
|
+ dev_err(&pdev->dev, "Failed to enable acodec mclk_acodec: %d\n", ret);
|
|
+ goto failed_1;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * In PERICRU_PERICLKSEL_CON08, the mclk_acodec_t/rx_div are div 4
|
|
+ * by default, we need to calibrate once, make the div is 1 and keep
|
|
+ * the rate of mclk_acodec is the same with mclk_i2s.
|
|
+ *
|
|
+ * FIXME: need to handle div dynamically if the DSMAUDIO is enabled.
|
|
+ */
|
|
+ clk_set_rate(rv1106->mclk_acodec, clk_get_rate(rv1106->mclk_cpu));
|
|
+
|
|
+ rv1106_codec_check_micbias(rv1106, np);
|
|
+
|
|
+ ret = rv1106_codec_adc_i2s_route(rv1106);
|
|
+ if (ret < 0) {
|
|
+ dev_err(&pdev->dev, "Failed to route ADC to i2s: %d\n",
|
|
+ ret);
|
|
+ goto failed;
|
|
+ }
|
|
+
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ rv1106->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
|
+ &rv1106_codec_regmap_config);
|
|
+ if (IS_ERR(rv1106->regmap)) {
|
|
+ ret = PTR_ERR(rv1106->regmap);
|
|
+ dev_err(&pdev->dev, "Failed to regmap mmio\n");
|
|
+ goto failed;
|
|
+ }
|
|
+
|
|
+ platform_set_drvdata(pdev, rv1106);
|
|
+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rv1106,
|
|
+ rv1106_dai, ARRAY_SIZE(rv1106_dai));
|
|
+ if (ret < 0) {
|
|
+ dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
|
|
+ goto failed;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+
|
|
+failed:
|
|
+ clk_disable_unprepare(rv1106->mclk_acodec);
|
|
+failed_1:
|
|
+ clk_disable_unprepare(rv1106->pclk_acodec);
|
|
+failed_2:
|
|
+#if defined(CONFIG_DEBUG_FS)
|
|
+ debugfs_remove_recursive(rv1106->dbg_codec);
|
|
+#endif
|
|
+ rv1106_codec_sysfs_exit(rv1106);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void rv1106_platform_remove(struct platform_device *pdev)
|
|
+{
|
|
+ struct rv1106_codec_priv *rv1106 =
|
|
+ (struct rv1106_codec_priv *)platform_get_drvdata(pdev);
|
|
+
|
|
+ clk_disable_unprepare(rv1106->mclk_acodec);
|
|
+ clk_disable_unprepare(rv1106->pclk_acodec);
|
|
+#if defined(CONFIG_DEBUG_FS)
|
|
+ debugfs_remove_recursive(rv1106->dbg_codec);
|
|
+#endif
|
|
+ rv1106_codec_sysfs_exit(rv1106);
|
|
+}
|
|
+
|
|
+static struct platform_driver rv1106_codec_driver = {
|
|
+ .driver = {
|
|
+ .name = CODEC_DRV_NAME,
|
|
+ .of_match_table = of_match_ptr(rv1106_codec_of_match),
|
|
+ },
|
|
+ .probe = rv1106_platform_probe,
|
|
+ .remove = rv1106_platform_remove,
|
|
+};
|
|
+module_platform_driver(rv1106_codec_driver);
|
|
+
|
|
+MODULE_DESCRIPTION("ASoC RV1106 Codec Driver");
|
|
+MODULE_AUTHOR("Jason Zhu <jason.zhu@rock-chips.com>");
|
|
+MODULE_LICENSE("GPL");
|
|
diff --git a/sound/soc/codecs/rv1106_codec.h b/sound/soc/codecs/rv1106_codec.h
|
|
new file mode 100644
|
|
index 000000000..a62fd549f
|
|
--- /dev/null
|
|
+++ b/sound/soc/codecs/rv1106_codec.h
|
|
@@ -0,0 +1,753 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0+ */
|
|
+/*
|
|
+ * rv1106_codec.h - Rockchip RV1106 SoC Codec Driver
|
|
+ *
|
|
+ * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
|
+ */
|
|
+
|
|
+#ifndef __RV1106_CODEC_H__
|
|
+#define __RV1106_CODEC_H__
|
|
+
|
|
+#define ACODEC_RESET_CTL 0x00 /* REG 0x00 */
|
|
+#define ACODEC_GLB_CON ACODEC_RESET_CTL
|
|
+#define ACODEC_MUTE_DA_DITHER_CTL 0x04 /* REG 0x01 */
|
|
+
|
|
+/* ADC DIGITAL REGISTERS */
|
|
+#define ACODEC_ADC_I2S_CTL0 0x08 /* REG 0x02 */
|
|
+#define ACODEC_ADC_I2S_CTL1 0x0c /* REG 0x03 */
|
|
+#define ACODEC_DAC_I2S_CTL0 0x10 /* REG 0x04 */
|
|
+#define ACODEC_DAC_I2S_CTL1 0x14 /* REG 0x05 */
|
|
+#define ACODEC_DAC_GAIN_SEL 0x18 /* REG 0x06 */
|
|
+#define ACODEC_DAC_L_BIST_MODE_SEL 0x1c /* REG 0x07 */
|
|
+#define ACODEC_ADC_L_DIG_VOL 0x20 /* REG 0x08 */
|
|
+#define ACODEC_ADC_R_DIG_VOL 0x24 /* REG 0x09 */
|
|
+#define ACODEC_ADC_HPF_PGA_CTL 0x28 /* REG 0x0a */
|
|
+#define ACODEC_INIT_DELAY_CNT1 0x2c /* REG 0x0b */
|
|
+#define ACODEC_INIT_DELAY_CNT2 0x30 /* REG 0x0c */
|
|
+#define ACODEC_ADC_BIST_MODE_SEL 0x34 /* REG 0x0d */
|
|
+#define ACODEC_DAC_CONFIG_OUTPUT 0x38 /* REG 0x0e */
|
|
+#define ACODEC_LINEOUT_CTL 0x80 /* REG 0x20 */
|
|
+#define ACODEC_CURRENT_CHARGE_CTL 0x84 /* REG 0x21 */
|
|
+
|
|
+#define ACODEC_ADC_ANA_CTL0 0x88 /* REG 0x22 */
|
|
+#define ACODEC_ADC_ANA_CTL1 0x8c /* REG 0x23 */
|
|
+#define ACODEC_ADC_ANA_CTL2 0x90 /* REG 0x24 */
|
|
+#define ACODEC_ADC_ANA_CTL3 0x94 /* REG 0x25 */
|
|
+#define ACODEC_ADC_ANA_CTL4 0x98 /* REG 0x26 */
|
|
+#define ACODEC_ADC_ANA_CTL5 0x9c /* REG 0x27 */
|
|
+#define ACODEC_ADC_ANA_CTL6 0xa0 /* REG 0x28 */
|
|
+
|
|
+#define ACODEC_DAC_ANA_CTL0 0xa4 /* REG 0x29 */
|
|
+#define ACODEC_DAC_ANA_CTL1 0xa8 /* REG 0x2a */
|
|
+#define ACODEC_DAC_ANA_CTL2 0xac /* REG 0x2b */
|
|
+#define ACODEC_DAC_HPMIX_CTL 0xbc /* REG 0x2f */
|
|
+
|
|
+/* The description of the agc register for the left channel */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL0 0x100 /* REG 0x40 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL1 0x104 /* REG 0x41 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL2 0x108 /* REG 0x42 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL3 0x10c /* REG 0x43 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL4 0x110 /* REG 0x44 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL5 0x114 /* REG 0x45 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL6 0x118 /* REG 0x46 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL7 0x11c /* REG 0x47 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL8 0x120 /* REG 0x48 */
|
|
+#define ACODEC_ADC_PGA_AGC_L_CTL9 0x124 /* REG 0x49 */
|
|
+
|
|
+/* The description of the agc register for the right channel */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL0 0x140 /* REG 0x50 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL1 0x144 /* REG 0x51 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL2 0x148 /* REG 0x52 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL3 0x14c /* REG 0x53 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL4 0x150 /* REG 0x54 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL5 0x154 /* REG 0x55 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL6 0x158 /* REG 0x56 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL7 0x15c /* REG 0x57 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL8 0x160 /* REG 0x58 */
|
|
+#define ACODEC_ADC_PGA_AGC_R_CTL9 0x164 /* REG 0x59 */
|
|
+
|
|
+#define ACODEC_REG_MAX ACODEC_ADC_PGA_AGC_R_CTL9
|
|
+
|
|
+/* ACODEC_RESET_CTL */
|
|
+#define ACODEC_CODEC_BIST_MSK (1 << 7)
|
|
+#define ACODEC_CODEC_BIST_WORK (1 << 7)
|
|
+#define ACODEC_CODEC_BIST_RST (0 << 7)
|
|
+#define ACODEC_CODEC_CORE_RST_MSK (1 << 1)
|
|
+#define ACODEC_CODEC_CORE_WORK (1 << 1)
|
|
+#define ACODEC_CODEC_CORE_RST (0 << 1)
|
|
+#define ACODEC_CODEC_SYS_RST_MSK (1 << 0)
|
|
+#define ACODEC_CODEC_SYS_WORK (1 << 0)
|
|
+#define ACODEC_CODEC_SYS_RST (0 << 0)
|
|
+
|
|
+/* ACODEC_MUTE_DA_DITHER_CTL */
|
|
+#define ACODEC_DAC_MUTE_MSK (1 << 7)
|
|
+#define ACODEC_DAC_MUTE_EN (1 << 7)
|
|
+#define ACODEC_DAC_MUTE_DIS (0 << 7)
|
|
+#define ACODEC_DITHER_LEVEL_SEL (1 << 3)
|
|
+#define ACODEC_DA_MSK (1 << 2)
|
|
+#define ACODEC_DA_EN (1 << 2)
|
|
+#define ACODEC_DA_DIS (0 << 2)
|
|
+#define ACODEC_DITHER_MSK (1 << 1)
|
|
+#define ACODEC_DITHER_EN (1 << 1)
|
|
+#define ACODEC_DITHER_DIS (0 << 1)
|
|
+#define ACODEC_DITHER_SIGN (1 << 0)
|
|
+
|
|
+/* ACODEC_ADC_I2S_CTL0 */
|
|
+#define ACODEC_ADC_I2S_LRC_POL_MSK (1 << 7)
|
|
+#define ACODEC_ADC_I2S_LRC_POL_REVERSAL (1 << 7)
|
|
+#define ACODEC_ADC_I2S_LRC_POL_NORMAL (0 << 7)
|
|
+#define ACODEC_ADC_I2S_VALID_LEN_SFT 5
|
|
+#define ACODEC_ADC_I2S_VALID_LEN_MSK (0x3 << ACODEC_ADC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_VALID_LEN_32BITS (0x3 << ACODEC_ADC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_VALID_LEN_24BITS (0x2 << ACODEC_ADC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_VALID_LEN_20BITS (0x1 << ACODEC_ADC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_VALID_LEN_16BITS (0x0 << ACODEC_ADC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_MODE_SFT 3
|
|
+#define ACODEC_ADC_I2S_MODE_MSK (0x3 << ACODEC_ADC_I2S_MODE_SFT)
|
|
+#define ACODEC_ADC_I2S_MODE_PCM (0x3 << ACODEC_ADC_I2S_MODE_SFT)
|
|
+#define ACODEC_ADC_I2S_MODE_I2S (0x2 << ACODEC_ADC_I2S_MODE_SFT)
|
|
+#define ACODEC_ADC_I2S_MODE_LJ (0x1 << ACODEC_ADC_I2S_MODE_SFT)
|
|
+#define ACODEC_ADC_I2S_MODE_RJ (0x0 << ACODEC_ADC_I2S_MODE_SFT)
|
|
+#define ACODEC_ADC_I2S_SEL_DATA_MSK (1 << 2)
|
|
+#define ACODEC_ADC_I2S_SEL_ADC_DATA (1 << 2)
|
|
+#define ACODEC_ADC_I2S_SEL_ADCL_DACL_DATA (0 << 2)
|
|
+#define ACODEC_ADC_I2S_DATA_SEL 0
|
|
+#define ACODEC_ADC_I2S_DATA_SEL_MSK (0x3 << ACODEC_ADC_I2S_DATA_SEL)
|
|
+#define ACODEC_ADC_I2S_DATA_SWAP (0x3 << ACODEC_ADC_I2S_DATA_SEL)
|
|
+#define ACODEC_ADC_I2S_DATA_SEL_LEFT (0x2 << ACODEC_ADC_I2S_DATA_SEL)
|
|
+#define ACODEC_ADC_I2S_DATA_SEL_RIGHT (0x1 << ACODEC_ADC_I2S_DATA_SEL)
|
|
+#define ACODEC_ADC_I2S_DATA_SEL_NORMAL (0x0 << ACODEC_ADC_I2S_DATA_SEL)
|
|
+
|
|
+/* ACODEC_ADC_I2S_CTL1 */
|
|
+#define ACODEC_DAC_IO_MODE_MSK (0x1 << 7)
|
|
+#define ACODEC_DAC_IO_MODE_MASTER (0x1 << 7)
|
|
+#define ACODEC_DAC_IO_MODE_SLAVE (0x0 << 7)
|
|
+#define ACODEC_DAC_MODE_MSK (0x1 << 6)
|
|
+#define ACODEC_DAC_MODE_MASTER (0x1 << 6)
|
|
+#define ACODEC_DAC_MODE_SLAVE (0x0 << 6)
|
|
+#define ACODEC_ADC_IO_MODE_MSK (0x1 << 5)
|
|
+#define ACODEC_ADC_IO_MODE_MASTER (0x1 << 5)
|
|
+#define ACODEC_ADC_IO_MODE_SLAVE (0x0 << 5)
|
|
+#define ACODEC_ADC_MODE_MSK (0x1 << 4)
|
|
+#define ACODEC_ADC_MODE_MASTER (0x1 << 4)
|
|
+#define ACODEC_ADC_MODE_SLAVE (0x0 << 4)
|
|
+#define ACODEC_ADC_I2S_FRAME_LEN_SFT 2
|
|
+#define ACODEC_ADC_I2S_FRAME_LEN_MSK (0x3 << ACODEC_ADC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_FRAME_32BITS (0x3 << ACODEC_ADC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_FRAME_24BITS (0x1 << ACODEC_ADC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_ADC_I2S_MSK (0x1 << 1)
|
|
+#define ACODEC_ADC_I2S_WORK (0x1 << 1)
|
|
+#define ACODEC_ADC_I2S_RESET (0x0 << 1)
|
|
+#define ACODEC_ADC_I2S_BIT_CLK_POL_MSK (0x1 << 0)
|
|
+#define ACODEC_ADC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0)
|
|
+#define ACODEC_ADC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0)
|
|
+
|
|
+/* ACODEC_DAC_I2S_CTL0 */
|
|
+#define ACODEC_DAC_I2S_LRC_POL_MSK (0x1 << 7)
|
|
+#define ACODEC_DAC_I2S_LRC_POL_REVERSAL (0x1 << 7)
|
|
+#define ACODEC_DAC_I2S_LRC_POL_NORMAL (0x0 << 7)
|
|
+#define ACODEC_DAC_I2S_VALID_LEN_SFT 5
|
|
+#define ACODEC_DAC_I2S_VALID_LEN_MSK (0x3 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_VALID_LEN_32BITS (0x3 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_VALID_LEN_24BITS (0x2 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_VALID_LEN_20BITS (0x1 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_VALID_LEN_16BITS (0x0 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_MODE_SFT 3
|
|
+#define ACODEC_DAC_I2S_MODE_MSK (0x3 << ACODEC_DAC_I2S_MODE_SFT)
|
|
+#define ACODEC_DAC_I2S_MODE_PCM (0x3 << ACODEC_DAC_I2S_MODE_SFT)
|
|
+#define ACODEC_DAC_I2S_MODE_I2S (0x2 << ACODEC_DAC_I2S_MODE_SFT)
|
|
+#define ACODEC_DAC_I2S_MODE_LJ (0x1 << ACODEC_DAC_I2S_MODE_SFT)
|
|
+#define ACODEC_DAC_I2S_MODE_RJ (0x0 << ACODEC_DAC_I2S_MODE_SFT)
|
|
+#define ACODEC_DAC_I2S_LR_MSK (0x1 << 2)
|
|
+#define ACODEC_DAC_I2S_LR_SWAP (0x1 << 2)
|
|
+#define ACODEC_DAC_I2S_LR_NORMAL (0x0 << 2)
|
|
+
|
|
+/* ACODEC_DAC_I2S_CTL1 */
|
|
+#define ACODEC_DAC_DE_EMPHASIS_FILTER_SFT 4
|
|
+#define ACODEC_DAC_DE_EMPHASIS_FILTER_MSK (0x3 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_48_DE_EMPHASIS_FILTER (0x3 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_441_DE_EMPHASIS_FILTER (0x2 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_32_DE_EMPHASIS_FILTER (0x1 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_NO_DE_EMPHASIS_FILTER (0x0 << ACODEC_DAC_I2S_VALID_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_FRAME_LEN_SFT 2
|
|
+#define ACODEC_DAC_I2S_FRAME_LEN_MSK (0x3 << ACODEC_DAC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_FRAME_32BITS (0x3 << ACODEC_DAC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_FRAME_24BITS (0x2 << ACODEC_DAC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_FRAME_20BITS (0x1 << ACODEC_DAC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_FRAME_16BITS (0x0 << ACODEC_DAC_I2S_FRAME_LEN_SFT)
|
|
+#define ACODEC_DAC_I2S_MSK (0x1 << 1)
|
|
+#define ACODEC_DAC_I2S_WORK (0x1 << 1)
|
|
+#define ACODEC_DAC_I2S_RESET (0x0 << 1)
|
|
+#define ACODEC_DAC_I2S_BIT_CLK_POL_MSK (0x1 << 0)
|
|
+#define ACODEC_DAC_I2S_BIT_CLK_POL_REVERSAL (0x1 << 0)
|
|
+#define ACODEC_DAC_I2S_BIT_CLK_POL_NORMAL (0x0 << 0)
|
|
+
|
|
+/* ACODEC_DAC_GAIN_SEL */
|
|
+#define ACODEC_DAC_DIG_GAIN_SFT 0
|
|
+#define ACODEC_DAC_DIG_GAIN_MSK (0xff << ACODEC_DAC_DIG_GAIN_SFT)
|
|
+#define ACODEC_DAC_DIG_GAIN(x) ((x) & ACODEC_DAC_DIG_GAIN_MSK)
|
|
+#define ACODEC_DAC_DIG_0DB 0xed
|
|
+
|
|
+/* ACODEC_DAC_L_BIST_MODE_SEL */
|
|
+#define ACODEC_DAC_L_CH_BIST_SFT 4
|
|
+#define ACODEC_DAC_L_CH_BIST_MSK (0x3 << ACODEC_DAC_L_CH_BIST_SFT)
|
|
+#define ACODEC_DAC_L_CH_BIST_SINE (0x1 << ACODEC_DAC_L_CH_BIST_SFT)
|
|
+#define ACODEC_DAC_L_CH_BIST_LEFT (0x0 << ACODEC_DAC_L_CH_BIST_SFT) /* normal mode */
|
|
+
|
|
+/* ACODEC_ADC_L_DIG_VOL */
|
|
+#define ACODEC_ADC_L_DIG_VOL_MAX 0xff
|
|
+#define ACODEC_ADC_L_DIG_VOL_MIN 0
|
|
+#define ACODEC_ADC_L_DIG_VOL_SFT 0
|
|
+#define ACODEC_ADC_L_DIG_VOL_MUTE 0
|
|
+#define ACODEC_ADC_L_DIG_VOL_0DB 0xc3
|
|
+
|
|
+/* ACODEC_ADC_R_DIG_VOL */
|
|
+#define ACODEC_ADC_R_DIG_VOL_MAX 0xff
|
|
+#define ACODEC_ADC_R_DIG_VOL_MIN 0
|
|
+#define ACODEC_ADC_R_DIG_VOL_SFT 0
|
|
+#define ACODEC_ADC_R_DIG_VOL_MUTE 0
|
|
+#define ACODEC_ADC_R_DIG_VOL_0DB 0xc3
|
|
+
|
|
+/* ACODEC_ADC_HPF_PGA_CTL */
|
|
+#define ACODEC_ADC_FILTER_MSK (1 << 7)
|
|
+#define ACODEC_ADC_FILTER_EN (1 << 7)
|
|
+#define ACODEC_ADC_FILTER_DIS (0 << 7)
|
|
+#define ACODEC_ADC_AGC_MSK (1 << 6)
|
|
+#define ACODEC_ADC_FILTER_OUTPUT (1 << 6)
|
|
+#define ACODEC_ADC_SINC_OUTPUT (0 << 6)
|
|
+#define ACODEC_ADC_L_PGA_MSK (1 << 5)
|
|
+#define ACODEC_ADC_PGA_ALCL_EN (1 << 5)
|
|
+#define ACODEC_ADC_PGA_ALCL_DIS (0 << 5)
|
|
+#define ACODEC_ADC_R_PGA_MSK (1 << 4)
|
|
+#define ACODEC_ADC_PGA_ALCR_EN (1 << 4)
|
|
+#define ACODEC_ADC_PGA_ALCR_DIS (0 << 4)
|
|
+#define ACODEC_ADC_HPF_SFT 2
|
|
+#define ACODEC_ADC_HPF_MSK (3 << ACODEC_ADC_HPF_SFT)
|
|
+#define ACODEC_ADC_HPF_EN (3 << ACODEC_ADC_HPF_SFT)
|
|
+#define ACODEC_ADC_HPF_DIS (0 << ACODEC_ADC_HPF_SFT)
|
|
+#define ACODEC_ADC_R_DATA_POL_INV_MSK (1 << 1)
|
|
+#define ACODEC_ADC_R_DATA_POL_INV_EN (1 << 1)
|
|
+#define ACODEC_ADC_R_DATA_POL_INV_DIS (0 << 1)
|
|
+#define ACODEC_ADC_L_DATA_POL_INV_MSK (1 << 0)
|
|
+#define ACODEC_ADC_L_DATA_POL_INV_EN (1 << 0)
|
|
+#define ACODEC_ADC_L_DATA_POL_INV_DIS (0 << 0)
|
|
+
|
|
+/* ACODEC_ADC_BIST_MODE_SEL */
|
|
+#define ACODEC_ADC_R_BIST_SFT 6
|
|
+#define ACODEC_ADC_R_BIST_MSK (0x3 << ACODEC_ADC_R_BIST_SFT)
|
|
+#define ACODEC_ADC_R_BIST_SINE (0x1 << ACODEC_ADC_R_BIST_SFT)
|
|
+#define ACODEC_ADC_BIST_RIGHT (0x0 << ACODEC_ADC_R_BIST_SFT) /* normal mode */
|
|
+#define ACODEC_ADC_L_BIST_SFT 4
|
|
+#define ACODEC_ADC_L_BIST_MSK (0x3 << ACODEC_ADC_L_BIST_SFT)
|
|
+#define ACODEC_ADC_L_BIST_SINE (0x1 << ACODEC_ADC_L_BIST_SFT)
|
|
+#define ACODEC_ADC_BIST_LEFT (0x0 << ACODEC_ADC_L_BIST_SFT) /* normal mode */
|
|
+
|
|
+/* ACODEC_LINEOUT_CTL */
|
|
+#define ACODEC_DAC_LINEOUT_EN_SFT 7
|
|
+#define ACODEC_DAC_LINEOUT_EN_WORK (0x1 << ACODEC_DAC_LINEOUT_EN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_EN_RST (0x0 << ACODEC_DAC_LINEOUT_EN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_INI_SFT 6
|
|
+#define ACODEC_DAC_LINEOUT_INI_WORK (0x1 << ACODEC_DAC_LINEOUT_INI_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_INI_RST (0x0 << ACODEC_DAC_LINEOUT_INI_SFT)
|
|
+#define ACODEC_DAC_IBIAS_SEL_SFT 0
|
|
+#define ACODEC_DAC_IBIAS_SEL_MSK (0xf << ACODEC_DAC_IBIAS_SEL_SFT)
|
|
+
|
|
+/* ACODEC_CURRENT_CHARGE_CTL */
|
|
+#define ACODEC_ADC_CURRENT_CHARGE_SFT 0
|
|
+#define ACODEC_ADC_CURRENT_CHARGE_MSK (0xff << ACODEC_ADC_CURRENT_CHARGE_SFT)
|
|
+/*
|
|
+ * 1: Choose the current I
|
|
+ * 0: Don't choose the current I
|
|
+ */
|
|
+#define ACODEC_ADC_SEL_I(x) (x & 0xff)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL0 */
|
|
+#define ACODEC_ADC_REF_VOL_MSK (0x1 << 5)
|
|
+#define ACODEC_ADC_REF_VOL_EN (0x1 << 5)
|
|
+#define ACODEC_ADC_REF_VOL_DIS (0x0 << 5)
|
|
+#define ACODEC_ADC_IBIAS_MSK (0x1 << 4)
|
|
+#define ACODEC_ADC_IBIAS_EN (0x1 << 4)
|
|
+#define ACODEC_ADC_IBIAS_DIS (0x0 << 4)
|
|
+#define ACODEC_MICBIAS_SFT 3
|
|
+#define ACODEC_MICBIAS_MSK (0x1 << 3)
|
|
+#define ACODEC_MICBIAS_WORK (0x1 << 3)
|
|
+#define ACODEC_MICBIAS_RST (0x0 << 3)
|
|
+#define ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT 0
|
|
+#define ACODEC_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_975 (0x7 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_95 (0x6 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_925 (0x5 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_9 (0x4 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_875 (0x3 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_85 (0x2 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_825 (0x1 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+#define ACODEC_ADC_MICBIAS_VOLT_0_8 (0x0 << ACODEC_ADC_LEVEL_RANGE_MICBIAS_SFT)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL1 */
|
|
+#define ACODEC_ADC_L_MIC_MSK (0x1 << 7)
|
|
+#define ACODEC_ADC_L_MIC_WORK (0x1 << 7)
|
|
+#define ACODEC_ADC_L_MIC_MUTE (0x0 << 7)
|
|
+#define ACODEC_ADC_L_MIC_SIGNAL_MSK (0x1 << 6)
|
|
+#define ACODEC_ADC_L_MIC_SIGNAL_WORK (0x1 << 6)
|
|
+#define ACODEC_ADC_L_MIC_SIGNAL_INIT (0x0 << 6)
|
|
+#define ACODEC_ADC_L_REF_VOL_BUF_MSK (0x1 << 5)
|
|
+#define ACODEC_ADC_L_REF_VOL_BUF_EN (0x1 << 5)
|
|
+#define ACODEC_ADC_L_REF_VOL_BUF_DIS (0x0 << 5)
|
|
+#define ACODEC_ADC_L_ZERO_CROSS_DET_MSK (0x1 << 4)
|
|
+#define ACODEC_ADC_L_ZERO_CROSS_DET_EN (0x1 << 4)
|
|
+#define ACODEC_ADC_L_ZERO_CROSS_DET_DIS (0x0 << 4)
|
|
+#define ACODEC_ADC_R_MIC_MSK (0x1 << 3)
|
|
+#define ACODEC_ADC_R_MIC_WORK (0x1 << 3)
|
|
+#define ACODEC_ADC_R_MIC_MUTE (0x0 << 3)
|
|
+#define ACODEC_ADC_R_MIC_SIGNAL_MSK (0x1 << 2)
|
|
+#define ACODEC_ADC_R_MIC_SIGNAL_WORK (0x1 << 2)
|
|
+#define ACODEC_ADC_R_MIC_SIGNAL_INIT (0x0 << 2)
|
|
+#define ACODEC_ADC_R_REF_VOL_BUF_MSK (0x1 << 1)
|
|
+#define ACODEC_ADC_R_REF_VOL_BUF_EN (0x1 << 1)
|
|
+#define ACODEC_ADC_R_REF_VOL_BUF_DIS (0x0 << 1)
|
|
+#define ACODEC_ADC_R_ZERO_CROSS_DET_MSK (0x1 << 0)
|
|
+#define ACODEC_ADC_R_ZERO_CROSS_DET_EN (0x1 << 0)
|
|
+#define ACODEC_ADC_R_ZERO_CROSS_DET_DIS (0x0 << 0)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL2 */
|
|
+#define ACODEC_ADC_MIC_GAIN_MAX 0x3
|
|
+#define ACODEC_ADC_MIC_GAIN_MIN 0x1
|
|
+#define ACODEC_ADC_L_MIC_GAIN_SFT 6
|
|
+#define ACODEC_ADC_L_MIC_GAIN_MSK (0x3 << ACODEC_ADC_L_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_MIC_GAIN_12DB (0x3 << ACODEC_ADC_L_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_MIC_GAIN_20DB (0x2 << ACODEC_ADC_L_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_MIC_GAIN_0DB (0x1 << ACODEC_ADC_L_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_MIC_GAIN_SFT 4
|
|
+#define ACODEC_ADC_R_MIC_GAIN_MSK (0x3 << ACODEC_ADC_R_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_MIC_GAIN_12DB (0x3 << ACODEC_ADC_R_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_MIC_GAIN_20DB (0x2 << ACODEC_ADC_R_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_MIC_GAIN_0DB (0x1 << ACODEC_ADC_R_MIC_GAIN_SFT)
|
|
+#define ACODEC_ADC_IBIAS_SEL_SFT 0
|
|
+#define ACODEC_ADC_IBIAS_SEL_MSK (0xf << ACODEC_ADC_IBIAS_SEL_SFT)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL3 */
|
|
+#define ACODEC_ADC_L_MODE_SEL_SFT 6
|
|
+#define ACODEC_ADC_L_MODE_SEL_MSK (0x3 << ACODEC_ADC_L_MODE_SEL_SFT)
|
|
+#define ACODEC_ADC_L_FULL_DIFFER2 (0x2 << ACODEC_ADC_L_MODE_SEL_SFT) /* Only used for rv1103 acodec */
|
|
+#define ACODEC_ADC_L_SINGLE_END (0x1 << ACODEC_ADC_L_MODE_SEL_SFT)
|
|
+#define ACODEC_ADC_L_FULL_DIFFER (0x0 << ACODEC_ADC_L_MODE_SEL_SFT)
|
|
+#define ACODEC_ADC_L_MSK (0x1 << 5)
|
|
+#define ACODEC_ADC_L_EN (0x1 << 5)
|
|
+#define ACODEC_ADC_L_DIS (0x0 << 5)
|
|
+#define ACODEC_MIC_L_MSK (0x1 << 4)
|
|
+#define ACODEC_MIC_L_EN (0x1 << 4)
|
|
+#define ACODEC_MIC_L_DIS (0x0 << 4)
|
|
+#define ACODEC_ADC_R_MODE_SEL_SFT 2
|
|
+#define ACODEC_ADC_R_MODE_SEL_MSK (0x3 << ACODEC_ADC_R_MODE_SEL_SFT)
|
|
+#define ACODEC_ADC_R_SINGLE_END (0x1 << ACODEC_ADC_R_MODE_SEL_SFT)
|
|
+#define ACODEC_ADC_R_FULL_DIFFER (0x0 << ACODEC_ADC_R_MODE_SEL_SFT)
|
|
+#define ACODEC_ADC_R_MSK (0x1 << 1)
|
|
+#define ACODEC_ADC_R_EN (0x1 << 1)
|
|
+#define ACODEC_ADC_R_DIS (0x0 << 1)
|
|
+#define ACODEC_MIC_R_MSK (0x1 << 0)
|
|
+#define ACODEC_MIC_R_EN (0x1 << 0)
|
|
+#define ACODEC_MIC_R_DIS (0x0 << 0)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL4 */
|
|
+#define ACODEC_ADC_L_ALC_GAIN_MAX 0x1f
|
|
+#define ACODEC_ADC_L_ALC_GAIN_MIN 0
|
|
+#define ACODEC_ADC_L_ALC_GAIN_SFT 0
|
|
+#define ACODEC_ADC_L_ALC_GAIN_MSK (0x1f << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_37_5 (0x1f << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_36 (0x1e << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_34_5 (0x1d << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_33 (0x1c << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_31_5 (0x1b << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_30 (0x1a << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_28_5 (0x19 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_27 (0x18 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_25_5 (0x17 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_24 (0x16 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_22_5 (0x15 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_21 (0x14 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_19_5 (0x13 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_18 (0x12 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_16_5 (0x11 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_15 (0x10 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_13_5 (0x0f << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_12 (0x0e << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_10_5 (0x0d << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_9 (0x0c << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_7_5 (0x0b << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_6 (0x0a << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_4_5 (0x09 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_3 (0x08 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_PDB_1_5 (0x07 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_0DB (0x06 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_NDB_1_5 (0x05 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_NDB_3 (0x04 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_NDB_4_5 (0x03 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_NDB_6 (0x02 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_NDB_7_5 (0x01 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_L_ALC_GAIN_NDB_9 (0x00 << ACODEC_ADC_L_ALC_GAIN_SFT)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL5 */
|
|
+#define ACODEC_ADC_R_ALC_GAIN_MAX 0x1f
|
|
+#define ACODEC_ADC_R_ALC_GAIN_MIN 0
|
|
+#define ACODEC_ADC_R_ALC_GAIN_SFT 0
|
|
+#define ACODEC_ADC_R_ALC_GAIN_MSK (0x1f << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_37_5 (0x1f << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_36 (0x1e << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_34_5 (0x1d << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_33 (0x1c << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_31_5 (0x1b << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_30 (0x1a << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_28_5 (0x19 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_27 (0x18 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_25_5 (0x17 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_24 (0x16 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_22_5 (0x15 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_21 (0x14 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_19_5 (0x13 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_18 (0x12 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_16_5 (0x11 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_15 (0x10 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_13_5 (0x0f << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_12 (0x0e << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_10_5 (0x0d << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_9 (0x0c << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_7_5 (0x0b << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_6 (0x0a << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_4_5 (0x09 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_3 (0x08 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_PDB_1_5 (0x07 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_0DB (0x06 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_NDB_1_5 (0x05 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_NDB_3 (0x04 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_NDB_4_5 (0x03 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_NDB_6 (0x02 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_NDB_7_5 (0x01 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+#define ACODEC_ADC_R_ALC_GAIN_NDB_9 (0x00 << ACODEC_ADC_R_ALC_GAIN_SFT)
|
|
+
|
|
+/* ACODEC_ADC_ANA_CTL6 */
|
|
+#define ACODEC_ADC_L_ALC_MSK (0x1 << 7)
|
|
+#define ACODEC_ADC_L_ALC_WORK (0x1 << 7)
|
|
+#define ACODEC_ADC_L_ALC_INIT (0x0 << 7)
|
|
+#define ACODEC_ADC_L_CLK_MSK (0x1 << 6)
|
|
+#define ACODEC_ADC_L_CLK_WORK (0x1 << 6)
|
|
+#define ACODEC_ADC_L_CLK_RST (0x0 << 6)
|
|
+#define ACODEC_ADC_L_WORK (0x1 << 5)
|
|
+#define ACODEC_ADC_L_INIT (0x0 << 5)
|
|
+#define ACODEC_ADC_L_SIGNAL_EN (0x1 << 4)
|
|
+#define ACODEC_ADC_L_SIGNAL_DIS (0x0 << 4)
|
|
+#define ACODEC_ADC_R_ALC_MSK (0x1 << 3)
|
|
+#define ACODEC_ADC_R_ALC_WORK (0x1 << 3)
|
|
+#define ACODEC_ADC_R_ALC_INIT (0x0 << 3)
|
|
+#define ACODEC_ADC_R_CLK_MSK (0x1 << 2)
|
|
+#define ACODEC_ADC_R_CLK_WORK (0x1 << 2)
|
|
+#define ACODEC_ADC_R_CLK_RST (0x0 << 2)
|
|
+#define ACODEC_ADC_R_WORK (0x1 << 1)
|
|
+#define ACODEC_ADC_R_INIT (0x0 << 1)
|
|
+#define ACODEC_ADC_R_SIGNAL_EN (0x1 << 0)
|
|
+#define ACODEC_ADC_R_SIGNAL_DIS (0x0 << 0)
|
|
+
|
|
+/* ACODEC_DAC_ANA_CTL0 */
|
|
+#define ACODEC_DAC_IBIAS_MSK (0x1 << 7)
|
|
+#define ACODEC_DAC_IBIAS_EN (0x1 << 7)
|
|
+#define ACODEC_DAC_IBIAS_DIS (0x0 << 7)
|
|
+#define ACODEC_DAC_L_REF_VOL_BUF_MSK (0x1 << 6)
|
|
+#define ACODEC_DAC_L_REF_VOL_BUF_EN (0x1 << 6)
|
|
+#define ACODEC_DAC_L_REF_VOL_BUF_DIS (0x0 << 6)
|
|
+#define ACODEC_DAC_L_REF_POP_SOUND_MSK (0x3 << 4)
|
|
+#define ACODEC_DAC_L_REF_POP_SOUND_WORK (0x2 << 4)
|
|
+#define ACODEC_DAC_L_REF_POP_SOUND_INIT (0x1 << 4)
|
|
+#define ACODEC_DAC_L_REF_POP_SOUND_DIS (0x0 << 4)
|
|
+#define ACODEC_DAC_L_REF_VOL_MSK (0x1 << 3)
|
|
+#define ACODEC_DAC_L_REF_VOL_EN (0x1 << 3)
|
|
+#define ACODEC_DAC_L_REF_VOL_DIS (0x0 << 3)
|
|
+#define ACODEC_DAC_L_CLK_MSK (0x1 << 2)
|
|
+#define ACODEC_DAC_L_CLK_EN (0x1 << 2)
|
|
+#define ACODEC_DAC_L_CLK_DIS (0x0 << 2)
|
|
+#define ACODEC_DAC_SRC_SIGNAL_MSK (0x1 << 1)
|
|
+#define ACODEC_DAC_SRC_SIGNAL_EN (0x1 << 1)
|
|
+#define ACODEC_DAC_SRC_SIGNAL_DIS (0x0 << 1)
|
|
+#define ACODEC_DAC_L_SIGNAL_MSK (0x1 << 0)
|
|
+#define ACODEC_DAC_L_SIGNAL_WORK (0x1 << 0)
|
|
+#define ACODEC_DAC_L_SIGNAL_INIT (0x0 << 0)
|
|
+
|
|
+/* ACODEC_DAC_ANA_CTL1 */
|
|
+#define ACODEC_DAC_L_LINEOUT_MUTE_MSK (0x1 << 6)
|
|
+#define ACODEC_DAC_L_LINEOUT_MUTE (0x0 << 6)
|
|
+#define ACODEC_DAC_L_LINEOUT_WORK (0x1 << 6)
|
|
+#define ACODEC_DAC_L_LINEOUT_SIGNAL_MSK (0x1 << 5)
|
|
+#define ACODEC_DAC_L_LINEOUT_SIGNAL_WORK (0x1 << 5)
|
|
+#define ACODEC_DAC_L_LINEOUT_SIGNAL_INIT (0x0 << 5)
|
|
+#define ACODEC_DAC_L_LINEOUT_MSK (0x1 << 4)
|
|
+#define ACODEC_DAC_L_LINEOUT_EN (0x1 << 4)
|
|
+#define ACODEC_DAC_L_LINEOUT_DIS (0x0 << 4)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_SFT 0
|
|
+#define ACODEC_DAC_DRV_STRENGTH_MSK (0xf << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_20_4 (0x8 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_22_7 (0x7 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_25_7 (0x6 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_29_7 (0x5 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_35_5 (0x4 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_44_2 (0x3 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_60_1 (0x2 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+#define ACODEC_DAC_DRV_STRENGTH_100 (0x1 << ACODEC_DAC_DRV_STRENGTH_SFT)
|
|
+
|
|
+/* ACODEC_DAC_ANA_CTL2 */
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_MAX 0x1e
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_MIN 0
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_SFT 0
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_MSK (0x1f << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_PDB_6_0 (0x1f << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_PDB_6 (0x1e << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_PDB_4_5 (0x1d << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_PDB_3 (0x1c << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_PDB_1_5 (0x1b << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_0DB (0x1a << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_1_5 (0x19 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_3 (0x18 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_4_5 (0x17 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_6 (0x16 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_7_5 (0x15 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_9 (0x14 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_10_5 (0x13 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_12 (0x12 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_13_5 (0x11 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_15 (0x10 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_16_5 (0x0f << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_18 (0x0e << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_19_5 (0x0d << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_21 (0x0c << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_22_5 (0x0b << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_24 (0x0a << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_25_5 (0x09 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_27 (0x08 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_28_5 (0x07 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_30 (0x06 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_31_5 (0x05 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_33 (0x04 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_34_5 (0x03 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_36 (0x02 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_37_5 (0x01 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+#define ACODEC_DAC_LINEOUT_GAIN_NDB_39 (0x00 << ACODEC_DAC_LINEOUT_GAIN_SFT)
|
|
+
|
|
+/* ACODEC_DAC_HPMIX_CTL */
|
|
+#define ACODEC_DAC_HPMIX_MSK (0x1 << 7)
|
|
+#define ACODEC_DAC_HPMIX_EN (0x1 << 7)
|
|
+#define ACODEC_DAC_HPMIX_DIS (0x0 << 7)
|
|
+#define ACODEC_DAC_HPMIX_GAIN_SFT 5
|
|
+#define ACODEC_DAC_HPMIX_GAIN_MAX 2
|
|
+#define ACODEC_DAC_HPMIX_GAIN_MIN 1
|
|
+#define ACODEC_DAC_HPMIX_GAIN_MSK (0x3 << ACODEC_DAC_HPMIX_GAIN_SFT)
|
|
+#define ACODEC_DAC_HPMIX_GAIN_6DB (0x2 << ACODEC_DAC_HPMIX_GAIN_SFT)
|
|
+#define ACODEC_DAC_HPMIX_GAIN_0DB (0x1 << ACODEC_DAC_HPMIX_GAIN_SFT)
|
|
+#define ACODEC_DAC_HPMIX_MDL_MSK (0x1 << 4)
|
|
+#define ACODEC_DAC_HPMIX_MDL_WORK (0x1 << 4)
|
|
+#define ACODEC_DAC_HPMIX_MDL_INIT (0x0 << 4)
|
|
+#define ACODEC_DAC_HPMIX_MUTE_MSK (0x1 << 3)
|
|
+#define ACODEC_DAC_HPMIX_WORK (0x1 << 3)
|
|
+#define ACODEC_DAC_HPMIX_MUTE (0x0 << 3)
|
|
+#define ACODEC_DAC_HPMIX_SEL_SFT 0
|
|
+#define ACODEC_DAC_HPMIX_SEL_MSK (0x7 << ACODEC_DAC_HPMIX_SEL_SFT)
|
|
+#define ACODEC_DAC_HPMIX_ADCR (0x4 << ACODEC_DAC_HPMIX_SEL_SFT)
|
|
+#define ACODEC_DAC_HPMIX_ADCL (0x2 << ACODEC_DAC_HPMIX_SEL_SFT)
|
|
+#define ACODEC_DAC_HPMIX_I2S (0x1 << ACODEC_DAC_HPMIX_SEL_SFT)
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL0 */
|
|
+#define ACODEC_GAIN_ATTACK_MSK (1 << 6)
|
|
+#define ACODEC_GAIN_ATTACK_JACK (1 << 6)
|
|
+#define ACODEC_GAIN_ATTACK_NORMAL (0 << 6)
|
|
+#define ACODEC_CTRL_GEN_SFT 4
|
|
+#define ACODEC_CTRL_GEN_MSK (0x3 << ACODEC_ALC_CTRL_GEN_SFT)
|
|
+#define ACODEC_CTRL_GEN_JACK3 (0x3 << ACODEC_ALC_CTRL_GEN_SFT)
|
|
+#define ACODEC_CTRL_GEN_JACK2 (0x2 << ACODEC_ALC_CTRL_GEN_SFT)
|
|
+#define ACODEC_CTRL_GEN_JACK1 (0x1 << ACODEC_ALC_CTRL_GEN_SFT)
|
|
+#define ACODEC_CTRL_GEN_NORMAL (0x0 << ACODEC_ALC_CTRL_GEN_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_SFT 0
|
|
+#define ACODEC_AGC_HOLD_TIME_MSK (0xf << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_1S (0xa << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_512MS (0x9 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_256MS (0x8 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_128MS (0x7 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_64MS (0x6 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_32MS (0x5 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_16MS (0x4 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_8MS (0x3 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_4MS (0x2 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_2MS (0x1 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+#define ACODEC_AGC_HOLD_TIME_0MS (0x0 << ACODEC_AGC_HOLD_TIME_SFT)
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL1 */
|
|
+#define ACODEC_AGC_DECAY_TIME_SFT 4
|
|
+/* Normal mode (reg_agc_mode = 0) */
|
|
+#define ACODEC_AGC_DECAY_NORMAL_MSK (0xf << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_512MS (0xa << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_256MS (0x9 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_128MS (0x8 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_64MS (0x7 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_32MS (0x6 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_16MS (0x5 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_8MS (0x4 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_4MS (0x3 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_2MS (0x2 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_1MS (0x1 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_NORMAL_0MS (0x0 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+/* Limiter mode (reg_agc_mode = 1) */
|
|
+#define ACODEC_AGC_DECAY_LIMITER_MSK (0xf << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_128MS (0xa << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_64MS (0x9 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_32MS (0x8 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_16MS (0x7 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_8MS (0x6 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_4MS (0x5 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_2MS (0x4 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_1MS (0x3 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_500US (0x2 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_250US (0x1 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_DECAY_LIMITER_125US (0x0 << ACODEC_AGC_DECAY_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_TIME_SFT 0
|
|
+/* Normal mode (reg_agc_mode = 0) */
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_MSK (0xf << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_128MS (0xa << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_64MS (0x9 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_32MS (0x8 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_16MS (0x7 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_8MS (0x6 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_4MS (0x5 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_2MS (0x4 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_1MS (0x3 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_500US (0x2 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_250US (0x1 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_NORMAL_125US (0x0 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+/* Limiter mode (reg_agc_mode = 1) */
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_MSK (0xf << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_32MS (0xa << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_16MS (0x9 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_8MS (0x8 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_4MS (0x7 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_2MS (0x6 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_1MS (0x5 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_500US (0x4 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_250US (0x3 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_125US (0x2 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_64US (0x1 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+#define ACODEC_AGC_ATTACK_LIMITER_32US (0x0 << ACODEC_AGC_ATTACK_TIME_SFT)
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL2 */
|
|
+#define ACODEC_AGC_MODE_LIMITER (0x1 << 7)
|
|
+#define ACODEC_AGC_MODE_NORMAL (0x0 << 7)
|
|
+#define ACODEC_AGC_ZERO_CRO_EN (0x1 << 6)
|
|
+#define ACODEC_AGC_ZERO_CRO_DIS (0x0 << 6)
|
|
+#define ACODEC_AGC_AMP_RECOVER_GAIN (0x1 << 5)
|
|
+#define ACODEC_AGC_AMP_RECOVER_LVOL (0x0 << 5)
|
|
+#define ACODEC_AGC_FAST_DEC_EN (0x1 << 4)
|
|
+#define ACODEC_AGC_FAST_DEC_DIS (0x0 << 4)
|
|
+#define ACODEC_AGC_NOISE_GATE_EN (0x1 << 3)
|
|
+#define ACODEC_AGC_NOISE_GATE_DIS (0x0 << 3)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_SFT 0
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_MSK (0x7 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N81DB (0x7 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N75DB (0x6 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N69DB (0x5 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N63DB (0x4 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N57DB (0x3 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N51DB (0x2 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N45DB (0x1 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+#define ACODEC_AGC_NOISE_GATE_THRESH_N39DB (0x0 << ACODEC_AGC_NOISE_GATE_THRESH_SFT)
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL3 */
|
|
+#define ACODEC_AGC_PGA_ZERO_CRO_EN (0x1 << 5)
|
|
+#define ACODEC_AGC_PGA_ZERO_CRO_DIS (0x0 << 5)
|
|
+#define ACODEC_AGC_PGA_GAIN_MAX 0x1f
|
|
+#define ACODEC_AGC_PGA_GAIN_MIN 0
|
|
+#define ACODEC_AGC_PGA_GAIN_SFT 0
|
|
+#define ACODEC_AGC_PGA_GAIN_MSK (0x1f << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_28_5 (0x1f << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_27 (0x1e << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_25_5 (0x1d << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_24 (0x1c << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_22_5 (0x1b << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_21 (0x1a << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_19_5 (0x19 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_18 (0x18 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_16_5 (0x17 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_15 (0x16 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_13_5 (0x15 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_12 (0x14 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_10_5 (0x13 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_9 (0x12 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_7_5 (0x11 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_6 (0x10 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_4_5 (0x0f << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_3 (0x0e << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_PDB_1_5 (0x0d << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_0DB (0x0c << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_1_5 (0x0b << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_3 (0x0a << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_4_5 (0x09 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_6 (0x08 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_7_5 (0x07 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_9 (0x06 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_10_5 (0x05 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_12 (0x04 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_13_5 (0x03 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_15 (0x02 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_16_5 (0x01 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+#define ACODEC_AGC_PGA_GAIN_NDB_18 (0x00 << ACODEC_AGC_PGA_GAIN_SFT)
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL4 */
|
|
+#define ACODEC_AGC_SLOW_CLK_EN (0x1 << 3)
|
|
+#define ACODEC_AGC_SLOW_CLK_DIS (0x0 << 3)
|
|
+#define ACODEC_AGC_APPROX_RATE_SFT 0
|
|
+#define ACODEC_AGC_APPROX_RATE_MSK (0x7 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_8K (0x7 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_12K (0x6 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_16K (0x5 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_24K (0x4 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_32K (0x3 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_44_1K (0x2 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_48K (0x1 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+#define ACODEC_AGC_APPROX_RATE_96K (0x0 << ACODEC_AGC_APPROX_RATE_SFT)
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL5 */
|
|
+#define ACODEC_AGC_LO_8BITS_AGC_MAX_MSK 0xff
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL6 */
|
|
+#define ACODEC_AGC_HI_8BITS_AGC_MAX_MSK 0xff
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL7 */
|
|
+#define ACODEC_AGC_LO_8BITS_AGC_MIN_MSK 0xff
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL8 */
|
|
+#define ACODEC_AGC_HI_8BITS_AGC_MIN_MSK 0xff
|
|
+
|
|
+/* ACODEC_ADC_PGA_AGC_L_CTL9 */
|
|
+#define ACODEC_AGC_FUNC_SEL_MSK (0x1 << 6)
|
|
+#define ACODEC_AGC_FUNC_SEL_EN (0x1 << 6)
|
|
+#define ACODEC_AGC_FUNC_SEL_DIS (0x0 << 6)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_MAX 0x7
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_MIN 0
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_SFT 3
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_MSK (0x7 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_PDB_28_5 (0x7 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_PDB_22_5 (0x6 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_PDB_16_5 (0x5 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_PDB_10_5 (0x4 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_PDB_4_5 (0x3 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_NDB_1_5 (0x2 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_NDB_7_5 (0x1 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MAX_GAIN_PGA_NDB_13_5 (0x0 << ACODEC_AGC_MAX_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_MAX 0x7
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_MIN 0
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_SFT 0
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_MSK (0x7 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_PDB_24 (0x7 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_PDB_18 (0x6 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_PDB_12 (0x5 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_PDB_6 (0x4 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_0DB (0x3 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_NDB_6 (0x2 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_NDB_12 (0x1 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+#define ACODEC_AGC_MIN_GAIN_PGA_NDB_18 (0x0 << ACODEC_AGC_MIN_GAIN_PGA_SFT)
|
|
+
|
|
+#define ACODEC_HIFI 0x0
|
|
+
|
|
+#endif /* __RV1106_CODEC_H__ */
|