aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt71
-rw-r--r--Documentation/devicetree/bindings/sound/rt5640.txt30
-rw-r--r--include/sound/rt5640.h22
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/rt5640.c2128
-rw-r--r--sound/soc/codecs/rt5640.h2092
-rw-r--r--sound/soc/tegra/Kconfig10
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra_rt5640.c257
10 files changed, 4618 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt
new file mode 100644
index 00000000000..d130818700b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-rt5640.txt
@@ -0,0 +1,71 @@
+NVIDIA Tegra audio complex, with RT5640 CODEC
+
+Required properties:
+- compatible : "nvidia,tegra-audio-rt5640"
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+ "pll_a" (The Tegra clock of that name),
+ "pll_a_out0" (The Tegra clock of that name),
+ "mclk" (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+ Each entry is a pair of strings, the first being the connection's sink,
+ the second being the connection's source. Valid names for sources and
+ sinks are the RT5640's pins, and the jacks on the board:
+
+ RT5640 pins:
+
+ * DMIC1
+ * DMIC2
+ * MICBIAS1
+ * IN1P
+ * IN1R
+ * IN2P
+ * IN2R
+ * HPOL
+ * HPOR
+ * LOUTL
+ * LOUTR
+ * MONOP
+ * MONON
+ * SPOLP
+ * SPOLN
+ * SPORP
+ * SPORN
+
+ Board connectors:
+
+ * Headphones
+ * Speakers
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
+ connected to the CODEC.
+- nvidia,audio-codec : The phandle of the RT5640 audio codec. This binding
+ assumes that AIF1 on the CODEC is connected to Tegra.
+
+Optional properties:
+- nvidia,hp-det-gpios : The GPIO that detects headphones are plugged in
+
+Example:
+
+sound {
+ compatible = "nvidia,tegra-audio-rt5640-dalmore",
+ "nvidia,tegra-audio-rt5640";
+ nvidia,model = "NVIDIA Tegra Dalmore";
+
+ nvidia,audio-routing =
+ "Headphones", "HPOR",
+ "Headphones", "HPOL",
+ "Speakers", "SPORP",
+ "Speakers", "SPORN",
+ "Speakers", "SPOLP",
+ "Speakers", "SPOLN";
+
+ nvidia,i2s-controller = <&tegra_i2s1>;
+ nvidia,audio-codec = <&rt5640>;
+
+ nvidia,hp-det-gpios = <&gpio 143 0>; /* GPIO PR7 */
+
+ clocks = <&tegra_car 216>, <&tegra_car 217>, <&tegra_car 120>;
+ clock-names = "pll_a", "pll_a_out0", "mclk";
+};
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt
new file mode 100644
index 00000000000..005bcb24d72
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rt5640.txt
@@ -0,0 +1,30 @@
+RT5640 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : "realtek,rt5640".
+
+- reg : The I2C address of the device.
+
+- interrupts : The CODEC's interrupt output.
+
+Optional properties:
+
+- realtek,in1-differential
+- realtek,in2-differential
+ Boolean. Indicate MIC1/2 input are differential, rather than single-ended.
+
+- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
+
+Example:
+
+rt5640 {
+ compatible = "realtek,rt5640";
+ reg = <0x1c>;
+ interrupt-parent = <&gpio>;
+ interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
+ realtek,ldo1-en-gpios =
+ <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
+};
diff --git a/include/sound/rt5640.h b/include/sound/rt5640.h
new file mode 100644
index 00000000000..27cc75ed67f
--- /dev/null
+++ b/include/sound/rt5640.h
@@ -0,0 +1,22 @@
+/*
+ * linux/sound/rt5640.h -- Platform data for RT5640
+ *
+ * Copyright 2011 Realtek Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_RT5640_H
+#define __LINUX_SND_RT5640_H
+
+struct rt5640_platform_data {
+ /* IN1 & IN2 can optionally be differential */
+ bool in1_diff;
+ bool in2_diff;
+
+ int ldo1_en; /* GPIO for LDO1_EN */
+};
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c691e222670..0615e00b4ab 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -56,6 +56,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_HDMI_CODEC
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
+ select SND_SOC_RT5640 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE
select SND_SOC_SN95031 if INTEL_SCU_IPC
@@ -296,6 +297,9 @@ config SND_SOC_PCM3008
config SND_SOC_RT5631
tristate
+config SND_SOC_RT5640
+ tristate
+
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 82aa34e034c..93b3e222048 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -44,6 +44,7 @@ snd-soc-ml26124-objs := ml26124.o
snd-soc-hdmi-codec-objs := hdmi.o
snd-soc-pcm3008-objs := pcm3008.o
snd-soc-rt5631-objs := rt5631.o
+snd-soc-rt5640-objs := rt5640.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
snd-soc-alc5632-objs := alc5632.o
@@ -171,6 +172,7 @@ obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
+obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
new file mode 100644
index 00000000000..ce585e37e38
--- /dev/null
+++ b/sound/soc/codecs/rt5640.c
@@ -0,0 +1,2128 @@
+/*
+ * rt5640.c -- RT5640 ALSA SoC audio codec driver
+ *
+ * Copyright 2011 Realtek Semiconductor Corp.
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rt5640.h"
+
+#define RT5640_DEVICE_ID 0x6231
+
+#define RT5640_PR_RANGE_BASE (0xff + 1)
+#define RT5640_PR_SPACING 0x100
+
+#define RT5640_PR_BASE (RT5640_PR_RANGE_BASE + (0 * RT5640_PR_SPACING))
+
+static const struct regmap_range_cfg rt5640_ranges[] = {
+ { .name = "PR", .range_min = RT5640_PR_BASE,
+ .range_max = RT5640_PR_BASE + 0xb4,
+ .selector_reg = RT5640_PRIV_INDEX,
+ .selector_mask = 0xff,
+ .selector_shift = 0x0,
+ .window_start = RT5640_PRIV_DATA,
+ .window_len = 0x1, },
+};
+
+static struct reg_default init_list[] = {
+ {RT5640_PR_BASE + 0x3d, 0x3600},
+ {RT5640_PR_BASE + 0x1c, 0x0D21},
+ {RT5640_PR_BASE + 0x1b, 0x0000},
+ {RT5640_PR_BASE + 0x12, 0x0aa8},
+ {RT5640_PR_BASE + 0x14, 0x0aaa},
+ {RT5640_PR_BASE + 0x20, 0x6110},
+ {RT5640_PR_BASE + 0x21, 0xe0e0},
+ {RT5640_PR_BASE + 0x23, 0x1804},
+};
+#define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
+ { 0x00, 0x000e },
+ { 0x01, 0xc8c8 },
+ { 0x02, 0xc8c8 },
+ { 0x03, 0xc8c8 },
+ { 0x04, 0x8000 },
+ { 0x0d, 0x0000 },
+ { 0x0e, 0x0000 },
+ { 0x0f, 0x0808 },
+ { 0x19, 0xafaf },
+ { 0x1a, 0xafaf },
+ { 0x1b, 0x0000 },
+ { 0x1c, 0x2f2f },
+ { 0x1d, 0x2f2f },
+ { 0x1e, 0x0000 },
+ { 0x27, 0x7060 },
+ { 0x28, 0x7070 },
+ { 0x29, 0x8080 },
+ { 0x2a, 0x5454 },
+ { 0x2b, 0x5454 },
+ { 0x2c, 0xaa00 },
+ { 0x2d, 0x0000 },
+ { 0x2e, 0xa000 },
+ { 0x2f, 0x0000 },
+ { 0x3b, 0x0000 },
+ { 0x3c, 0x007f },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x007f },
+ { 0x45, 0xe000 },
+ { 0x46, 0x003e },
+ { 0x47, 0x003e },
+ { 0x48, 0xf800 },
+ { 0x49, 0x3800 },
+ { 0x4a, 0x0004 },
+ { 0x4c, 0xfc00 },
+ { 0x4d, 0x0000 },
+ { 0x4f, 0x01ff },
+ { 0x50, 0x0000 },
+ { 0x51, 0x0000 },
+ { 0x52, 0x01ff },
+ { 0x53, 0xf000 },
+ { 0x61, 0x0000 },
+ { 0x62, 0x0000 },
+ { 0x63, 0x00c0 },
+ { 0x64, 0x0000 },
+ { 0x65, 0x0000 },
+ { 0x66, 0x0000 },
+ { 0x6a, 0x0000 },
+ { 0x6c, 0x0000 },
+ { 0x70, 0x8000 },
+ { 0x71, 0x8000 },
+ { 0x72, 0x8000 },
+ { 0x73, 0x1114 },
+ { 0x74, 0x0c00 },
+ { 0x75, 0x1d00 },
+ { 0x80, 0x0000 },
+ { 0x81, 0x0000 },
+ { 0x82, 0x0000 },
+ { 0x83, 0x0000 },
+ { 0x84, 0x0000 },
+ { 0x85, 0x0008 },
+ { 0x89, 0x0000 },
+ { 0x8a, 0x0000 },
+ { 0x8b, 0x0600 },
+ { 0x8c, 0x0228 },
+ { 0x8d, 0xa000 },
+ { 0x8e, 0x0004 },
+ { 0x8f, 0x1100 },
+ { 0x90, 0x0646 },
+ { 0x91, 0x0c00 },
+ { 0x92, 0x0000 },
+ { 0x93, 0x3000 },
+ { 0xb0, 0x2080 },
+ { 0xb1, 0x0000 },
+ { 0xb4, 0x2206 },
+ { 0xb5, 0x1f00 },
+ { 0xb6, 0x0000 },
+ { 0xb8, 0x034b },
+ { 0xb9, 0x0066 },
+ { 0xba, 0x000b },
+ { 0xbb, 0x0000 },
+ { 0xbc, 0x0000 },
+ { 0xbd, 0x0000 },
+ { 0xbe, 0x0000 },
+ { 0xbf, 0x0000 },
+ { 0xc0, 0x0400 },
+ { 0xc2, 0x0000 },
+ { 0xc4, 0x0000 },
+ { 0xc5, 0x0000 },
+ { 0xc6, 0x2000 },
+ { 0xc8, 0x0000 },
+ { 0xc9, 0x0000 },
+ { 0xca, 0x0000 },
+ { 0xcb, 0x0000 },
+ { 0xcc, 0x0000 },
+ { 0xcf, 0x0013 },
+ { 0xd0, 0x0680 },
+ { 0xd1, 0x1c17 },
+ { 0xd2, 0x8c00 },
+ { 0xd3, 0xaa20 },
+ { 0xd6, 0x0400 },
+ { 0xd9, 0x0809 },
+ { 0xfe, 0x10ec },
+ { 0xff, 0x6231 },
+};
+
+static int rt5640_reset(struct snd_soc_codec *codec)
+{
+ return snd_soc_write(codec, RT5640_RESET, 0);
+}
+
+static bool rt5640_volatile_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5640_ranges); i++)
+ if ((reg >= rt5640_ranges[i].window_start &&
+ reg <= rt5640_ranges[i].window_start +
+ rt5640_ranges[i].window_len) ||
+ (reg >= rt5640_ranges[i].range_min &&
+ reg <= rt5640_ranges[i].range_max))
+ return true;
+
+ switch (reg) {
+ case RT5640_RESET:
+ case RT5640_ASRC_5:
+ case RT5640_EQ_CTRL1:
+ case RT5640_DRC_AGC_1:
+ case RT5640_ANC_CTRL1:
+ case RT5640_IRQ_CTRL2:
+ case RT5640_INT_IRQ_ST:
+ case RT5640_DSP_CTRL2:
+ case RT5640_DSP_CTRL3:
+ case RT5640_PRIV_INDEX:
+ case RT5640_PRIV_DATA:
+ case RT5640_PGM_REG_ARR1:
+ case RT5640_PGM_REG_ARR3:
+ case RT5640_VENDOR_ID:
+ case RT5640_VENDOR_ID1:
+ case RT5640_VENDOR_ID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool rt5640_readable_register(struct device *dev, unsigned int reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rt5640_ranges); i++)
+ if ((reg >= rt5640_ranges[i].window_start &&
+ reg <= rt5640_ranges[i].window_start +
+ rt5640_ranges[i].window_len) ||
+ (reg >= rt5640_ranges[i].range_min &&
+ reg <= rt5640_ranges[i].range_max))
+ return true;
+
+ switch (reg) {
+ case RT5640_RESET:
+ case RT5640_SPK_VOL:
+ case RT5640_HP_VOL:
+ case RT5640_OUTPUT:
+ case RT5640_MONO_OUT:
+ case RT5640_IN1_IN2:
+ case RT5640_IN3_IN4:
+ case RT5640_INL_INR_VOL:
+ case RT5640_DAC1_DIG_VOL:
+ case RT5640_DAC2_DIG_VOL:
+ case RT5640_DAC2_CTRL:
+ case RT5640_ADC_DIG_VOL:
+ case RT5640_ADC_DATA:
+ case RT5640_ADC_BST_VOL:
+ case RT5640_STO_ADC_MIXER:
+ case RT5640_MONO_ADC_MIXER:
+ case RT5640_AD_DA_MIXER:
+ case RT5640_STO_DAC_MIXER:
+ case RT5640_MONO_DAC_MIXER:
+ case RT5640_DIG_MIXER:
+ case RT5640_DSP_PATH1:
+ case RT5640_DSP_PATH2:
+ case RT5640_DIG_INF_DATA:
+ case RT5640_REC_L1_MIXER:
+ case RT5640_REC_L2_MIXER:
+ case RT5640_REC_R1_MIXER:
+ case RT5640_REC_R2_MIXER:
+ case RT5640_HPO_MIXER:
+ case RT5640_SPK_L_MIXER:
+ case RT5640_SPK_R_MIXER:
+ case RT5640_SPO_L_MIXER:
+ case RT5640_SPO_R_MIXER:
+ case RT5640_SPO_CLSD_RATIO:
+ case RT5640_MONO_MIXER:
+ case RT5640_OUT_L1_MIXER:
+ case RT5640_OUT_L2_MIXER:
+ case RT5640_OUT_L3_MIXER:
+ case RT5640_OUT_R1_MIXER:
+ case RT5640_OUT_R2_MIXER:
+ case RT5640_OUT_R3_MIXER:
+ case RT5640_LOUT_MIXER:
+ case RT5640_PWR_DIG1:
+ case RT5640_PWR_DIG2:
+ case RT5640_PWR_ANLG1:
+ case RT5640_PWR_ANLG2:
+ case RT5640_PWR_MIXER:
+ case RT5640_PWR_VOL:
+ case RT5640_PRIV_INDEX:
+ case RT5640_PRIV_DATA:
+ case RT5640_I2S1_SDP:
+ case RT5640_I2S2_SDP:
+ case RT5640_ADDA_CLK1:
+ case RT5640_ADDA_CLK2:
+ case RT5640_DMIC:
+ case RT5640_GLB_CLK:
+ case RT5640_PLL_CTRL1:
+ case RT5640_PLL_CTRL2:
+ case RT5640_ASRC_1:
+ case RT5640_ASRC_2:
+ case RT5640_ASRC_3:
+ case RT5640_ASRC_4:
+ case RT5640_ASRC_5:
+ case RT5640_HP_OVCD:
+ case RT5640_CLS_D_OVCD:
+ case RT5640_CLS_D_OUT:
+ case RT5640_DEPOP_M1:
+ case RT5640_DEPOP_M2:
+ case RT5640_DEPOP_M3:
+ case RT5640_CHARGE_PUMP:
+ case RT5640_PV_DET_SPK_G:
+ case RT5640_MICBIAS:
+ case RT5640_EQ_CTRL1:
+ case RT5640_EQ_CTRL2:
+ case RT5640_WIND_FILTER:
+ case RT5640_DRC_AGC_1:
+ case RT5640_DRC_AGC_2:
+ case RT5640_DRC_AGC_3:
+ case RT5640_SVOL_ZC:
+ case RT5640_ANC_CTRL1:
+ case RT5640_ANC_CTRL2:
+ case RT5640_ANC_CTRL3:
+ case RT5640_JD_CTRL:
+ case RT5640_ANC_JD:
+ case RT5640_IRQ_CTRL1:
+ case RT5640_IRQ_CTRL2:
+ case RT5640_INT_IRQ_ST:
+ case RT5640_GPIO_CTRL1:
+ case RT5640_GPIO_CTRL2:
+ case RT5640_GPIO_CTRL3:
+ case RT5640_DSP_CTRL1:
+ case RT5640_DSP_CTRL2:
+ case RT5640_DSP_CTRL3:
+ case RT5640_DSP_CTRL4:
+ case RT5640_PGM_REG_ARR1:
+ case RT5640_PGM_REG_ARR2:
+ case RT5640_PGM_REG_ARR3:
+ case RT5640_PGM_REG_ARR4:
+ case RT5640_PGM_REG_ARR5:
+ case RT5640_SCB_FUNC:
+ case RT5640_SCB_CTRL:
+ case RT5640_BASE_BACK:
+ case RT5640_MP3_PLUS1:
+ case RT5640_MP3_PLUS2:
+ case RT5640_3D_HP:
+ case RT5640_ADJ_HPF:
+ case RT5640_HP_CALIB_AMP_DET:
+ case RT5640_HP_CALIB2:
+ case RT5640_SV_ZCD1:
+ case RT5640_SV_ZCD2:
+ case RT5640_DUMMY1:
+ case RT5640_DUMMY2:
+ case RT5640_DUMMY3:
+ case RT5640_VENDOR_ID:
+ case RT5640_VENDOR_ID1:
+ case RT5640_VENDOR_ID2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
+
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
+static unsigned int bst_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+/* Interface data select */
+static const char * const rt5640_data_select[] = {
+ "Normal", "left copy to right", "right copy to left", "Swap"};
+
+static const SOC_ENUM_SINGLE_DECL(rt5640_if1_dac_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF1_DAC_SEL_SFT, rt5640_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5640_if1_adc_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF1_ADC_SEL_SFT, rt5640_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5640_if2_dac_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF2_DAC_SEL_SFT, rt5640_data_select);
+
+static const SOC_ENUM_SINGLE_DECL(rt5640_if2_adc_enum, RT5640_DIG_INF_DATA,
+ RT5640_IF2_ADC_SEL_SFT, rt5640_data_select);
+
+/* Class D speaker gain ratio */
+static const char * const rt5640_clsd_spk_ratio[] = {"1.66x", "1.83x", "1.94x",
+ "2x", "2.11x", "2.22x", "2.33x", "2.44x", "2.55x", "2.66x", "2.77x"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_clsd_spk_ratio_enum, RT5640_CLS_D_OUT,
+ RT5640_CLSD_RATIO_SFT, rt5640_clsd_spk_ratio);
+
+static const struct snd_kcontrol_new rt5640_snd_controls[] = {
+ /* Speaker Output Volume */
+ SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL,
+ RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL,
+ RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
+ /* Headphone Output Volume */
+ SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL,
+ RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL,
+ RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
+ /* OUTPUT Control */
+ SOC_DOUBLE("OUT Playback Switch", RT5640_OUTPUT,
+ RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE("OUT Channel Switch", RT5640_OUTPUT,
+ RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1),
+ SOC_DOUBLE_TLV("OUT Playback Volume", RT5640_OUTPUT,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv),
+ /* MONO Output Control */
+ SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT,
+ RT5640_L_MUTE_SFT, 1, 1),
+ /* DAC Digital Volume */
+ SOC_DOUBLE("DAC2 Playback Switch", RT5640_DAC2_CTRL,
+ RT5640_M_DAC_L2_VOL_SFT, RT5640_M_DAC_R2_VOL_SFT, 1, 1),
+ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5640_DAC1_DIG_VOL,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
+ 175, 0, dac_vol_tlv),
+ SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
+ 175, 0, dac_vol_tlv),
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost", RT5640_IN1_IN2,
+ RT5640_BST_SFT1, 8, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost", RT5640_IN3_IN4,
+ RT5640_BST_SFT2, 8, 0, bst_tlv),
+ /* INL/INR Volume Control */
+ SOC_DOUBLE_TLV("IN Capture Volume", RT5640_INL_INR_VOL,
+ RT5640_INL_VOL_SFT, RT5640_INR_VOL_SFT,
+ 31, 1, in_vol_tlv),
+ /* ADC Digital Volume Control */
+ SOC_DOUBLE("ADC Capture Switch", RT5640_ADC_DIG_VOL,
+ RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1),
+ SOC_DOUBLE_TLV("ADC Capture Volume", RT5640_ADC_DIG_VOL,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
+ 127, 0, adc_vol_tlv),
+ SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5640_ADC_DATA,
+ RT5640_L_VOL_SFT, RT5640_R_VOL_SFT,
+ 127, 0, adc_vol_tlv),
+ /* ADC Boost Volume Control */
+ SOC_DOUBLE_TLV("ADC Boost Gain", RT5640_ADC_BST_VOL,
+ RT5640_ADC_L_BST_SFT, RT5640_ADC_R_BST_SFT,
+ 3, 0, adc_bst_tlv),
+ /* Class D speaker gain ratio */
+ SOC_ENUM("Class D SPK Ratio Control", rt5640_clsd_spk_ratio_enum),
+
+ SOC_ENUM("ADC IF1 Data Switch", rt5640_if1_adc_enum),
+ SOC_ENUM("DAC IF1 Data Switch", rt5640_if1_dac_enum),
+ SOC_ENUM("ADC IF2 Data Switch", rt5640_if2_adc_enum),
+ SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum),
+};
+
+/**
+ * set_dmic_clk - Set parameter of dmic.
+ *
+ * @w: DAPM widget.
+ * @kcontrol: The kcontrol of this widget.
+ * @event: Event id.
+ *
+ * Choose dmic clock between 1MHz and 3MHz.
+ * It is better for clock to approximate 3MHz.
+ */
+static int set_dmic_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+ int div[] = {2, 3, 4, 6, 8, 12};
+ int idx = -EINVAL, i;
+ int rate, red, bound, temp;
+
+ rate = rt5640->sysclk;
+ red = 3000000 * 12;
+ for (i = 0; i < ARRAY_SIZE(div); i++) {
+ bound = div[i] * 3000000;
+ if (rate > bound)
+ continue;
+ temp = bound - rate;
+ if (temp < red) {
+ red = temp;
+ idx = i;
+ }
+ }
+ if (idx < 0)
+ dev_err(codec->dev, "Failed to set DMIC clock\n");
+ else
+ snd_soc_update_bits(codec, RT5640_DMIC, RT5640_DMIC_CLK_MASK,
+ idx << RT5640_DMIC_CLK_SFT);
+ return idx;
+}
+
+static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int val;
+
+ val = snd_soc_read(source->codec, RT5640_GLB_CLK);
+ val &= RT5640_SCLK_SRC_MASK;
+ if (val == RT5640_SCLK_SRC_PLL1 || val == RT5640_SCLK_SRC_PLL1T)
+ return 1;
+ else
+ return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5640_sto_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
+ RT5640_M_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5640_STO_ADC_MIXER,
+ RT5640_M_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_sto_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5640_STO_ADC_MIXER,
+ RT5640_M_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5640_STO_ADC_MIXER,
+ RT5640_M_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_mono_adc_l_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5640_MONO_ADC_MIXER,
+ RT5640_M_MONO_ADC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5640_MONO_ADC_MIXER,
+ RT5640_M_MONO_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_mono_adc_r_mix[] = {
+ SOC_DAPM_SINGLE("ADC1 Switch", RT5640_MONO_ADC_MIXER,
+ RT5640_M_MONO_ADC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ADC2 Switch", RT5640_MONO_ADC_MIXER,
+ RT5640_M_MONO_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5640_AD_DA_MIXER,
+ RT5640_M_ADCMIX_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INF1 Switch", RT5640_AD_DA_MIXER,
+ RT5640_M_IF1_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("Stereo ADC Switch", RT5640_AD_DA_MIXER,
+ RT5640_M_ADCMIX_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INF1 Switch", RT5640_AD_DA_MIXER,
+ RT5640_M_IF1_DAC_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_sto_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_L1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_L2_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ANC Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_ANC_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_sto_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_R1_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_DAC_R2_SFT, 1, 1),
+ SOC_DAPM_SINGLE("ANC Switch", RT5640_STO_DAC_MIXER,
+ RT5640_M_ANC_DAC_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_mono_dac_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_MONO_DAC_MIXER,
+ RT5640_M_DAC_L1_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_DAC_MIXER,
+ RT5640_M_DAC_L2_MONO_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_DAC_MIXER,
+ RT5640_M_DAC_R2_MONO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_mono_dac_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_MONO_DAC_MIXER,
+ RT5640_M_DAC_R1_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_DAC_MIXER,
+ RT5640_M_DAC_R2_MONO_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_DAC_MIXER,
+ RT5640_M_DAC_L2_MONO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_dig_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_DIG_MIXER,
+ RT5640_M_STO_L_DAC_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_DIG_MIXER,
+ RT5640_M_DAC_L2_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_dig_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_DIG_MIXER,
+ RT5640_M_STO_R_DAC_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_DIG_MIXER,
+ RT5640_M_DAC_R2_DAC_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5640_rec_l_mix[] = {
+ SOC_DAPM_SINGLE("HPOL Switch", RT5640_REC_L2_MIXER,
+ RT5640_M_HP_L_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5640_REC_L2_MIXER,
+ RT5640_M_IN_L_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5640_REC_L2_MIXER,
+ RT5640_M_BST4_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_REC_L2_MIXER,
+ RT5640_M_BST1_RM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUT MIXL Switch", RT5640_REC_L2_MIXER,
+ RT5640_M_OM_L_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_rec_r_mix[] = {
+ SOC_DAPM_SINGLE("HPOR Switch", RT5640_REC_R2_MIXER,
+ RT5640_M_HP_R_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5640_REC_R2_MIXER,
+ RT5640_M_IN_R_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5640_REC_R2_MIXER,
+ RT5640_M_BST4_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_REC_R2_MIXER,
+ RT5640_M_BST1_RM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUT MIXR Switch", RT5640_REC_R2_MIXER,
+ RT5640_M_OM_R_RM_R_SFT, 1, 1),
+};
+
+/* Analog Output Mixer */
+static const struct snd_kcontrol_new rt5640_spk_l_mix[] = {
+ SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_SPK_L_MIXER,
+ RT5640_M_RM_L_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5640_SPK_L_MIXER,
+ RT5640_M_IN_L_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_SPK_L_MIXER,
+ RT5640_M_DAC_L1_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_SPK_L_MIXER,
+ RT5640_M_DAC_L2_SM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUT MIXL Switch", RT5640_SPK_L_MIXER,
+ RT5640_M_OM_L_SM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_spk_r_mix[] = {
+ SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_SPK_R_MIXER,
+ RT5640_M_RM_R_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5640_SPK_R_MIXER,
+ RT5640_M_IN_R_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPK_R_MIXER,
+ RT5640_M_DAC_R1_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_SPK_R_MIXER,
+ RT5640_M_DAC_R2_SM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUT MIXR Switch", RT5640_SPK_R_MIXER,
+ RT5640_M_OM_R_SM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_out_l_mix[] = {
+ SOC_DAPM_SINGLE("SPK MIXL Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_SM_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_BST1_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INL Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_IN_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXL Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_RM_L_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_DAC_R2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_DAC_L2_OM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_OUT_L3_MIXER,
+ RT5640_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_out_r_mix[] = {
+ SOC_DAPM_SINGLE("SPK MIXR Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_SM_L_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST2 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_BST4_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_BST1_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("INR Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_IN_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("REC MIXR Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_RM_R_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_DAC_L2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_DAC_R2_OM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_OUT_R3_MIXER,
+ RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_spo_l_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_L_MIXER,
+ RT5640_M_DAC_R1_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_SPO_L_MIXER,
+ RT5640_M_DAC_L1_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOL R Switch", RT5640_SPO_L_MIXER,
+ RT5640_M_SV_R_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOL L Switch", RT5640_SPO_L_MIXER,
+ RT5640_M_SV_L_SPM_L_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_SPO_L_MIXER,
+ RT5640_M_BST1_SPM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_spo_r_mix[] = {
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_SPO_R_MIXER,
+ RT5640_M_DAC_R1_SPM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOL R Switch", RT5640_SPO_R_MIXER,
+ RT5640_M_SV_R_SPM_R_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_SPO_R_MIXER,
+ RT5640_M_BST1_SPM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_hpo_mix[] = {
+ SOC_DAPM_SINGLE("HPO MIX DAC2 Switch", RT5640_HPO_MIXER,
+ RT5640_M_DAC2_HM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5640_HPO_MIXER,
+ RT5640_M_DAC1_HM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5640_HPO_MIXER,
+ RT5640_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_lout_mix[] = {
+ SOC_DAPM_SINGLE("DAC L1 Switch", RT5640_LOUT_MIXER,
+ RT5640_M_DAC_L1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC R1 Switch", RT5640_LOUT_MIXER,
+ RT5640_M_DAC_R1_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL L Switch", RT5640_LOUT_MIXER,
+ RT5640_M_OV_L_LM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL R Switch", RT5640_LOUT_MIXER,
+ RT5640_M_OV_R_LM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5640_mono_mix[] = {
+ SOC_DAPM_SINGLE("DAC R2 Switch", RT5640_MONO_MIXER,
+ RT5640_M_DAC_R2_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("DAC L2 Switch", RT5640_MONO_MIXER,
+ RT5640_M_DAC_L2_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL R Switch", RT5640_MONO_MIXER,
+ RT5640_M_OV_R_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOL L Switch", RT5640_MONO_MIXER,
+ RT5640_M_OV_L_MM_SFT, 1, 1),
+ SOC_DAPM_SINGLE("BST1 Switch", RT5640_MONO_MIXER,
+ RT5640_M_BST1_MM_SFT, 1, 1),
+};
+
+/* INL/R source */
+static const char * const rt5640_inl_src[] = {
+ "IN2P", "MONOP"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_inl_enum, RT5640_INL_INR_VOL,
+ RT5640_INL_SEL_SFT, rt5640_inl_src);
+
+static const struct snd_kcontrol_new rt5640_inl_mux =
+ SOC_DAPM_ENUM("INL source", rt5640_inl_enum);
+
+static const char * const rt5640_inr_src[] = {
+ "IN2N", "MONON"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_inr_enum, RT5640_INL_INR_VOL,
+ RT5640_INR_SEL_SFT, rt5640_inr_src);
+
+static const struct snd_kcontrol_new rt5640_inr_mux =
+ SOC_DAPM_ENUM("INR source", rt5640_inr_enum);
+
+/* Stereo ADC source */
+static const char * const rt5640_stereo_adc1_src[] = {
+ "DIG MIX", "ADC"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_stereo_adc1_enum, RT5640_STO_ADC_MIXER,
+ RT5640_ADC_1_SRC_SFT, rt5640_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5640_sto_adc_1_mux =
+ SOC_DAPM_ENUM("Stereo ADC1 Mux", rt5640_stereo_adc1_enum);
+
+static const char * const rt5640_stereo_adc2_src[] = {
+ "DMIC1", "DMIC2", "DIG MIX"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_stereo_adc2_enum, RT5640_STO_ADC_MIXER,
+ RT5640_ADC_2_SRC_SFT, rt5640_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5640_sto_adc_2_mux =
+ SOC_DAPM_ENUM("Stereo ADC2 Mux", rt5640_stereo_adc2_enum);
+
+/* Mono ADC source */
+static const char * const rt5640_mono_adc_l1_src[] = {
+ "Mono DAC MIXL", "ADCL"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_mono_adc_l1_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_L1_SRC_SFT, rt5640_mono_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5640_mono_adc_l1_mux =
+ SOC_DAPM_ENUM("Mono ADC1 left source", rt5640_mono_adc_l1_enum);
+
+static const char * const rt5640_mono_adc_l2_src[] = {
+ "DMIC L1", "DMIC L2", "Mono DAC MIXL"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_mono_adc_l2_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_L2_SRC_SFT, rt5640_mono_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5640_mono_adc_l2_mux =
+ SOC_DAPM_ENUM("Mono ADC2 left source", rt5640_mono_adc_l2_enum);
+
+static const char * const rt5640_mono_adc_r1_src[] = {
+ "Mono DAC MIXR", "ADCR"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_mono_adc_r1_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_R1_SRC_SFT, rt5640_mono_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5640_mono_adc_r1_mux =
+ SOC_DAPM_ENUM("Mono ADC1 right source", rt5640_mono_adc_r1_enum);
+
+static const char * const rt5640_mono_adc_r2_src[] = {
+ "DMIC R1", "DMIC R2", "Mono DAC MIXR"
+};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5640_mono_adc_r2_enum, RT5640_MONO_ADC_MIXER,
+ RT5640_MONO_ADC_R2_SRC_SFT, rt5640_mono_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5640_mono_adc_r2_mux =
+ SOC_DAPM_ENUM("Mono ADC2 right source", rt5640_mono_adc_r2_enum);
+
+/* DAC2 channel source */
+static const char * const rt5640_dac_l2_src[] = {
+ "IF2", "Base L/R"
+};
+
+static int rt5640_dac_l2_values[] = {
+ 0,
+ 3,
+};
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5640_dac_l2_enum, RT5640_DSP_PATH2, RT5640_DAC_L2_SEL_SFT,
+ 0x3, rt5640_dac_l2_src, rt5640_dac_l2_values);
+
+static const struct snd_kcontrol_new rt5640_dac_l2_mux =
+ SOC_DAPM_VALUE_ENUM("DAC2 left channel source", rt5640_dac_l2_enum);
+
+static const char * const rt5640_dac_r2_src[] = {
+ "IF2",
+};
+
+static int rt5640_dac_r2_values[] = {
+ 0,
+};
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(
+ rt5640_dac_r2_enum, RT5640_DSP_PATH2, RT5640_DAC_R2_SEL_SFT,
+ 0x3, rt5640_dac_r2_src, rt5640_dac_r2_values);
+
+static const struct snd_kcontrol_new rt5640_dac_r2_mux =
+ SOC_DAPM_ENUM("DAC2 right channel source", rt5640_dac_r2_enum);
+
+/* digital interface and iis interface map *