From edcf139081f501b1468ae6665217e8320d4c75e8 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Date: Wed, 12 Mar 2014 19:44:50 +0100
Subject: [PATCH 01/86] ARM: shmobile: r8a7791: Use rcar_gen2_read_mode_pins()
 helper

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/clock-r8a7791.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
index 701383fe32674..36e57508d8796 100644
--- a/arch/arm/mach-shmobile/clock-r8a7791.c
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -25,6 +25,7 @@
 #include <linux/clkdev.h>
 #include <mach/clock.h>
 #include <mach/common.h>
+#include <mach/rcar-gen2.h>
 
 /*
  *   MD		EXTAL		PLL0	PLL1	PLL3
@@ -43,8 +44,6 @@
  *	see "p1 / 2" on R8A7791_CLOCK_ROOT() below
  */
 
-#define MD(nr)	(1 << nr)
-
 #define CPG_BASE 0xe6150000
 #define CPG_LEN 0x1000
 
@@ -68,7 +67,6 @@
 #define MSTPSR9		IOMEM(0xe61509a4)
 #define MSTPSR11	IOMEM(0xe61509ac)
 
-#define MODEMR		0xE6160060
 #define SDCKCR		0xE6150074
 #define SD1CKCR		0xE6150078
 #define SD2CKCR		0xE615026c
@@ -295,14 +293,9 @@ static struct clk_lookup lookups[] = {
 
 void __init r8a7791_clock_init(void)
 {
-	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
-	u32 mode;
+	u32 mode = rcar_gen2_read_mode_pins();
 	int k, ret = 0;
 
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-
 	switch (mode & (MD(14) | MD(13))) {
 	case 0:
 		R8A7791_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);

From 25f5550f5a4b18fd77a2e719ba63cb34931ab66a Mon Sep 17 00:00:00 2001
From: Magnus Damm <damm@opensource.se>
Date: Thu, 13 Mar 2014 08:36:17 +0900
Subject: [PATCH 02/86] ARM: shmobile: Introduce shmobile_clk_workaround()

Introduce a new clock workaround function used by DT reference
code on the mach-shmobile subarchitecture. The new function
shmobile_clk_workaround() is used to configure clkdev to
allow DT and platform devices to coexist. It is possible for
the DT reference board code to also request enabling of the clock
in case the driver does not implement clock control.

Signed-off-by: Magnus Damm <damm@opensource.se>
[horms+renesas@verge.net.au: Removed trailing blank line]
Reviewed-by: Wolfram Sang <wsa@sang-engineering.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/Makefile             |  2 +-
 arch/arm/mach-shmobile/clock.c              | 28 +++++++++++++++++++++
 arch/arm/mach-shmobile/include/mach/clock.h | 16 ++++++++++++
 3 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 4caffc912a81c..c12a1c50e9d2a 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -21,8 +21,8 @@ obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)	+= setup-r7s72100.o
 
 # Clock objects
-ifndef CONFIG_COMMON_CLK
 obj-y				+= clock.o
+ifndef CONFIG_COMMON_CLK
 obj-$(CONFIG_ARCH_SH7372)	+= clock-sh7372.o
 obj-$(CONFIG_ARCH_SH73A0)	+= clock-sh73a0.o
 obj-$(CONFIG_ARCH_R8A73A4)	+= clock-r8a73a4.o
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
index ad7df629d9954..e7232a0373b9f 100644
--- a/arch/arm/mach-shmobile/clock.c
+++ b/arch/arm/mach-shmobile/clock.c
@@ -21,6 +21,32 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+
+#ifdef CONFIG_COMMON_CLK
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <mach/clock.h>
+
+void __init shmobile_clk_workaround(const struct clk_name *clks,
+				    int nr_clks, bool enable)
+{
+	const struct clk_name *clkn;
+	struct clk *clk;
+	unsigned int i;
+
+	for (i = 0; i < nr_clks; ++i) {
+		clkn = clks + i;
+		clk = clk_get(NULL, clkn->clk);
+		if (!IS_ERR(clk)) {
+			clk_register_clkdev(clk, clkn->con_id, clkn->dev_id);
+			if (enable)
+				clk_prepare_enable(clk);
+			clk_put(clk);
+		}
+	}
+}
+
+#else /* CONFIG_COMMON_CLK */
 #include <linux/sh_clk.h>
 #include <linux/export.h>
 #include <mach/clock.h>
@@ -58,3 +84,5 @@ void __clk_put(struct clk *clk)
 {
 }
 EXPORT_SYMBOL(__clk_put);
+
+#endif /* CONFIG_COMMON_CLK */
diff --git a/arch/arm/mach-shmobile/include/mach/clock.h b/arch/arm/mach-shmobile/include/mach/clock.h
index 03e56074928c2..9a93cf924b9cf 100644
--- a/arch/arm/mach-shmobile/include/mach/clock.h
+++ b/arch/arm/mach-shmobile/include/mach/clock.h
@@ -1,6 +1,21 @@
 #ifndef CLOCK_H
 #define CLOCK_H
 
+#ifdef CONFIG_COMMON_CLK
+/* temporary clock configuration helper for platform devices */
+
+struct clk_name {
+	const char *clk;
+	const char *con_id;
+	const char *dev_id;
+};
+
+void shmobile_clk_workaround(const struct clk_name *clks, int nr_clks,
+			     bool enable);
+
+#else /* CONFIG_COMMON_CLK */
+/* legacy clock implementation */
+
 unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk);
 extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops;
 
@@ -36,4 +51,5 @@ do {			\
 	(p)->div = d;	\
 } while (0)
 
+#endif /* CONFIG_COMMON_CLK */
 #endif

From ab077bfdc4eaffa5328a9843d4d7970718ac0b8a Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Tue, 1 Apr 2014 13:02:15 +0200
Subject: [PATCH 03/86] ARM: shmobile: r8a7790: Fix the I2C clocks parents in
 legacy code

All I2C clocks derive from the HP clock, not from the P clock. Fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: Wolfram Sang <wsa@sang-engineering.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/clock-r8a7790.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index 3f93503f5b96f..331013995fe37 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -249,10 +249,10 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP1007] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 7, MSTPSR10, 0), /* SSI8 */
 	[MSTP1006] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 6, MSTPSR10, 0), /* SSI9 */
 	[MSTP1005] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 5, MSTPSR10, 0), /* SSI ALL */
-	[MSTP931] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
-	[MSTP930] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
-	[MSTP929] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
-	[MSTP928] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
+	[MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
+	[MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
+	[MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
+	[MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
 	[MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */
 	[MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */
 	[MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */

From 2b1b6e6865aeb236f759ad3f91db27b514e29023 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Tue, 1 Apr 2014 13:02:16 +0200
Subject: [PATCH 04/86] ARM: shmobile: r8a7791: Fix the I2C clocks parents in
 legacy code

All I2C clocks derive from the HP clock, not from the P clock. Fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: Wolfram Sang <wsa@sang-engineering.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/clock-r8a7791.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
index 36e57508d8796..3b26c7eee873f 100644
--- a/arch/arm/mach-shmobile/clock-r8a7791.c
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -188,12 +188,12 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP1108] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 8, MSTPSR11, 0), /* SCIFA5 */
 	[MSTP1107] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 7, MSTPSR11, 0), /* SCIFA4 */
 	[MSTP1106] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 6, MSTPSR11, 0), /* SCIFA3 */
-	[MSTP931] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
-	[MSTP930] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
-	[MSTP929] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
-	[MSTP928] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
-	[MSTP927] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 27, MSTPSR9, 0), /* I2C4 */
-	[MSTP925] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR9, 25, MSTPSR9, 0), /* I2C5 */
+	[MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
+	[MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
+	[MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
+	[MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
+	[MSTP927] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 27, MSTPSR9, 0), /* I2C4 */
+	[MSTP925] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 25, MSTPSR9, 0), /* I2C5 */
 	[MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */
 	[MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */
 	[MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */

From 79ea9934b8df700fa306c8ced2d3bbf94ff276a8 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Wed, 2 Apr 2014 16:31:46 +0200
Subject: [PATCH 05/86] ARM: shmobile: r8a7790: Rename VSP1_(SY|RT) clocks to
 VSP1_(S|R)

The r8a7790 has four VSP1 instances, two of them being named VSPS (which
stands for "VSP Standard") and VSPR (which stands for "VSP for
Resizing"). The clock section in the SoC datasheet misunderstood the
abbreviations as meaning VSP System and VSP Realtime, and named the
corresponding clocks VSP1(SY) and VSP1(RT). This mistake has been
carried over to the kernel code.

Fix this by renaming the VSP1_SY and VSP1_RT clocks to VSP1_S and VSP1_R.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/boot/dts/r8a7790.dtsi            | 2 +-
 include/dt-bindings/clock/r8a7790-clock.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 618e5b537eaf9..10b326bdf831a 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -673,7 +673,7 @@
 			renesas,clock-indices = <
 				R8A7790_CLK_TMU1 R8A7790_CLK_TMU3 R8A7790_CLK_TMU2
 				R8A7790_CLK_CMT0 R8A7790_CLK_TMU0 R8A7790_CLK_VSP1_DU1
-				R8A7790_CLK_VSP1_DU0 R8A7790_CLK_VSP1_RT R8A7790_CLK_VSP1_SY
+				R8A7790_CLK_VSP1_DU0 R8A7790_CLK_VSP1_R R8A7790_CLK_VSP1_S
 			>;
 			clock-output-names =
 				"tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1",
diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h
index 6548a5fbcf4a4..9a7c4c5a35d1c 100644
--- a/include/dt-bindings/clock/r8a7790-clock.h
+++ b/include/dt-bindings/clock/r8a7790-clock.h
@@ -33,8 +33,8 @@
 #define R8A7790_CLK_TMU0		25
 #define R8A7790_CLK_VSP1_DU1		27
 #define R8A7790_CLK_VSP1_DU0		28
-#define R8A7790_CLK_VSP1_RT		30
-#define R8A7790_CLK_VSP1_SY		31
+#define R8A7790_CLK_VSP1_R		30
+#define R8A7790_CLK_VSP1_S		31
 
 /* MSTP2 */
 #define R8A7790_CLK_SCIFA2		2

From 58ea1d53ba93620ac50fef9d9720b2323971f243 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Wed, 2 Apr 2014 16:31:47 +0200
Subject: [PATCH 06/86] ARM: shmobile: r8a7791: Rename VSP1_SY clocks to VSP1_S

The r8a7791 has three VSP1 instances, one of them being named VSPS (which
stands for "VSP Standard"). The clock section in the SoC datasheet
misunderstood the abbreviation as meaning VSP System, and named the
corresponding clock VSP1(SY). This mistake has been carried over to the
kernel code.

Fix this by renaming the VSP1_SY clock to VSP1_S.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/boot/dts/r8a7791.dtsi            | 2 +-
 include/dt-bindings/clock/r8a7791-clock.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 46181708e59c5..aa1cba94196c1 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -688,7 +688,7 @@
 			renesas,clock-indices = <
 				R8A7791_CLK_TMU1 R8A7791_CLK_TMU3 R8A7791_CLK_TMU2
 				R8A7791_CLK_CMT0 R8A7791_CLK_TMU0 R8A7791_CLK_VSP1_DU1
-				R8A7791_CLK_VSP1_DU0 R8A7791_CLK_VSP1_SY
+				R8A7791_CLK_VSP1_DU0 R8A7791_CLK_VSP1_S
 			>;
 			clock-output-names =
 				"tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1",
diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h
index 30f82f286e295..f069bc6627cb3 100644
--- a/include/dt-bindings/clock/r8a7791-clock.h
+++ b/include/dt-bindings/clock/r8a7791-clock.h
@@ -32,7 +32,7 @@
 #define R8A7791_CLK_TMU0		25
 #define R8A7791_CLK_VSP1_DU1		27
 #define R8A7791_CLK_VSP1_DU0		28
-#define R8A7791_CLK_VSP1_SY		31
+#define R8A7791_CLK_VSP1_S		31
 
 /* MSTP2 */
 #define R8A7791_CLK_SCIFA2		2

From e6597e0e19bbabfdd1983dbe79892d8ba210a180 Mon Sep 17 00:00:00 2001
From: Magnus Damm <damm@opensource.se>
Date: Thu, 13 Mar 2014 08:36:26 +0900
Subject: [PATCH 07/86] ARM: shmobile: Use shmobile_clk_workaround() on Lager

Convert the Lager DT reference code to use the newly introduced
function shmobile_clk_workaround().

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 .../arm/mach-shmobile/board-lager-reference.c | 65 +++++++------------
 1 file changed, 25 insertions(+), 40 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 440aac36d6938..c76248b9a5e75 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -18,12 +18,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/rcar-du.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/rcar-gen2.h>
@@ -86,46 +85,32 @@ static void __init lager_add_du_device(void)
 	platform_device_register_full(&info);
 }
 
+/*
+ * This is a really crude hack to provide clkdev support to platform
+ * devices until they get moved to DT.
+ */
+static const struct clk_name clk_names[] = {
+	{ "cmt0", NULL, "sh_cmt.0" },
+	{ "scifa0", NULL, "sh-sci.0" },
+	{ "scifa1", NULL, "sh-sci.1" },
+	{ "scifb0", NULL, "sh-sci.2" },
+	{ "scifb1", NULL, "sh-sci.3" },
+	{ "scifb2", NULL, "sh-sci.4" },
+	{ "scifa2", NULL, "sh-sci.5" },
+	{ "scif0", NULL, "sh-sci.6" },
+	{ "scif1", NULL, "sh-sci.7" },
+	{ "hscif0", NULL, "sh-sci.8" },
+	{ "hscif1", NULL, "sh-sci.9" },
+	{ "du0", "du.0", "rcar-du-r8a7790" },
+	{ "du1", "du.1", "rcar-du-r8a7790" },
+	{ "du2", "du.2", "rcar-du-r8a7790" },
+	{ "lvds0", "lvds.0", "rcar-du-r8a7790" },
+	{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
+};
+
 static void __init lager_add_standard_devices(void)
 {
-	/*
-	 * This is a really crude hack to provide clkdev support to platform
-	 * devices until they get moved to DT.
-	 */
-	static const struct clk_name {
-		const char *clk;
-		const char *con_id;
-		const char *dev_id;
-	} clk_names[] = {
-		{ "cmt0", NULL, "sh_cmt.0" },
-		{ "scifa0", NULL, "sh-sci.0" },
-		{ "scifa1", NULL, "sh-sci.1" },
-		{ "scifb0", NULL, "sh-sci.2" },
-		{ "scifb1", NULL, "sh-sci.3" },
-		{ "scifb2", NULL, "sh-sci.4" },
-		{ "scifa2", NULL, "sh-sci.5" },
-		{ "scif0", NULL, "sh-sci.6" },
-		{ "scif1", NULL, "sh-sci.7" },
-		{ "hscif0", NULL, "sh-sci.8" },
-		{ "hscif1", NULL, "sh-sci.9" },
-		{ "du0", "du.0", "rcar-du-r8a7790" },
-		{ "du1", "du.1", "rcar-du-r8a7790" },
-		{ "du2", "du.2", "rcar-du-r8a7790" },
-		{ "lvds0", "lvds.0", "rcar-du-r8a7790" },
-		{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
-	};
-	struct clk *clk;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(clk_names); ++i) {
-		clk = clk_get(NULL, clk_names[i].clk);
-		if (!IS_ERR(clk)) {
-			clk_register_clkdev(clk, clk_names[i].con_id,
-					    clk_names[i].dev_id);
-			clk_put(clk);
-		}
-	}
-
+	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
 	r8a7790_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 

From 89aff406dbc3ea3dfc008e8472181532c0c0f4ea Mon Sep 17 00:00:00 2001
From: Magnus Damm <damm@opensource.se>
Date: Thu, 13 Mar 2014 08:36:35 +0900
Subject: [PATCH 08/86] ARM: shmobile: Use shmobile_clk_workaround() on Koelsch

Convert the Koelsch DT reference code to use the newly introduced
function shmobile_clk_workaround().

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 .../mach-shmobile/board-koelsch-reference.c   | 71 ++++++++-----------
 1 file changed, 28 insertions(+), 43 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index a3fd30242bd87..a760f7f19bc99 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -19,12 +19,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/clk.h>
-#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/platform_data/rcar-du.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/rcar-gen2.h>
@@ -82,49 +81,35 @@ static void __init koelsch_add_du_device(void)
 	platform_device_register_full(&info);
 }
 
+/*
+ * This is a really crude hack to provide clkdev support to platform
+ * devices until they get moved to DT.
+ */
+static const struct clk_name clk_names[] = {
+	{ "cmt0", NULL, "sh_cmt.0" },
+	{ "scifa0", NULL, "sh-sci.0" },
+	{ "scifa1", NULL, "sh-sci.1" },
+	{ "scifb0", NULL, "sh-sci.2" },
+	{ "scifb1", NULL, "sh-sci.3" },
+	{ "scifb2", NULL, "sh-sci.4" },
+	{ "scifa2", NULL, "sh-sci.5" },
+	{ "scif0", NULL, "sh-sci.6" },
+	{ "scif1", NULL, "sh-sci.7" },
+	{ "scif2", NULL, "sh-sci.8" },
+	{ "scif3", NULL, "sh-sci.9" },
+	{ "scif4", NULL, "sh-sci.10" },
+	{ "scif5", NULL, "sh-sci.11" },
+	{ "scifa3", NULL, "sh-sci.12" },
+	{ "scifa4", NULL, "sh-sci.13" },
+	{ "scifa5", NULL, "sh-sci.14" },
+	{ "du0", "du.0", "rcar-du-r8a7791" },
+	{ "du1", "du.1", "rcar-du-r8a7791" },
+	{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
+};
+
 static void __init koelsch_add_standard_devices(void)
 {
-	/*
-	 * This is a really crude hack to provide clkdev support to the CMT and
-	 * DU devices until they get moved to DT.
-	 */
-	static const struct clk_name {
-		const char *clk;
-		const char *con_id;
-		const char *dev_id;
-	} clk_names[] = {
-		{ "cmt0", NULL, "sh_cmt.0" },
-		{ "scifa0", NULL, "sh-sci.0" },
-		{ "scifa1", NULL, "sh-sci.1" },
-		{ "scifb0", NULL, "sh-sci.2" },
-		{ "scifb1", NULL, "sh-sci.3" },
-		{ "scifb2", NULL, "sh-sci.4" },
-		{ "scifa2", NULL, "sh-sci.5" },
-		{ "scif0", NULL, "sh-sci.6" },
-		{ "scif1", NULL, "sh-sci.7" },
-		{ "scif2", NULL, "sh-sci.8" },
-		{ "scif3", NULL, "sh-sci.9" },
-		{ "scif4", NULL, "sh-sci.10" },
-		{ "scif5", NULL, "sh-sci.11" },
-		{ "scifa3", NULL, "sh-sci.12" },
-		{ "scifa4", NULL, "sh-sci.13" },
-		{ "scifa5", NULL, "sh-sci.14" },
-		{ "du0", "du.0", "rcar-du-r8a7791" },
-		{ "du1", "du.1", "rcar-du-r8a7791" },
-		{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
-	};
-	struct clk *clk;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(clk_names); ++i) {
-		clk = clk_get(NULL, clk_names[i].clk);
-		if (!IS_ERR(clk)) {
-			clk_register_clkdev(clk, clk_names[i].con_id,
-					    clk_names[i].dev_id);
-			clk_put(clk);
-		}
-	}
-
+	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
 	r8a7791_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 

From f6f98b3e44ea408e33eb4d695a4225cc11210cdb Mon Sep 17 00:00:00 2001
From: Simon Horman <horms+renesas@verge.net.au>
Date: Thu, 13 Mar 2014 15:29:57 +0900
Subject: [PATCH 09/86] ARM: shmobile: koelsch: Annotate clk_names with
 __initconst

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 arch/arm/mach-shmobile/board-koelsch-reference.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index a760f7f19bc99..1e6a4361c0eb4 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -85,7 +85,7 @@ static void __init koelsch_add_du_device(void)
  * This is a really crude hack to provide clkdev support to platform
  * devices until they get moved to DT.
  */
-static const struct clk_name clk_names[] = {
+static const struct clk_name clk_names[] __initconst = {
 	{ "cmt0", NULL, "sh_cmt.0" },
 	{ "scifa0", NULL, "sh-sci.0" },
 	{ "scifa1", NULL, "sh-sci.1" },

From f71c77286b2c1f809a85e8e42df88eb2ec132e5f Mon Sep 17 00:00:00 2001
From: Simon Horman <horms+renesas@verge.net.au>
Date: Thu, 13 Mar 2014 15:29:58 +0900
Subject: [PATCH 10/86] ARM: shmobile: lager: Annotate clk_names with
 __initconst

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 arch/arm/mach-shmobile/board-lager-reference.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index c76248b9a5e75..7ff395efa9fe3 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -89,7 +89,7 @@ static void __init lager_add_du_device(void)
  * This is a really crude hack to provide clkdev support to platform
  * devices until they get moved to DT.
  */
-static const struct clk_name clk_names[] = {
+static const struct clk_name clk_names[] __initconst = {
 	{ "cmt0", NULL, "sh_cmt.0" },
 	{ "scifa0", NULL, "sh-sci.0" },
 	{ "scifa1", NULL, "sh-sci.1" },

From 53cf0cf7ba2ef785b339826a0765bb6b1756adeb Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Date: Thu, 13 Mar 2014 15:29:30 +0100
Subject: [PATCH 11/86] ARM: shmobile: koelsch-reference: Work around core
 clock issues

Due to issues with runtime PM clock management, clocks not explicitly
managed by their drivers may not be enabled at all, or be inadvertently
disabled by the clk_disable_unused() late initcall.

Until this is fixed, add a temporary workaround, calling
shmobile_clk_workaround() with enable == true.

For now this enables the clocks for: ether, i2c2, msiof0, qspi_mod, and
thermal. More clocks can be added if needed.

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-koelsch-reference.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index 1e6a4361c0eb4..a39114a1fe1b2 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -107,9 +107,21 @@ static const struct clk_name clk_names[] __initconst = {
 	{ "lvds0", "lvds.0", "rcar-du-r8a7791" },
 };
 
+/*
+ * This is a really crude hack to work around core platform clock issues
+ */
+static const struct clk_name clk_enables[] = {
+	{ "ether", NULL, "ee700000.ethernet" },
+	{ "i2c2", NULL, "e6530000.i2c" },
+	{ "msiof0", NULL, "e6e20000.spi" },
+	{ "qspi_mod", NULL, "e6b10000.spi" },
+	{ "thermal", NULL, "e61f0000.thermal" },
+};
+
 static void __init koelsch_add_standard_devices(void)
 {
 	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
+	shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
 	r8a7791_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 

From 9e7b83c221cc257f4dc37acc82bbcb80627c0ab9 Mon Sep 17 00:00:00 2001
From: Simon Horman <horms+renesas@verge.net.au>
Date: Mon, 17 Mar 2014 11:19:56 +0900
Subject: [PATCH 12/86] ARM: shmobile: koelsch-reference: Annotate clk_enables
 as __initconst

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 arch/arm/mach-shmobile/board-koelsch-reference.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index a39114a1fe1b2..63117d52db9ee 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -110,7 +110,7 @@ static const struct clk_name clk_names[] __initconst = {
 /*
  * This is a really crude hack to work around core platform clock issues
  */
-static const struct clk_name clk_enables[] = {
+static const struct clk_name clk_enables[] __initconst = {
 	{ "ether", NULL, "ee700000.ethernet" },
 	{ "i2c2", NULL, "e6530000.i2c" },
 	{ "msiof0", NULL, "e6e20000.spi" },

From aa5de826afe747c353162bbc116c63ab5335f91c Mon Sep 17 00:00:00 2001
From: Simon Horman <horms+renesas@verge.net.au>
Date: Mon, 17 Mar 2014 11:18:56 +0900
Subject: [PATCH 13/86] ARM: shmobile: lager-reference: Work around core clock
 issues

Due to issues with runtime PM clock management, clocks not explicitly
managed by their drivers may not be enabled at all, or be inadvertently
disabled by the clk_disable_unused() late initcall.

Until this is fixed, add a temporary workaround, calling
shmobile_clk_workaround() with enable == true.

For now this enables the clocks for: ether, msiof1, qspi_mod, and
thermal. More clocks can be added if needed.

Based on work for the koelsch board by Geert Uytterhoeven.

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
---
 arch/arm/mach-shmobile/board-lager-reference.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 7ff395efa9fe3..313118c5f3651 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -108,9 +108,20 @@ static const struct clk_name clk_names[] __initconst = {
 	{ "lvds1", "lvds.1", "rcar-du-r8a7790" },
 };
 
+/*
+ * This is a really crude hack to work around core platform clock issues
+ */
+static const struct clk_name clk_enables[] __initconst = {
+	{ "ether", NULL, "ee700000.ethernet" },
+	{ "msiof1", NULL, "e6e10000.spi" },
+	{ "qspi_mod", NULL, "e6b10000.spi" },
+	{ "thermal", NULL, "e61f0000.thermal" },
+};
+
 static void __init lager_add_standard_devices(void)
 {
 	shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
+	shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
 	r8a7790_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 

From f98b55d730492e664fb2649bd7054fec0fe81acd Mon Sep 17 00:00:00 2001
From: Magnus Damm <damm@opensource.se>
Date: Tue, 18 Mar 2014 21:52:47 +0900
Subject: [PATCH 14/86] ARM: shmobile: Add Lager clock workarounds for SDHI and
 MMCIF

Add MMCIF1, SDHI0 and SDHI2 to the clock workaround list for
Lager multiplatform. Without these additional lines wakeup
from Suspend-to-RAM never happens.

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-lager-reference.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 313118c5f3651..1eb48cffb4c58 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -114,7 +114,10 @@ static const struct clk_name clk_names[] __initconst = {
 static const struct clk_name clk_enables[] __initconst = {
 	{ "ether", NULL, "ee700000.ethernet" },
 	{ "msiof1", NULL, "e6e10000.spi" },
+	{ "mmcif1", NULL, "ee220000.mmc" },
 	{ "qspi_mod", NULL, "e6b10000.spi" },
+	{ "sdhi0", NULL, "ee100000.sd" },
+	{ "sdhi2", NULL, "ee140000.sd" },
 	{ "thermal", NULL, "e61f0000.thermal" },
 };
 

From f278ea78beeb17ea07d11fc3372d4f98c94dcf46 Mon Sep 17 00:00:00 2001
From: Magnus Damm <damm@opensource.se>
Date: Tue, 18 Mar 2014 21:54:34 +0900
Subject: [PATCH 15/86] ARM: shmobile: Add Koelsch clock workarounds for SDHI

Add SDHI0, SDHI1 and SDHI2 to the clock workaround list for
Koelsch multiplatform. Without these additional lines wakeup
from Suspend-to-RAM never happens.

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-koelsch-reference.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index 63117d52db9ee..941f8b394e84c 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -115,6 +115,9 @@ static const struct clk_name clk_enables[] __initconst = {
 	{ "i2c2", NULL, "e6530000.i2c" },
 	{ "msiof0", NULL, "e6e20000.spi" },
 	{ "qspi_mod", NULL, "e6b10000.spi" },
+	{ "sdhi0", NULL, "ee100000.sd" },
+	{ "sdhi1", NULL, "ee140000.sd" },
+	{ "sdhi2", NULL, "ee160000.sd" },
 	{ "thermal", NULL, "e61f0000.thermal" },
 };
 

From a9d83bd6abc00e14e2db1660e2c7d889745bb3aa Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Sun, 13 Apr 2014 17:56:42 -0700
Subject: [PATCH 16/86] ARM: shmobile: r8a7778: remove old style audio clock

Current sound driver moves to new style clock,
but is keeping compatiblity at this point.
Move to new style on r8a7778

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/clock-r8a7778.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index 2009a9bc63562..201fc487e4e17 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -175,10 +175,6 @@ static struct clk mstp_clks[MSTP_NR] = {
 
 static struct clk_lookup lookups[] = {
 	/* main */
-	CLKDEV_CON_ID("audio_clk_a",	&audio_clk_a),
-	CLKDEV_CON_ID("audio_clk_b",	&audio_clk_b),
-	CLKDEV_CON_ID("audio_clk_c",	&audio_clk_c),
-	CLKDEV_CON_ID("audio_clk_internal",	&s1_clk),
 	CLKDEV_CON_ID("shyway_clk",	&s_clk),
 	CLKDEV_CON_ID("peripheral_clk",	&p_clk),
 
@@ -234,15 +230,15 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
 	CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
 	CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
-	CLKDEV_ICK_ID("scu.0", "rcar_sound", &mstp_clks[MSTP531]),
-	CLKDEV_ICK_ID("scu.1", "rcar_sound", &mstp_clks[MSTP530]),
-	CLKDEV_ICK_ID("scu.2", "rcar_sound", &mstp_clks[MSTP529]),
-	CLKDEV_ICK_ID("scu.3", "rcar_sound", &mstp_clks[MSTP528]),
-	CLKDEV_ICK_ID("scu.4", "rcar_sound", &mstp_clks[MSTP527]),
-	CLKDEV_ICK_ID("scu.5", "rcar_sound", &mstp_clks[MSTP526]),
-	CLKDEV_ICK_ID("scu.6", "rcar_sound", &mstp_clks[MSTP525]),
-	CLKDEV_ICK_ID("scu.7", "rcar_sound", &mstp_clks[MSTP524]),
-	CLKDEV_ICK_ID("scu.8", "rcar_sound", &mstp_clks[MSTP523]),
+	CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP531]),
+	CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP530]),
+	CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP529]),
+	CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP528]),
+	CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP527]),
+	CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP526]),
+	CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP525]),
+	CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]),
+	CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]),
 };
 
 void __init r8a7778_clock_init(void)

From 932616eed0308cbebbb20a079e4bed3674bf1117 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Sun, 13 Apr 2014 17:56:50 -0700
Subject: [PATCH 17/86] ARM: shmobile: r8a7790: remove old style audio clock

Current sound driver moves to new style clock,
but is keeping compatiblity at this point.
Move to new style on r8a7790

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/clock-r8a7790.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index 331013995fe37..a936ae7de0838 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -294,10 +294,6 @@ static struct clk mstp_clks[MSTP_NR] = {
 static struct clk_lookup lookups[] = {
 
 	/* main clocks */
-	CLKDEV_CON_ID("audio_clk_a",	&audio_clk_a),
-	CLKDEV_CON_ID("audio_clk_b",	&audio_clk_b),
-	CLKDEV_CON_ID("audio_clk_c",	&audio_clk_c),
-	CLKDEV_CON_ID("audio_clk_internal",	&m2_clk),
 	CLKDEV_CON_ID("extal",		&extal_clk),
 	CLKDEV_CON_ID("extal_div2",	&extal_div2_clk),
 	CLKDEV_CON_ID("main",		&main_clk),
@@ -381,16 +377,16 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b),
 	CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c),
 	CLKDEV_ICK_ID("clk_i", "rcar_sound", &m2_clk),
-	CLKDEV_ICK_ID("scu.0", "rcar_sound", &mstp_clks[MSTP1031]),
-	CLKDEV_ICK_ID("scu.1", "rcar_sound", &mstp_clks[MSTP1030]),
-	CLKDEV_ICK_ID("scu.2", "rcar_sound", &mstp_clks[MSTP1029]),
-	CLKDEV_ICK_ID("scu.3", "rcar_sound", &mstp_clks[MSTP1028]),
-	CLKDEV_ICK_ID("scu.4", "rcar_sound", &mstp_clks[MSTP1027]),
-	CLKDEV_ICK_ID("scu.5", "rcar_sound", &mstp_clks[MSTP1026]),
-	CLKDEV_ICK_ID("scu.6", "rcar_sound", &mstp_clks[MSTP1025]),
-	CLKDEV_ICK_ID("scu.7", "rcar_sound", &mstp_clks[MSTP1024]),
-	CLKDEV_ICK_ID("scu.8", "rcar_sound", &mstp_clks[MSTP1023]),
-	CLKDEV_ICK_ID("scu.9", "rcar_sound", &mstp_clks[MSTP1022]),
+	CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP1031]),
+	CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP1030]),
+	CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP1029]),
+	CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP1028]),
+	CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP1027]),
+	CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP1026]),
+	CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP1025]),
+	CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP1024]),
+	CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP1023]),
+	CLKDEV_ICK_ID("src.9", "rcar_sound", &mstp_clks[MSTP1022]),
 	CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]),
 	CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]),
 	CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]),

From 115897dab004f580fc8b4c6bab057940ccb64989 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Sun, 13 Apr 2014 17:56:57 -0700
Subject: [PATCH 18/86] ARM: shmobile: bockw: remove old style audio clock

Current audio clock didn't have dependency to device/driver,
but, it was not good design for DT support.
To avoid branch merge conflict issue,
it is using this load map, and this patch is 3) part.
 1) add new style clock in platform
 2) add new style clock method in driver
 3) remove old tyle clock from platform

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-bockw.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index b4122f8cb8d9f..1aca107f959fe 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -591,6 +591,7 @@ static void __init bockw_init(void)
 {
 	void __iomem *base;
 	struct clk *clk;
+	struct platform_device *pdev;
 	int i;
 
 	r8a7778_clock_init();
@@ -673,9 +674,6 @@ static void __init bockw_init(void)
 	}
 
 	/* for Audio */
-	clk = clk_get(NULL, "audio_clk_b");
-	clk_set_rate(clk, 24576000);
-	clk_put(clk);
 	rsnd_codec_power(5, 1); /* enable ak4642 */
 
 	platform_device_register_simple(
@@ -684,11 +682,15 @@ static void __init bockw_init(void)
 	platform_device_register_simple(
 		"ak4554-adc-dac", 1, NULL, 0);
 
-	platform_device_register_resndata(
+	pdev = platform_device_register_resndata(
 		&platform_bus, "rcar_sound", -1,
 		rsnd_resources, ARRAY_SIZE(rsnd_resources),
 		&rsnd_info, sizeof(rsnd_info));
 
+	clk = clk_get(&pdev->dev, "clk_b");
+	clk_set_rate(clk, 24576000);
+	clk_put(clk);
+
 	for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
 		struct platform_device_info cardinfo = {
 			.parent         = &platform_bus,

From a3f50d1bdd47dfa07cb42f7d954739389664f166 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Sun, 13 Apr 2014 17:57:05 -0700
Subject: [PATCH 19/86] ARM: shmobile: bockw: switch to use dai info for R-Car
 sound

Now, R-Car sound driver supports dai info settings.
switch to use it

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-bockw.c | 53 ++++++++++++++++++----------
 1 file changed, 35 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index 1aca107f959fe..f444be2f241ed 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -345,24 +345,39 @@ static struct rsnd_ssi_platform_info rsnd_ssi[] = {
 	RSND_SSI_UNUSED, /* SSI 0 */
 	RSND_SSI_UNUSED, /* SSI 1 */
 	RSND_SSI_UNUSED, /* SSI 2 */
-	RSND_SSI_SET(1, HPBDMA_SLAVE_HPBIF3_TX, gic_iid(0x85), RSND_SSI_PLAY),
-	RSND_SSI_SET(2, HPBDMA_SLAVE_HPBIF4_RX, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
-	RSND_SSI_SET(0, HPBDMA_SLAVE_HPBIF5_TX, gic_iid(0x86), RSND_SSI_PLAY),
-	RSND_SSI_SET(0, HPBDMA_SLAVE_HPBIF6_RX, gic_iid(0x86), 0),
-	RSND_SSI_SET(3, HPBDMA_SLAVE_HPBIF7_TX, gic_iid(0x86), RSND_SSI_PLAY),
-	RSND_SSI_SET(4, HPBDMA_SLAVE_HPBIF8_RX, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF3_TX, gic_iid(0x85), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF4_RX, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF5_TX, gic_iid(0x86), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF6_RX, gic_iid(0x86), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF7_TX, gic_iid(0x86), 0),
+	RSND_SSI(HPBDMA_SLAVE_HPBIF8_RX, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
 };
 
-static struct rsnd_scu_platform_info rsnd_scu[9] = {
-	{ .flags = 0, }, /* SRU 0 */
-	{ .flags = 0, }, /* SRU 1 */
-	{ .flags = 0, }, /* SRU 2 */
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
-	{ .flags = RSND_SCU_USE_HPBIF, },
+static struct rsnd_src_platform_info rsnd_src[9] = {
+	RSND_SRC_UNUSED, /* SRU 0 */
+	RSND_SRC_UNUSED, /* SRU 1 */
+	RSND_SRC_UNUSED, /* SRU 2 */
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+	RSND_SRC(0, 0),
+};
+
+static struct rsnd_dai_platform_info rsnd_dai[] = {
+	{
+		.playback = { .ssi = &rsnd_ssi[5], .src = &rsnd_src[5] },
+		.capture  = { .ssi = &rsnd_ssi[6], .src = &rsnd_src[6] },
+	}, {
+		.playback = { .ssi = &rsnd_ssi[3], .src = &rsnd_src[3] },
+	}, {
+		.capture  = { .ssi = &rsnd_ssi[4], .src = &rsnd_src[4] },
+	}, {
+		.playback = { .ssi = &rsnd_ssi[7], .src = &rsnd_src[7] },
+	}, {
+		.capture  = { .ssi = &rsnd_ssi[8], .src = &rsnd_src[8] },
+	},
 };
 
 enum {
@@ -437,8 +452,10 @@ static struct rcar_snd_info rsnd_info = {
 	.flags		= RSND_GEN1,
 	.ssi_info	= rsnd_ssi,
 	.ssi_info_nr	= ARRAY_SIZE(rsnd_ssi),
-	.scu_info	= rsnd_scu,
-	.scu_info_nr	= ARRAY_SIZE(rsnd_scu),
+	.src_info	= rsnd_src,
+	.src_info_nr	= ARRAY_SIZE(rsnd_src),
+	.dai_info	= rsnd_dai,
+	.dai_info_nr	= ARRAY_SIZE(rsnd_dai),
 	.start		= rsnd_start,
 	.stop		= rsnd_stop,
 };

From 50f359d7389be354b46d781f3b234d3008d20f2f Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Sun, 13 Apr 2014 17:57:12 -0700
Subject: [PATCH 20/86] ARM: shmobile: lager: switch to use dai info for R-Car
 sound

Now, R-Car sound driver supports dai info settings.
switch to use it

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-lager.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index f0104bfe544e3..6af09e1e0841d 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -567,20 +567,27 @@ static struct resource rsnd_resources[] __initdata = {
 };
 
 static struct rsnd_ssi_platform_info rsnd_ssi[] = {
-	RSND_SSI_SET(0, 0, gic_spi(370), RSND_SSI_PLAY),
-	RSND_SSI_SET(0, 0, gic_spi(371), RSND_SSI_CLK_PIN_SHARE),
+	RSND_SSI(0, gic_spi(370), 0),
+	RSND_SSI(0, gic_spi(371), RSND_SSI_CLK_PIN_SHARE),
 };
 
-static struct rsnd_scu_platform_info rsnd_scu[2] = {
+static struct rsnd_src_platform_info rsnd_src[2] = {
 	/* no member at this point */
 };
 
+static struct rsnd_dai_platform_info rsnd_dai = {
+	.playback = { .ssi = &rsnd_ssi[0], },
+	.capture  = { .ssi = &rsnd_ssi[1], },
+};
+
 static struct rcar_snd_info rsnd_info = {
 	.flags		= RSND_GEN2,
 	.ssi_info	= rsnd_ssi,
 	.ssi_info_nr	= ARRAY_SIZE(rsnd_ssi),
-	.scu_info	= rsnd_scu,
-	.scu_info_nr	= ARRAY_SIZE(rsnd_scu),
+	.src_info	= rsnd_src,
+	.src_info_nr	= ARRAY_SIZE(rsnd_src),
+	.dai_info	= &rsnd_dai,
+	.dai_info_nr	= 1,
 };
 
 static struct asoc_simple_card_info rsnd_card_info = {

From 4c9185be5e8eefd10b0f172e794b108697d86985 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 27 Mar 2014 15:55:47 +0800
Subject: [PATCH 21/86] ASoC: rt5640: Move cache sync() to resume()

The patch fixes the defect in case of resume which doesn't sync the cache.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 68b4dd622b879..4a7bd0a16912d 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1890,11 +1890,9 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
-	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
 	switch (level) {
 	case SND_SOC_BIAS_STANDBY:
 		if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
-			regcache_cache_only(rt5640->regmap, false);
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_VREF1 | RT5640_PWR_MB |
 				RT5640_PWR_BG | RT5640_PWR_VREF2,
@@ -1904,7 +1902,6 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
 			snd_soc_update_bits(codec, RT5640_PWR_ANLG1,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2,
 				RT5640_PWR_FV1 | RT5640_PWR_FV2);
-			regcache_sync(rt5640->regmap);
 			snd_soc_update_bits(codec, RT5640_DUMMY1,
 						0x0301, 0x0301);
 			snd_soc_update_bits(codec, RT5640_MICBIAS,
@@ -1979,6 +1976,9 @@ static int rt5640_resume(struct snd_soc_codec *codec)
 		msleep(400);
 	}
 
+	regcache_cache_only(rt5640->regmap, false);
+	regcache_sync(rt5640->regmap);
+
 	return 0;
 }
 #else

From 9bccae733b8d0e281729464267191103c09b3d13 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 27 Mar 2014 19:34:51 +0800
Subject: [PATCH 22/86] ASoC: rt5640: Correct the judgement of data length

The patch corrects the judgement of data length.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 4a7bd0a16912d..f0717db3e9353 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1622,16 +1622,16 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
 	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
 				bclk_ms, pre_div, dai->id);
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
+	case 20:
 		val_len |= RT5640_I2S_DL_20;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		val_len |= RT5640_I2S_DL_24;
 		break;
-	case SNDRV_PCM_FORMAT_S8:
+	case 8:
 		val_len |= RT5640_I2S_DL_8;
 		break;
 	default:

From 71d97a7943017faf03707836d00a260a108f4c89 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Fri, 28 Mar 2014 10:46:18 +0800
Subject: [PATCH 23/86] ASoC: rt5640: Use the platform data for DMIC settings

The patch uses the platform data for DMIC settings.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/rt5640.h    |  4 ++
 sound/soc/codecs/rt5640.c | 77 ++++++++++++---------------------------
 2 files changed, 27 insertions(+), 54 deletions(-)

diff --git a/include/sound/rt5640.h b/include/sound/rt5640.h
index 27cc75ed67f87..59d26dd81e453 100644
--- a/include/sound/rt5640.h
+++ b/include/sound/rt5640.h
@@ -16,6 +16,10 @@ struct rt5640_platform_data {
 	bool in1_diff;
 	bool in2_diff;
 
+	bool dmic_en;
+	bool dmic1_data_pin; /* 0 = IN1P; 1 = GPIO3 */
+	bool dmic2_data_pin; /* 0 = IN1N; 1 = GPIO4 */
+
 	int ldo1_en; /* GPIO for LDO1_EN */
 };
 
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index f0717db3e9353..6ede622ad44fb 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -872,54 +872,6 @@ static SOC_ENUM_SINGLE_DECL(rt5640_sdi_sel_enum, RT5640_I2S2_SDP,
 static const struct snd_kcontrol_new rt5640_sdi_mux =
 	SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum);
 
-static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
-			RT5640_GP2_PIN_MASK | RT5640_GP3_PIN_MASK,
-			RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP3_PIN_DMIC1_SDA);
-		snd_soc_update_bits(codec, RT5640_DMIC,
-			RT5640_DMIC_1L_LH_MASK | RT5640_DMIC_1R_LH_MASK |
-			RT5640_DMIC_1_DP_MASK,
-			RT5640_DMIC_1L_LH_FALLING | RT5640_DMIC_1R_LH_RISING |
-			RT5640_DMIC_1_DP_IN1P);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
-static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, RT5640_GPIO_CTRL1,
-			RT5640_GP2_PIN_MASK | RT5640_GP4_PIN_MASK,
-			RT5640_GP2_PIN_DMIC1_SCL | RT5640_GP4_PIN_DMIC2_SDA);
-		snd_soc_update_bits(codec, RT5640_DMIC,
-			RT5640_DMIC_2L_LH_MASK | RT5640_DMIC_2R_LH_MASK |
-			RT5640_DMIC_2_DP_MASK,
-			RT5640_DMIC_2L_LH_FALLING | RT5640_DMIC_2R_LH_RISING |
-			RT5640_DMIC_2_DP_IN1N);
-		break;
-
-	default:
-		return 0;
-	}
-
-	return 0;
-}
-
 static void hp_amp_power_on(struct snd_soc_codec *codec)
 {
 	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
@@ -1054,12 +1006,10 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 
 	SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
 		set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC,
-		RT5640_DMIC_1_EN_SFT, 0, rt5640_set_dmic1_event,
-		SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC,
-		RT5640_DMIC_2_EN_SFT, 0, rt5640_set_dmic2_event,
-		SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5640_DMIC, RT5640_DMIC_1_EN_SFT, 0,
+		NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5640_DMIC, RT5640_DMIC_2_EN_SFT, 0,
+		NULL, 0),
 	/* Boost */
 	SND_SOC_DAPM_PGA("BST1", RT5640_PWR_ANLG2,
 		RT5640_PWR_BST1_BIT, 0, NULL, 0),
@@ -2187,6 +2137,25 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
 		regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4,
 					RT5640_IN_DF2, RT5640_IN_DF2);
 
+	if (rt5640->pdata.dmic_en) {
+		regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+			RT5640_GP2_PIN_MASK, RT5640_GP2_PIN_DMIC1_SCL);
+
+		if (rt5640->pdata.dmic1_data_pin) {
+			regmap_update_bits(rt5640->regmap, RT5640_DMIC,
+				RT5640_DMIC_1_DP_MASK, RT5640_DMIC_1_DP_GPIO3);
+			regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+				RT5640_GP3_PIN_MASK, RT5640_GP3_PIN_DMIC1_SDA);
+		}
+
+		if (rt5640->pdata.dmic2_data_pin) {
+			regmap_update_bits(rt5640->regmap, RT5640_DMIC,
+				RT5640_DMIC_2_DP_MASK, RT5640_DMIC_2_DP_GPIO4);
+			regmap_update_bits(rt5640->regmap, RT5640_GPIO_CTRL1,
+				RT5640_GP4_PIN_MASK, RT5640_GP4_PIN_DMIC2_SDA);
+		}
+	}
+
 	rt5640->hp_mute = 1;
 
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640,

From 2f2a714c1bed2702e5abf55381c03ccdf7b0fd06 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Fri, 28 Mar 2014 20:28:25 +0800
Subject: [PATCH 24/86] ASoC: rt5640: Remove the pre-allocated size of
 reg_default

In order to prevent the redundant memory usage, the pre-allocated size of
reg_default should be remove.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 6ede622ad44fb..84ee7ef8eb170 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -59,7 +59,7 @@ static struct reg_default init_list[] = {
 };
 #define RT5640_INIT_REG_LEN ARRAY_SIZE(init_list)
 
-static const struct reg_default rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
+static const struct reg_default rt5640_reg[] = {
 	{ 0x00, 0x000e },
 	{ 0x01, 0xc8c8 },
 	{ 0x02, 0xc8c8 },

From 218a3f963822aca1d38b0175b6454fe53d15c2dd Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Fri, 28 Mar 2014 20:28:26 +0800
Subject: [PATCH 25/86] ASoC: rt5640: Rename the function of clock checking

In order to identify clearly, the patch renames the function
"check_sysclk1_source" to "is_sys_clk_from_pll".

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 84ee7ef8eb170..19634d0992bcf 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -480,7 +480,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
 	return idx;
 }
 
-static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
 			 struct snd_soc_dapm_widget *sink)
 {
 	unsigned int val;
@@ -1273,22 +1273,22 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"Stereo ADC MIXL", "ADC1 Switch", "Stereo ADC L1 Mux"},
 	{"Stereo ADC MIXL", "ADC2 Switch", "Stereo ADC L2 Mux"},
 	{"Stereo ADC MIXL", NULL, "Stereo Filter"},
-	{"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"Stereo ADC MIXR", "ADC1 Switch", "Stereo ADC R1 Mux"},
 	{"Stereo ADC MIXR", "ADC2 Switch", "Stereo ADC R2 Mux"},
 	{"Stereo ADC MIXR", NULL, "Stereo Filter"},
-	{"Stereo Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Stereo Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux"},
 	{"Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux"},
 	{"Mono ADC MIXL", NULL, "Mono Left Filter"},
-	{"Mono Left Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux"},
 	{"Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux"},
 	{"Mono ADC MIXR", NULL, "Mono Right Filter"},
-	{"Mono Right Filter", NULL, "PLL1", check_sysclk1_source},
+	{"Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"IF2 ADC L", NULL, "Mono ADC MIXL"},
 	{"IF2 ADC R", NULL, "Mono ADC MIXR"},
@@ -1377,13 +1377,13 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
 
 	{"DAC L1", NULL, "Stereo DAC MIXL"},
-	{"DAC L1", NULL, "PLL1", check_sysclk1_source},
+	{"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
 	{"DAC R1", NULL, "Stereo DAC MIXR"},
-	{"DAC R1", NULL, "PLL1", check_sysclk1_source},
+	{"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
 	{"DAC L2", NULL, "Mono DAC MIXL"},
-	{"DAC L2", NULL, "PLL1", check_sysclk1_source},
+	{"DAC L2", NULL, "PLL1", is_sys_clk_from_pll},
 	{"DAC R2", NULL, "Mono DAC MIXR"},
-	{"DAC R2", NULL, "PLL1", check_sysclk1_source},
+	{"DAC R2", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"SPK MIXL", "REC MIXL Switch", "RECMIXL"},
 	{"SPK MIXL", "INL Switch", "INL VOL"},

From acf04e639bba2270fd07e161fa984234591ef43b Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Fri, 28 Mar 2014 20:28:27 +0800
Subject: [PATCH 26/86] ASoC: rt5640: Remove the unused or incorrect setting of
 clock source

The patch removes the unused or incorrect setting of clock source.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 8 +-------
 sound/soc/codecs/rt5640.h | 2 --
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 19634d0992bcf..4c866135e40fc 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -487,7 +487,7 @@ static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
 
 	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)
+	if (val == RT5640_SCLK_SRC_PLL1)
 		return 1;
 	else
 		return 0;
@@ -1694,12 +1694,6 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
 	case RT5640_SCLK_S_PLL1:
 		reg_val |= RT5640_SCLK_SRC_PLL1;
 		break;
-	case RT5640_SCLK_S_PLL1_TK:
-		reg_val |= RT5640_SCLK_SRC_PLL1T;
-		break;
-	case RT5640_SCLK_S_RCCLK:
-		reg_val |= RT5640_SCLK_SRC_RCCLK;
-		break;
 	default:
 		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
 		return -EINVAL;
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 5e8df25a13f34..cbd07b5f8060c 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -976,8 +976,6 @@
 #define RT5640_SCLK_SRC_SFT			14
 #define RT5640_SCLK_SRC_MCLK			(0x0 << 14)
 #define RT5640_SCLK_SRC_PLL1			(0x1 << 14)
-#define RT5640_SCLK_SRC_PLL1T			(0x2 << 14)
-#define RT5640_SCLK_SRC_RCCLK			(0x3 << 14) /* 15MHz */
 #define RT5640_PLL1_SRC_MASK			(0x3 << 12)
 #define RT5640_PLL1_SRC_SFT			12
 #define RT5640_PLL1_SRC_MCLK			(0x0 << 12)

From bc49e462cd6ded128cc6dbb6775de4a4c3d6bbc8 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Fri, 28 Mar 2014 20:28:28 +0800
Subject: [PATCH 27/86] ASoC: rt5640: Remove the unused field in private data

The patch removes the unused field in private data.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index cbd07b5f8060c..d7bd525caf85b 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -2095,7 +2095,6 @@ struct rt5640_priv {
 	int pll_in;
 	int pll_out;
 
-	int dmic_en;
 	bool hp_mute;
 };
 

From 3441e524293c5e8d640488e343f2eb2bcc944108 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Fri, 28 Mar 2014 20:28:29 +0800
Subject: [PATCH 28/86] ASoC: rt5640: Remove the unnecessary parentheses

The patch removes the unnecessary parentheses.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 4c866135e40fc..b6a02c16f100f 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2110,7 +2110,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
 	}
 
 	regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val);
-	if ((val != RT5640_DEVICE_ID)) {
+	if (val != RT5640_DEVICE_ID) {
 		dev_err(&i2c->dev,
 			"Device with ID register %x is not rt5640/39\n", val);
 		return -ENODEV;

From 09caf300540c4a610dbe6e46afdab18f365be7e7 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Mon, 31 Mar 2014 10:21:10 +0800
Subject: [PATCH 29/86] ASoC: rt5640: Change the setting method of
 idle_bias_off

The patch moves the idle_bias_off setting to struct "soc_codec_dev_rt5640".

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index b6a02c16f100f..a7db7ef38cfc4 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1879,7 +1879,6 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 
 	rt5640->codec = codec;
 
-	codec->dapm.idle_bias_off = 1;
 	rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301);
@@ -1988,6 +1987,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
 	.suspend = rt5640_suspend,
 	.resume = rt5640_resume,
 	.set_bias_level = rt5640_set_bias_level,
+	.idle_bias_off = true,
 	.controls = rt5640_snd_controls,
 	.num_controls = ARRAY_SIZE(rt5640_snd_controls),
 	.dapm_widgets = rt5640_dapm_widgets,

From 022d21f004c14db2151d08143a544b292324d099 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Tue, 8 Apr 2014 19:40:00 +0800
Subject: [PATCH 30/86] ASoC: rt5640: add rt5639 support

This patch adds the rt5639 support

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 286 ++++++++++++++++++++++++++++----------
 sound/soc/codecs/rt5640.h |   3 +
 2 files changed, 213 insertions(+), 76 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index a7db7ef38cfc4..a20781eda7193 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -398,18 +398,13 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 		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),
@@ -441,6 +436,15 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = {
 	SOC_ENUM("DAC IF2 Data Switch", rt5640_if2_dac_enum),
 };
 
+static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = {
+	/* MONO Output Control */
+	SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT, RT5640_L_MUTE_SFT,
+		1, 1),
+
+	SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL,
+		RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 175, 0, dac_vol_tlv),
+};
+
 /**
  * set_dmic_clk - Set parameter of dmic.
  *
@@ -554,6 +558,20 @@ static const struct snd_kcontrol_new rt5640_sto_dac_r_mix[] = {
 			RT5640_M_ANC_DAC_R_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new rt5639_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),
+};
+
+static const struct snd_kcontrol_new rt5639_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),
+};
+
 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),
@@ -676,6 +694,30 @@ static const struct snd_kcontrol_new rt5640_out_r_mix[] = {
 			RT5640_M_DAC_R1_OM_R_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new rt5639_out_l_mix[] = {
+	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 L1 Switch", RT5640_OUT_L3_MIXER,
+			RT5640_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5639_out_r_mix[] = {
+	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 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),
@@ -707,6 +749,13 @@ static const struct snd_kcontrol_new rt5640_hpo_mix[] = {
 			RT5640_M_HPVOL_HM_SFT, 1, 1),
 };
 
+static const struct snd_kcontrol_new rt5639_hpo_mix[] = {
+	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),
@@ -1096,26 +1145,15 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
-	/* Audio DSP */
-	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
-	/* ANC */
-	SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
 	/* Output Side */
 	/* DAC mixer before sound effect  */
 	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
 		rt5640_dac_l_mix, ARRAY_SIZE(rt5640_dac_l_mix)),
 	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
 		rt5640_dac_r_mix, ARRAY_SIZE(rt5640_dac_r_mix)),
-	/* DAC2 channel Mux */
-	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0,
-				&rt5640_dac_l2_mux),
-	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0,
-				&rt5640_dac_r2_mux),
+
 	/* DAC Mixer */
-	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
-		rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
-	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
-		rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
 	SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
 		rt5640_mono_dac_l_mix, ARRAY_SIZE(rt5640_mono_dac_l_mix)),
 	SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
@@ -1127,21 +1165,14 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	/* DACs */
 	SND_SOC_DAPM_DAC("DAC L1", NULL, RT5640_PWR_DIG1,
 			RT5640_PWR_DAC_L1_BIT, 0),
-	SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1,
-			RT5640_PWR_DAC_L2_BIT, 0),
 	SND_SOC_DAPM_DAC("DAC R1", NULL, RT5640_PWR_DIG1,
 			RT5640_PWR_DAC_R1_BIT, 0),
-	SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1,
-			RT5640_PWR_DAC_R2_BIT, 0),
+
 	/* SPK/OUT Mixer */
 	SND_SOC_DAPM_MIXER("SPK MIXL", RT5640_PWR_MIXER, RT5640_PWR_SM_L_BIT,
 		0, rt5640_spk_l_mix, ARRAY_SIZE(rt5640_spk_l_mix)),
 	SND_SOC_DAPM_MIXER("SPK MIXR", RT5640_PWR_MIXER, RT5640_PWR_SM_R_BIT,
 		0, rt5640_spk_r_mix, ARRAY_SIZE(rt5640_spk_r_mix)),
-	SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
-		0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
-	SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
-		0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
 	/* Ouput Volume */
 	SND_SOC_DAPM_PGA("SPKVOL L", RT5640_PWR_VOL,
 		RT5640_PWR_SV_L_BIT, 0, NULL, 0),
@@ -1160,16 +1191,8 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 		0, rt5640_spo_l_mix, ARRAY_SIZE(rt5640_spo_l_mix)),
 	SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0,
 		0, rt5640_spo_r_mix, ARRAY_SIZE(rt5640_spo_r_mix)),
-	SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
-		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
-	SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
-		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
 	SND_SOC_DAPM_MIXER("LOUT MIX", RT5640_PWR_ANLG1, RT5640_PWR_LM_BIT, 0,
 		rt5640_lout_mix, ARRAY_SIZE(rt5640_lout_mix)),
-	SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
-		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
-	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
-		RT5640_PWR_MA_BIT, 0, NULL, 0),
 	SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM,
 		0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0,
@@ -1201,10 +1224,69 @@ static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("HPOR"),
 	SND_SOC_DAPM_OUTPUT("LOUTL"),
 	SND_SOC_DAPM_OUTPUT("LOUTR"),
+};
+
+static const struct snd_soc_dapm_widget rt5640_specific_dapm_widgets[] = {
+	/* Audio DSP */
+	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+	/* ANC */
+	SND_SOC_DAPM_PGA("ANC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* DAC2 channel Mux */
+	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dac_l2_mux),
+	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5640_dac_r2_mux),
+
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5640_sto_dac_l_mix, ARRAY_SIZE(rt5640_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5640_sto_dac_r_mix, ARRAY_SIZE(rt5640_sto_dac_r_mix)),
+
+	SND_SOC_DAPM_DAC("DAC R2", NULL, RT5640_PWR_DIG1, RT5640_PWR_DAC_R2_BIT,
+		0),
+	SND_SOC_DAPM_DAC("DAC L2", NULL, RT5640_PWR_DIG1, RT5640_PWR_DAC_L2_BIT,
+		0),
+
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
+		0, rt5640_out_l_mix, ARRAY_SIZE(rt5640_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
+		0, rt5640_out_r_mix, ARRAY_SIZE(rt5640_out_r_mix)),
+
+	SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
+		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
+	SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
+		rt5640_hpo_mix, ARRAY_SIZE(rt5640_hpo_mix)),
+
+	SND_SOC_DAPM_MIXER("Mono MIX", RT5640_PWR_ANLG1, RT5640_PWR_MM_BIT, 0,
+		rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)),
+	SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1,
+		RT5640_PWR_MA_BIT, 0, NULL, 0),
+
 	SND_SOC_DAPM_OUTPUT("MONOP"),
 	SND_SOC_DAPM_OUTPUT("MONON"),
 };
 
+static const struct snd_soc_dapm_widget rt5639_specific_dapm_widgets[] = {
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5639_sto_dac_l_mix, ARRAY_SIZE(rt5639_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5639_sto_dac_r_mix, ARRAY_SIZE(rt5639_sto_dac_r_mix)),
+
+	SND_SOC_DAPM_SUPPLY("DAC L2 Filter", RT5640_PWR_DIG1,
+		RT5640_PWR_DAC_L2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC R2 Filter", RT5640_PWR_DIG1,
+		RT5640_PWR_DAC_R2_BIT, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5640_PWR_MIXER, RT5640_PWR_OM_L_BIT,
+		0, rt5639_out_l_mix, ARRAY_SIZE(rt5639_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5640_PWR_MIXER, RT5640_PWR_OM_R_BIT,
+		0, rt5639_out_r_mix, ARRAY_SIZE(rt5639_out_r_mix)),
+
+	SND_SOC_DAPM_MIXER("HPO MIX L", SND_SOC_NOPM, 0, 0,
+		rt5639_hpo_mix, ARRAY_SIZE(rt5639_hpo_mix)),
+	SND_SOC_DAPM_MIXER("HPO MIX R", SND_SOC_NOPM, 0, 0,
+		rt5639_hpo_mix, ARRAY_SIZE(rt5639_hpo_mix)),
+};
+
 static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"IN1P", NULL, "LDO2"},
 	{"IN2P", NULL, "LDO2"},
@@ -1346,71 +1428,38 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"DAC MIXR", "Stereo ADC Switch", "Stereo ADC MIXR"},
 	{"DAC MIXR", "INF1 Switch", "IF1 DAC R"},
 
-	{"ANC", NULL, "Stereo ADC MIXL"},
-	{"ANC", NULL, "Stereo ADC MIXR"},
-
-	{"Audio DSP", NULL, "DAC MIXL"},
-	{"Audio DSP", NULL, "DAC MIXR"},
-
-	{"DAC L2 Mux", "IF2", "IF2 DAC L"},
-	{"DAC L2 Mux", "Base L/R", "Audio DSP"},
-
-	{"DAC R2 Mux", "IF2", "IF2 DAC R"},
-
 	{"Stereo DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
-	{"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
-	{"Stereo DAC MIXL", "ANC Switch", "ANC"},
 	{"Stereo DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
-	{"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
-	{"Stereo DAC MIXR", "ANC Switch", "ANC"},
 
 	{"Mono DAC MIXL", "DAC L1 Switch", "DAC MIXL"},
-	{"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
-	{"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
 	{"Mono DAC MIXR", "DAC R1 Switch", "DAC MIXR"},
-	{"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
-	{"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
 
 	{"DIG MIXL", "DAC L1 Switch", "DAC MIXL"},
-	{"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
 	{"DIG MIXR", "DAC R1 Switch", "DAC MIXR"},
-	{"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
 
 	{"DAC L1", NULL, "Stereo DAC MIXL"},
 	{"DAC L1", NULL, "PLL1", is_sys_clk_from_pll},
 	{"DAC R1", NULL, "Stereo DAC MIXR"},
 	{"DAC R1", NULL, "PLL1", is_sys_clk_from_pll},
-	{"DAC L2", NULL, "Mono DAC MIXL"},
-	{"DAC L2", NULL, "PLL1", is_sys_clk_from_pll},
-	{"DAC R2", NULL, "Mono DAC MIXR"},
-	{"DAC R2", NULL, "PLL1", is_sys_clk_from_pll},
 
 	{"SPK MIXL", "REC MIXL Switch", "RECMIXL"},
 	{"SPK MIXL", "INL Switch", "INL VOL"},
 	{"SPK MIXL", "DAC L1 Switch", "DAC L1"},
-	{"SPK MIXL", "DAC L2 Switch", "DAC L2"},
 	{"SPK MIXL", "OUT MIXL Switch", "OUT MIXL"},
 	{"SPK MIXR", "REC MIXR Switch", "RECMIXR"},
 	{"SPK MIXR", "INR Switch", "INR VOL"},
 	{"SPK MIXR", "DAC R1 Switch", "DAC R1"},
-	{"SPK MIXR", "DAC R2 Switch", "DAC R2"},
 	{"SPK MIXR", "OUT MIXR Switch", "OUT MIXR"},
 
-	{"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
 	{"OUT MIXL", "BST1 Switch", "BST1"},
 	{"OUT MIXL", "INL Switch", "INL VOL"},
 	{"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
-	{"OUT MIXL", "DAC R2 Switch", "DAC R2"},
-	{"OUT MIXL", "DAC L2 Switch", "DAC L2"},
 	{"OUT MIXL", "DAC L1 Switch", "DAC L1"},
 
-	{"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
 	{"OUT MIXR", "BST2 Switch", "BST2"},
 	{"OUT MIXR", "BST1 Switch", "BST1"},
 	{"OUT MIXR", "INR Switch", "INR VOL"},
 	{"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
-	{"OUT MIXR", "DAC L2 Switch", "DAC L2"},
-	{"OUT MIXR", "DAC R2 Switch", "DAC R2"},
 	{"OUT MIXR", "DAC R1 Switch", "DAC R1"},
 
 	{"SPKVOL L", NULL, "SPK MIXL"},
@@ -1429,11 +1478,9 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"SPOR MIX", "SPKVOL R Switch", "SPKVOL R"},
 	{"SPOR MIX", "BST1 Switch", "BST1"},
 
-	{"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
 	{"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"},
 	{"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"},
 	{"HPO MIX L", NULL, "HP L Amp"},
-	{"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
 	{"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"},
 	{"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"},
 	{"HPO MIX R", NULL, "HP R Amp"},
@@ -1443,12 +1490,6 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
 	{"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
 
-	{"Mono MIX", "DAC R2 Switch", "DAC R2"},
-	{"Mono MIX", "DAC L2 Switch", "DAC L2"},
-	{"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
-	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
-	{"Mono MIX", "BST1 Switch", "BST1"},
-
 	{"HP Amp", NULL, "HPO MIX L"},
 	{"HP Amp", NULL, "HPO MIX R"},
 
@@ -1473,11 +1514,82 @@ static const struct snd_soc_dapm_route rt5640_dapm_routes[] = {
 	{"HPOR", NULL, "HP R Playback"},
 	{"LOUTL", NULL, "LOUT MIX"},
 	{"LOUTR", NULL, "LOUT MIX"},
+};
+
+static const struct snd_soc_dapm_route rt5640_specific_dapm_routes[] = {
+	{"ANC", NULL, "Stereo ADC MIXL"},
+	{"ANC", NULL, "Stereo ADC MIXR"},
+
+	{"Audio DSP", NULL, "DAC MIXL"},
+	{"Audio DSP", NULL, "DAC MIXR"},
+
+	{"DAC L2 Mux", "IF2", "IF2 DAC L"},
+	{"DAC L2 Mux", "Base L/R", "Audio DSP"},
+
+	{"DAC R2 Mux", "IF2", "IF2 DAC R"},
+
+	{"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+	{"Stereo DAC MIXL", "ANC Switch", "ANC"},
+	{"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+	{"Stereo DAC MIXR", "ANC Switch", "ANC"},
+
+	{"Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+	{"Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Mux"},
+
+	{"Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+	{"Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Mux"},
+
+	{"DIG MIXR", "DAC R2 Switch", "DAC R2 Mux"},
+	{"DIG MIXL", "DAC L2 Switch", "DAC L2 Mux"},
+
+	{"DAC L2", NULL, "Mono DAC MIXL"},
+	{"DAC L2", NULL, "PLL1", is_sys_clk_from_pll},
+	{"DAC R2", NULL, "Mono DAC MIXR"},
+	{"DAC R2", NULL, "PLL1", is_sys_clk_from_pll},
+
+	{"SPK MIXL", "DAC L2 Switch", "DAC L2"},
+	{"SPK MIXR", "DAC R2 Switch", "DAC R2"},
+
+	{"OUT MIXL", "SPK MIXL Switch", "SPK MIXL"},
+	{"OUT MIXR", "SPK MIXR Switch", "SPK MIXR"},
+
+	{"OUT MIXL", "DAC R2 Switch", "DAC R2"},
+	{"OUT MIXL", "DAC L2 Switch", "DAC L2"},
+
+	{"OUT MIXR", "DAC L2 Switch", "DAC L2"},
+	{"OUT MIXR", "DAC R2 Switch", "DAC R2"},
+
+	{"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"},
+	{"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"},
+
+	{"Mono MIX", "DAC R2 Switch", "DAC R2"},
+	{"Mono MIX", "DAC L2 Switch", "DAC L2"},
+	{"Mono MIX", "OUTVOL R Switch", "OUTVOL R"},
+	{"Mono MIX", "OUTVOL L Switch", "OUTVOL L"},
+	{"Mono MIX", "BST1 Switch", "BST1"},
+
 	{"MONOP", NULL, "Mono MIX"},
 	{"MONON", NULL, "Mono MIX"},
 	{"MONOP", NULL, "Improve MONO Amp Drv"},
 };
 
+static const struct snd_soc_dapm_route rt5639_specific_dapm_routes[] = {
+	{"Stereo DAC MIXL", "DAC L2 Switch", "IF2 DAC L"},
+	{"Stereo DAC MIXR", "DAC R2 Switch", "IF2 DAC R"},
+
+	{"Mono DAC MIXL", "DAC L2 Switch", "IF2 DAC L"},
+	{"Mono DAC MIXL", "DAC R2 Switch", "IF2 DAC R"},
+
+	{"Mono DAC MIXR", "DAC R2 Switch", "IF2 DAC R"},
+	{"Mono DAC MIXR", "DAC L2 Switch", "IF2 DAC L"},
+
+	{"DIG MIXL", "DAC L2 Switch", "IF2 DAC L"},
+	{"DIG MIXR", "DAC R2 Switch", "IF2 DAC R"},
+
+	{"IF2 DAC L", NULL, "DAC L2 Filter"},
+	{"IF2 DAC R", NULL, "DAC R2 Filter"},
+};
+
 static int get_sdp_info(struct snd_soc_codec *codec, int dai_id)
 {
 	int ret = 0, val;
@@ -1885,6 +1997,28 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
 	snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
 
+	switch (snd_soc_read(codec, RT5640_RESET)) {
+	case RT5640_RESET_ID:
+		snd_soc_add_codec_controls(codec,
+			rt5640_specific_snd_controls,
+			ARRAY_SIZE(rt5640_specific_snd_controls));
+		snd_soc_dapm_new_controls(&codec->dapm,
+			rt5640_specific_dapm_widgets,
+			ARRAY_SIZE(rt5640_specific_dapm_widgets));
+		snd_soc_dapm_add_routes(&codec->dapm,
+			rt5640_specific_dapm_routes,
+			ARRAY_SIZE(rt5640_specific_dapm_routes));
+		break;
+	case RT5639_RESET_ID:
+		snd_soc_dapm_new_controls(&codec->dapm,
+			rt5639_specific_dapm_widgets,
+			ARRAY_SIZE(rt5639_specific_dapm_widgets));
+		snd_soc_dapm_add_routes(&codec->dapm,
+			rt5639_specific_dapm_routes,
+			ARRAY_SIZE(rt5639_specific_dapm_routes));
+		break;
+	}
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index d7bd525caf85b..3b50459a83b4b 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -14,6 +14,9 @@
 
 #include <sound/rt5640.h>
 
+#define RT5639_RESET_ID				0x0008
+#define RT5640_RESET_ID				0x000c
+
 /* Info */
 #define RT5640_RESET				0x00
 #define RT5640_VENDOR_ID			0xfd

From b0c278469777b75d0af3b5718369084acb71c344 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 10 Apr 2014 10:57:34 +0800
Subject: [PATCH 31/86] ASoC: rt5640: Add the string "rt5639" to the list of
 I2C device IDs

The patch adds the string "rt5639" to the list of I2C device IDs.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index a20781eda7193..6674372be12c0 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1,5 +1,5 @@
 /*
- * rt5640.c  --  RT5640 ALSA SoC audio codec driver
+ * rt5640.c  --  RT5640/RT5639 ALSA SoC audio codec driver
  *
  * Copyright 2011 Realtek Semiconductor Corp.
  * Author: Johnny Hsu <johnnyhsu@realtek.com>
@@ -2148,6 +2148,7 @@ static const struct regmap_config rt5640_regmap = {
 
 static const struct i2c_device_id rt5640_i2c_id[] = {
 	{ "rt5640", 0 },
+	{ "rt5639", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
@@ -2316,6 +2317,6 @@ static struct i2c_driver rt5640_i2c_driver = {
 };
 module_i2c_driver(rt5640_i2c_driver);
 
-MODULE_DESCRIPTION("ASoC RT5640 driver");
+MODULE_DESCRIPTION("ASoC RT5640/RT5639 driver");
 MODULE_AUTHOR("Johnny Hsu <johnnyhsu@realtek.com>");
 MODULE_LICENSE("GPL v2");

From 908b7032a8b5cb7110beac213f7d3058097fa5aa Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 10 Apr 2014 10:57:35 +0800
Subject: [PATCH 32/86] ASoC: rt5640: Add the info of rt5639 to the binding
 document

The patch adds the info of rt5639 to the binding document.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 Documentation/devicetree/bindings/sound/rt5640.txt | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt
index 068a1141b06f1..bac4d9ac1edc8 100644
--- a/Documentation/devicetree/bindings/sound/rt5640.txt
+++ b/Documentation/devicetree/bindings/sound/rt5640.txt
@@ -1,10 +1,10 @@
-RT5640 audio CODEC
+RT5640/RT5639 audio CODEC
 
 This device supports I2C only.
 
 Required properties:
 
-- compatible : "realtek,rt5640".
+- compatible : One of "realtek,rt5640" or "realtek,rt5639".
 
 - reg : The I2C address of the device.
 
@@ -18,7 +18,7 @@ Optional properties:
 
 - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
 
-Pins on the device (for linking into audio routes):
+Pins on the device (for linking into audio routes) for RT5639/RT5640:
 
   * DMIC1
   * DMIC2
@@ -31,13 +31,16 @@ Pins on the device (for linking into audio routes):
   * HPOR
   * LOUTL
   * LOUTR
-  * MONOP
-  * MONON
   * SPOLP
   * SPOLN
   * SPORP
   * SPORN
 
+Additional pins on the device for RT5640:
+
+  * MONOP
+  * MONON
+
 Example:
 
 rt5640 {

From 4d4a0ff30c39b82c1dc549f2cc7a62b514431e64 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Mon, 14 Apr 2014 19:35:57 +0200
Subject: [PATCH 33/86] ARM: shmobile: koelsch legacy: Enable Quad SPI
 transfers for the SPI FLASH

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-koelsch.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
index 5a034ff405d00..a12a9d3b4b6e3 100644
--- a/arch/arm/mach-shmobile/board-koelsch.c
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -216,7 +216,7 @@ static const struct spi_board_info spi_info[] __initconst = {
 	{
 		.modalias	= "m25p80",
 		.platform_data	= &spi_flash_data,
-		.mode		= SPI_MODE_0,
+		.mode		= SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD,
 		.max_speed_hz	= 30000000,
 		.bus_num	= 0,
 		.chip_select	= 0,

From a09b2f0ba170dc89a67d6c4c4f027b37a085dad9 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Mon, 14 Apr 2014 19:35:59 +0200
Subject: [PATCH 34/86] ARM: shmobile: lager legacy: Enable Quad SPI transfers
 for the SPI FLASH

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm/mach-shmobile/board-lager.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index 6af09e1e0841d..6c4fcfe5d9db3 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -325,12 +325,12 @@ static const struct rspi_plat_data qspi_pdata __initconst = {
 
 static const struct spi_board_info spi_info[] __initconst = {
 	{
-		.modalias               = "m25p80",
-		.platform_data          = &spi_flash_data,
-		.mode                   = SPI_MODE_0,
-		.max_speed_hz           = 30000000,
-		.bus_num                = 0,
-		.chip_select            = 0,
+		.modalias	= "m25p80",
+		.platform_data	= &spi_flash_data,
+		.mode		= SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD,
+		.max_speed_hz	= 30000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
 	},
 };
 

From f6563b31fb4878fddc846d2012bcee9c5f260d11 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:13 +0300
Subject: [PATCH 35/86] ASoC: omap-mcpdm: Assign the dai DMA data at earlier
 time

Assign the dai dma data at dai driver probe time, not in startup.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-mcpdm.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 2f5b1536477e8..e984b0485e923 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -265,9 +265,6 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
 	}
 	mutex_unlock(&mcpdm->mutex);
 
-	snd_soc_dai_set_dma_data(dai, substream,
-				 &mcpdm->dma_data[substream->stream]);
-
 	return 0;
 }
 
@@ -406,6 +403,11 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
 	mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2;
 	mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold =
 							MCPDM_UP_THRES_MAX - 3;
+
+	snd_soc_dai_init_dma_data(dai,
+				  &mcpdm->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
+				  &mcpdm->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
+
 	return ret;
 }
 

From 335b06515eda252b36aa9063596f740a903c1e35 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:14 +0300
Subject: [PATCH 36/86] ASoC: omap-mcpdm: Bind the platform driver to the dai
 driver when loading

Use the same device for the platform driver when registering as the dai
driver. This will enable us to clean up some DT booted cases.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-mcpdm.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index e984b0485e923..d8ebb52645a99 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -42,6 +42,7 @@
 #include <sound/dmaengine_pcm.h>
 
 #include "omap-mcpdm.h"
+#include "omap-pcm.h"
 
 struct mcpdm_link_config {
 	u32 link_mask; /* channel mask for the direction */
@@ -462,6 +463,7 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
 {
 	struct omap_mcpdm *mcpdm;
 	struct resource *res;
+	int ret;
 
 	mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL);
 	if (!mcpdm)
@@ -492,9 +494,13 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
 
 	mcpdm->dev = &pdev->dev;
 
-	return devm_snd_soc_register_component(&pdev->dev,
+	ret =  devm_snd_soc_register_component(&pdev->dev,
 					       &omap_mcpdm_component,
 					       &omap_mcpdm_dai, 1);
+	if (ret)
+		return ret;
+
+	return omap_pcm_platform_register(&pdev->dev);
 }
 
 static const struct of_device_id omap_mcpdm_of_match[] = {

From 3fe856b3127744ce30d4369ba760459b6ac9f820 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:15 +0300
Subject: [PATCH 37/86] ASoC: omap-mcbsp: Assign the dai DMA data at earlier
 time

Assign the dai dma data at dai driver probe time, not in startup.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-mcbsp.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6c19bba235700..4525190d55995 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -149,9 +149,6 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
 					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
 	}
 
-	snd_soc_dai_set_dma_data(cpu_dai, substream,
-				 &mcbsp->dma_data[substream->stream]);
-
 	return err;
 }
 
@@ -559,6 +556,10 @@ static int omap_mcbsp_probe(struct snd_soc_dai *dai)
 
 	pm_runtime_enable(mcbsp->dev);
 
+	snd_soc_dai_init_dma_data(dai,
+				  &mcbsp->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
+				  &mcbsp->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
+
 	return 0;
 }
 

From 64241425b8eaf46c971b6ba400c21f71979e6782 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:16 +0300
Subject: [PATCH 38/86] ASoC: omap-mcbsp: Bind the platform driver to the dai
 driver when loading

Use the same device for the platform driver when registering as the dai
driver. This will enable us to clean up some DT booted cases.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-mcbsp.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 4525190d55995..af2764adf2523 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -38,6 +38,7 @@
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 #include "mcbsp.h"
 #include "omap-mcbsp.h"
+#include "omap-pcm.h"
 
 #define OMAP_MCBSP_RATES	(SNDRV_PCM_RATE_8000_96000)
 
@@ -800,11 +801,15 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, mcbsp);
 
 	ret = omap_mcbsp_init(pdev);
-	if (!ret)
-		return snd_soc_register_component(&pdev->dev, &omap_mcbsp_component,
-						  &omap_mcbsp_dai, 1);
+	if (ret)
+		return ret;
 
-	return ret;
+	ret = snd_soc_register_component(&pdev->dev, &omap_mcbsp_component,
+					 &omap_mcbsp_dai, 1);
+	if (ret)
+		return ret;
+
+	return omap_pcm_platform_register(&pdev->dev);
 }
 
 static int asoc_mcbsp_remove(struct platform_device *pdev)

From 3802a259272e48870b8d7e02c4fc28f938a699cb Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:17 +0300
Subject: [PATCH 39/86] ASoC: omap-dmic: Assign the dai DMA data at earlier
 time

Assign the dai dma data at dai driver probe time, not in startup.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-dmic.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 1bd531d718f95..7fb7703264fa9 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -113,7 +113,6 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
 
 	mutex_unlock(&dmic->mutex);
 
-	snd_soc_dai_set_dma_data(dai, substream, &dmic->dma_data);
 	return ret;
 }
 
@@ -417,6 +416,9 @@ static int omap_dmic_probe(struct snd_soc_dai *dai)
 
 	/* Configure DMIC threshold value */
 	dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
+
+	snd_soc_dai_init_dma_data(dai, NULL, &dmic->dma_data);
+
 	return 0;
 }
 

From 18d7cfea28fe7e06047abef40a18db2643a427be Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:18 +0300
Subject: [PATCH 40/86] ASoC: omap-dmic: Bind the platform driver to the dai
 driver when loading

Use the same device for the platform driver when registering as the dai
driver. This will enable us to clean up some DT booted cases.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-dmic.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
index 7fb7703264fa9..53da041896c43 100644
--- a/sound/soc/omap/omap-dmic.c
+++ b/sound/soc/omap/omap-dmic.c
@@ -42,6 +42,7 @@
 #include <sound/dmaengine_pcm.h>
 
 #include "omap-dmic.h"
+#include "omap-pcm.h"
 
 struct omap_dmic {
 	struct device *dev;
@@ -494,6 +495,10 @@ static int asoc_dmic_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_put_clk;
 
+	ret = omap_pcm_platform_register(&pdev->dev);
+	if (ret)
+		goto err_put_clk;
+
 	return 0;
 
 err_put_clk:

From 9769824cf9ca4bb877146dbec2695bdbf577c499 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:19 +0300
Subject: [PATCH 41/86] ASoC: omap-hdmi: Bind the platform driver to the dai
 driver when loading

Use the same device for the platform driver when registering as the dai
driver. This will enable us to clean up some DT booted cases.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-hdmi.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index ced3b88b44d43..32614b49653cb 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -36,6 +36,7 @@
 #include <video/omapdss.h>
 
 #include "omap-hdmi.h"
+#include "omap-pcm.h"
 
 #define DRV_NAME "omap-hdmi-audio-dai"
 
@@ -324,7 +325,11 @@ static int omap_hdmi_probe(struct platform_device *pdev)
 	ret = snd_soc_register_component(&pdev->dev, &omap_hdmi_component,
 					 &omap_hdmi_dai, 1);
 
-	return ret;
+	if (ret)
+		return ret;
+
+	return omap_pcm_platform_register(&pdev->dev);
+}
 }
 
 static int omap_hdmi_remove(struct platform_device *pdev)

From 25bed461f96f883830b249ed1b1d6eb5d3930537 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:21 +0300
Subject: [PATCH 42/86] ASoC: omap-abe-twl6040: Use the cpu_dai node to specify
 the platform driver

Now that the platform driver is registered with the cpu_dai's device we
can use the same node for it instead of the hardwired name.
We can also remove the cpu_dai_name and platform_name from the dai_link
struct since we only support DT boot on OMAP4/5

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-abe-twl6040.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index 024dafc3e2981..1a89e5b1be163 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -214,9 +214,7 @@ static struct snd_soc_dai_link abe_twl6040_dai_links[] = {
 	{
 		.name = "TWL6040",
 		.stream_name = "TWL6040",
-		.cpu_dai_name = "omap-mcpdm",
 		.codec_dai_name = "twl6040-legacy",
-		.platform_name = "omap-pcm-audio",
 		.codec_name = "twl6040-codec",
 		.init = omap_abe_twl6040_init,
 		.ops = &omap_abe_ops,
@@ -224,9 +222,7 @@ static struct snd_soc_dai_link abe_twl6040_dai_links[] = {
 	{
 		.name = "DMIC",
 		.stream_name = "DMIC Capture",
-		.cpu_dai_name = "omap-dmic",
 		.codec_dai_name = "dmic-hifi",
-		.platform_name = "omap-pcm-audio",
 		.codec_name = "dmic-codec",
 		.init = omap_abe_dmic_init,
 		.ops = &omap_abe_dmic_ops,
@@ -281,14 +277,14 @@ static int omap_abe_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "McPDM node is not provided\n");
 		return -EINVAL;
 	}
-	abe_twl6040_dai_links[0].cpu_dai_name  = NULL;
 	abe_twl6040_dai_links[0].cpu_of_node = dai_node;
+	abe_twl6040_dai_links[0].platform_of_node = dai_node;
 
 	dai_node = of_parse_phandle(node, "ti,dmic", 0);
 	if (dai_node) {
 		num_links = 2;
-		abe_twl6040_dai_links[1].cpu_dai_name  = NULL;
 		abe_twl6040_dai_links[1].cpu_of_node = dai_node;
+		abe_twl6040_dai_links[1].platform_of_node = dai_node;
 
 		priv->dmic_codec_dev = platform_device_register_simple(
 						"dmic-codec", -1, NULL, 0);

From dc568f876ad5d2962309c3d41dae879637de37de Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:22 +0300
Subject: [PATCH 43/86] ASoC: omap-twl4030: Use the same name/node for platform
 as the cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name/node for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-twl4030.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index 6a8d6b5f160de..0c83e206e9574 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -239,7 +239,7 @@ static struct snd_soc_dai_link omap_twl4030_dai_links[] = {
 		.stream_name = "TWL4030 HiFi",
 		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "twl4030-hifi",
-		.platform_name = "omap-pcm-audio",
+		.platform_name = "omap-mcbsp.2",
 		.codec_name = "twl4030-codec",
 		.init = omap_twl4030_init,
 		.ops = &omap_twl4030_ops,
@@ -249,7 +249,7 @@ static struct snd_soc_dai_link omap_twl4030_dai_links[] = {
 		.stream_name = "TWL4030 Voice",
 		.cpu_dai_name = "omap-mcbsp.3",
 		.codec_dai_name = "twl4030-voice",
-		.platform_name = "omap-pcm-audio",
+		.platform_name = "omap-mcbsp.2",
 		.codec_name = "twl4030-codec",
 		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
 			   SND_SOC_DAIFMT_CBM_CFM,
@@ -299,12 +299,18 @@ static int omap_twl4030_probe(struct platform_device *pdev)
 		omap_twl4030_dai_links[0].cpu_dai_name  = NULL;
 		omap_twl4030_dai_links[0].cpu_of_node = dai_node;
 
+		omap_twl4030_dai_links[0].platform_name  = NULL;
+		omap_twl4030_dai_links[0].platform_of_node = dai_node;
+
 		dai_node = of_parse_phandle(node, "ti,mcbsp-voice", 0);
 		if (!dai_node) {
 			card->num_links = 1;
 		} else {
 			omap_twl4030_dai_links[1].cpu_dai_name  = NULL;
 			omap_twl4030_dai_links[1].cpu_of_node = dai_node;
+
+			omap_twl4030_dai_links[1].platform_name  = NULL;
+			omap_twl4030_dai_links[1].platform_of_node = dai_node;
 		}
 
 		priv->jack_detect = of_get_named_gpio(node,

From 301151733a783d4d8bfa08af8a1eadfea2338cf3 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:23 +0300
Subject: [PATCH 44/86] ASoC: am3517evm: Use the same name for platform as the
 cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/am3517evm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index 994dcf345975b..25a33e9d417a7 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -77,7 +77,7 @@ static struct snd_soc_dai_link am3517evm_dai = {
 	.stream_name = "AIC23",
 	.cpu_dai_name = "omap-mcbsp.1",
 	.codec_dai_name = "tlv320aic23-hifi",
-	.platform_name = "omap-pcm-audio",
+	.platform_name = "omap-mcbsp.1",
 	.codec_name = "tlv320aic23-codec.2-001a",
 	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
 		   SND_SOC_DAIFMT_CBM_CFM,

From a25f478f792d9992dbb0ffdb79384856150e93ff Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:24 +0300
Subject: [PATCH 45/86] ASoC: ams-delta: Use the same name for platform as the
 cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/ams-delta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 2ac0a0c3b570f..b0f8dbc1f635a 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -536,7 +536,7 @@ static struct snd_soc_dai_link ams_delta_dai_link = {
 	.cpu_dai_name = "omap-mcbsp.1",
 	.codec_dai_name = "cx20442-voice",
 	.init = ams_delta_cx20442_init,
-	.platform_name = "omap-pcm-audio",
+	.platform_name = "omap-mcbsp.1",
 	.codec_name = "cx20442-codec",
 	.ops = &ams_delta_ops,
 };

From 7f46b0b5445ac4763512bd20dbed77edcc70a8cd Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:25 +0300
Subject: [PATCH 46/86] ASoC: n810: Use the same name for platform as the
 cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/n810.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index fd4d9c809e50a..5d7f9cebe0414 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -278,7 +278,7 @@ static struct snd_soc_dai_link n810_dai = {
 	.name = "TLV320AIC33",
 	.stream_name = "AIC33",
 	.cpu_dai_name = "omap-mcbsp.2",
-	.platform_name = "omap-pcm-audio",
+	.platform_name = "omap-mcbsp.2",
 	.codec_name = "tlv320aic3x-codec.2-0018",
 	.codec_dai_name = "tlv320aic3x-hifi",
 	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |

From bffbe637aafa14cd30e5885eb0f1a59075a19452 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:26 +0300
Subject: [PATCH 47/86] ASoC: omap3pandora: Use the same name for platform as
 the cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap3pandora.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 02181bb70400a..076bec606d78a 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -197,7 +197,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 		.stream_name = "HiFi Out",
 		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "twl4030-hifi",
-		.platform_name = "omap-pcm-audio",
+		.platform_name = "omap-mcbsp.2",
 		.codec_name = "twl4030-codec",
 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 			   SND_SOC_DAIFMT_CBS_CFS,
@@ -208,7 +208,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 		.stream_name = "Line/Mic In",
 		.cpu_dai_name = "omap-mcbsp.4",
 		.codec_dai_name = "twl4030-hifi",
-		.platform_name = "omap-pcm-audio",
+		.platform_name = "omap-mcbsp.4",
 		.codec_name = "twl4030-codec",
 		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 			   SND_SOC_DAIFMT_CBS_CFS,

From b29064af5dcf703b6616810908c57ba8213ad071 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:27 +0300
Subject: [PATCH 48/86] ASoC: osk5912: Use the same name for platform as the
 cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/osk5912.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index d03e57da7708f..aa4053bf6710f 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -96,7 +96,7 @@ static struct snd_soc_dai_link osk_dai = {
 	.stream_name = "AIC23",
 	.cpu_dai_name = "omap-mcbsp.1",
 	.codec_dai_name = "tlv320aic23-hifi",
-	.platform_name = "omap-pcm-audio",
+	.platform_name = "omap-mcbsp.1",
 	.codec_name = "tlv320aic23-codec",
 	.dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
 		   SND_SOC_DAIFMT_CBM_CFM,

From aac25145886d937d29347af80846768b0f1a4bcb Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:28 +0300
Subject: [PATCH 49/86] ASoC: rx51: Use the same name for platform as the
 cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/rx51.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 2b4641123142a..add0047ea6c5a 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -319,7 +319,7 @@ static struct snd_soc_dai_link rx51_dai[] = {
 		.stream_name = "AIC34",
 		.cpu_dai_name = "omap-mcbsp.2",
 		.codec_dai_name = "tlv320aic3x-hifi",
-		.platform_name = "omap-pcm-audio",
+		.platform_name = "omap-mcbsp.2",
 		.codec_name = "tlv320aic3x-codec.2-0018",
 		.dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
 			   SND_SOC_DAIFMT_CBM_CFM,

From b30ca4bdde773534daa5e04da946a00cabe44bb5 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:29 +0300
Subject: [PATCH 50/86] ASoC: omap-hdmi-card: Use the same name for platform as
 the cpu_dai

Now that the platform driver is registered with the cpu_dai's device we
can use the same name for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-hdmi-card.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c
index 7e66e9cba5a87..f649fe84b629f 100644
--- a/sound/soc/omap/omap-hdmi-card.c
+++ b/sound/soc/omap/omap-hdmi-card.c
@@ -33,7 +33,7 @@ static struct snd_soc_dai_link omap_hdmi_dai = {
 	.name = "HDMI",
 	.stream_name = "HDMI",
 	.cpu_dai_name = "omap-hdmi-audio-dai",
-	.platform_name = "omap-pcm-audio",
+	.platform_name = "omap-hdmi-audio-dai",
 	.codec_name = "hdmi-audio-codec",
 	.codec_dai_name = "hdmi-hifi",
 };

From 5601174ff89f174b36437f7125785552e9c0b0c0 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Wed, 16 Apr 2014 15:46:30 +0300
Subject: [PATCH 51/86] ASoC: omap-pcm: Drop the platform driver init code

The omap-pcm no longer need to be a platform driver since all cpu_dai will
bind the platform to it's own device which we can use.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-pcm.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index c3711b582d5f7..8d809f8509c8e 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -238,31 +238,6 @@ int omap_pcm_platform_register(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(omap_pcm_platform_register);
 
-static int omap_pcm_probe(struct platform_device *pdev)
-{
-	return snd_soc_register_platform(&pdev->dev,
-			&omap_soc_platform);
-}
-
-static int omap_pcm_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_platform(&pdev->dev);
-	return 0;
-}
-
-static struct platform_driver omap_pcm_driver = {
-	.driver = {
-			.name = "omap-pcm-audio",
-			.owner = THIS_MODULE,
-	},
-
-	.probe = omap_pcm_probe,
-	.remove = omap_pcm_remove,
-};
-
-module_platform_driver(omap_pcm_driver);
-
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP PCM DMA module");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:omap-pcm-audio");

From 40bc18a2a2677150840eff7fa77835b07da214dd Mon Sep 17 00:00:00 2001
From: Bard Liao <bardliao@realtek.com>
Date: Wed, 16 Apr 2014 19:20:46 +0800
Subject: [PATCH 52/86] ASoC: add RT5651 CODEC driver

This patch adds the Realtek ALC5651 codec driver.

Signed-off-by: Bard Liao <bardliao@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/rt5651.h    |   21 +
 sound/soc/codecs/Kconfig  |    4 +
 sound/soc/codecs/Makefile |    2 +
 sound/soc/codecs/rt5651.c | 1898 +++++++++++++++++++++++++++++++++
 sound/soc/codecs/rt5651.h | 2081 +++++++++++++++++++++++++++++++++++++
 5 files changed, 4006 insertions(+)
 create mode 100644 include/sound/rt5651.h
 create mode 100644 sound/soc/codecs/rt5651.c
 create mode 100644 sound/soc/codecs/rt5651.h

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
new file mode 100644
index 0000000000000..d35de758dfb55
--- /dev/null
+++ b/include/sound/rt5651.h
@@ -0,0 +1,21 @@
+/*
+ * linux/sound/rt286.h -- Platform data for RT286
+ *
+ * Copyright 2013 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_RT5651_H
+#define __LINUX_SND_RT5651_H
+
+struct rt5651_platform_data {
+	/* IN2 can optionally be differential */
+	bool in2_diff;
+
+	bool dmic_en;
+};
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f0e8401378873..deba71bad6e9c 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -71,6 +71,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_PCM512x_SPI if SPI_MASTER
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5640 if I2C
+	select SND_SOC_RT5651 if I2C
 	select SND_SOC_SGTL5000 if I2C
 	select SND_SOC_SI476X if MFD_SI476X_CORE
 	select SND_SOC_SIRF_AUDIO_CODEC
@@ -396,6 +397,9 @@ config SND_SOC_RT5631
 config SND_SOC_RT5640
 	tristate
 
+config SND_SOC_RT5651
+	tristate
+
 #Freescale sgtl5000 codec
 config SND_SOC_SGTL5000
 	tristate "Freescale SGTL5000 CODEC"
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 3c4d275d064bf..e76938ee82f4c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -60,6 +60,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
+snd-soc-rt5651-objs := rt5651.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5632-objs := alc5632.o
@@ -211,6 +212,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
+obj-$(CONFIG_SND_SOC_RT5651)	+= snd-soc-rt5651.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/rt5651.c b/sound/soc/codecs/rt5651.c
new file mode 100644
index 0000000000000..a1577369c49cc
--- /dev/null
+++ b/sound/soc/codecs/rt5651.c
@@ -0,0 +1,1898 @@
+/*
+ * rt5651.c  --  RT5651 ALSA SoC audio codec driver
+ *
+ * Copyright 2014 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * 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/i2c.h>
+#include <linux/regmap.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 "rt5651.h"
+
+#define RT5651_DEVICE_ID_VALUE 0x6281
+
+#define RT5651_PR_RANGE_BASE (0xff + 1)
+#define RT5651_PR_SPACING 0x100
+
+#define RT5651_PR_BASE (RT5651_PR_RANGE_BASE + (0 * RT5651_PR_SPACING))
+
+static const struct regmap_range_cfg rt5651_ranges[] = {
+	{ .name = "PR", .range_min = RT5651_PR_BASE,
+	  .range_max = RT5651_PR_BASE + 0xb4,
+	  .selector_reg = RT5651_PRIV_INDEX,
+	  .selector_mask = 0xff,
+	  .selector_shift = 0x0,
+	  .window_start = RT5651_PRIV_DATA,
+	  .window_len = 0x1, },
+};
+
+static struct reg_default init_list[] = {
+	{RT5651_PR_BASE + 0x3d,	0x3e00},
+};
+
+static const struct reg_default rt5651_reg[] = {
+	{ 0x00, 0x0000 },
+	{ 0x02, 0xc8c8 },
+	{ 0x03, 0xc8c8 },
+	{ 0x05, 0x0000 },
+	{ 0x0d, 0x0000 },
+	{ 0x0e, 0x0000 },
+	{ 0x0f, 0x0808 },
+	{ 0x10, 0x0808 },
+	{ 0x19, 0xafaf },
+	{ 0x1a, 0xafaf },
+	{ 0x1b, 0x0c00 },
+	{ 0x1c, 0x2f2f },
+	{ 0x1d, 0x2f2f },
+	{ 0x1e, 0x0000 },
+	{ 0x27, 0x7860 },
+	{ 0x28, 0x7070 },
+	{ 0x29, 0x8080 },
+	{ 0x2a, 0x5252 },
+	{ 0x2b, 0x5454 },
+	{ 0x2f, 0x0000 },
+	{ 0x30, 0x5000 },
+	{ 0x3b, 0x0000 },
+	{ 0x3c, 0x006f },
+	{ 0x3d, 0x0000 },
+	{ 0x3e, 0x006f },
+	{ 0x45, 0x6000 },
+	{ 0x4d, 0x0000 },
+	{ 0x4e, 0x0000 },
+	{ 0x4f, 0x0279 },
+	{ 0x50, 0x0000 },
+	{ 0x51, 0x0000 },
+	{ 0x52, 0x0279 },
+	{ 0x53, 0xf000 },
+	{ 0x61, 0x0000 },
+	{ 0x62, 0x0000 },
+	{ 0x63, 0x00c0 },
+	{ 0x64, 0x0000 },
+	{ 0x65, 0x0000 },
+	{ 0x66, 0x0000 },
+	{ 0x70, 0x8000 },
+	{ 0x71, 0x8000 },
+	{ 0x73, 0x1104 },
+	{ 0x74, 0x0c00 },
+	{ 0x75, 0x1400 },
+	{ 0x77, 0x0c00 },
+	{ 0x78, 0x4000 },
+	{ 0x79, 0x0123 },
+	{ 0x80, 0x0000 },
+	{ 0x81, 0x0000 },
+	{ 0x82, 0x0000 },
+	{ 0x83, 0x0800 },
+	{ 0x84, 0x0000 },
+	{ 0x85, 0x0008 },
+	{ 0x89, 0x0000 },
+	{ 0x8e, 0x0004 },
+	{ 0x8f, 0x1100 },
+	{ 0x90, 0x0000 },
+	{ 0x93, 0x2000 },
+	{ 0x94, 0x0200 },
+	{ 0xb0, 0x2080 },
+	{ 0xb1, 0x0000 },
+	{ 0xb4, 0x2206 },
+	{ 0xb5, 0x1f00 },
+	{ 0xb6, 0x0000 },
+	{ 0xbb, 0x0000 },
+	{ 0xbc, 0x0000 },
+	{ 0xbd, 0x0000 },
+	{ 0xbe, 0x0000 },
+	{ 0xbf, 0x0000 },
+	{ 0xc0, 0x0400 },
+	{ 0xc1, 0x0000 },
+	{ 0xc2, 0x0000 },
+	{ 0xcf, 0x0013 },
+	{ 0xd0, 0x0680 },
+	{ 0xd1, 0x1c17 },
+	{ 0xd3, 0xb320 },
+	{ 0xd9, 0x0809 },
+	{ 0xfa, 0x0010 },
+	{ 0xfe, 0x10ec },
+	{ 0xff, 0x6281 },
+};
+
+static bool rt5651_volatile_register(struct device *dev,  unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rt5651_ranges); i++) {
+		if ((reg >= rt5651_ranges[i].window_start &&
+		     reg <= rt5651_ranges[i].window_start +
+		     rt5651_ranges[i].window_len) ||
+		    (reg >= rt5651_ranges[i].range_min &&
+		     reg <= rt5651_ranges[i].range_max)) {
+			return true;
+		}
+	}
+
+	switch (reg) {
+	case RT5651_RESET:
+	case RT5651_PRIV_DATA:
+	case RT5651_EQ_CTRL1:
+	case RT5651_ALC_1:
+	case RT5651_IRQ_CTRL2:
+	case RT5651_INT_IRQ_ST:
+	case RT5651_PGM_REG_ARR1:
+	case RT5651_PGM_REG_ARR3:
+	case RT5651_VENDOR_ID:
+	case RT5651_DEVICE_ID:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rt5651_readable_register(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rt5651_ranges); i++) {
+		if ((reg >= rt5651_ranges[i].window_start &&
+		     reg <= rt5651_ranges[i].window_start +
+		     rt5651_ranges[i].window_len) ||
+		    (reg >= rt5651_ranges[i].range_min &&
+		     reg <= rt5651_ranges[i].range_max)) {
+			return true;
+		}
+	}
+
+	switch (reg) {
+	case RT5651_RESET:
+	case RT5651_VERSION_ID:
+	case RT5651_VENDOR_ID:
+	case RT5651_DEVICE_ID:
+	case RT5651_HP_VOL:
+	case RT5651_LOUT_CTRL1:
+	case RT5651_LOUT_CTRL2:
+	case RT5651_IN1_IN2:
+	case RT5651_IN3:
+	case RT5651_INL1_INR1_VOL:
+	case RT5651_INL2_INR2_VOL:
+	case RT5651_DAC1_DIG_VOL:
+	case RT5651_DAC2_DIG_VOL:
+	case RT5651_DAC2_CTRL:
+	case RT5651_ADC_DIG_VOL:
+	case RT5651_ADC_DATA:
+	case RT5651_ADC_BST_VOL:
+	case RT5651_STO1_ADC_MIXER:
+	case RT5651_STO2_ADC_MIXER:
+	case RT5651_AD_DA_MIXER:
+	case RT5651_STO_DAC_MIXER:
+	case RT5651_DD_MIXER:
+	case RT5651_DIG_INF_DATA:
+	case RT5651_PDM_CTL:
+	case RT5651_REC_L1_MIXER:
+	case RT5651_REC_L2_MIXER:
+	case RT5651_REC_R1_MIXER:
+	case RT5651_REC_R2_MIXER:
+	case RT5651_HPO_MIXER:
+	case RT5651_OUT_L1_MIXER:
+	case RT5651_OUT_L2_MIXER:
+	case RT5651_OUT_L3_MIXER:
+	case RT5651_OUT_R1_MIXER:
+	case RT5651_OUT_R2_MIXER:
+	case RT5651_OUT_R3_MIXER:
+	case RT5651_LOUT_MIXER:
+	case RT5651_PWR_DIG1:
+	case RT5651_PWR_DIG2:
+	case RT5651_PWR_ANLG1:
+	case RT5651_PWR_ANLG2:
+	case RT5651_PWR_MIXER:
+	case RT5651_PWR_VOL:
+	case RT5651_PRIV_INDEX:
+	case RT5651_PRIV_DATA:
+	case RT5651_I2S1_SDP:
+	case RT5651_I2S2_SDP:
+	case RT5651_ADDA_CLK1:
+	case RT5651_ADDA_CLK2:
+	case RT5651_DMIC:
+	case RT5651_TDM_CTL_1:
+	case RT5651_TDM_CTL_2:
+	case RT5651_TDM_CTL_3:
+	case RT5651_GLB_CLK:
+	case RT5651_PLL_CTRL1:
+	case RT5651_PLL_CTRL2:
+	case RT5651_PLL_MODE_1:
+	case RT5651_PLL_MODE_2:
+	case RT5651_PLL_MODE_3:
+	case RT5651_PLL_MODE_4:
+	case RT5651_PLL_MODE_5:
+	case RT5651_PLL_MODE_6:
+	case RT5651_PLL_MODE_7:
+	case RT5651_DEPOP_M1:
+	case RT5651_DEPOP_M2:
+	case RT5651_DEPOP_M3:
+	case RT5651_CHARGE_PUMP:
+	case RT5651_MICBIAS:
+	case RT5651_A_JD_CTL1:
+	case RT5651_EQ_CTRL1:
+	case RT5651_EQ_CTRL2:
+	case RT5651_ALC_1:
+	case RT5651_ALC_2:
+	case RT5651_ALC_3:
+	case RT5651_JD_CTRL1:
+	case RT5651_JD_CTRL2:
+	case RT5651_IRQ_CTRL1:
+	case RT5651_IRQ_CTRL2:
+	case RT5651_INT_IRQ_ST:
+	case RT5651_GPIO_CTRL1:
+	case RT5651_GPIO_CTRL2:
+	case RT5651_GPIO_CTRL3:
+	case RT5651_PGM_REG_ARR1:
+	case RT5651_PGM_REG_ARR2:
+	case RT5651_PGM_REG_ARR3:
+	case RT5651_PGM_REG_ARR4:
+	case RT5651_PGM_REG_ARR5:
+	case RT5651_SCB_FUNC:
+	case RT5651_SCB_CTRL:
+	case RT5651_BASE_BACK:
+	case RT5651_MP3_PLUS1:
+	case RT5651_MP3_PLUS2:
+	case RT5651_ADJ_HPF_CTRL1:
+	case RT5651_ADJ_HPF_CTRL2:
+	case RT5651_HP_CALIB_AMP_DET:
+	case RT5651_HP_CALIB2:
+	case RT5651_SV_ZCD1:
+	case RT5651_SV_ZCD2:
+	case RT5651_D_MISC:
+	case RT5651_DUMMY2:
+	case RT5651_DUMMY3:
+		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 rt5651_data_select[] = {
+	"Normal", "Swap", "left copy to right", "right copy to left"};
+
+static SOC_ENUM_SINGLE_DECL(rt5651_if2_dac_enum, RT5651_DIG_INF_DATA,
+				RT5651_IF2_DAC_SEL_SFT, rt5651_data_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5651_if2_adc_enum, RT5651_DIG_INF_DATA,
+				RT5651_IF2_ADC_SEL_SFT, rt5651_data_select);
+
+static const struct snd_kcontrol_new rt5651_snd_controls[] = {
+	/* Headphone Output Volume */
+	SOC_DOUBLE_TLV("HP Playback Volume", RT5651_HP_VOL,
+		RT5651_L_VOL_SFT, RT5651_R_VOL_SFT, 39, 1, out_vol_tlv),
+	/* OUTPUT Control */
+	SOC_DOUBLE_TLV("OUT Playback Volume", RT5651_LOUT_CTRL1,
+		RT5651_L_VOL_SFT, RT5651_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+	/* DAC Digital Volume */
+	SOC_DOUBLE("DAC2 Playback Switch", RT5651_DAC2_CTRL,
+		RT5651_M_DAC_L2_VOL_SFT, RT5651_M_DAC_R2_VOL_SFT, 1, 1),
+	SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5651_DAC1_DIG_VOL,
+			RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+			175, 0, dac_vol_tlv),
+	SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5651_DAC2_DIG_VOL,
+			RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+			175, 0, dac_vol_tlv),
+	/* IN1/IN2 Control */
+	SOC_SINGLE_TLV("IN1 Boost", RT5651_IN1_IN2,
+		RT5651_BST_SFT1, 8, 0, bst_tlv),
+	SOC_SINGLE_TLV("IN2 Boost", RT5651_IN1_IN2,
+		RT5651_BST_SFT2, 8, 0, bst_tlv),
+	/* INL/INR Volume Control */
+	SOC_DOUBLE_TLV("IN Capture Volume", RT5651_INL1_INR1_VOL,
+			RT5651_INL_VOL_SFT, RT5651_INR_VOL_SFT,
+			31, 1, in_vol_tlv),
+	/* ADC Digital Volume Control */
+	SOC_DOUBLE("ADC Capture Switch", RT5651_ADC_DIG_VOL,
+		RT5651_L_MUTE_SFT, RT5651_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_TLV("ADC Capture Volume", RT5651_ADC_DIG_VOL,
+			RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+			127, 0, adc_vol_tlv),
+	SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5651_ADC_DATA,
+			RT5651_L_VOL_SFT, RT5651_R_VOL_SFT,
+			127, 0, adc_vol_tlv),
+	/* ADC Boost Volume Control */
+	SOC_DOUBLE_TLV("ADC Boost Gain", RT5651_ADC_BST_VOL,
+			RT5651_ADC_L_BST_SFT, RT5651_ADC_R_BST_SFT,
+			3, 0, adc_bst_tlv),
+
+	/* ASRC */
+	SOC_SINGLE("IF1 ASRC Switch", RT5651_PLL_MODE_1,
+		RT5651_STO1_T_SFT, 1, 0),
+	SOC_SINGLE("IF2 ASRC Switch", RT5651_PLL_MODE_1,
+		RT5651_STO2_T_SFT, 1, 0),
+	SOC_SINGLE("DMIC ASRC Switch", RT5651_PLL_MODE_1,
+		RT5651_DMIC_1_M_SFT, 1, 0),
+
+	SOC_ENUM("ADC IF2 Data Switch", rt5651_if2_adc_enum),
+	SOC_ENUM("DAC IF2 Data Switch", rt5651_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 rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	int div[] = {2, 3, 4, 6, 8, 12}, idx = -EINVAL;
+	int i, rate, red, bound, temp;
+
+	rate = rt5651->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, RT5651_DMIC, RT5651_DMIC_CLK_MASK,
+					idx << RT5651_DMIC_CLK_SFT);
+
+	return idx;
+}
+
+static int is_sysclk_from_pll(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int val;
+
+	val = snd_soc_read(source->codec, RT5651_GLB_CLK);
+	val &= RT5651_SCLK_SRC_MASK;
+	if (val == RT5651_SCLK_SRC_PLL1)
+		return 1;
+	else
+		return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5651_sto1_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO1_ADC_MIXER,
+			RT5651_M_STO1_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO1_ADC_MIXER,
+			RT5651_M_STO1_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO1_ADC_MIXER,
+			RT5651_M_STO1_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO1_ADC_MIXER,
+			RT5651_M_STO1_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO2_ADC_MIXER,
+			RT5651_M_STO2_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO2_ADC_MIXER,
+			RT5651_M_STO2_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO2_ADC_MIXER,
+			RT5651_M_STO2_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5651_STO2_ADC_MIXER,
+			RT5651_M_STO2_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5651_AD_DA_MIXER,
+			RT5651_M_ADCMIX_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INF1 Switch", RT5651_AD_DA_MIXER,
+			RT5651_M_IF1_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5651_AD_DA_MIXER,
+			RT5651_M_ADCMIX_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INF1 Switch", RT5651_AD_DA_MIXER,
+			RT5651_M_IF1_DAC_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_STO_DAC_MIXER,
+			RT5651_M_DAC_L1_MIXL_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5651_STO_DAC_MIXER,
+			RT5651_M_DAC_L2_MIXL_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_STO_DAC_MIXER,
+			RT5651_M_DAC_R1_MIXL_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_sto_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_STO_DAC_MIXER,
+			RT5651_M_DAC_R1_MIXR_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5651_STO_DAC_MIXER,
+			RT5651_M_DAC_R2_MIXR_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_STO_DAC_MIXER,
+			RT5651_M_DAC_L1_MIXR_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dd_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_DD_MIXER,
+			RT5651_M_STO_DD_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5651_DD_MIXER,
+			RT5651_M_STO_DD_L2_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5651_DD_MIXER,
+			RT5651_M_STO_DD_R2_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_dd_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_DD_MIXER,
+			RT5651_M_STO_DD_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5651_DD_MIXER,
+			RT5651_M_STO_DD_R2_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5651_DD_MIXER,
+			RT5651_M_STO_DD_L2_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5651_rec_l_mix[] = {
+	SOC_DAPM_SINGLE("INL1 Switch", RT5651_REC_L2_MIXER,
+			RT5651_M_IN1_L_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST3 Switch", RT5651_REC_L2_MIXER,
+			RT5651_M_BST3_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5651_REC_L2_MIXER,
+			RT5651_M_BST2_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5651_REC_L2_MIXER,
+			RT5651_M_BST1_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_rec_r_mix[] = {
+	SOC_DAPM_SINGLE("INR1 Switch", RT5651_REC_R2_MIXER,
+			RT5651_M_IN1_R_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST3 Switch", RT5651_REC_R2_MIXER,
+			RT5651_M_BST3_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5651_REC_R2_MIXER,
+			RT5651_M_BST2_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5651_REC_R2_MIXER,
+			RT5651_M_BST1_RM_R_SFT, 1, 1),
+};
+
+/* Analog Output Mixer */
+
+static const struct snd_kcontrol_new rt5651_out_l_mix[] = {
+	SOC_DAPM_SINGLE("BST1 Switch", RT5651_OUT_L3_MIXER,
+			RT5651_M_BST1_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5651_OUT_L3_MIXER,
+			RT5651_M_BST2_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL1 Switch", RT5651_OUT_L3_MIXER,
+			RT5651_M_IN1_L_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("REC MIXL Switch", RT5651_OUT_L3_MIXER,
+			RT5651_M_RM_L_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_OUT_L3_MIXER,
+			RT5651_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_out_r_mix[] = {
+	SOC_DAPM_SINGLE("BST2 Switch", RT5651_OUT_R3_MIXER,
+			RT5651_M_BST2_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5651_OUT_R3_MIXER,
+			RT5651_M_BST1_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR1 Switch", RT5651_OUT_R3_MIXER,
+			RT5651_M_IN1_R_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("REC MIXR Switch", RT5651_OUT_R3_MIXER,
+			RT5651_M_RM_R_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_OUT_R3_MIXER,
+			RT5651_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_hpo_mix[] = {
+	SOC_DAPM_SINGLE("HPO MIX DAC1 Switch", RT5651_HPO_MIXER,
+			RT5651_M_DAC1_HM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("HPO MIX HPVOL Switch", RT5651_HPO_MIXER,
+			RT5651_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5651_lout_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5651_LOUT_MIXER,
+			RT5651_M_DAC_L1_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5651_LOUT_MIXER,
+			RT5651_M_DAC_R1_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUTVOL L Switch", RT5651_LOUT_MIXER,
+			RT5651_M_OV_L_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUTVOL R Switch", RT5651_LOUT_MIXER,
+			RT5651_M_OV_R_LM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new outvol_l_control =
+	SOC_DAPM_SINGLE("Switch", RT5651_LOUT_CTRL1,
+			RT5651_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new outvol_r_control =
+	SOC_DAPM_SINGLE("Switch", RT5651_LOUT_CTRL1,
+			RT5651_VOL_R_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_l_mute_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_LOUT_CTRL1,
+				    RT5651_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new lout_r_mute_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_LOUT_CTRL1,
+				    RT5651_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpovol_l_control =
+	SOC_DAPM_SINGLE("Switch", RT5651_HP_VOL,
+			RT5651_VOL_L_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpovol_r_control =
+	SOC_DAPM_SINGLE("Switch", RT5651_HP_VOL,
+			RT5651_VOL_R_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpo_l_mute_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_HP_VOL,
+				    RT5651_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hpo_r_mute_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5651_HP_VOL,
+				    RT5651_R_MUTE_SFT, 1, 1);
+
+/* INL/R source */
+static const char * const rt5651_inl_src[] = {"IN2P", "HPOVOLLP"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_inl_enum, RT5651_INL1_INR1_VOL,
+	RT5651_INL_SEL_SFT, rt5651_inl_src);
+
+static const struct snd_kcontrol_new rt5651_inl1_mux =
+	SOC_DAPM_ENUM("INL1 source", rt5651_inl_enum);
+
+static const char * const rt5651_inr1_src[] = {"IN2N", "HPOVOLRP"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_inr1_enum, RT5651_INL1_INR1_VOL,
+	RT5651_INR_SEL_SFT, rt5651_inr1_src);
+
+static const struct snd_kcontrol_new rt5651_inr1_mux =
+	SOC_DAPM_ENUM("INR1 source", rt5651_inr1_enum);
+
+static const char * const rt5651_inl2_src[] = {"IN3P", "OUTVOLLP"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_inl2_enum, RT5651_INL2_INR2_VOL,
+	RT5651_INL_SEL_SFT, rt5651_inl2_src);
+
+static const struct snd_kcontrol_new rt5651_inl2_mux =
+	SOC_DAPM_ENUM("INL2 source", rt5651_inl2_enum);
+
+static const char * const rt5651_inr2_src[] = {"IN3N", "OUTVOLRP"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_inr2_enum, RT5651_INL2_INR2_VOL,
+	RT5651_INR_SEL_SFT, rt5651_inr2_src);
+
+static const struct snd_kcontrol_new rt5651_inr2_mux =
+	SOC_DAPM_ENUM("INR2 source", rt5651_inr2_enum);
+
+
+/* Stereo ADC source */
+static const char * const rt5651_stereo1_adc1_src[] = {"DD MIX", "ADC"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_stereo1_adc1_enum, RT5651_STO1_ADC_MIXER,
+	RT5651_STO1_ADC_1_SRC_SFT, rt5651_stereo1_adc1_src);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_l1_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC L1 source", rt5651_stereo1_adc1_enum);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_r1_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC R1 source", rt5651_stereo1_adc1_enum);
+
+static const char * const rt5651_stereo1_adc2_src[] = {"DMIC", "DD MIX"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_stereo1_adc2_enum, RT5651_STO1_ADC_MIXER,
+	RT5651_STO1_ADC_2_SRC_SFT, rt5651_stereo1_adc2_src);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_l2_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC L2 source", rt5651_stereo1_adc2_enum);
+
+static const struct snd_kcontrol_new rt5651_sto1_adc_r2_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC R2 source", rt5651_stereo1_adc2_enum);
+
+/* Mono ADC source */
+static const char * const rt5651_sto2_adc_l1_src[] = {"DD MIXL", "ADCL"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_sto2_adc_l1_enum, RT5651_STO1_ADC_MIXER,
+	RT5651_STO2_ADC_L1_SRC_SFT, rt5651_sto2_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_l1_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC1 left source", rt5651_sto2_adc_l1_enum);
+
+static const char * const rt5651_sto2_adc_l2_src[] = {"DMIC L", "DD MIXL"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_sto2_adc_l2_enum, RT5651_STO1_ADC_MIXER,
+	RT5651_STO2_ADC_L2_SRC_SFT, rt5651_sto2_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_l2_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC2 left source", rt5651_sto2_adc_l2_enum);
+
+static const char * const rt5651_sto2_adc_r1_src[] = {"DD MIXR", "ADCR"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_sto2_adc_r1_enum, RT5651_STO1_ADC_MIXER,
+	RT5651_STO2_ADC_R1_SRC_SFT, rt5651_sto2_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_r1_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC1 right source", rt5651_sto2_adc_r1_enum);
+
+static const char * const rt5651_sto2_adc_r2_src[] = {"DMIC R", "DD MIXR"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_sto2_adc_r2_enum, RT5651_STO1_ADC_MIXER,
+	RT5651_STO2_ADC_R2_SRC_SFT, rt5651_sto2_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5651_sto2_adc_r2_mux =
+	SOC_DAPM_ENUM("Stereo2 ADC2 right source", rt5651_sto2_adc_r2_enum);
+
+/* DAC2 channel source */
+
+static const char * const rt5651_dac_src[] = {"IF1", "IF2"};
+
+static SOC_ENUM_SINGLE_DECL(rt5651_dac_l2_enum, RT5651_DAC2_CTRL,
+				RT5651_SEL_DAC_L2_SFT, rt5651_dac_src);
+
+static const struct snd_kcontrol_new rt5651_dac_l2_mux =
+	SOC_DAPM_ENUM("DAC2 left channel source", rt5651_dac_l2_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_dac_r2_enum, RT5651_DAC2_CTRL,
+	RT5651_SEL_DAC_R2_SFT, rt5651_dac_src);
+
+static const struct snd_kcontrol_new rt5651_dac_r2_mux =
+	SOC_DAPM_ENUM("DAC2 right channel source", rt5651_dac_r2_enum);
+
+/* IF2_ADC channel source */
+
+static const char * const rt5651_adc_src[] = {"IF1 ADC1", "IF1 ADC2"};
+
+static SOC_ENUM_SINGLE_DECL(rt5651_if2_adc_src_enum, RT5651_DIG_INF_DATA,
+				RT5651_IF2_ADC_SRC_SFT, rt5651_adc_src);
+
+static const struct snd_kcontrol_new rt5651_if2_adc_src_mux =
+	SOC_DAPM_ENUM("IF2 ADC channel source", rt5651_if2_adc_src_enum);
+
+/* PDM select */
+static const char * const rt5651_pdm_sel[] = {"DD MIX", "Stereo DAC MIX"};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_pdm_l_sel_enum, RT5651_PDM_CTL,
+	RT5651_PDM_L_SEL_SFT, rt5651_pdm_sel);
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5651_pdm_r_sel_enum, RT5651_PDM_CTL,
+	RT5651_PDM_R_SEL_SFT, rt5651_pdm_sel);
+
+static const struct snd_kcontrol_new rt5651_pdm_l_mux =
+	SOC_DAPM_ENUM("PDM L select", rt5651_pdm_l_sel_enum);
+
+static const struct snd_kcontrol_new rt5651_pdm_r_mux =
+	SOC_DAPM_ENUM("PDM R select", rt5651_pdm_r_sel_enum);
+
+static int rt5651_amp_power_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* depop parameters */
+		regmap_update_bits(rt5651->regmap, RT5651_PR_BASE +
+			RT5651_CHPUMP_INT_REG1, 0x0700, 0x0200);
+		regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M2,
+			RT5651_DEPOP_MASK, RT5651_DEPOP_MAN);
+		regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M1,
+			RT5651_HP_CP_MASK | RT5651_HP_SG_MASK |
+			RT5651_HP_CB_MASK, RT5651_HP_CP_PU |
+			RT5651_HP_SG_DIS | RT5651_HP_CB_PU);
+		regmap_write(rt5651->regmap, RT5651_PR_BASE +
+				RT5651_HP_DCC_INT1, 0x9f00);
+		/* headphone amp power on */
+		regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG1,
+			RT5651_PWR_FV1 | RT5651_PWR_FV2, 0);
+		regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG1,
+			RT5651_PWR_HA,
+			RT5651_PWR_HA);
+		usleep_range(10000, 15000);
+		regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG1,
+			RT5651_PWR_FV1 | RT5651_PWR_FV2 ,
+			RT5651_PWR_FV1 | RT5651_PWR_FV2);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5651_hp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* headphone unmute sequence */
+		regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M2,
+			RT5651_DEPOP_MASK | RT5651_DIG_DP_MASK,
+			RT5651_DEPOP_AUTO | RT5651_DIG_DP_EN);
+		regmap_update_bits(rt5651->regmap, RT5651_CHARGE_PUMP,
+			RT5651_PM_HP_MASK, RT5651_PM_HP_HV);
+
+		regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M3,
+			RT5651_CP_FQ1_MASK | RT5651_CP_FQ2_MASK |
+			RT5651_CP_FQ3_MASK,
+			(RT5651_CP_FQ_192_KHZ << RT5651_CP_FQ1_SFT) |
+			(RT5651_CP_FQ_12_KHZ << RT5651_CP_FQ2_SFT) |
+			(RT5651_CP_FQ_192_KHZ << RT5651_CP_FQ3_SFT));
+
+		regmap_write(rt5651->regmap, RT5651_PR_BASE +
+			RT5651_MAMP_INT_REG2, 0x1c00);
+		regmap_update_bits(rt5651->regmap, RT5651_DEPOP_M1,
+			RT5651_HP_CP_MASK | RT5651_HP_SG_MASK,
+			RT5651_HP_CP_PD | RT5651_HP_SG_EN);
+		regmap_update_bits(rt5651->regmap, RT5651_PR_BASE +
+			RT5651_CHPUMP_INT_REG1, 0x0700, 0x0400);
+		rt5651->hp_mute = 0;
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		rt5651->hp_mute = 1;
+		usleep_range(70000, 75000);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5651_hp_post_event(struct snd_soc_dapm_widget *w,
+			   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (!rt5651->hp_mute)
+			usleep_range(80000, 85000);
+
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5651_bst1_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+			RT5651_PWR_BST1_OP2, RT5651_PWR_BST1_OP2);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+			RT5651_PWR_BST1_OP2, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5651_bst2_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+			RT5651_PWR_BST2_OP2, RT5651_PWR_BST2_OP2);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+			RT5651_PWR_BST2_OP2, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5651_bst3_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+			RT5651_PWR_BST3_OP2, RT5651_PWR_BST3_OP2);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+			RT5651_PWR_BST3_OP2, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
+	/* ASRC */
+	SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5651_PLL_MODE_2,
+			      15, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5651_PLL_MODE_2,
+			      14, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("STO1 DAC ASRC", 1, RT5651_PLL_MODE_2,
+			      13, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("STO2 DAC ASRC", 1, RT5651_PLL_MODE_2,
+			      12, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC ASRC", 1, RT5651_PLL_MODE_2,
+			      11, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
+			RT5651_PWR_PLL_BIT, 0, NULL, 0),
+	/* Input Side */
+	/* micbias */
+	SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
+			RT5651_PWR_LDO_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MICBIAS("micbias1", RT5651_PWR_ANLG2,
+			RT5651_PWR_MB1_BIT, 0),
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("MIC1"),
+	SND_SOC_DAPM_INPUT("MIC2"),
+	SND_SOC_DAPM_INPUT("MIC3"),
+
+	SND_SOC_DAPM_INPUT("IN1P"),
+	SND_SOC_DAPM_INPUT("IN2P"),
+	SND_SOC_DAPM_INPUT("IN2N"),
+	SND_SOC_DAPM_INPUT("IN3P"),
+	SND_SOC_DAPM_INPUT("DMIC L1"),
+	SND_SOC_DAPM_INPUT("DMIC R1"),
+	SND_SOC_DAPM_SUPPLY("DMIC CLK", RT5651_DMIC, RT5651_DMIC_1_EN_SFT,
+			    0, set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+	/* Boost */
+	SND_SOC_DAPM_PGA_E("BST1", RT5651_PWR_ANLG2,
+		RT5651_PWR_BST1_BIT, 0, NULL, 0, rt5651_bst1_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_E("BST2", RT5651_PWR_ANLG2,
+		RT5651_PWR_BST2_BIT, 0, NULL, 0, rt5651_bst2_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_E("BST3", RT5651_PWR_ANLG2,
+		RT5651_PWR_BST3_BIT, 0, NULL, 0, rt5651_bst3_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	/* Input Volume */
+	SND_SOC_DAPM_PGA("INL1 VOL", RT5651_PWR_VOL,
+			 RT5651_PWR_IN1_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INR1 VOL", RT5651_PWR_VOL,
+			 RT5651_PWR_IN1_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INL2 VOL", RT5651_PWR_VOL,
+			 RT5651_PWR_IN2_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INR2 VOL", RT5651_PWR_VOL,
+			 RT5651_PWR_IN2_R_BIT, 0, NULL, 0),
+	/* IN Mux */
+	SND_SOC_DAPM_MUX("INL1 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inl1_mux),
+	SND_SOC_DAPM_MUX("INR1 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inr1_mux),
+	SND_SOC_DAPM_MUX("INL2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inl2_mux),
+	SND_SOC_DAPM_MUX("INR2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_inr2_mux),
+	/* REC Mixer */
+	SND_SOC_DAPM_MIXER("RECMIXL", RT5651_PWR_MIXER, RT5651_PWR_RM_L_BIT, 0,
+			   rt5651_rec_l_mix, ARRAY_SIZE(rt5651_rec_l_mix)),
+	SND_SOC_DAPM_MIXER("RECMIXR", RT5651_PWR_MIXER, RT5651_PWR_RM_R_BIT, 0,
+			   rt5651_rec_r_mix, ARRAY_SIZE(rt5651_rec_r_mix)),
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_SUPPLY("ADC L Power", RT5651_PWR_DIG1,
+			    RT5651_PWR_ADC_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("ADC R Power", RT5651_PWR_DIG1,
+			    RT5651_PWR_ADC_R_BIT, 0, NULL, 0),
+	/* ADC Mux */
+	SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto1_adc_l2_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto1_adc_r2_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto1_adc_l1_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto1_adc_r1_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto2_adc_l2_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto2_adc_l1_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto2_adc_r1_mux),
+	SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+			 &rt5651_sto2_adc_r2_mux),
+	/* ADC Mixer */
+	SND_SOC_DAPM_SUPPLY("Stereo1 Filter", RT5651_PWR_DIG2,
+			    RT5651_PWR_ADC_STO1_F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Stereo2 Filter", RT5651_PWR_DIG2,
+			    RT5651_PWR_ADC_STO2_F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5651_sto1_adc_l_mix,
+			   ARRAY_SIZE(rt5651_sto1_adc_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5651_sto1_adc_r_mix,
+			   ARRAY_SIZE(rt5651_sto1_adc_r_mix)),
+	SND_SOC_DAPM_MIXER("Stereo2 ADC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5651_sto2_adc_l_mix,
+			   ARRAY_SIZE(rt5651_sto2_adc_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo2 ADC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5651_sto2_adc_r_mix,
+			   ARRAY_SIZE(rt5651_sto2_adc_r_mix)),
+
+	/* Digital Interface */
+	SND_SOC_DAPM_SUPPLY("I2S1", RT5651_PWR_DIG1,
+			    RT5651_PWR_I2S1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("I2S2", RT5651_PWR_DIG1,
+			    RT5651_PWR_I2S2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MUX("IF2 ADC", SND_SOC_NOPM, 0, 0,
+			 &rt5651_if2_adc_src_mux),
+
+	/* Digital Interface Select */
+
+	SND_SOC_DAPM_MUX("PDM L Mux", RT5651_PDM_CTL,
+			 RT5651_M_PDM_L_SFT, 1, &rt5651_pdm_l_mux),
+	SND_SOC_DAPM_MUX("PDM R Mux", RT5651_PDM_CTL,
+			 RT5651_M_PDM_R_SFT, 1, &rt5651_pdm_r_mux),
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+	/* Audio DSP */
+	SND_SOC_DAPM_PGA("Audio DSP", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Output Side */
+	/* DAC mixer before sound effect  */
+	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5651_dac_l_mix, ARRAY_SIZE(rt5651_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5651_dac_r_mix, ARRAY_SIZE(rt5651_dac_r_mix)),
+
+	/* DAC2 channel Mux */
+	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_dac_l2_mux),
+	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5651_dac_r2_mux),
+	SND_SOC_DAPM_PGA("DAC L2 Volume", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DAC R2 Volume", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("Stero1 DAC Power", RT5651_PWR_DIG2,
+			    RT5651_PWR_DAC_STO1_F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Stero2 DAC Power", RT5651_PWR_DIG2,
+			    RT5651_PWR_DAC_STO2_F_BIT, 0, NULL, 0),
+	/* DAC Mixer */
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5651_sto_dac_l_mix,
+			   ARRAY_SIZE(rt5651_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5651_sto_dac_r_mix,
+			   ARRAY_SIZE(rt5651_sto_dac_r_mix)),
+	SND_SOC_DAPM_MIXER("DD MIXL", SND_SOC_NOPM, 0, 0,
+			   rt5651_dd_dac_l_mix,
+			   ARRAY_SIZE(rt5651_dd_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("DD MIXR", SND_SOC_NOPM, 0, 0,
+			   rt5651_dd_dac_r_mix,
+			   ARRAY_SIZE(rt5651_dd_dac_r_mix)),
+
+	/* DACs */
+	SND_SOC_DAPM_DAC("DAC L1", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_DAC("DAC R1", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_SUPPLY("DAC L1 Power", RT5651_PWR_DIG1,
+			    RT5651_PWR_DAC_L1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DAC R1 Power", RT5651_PWR_DIG1,
+			    RT5651_PWR_DAC_R1_BIT, 0, NULL, 0),
+	/* OUT Mixer */
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5651_PWR_MIXER, RT5651_PWR_OM_L_BIT,
+			   0, rt5651_out_l_mix, ARRAY_SIZE(rt5651_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5651_PWR_MIXER, RT5651_PWR_OM_R_BIT,
+			   0, rt5651_out_r_mix, ARRAY_SIZE(rt5651_out_r_mix)),
+	/* Ouput Volume */
+	SND_SOC_DAPM_SWITCH("OUTVOL L", RT5651_PWR_VOL,
+			    RT5651_PWR_OV_L_BIT, 0, &outvol_l_control),
+	SND_SOC_DAPM_SWITCH("OUTVOL R", RT5651_PWR_VOL,
+			    RT5651_PWR_OV_R_BIT, 0, &outvol_r_control),
+	SND_SOC_DAPM_SWITCH("HPOVOL L", RT5651_PWR_VOL,
+			    RT5651_PWR_HV_L_BIT, 0, &hpovol_l_control),
+	SND_SOC_DAPM_SWITCH("HPOVOL R", RT5651_PWR_VOL,
+			    RT5651_PWR_HV_R_BIT, 0, &hpovol_r_control),
+	SND_SOC_DAPM_PGA("INL1", RT5651_PWR_VOL,
+			 RT5651_PWR_IN1_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INR1", RT5651_PWR_VOL,
+			 RT5651_PWR_IN1_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INL2", RT5651_PWR_VOL,
+			 RT5651_PWR_IN2_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INR2", RT5651_PWR_VOL,
+			 RT5651_PWR_IN2_R_BIT, 0, NULL, 0),
+	/* HPO/LOUT/Mono Mixer */
+	SND_SOC_DAPM_MIXER("HPOL MIX", SND_SOC_NOPM, 0, 0,
+			   rt5651_hpo_mix, ARRAY_SIZE(rt5651_hpo_mix)),
+	SND_SOC_DAPM_MIXER("HPOR MIX", SND_SOC_NOPM, 0, 0,
+			   rt5651_hpo_mix, ARRAY_SIZE(rt5651_hpo_mix)),
+	SND_SOC_DAPM_SUPPLY("HP L Amp", RT5651_PWR_ANLG1,
+			    RT5651_PWR_HP_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HP R Amp", RT5651_PWR_ANLG1,
+			    RT5651_PWR_HP_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("LOUT MIX", RT5651_PWR_ANLG1, RT5651_PWR_LM_BIT, 0,
+			   rt5651_lout_mix, ARRAY_SIZE(rt5651_lout_mix)),
+
+	SND_SOC_DAPM_SUPPLY("Amp Power", RT5651_PWR_ANLG1,
+			    RT5651_PWR_HA_BIT, 0, rt5651_amp_power_event,
+			    SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5651_hp_event,
+			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SWITCH("HPO L Playback", SND_SOC_NOPM, 0, 0,
+			    &hpo_l_mute_control),
+	SND_SOC_DAPM_SWITCH("HPO R Playback", SND_SOC_NOPM, 0, 0,
+			    &hpo_r_mute_control),
+	SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0,
+			    &lout_l_mute_control),
+	SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0,
+			    &lout_r_mute_control),
+	SND_SOC_DAPM_POST("HP Post", rt5651_hp_post_event),
+
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+	SND_SOC_DAPM_OUTPUT("LOUTL"),
+	SND_SOC_DAPM_OUTPUT("LOUTR"),
+	SND_SOC_DAPM_OUTPUT("PDML"),
+	SND_SOC_DAPM_OUTPUT("PDMR"),
+};
+
+static const struct snd_soc_dapm_route rt5651_dapm_routes[] = {
+	{"Stero1 DAC Power", NULL, "STO1 DAC ASRC"},
+	{"Stero2 DAC Power", NULL, "STO2 DAC ASRC"},
+	{"I2S1", NULL, "I2S1 ASRC"},
+	{"I2S2", NULL, "I2S2 ASRC"},
+
+	{"IN1P", NULL, "LDO"},
+	{"IN2P", NULL, "LDO"},
+	{"IN3P", NULL, "LDO"},
+
+	{"IN1P", NULL, "MIC1"},
+	{"IN2P", NULL, "MIC2"},
+	{"IN2N", NULL, "MIC2"},
+	{"IN3P", NULL, "MIC3"},
+
+	{"BST1", NULL, "IN1P"},
+	{"BST2", NULL, "IN2P"},
+	{"BST2", NULL, "IN2N"},
+	{"BST3", NULL, "IN3P"},
+
+	{"INL1 VOL", NULL, "IN2P"},
+	{"INR1 VOL", NULL, "IN2N"},
+
+	{"RECMIXL", "INL1 Switch", "INL1 VOL"},
+	{"RECMIXL", "BST3 Switch", "BST3"},
+	{"RECMIXL", "BST2 Switch", "BST2"},
+	{"RECMIXL", "BST1 Switch", "BST1"},
+
+	{"RECMIXR", "INR1 Switch", "INR1 VOL"},
+	{"RECMIXR", "BST3 Switch", "BST3"},
+	{"RECMIXR", "BST2 Switch", "BST2"},
+	{"RECMIXR", "BST1 Switch", "BST1"},
+
+	{"ADC L", NULL, "RECMIXL"},
+	{"ADC L", NULL, "ADC L Power"},
+	{"ADC R", NULL, "RECMIXR"},
+	{"ADC R", NULL, "ADC R Power"},
+
+	{"DMIC L1", NULL, "DMIC CLK"},
+	{"DMIC R1", NULL, "DMIC CLK"},
+
+	{"Stereo1 ADC L2 Mux", "DMIC", "DMIC L1"},
+	{"Stereo1 ADC L2 Mux", "DD MIX", "DD MIXL"},
+	{"Stereo1 ADC L1 Mux", "ADC", "ADC L"},
+	{"Stereo1 ADC L1 Mux", "DD MIX", "DD MIXL"},
+
+	{"Stereo1 ADC R1 Mux", "ADC", "ADC R"},
+	{"Stereo1 ADC R1 Mux", "DD MIX", "DD MIXR"},
+	{"Stereo1 ADC R2 Mux", "DMIC", "DMIC R1"},
+	{"Stereo1 ADC R2 Mux", "DD MIX", "DD MIXR"},
+
+	{"Stereo2 ADC L2 Mux", "DMIC L", "DMIC L1"},
+	{"Stereo2 ADC L2 Mux", "DD MIXL", "DD MIXL"},
+	{"Stereo2 ADC L1 Mux", "DD MIXL", "DD MIXL"},
+	{"Stereo2 ADC L1 Mux", "ADCL", "ADC L"},
+
+	{"Stereo2 ADC R1 Mux", "DD MIXR", "DD MIXR"},
+	{"Stereo2 ADC R1 Mux", "ADCR", "ADC R"},
+	{"Stereo2 ADC R2 Mux", "DMIC R", "DMIC R1"},
+	{"Stereo2 ADC R2 Mux", "DD MIXR", "DD MIXR"},
+
+	{"Stereo1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux"},
+	{"Stereo1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux"},
+	{"Stereo1 ADC MIXL", NULL, "Stereo1 Filter"},
+	{"Stereo1 Filter", NULL, "PLL1", is_sysclk_from_pll},
+	{"Stereo1 Filter", NULL, "ADC ASRC"},
+
+	{"Stereo1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux"},
+	{"Stereo1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux"},
+	{"Stereo1 ADC MIXR", NULL, "Stereo1 Filter"},
+
+	{"Stereo2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux"},
+	{"Stereo2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux"},
+	{"Stereo2 ADC MIXL", NULL, "Stereo2 Filter"},
+	{"Stereo2 Filter", NULL, "PLL1", is_sysclk_from_pll},
+	{"Stereo2 Filter", NULL, "ADC ASRC"},
+
+	{"Stereo2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux"},
+	{"Stereo2 ADC MIXR", "ADC2 Switch", "Stereo2 ADC R2 Mux"},
+	{"Stereo2 ADC MIXR", NULL, "Stereo2 Filter"},
+
+	{"IF1 ADC2", NULL, "Stereo2 ADC MIXL"},
+	{"IF1 ADC2", NULL, "Stereo2 ADC MIXR"},
+	{"IF1 ADC1", NULL, "Stereo1 ADC MIXL"},
+	{"IF1 ADC1", NULL, "Stereo1 ADC MIXR"},
+
+	{"IF1 ADC1", NULL, "I2S1"},
+
+	{"IF2 ADC", "IF1 ADC1", "IF1 ADC1"},
+	{"IF2 ADC", "IF1 ADC2", "IF1 ADC2"},
+	{"IF2 ADC", NULL, "I2S2"},
+
+	{"AIF1TX", NULL, "IF1 ADC1"},
+	{"AIF1TX", NULL, "IF1 ADC2"},
+	{"AIF2TX", NULL, "IF2 ADC"},
+
+	{"IF1 DAC", NULL, "AIF1RX"},
+	{"IF1 DAC", NULL, "I2S1"},
+	{"IF2 DAC", NULL, "AIF2RX"},
+	{"IF2 DAC", NULL, "I2S2"},
+
+	{"IF1 DAC1 L", NULL, "IF1 DAC"},
+	{"IF1 DAC1 R", NULL, "IF1 DAC"},
+	{"IF1 DAC2 L", NULL, "IF1 DAC"},
+	{"IF1 DAC2 R", NULL, "IF1 DAC"},
+	{"IF2 DAC L", NULL, "IF2 DAC"},
+	{"IF2 DAC R", NULL, "IF2 DAC"},
+
+	{"DAC MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL"},
+	{"DAC MIXL", "INF1 Switch", "IF1 DAC1 L"},
+	{"DAC MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR"},
+	{"DAC MIXR", "INF1 Switch", "IF1 DAC1 R"},
+
+	{"Audio DSP", NULL, "DAC MIXL"},
+	{"Audio DSP", NULL, "DAC MIXR"},
+
+	{"DAC L2 Mux", "IF1", "IF1 DAC2 L"},
+	{"DAC L2 Mux", "IF2", "IF2 DAC L"},
+	{"DAC L2 Volume", NULL, "DAC L2 Mux"},
+
+	{"DAC R2 Mux", "IF1", "IF1 DAC2 R"},
+	{"DAC R2 Mux", "IF2", "IF2 DAC R"},
+	{"DAC R2 Volume", NULL, "DAC R2 Mux"},
+
+	{"Stereo DAC MIXL", "DAC L1 Switch", "Audio DSP"},
+	{"Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume"},
+	{"Stereo DAC MIXL", "DAC R1 Switch", "DAC MIXR"},
+	{"Stereo DAC MIXL", NULL, "Stero1 DAC Power"},
+	{"Stereo DAC MIXL", NULL, "Stero2 DAC Power"},
+	{"Stereo DAC MIXR", "DAC R1 Switch", "Audio DSP"},
+	{"Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume"},
+	{"Stereo DAC MIXR", "DAC L1 Switch", "DAC MIXL"},
+	{"Stereo DAC MIXR", NULL, "Stero1 DAC Power"},
+	{"Stereo DAC MIXR", NULL, "Stero2 DAC Power"},
+
+	{"PDM L Mux", "Stereo DAC MIX", "Stereo DAC MIXL"},
+	{"PDM L Mux", "DD MIX", "DAC MIXL"},
+	{"PDM R Mux", "Stereo DAC MIX", "Stereo DAC MIXR"},
+	{"PDM R Mux", "DD MIX", "DAC MIXR"},
+
+	{"DAC L1", NULL, "Stereo DAC MIXL"},
+	{"DAC L1", NULL, "PLL1", is_sysclk_from_pll},
+	{"DAC L1", NULL, "DAC L1 Power"},
+	{"DAC R1", NULL, "Stereo DAC MIXR"},
+	{"DAC R1", NULL, "PLL1", is_sysclk_from_pll},
+	{"DAC R1", NULL, "DAC R1 Power"},
+
+	{"DD MIXL", "DAC L1 Switch", "DAC MIXL"},
+	{"DD MIXL", "DAC L2 Switch", "DAC L2 Volume"},
+	{"DD MIXL", "DAC R2 Switch", "DAC R2 Volume"},
+	{"DD MIXL", NULL, "Stero2 DAC Power"},
+
+	{"DD MIXR", "DAC R1 Switch", "DAC MIXR"},
+	{"DD MIXR", "DAC R2 Switch", "DAC R2 Volume"},
+	{"DD MIXR", "DAC L2 Switch", "DAC L2 Volume"},
+	{"DD MIXR", NULL, "Stero2 DAC Power"},
+
+	{"OUT MIXL", "BST1 Switch", "BST1"},
+	{"OUT MIXL", "BST2 Switch", "BST2"},
+	{"OUT MIXL", "INL1 Switch", "INL1 VOL"},
+	{"OUT MIXL", "REC MIXL Switch", "RECMIXL"},
+	{"OUT MIXL", "DAC L1 Switch", "DAC L1"},
+
+	{"OUT MIXR", "BST2 Switch", "BST2"},
+	{"OUT MIXR", "BST1 Switch", "BST1"},
+	{"OUT MIXR", "INR1 Switch", "INR1 VOL"},
+	{"OUT MIXR", "REC MIXR Switch", "RECMIXR"},
+	{"OUT MIXR", "DAC R1 Switch", "DAC R1"},
+
+	{"HPOVOL L", "Switch", "OUT MIXL"},
+	{"HPOVOL R", "Switch", "OUT MIXR"},
+	{"OUTVOL L", "Switch", "OUT MIXL"},
+	{"OUTVOL R", "Switch", "OUT MIXR"},
+
+	{"HPOL MIX", "HPO MIX DAC1 Switch", "DAC L1"},
+	{"HPOL MIX", "HPO MIX HPVOL Switch", "HPOVOL L"},
+	{"HPOL MIX", NULL, "HP L Amp"},
+	{"HPOR MIX", "HPO MIX DAC1 Switch", "DAC R1"},
+	{"HPOR MIX", "HPO MIX HPVOL Switch", "HPOVOL R"},
+	{"HPOR MIX", NULL, "HP R Amp"},
+
+	{"LOUT MIX", "DAC L1 Switch", "DAC L1"},
+	{"LOUT MIX", "DAC R1 Switch", "DAC R1"},
+	{"LOUT MIX", "OUTVOL L Switch", "OUTVOL L"},
+	{"LOUT MIX", "OUTVOL R Switch", "OUTVOL R"},
+
+	{"HP Amp", NULL, "HPOL MIX"},
+	{"HP Amp", NULL, "HPOR MIX"},
+	{"HP Amp", NULL, "Amp Power"},
+	{"HPO L Playback", "Switch", "HP Amp"},
+	{"HPO R Playback", "Switch", "HP Amp"},
+	{"HPOL", NULL, "HPO L Playback"},
+	{"HPOR", NULL, "HPO R Playback"},
+
+	{"LOUT L Playback", "Switch", "LOUT MIX"},
+	{"LOUT R Playback", "Switch", "LOUT MIX"},
+	{"LOUTL", NULL, "LOUT L Playback"},
+	{"LOUTL", NULL, "Amp Power"},
+	{"LOUTR", NULL, "LOUT R Playback"},
+	{"LOUTR", NULL, "Amp Power"},
+
+	{"PDML", NULL, "PDM L Mux"},
+	{"PDMR", NULL, "PDM R Mux"},
+};
+
+static int get_clk_info(int sclk, int rate)
+{
+	int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
+
+	if (sclk <= 0 || rate <= 0)
+		return -EINVAL;
+
+	rate = rate << 8;
+	for (i = 0; i < ARRAY_SIZE(pd); i++)
+		if (sclk == rate * pd[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int rt5651_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val_len = 0, val_clk, mask_clk;
+	int pre_div, bclk_ms, frame_size;
+
+	rt5651->lrck[dai->id] = params_rate(params);
+	pre_div = get_clk_info(rt5651->sysclk, rt5651->lrck[dai->id]);
+
+	if (pre_div < 0) {
+		dev_err(codec->dev, "Unsupported clock setting\n");
+		return -EINVAL;
+	}
+	frame_size = snd_soc_params_to_frame_size(params);
+	if (frame_size < 0) {
+		dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+		return -EINVAL;
+	}
+	bclk_ms = frame_size > 32 ? 1 : 0;
+	rt5651->bclk[dai->id] = rt5651->lrck[dai->id] * (32 << bclk_ms);
+
+	dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+		rt5651->bclk[dai->id], rt5651->lrck[dai->id]);
+	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+				bclk_ms, pre_div, dai->id);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		val_len |= RT5651_I2S_DL_20;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		val_len |= RT5651_I2S_DL_24;
+		break;
+	case SNDRV_PCM_FORMAT_S8:
+		val_len |= RT5651_I2S_DL_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (dai->id) {
+	case RT5651_AIF1:
+		mask_clk = RT5651_I2S_PD1_MASK;
+		val_clk = pre_div << RT5651_I2S_PD1_SFT;
+		snd_soc_update_bits(codec, RT5651_I2S1_SDP,
+			RT5651_I2S_DL_MASK, val_len);
+		snd_soc_update_bits(codec, RT5651_ADDA_CLK1, mask_clk, val_clk);
+		break;
+	case RT5651_AIF2:
+		mask_clk = RT5651_I2S_BCLK_MS2_MASK | RT5651_I2S_PD2_MASK;
+		val_clk = pre_div << RT5651_I2S_PD2_SFT;
+		snd_soc_update_bits(codec, RT5651_I2S2_SDP,
+			RT5651_I2S_DL_MASK, val_len);
+		snd_soc_update_bits(codec, RT5651_ADDA_CLK1, mask_clk, val_clk);
+		break;
+	default:
+		dev_err(codec->dev, "Wrong dai->id: %d\n", dai->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rt5651_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		rt5651->master[dai->id] = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		reg_val |= RT5651_I2S_MS_S;
+		rt5651->master[dai->id] = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		reg_val |= RT5651_I2S_BP_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		reg_val |= RT5651_I2S_DF_LEFT;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		reg_val |= RT5651_I2S_DF_PCM_A;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		reg_val |= RT5651_I2S_DF_PCM_B;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (dai->id) {
+	case RT5651_AIF1:
+		snd_soc_update_bits(codec, RT5651_I2S1_SDP,
+			RT5651_I2S_MS_MASK | RT5651_I2S_BP_MASK |
+			RT5651_I2S_DF_MASK, reg_val);
+		break;
+	case RT5651_AIF2:
+		snd_soc_update_bits(codec, RT5651_I2S2_SDP,
+			RT5651_I2S_MS_MASK | RT5651_I2S_BP_MASK |
+			RT5651_I2S_DF_MASK, reg_val);
+		break;
+	default:
+		dev_err(codec->dev, "Wrong dai->id: %d\n", dai->id);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int rt5651_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val = 0;
+
+	if (freq == rt5651->sysclk && clk_id == rt5651->sysclk_src)
+		return 0;
+
+	switch (clk_id) {
+	case RT5651_SCLK_S_MCLK:
+		reg_val |= RT5651_SCLK_SRC_MCLK;
+		break;
+	case RT5651_SCLK_S_PLL1:
+		reg_val |= RT5651_SCLK_SRC_PLL1;
+		break;
+	case RT5651_SCLK_S_RCCLK:
+		reg_val |= RT5651_SCLK_SRC_RCCLK;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+		return -EINVAL;
+	}
+	snd_soc_update_bits(codec, RT5651_GLB_CLK,
+		RT5651_SCLK_SRC_MASK, reg_val);
+	rt5651->sysclk = freq;
+	rt5651->sysclk_src = clk_id;
+
+	dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+	return 0;
+}
+
+/**
+ * rt5651_pll_calc - Calcualte PLL M/N/K code.
+ * @freq_in: external clock provided to codec.
+ * @freq_out: target clock which codec works on.
+ * @pll_code: Pointer to structure with M, N, K and bypass flag.
+ *
+ * Calcualte M/N/K code to configure PLL for codec. And K is assigned to 2
+ * which make calculation more efficiently.
+ *
+ * Returns 0 for success or negative error code.
+ */
+static int rt5651_pll_calc(const unsigned int freq_in,
+	const unsigned int freq_out, struct rt5651_pll_code *pll_code)
+{
+	int max_n = RT5651_PLL_N_MAX, max_m = RT5651_PLL_M_MAX;
+	int n = 0, m = 0, red, n_t, m_t, in_t, out_t;
+	int red_t = abs(freq_out - freq_in);
+	bool bypass = false;
+
+	if (RT5651_PLL_INP_MAX < freq_in || RT5651_PLL_INP_MIN > freq_in)
+		return -EINVAL;
+
+	for (n_t = 0; n_t <= max_n; n_t++) {
+		in_t = (freq_in >> 1) + (freq_in >> 2) * n_t;
+		if (in_t < 0)
+			continue;
+		if (in_t == freq_out) {
+			bypass = true;
+			n = n_t;
+			goto code_find;
+		}
+		for (m_t = 0; m_t <= max_m; m_t++) {
+			out_t = in_t / (m_t + 2);
+			red = abs(out_t - freq_out);
+			if (red < red_t) {
+				n = n_t;
+				m = m_t;
+				if (red == 0)
+					goto code_find;
+				red_t = red;
+			}
+		}
+	}
+	pr_debug("Only get approximation about PLL\n");
+
+code_find:
+	pll_code->m_bp = bypass;
+	pll_code->m_code = m;
+	pll_code->n_code = n;
+	pll_code->k_code = 2;
+	return 0;
+}
+
+static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+			unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	struct rt5651_pll_code *pll_code = &rt5651->pll_code;
+	int ret;
+
+	if (source == rt5651->pll_src && freq_in == rt5651->pll_in &&
+	    freq_out == rt5651->pll_out)
+		return 0;
+
+	if (!freq_in || !freq_out) {
+		dev_dbg(codec->dev, "PLL disabled\n");
+
+		rt5651->pll_in = 0;
+		rt5651->pll_out = 0;
+		snd_soc_update_bits(codec, RT5651_GLB_CLK,
+			RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_MCLK);
+		return 0;
+	}
+
+	switch (source) {
+	case RT5651_PLL1_S_MCLK:
+		snd_soc_update_bits(codec, RT5651_GLB_CLK,
+			RT5651_PLL1_SRC_MASK, RT5651_PLL1_SRC_MCLK);
+		break;
+	case RT5651_PLL1_S_BCLK1:
+		snd_soc_update_bits(codec, RT5651_GLB_CLK,
+				RT5651_PLL1_SRC_MASK, RT5651_PLL1_SRC_BCLK1);
+		break;
+	case RT5651_PLL1_S_BCLK2:
+			snd_soc_update_bits(codec, RT5651_GLB_CLK,
+				RT5651_PLL1_SRC_MASK, RT5651_PLL1_SRC_BCLK2);
+		break;
+	default:
+		dev_err(codec->dev, "Unknown PLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	ret = rt5651_pll_calc(freq_in, freq_out, pll_code);
+	if (ret < 0) {
+		dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+		return ret;
+	}
+
+	dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code->m_bp,
+		(pll_code->m_bp ? 0 : pll_code->m_code), pll_code->n_code);
+
+	snd_soc_write(codec, RT5651_PLL_CTRL1,
+		pll_code->n_code << RT5651_PLL_N_SFT | pll_code->k_code);
+	snd_soc_write(codec, RT5651_PLL_CTRL2,
+		(pll_code->m_bp ? 0 : pll_code->m_code) << RT5651_PLL_M_SFT |
+		pll_code->m_bp << RT5651_PLL_M_BP_SFT);
+
+	rt5651->pll_in = freq_in;
+	rt5651->pll_out = freq_out;
+	rt5651->pll_src = source;
+
+	return 0;
+}
+
+static int rt5651_set_bias_level(struct snd_soc_codec *codec,
+			enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_PREPARE:
+		if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) {
+			snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+				RT5651_PWR_VREF1 | RT5651_PWR_MB |
+				RT5651_PWR_BG | RT5651_PWR_VREF2,
+				RT5651_PWR_VREF1 | RT5651_PWR_MB |
+				RT5651_PWR_BG | RT5651_PWR_VREF2);
+			usleep_range(10000, 15000);
+			snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+				RT5651_PWR_FV1 | RT5651_PWR_FV2,
+				RT5651_PWR_FV1 | RT5651_PWR_FV2);
+			snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+				RT5651_PWR_LDO_DVO_MASK,
+				RT5651_PWR_LDO_DVO_1_2V);
+			snd_soc_update_bits(codec, RT5651_D_MISC, 0x1, 0x1);
+			if (snd_soc_read(codec, RT5651_PLL_MODE_1) & 0x9200)
+				snd_soc_update_bits(codec, RT5651_D_MISC,
+						    0xc00, 0xc00);
+		}
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_write(codec, RT5651_D_MISC, 0x0010);
+		snd_soc_write(codec, RT5651_PWR_DIG1, 0x0000);
+		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
+		snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
+		snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
+		snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+		snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		break;
+
+	default:
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int rt5651_probe(struct snd_soc_codec *codec)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->codec = codec;
+
+	snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+		RT5651_PWR_VREF1 | RT5651_PWR_MB |
+		RT5651_PWR_BG | RT5651_PWR_VREF2,
+		RT5651_PWR_VREF1 | RT5651_PWR_MB |
+		RT5651_PWR_BG | RT5651_PWR_VREF2);
+	usleep_range(10000, 15000);
+	snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
+		RT5651_PWR_FV1 | RT5651_PWR_FV2,
+		RT5651_PWR_FV1 | RT5651_PWR_FV2);
+
+	rt5651_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5651_suspend(struct snd_soc_codec *codec)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt5651->regmap, true);
+	regcache_mark_dirty(rt5651->regmap);
+	return 0;
+}
+
+static int rt5651_resume(struct snd_soc_codec *codec)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt5651->regmap, false);
+	snd_soc_cache_sync(codec);
+
+	return 0;
+}
+#else
+#define rt5651_suspend NULL
+#define rt5651_resume NULL
+#endif
+
+#define RT5651_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5651_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+struct snd_soc_dai_ops rt5651_aif_dai_ops = {
+	.hw_params = rt5651_hw_params,
+	.set_fmt = rt5651_set_dai_fmt,
+	.set_sysclk = rt5651_set_dai_sysclk,
+	.set_pll = rt5651_set_dai_pll,
+};
+
+struct snd_soc_dai_driver rt5651_dai[] = {
+	{
+		.name = "rt5651-aif1",
+		.id = RT5651_AIF1,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5651_STEREO_RATES,
+			.formats = RT5651_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5651_STEREO_RATES,
+			.formats = RT5651_FORMATS,
+		},
+		.ops = &rt5651_aif_dai_ops,
+	},
+	{
+		.name = "rt5651-aif2",
+		.id = RT5651_AIF2,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5651_STEREO_RATES,
+			.formats = RT5651_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5651_STEREO_RATES,
+			.formats = RT5651_FORMATS,
+		},
+		.ops = &rt5651_aif_dai_ops,
+	},
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
+	.probe = rt5651_probe,
+	.suspend = rt5651_suspend,
+	.resume = rt5651_resume,
+	.set_bias_level = rt5651_set_bias_level,
+	.idle_bias_off = true,
+	.controls = rt5651_snd_controls,
+	.num_controls = ARRAY_SIZE(rt5651_snd_controls),
+	.dapm_widgets = rt5651_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rt5651_dapm_widgets),
+	.dapm_routes = rt5651_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rt5651_dapm_routes),
+};
+
+static const struct regmap_config rt5651_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = RT5651_DEVICE_ID + 1 + (ARRAY_SIZE(rt5651_ranges) *
+					       RT5651_PR_SPACING),
+	.volatile_reg = rt5651_volatile_register,
+	.readable_reg = rt5651_readable_register,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = rt5651_reg,
+	.num_reg_defaults = ARRAY_SIZE(rt5651_reg),
+	.ranges = rt5651_ranges,
+	.num_ranges = ARRAY_SIZE(rt5651_ranges),
+};
+
+static const struct i2c_device_id rt5651_i2c_id[] = {
+	{ "rt5651", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
+
+static int rt5651_i2c_probe(struct i2c_client *i2c,
+		    const struct i2c_device_id *id)
+{
+	struct rt5651_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct rt5651_priv *rt5651;
+	int ret;
+
+	rt5651 = devm_kzalloc(&i2c->dev, sizeof(*rt5651),
+				GFP_KERNEL);
+	if (NULL == rt5651)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, rt5651);
+
+	if (pdata)
+		rt5651->pdata = *pdata;
+
+	rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
+	if (IS_ERR(rt5651->regmap)) {
+		ret = PTR_ERR(rt5651->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	regmap_read(rt5651->regmap, RT5651_DEVICE_ID, &ret);
+	if (ret != RT5651_DEVICE_ID_VALUE) {
+		dev_err(&i2c->dev,
+			"Device with ID register %x is not rt5651\n", ret);
+		return -ENODEV;
+	}
+
+	regmap_write(rt5651->regmap, RT5651_RESET, 0);
+
+	ret = regmap_register_patch(rt5651->regmap, init_list,
+				    ARRAY_SIZE(init_list));
+	if (ret != 0)
+		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+	if (rt5651->pdata.in2_diff)
+		regmap_update_bits(rt5651->regmap, RT5651_IN1_IN2,
+					RT5651_IN_DF2, RT5651_IN_DF2);
+
+	if (rt5651->pdata.dmic_en)
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				RT5651_GP2_PIN_MASK, RT5651_GP2_PIN_DMIC1_SCL);
+
+	rt5651->hp_mute = 1;
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
+				rt5651_dai, ARRAY_SIZE(rt5651_dai));
+
+	return ret;
+}
+
+static int rt5651_i2c_remove(struct i2c_client *i2c)
+{
+	snd_soc_unregister_codec(&i2c->dev);
+
+	return 0;
+}
+
+struct i2c_driver rt5651_i2c_driver = {
+	.driver = {
+		.name = "rt5651",
+		.owner = THIS_MODULE,
+	},
+	.probe = rt5651_i2c_probe,
+	.remove   = rt5651_i2c_remove,
+	.id_table = rt5651_i2c_id,
+};
+module_i2c_driver(rt5651_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5651 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
new file mode 100644
index 0000000000000..a28bd0c3d613f
--- /dev/null
+++ b/sound/soc/codecs/rt5651.h
@@ -0,0 +1,2081 @@
+/*
+ * rt5651.h  --  RT5651 ALSA SoC audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ * Author: Johnny Hsu <johnnyhsu@realtek.com>
+ *
+ * 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 __RT5651_H__
+#define __RT5651_H__
+
+#include <sound/rt5651.h>
+
+/* Info */
+#define RT5651_RESET				0x00
+#define RT5651_VERSION_ID			0xfd
+#define RT5651_VENDOR_ID			0xfe
+#define RT5651_DEVICE_ID			0xff
+/*  I/O - Output */
+#define RT5651_HP_VOL				0x02
+#define RT5651_LOUT_CTRL1			0x03
+#define RT5651_LOUT_CTRL2			0x05
+/* I/O - Input */
+#define RT5651_IN1_IN2				0x0d
+#define RT5651_IN3				0x0e
+#define RT5651_INL1_INR1_VOL			0x0f
+#define RT5651_INL2_INR2_VOL			0x10
+/* I/O - ADC/DAC/DMIC */
+#define RT5651_DAC1_DIG_VOL			0x19
+#define RT5651_DAC2_DIG_VOL			0x1a
+#define RT5651_DAC2_CTRL			0x1b
+#define RT5651_ADC_DIG_VOL			0x1c
+#define RT5651_ADC_DATA				0x1d
+#define RT5651_ADC_BST_VOL			0x1e
+/* Mixer - D-D */
+#define RT5651_STO1_ADC_MIXER			0x27
+#define RT5651_STO2_ADC_MIXER			0x28
+#define RT5651_AD_DA_MIXER			0x29
+#define RT5651_STO_DAC_MIXER			0x2a
+#define RT5651_DD_MIXER				0x2b
+#define RT5651_DIG_INF_DATA			0x2f
+/* PDM */
+#define RT5651_PDM_CTL				0x30
+#define RT5651_PDM_I2C_CTL1			0x31
+#define RT5651_PDM_I2C_CTL2			0x32
+#define RT5651_PDM_I2C_DATA_W			0x33
+#define RT5651_PDM_I2C_DATA_R			0x34
+/* Mixer - ADC */
+#define RT5651_REC_L1_MIXER			0x3b
+#define RT5651_REC_L2_MIXER			0x3c
+#define RT5651_REC_R1_MIXER			0x3d
+#define RT5651_REC_R2_MIXER			0x3e
+/* Mixer - DAC */
+#define RT5651_HPO_MIXER			0x45
+#define RT5651_OUT_L1_MIXER			0x4d
+#define RT5651_OUT_L2_MIXER			0x4e
+#define RT5651_OUT_L3_MIXER			0x4f
+#define RT5651_OUT_R1_MIXER			0x50
+#define RT5651_OUT_R2_MIXER			0x51
+#define RT5651_OUT_R3_MIXER			0x52
+#define RT5651_LOUT_MIXER			0x53
+/* Power */
+#define RT5651_PWR_DIG1				0x61
+#define RT5651_PWR_DIG2				0x62
+#define RT5651_PWR_ANLG1			0x63
+#define RT5651_PWR_ANLG2			0x64
+#define RT5651_PWR_MIXER			0x65
+#define RT5651_PWR_VOL				0x66
+/* Private Register Control */
+#define RT5651_PRIV_INDEX			0x6a
+#define RT5651_PRIV_DATA			0x6c
+/* Format - ADC/DAC */
+#define RT5651_I2S1_SDP				0x70
+#define RT5651_I2S2_SDP				0x71
+#define RT5651_ADDA_CLK1			0x73
+#define RT5651_ADDA_CLK2			0x74
+#define RT5651_DMIC				0x75
+/* TDM Control */
+#define RT5651_TDM_CTL_1			0x77
+#define RT5651_TDM_CTL_2			0x78
+#define RT5651_TDM_CTL_3			0x79
+/* Function - Analog */
+#define RT5651_GLB_CLK				0x80
+#define RT5651_PLL_CTRL1			0x81
+#define RT5651_PLL_CTRL2			0x82
+#define RT5651_PLL_MODE_1			0x83
+#define RT5651_PLL_MODE_2			0x84
+#define RT5651_PLL_MODE_3			0x85
+#define RT5651_PLL_MODE_4			0x86
+#define RT5651_PLL_MODE_5			0x87
+#define RT5651_PLL_MODE_6			0x89
+#define RT5651_PLL_MODE_7			0x8a
+#define RT5651_DEPOP_M1				0x8e
+#define RT5651_DEPOP_M2				0x8f
+#define RT5651_DEPOP_M3				0x90
+#define RT5651_CHARGE_PUMP			0x91
+#define RT5651_MICBIAS				0x93
+#define RT5651_A_JD_CTL1			0x94
+/* Function - Digital */
+#define RT5651_EQ_CTRL1				0xb0
+#define RT5651_EQ_CTRL2				0xb1
+#define RT5651_ALC_1				0xb4
+#define RT5651_ALC_2				0xb5
+#define RT5651_ALC_3				0xb6
+#define RT5651_JD_CTRL1				0xbb
+#define RT5651_JD_CTRL2				0xbc
+#define RT5651_IRQ_CTRL1			0xbd
+#define RT5651_IRQ_CTRL2			0xbe
+#define RT5651_INT_IRQ_ST			0xbf
+#define RT5651_GPIO_CTRL1			0xc0
+#define RT5651_GPIO_CTRL2			0xc1
+#define RT5651_GPIO_CTRL3			0xc2
+#define RT5651_PGM_REG_ARR1			0xc8
+#define RT5651_PGM_REG_ARR2			0xc9
+#define RT5651_PGM_REG_ARR3			0xca
+#define RT5651_PGM_REG_ARR4			0xcb
+#define RT5651_PGM_REG_ARR5			0xcc
+#define RT5651_SCB_FUNC				0xcd
+#define RT5651_SCB_CTRL				0xce
+#define RT5651_BASE_BACK			0xcf
+#define RT5651_MP3_PLUS1			0xd0
+#define RT5651_MP3_PLUS2			0xd1
+#define RT5651_ADJ_HPF_CTRL1			0xd3
+#define RT5651_ADJ_HPF_CTRL2			0xd4
+#define RT5651_HP_CALIB_AMP_DET			0xd6
+#define RT5651_HP_CALIB2			0xd7
+#define RT5651_SV_ZCD1				0xd9
+#define RT5651_SV_ZCD2				0xda
+#define RT5651_D_MISC				0xfa
+/* Dummy Register */
+#define RT5651_DUMMY2				0xfb
+#define RT5651_DUMMY3				0xfc
+
+
+/* Index of Codec Private Register definition */
+#define RT5651_BIAS_CUR1			0x12
+#define RT5651_BIAS_CUR3			0x14
+#define RT5651_CLSD_INT_REG1			0x1c
+#define RT5651_CHPUMP_INT_REG1			0x24
+#define RT5651_MAMP_INT_REG2			0x37
+#define RT5651_CHOP_DAC_ADC			0x3d
+#define RT5651_3D_SPK				0x63
+#define RT5651_WND_1				0x6c
+#define RT5651_WND_2				0x6d
+#define RT5651_WND_3				0x6e
+#define RT5651_WND_4				0x6f
+#define RT5651_WND_5				0x70
+#define RT5651_WND_8				0x73
+#define RT5651_DIP_SPK_INF			0x75
+#define RT5651_HP_DCC_INT1			0x77
+#define RT5651_EQ_BW_LOP			0xa0
+#define RT5651_EQ_GN_LOP			0xa1
+#define RT5651_EQ_FC_BP1			0xa2
+#define RT5651_EQ_BW_BP1			0xa3
+#define RT5651_EQ_GN_BP1			0xa4
+#define RT5651_EQ_FC_BP2			0xa5
+#define RT5651_EQ_BW_BP2			0xa6
+#define RT5651_EQ_GN_BP2			0xa7
+#define RT5651_EQ_FC_BP3			0xa8
+#define RT5651_EQ_BW_BP3			0xa9
+#define RT5651_EQ_GN_BP3			0xaa
+#define RT5651_EQ_FC_BP4			0xab
+#define RT5651_EQ_BW_BP4			0xac
+#define RT5651_EQ_GN_BP4			0xad
+#define RT5651_EQ_FC_HIP1			0xae
+#define RT5651_EQ_GN_HIP1			0xaf
+#define RT5651_EQ_FC_HIP2			0xb0
+#define RT5651_EQ_BW_HIP2			0xb1
+#define RT5651_EQ_GN_HIP2			0xb2
+#define RT5651_EQ_PRE_VOL			0xb3
+#define RT5651_EQ_PST_VOL			0xb4
+
+
+/* global definition */
+#define RT5651_L_MUTE				(0x1 << 15)
+#define RT5651_L_MUTE_SFT			15
+#define RT5651_VOL_L_MUTE			(0x1 << 14)
+#define RT5651_VOL_L_SFT			14
+#define RT5651_R_MUTE				(0x1 << 7)
+#define RT5651_R_MUTE_SFT			7
+#define RT5651_VOL_R_MUTE			(0x1 << 6)
+#define RT5651_VOL_R_SFT			6
+#define RT5651_L_VOL_MASK			(0x3f << 8)
+#define RT5651_L_VOL_SFT			8
+#define RT5651_R_VOL_MASK			(0x3f)
+#define RT5651_R_VOL_SFT			0
+
+/* LOUT Control 2(0x05) */
+#define RT5651_EN_DFO				(0x1 << 15)
+
+/* IN1 and IN2 Control (0x0d) */
+/* IN3 and IN4 Control (0x0e) */
+#define RT5651_BST_MASK1			(0xf<<12)
+#define RT5651_BST_SFT1				12
+#define RT5651_BST_MASK2			(0xf<<8)
+#define RT5651_BST_SFT2				8
+#define RT5651_IN_DF1				(0x1 << 7)
+#define RT5651_IN_SFT1				7
+#define RT5651_IN_DF2				(0x1 << 6)
+#define RT5651_IN_SFT2				6
+
+/* INL1 and INR1 Volume Control (0x0f) */
+/* INL2 and INR2 Volume Control (0x10) */
+#define RT5651_INL_SEL_MASK			(0x1 << 15)
+#define RT5651_INL_SEL_SFT			15
+#define RT5651_INL_SEL_IN4P			(0x0 << 15)
+#define RT5651_INL_SEL_MONOP			(0x1 << 15)
+#define RT5651_INL_VOL_MASK			(0x1f << 8)
+#define RT5651_INL_VOL_SFT			8
+#define RT5651_INR_SEL_MASK			(0x1 << 7)
+#define RT5651_INR_SEL_SFT			7
+#define RT5651_INR_SEL_IN4N			(0x0 << 7)
+#define RT5651_INR_SEL_MONON			(0x1 << 7)
+#define RT5651_INR_VOL_MASK			(0x1f)
+#define RT5651_INR_VOL_SFT			0
+
+/* DAC1 Digital Volume (0x19) */
+#define RT5651_DAC_L1_VOL_MASK			(0xff << 8)
+#define RT5651_DAC_L1_VOL_SFT			8
+#define RT5651_DAC_R1_VOL_MASK			(0xff)
+#define RT5651_DAC_R1_VOL_SFT			0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5651_DAC_L2_VOL_MASK			(0xff << 8)
+#define RT5651_DAC_L2_VOL_SFT			8
+#define RT5651_DAC_R2_VOL_MASK			(0xff)
+#define RT5651_DAC_R2_VOL_SFT			0
+
+/* DAC2 Control (0x1b) */
+#define RT5651_M_DAC_L2_VOL			(0x1 << 13)
+#define RT5651_M_DAC_L2_VOL_SFT			13
+#define RT5651_M_DAC_R2_VOL			(0x1 << 12)
+#define RT5651_M_DAC_R2_VOL_SFT			12
+#define RT5651_SEL_DAC_L2			(0x1 << 11)
+#define RT5651_IF2_DAC_L2			(0x1 << 11)
+#define RT5651_IF1_DAC_L2			(0x0 << 11)
+#define RT5651_SEL_DAC_L2_SFT			11
+#define RT5651_SEL_DAC_R2			(0x1 << 10)
+#define RT5651_IF2_DAC_R2			(0x1 << 11)
+#define RT5651_IF1_DAC_R2			(0x0 << 11)
+#define RT5651_SEL_DAC_R2_SFT			10
+
+/* ADC Digital Volume Control (0x1c) */
+#define RT5651_ADC_L_VOL_MASK			(0x7f << 8)
+#define RT5651_ADC_L_VOL_SFT			8
+#define RT5651_ADC_R_VOL_MASK			(0x7f)
+#define RT5651_ADC_R_VOL_SFT			0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5651_M_MONO_ADC_L			(0x1 << 15)
+#define RT5651_M_MONO_ADC_L_SFT			15
+#define RT5651_MONO_ADC_L_VOL_MASK		(0x7f << 8)
+#define RT5651_MONO_ADC_L_VOL_SFT		8
+#define RT5651_M_MONO_ADC_R			(0x1 << 7)
+#define RT5651_M_MONO_ADC_R_SFT			7
+#define RT5651_MONO_ADC_R_VOL_MASK		(0x7f)
+#define RT5651_MONO_ADC_R_VOL_SFT		0
+
+/* ADC Boost Volume Control (0x1e) */
+#define RT5651_ADC_L_BST_MASK			(0x3 << 14)
+#define RT5651_ADC_L_BST_SFT			14
+#define RT5651_ADC_R_BST_MASK			(0x3 << 12)
+#define RT5651_ADC_R_BST_SFT			12
+#define RT5651_ADC_COMP_MASK			(0x3 << 10)
+#define RT5651_ADC_COMP_SFT			10
+
+/* Stereo ADC1 Mixer Control (0x27) */
+#define RT5651_M_STO1_ADC_L1			(0x1 << 14)
+#define RT5651_M_STO1_ADC_L1_SFT		14
+#define RT5651_M_STO1_ADC_L2			(0x1 << 13)
+#define RT5651_M_STO1_ADC_L2_SFT		13
+#define RT5651_STO1_ADC_1_SRC_MASK		(0x1 << 12)
+#define RT5651_STO1_ADC_1_SRC_SFT		12
+#define RT5651_STO1_ADC_1_SRC_ADC		(0x1 << 12)
+#define RT5651_STO1_ADC_1_SRC_DACMIX		(0x0 << 12)
+#define RT5651_STO1_ADC_2_SRC_MASK		(0x1 << 11)
+#define RT5651_STO1_ADC_2_SRC_SFT		11
+#define RT5651_STO1_ADC_2_SRC_DMIC		(0x0 << 11)
+#define RT5651_STO1_ADC_2_SRC_DACMIXR	(0x1 << 11)
+#define RT5651_M_STO1_ADC_R1			(0x1 << 6)
+#define RT5651_M_STO1_ADC_R1_SFT		6
+#define RT5651_M_STO1_ADC_R2			(0x1 << 5)
+#define RT5651_M_STO1_ADC_R2_SFT		5
+
+/* Stereo ADC2 Mixer Control (0x28) */
+#define RT5651_M_STO2_ADC_L1			(0x1 << 14)
+#define RT5651_M_STO2_ADC_L1_SFT		14
+#define RT5651_M_STO2_ADC_L2			(0x1 << 13)
+#define RT5651_M_STO2_ADC_L2_SFT		13
+#define RT5651_STO2_ADC_L1_SRC_MASK		(0x1 << 12)
+#define RT5651_STO2_ADC_L1_SRC_SFT		12
+#define RT5651_STO2_ADC_L1_SRC_DACMIXL		(0x0 << 12)
+#define RT5651_STO2_ADC_L1_SRC_ADCL		(0x1 << 12)
+#define RT5651_STO2_ADC_L2_SRC_MASK		(0x1 << 11)
+#define RT5651_STO2_ADC_L2_SRC_SFT		11
+#define RT5651_STO2_ADC_L2_SRC_DMIC		(0x0 << 11)
+#define RT5651_STO2_ADC_L2_SRC_DACMIXR		(0x1 << 11)
+#define RT5651_M_STO2_ADC_R1			(0x1 << 6)
+#define RT5651_M_STO2_ADC_R1_SFT		6
+#define RT5651_M_STO2_ADC_R2			(0x1 << 5)
+#define RT5651_M_STO2_ADC_R2_SFT		5
+#define RT5651_STO2_ADC_R1_SRC_MASK		(0x1 << 4)
+#define RT5651_STO2_ADC_R1_SRC_SFT		4
+#define RT5651_STO2_ADC_R1_SRC_ADCR		(0x1 << 4)
+#define RT5651_STO2_ADC_R1_SRC_DACMIXR		(0x0 << 4)
+#define RT5651_STO2_ADC_R2_SRC_MASK		(0x1 << 3)
+#define RT5651_STO2_ADC_R2_SRC_SFT		3
+#define RT5651_STO2_ADC_R2_SRC_DMIC		(0x0 << 3)
+#define RT5651_STO2_ADC_R2_SRC_DACMIXR		(0x1 << 3)
+
+/* ADC Mixer to DAC Mixer Control (0x29) */
+#define RT5651_M_ADCMIX_L			(0x1 << 15)
+#define RT5651_M_ADCMIX_L_SFT			15
+#define RT5651_M_IF1_DAC_L			(0x1 << 14)
+#define RT5651_M_IF1_DAC_L_SFT			14
+#define RT5651_M_ADCMIX_R			(0x1 << 7)
+#define RT5651_M_ADCMIX_R_SFT			7
+#define RT5651_M_IF1_DAC_R			(0x1 << 6)
+#define RT5651_M_IF1_DAC_R_SFT			6
+
+/* Stereo DAC Mixer Control (0x2a) */
+#define RT5651_M_DAC_L1_MIXL			(0x1 << 14)
+#define RT5651_M_DAC_L1_MIXL_SFT		14
+#define RT5651_DAC_L1_STO_L_VOL_MASK		(0x1 << 13)
+#define RT5651_DAC_L1_STO_L_VOL_SFT		13
+#define RT5651_M_DAC_L2_MIXL			(0x1 << 12)
+#define RT5651_M_DAC_L2_MIXL_SFT		12
+#define RT5651_DAC_L2_STO_L_VOL_MASK		(0x1 << 11)
+#define RT5651_DAC_L2_STO_L_VOL_SFT		11
+#define RT5651_M_DAC_R1_MIXL			(0x1 << 9)
+#define RT5651_M_DAC_R1_MIXL_SFT		9
+#define RT5651_DAC_R1_STO_L_VOL_MASK		(0x1 << 8)
+#define RT5651_DAC_R1_STO_L_VOL_SFT		8
+#define RT5651_M_DAC_R1_MIXR			(0x1 << 6)
+#define RT5651_M_DAC_R1_MIXR_SFT		6
+#define RT5651_DAC_R1_STO_R_VOL_MASK		(0x1 << 5)
+#define RT5651_DAC_R1_STO_R_VOL_SFT		5
+#define RT5651_M_DAC_R2_MIXR			(0x1 << 4)
+#define RT5651_M_DAC_R2_MIXR_SFT		4
+#define RT5651_DAC_R2_STO_R_VOL_MASK		(0x1 << 3)
+#define RT5651_DAC_R2_STO_R_VOL_SFT		3
+#define RT5651_M_DAC_L1_MIXR			(0x1 << 1)
+#define RT5651_M_DAC_L1_MIXR_SFT		1
+#define RT5651_DAC_L1_STO_R_VOL_MASK		(0x1)
+#define RT5651_DAC_L1_STO_R_VOL_SFT		0
+
+/* DD Mixer Control (0x2b) */
+#define RT5651_M_STO_DD_L1			(0x1 << 14)
+#define RT5651_M_STO_DD_L1_SFT			14
+#define RT5651_STO_DD_L1_VOL_MASK		(0x1 << 13)
+#define RT5651_DAC_DD_L1_VOL_SFT		13
+#define RT5651_M_STO_DD_L2			(0x1 << 12)
+#define RT5651_M_STO_DD_L2_SFT			12
+#define RT5651_STO_DD_L2_VOL_MASK		(0x1 << 11)
+#define RT5651_STO_DD_L2_VOL_SFT		11
+#define RT5651_M_STO_DD_R2_L			(0x1 << 10)
+#define RT5651_M_STO_DD_R2_L_SFT		10
+#define RT5651_STO_DD_R2_L_VOL_MASK		(0x1 << 9)
+#define RT5651_STO_DD_R2_L_VOL_SFT		9
+#define RT5651_M_STO_DD_R1			(0x1 << 6)
+#define RT5651_M_STO_DD_R1_SFT			6
+#define RT5651_STO_DD_R1_VOL_MASK		(0x1 << 5)
+#define RT5651_STO_DD_R1_VOL_SFT		5
+#define RT5651_M_STO_DD_R2			(0x1 << 4)
+#define RT5651_M_STO_DD_R2_SFT			4
+#define RT5651_STO_DD_R2_VOL_MASK		(0x1 << 3)
+#define RT5651_STO_DD_R2_VOL_SFT		3
+#define RT5651_M_STO_DD_L2_R			(0x1 << 2)
+#define RT5651_M_STO_DD_L2_R_SFT		2
+#define RT5651_STO_DD_L2_R_VOL_MASK		(0x1 << 1)
+#define RT5651_STO_DD_L2_R_VOL_SFT		1
+
+/* Digital Mixer Control (0x2c) */
+#define RT5651_M_STO_L_DAC_L			(0x1 << 15)
+#define RT5651_M_STO_L_DAC_L_SFT		15
+#define RT5651_STO_L_DAC_L_VOL_MASK		(0x1 << 14)
+#define RT5651_STO_L_DAC_L_VOL_SFT		14
+#define RT5651_M_DAC_L2_DAC_L			(0x1 << 13)
+#define RT5651_M_DAC_L2_DAC_L_SFT		13
+#define RT5651_DAC_L2_DAC_L_VOL_MASK		(0x1 << 12)
+#define RT5651_DAC_L2_DAC_L_VOL_SFT		12
+#define RT5651_M_STO_R_DAC_R			(0x1 << 11)
+#define RT5651_M_STO_R_DAC_R_SFT		11
+#define RT5651_STO_R_DAC_R_VOL_MASK		(0x1 << 10)
+#define RT5651_STO_R_DAC_R_VOL_SFT		10
+#define RT5651_M_DAC_R2_DAC_R			(0x1 << 9)
+#define RT5651_M_DAC_R2_DAC_R_SFT		9
+#define RT5651_DAC_R2_DAC_R_VOL_MASK		(0x1 << 8)
+#define RT5651_DAC_R2_DAC_R_VOL_SFT		8
+
+/* DSP Path Control 1 (0x2d) */
+#define RT5651_RXDP_SRC_MASK			(0x1 << 15)
+#define RT5651_RXDP_SRC_SFT			15
+#define RT5651_RXDP_SRC_NOR			(0x0 << 15)
+#define RT5651_RXDP_SRC_DIV3			(0x1 << 15)
+#define RT5651_TXDP_SRC_MASK			(0x1 << 14)
+#define RT5651_TXDP_SRC_SFT			14
+#define RT5651_TXDP_SRC_NOR			(0x0 << 14)
+#define RT5651_TXDP_SRC_DIV3			(0x1 << 14)
+
+/* DSP Path Control 2 (0x2e) */
+#define RT5651_DAC_L2_SEL_MASK			(0x3 << 14)
+#define RT5651_DAC_L2_SEL_SFT			14
+#define RT5651_DAC_L2_SEL_IF2			(0x0 << 14)
+#define RT5651_DAC_L2_SEL_IF3			(0x1 << 14)
+#define RT5651_DAC_L2_SEL_TXDC			(0x2 << 14)
+#define RT5651_DAC_L2_SEL_BASS			(0x3 << 14)
+#define RT5651_DAC_R2_SEL_MASK			(0x3 << 12)
+#define RT5651_DAC_R2_SEL_SFT			12
+#define RT5651_DAC_R2_SEL_IF2			(0x0 << 12)
+#define RT5651_DAC_R2_SEL_IF3			(0x1 << 12)
+#define RT5651_DAC_R2_SEL_TXDC			(0x2 << 12)
+#define RT5651_IF2_ADC_L_SEL_MASK		(0x1 << 11)
+#define RT5651_IF2_ADC_L_SEL_SFT		11
+#define RT5651_IF2_ADC_L_SEL_TXDP		(0x0 << 11)
+#define RT5651_IF2_ADC_L_SEL_PASS		(0x1 << 11)
+#define RT5651_IF2_ADC_R_SEL_MASK		(0x1 << 10)
+#define RT5651_IF2_ADC_R_SEL_SFT		10
+#define RT5651_IF2_ADC_R_SEL_TXDP		(0x0 << 10)
+#define RT5651_IF2_ADC_R_SEL_PASS		(0x1 << 10)
+#define RT5651_RXDC_SEL_MASK			(0x3 << 8)
+#define RT5651_RXDC_SEL_SFT			8
+#define RT5651_RXDC_SEL_NOR			(0x0 << 8)
+#define RT5651_RXDC_SEL_L2R			(0x1 << 8)
+#define RT5651_RXDC_SEL_R2L			(0x2 << 8)
+#define RT5651_RXDC_SEL_SWAP			(0x3 << 8)
+#define RT5651_RXDP_SEL_MASK			(0x3 << 6)
+#define RT5651_RXDP_SEL_SFT			6
+#define RT5651_RXDP_SEL_NOR			(0x0 << 6)
+#define RT5651_RXDP_SEL_L2R			(0x1 << 6)
+#define RT5651_RXDP_SEL_R2L			(0x2 << 6)
+#define RT5651_RXDP_SEL_SWAP			(0x3 << 6)
+#define RT5651_TXDC_SEL_MASK			(0x3 << 4)
+#define RT5651_TXDC_SEL_SFT			4
+#define RT5651_TXDC_SEL_NOR			(0x0 << 4)
+#define RT5651_TXDC_SEL_L2R			(0x1 << 4)
+#define RT5651_TXDC_SEL_R2L			(0x2 << 4)
+#define RT5651_TXDC_SEL_SWAP			(0x3 << 4)
+#define RT5651_TXDP_SEL_MASK			(0x3 << 2)
+#define RT5651_TXDP_SEL_SFT			2
+#define RT5651_TXDP_SEL_NOR			(0x0 << 2)
+#define RT5651_TXDP_SEL_L2R			(0x1 << 2)
+#define RT5651_TXDP_SEL_R2L			(0x2 << 2)
+#define RT5651_TRXDP_SEL_SWAP			(0x3 << 2)
+
+/* Digital Interface Data Control (0x2f) */
+#define RT5651_IF2_DAC_SEL_MASK			(0x3 << 10)
+#define RT5651_IF2_DAC_SEL_SFT			10
+#define RT5651_IF2_DAC_SEL_NOR			(0x0 << 10)
+#define RT5651_IF2_DAC_SEL_SWAP			(0x1 << 10)
+#define RT5651_IF2_DAC_SEL_L2R			(0x2 << 10)
+#define RT5651_IF2_DAC_SEL_R2L			(0x3 << 10)
+#define RT5651_IF2_ADC_SEL_MASK			(0x3 << 8)
+#define RT5651_IF2_ADC_SEL_SFT			8
+#define RT5651_IF2_ADC_SEL_NOR			(0x0 << 8)
+#define RT5651_IF2_ADC_SEL_SWAP			(0x1 << 8)
+#define RT5651_IF2_ADC_SEL_L2R			(0x2 << 8)
+#define RT5651_IF2_ADC_SEL_R2L			(0x3 << 8)
+#define RT5651_IF2_ADC_SRC_MASK			(0x1 << 7)
+#define RT5651_IF2_ADC_SRC_SFT			7
+#define RT5651_IF1_ADC1				(0x0 << 7)
+#define RT5651_IF1_ADC2				(0x1 << 7)
+
+/* PDM Output Control (0x30) */
+#define RT5651_PDM_L_SEL_MASK			(0x1 << 15)
+#define RT5651_PDM_L_SEL_SFT			15
+#define RT5651_PDM_L_SEL_DD_L			(0x0 << 15)
+#define RT5651_PDM_L_SEL_STO_L			(0x1 << 15)
+#define RT5651_M_PDM_L				(0x1 << 14)
+#define RT5651_M_PDM_L_SFT			14
+#define RT5651_PDM_R_SEL_MASK			(0x1 << 13)
+#define RT5651_PDM_R_SEL_SFT			13
+#define RT5651_PDM_R_SEL_DD_L			(0x0 << 13)
+#define RT5651_PDM_R_SEL_STO_L			(0x1 << 13)
+#define RT5651_M_PDM_R				(0x1 << 12)
+#define RT5651_M_PDM_R_SFT			12
+#define RT5651_PDM_BUSY				(0x1 << 6)
+#define RT5651_PDM_BUSY_SFT			6
+#define RT5651_PDM_PATTERN_SEL_MASK		(0x1 << 5)
+#define RT5651_PDM_PATTERN_SEL_64		(0x0 << 5)
+#define RT5651_PDM_PATTERN_SEL_128		(0x1 << 5)
+#define RT5651_PDM_VOL_MASK			(0x1 << 4)
+#define RT5651_PDM_VOL_SFT			4
+#define RT5651_PDM_DIV_MASK			(0x3)
+#define RT5651_PDM_DIV_SFT			0
+#define RT5651_PDM_DIV_1			0
+#define RT5651_PDM_DIV_2			1
+#define RT5651_PDM_DIV_3			2
+#define RT5651_PDM_DIV_4			3
+
+/* PDM I2C/Data Control 1 (0x31) */
+#define RT5651_PDM_I2C_ID_MASK			(0xf << 12)
+#define PT5631_PDM_CMD_EXE			(0x1 << 11)
+#define RT5651_PDM_I2C_CMD_MASK			(0x1 << 10)
+#define RT5651_PDM_I2C_CMD_R			(0x0 << 10)
+#define RT5651_PDM_I2C_CMD_W			(0x1 << 10)
+#define RT5651_PDM_I2C_CMD_EXE			(0x1 << 9)
+#define RT5651_PDM_I2C_NORMAL			(0x0 << 8)
+#define RT5651_PDM_I2C_BUSY			(0x1 << 8)
+
+/* PDM I2C/Data Control 2 (0x32) */
+#define RT5651_PDM_I2C_ADDR			(0xff << 8)
+#define RT5651_PDM_I2C_CMD_PATTERN		(0xff)
+
+
+/* REC Left Mixer Control 1 (0x3b) */
+#define RT5651_G_LN_L2_RM_L_MASK		(0x7 << 13)
+#define RT5651_G_IN_L2_RM_L_SFT			13
+#define RT5651_G_LN_L1_RM_L_MASK		(0x7 << 10)
+#define RT5651_G_IN_L1_RM_L_SFT			10
+#define RT5651_G_BST3_RM_L_MASK			(0x7 << 4)
+#define RT5651_G_BST3_RM_L_SFT			4
+#define RT5651_G_BST2_RM_L_MASK			(0x7 << 1)
+#define RT5651_G_BST2_RM_L_SFT			1
+
+/* REC Left Mixer Control 2 (0x3c) */
+#define RT5651_G_BST1_RM_L_MASK			(0x7 << 13)
+#define RT5651_G_BST1_RM_L_SFT			13
+#define RT5651_G_OM_L_RM_L_MASK			(0x7 << 10)
+#define RT5651_G_OM_L_RM_L_SFT			10
+#define RT5651_M_IN2_L_RM_L			(0x1 << 6)
+#define RT5651_M_IN2_L_RM_L_SFT			6
+#define RT5651_M_IN1_L_RM_L			(0x1 << 5)
+#define RT5651_M_IN1_L_RM_L_SFT			5
+#define RT5651_M_BST3_RM_L			(0x1 << 3)
+#define RT5651_M_BST3_RM_L_SFT			3
+#define RT5651_M_BST2_RM_L			(0x1 << 2)
+#define RT5651_M_BST2_RM_L_SFT			2
+#define RT5651_M_BST1_RM_L			(0x1 << 1)
+#define RT5651_M_BST1_RM_L_SFT			1
+#define RT5651_M_OM_L_RM_L			(0x1)
+#define RT5651_M_OM_L_RM_L_SFT			0
+
+/* REC Right Mixer Control 1 (0x3d) */
+#define RT5651_G_IN2_R_RM_R_MASK		(0x7 << 13)
+#define RT5651_G_IN2_R_RM_R_SFT			13
+#define RT5651_G_IN1_R_RM_R_MASK		(0x7 << 10)
+#define RT5651_G_IN1_R_RM_R_SFT			10
+#define RT5651_G_BST3_RM_R_MASK			(0x7 << 4)
+#define RT5651_G_BST3_RM_R_SFT			4
+#define RT5651_G_BST2_RM_R_MASK			(0x7 << 1)
+#define RT5651_G_BST2_RM_R_SFT			1
+
+/* REC Right Mixer Control 2 (0x3e) */
+#define RT5651_G_BST1_RM_R_MASK			(0x7 << 13)
+#define RT5651_G_BST1_RM_R_SFT			13
+#define RT5651_G_OM_R_RM_R_MASK			(0x7 << 10)
+#define RT5651_G_OM_R_RM_R_SFT			10
+#define RT5651_M_IN2_R_RM_R			(0x1 << 6)
+#define RT5651_M_IN2_R_RM_R_SFT			6
+#define RT5651_M_IN1_R_RM_R			(0x1 << 5)
+#define RT5651_M_IN1_R_RM_R_SFT			5
+#define RT5651_M_BST3_RM_R			(0x1 << 3)
+#define RT5651_M_BST3_RM_R_SFT			3
+#define RT5651_M_BST2_RM_R			(0x1 << 2)
+#define RT5651_M_BST2_RM_R_SFT			2
+#define RT5651_M_BST1_RM_R			(0x1 << 1)
+#define RT5651_M_BST1_RM_R_SFT			1
+#define RT5651_M_OM_R_RM_R			(0x1)
+#define RT5651_M_OM_R_RM_R_SFT			0
+
+/* HPMIX Control (0x45) */
+#define RT5651_M_DAC1_HM			(0x1 << 14)
+#define RT5651_M_DAC1_HM_SFT			14
+#define RT5651_M_HPVOL_HM			(0x1 << 13)
+#define RT5651_M_HPVOL_HM_SFT			13
+#define RT5651_G_HPOMIX_MASK			(0x1 << 12)
+#define RT5651_G_HPOMIX_SFT			12
+
+/* SPK Left Mixer Control (0x46) */
+#define RT5651_G_RM_L_SM_L_MASK			(0x3 << 14)
+#define RT5651_G_RM_L_SM_L_SFT			14
+#define RT5651_G_IN_L_SM_L_MASK			(0x3 << 12)
+#define RT5651_G_IN_L_SM_L_SFT			12
+#define RT5651_G_DAC_L1_SM_L_MASK		(0x3 << 10)
+#define RT5651_G_DAC_L1_SM_L_SFT		10
+#define RT5651_G_DAC_L2_SM_L_MASK		(0x3 << 8)
+#define RT5651_G_DAC_L2_SM_L_SFT		8
+#define RT5651_G_OM_L_SM_L_MASK			(0x3 << 6)
+#define RT5651_G_OM_L_SM_L_SFT			6
+#define RT5651_M_RM_L_SM_L			(0x1 << 5)
+#define RT5651_M_RM_L_SM_L_SFT			5
+#define RT5651_M_IN_L_SM_L			(0x1 << 4)
+#define RT5651_M_IN_L_SM_L_SFT			4
+#define RT5651_M_DAC_L1_SM_L			(0x1 << 3)
+#define RT5651_M_DAC_L1_SM_L_SFT		3
+#define RT5651_M_DAC_L2_SM_L			(0x1 << 2)
+#define RT5651_M_DAC_L2_SM_L_SFT		2
+#define RT5651_M_OM_L_SM_L			(0x1 << 1)
+#define RT5651_M_OM_L_SM_L_SFT			1
+
+/* SPK Right Mixer Control (0x47) */
+#define RT5651_G_RM_R_SM_R_MASK			(0x3 << 14)
+#define RT5651_G_RM_R_SM_R_SFT			14
+#define RT5651_G_IN_R_SM_R_MASK			(0x3 << 12)
+#define RT5651_G_IN_R_SM_R_SFT			12
+#define RT5651_G_DAC_R1_SM_R_MASK		(0x3 << 10)
+#define RT5651_G_DAC_R1_SM_R_SFT		10
+#define RT5651_G_DAC_R2_SM_R_MASK		(0x3 << 8)
+#define RT5651_G_DAC_R2_SM_R_SFT		8
+#define RT5651_G_OM_R_SM_R_MASK			(0x3 << 6)
+#define RT5651_G_OM_R_SM_R_SFT			6
+#define RT5651_M_RM_R_SM_R			(0x1 << 5)
+#define RT5651_M_RM_R_SM_R_SFT			5
+#define RT5651_M_IN_R_SM_R			(0x1 << 4)
+#define RT5651_M_IN_R_SM_R_SFT			4
+#define RT5651_M_DAC_R1_SM_R			(0x1 << 3)
+#define RT5651_M_DAC_R1_SM_R_SFT		3
+#define RT5651_M_DAC_R2_SM_R			(0x1 << 2)
+#define RT5651_M_DAC_R2_SM_R_SFT		2
+#define RT5651_M_OM_R_SM_R			(0x1 << 1)
+#define RT5651_M_OM_R_SM_R_SFT			1
+
+/* SPOLMIX Control (0x48) */
+#define RT5651_M_DAC_R1_SPM_L			(0x1 << 15)
+#define RT5651_M_DAC_R1_SPM_L_SFT		15
+#define RT5651_M_DAC_L1_SPM_L			(0x1 << 14)
+#define RT5651_M_DAC_L1_SPM_L_SFT		14
+#define RT5651_M_SV_R_SPM_L			(0x1 << 13)
+#define RT5651_M_SV_R_SPM_L_SFT			13
+#define RT5651_M_SV_L_SPM_L			(0x1 << 12)
+#define RT5651_M_SV_L_SPM_L_SFT			12
+#define RT5651_M_BST1_SPM_L			(0x1 << 11)
+#define RT5651_M_BST1_SPM_L_SFT			11
+
+/* SPORMIX Control (0x49) */
+#define RT5651_M_DAC_R1_SPM_R			(0x1 << 13)
+#define RT5651_M_DAC_R1_SPM_R_SFT		13
+#define RT5651_M_SV_R_SPM_R			(0x1 << 12)
+#define RT5651_M_SV_R_SPM_R_SFT			12
+#define RT5651_M_BST1_SPM_R			(0x1 << 11)
+#define RT5651_M_BST1_SPM_R_SFT			11
+
+/* SPOLMIX / SPORMIX Ratio Control (0x4a) */
+#define RT5651_SPO_CLSD_RATIO_MASK		(0x7)
+#define RT5651_SPO_CLSD_RATIO_SFT		0
+
+/* Mono Output Mixer Control (0x4c) */
+#define RT5651_M_DAC_R2_MM			(0x1 << 15)
+#define RT5651_M_DAC_R2_MM_SFT			15
+#define RT5651_M_DAC_L2_MM			(0x1 << 14)
+#define RT5651_M_DAC_L2_MM_SFT			14
+#define RT5651_M_OV_R_MM			(0x1 << 13)
+#define RT5651_M_OV_R_MM_SFT			13
+#define RT5651_M_OV_L_MM			(0x1 << 12)
+#define RT5651_M_OV_L_MM_SFT			12
+#define RT5651_M_BST1_MM			(0x1 << 11)
+#define RT5651_M_BST1_MM_SFT			11
+#define RT5651_G_MONOMIX_MASK			(0x1 << 10)
+#define RT5651_G_MONOMIX_SFT			10
+
+/* Output Left Mixer Control 1 (0x4d) */
+#define RT5651_G_BST2_OM_L_MASK			(0x7 << 10)
+#define RT5651_G_BST2_OM_L_SFT			10
+#define RT5651_G_BST1_OM_L_MASK			(0x7 << 7)
+#define RT5651_G_BST1_OM_L_SFT			7
+#define RT5651_G_IN1_L_OM_L_MASK		(0x7 << 4)
+#define RT5651_G_IN1_L_OM_L_SFT			4
+#define RT5651_G_RM_L_OM_L_MASK			(0x7 << 1)
+#define RT5651_G_RM_L_OM_L_SFT			1
+
+/* Output Left Mixer Control 2 (0x4e) */
+#define RT5651_G_DAC_L1_OM_L_MASK		(0x7 << 7)
+#define RT5651_G_DAC_L1_OM_L_SFT		7
+#define RT5651_G_IN2_L_OM_L_MASK		(0x7 << 4)
+#define RT5651_G_IN2_L_OM_L_SFT			4
+
+/* Output Left Mixer Control 3 (0x4f) */
+#define RT5651_M_IN2_L_OM_L			(0x1 << 9)
+#define RT5651_M_IN2_L_OM_L_SFT			9
+#define RT5651_M_BST2_OM_L			(0x1 << 6)
+#define RT5651_M_BST2_OM_L_SFT			6
+#define RT5651_M_BST1_OM_L			(0x1 << 5)
+#define RT5651_M_BST1_OM_L_SFT			5
+#define RT5651_M_IN1_L_OM_L			(0x1 << 4)
+#define RT5651_M_IN1_L_OM_L_SFT			4
+#define RT5651_M_RM_L_OM_L			(0x1 << 3)
+#define RT5651_M_RM_L_OM_L_SFT			3
+#define RT5651_M_DAC_L1_OM_L			(0x1)
+#define RT5651_M_DAC_L1_OM_L_SFT		0
+
+/* Output Right Mixer Control 1 (0x50) */
+#define RT5651_G_BST2_OM_R_MASK			(0x7 << 10)
+#define RT5651_G_BST2_OM_R_SFT			10
+#define RT5651_G_BST1_OM_R_MASK			(0x7 << 7)
+#define RT5651_G_BST1_OM_R_SFT			7
+#define RT5651_G_IN1_R_OM_R_MASK		(0x7 << 4)
+#define RT5651_G_IN1_R_OM_R_SFT			4
+#define RT5651_G_RM_R_OM_R_MASK			(0x7 << 1)
+#define RT5651_G_RM_R_OM_R_SFT			1
+
+/* Output Right Mixer Control 2 (0x51) */
+#define RT5651_G_DAC_R1_OM_R_MASK		(0x7 << 7)
+#define RT5651_G_DAC_R1_OM_R_SFT		7
+#define RT5651_G_IN2_R_OM_R_MASK		(0x7 << 4)
+#define RT5651_G_IN2_R_OM_R_SFT			4
+
+/* Output Right Mixer Control 3 (0x52) */
+#define RT5651_M_IN2_R_OM_R			(0x1 << 9)
+#define RT5651_M_IN2_R_OM_R_SFT			9
+#define RT5651_M_BST2_OM_R			(0x1 << 6)
+#define RT5651_M_BST2_OM_R_SFT			6
+#define RT5651_M_BST1_OM_R			(0x1 << 5)
+#define RT5651_M_BST1_OM_R_SFT			5
+#define RT5651_M_IN1_R_OM_R			(0x1 << 4)
+#define RT5651_M_IN1_R_OM_R_SFT			4
+#define RT5651_M_RM_R_OM_R			(0x1 << 3)
+#define RT5651_M_RM_R_OM_R_SFT			3
+#define RT5651_M_DAC_R1_OM_R			(0x1)
+#define RT5651_M_DAC_R1_OM_R_SFT		0
+
+/* LOUT Mixer Control (0x53) */
+#define RT5651_M_DAC_L1_LM			(0x1 << 15)
+#define RT5651_M_DAC_L1_LM_SFT			15
+#define RT5651_M_DAC_R1_LM			(0x1 << 14)
+#define RT5651_M_DAC_R1_LM_SFT			14
+#define RT5651_M_OV_L_LM			(0x1 << 13)
+#define RT5651_M_OV_L_LM_SFT			13
+#define RT5651_M_OV_R_LM			(0x1 << 12)
+#define RT5651_M_OV_R_LM_SFT			12
+#define RT5651_G_LOUTMIX_MASK			(0x1 << 11)
+#define RT5651_G_LOUTMIX_SFT			11
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5651_PWR_I2S1				(0x1 << 15)
+#define RT5651_PWR_I2S1_BIT			15
+#define RT5651_PWR_I2S2				(0x1 << 14)
+#define RT5651_PWR_I2S2_BIT			14
+#define RT5651_PWR_DAC_L1			(0x1 << 12)
+#define RT5651_PWR_DAC_L1_BIT			12
+#define RT5651_PWR_DAC_R1			(0x1 << 11)
+#define RT5651_PWR_DAC_R1_BIT			11
+#define RT5651_PWR_ADC_L			(0x1 << 2)
+#define RT5651_PWR_ADC_L_BIT			2
+#define RT5651_PWR_ADC_R			(0x1 << 1)
+#define RT5651_PWR_ADC_R_BIT			1
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5651_PWR_ADC_STO1_F			(0x1 << 15)
+#define RT5651_PWR_ADC_STO1_F_BIT			15
+#define RT5651_PWR_ADC_STO2_F			(0x1 << 14)
+#define RT5651_PWR_ADC_STO2_F_BIT		14
+#define RT5651_PWR_DAC_STO1_F			(0x1 << 11)
+#define RT5651_PWR_DAC_STO1_F_BIT			11
+#define RT5651_PWR_DAC_STO2_F			(0x1 << 10)
+#define RT5651_PWR_DAC_STO2_F_BIT		10
+#define RT5651_PWR_PDM				(0x1 << 9)
+#define RT5651_PWR_PDM_BIT			9
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5651_PWR_VREF1			(0x1 << 15)
+#define RT5651_PWR_VREF1_BIT			15
+#define RT5651_PWR_FV1				(0x1 << 14)
+#define RT5651_PWR_FV1_BIT			14
+#define RT5651_PWR_MB				(0x1 << 13)
+#define RT5651_PWR_MB_BIT			13
+#define RT5651_PWR_LM				(0x1 << 12)
+#define RT5651_PWR_LM_BIT			12
+#define RT5651_PWR_BG				(0x1 << 11)
+#define RT5651_PWR_BG_BIT			11
+#define RT5651_PWR_HP_L				(0x1 << 7)
+#define RT5651_PWR_HP_L_BIT			7
+#define RT5651_PWR_HP_R				(0x1 << 6)
+#define RT5651_PWR_HP_R_BIT			6
+#define RT5651_PWR_HA				(0x1 << 5)
+#define RT5651_PWR_HA_BIT			5
+#define RT5651_PWR_VREF2			(0x1 << 4)
+#define RT5651_PWR_VREF2_BIT			4
+#define RT5651_PWR_FV2				(0x1 << 3)
+#define RT5651_PWR_FV2_BIT			3
+#define RT5651_PWR_LDO				(0x1 << 2)
+#define RT5651_PWR_LDO_BIT			2
+#define RT5651_PWR_LDO_DVO_MASK			(0x3)
+#define RT5651_PWR_LDO_DVO_1_0V			0
+#define RT5651_PWR_LDO_DVO_1_1V			1
+#define RT5651_PWR_LDO_DVO_1_2V			2
+#define RT5651_PWR_LDO_DVO_1_3V			3
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5651_PWR_BST1				(0x1 << 15)
+#define RT5651_PWR_BST1_BIT			15
+#define RT5651_PWR_BST2				(0x1 << 14)
+#define RT5651_PWR_BST2_BIT			14
+#define RT5651_PWR_BST3				(0x1 << 13)
+#define RT5651_PWR_BST3_BIT			13
+#define RT5651_PWR_MB1				(0x1 << 11)
+#define RT5651_PWR_MB1_BIT			11
+#define RT5651_PWR_PLL				(0x1 << 9)
+#define RT5651_PWR_PLL_BIT			9
+#define RT5651_PWR_BST1_OP2			(0x1 << 5)
+#define RT5651_PWR_BST1_OP2_BIT			5
+#define RT5651_PWR_BST2_OP2			(0x1 << 4)
+#define RT5651_PWR_BST2_OP2_BIT			4
+#define RT5651_PWR_BST3_OP2			(0x1 << 3)
+#define RT5651_PWR_BST3_OP2_BIT			3
+#define RT5651_PWR_JD_M				(0x1 << 2)
+#define RT5651_PWM_JD_M_BIT			2
+#define RT5651_PWR_JD2				(0x1 << 1)
+#define RT5651_PWM_JD2_BIT			1
+#define RT5651_PWR_JD3				(0x1)
+#define RT5651_PWM_JD3_BIT			0
+
+/* Power Management for Mixer (0x65) */
+#define RT5651_PWR_OM_L				(0x1 << 15)
+#define RT5651_PWR_OM_L_BIT			15
+#define RT5651_PWR_OM_R				(0x1 << 14)
+#define RT5651_PWR_OM_R_BIT			14
+#define RT5651_PWR_RM_L				(0x1 << 11)
+#define RT5651_PWR_RM_L_BIT			11
+#define RT5651_PWR_RM_R				(0x1 << 10)
+#define RT5651_PWR_RM_R_BIT			10
+
+/* Power Management for Volume (0x66) */
+#define RT5651_PWR_OV_L				(0x1 << 13)
+#define RT5651_PWR_OV_L_BIT			13
+#define RT5651_PWR_OV_R				(0x1 << 12)
+#define RT5651_PWR_OV_R_BIT			12
+#define RT5651_PWR_HV_L				(0x1 << 11)
+#define RT5651_PWR_HV_L_BIT			11
+#define RT5651_PWR_HV_R				(0x1 << 10)
+#define RT5651_PWR_HV_R_BIT			10
+#define RT5651_PWR_IN1_L			(0x1 << 9)
+#define RT5651_PWR_IN1_L_BIT			9
+#define RT5651_PWR_IN1_R			(0x1 << 8)
+#define RT5651_PWR_IN1_R_BIT			8
+#define RT5651_PWR_IN2_L			(0x1 << 7)
+#define RT5651_PWR_IN2_L_BIT			7
+#define RT5651_PWR_IN2_R			(0x1 << 6)
+#define RT5651_PWR_IN2_R_BIT			6
+
+/* I2S1/2/3 Audio Serial Data Port Control (0x70 0x71) */
+#define RT5651_I2S_MS_MASK			(0x1 << 15)
+#define RT5651_I2S_MS_SFT			15
+#define RT5651_I2S_MS_M				(0x0 << 15)
+#define RT5651_I2S_MS_S				(0x1 << 15)
+#define RT5651_I2S_O_CP_MASK			(0x3 << 10)
+#define RT5651_I2S_O_CP_SFT			10
+#define RT5651_I2S_O_CP_OFF			(0x0 << 10)
+#define RT5651_I2S_O_CP_U_LAW			(0x1 << 10)
+#define RT5651_I2S_O_CP_A_LAW			(0x2 << 10)
+#define RT5651_I2S_I_CP_MASK			(0x3 << 8)
+#define RT5651_I2S_I_CP_SFT			8
+#define RT5651_I2S_I_CP_OFF			(0x0 << 8)
+#define RT5651_I2S_I_CP_U_LAW			(0x1 << 8)
+#define RT5651_I2S_I_CP_A_LAW			(0x2 << 8)
+#define RT5651_I2S_BP_MASK			(0x1 << 7)
+#define RT5651_I2S_BP_SFT			7
+#define RT5651_I2S_BP_NOR			(0x0 << 7)
+#define RT5651_I2S_BP_INV			(0x1 << 7)
+#define RT5651_I2S_DL_MASK			(0x3 << 2)
+#define RT5651_I2S_DL_SFT			2
+#define RT5651_I2S_DL_16			(0x0 << 2)
+#define RT5651_I2S_DL_20			(0x1 << 2)
+#define RT5651_I2S_DL_24			(0x2 << 2)
+#define RT5651_I2S_DL_8				(0x3 << 2)
+#define RT5651_I2S_DF_MASK			(0x3)
+#define RT5651_I2S_DF_SFT			0
+#define RT5651_I2S_DF_I2S			(0x0)
+#define RT5651_I2S_DF_LEFT			(0x1)
+#define RT5651_I2S_DF_PCM_A			(0x2)
+#define RT5651_I2S_DF_PCM_B			(0x3)
+
+/* ADC/DAC Clock Control 1 (0x73) */
+#define RT5651_I2S_PD1_MASK			(0x7 << 12)
+#define RT5651_I2S_PD1_SFT			12
+#define RT5651_I2S_PD1_1			(0x0 << 12)
+#define RT5651_I2S_PD1_2			(0x1 << 12)
+#define RT5651_I2S_PD1_3			(0x2 << 12)
+#define RT5651_I2S_PD1_4			(0x3 << 12)
+#define RT5651_I2S_PD1_6			(0x4 << 12)
+#define RT5651_I2S_PD1_8			(0x5 << 12)
+#define RT5651_I2S_PD1_12			(0x6 << 12)
+#define RT5651_I2S_PD1_16			(0x7 << 12)
+#define RT5651_I2S_BCLK_MS2_MASK		(0x1 << 11)
+#define RT5651_I2S_BCLK_MS2_SFT			11
+#define RT5651_I2S_BCLK_MS2_32			(0x0 << 11)
+#define RT5651_I2S_BCLK_MS2_64			(0x1 << 11)
+#define RT5651_I2S_PD2_MASK			(0x7 << 8)
+#define RT5651_I2S_PD2_SFT			8
+#define RT5651_I2S_PD2_1			(0x0 << 8)
+#define RT5651_I2S_PD2_2			(0x1 << 8)
+#define RT5651_I2S_PD2_3			(0x2 << 8)
+#define RT5651_I2S_PD2_4			(0x3 << 8)
+#define RT5651_I2S_PD2_6			(0x4 << 8)
+#define RT5651_I2S_PD2_8			(0x5 << 8)
+#define RT5651_I2S_PD2_12			(0x6 << 8)
+#define RT5651_I2S_PD2_16			(0x7 << 8)
+#define RT5651_DAC_OSR_MASK			(0x3 << 2)
+#define RT5651_DAC_OSR_SFT			2
+#define RT5651_DAC_OSR_128			(0x0 << 2)
+#define RT5651_DAC_OSR_64			(0x1 << 2)
+#define RT5651_DAC_OSR_32			(0x2 << 2)
+#define RT5651_DAC_OSR_128_3			(0x3 << 2)
+#define RT5651_ADC_OSR_MASK			(0x3)
+#define RT5651_ADC_OSR_SFT			0
+#define RT5651_ADC_OSR_128			(0x0)
+#define RT5651_ADC_OSR_64			(0x1)
+#define RT5651_ADC_OSR_32			(0x2)
+#define RT5651_ADC_OSR_128_3			(0x3)
+
+/* ADC/DAC Clock Control 2 (0x74) */
+#define RT5651_DAHPF_EN				(0x1 << 11)
+#define RT5651_DAHPF_EN_SFT			11
+#define RT5651_ADHPF_EN				(0x1 << 10)
+#define RT5651_ADHPF_EN_SFT			10
+
+/* Digital Microphone Control (0x75) */
+#define RT5651_DMIC_1_EN_MASK			(0x1 << 15)
+#define RT5651_DMIC_1_EN_SFT			15
+#define RT5651_DMIC_1_DIS			(0x0 << 15)
+#define RT5651_DMIC_1_EN			(0x1 << 15)
+#define RT5651_DMIC_1L_LH_MASK			(0x1 << 13)
+#define RT5651_DMIC_1L_LH_SFT			13
+#define RT5651_DMIC_1L_LH_FALLING		(0x0 << 13)
+#define RT5651_DMIC_1L_LH_RISING		(0x1 << 13)
+#define RT5651_DMIC_1R_LH_MASK			(0x1 << 12)
+#define RT5651_DMIC_1R_LH_SFT			12
+#define RT5651_DMIC_1R_LH_FALLING		(0x0 << 12)
+#define RT5651_DMIC_1R_LH_RISING		(0x1 << 12)
+#define RT5651_DMIC_1_DP_MASK			(0x3 << 10)
+#define RT5651_DMIC_1_DP_SFT			10
+#define RT5651_DMIC_1_DP_GPIO6			(0x0 << 10)
+#define RT5651_DMIC_1_DP_IN1P			(0x1 << 10)
+#define RT5651_DMIC_2_DP_GPIO8			(0x2 << 10)
+#define RT5651_DMIC_CLK_MASK			(0x7 << 5)
+#define RT5651_DMIC_CLK_SFT			5
+
+/* TDM Control 1 (0x77) */
+#define RT5651_TDM_INTEL_SEL_MASK		(0x1 << 15)
+#define RT5651_TDM_INTEL_SEL_SFT		15
+#define RT5651_TDM_INTEL_SEL_64			(0x0 << 15)
+#define RT5651_TDM_INTEL_SEL_50			(0x1 << 15)
+#define RT5651_TDM_MODE_SEL_MASK		(0x1 << 14)
+#define RT5651_TDM_MODE_SEL_SFT			14
+#define RT5651_TDM_MODE_SEL_NOR			(0x0 << 14)
+#define RT5651_TDM_MODE_SEL_TDM			(0x1 << 14)
+#define RT5651_TDM_CH_NUM_SEL_MASK		(0x3 << 12)
+#define RT5651_TDM_CH_NUM_SEL_SFT		12
+#define RT5651_TDM_CH_NUM_SEL_2			(0x0 << 12)
+#define RT5651_TDM_CH_NUM_SEL_4			(0x1 << 12)
+#define RT5651_TDM_CH_NUM_SEL_6			(0x2 << 12)
+#define RT5651_TDM_CH_NUM_SEL_8			(0x3 << 12)
+#define RT5651_TDM_CH_LEN_SEL_MASK		(0x3 << 10)
+#define RT5651_TDM_CH_LEN_SEL_SFT		10
+#define RT5651_TDM_CH_LEN_SEL_16		(0x0 << 10)
+#define RT5651_TDM_CH_LEN_SEL_20		(0x1 << 10)
+#define RT5651_TDM_CH_LEN_SEL_24		(0x2 << 10)
+#define RT5651_TDM_CH_LEN_SEL_32		(0x3 << 10)
+#define RT5651_TDM_ADC_SEL_MASK			(0x1 << 9)
+#define RT5651_TDM_ADC_SEL_SFT			9
+#define RT5651_TDM_ADC_SEL_NOR			(0x0 << 9)
+#define RT5651_TDM_ADC_SEL_SWAP			(0x1 << 9)
+#define RT5651_TDM_ADC_START_SEL_MASK		(0x1 << 8)
+#define RT5651_TDM_ADC_START_SEL_SFT		8
+#define RT5651_TDM_ADC_START_SEL_SL0		(0x0 << 8)
+#define RT5651_TDM_ADC_START_SEL_SL4		(0x1 << 8)
+#define RT5651_TDM_I2S_CH2_SEL_MASK		(0x3 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_SFT		6
+#define RT5651_TDM_I2S_CH2_SEL_LR		(0x0 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_RL		(0x1 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_LL		(0x2 << 6)
+#define RT5651_TDM_I2S_CH2_SEL_RR		(0x3 << 6)
+#define RT5651_TDM_I2S_CH4_SEL_MASK		(0x3 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_SFT		4
+#define RT5651_TDM_I2S_CH4_SEL_LR		(0x0 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_RL		(0x1 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_LL		(0x2 << 4)
+#define RT5651_TDM_I2S_CH4_SEL_RR		(0x3 << 4)
+#define RT5651_TDM_I2S_CH6_SEL_MASK		(0x3 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_SFT		2
+#define RT5651_TDM_I2S_CH6_SEL_LR		(0x0 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_RL		(0x1 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_LL		(0x2 << 2)
+#define RT5651_TDM_I2S_CH6_SEL_RR		(0x3 << 2)
+#define RT5651_TDM_I2S_CH8_SEL_MASK		(0x3)
+#define RT5651_TDM_I2S_CH8_SEL_SFT		0
+#define RT5651_TDM_I2S_CH8_SEL_LR		(0x0)
+#define RT5651_TDM_I2S_CH8_SEL_RL		(0x1)
+#define RT5651_TDM_I2S_CH8_SEL_LL		(0x2)
+#define RT5651_TDM_I2S_CH8_SEL_RR		(0x3)
+
+/* TDM Control 2 (0x78) */
+#define RT5651_TDM_LRCK_POL_SEL_MASK		(0x1 << 15)
+#define RT5651_TDM_LRCK_POL_SEL_SFT		15
+#define RT5651_TDM_LRCK_POL_SEL_NOR		(0x0 << 15)
+#define RT5651_TDM_LRCK_POL_SEL_INV		(0x1 << 15)
+#define RT5651_TDM_CH_VAL_SEL_MASK		(0x1 << 14)
+#define RT5651_TDM_CH_VAL_SEL_SFT		14
+#define RT5651_TDM_CH_VAL_SEL_CH01		(0x0 << 14)
+#define RT5651_TDM_CH_VAL_SEL_CH0123		(0x1 << 14)
+#define RT5651_TDM_CH_VAL_EN			(0x1 << 13)
+#define RT5651_TDM_CH_VAL_SFT			13
+#define RT5651_TDM_LPBK_EN			(0x1 << 12)
+#define RT5651_TDM_LPBK_SFT			12
+#define RT5651_TDM_LRCK_PULSE_SEL_MASK		(0x1 << 11)
+#define RT5651_TDM_LRCK_PULSE_SEL_SFT		11
+#define RT5651_TDM_LRCK_PULSE_SEL_BCLK		(0x0 << 11)
+#define RT5651_TDM_LRCK_PULSE_SEL_CH		(0x1 << 11)
+#define RT5651_TDM_END_EDGE_SEL_MASK		(0x1 << 10)
+#define RT5651_TDM_END_EDGE_SEL_SFT		10
+#define RT5651_TDM_END_EDGE_SEL_POS		(0x0 << 10)
+#define RT5651_TDM_END_EDGE_SEL_NEG		(0x1 << 10)
+#define RT5651_TDM_END_EDGE_EN			(0x1 << 9)
+#define RT5651_TDM_END_EDGE_EN_SFT		9
+#define RT5651_TDM_TRAN_EDGE_SEL_MASK		(0x1 << 8)
+#define RT5651_TDM_TRAN_EDGE_SEL_SFT		8
+#define RT5651_TDM_TRAN_EDGE_SEL_POS		(0x0 << 8)
+#define RT5651_TDM_TRAN_EDGE_SEL_NEG		(0x1 << 8)
+#define RT5651_M_TDM2_L				(0x1 << 7)
+#define RT5651_M_TDM2_L_SFT			7
+#define RT5651_M_TDM2_R				(0x1 << 6)
+#define RT5651_M_TDM2_R_SFT			6
+#define RT5651_M_TDM4_L				(0x1 << 5)
+#define RT5651_M_TDM4_L_SFT			5
+#define RT5651_M_TDM4_R				(0x1 << 4)
+#define RT5651_M_TDM4_R_SFT			4
+
+/* TDM Control 3 (0x79) */
+#define RT5651_CH2_L_SEL_MASK			(0x7 << 12)
+#define RT5651_CH2_L_SEL_SFT			12
+#define RT5651_CH2_L_SEL_SL0			(0x0 << 12)
+#define RT5651_CH2_L_SEL_SL1			(0x1 << 12)
+#define RT5651_CH2_L_SEL_SL2			(0x2 << 12)
+#define RT5651_CH2_L_SEL_SL3			(0x3 << 12)
+#define RT5651_CH2_L_SEL_SL4			(0x4 << 12)
+#define RT5651_CH2_L_SEL_SL5			(0x5 << 12)
+#define RT5651_CH2_L_SEL_SL6			(0x6 << 12)
+#define RT5651_CH2_L_SEL_SL7			(0x7 << 12)
+#define RT5651_CH2_R_SEL_MASK			(0x7 << 8)
+#define RT5651_CH2_R_SEL_SFT			8
+#define RT5651_CH2_R_SEL_SL0			(0x0 << 8)
+#define RT5651_CH2_R_SEL_SL1			(0x1 << 8)
+#define RT5651_CH2_R_SEL_SL2			(0x2 << 8)
+#define RT5651_CH2_R_SEL_SL3			(0x3 << 8)
+#define RT5651_CH2_R_SEL_SL4			(0x4 << 8)
+#define RT5651_CH2_R_SEL_SL5			(0x5 << 8)
+#define RT5651_CH2_R_SEL_SL6			(0x6 << 8)
+#define RT5651_CH2_R_SEL_SL7			(0x7 << 8)
+#define RT5651_CH4_L_SEL_MASK			(0x7 << 4)
+#define RT5651_CH4_L_SEL_SFT			4
+#define RT5651_CH4_L_SEL_SL0			(0x0 << 4)
+#define RT5651_CH4_L_SEL_SL1			(0x1 << 4)
+#define RT5651_CH4_L_SEL_SL2			(0x2 << 4)
+#define RT5651_CH4_L_SEL_SL3			(0x3 << 4)
+#define RT5651_CH4_L_SEL_SL4			(0x4 << 4)
+#define RT5651_CH4_L_SEL_SL5			(0x5 << 4)
+#define RT5651_CH4_L_SEL_SL6			(0x6 << 4)
+#define RT5651_CH4_L_SEL_SL7			(0x7 << 4)
+#define RT5651_CH4_R_SEL_MASK			(0x7)
+#define RT5651_CH4_R_SEL_SFT			0
+#define RT5651_CH4_R_SEL_SL0			(0x0)
+#define RT5651_CH4_R_SEL_SL1			(0x1)
+#define RT5651_CH4_R_SEL_SL2			(0x2)
+#define RT5651_CH4_R_SEL_SL3			(0x3)
+#define RT5651_CH4_R_SEL_SL4			(0x4)
+#define RT5651_CH4_R_SEL_SL5			(0x5)
+#define RT5651_CH4_R_SEL_SL6			(0x6)
+#define RT5651_CH4_R_SEL_SL7			(0x7)
+
+/* Global Clock Control (0x80) */
+#define RT5651_SCLK_SRC_MASK			(0x3 << 14)
+#define RT5651_SCLK_SRC_SFT			14
+#define RT5651_SCLK_SRC_MCLK			(0x0 << 14)
+#define RT5651_SCLK_SRC_PLL1			(0x1 << 14)
+#define RT5651_SCLK_SRC_RCCLK			(0x2 << 14)
+#define RT5651_PLL1_SRC_MASK			(0x3 << 12)
+#define RT5651_PLL1_SRC_SFT			12
+#define RT5651_PLL1_SRC_MCLK			(0x0 << 12)
+#define RT5651_PLL1_SRC_BCLK1			(0x1 << 12)
+#define RT5651_PLL1_SRC_BCLK2			(0x2 << 12)
+#define RT5651_PLL1_PD_MASK			(0x1 << 3)
+#define RT5651_PLL1_PD_SFT			3
+#define RT5651_PLL1_PD_1			(0x0 << 3)
+#define RT5651_PLL1_PD_2			(0x1 << 3)
+
+#define RT5651_PLL_INP_MAX			40000000
+#define RT5651_PLL_INP_MIN			256000
+/* PLL M/N/K Code Control 1 (0x81) */
+#define RT5651_PLL_N_MAX			0x1ff
+#define RT5651_PLL_N_MASK			(RT5651_PLL_N_MAX << 7)
+#define RT5651_PLL_N_SFT			7
+#define RT5651_PLL_K_MAX			0x1f
+#define RT5651_PLL_K_MASK			(RT5651_PLL_K_MAX)
+#define RT5651_PLL_K_SFT			0
+
+/* PLL M/N/K Code Control 2 (0x82) */
+#define RT5651_PLL_M_MAX			0xf
+#define RT5651_PLL_M_MASK			(RT5651_PLL_M_MAX << 12)
+#define RT5651_PLL_M_SFT			12
+#define RT5651_PLL_M_BP				(0x1 << 11)
+#define RT5651_PLL_M_BP_SFT			11
+
+/* PLL tracking mode 1 (0x83) */
+#define RT5651_STO1_T_MASK			(0x1 << 15)
+#define RT5651_STO1_T_SFT			15
+#define RT5651_STO1_T_SCLK			(0x0 << 15)
+#define RT5651_STO1_T_LRCK1			(0x1 << 15)
+#define RT5651_STO2_T_MASK			(0x1 << 12)
+#define RT5651_STO2_T_SFT			12
+#define RT5651_STO2_T_I2S2			(0x0 << 12)
+#define RT5651_STO2_T_LRCK2			(0x1 << 12)
+#define RT5651_ASRC2_REF_MASK			(0x1 << 11)
+#define RT5651_ASRC2_REF_SFT			11
+#define RT5651_ASRC2_REF_LRCK2			(0x0 << 11)
+#define RT5651_ASRC2_REF_LRCK1			(0x1 << 11)
+#define RT5651_DMIC_1_M_MASK			(0x1 << 9)
+#define RT5651_DMIC_1_M_SFT			9
+#define RT5651_DMIC_1_M_NOR			(0x0 << 9)
+#define RT5651_DMIC_1_M_ASYN			(0x1 << 9)
+
+/* PLL tracking mode 2 (0x84) */
+#define RT5651_STO1_ASRC_EN			(0x1 << 15)
+#define RT5651_STO1_ASRC_EN_SFT			15
+#define RT5651_STO2_ASRC_EN			(0x1 << 14)
+#define RT5651_STO2_ASRC_EN_SFT			14
+#define RT5651_STO1_DAC_M_MASK			(0x1 << 13)
+#define RT5651_STO1_DAC_M_SFT			13
+#define RT5651_STO1_DAC_M_NOR			(0x0 << 13)
+#define RT5651_STO1_DAC_M_ASRC			(0x1 << 13)
+#define RT5651_STO2_DAC_M_MASK			(0x1 << 12)
+#define RT5651_STO2_DAC_M_SFT			12
+#define RT5651_STO2_DAC_M_NOR			(0x0 << 12)
+#define RT5651_STO2_DAC_M_ASRC			(0x1 << 12)
+#define RT5651_ADC_M_MASK			(0x1 << 11)
+#define RT5651_ADC_M_SFT			11
+#define RT5651_ADC_M_NOR			(0x0 << 11)
+#define RT5651_ADC_M_ASRC			(0x1 << 11)
+#define RT5651_I2S1_R_D_MASK			(0x1 << 4)
+#define RT5651_I2S1_R_D_SFT			4
+#define RT5651_I2S1_R_D_DIS			(0x0 << 4)
+#define RT5651_I2S1_R_D_EN			(0x1 << 4)
+#define RT5651_I2S2_R_D_MASK			(0x1 << 3)
+#define RT5651_I2S2_R_D_SFT			3
+#define RT5651_I2S2_R_D_DIS			(0x0 << 3)
+#define RT5651_I2S2_R_D_EN			(0x1 << 3)
+#define RT5651_PRE_SCLK_MASK			(0x3)
+#define RT5651_PRE_SCLK_SFT			0
+#define RT5651_PRE_SCLK_512			(0x0)
+#define RT5651_PRE_SCLK_1024			(0x1)
+#define RT5651_PRE_SCLK_2048			(0x2)
+
+/* PLL tracking mode 3 (0x85) */
+#define RT5651_I2S1_RATE_MASK			(0xf << 12)
+#define RT5651_I2S1_RATE_SFT			12
+#define RT5651_I2S2_RATE_MASK			(0xf << 8)
+#define RT5651_I2S2_RATE_SFT			8
+#define RT5651_G_ASRC_LP_MASK			(0x1 << 3)
+#define RT5651_G_ASRC_LP_SFT			3
+#define RT5651_ASRC_LP_F_M			(0x1 << 2)
+#define RT5651_ASRC_LP_F_SFT			2
+#define RT5651_ASRC_LP_F_NOR			(0x0 << 2)
+#define RT5651_ASRC_LP_F_SB			(0x1 << 2)
+#define RT5651_FTK_PH_DET_MASK			(0x3)
+#define RT5651_FTK_PH_DET_SFT			0
+#define RT5651_FTK_PH_DET_DIV1			(0x0)
+#define RT5651_FTK_PH_DET_DIV2			(0x1)
+#define RT5651_FTK_PH_DET_DIV4			(0x2)
+#define RT5651_FTK_PH_DET_DIV8			(0x3)
+
+/*PLL tracking mode 6 (0x89) */
+#define RT5651_I2S1_PD_MASK			(0x7 << 12)
+#define RT5651_I2S1_PD_SFT			12
+#define RT5651_I2S2_PD_MASK			(0x7 << 8)
+#define RT5651_I2S2_PD_SFT			8
+
+/*PLL tracking mode 7 (0x8a) */
+#define RT5651_FSI1_RATE_MASK			(0xf << 12)
+#define RT5651_FSI1_RATE_SFT			12
+#define RT5651_FSI2_RATE_MASK			(0xf << 8)
+#define RT5651_FSI2_RATE_SFT			8
+
+/* HPOUT Over Current Detection (0x8b) */
+#define RT5651_HP_OVCD_MASK			(0x1 << 10)
+#define RT5651_HP_OVCD_SFT			10
+#define RT5651_HP_OVCD_DIS			(0x0 << 10)
+#define RT5651_HP_OVCD_EN			(0x1 << 10)
+#define RT5651_HP_OC_TH_MASK			(0x3 << 8)
+#define RT5651_HP_OC_TH_SFT			8
+#define RT5651_HP_OC_TH_90			(0x0 << 8)
+#define RT5651_HP_OC_TH_105			(0x1 << 8)
+#define RT5651_HP_OC_TH_120			(0x2 << 8)
+#define RT5651_HP_OC_TH_135			(0x3 << 8)
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5651_SMT_TRIG_MASK			(0x1 << 15)
+#define RT5651_SMT_TRIG_SFT			15
+#define RT5651_SMT_TRIG_DIS			(0x0 << 15)
+#define RT5651_SMT_TRIG_EN			(0x1 << 15)
+#define RT5651_HP_L_SMT_MASK			(0x1 << 9)
+#define RT5651_HP_L_SMT_SFT			9
+#define RT5651_HP_L_SMT_DIS			(0x0 << 9)
+#define RT5651_HP_L_SMT_EN			(0x1 << 9)
+#define RT5651_HP_R_SMT_MASK			(0x1 << 8)
+#define RT5651_HP_R_SMT_SFT			8
+#define RT5651_HP_R_SMT_DIS			(0x0 << 8)
+#define RT5651_HP_R_SMT_EN			(0x1 << 8)
+#define RT5651_HP_CD_PD_MASK			(0x1 << 7)
+#define RT5651_HP_CD_PD_SFT			7
+#define RT5651_HP_CD_PD_DIS			(0x0 << 7)
+#define RT5651_HP_CD_PD_EN			(0x1 << 7)
+#define RT5651_RSTN_MASK			(0x1 << 6)
+#define RT5651_RSTN_SFT				6
+#define RT5651_RSTN_DIS				(0x0 << 6)
+#define RT5651_RSTN_EN				(0x1 << 6)
+#define RT5651_RSTP_MASK			(0x1 << 5)
+#define RT5651_RSTP_SFT				5
+#define RT5651_RSTP_DIS				(0x0 << 5)
+#define RT5651_RSTP_EN				(0x1 << 5)
+#define RT5651_HP_CO_MASK			(0x1 << 4)
+#define RT5651_HP_CO_SFT			4
+#define RT5651_HP_CO_DIS			(0x0 << 4)
+#define RT5651_HP_CO_EN				(0x1 << 4)
+#define RT5651_HP_CP_MASK			(0x1 << 3)
+#define RT5651_HP_CP_SFT			3
+#define RT5651_HP_CP_PD				(0x0 << 3)
+#define RT5651_HP_CP_PU				(0x1 << 3)
+#define RT5651_HP_SG_MASK			(0x1 << 2)
+#define RT5651_HP_SG_SFT			2
+#define RT5651_HP_SG_DIS			(0x0 << 2)
+#define RT5651_HP_SG_EN				(0x1 << 2)
+#define RT5651_HP_DP_MASK			(0x1 << 1)
+#define RT5651_HP_DP_SFT			1
+#define RT5651_HP_DP_PD				(0x0 << 1)
+#define RT5651_HP_DP_PU				(0x1 << 1)
+#define RT5651_HP_CB_MASK			(0x1)
+#define RT5651_HP_CB_SFT			0
+#define RT5651_HP_CB_PD				(0x0)
+#define RT5651_HP_CB_PU				(0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5651_DEPOP_MASK			(0x1 << 13)
+#define RT5651_DEPOP_SFT			13
+#define RT5651_DEPOP_AUTO			(0x0 << 13)
+#define RT5651_DEPOP_MAN			(0x1 << 13)
+#define RT5651_RAMP_MASK			(0x1 << 12)
+#define RT5651_RAMP_SFT				12
+#define RT5651_RAMP_DIS				(0x0 << 12)
+#define RT5651_RAMP_EN				(0x1 << 12)
+#define RT5651_BPS_MASK				(0x1 << 11)
+#define RT5651_BPS_SFT				11
+#define RT5651_BPS_DIS				(0x0 << 11)
+#define RT5651_BPS_EN				(0x1 << 11)
+#define RT5651_FAST_UPDN_MASK			(0x1 << 10)
+#define RT5651_FAST_UPDN_SFT			10
+#define RT5651_FAST_UPDN_DIS			(0x0 << 10)
+#define RT5651_FAST_UPDN_EN			(0x1 << 10)
+#define RT5651_MRES_MASK			(0x3 << 8)
+#define RT5651_MRES_SFT				8
+#define RT5651_MRES_15MO			(0x0 << 8)
+#define RT5651_MRES_25MO			(0x1 << 8)
+#define RT5651_MRES_35MO			(0x2 << 8)
+#define RT5651_MRES_45MO			(0x3 << 8)
+#define RT5651_VLO_MASK				(0x1 << 7)
+#define RT5651_VLO_SFT				7
+#define RT5651_VLO_3V				(0x0 << 7)
+#define RT5651_VLO_32V				(0x1 << 7)
+#define RT5651_DIG_DP_MASK			(0x1 << 6)
+#define RT5651_DIG_DP_SFT			6
+#define RT5651_DIG_DP_DIS			(0x0 << 6)
+#define RT5651_DIG_DP_EN			(0x1 << 6)
+#define RT5651_DP_TH_MASK			(0x3 << 4)
+#define RT5651_DP_TH_SFT			4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5651_CP_SYS_MASK			(0x7 << 12)
+#define RT5651_CP_SYS_SFT			12
+#define RT5651_CP_FQ1_MASK			(0x7 << 8)
+#define RT5651_CP_FQ1_SFT			8
+#define RT5651_CP_FQ2_MASK			(0x7 << 4)
+#define RT5651_CP_FQ2_SFT			4
+#define RT5651_CP_FQ3_MASK			(0x7)
+#define RT5651_CP_FQ3_SFT			0
+#define RT5651_CP_FQ_1_5_KHZ			0
+#define RT5651_CP_FQ_3_KHZ			1
+#define RT5651_CP_FQ_6_KHZ			2
+#define RT5651_CP_FQ_12_KHZ			3
+#define RT5651_CP_FQ_24_KHZ			4
+#define RT5651_CP_FQ_48_KHZ			5
+#define RT5651_CP_FQ_96_KHZ			6
+#define RT5651_CP_FQ_192_KHZ			7
+
+/* HPOUT charge pump (0x91) */
+#define RT5651_OSW_L_MASK			(0x1 << 11)
+#define RT5651_OSW_L_SFT			11
+#define RT5651_OSW_L_DIS			(0x0 << 11)
+#define RT5651_OSW_L_EN				(0x1 << 11)
+#define RT5651_OSW_R_MASK			(0x1 << 10)
+#define RT5651_OSW_R_SFT			10
+#define RT5651_OSW_R_DIS			(0x0 << 10)
+#define RT5651_OSW_R_EN				(0x1 << 10)
+#define RT5651_PM_HP_MASK			(0x3 << 8)
+#define RT5651_PM_HP_SFT			8
+#define RT5651_PM_HP_LV				(0x0 << 8)
+#define RT5651_PM_HP_MV				(0x1 << 8)
+#define RT5651_PM_HP_HV				(0x2 << 8)
+#define RT5651_IB_HP_MASK			(0x3 << 6)
+#define RT5651_IB_HP_SFT			6
+#define RT5651_IB_HP_125IL			(0x0 << 6)
+#define RT5651_IB_HP_25IL			(0x1 << 6)
+#define RT5651_IB_HP_5IL			(0x2 << 6)
+#define RT5651_IB_HP_1IL			(0x3 << 6)
+
+/* Micbias Control (0x93) */
+#define RT5651_MIC1_BS_MASK			(0x1 << 15)
+#define RT5651_MIC1_BS_SFT			15
+#define RT5651_MIC1_BS_9AV			(0x0 << 15)
+#define RT5651_MIC1_BS_75AV			(0x1 << 15)
+#define RT5651_MIC1_CLK_MASK			(0x1 << 13)
+#define RT5651_MIC1_CLK_SFT			13
+#define RT5651_MIC1_CLK_DIS			(0x0 << 13)
+#define RT5651_MIC1_CLK_EN			(0x1 << 13)
+#define RT5651_MIC1_OVCD_MASK			(0x1 << 11)
+#define RT5651_MIC1_OVCD_SFT			11
+#define RT5651_MIC1_OVCD_DIS			(0x0 << 11)
+#define RT5651_MIC1_OVCD_EN			(0x1 << 11)
+#define RT5651_MIC1_OVTH_MASK			(0x3 << 9)
+#define RT5651_MIC1_OVTH_SFT			9
+#define RT5651_MIC1_OVTH_600UA			(0x0 << 9)
+#define RT5651_MIC1_OVTH_1500UA			(0x1 << 9)
+#define RT5651_MIC1_OVTH_2000UA			(0x2 << 9)
+#define RT5651_PWR_MB_MASK			(0x1 << 5)
+#define RT5651_PWR_MB_SFT			5
+#define RT5651_PWR_MB_PD			(0x0 << 5)
+#define RT5651_PWR_MB_PU			(0x1 << 5)
+#define RT5651_PWR_CLK12M_MASK			(0x1 << 4)
+#define RT5651_PWR_CLK12M_SFT			4
+#define RT5651_PWR_CLK12M_PD			(0x0 << 4)
+#define RT5651_PWR_CLK12M_PU			(0x1 << 4)
+
+/* Analog JD Control 1 (0x94) */
+#define RT5651_JD2_CMP_MASK			(0x7 << 12)
+#define RT5651_JD2_CMP_SFT			12
+#define RT5651_JD_PU				(0x1 << 11)
+#define RT5651_JD_PU_SFT			11
+#define RT5651_JD_PD				(0x1 << 10)
+#define RT5651_JD_PD_SFT			10
+#define RT5651_JD_MODE_SEL_MASK			(0x3 << 8)
+#define RT5651_JD_MODE_SEL_SFT			8
+#define RT5651_JD_MODE_SEL_M0			(0x0 << 8)
+#define RT5651_JD_MODE_SEL_M1			(0x1 << 8)
+#define RT5651_JD_MODE_SEL_M2			(0x2 << 8)
+#define RT5651_JD_M_CMP				(0x7 << 4)
+#define RT5651_JD_M_CMP_SFT			4
+#define RT5651_JD_M_PU				(0x1 << 3)
+#define RT5651_JD_M_PU_SFT			3
+#define RT5651_JD_M_PD				(0x1 << 2)
+#define RT5651_JD_M_PD_SFT			2
+#define RT5651_JD_M_MODE_SEL_MASK		(0x3)
+#define RT5651_JD_M_MODE_SEL_SFT		0
+#define RT5651_JD_M_MODE_SEL_M0			(0x0)
+#define RT5651_JD_M_MODE_SEL_M1			(0x1)
+#define RT5651_JD_M_MODE_SEL_M2			(0x2)
+
+/* Analog JD Control 2 (0x95) */
+#define RT5651_JD3_CMP_MASK			(0x7 << 12)
+#define RT5651_JD3_CMP_SFT			12
+
+/* EQ Control 1 (0xb0) */
+#define RT5651_EQ_SRC_MASK			(0x1 << 15)
+#define RT5651_EQ_SRC_SFT			15
+#define RT5651_EQ_SRC_DAC			(0x0 << 15)
+#define RT5651_EQ_SRC_ADC			(0x1 << 15)
+#define RT5651_EQ_UPD				(0x1 << 14)
+#define RT5651_EQ_UPD_BIT			14
+#define RT5651_EQ_CD_MASK			(0x1 << 13)
+#define RT5651_EQ_CD_SFT			13
+#define RT5651_EQ_CD_DIS			(0x0 << 13)
+#define RT5651_EQ_CD_EN				(0x1 << 13)
+#define RT5651_EQ_DITH_MASK			(0x3 << 8)
+#define RT5651_EQ_DITH_SFT			8
+#define RT5651_EQ_DITH_NOR			(0x0 << 8)
+#define RT5651_EQ_DITH_LSB			(0x1 << 8)
+#define RT5651_EQ_DITH_LSB_1			(0x2 << 8)
+#define RT5651_EQ_DITH_LSB_2			(0x3 << 8)
+#define RT5651_EQ_CD_F				(0x1 << 7)
+#define RT5651_EQ_CD_F_BIT			7
+#define RT5651_EQ_STA_HP2			(0x1 << 6)
+#define RT5651_EQ_STA_HP2_BIT			6
+#define RT5651_EQ_STA_HP1			(0x1 << 5)
+#define RT5651_EQ_STA_HP1_BIT			5
+#define RT5651_EQ_STA_BP4			(0x1 << 4)
+#define RT5651_EQ_STA_BP4_BIT			4
+#define RT5651_EQ_STA_BP3			(0x1 << 3)
+#define RT5651_EQ_STA_BP3_BIT			3
+#define RT5651_EQ_STA_BP2			(0x1 << 2)
+#define RT5651_EQ_STA_BP2_BIT			2
+#define RT5651_EQ_STA_BP1			(0x1 << 1)
+#define RT5651_EQ_STA_BP1_BIT			1
+#define RT5651_EQ_STA_LP			(0x1)
+#define RT5651_EQ_STA_LP_BIT			0
+
+/* EQ Control 2 (0xb1) */
+#define RT5651_EQ_HPF1_M_MASK			(0x1 << 8)
+#define RT5651_EQ_HPF1_M_SFT			8
+#define RT5651_EQ_HPF1_M_HI			(0x0 << 8)
+#define RT5651_EQ_HPF1_M_1ST			(0x1 << 8)
+#define RT5651_EQ_LPF1_M_MASK			(0x1 << 7)
+#define RT5651_EQ_LPF1_M_SFT			7
+#define RT5651_EQ_LPF1_M_LO			(0x0 << 7)
+#define RT5651_EQ_LPF1_M_1ST			(0x1 << 7)
+#define RT5651_EQ_HPF2_MASK			(0x1 << 6)
+#define RT5651_EQ_HPF2_SFT			6
+#define RT5651_EQ_HPF2_DIS			(0x0 << 6)
+#define RT5651_EQ_HPF2_EN			(0x1 << 6)
+#define RT5651_EQ_HPF1_MASK			(0x1 << 5)
+#define RT5651_EQ_HPF1_SFT			5
+#define RT5651_EQ_HPF1_DIS			(0x0 << 5)
+#define RT5651_EQ_HPF1_EN			(0x1 << 5)
+#define RT5651_EQ_BPF4_MASK			(0x1 << 4)
+#define RT5651_EQ_BPF4_SFT			4
+#define RT5651_EQ_BPF4_DIS			(0x0 << 4)
+#define RT5651_EQ_BPF4_EN			(0x1 << 4)
+#define RT5651_EQ_BPF3_MASK			(0x1 << 3)
+#define RT5651_EQ_BPF3_SFT			3
+#define RT5651_EQ_BPF3_DIS			(0x0 << 3)
+#define RT5651_EQ_BPF3_EN			(0x1 << 3)
+#define RT5651_EQ_BPF2_MASK			(0x1 << 2)
+#define RT5651_EQ_BPF2_SFT			2
+#define RT5651_EQ_BPF2_DIS			(0x0 << 2)
+#define RT5651_EQ_BPF2_EN			(0x1 << 2)
+#define RT5651_EQ_BPF1_MASK			(0x1 << 1)
+#define RT5651_EQ_BPF1_SFT			1
+#define RT5651_EQ_BPF1_DIS			(0x0 << 1)
+#define RT5651_EQ_BPF1_EN			(0x1 << 1)
+#define RT5651_EQ_LPF_MASK			(0x1)
+#define RT5651_EQ_LPF_SFT			0
+#define RT5651_EQ_LPF_DIS			(0x0)
+#define RT5651_EQ_LPF_EN			(0x1)
+#define RT5651_EQ_CTRL_MASK			(0x7f)
+
+/* Memory Test (0xb2) */
+#define RT5651_MT_MASK				(0x1 << 15)
+#define RT5651_MT_SFT				15
+#define RT5651_MT_DIS				(0x0 << 15)
+#define RT5651_MT_EN				(0x1 << 15)
+
+/* ALC Control 1 (0xb4) */
+#define RT5651_ALC_P_MASK			(0x1 << 15)
+#define RT5651_ALC_P_SFT			15
+#define RT5651_ALC_P_DAC			(0x0 << 15)
+#define RT5651_ALC_P_ADC			(0x1 << 15)
+#define RT5651_ALC_MASK				(0x1 << 14)
+#define RT5651_ALC_SFT				14
+#define RT5651_ALC_DIS				(0x0 << 14)
+#define RT5651_ALC_EN				(0x1 << 14)
+#define RT5651_ALC_UPD				(0x1 << 13)
+#define RT5651_ALC_UPD_BIT			13
+#define RT5651_ALC_AR_MASK			(0x1f << 8)
+#define RT5651_ALC_AR_SFT			8
+#define RT5651_ALC_R_MASK			(0x7 << 5)
+#define RT5651_ALC_R_SFT			5
+#define RT5651_ALC_R_48K			(0x1 << 5)
+#define RT5651_ALC_R_96K			(0x2 << 5)
+#define RT5651_ALC_R_192K			(0x3 << 5)
+#define RT5651_ALC_R_441K			(0x5 << 5)
+#define RT5651_ALC_R_882K			(0x6 << 5)
+#define RT5651_ALC_R_1764K			(0x7 << 5)
+#define RT5651_ALC_RC_MASK			(0x1f)
+#define RT5651_ALC_RC_SFT			0
+
+/* ALC Control 2 (0xb5) */
+#define RT5651_ALC_POB_MASK			(0x3f << 8)
+#define RT5651_ALC_POB_SFT			8
+#define RT5651_ALC_DRC_MASK			(0x1 << 7)
+#define RT5651_ALC_DRC_SFT			7
+#define RT5651_ALC_DRC_DIS			(0x0 << 7)
+#define RT5651_ALC_DRC_EN			(0x1 << 7)
+#define RT5651_ALC_CPR_MASK			(0x3 << 5)
+#define RT5651_ALC_CPR_SFT			5
+#define RT5651_ALC_CPR_1_1			(0x0 << 5)
+#define RT5651_ALC_CPR_1_2			(0x1 << 5)
+#define RT5651_ALC_CPR_1_4			(0x2 << 5)
+#define RT5651_ALC_CPR_1_8			(0x3 << 5)
+#define RT5651_ALC_PRB_MASK			(0x1f)
+#define RT5651_ALC_PRB_SFT			0
+
+/* ALC Control 3 (0xb6) */
+#define RT5651_ALC_NGB_MASK			(0xf << 12)
+#define RT5651_ALC_NGB_SFT			12
+#define RT5651_ALC_TAR_MASK			(0x1f << 7)
+#define RT5651_ALC_TAR_SFT			7
+#define RT5651_ALC_NG_MASK			(0x1 << 6)
+#define RT5651_ALC_NG_SFT			6
+#define RT5651_ALC_NG_DIS			(0x0 << 6)
+#define RT5651_ALC_NG_EN			(0x1 << 6)
+#define RT5651_ALC_NGH_MASK			(0x1 << 5)
+#define RT5651_ALC_NGH_SFT			5
+#define RT5651_ALC_NGH_DIS			(0x0 << 5)
+#define RT5651_ALC_NGH_EN			(0x1 << 5)
+#define RT5651_ALC_NGT_MASK			(0x1f)
+#define RT5651_ALC_NGT_SFT			0
+
+/* Jack Detect Control 1 (0xbb) */
+#define RT5651_JD_MASK				(0x7 << 13)
+#define RT5651_JD_SFT				13
+#define RT5651_JD_DIS				(0x0 << 13)
+#define RT5651_JD_GPIO1				(0x1 << 13)
+#define RT5651_JD_GPIO2				(0x2 << 13)
+#define RT5651_JD_GPIO3				(0x3 << 13)
+#define RT5651_JD_GPIO4				(0x4 << 13)
+#define RT5651_JD_GPIO5				(0x5 << 13)
+#define RT5651_JD_GPIO6				(0x6 << 13)
+#define RT5651_JD_HP_MASK			(0x1 << 11)
+#define RT5651_JD_HP_SFT			11
+#define RT5651_JD_HP_DIS			(0x0 << 11)
+#define RT5651_JD_HP_EN				(0x1 << 11)
+#define RT5651_JD_HP_TRG_MASK			(0x1 << 10)
+#define RT5651_JD_HP_TRG_SFT			10
+#define RT5651_JD_HP_TRG_LO			(0x0 << 10)
+#define RT5651_JD_HP_TRG_HI			(0x1 << 10)
+#define RT5651_JD_SPL_MASK			(0x1 << 9)
+#define RT5651_JD_SPL_SFT			9
+#define RT5651_JD_SPL_DIS			(0x0 << 9)
+#define RT5651_JD_SPL_EN			(0x1 << 9)
+#define RT5651_JD_SPL_TRG_MASK			(0x1 << 8)
+#define RT5651_JD_SPL_TRG_SFT			8
+#define RT5651_JD_SPL_TRG_LO			(0x0 << 8)
+#define RT5651_JD_SPL_TRG_HI			(0x1 << 8)
+#define RT5651_JD_SPR_MASK			(0x1 << 7)
+#define RT5651_JD_SPR_SFT			7
+#define RT5651_JD_SPR_DIS			(0x0 << 7)
+#define RT5651_JD_SPR_EN			(0x1 << 7)
+#define RT5651_JD_SPR_TRG_MASK			(0x1 << 6)
+#define RT5651_JD_SPR_TRG_SFT			6
+#define RT5651_JD_SPR_TRG_LO			(0x0 << 6)
+#define RT5651_JD_SPR_TRG_HI			(0x1 << 6)
+#define RT5651_JD_LO_MASK			(0x1 << 3)
+#define RT5651_JD_LO_SFT			3
+#define RT5651_JD_LO_DIS			(0x0 << 3)
+#define RT5651_JD_LO_EN				(0x1 << 3)
+#define RT5651_JD_LO_TRG_MASK			(0x1 << 2)
+#define RT5651_JD_LO_TRG_SFT			2
+#define RT5651_JD_LO_TRG_LO			(0x0 << 2)
+#define RT5651_JD_LO_TRG_HI			(0x1 << 2)
+
+/* Jack Detect Control 2 (0xbc) */
+#define RT5651_JD_TRG_SEL_MASK			(0x7 << 9)
+#define RT5651_JD_TRG_SEL_SFT			9
+#define RT5651_JD_TRG_SEL_GPIO			(0x0 << 9)
+#define RT5651_JD_TRG_SEL_JD1_1			(0x1 << 9)
+#define RT5651_JD_TRG_SEL_JD1_2			(0x2 << 9)
+#define RT5651_JD_TRG_SEL_JD2			(0x3 << 9)
+#define RT5651_JD_TRG_SEL_JD3			(0x4 << 9)
+#define RT5651_JD3_IRQ_EN			(0x1 << 8)
+#define RT5651_JD3_IRQ_EN_SFT			8
+#define RT5651_JD3_EN_STKY			(0x1 << 7)
+#define RT5651_JD3_EN_STKY_SFT			7
+#define RT5651_JD3_INV				(0x1 << 6)
+#define RT5651_JD3_INV_SFT			6
+
+/* IRQ Control 1 (0xbd) */
+#define RT5651_IRQ_JD_MASK			(0x1 << 15)
+#define RT5651_IRQ_JD_SFT			15
+#define RT5651_IRQ_JD_BP			(0x0 << 15)
+#define RT5651_IRQ_JD_NOR			(0x1 << 15)
+#define RT5651_JD_STKY_MASK			(0x1 << 13)
+#define RT5651_JD_STKY_SFT			13
+#define RT5651_JD_STKY_DIS			(0x0 << 13)
+#define RT5651_JD_STKY_EN			(0x1 << 13)
+#define RT5651_JD_P_MASK			(0x1 << 11)
+#define RT5651_JD_P_SFT				11
+#define RT5651_JD_P_NOR				(0x0 << 11)
+#define RT5651_JD_P_INV				(0x1 << 11)
+#define RT5651_JD1_1_IRQ_EN			(0x1 << 9)
+#define RT5651_JD1_1_IRQ_EN_SFT			9
+#define RT5651_JD1_1_EN_STKY			(0x1 << 8)
+#define RT5651_JD1_1_EN_STKY_SFT			8
+#define RT5651_JD1_1_INV			(0x1 << 7)
+#define RT5651_JD1_1_INV_SFT			7
+#define RT5651_JD1_2_IRQ_EN			(0x1 << 6)
+#define RT5651_JD1_2_IRQ_EN_SFT			6
+#define RT5651_JD1_2_EN_STKY			(0x1 << 5)
+#define RT5651_JD1_2_EN_STKY_SFT			5
+#define RT5651_JD1_2_INV			(0x1 << 4)
+#define RT5651_JD1_2_INV_SFT			4
+#define RT5651_JD2_IRQ_EN			(0x1 << 3)
+#define RT5651_JD2_IRQ_EN_SFT			3
+#define RT5651_JD2_EN_STKY			(0x1 << 2)
+#define RT5651_JD2_EN_STKY_SFT			2
+#define RT5651_JD2_INV				(0x1 << 1)
+#define RT5651_JD2_INV_SFT			1
+
+/* IRQ Control 2 (0xbe) */
+#define RT5651_IRQ_MB1_OC_MASK			(0x1 << 15)
+#define RT5651_IRQ_MB1_OC_SFT			15
+#define RT5651_IRQ_MB1_OC_BP			(0x0 << 15)
+#define RT5651_IRQ_MB1_OC_NOR			(0x1 << 15)
+#define RT5651_MB1_OC_STKY_MASK			(0x1 << 11)
+#define RT5651_MB1_OC_STKY_SFT			11
+#define RT5651_MB1_OC_STKY_DIS			(0x0 << 11)
+#define RT5651_MB1_OC_STKY_EN			(0x1 << 11)
+#define RT5651_MB1_OC_P_MASK			(0x1 << 7)
+#define RT5651_MB1_OC_P_SFT			7
+#define RT5651_MB1_OC_P_NOR			(0x0 << 7)
+#define RT5651_MB1_OC_P_INV			(0x1 << 7)
+#define RT5651_MB2_OC_P_MASK			(0x1 << 6)
+#define RT5651_MB1_OC_CLR			(0x1 << 3)
+#define RT5651_MB1_OC_CLR_SFT			3
+#define RT5651_STA_GPIO8			(0x1)
+#define RT5651_STA_GPIO8_BIT			0
+
+/* Internal Status and GPIO status (0xbf) */
+#define RT5651_STA_JD3				(0x1 << 15)
+#define RT5651_STA_JD3_BIT			15
+#define RT5651_STA_JD2				(0x1 << 14)
+#define RT5651_STA_JD2_BIT			14
+#define RT5651_STA_JD1_2			(0x1 << 13)
+#define RT5651_STA_JD1_2_BIT			13
+#define RT5651_STA_JD1_1			(0x1 << 12)
+#define RT5651_STA_JD1_1_BIT			12
+#define RT5651_STA_GP7				(0x1 << 11)
+#define RT5651_STA_GP7_BIT			11
+#define RT5651_STA_GP6				(0x1 << 10)
+#define RT5651_STA_GP6_BIT			10
+#define RT5651_STA_GP5				(0x1 << 9)
+#define RT5651_STA_GP5_BIT			9
+#define RT5651_STA_GP1				(0x1 << 8)
+#define RT5651_STA_GP1_BIT			8
+#define RT5651_STA_GP2				(0x1 << 7)
+#define RT5651_STA_GP2_BIT			7
+#define RT5651_STA_GP3				(0x1 << 6)
+#define RT5651_STA_GP3_BIT			6
+#define RT5651_STA_GP4				(0x1 << 5)
+#define RT5651_STA_GP4_BIT			5
+#define RT5651_STA_GP_JD			(0x1 << 4)
+#define RT5651_STA_GP_JD_BIT			4
+
+/* GPIO Control 1 (0xc0) */
+#define RT5651_GP1_PIN_MASK			(0x1 << 15)
+#define RT5651_GP1_PIN_SFT			15
+#define RT5651_GP1_PIN_GPIO1			(0x0 << 15)
+#define RT5651_GP1_PIN_IRQ			(0x1 << 15)
+#define RT5651_GP2_PIN_MASK			(0x1 << 14)
+#define RT5651_GP2_PIN_SFT			14
+#define RT5651_GP2_PIN_GPIO2			(0x0 << 14)
+#define RT5651_GP2_PIN_DMIC1_SCL		(0x1 << 14)
+#define RT5651_GPIO_M_MASK			(0x1 << 9)
+#define RT5651_GPIO_M_SFT			9
+#define RT5651_GPIO_M_FLT			(0x0 << 9)
+#define RT5651_GPIO_M_PH			(0x1 << 9)
+#define RT5651_I2S2_SEL_MASK			(0x1 << 8)
+#define RT5651_I2S2_SEL_SFT			8
+#define RT5651_I2S2_SEL_I2S			(0x0 << 8)
+#define RT5651_I2S2_SEL_GPIO			(0x1 << 8)
+#define RT5651_GP5_PIN_MASK			(0x1 << 7)
+#define RT5651_GP5_PIN_SFT			7
+#define RT5651_GP5_PIN_GPIO5			(0x0 << 7)
+#define RT5651_GP5_PIN_IRQ			(0x1 << 7)
+#define RT5651_GP6_PIN_MASK			(0x1 << 6)
+#define RT5651_GP6_PIN_SFT			6
+#define RT5651_GP6_PIN_GPIO6			(0x0 << 6)
+#define RT5651_GP6_PIN_DMIC_SDA			(0x1 << 6)
+#define RT5651_GP7_PIN_MASK			(0x1 << 5)
+#define RT5651_GP7_PIN_SFT			5
+#define RT5651_GP7_PIN_GPIO7			(0x0 << 5)
+#define RT5651_GP7_PIN_IRQ			(0x1 << 5)
+#define RT5651_GP8_PIN_MASK			(0x1 << 4)
+#define RT5651_GP8_PIN_SFT			4
+#define RT5651_GP8_PIN_GPIO8			(0x0 << 4)
+#define RT5651_GP8_PIN_DMIC_SDA			(0x1 << 4)
+#define RT5651_GPIO_PDM_SEL_MASK		(0x1 << 3)
+#define RT5651_GPIO_PDM_SEL_SFT			3
+#define RT5651_GPIO_PDM_SEL_GPIO		(0x0 << 3)
+#define RT5651_GPIO_PDM_SEL_PDM			(0x1 << 3)
+
+/* GPIO Control 2 (0xc1) */
+#define RT5651_GP5_DR_MASK			(0x1 << 14)
+#define RT5651_GP5_DR_SFT			14
+#define RT5651_GP5_DR_IN			(0x0 << 14)
+#define RT5651_GP5_DR_OUT			(0x1 << 14)
+#define RT5651_GP5_OUT_MASK			(0x1 << 13)
+#define RT5651_GP5_OUT_SFT			13
+#define RT5651_GP5_OUT_LO			(0x0 << 13)
+#define RT5651_GP5_OUT_HI			(0x1 << 13)
+#define RT5651_GP5_P_MASK			(0x1 << 12)
+#define RT5651_GP5_P_SFT			12
+#define RT5651_GP5_P_NOR			(0x0 << 12)
+#define RT5651_GP5_P_INV			(0x1 << 12)
+#define RT5651_GP4_DR_MASK			(0x1 << 11)
+#define RT5651_GP4_DR_SFT			11
+#define RT5651_GP4_DR_IN			(0x0 << 11)
+#define RT5651_GP4_DR_OUT			(0x1 << 11)
+#define RT5651_GP4_OUT_MASK			(0x1 << 10)
+#define RT5651_GP4_OUT_SFT			10
+#define RT5651_GP4_OUT_LO			(0x0 << 10)
+#define RT5651_GP4_OUT_HI			(0x1 << 10)
+#define RT5651_GP4_P_MASK			(0x1 << 9)
+#define RT5651_GP4_P_SFT			9
+#define RT5651_GP4_P_NOR			(0x0 << 9)
+#define RT5651_GP4_P_INV			(0x1 << 9)
+#define RT5651_GP3_DR_MASK			(0x1 << 8)
+#define RT5651_GP3_DR_SFT			8
+#define RT5651_GP3_DR_IN			(0x0 << 8)
+#define RT5651_GP3_DR_OUT			(0x1 << 8)
+#define RT5651_GP3_OUT_MASK			(0x1 << 7)
+#define RT5651_GP3_OUT_SFT			7
+#define RT5651_GP3_OUT_LO			(0x0 << 7)
+#define RT5651_GP3_OUT_HI			(0x1 << 7)
+#define RT5651_GP3_P_MASK			(0x1 << 6)
+#define RT5651_GP3_P_SFT			6
+#define RT5651_GP3_P_NOR			(0x0 << 6)
+#define RT5651_GP3_P_INV			(0x1 << 6)
+#define RT5651_GP2_DR_MASK			(0x1 << 5)
+#define RT5651_GP2_DR_SFT			5
+#define RT5651_GP2_DR_IN			(0x0 << 5)
+#define RT5651_GP2_DR_OUT			(0x1 << 5)
+#define RT5651_GP2_OUT_MASK			(0x1 << 4)
+#define RT5651_GP2_OUT_SFT			4
+#define RT5651_GP2_OUT_LO			(0x0 << 4)
+#define RT5651_GP2_OUT_HI			(0x1 << 4)
+#define RT5651_GP2_P_MASK			(0x1 << 3)
+#define RT5651_GP2_P_SFT			3
+#define RT5651_GP2_P_NOR			(0x0 << 3)
+#define RT5651_GP2_P_INV			(0x1 << 3)
+#define RT5651_GP1_DR_MASK			(0x1 << 2)
+#define RT5651_GP1_DR_SFT			2
+#define RT5651_GP1_DR_IN			(0x0 << 2)
+#define RT5651_GP1_DR_OUT			(0x1 << 2)
+#define RT5651_GP1_OUT_MASK			(0x1 << 1)
+#define RT5651_GP1_OUT_SFT			1
+#define RT5651_GP1_OUT_LO			(0x0 << 1)
+#define RT5651_GP1_OUT_HI			(0x1 << 1)
+#define RT5651_GP1_P_MASK			(0x1)
+#define RT5651_GP1_P_SFT			0
+#define RT5651_GP1_P_NOR			(0x0)
+#define RT5651_GP1_P_INV			(0x1)
+
+/* GPIO Control 3 (0xc2) */
+#define RT5651_GP8_DR_MASK			(0x1 << 8)
+#define RT5651_GP8_DR_SFT			8
+#define RT5651_GP8_DR_IN			(0x0 << 8)
+#define RT5651_GP8_DR_OUT			(0x1 << 8)
+#define RT5651_GP8_OUT_MASK			(0x1 << 7)
+#define RT5651_GP8_OUT_SFT			7
+#define RT5651_GP8_OUT_LO			(0x0 << 7)
+#define RT5651_GP8_OUT_HI			(0x1 << 7)
+#define RT5651_GP8_P_MASK			(0x1 << 6)
+#define RT5651_GP8_P_SFT			6
+#define RT5651_GP8_P_NOR			(0x0 << 6)
+#define RT5651_GP8_P_INV			(0x1 << 6)
+#define RT5651_GP7_DR_MASK			(0x1 << 5)
+#define RT5651_GP7_DR_SFT			5
+#define RT5651_GP7_DR_IN			(0x0 << 5)
+#define RT5651_GP7_DR_OUT			(0x1 << 5)
+#define RT5651_GP7_OUT_MASK			(0x1 << 4)
+#define RT5651_GP7_OUT_SFT			4
+#define RT5651_GP7_OUT_LO			(0x0 << 4)
+#define RT5651_GP7_OUT_HI			(0x1 << 4)
+#define RT5651_GP7_P_MASK			(0x1 << 3)
+#define RT5651_GP7_P_SFT			3
+#define RT5651_GP7_P_NOR			(0x0 << 3)
+#define RT5651_GP7_P_INV			(0x1 << 3)
+#define RT5651_GP6_DR_MASK			(0x1 << 2)
+#define RT5651_GP6_DR_SFT			2
+#define RT5651_GP6_DR_IN			(0x0 << 2)
+#define RT5651_GP6_DR_OUT			(0x1 << 2)
+#define RT5651_GP6_OUT_MASK			(0x1 << 1)
+#define RT5651_GP6_OUT_SFT			1
+#define RT5651_GP6_OUT_LO			(0x0 << 1)
+#define RT5651_GP6_OUT_HI			(0x1 << 1)
+#define RT5651_GP6_P_MASK			(0x1)
+#define RT5651_GP6_P_SFT			0
+#define RT5651_GP6_P_NOR			(0x0)
+#define RT5651_GP6_P_INV			(0x1)
+
+/* Scramble Control (0xce) */
+#define RT5651_SCB_SWAP_MASK			(0x1 << 15)
+#define RT5651_SCB_SWAP_SFT			15
+#define RT5651_SCB_SWAP_DIS			(0x0 << 15)
+#define RT5651_SCB_SWAP_EN			(0x1 << 15)
+#define RT5651_SCB_MASK				(0x1 << 14)
+#define RT5651_SCB_SFT				14
+#define RT5651_SCB_DIS				(0x0 << 14)
+#define RT5651_SCB_EN				(0x1 << 14)
+
+/* Baseback Control (0xcf) */
+#define RT5651_BB_MASK				(0x1 << 15)
+#define RT5651_BB_SFT				15
+#define RT5651_BB_DIS				(0x0 << 15)
+#define RT5651_BB_EN				(0x1 << 15)
+#define RT5651_BB_CT_MASK			(0x7 << 12)
+#define RT5651_BB_CT_SFT			12
+#define RT5651_BB_CT_A				(0x0 << 12)
+#define RT5651_BB_CT_B				(0x1 << 12)
+#define RT5651_BB_CT_C				(0x2 << 12)
+#define RT5651_BB_CT_D				(0x3 << 12)
+#define RT5651_M_BB_L_MASK			(0x1 << 9)
+#define RT5651_M_BB_L_SFT			9
+#define RT5651_M_BB_R_MASK			(0x1 << 8)
+#define RT5651_M_BB_R_SFT			8
+#define RT5651_M_BB_HPF_L_MASK			(0x1 << 7)
+#define RT5651_M_BB_HPF_L_SFT			7
+#define RT5651_M_BB_HPF_R_MASK			(0x1 << 6)
+#define RT5651_M_BB_HPF_R_SFT			6
+#define RT5651_G_BB_BST_MASK			(0x3f)
+#define RT5651_G_BB_BST_SFT			0
+
+/* MP3 Plus Control 1 (0xd0) */
+#define RT5651_M_MP3_L_MASK			(0x1 << 15)
+#define RT5651_M_MP3_L_SFT			15
+#define RT5651_M_MP3_R_MASK			(0x1 << 14)
+#define RT5651_M_MP3_R_SFT			14
+#define RT5651_M_MP3_MASK			(0x1 << 13)
+#define RT5651_M_MP3_SFT			13
+#define RT5651_M_MP3_DIS			(0x0 << 13)
+#define RT5651_M_MP3_EN				(0x1 << 13)
+#define RT5651_EG_MP3_MASK			(0x1f << 8)
+#define RT5651_EG_MP3_SFT			8
+#define RT5651_MP3_HLP_MASK			(0x1 << 7)
+#define RT5651_MP3_HLP_SFT			7
+#define RT5651_MP3_HLP_DIS			(0x0 << 7)
+#define RT5651_MP3_HLP_EN			(0x1 << 7)
+#define RT5651_M_MP3_ORG_L_MASK			(0x1 << 6)
+#define RT5651_M_MP3_ORG_L_SFT			6
+#define RT5651_M_MP3_ORG_R_MASK			(0x1 << 5)
+#define RT5651_M_MP3_ORG_R_SFT			5
+
+/* MP3 Plus Control 2 (0xd1) */
+#define RT5651_MP3_WT_MASK			(0x1 << 13)
+#define RT5651_MP3_WT_SFT			13
+#define RT5651_MP3_WT_1_4			(0x0 << 13)
+#define RT5651_MP3_WT_1_2			(0x1 << 13)
+#define RT5651_OG_MP3_MASK			(0x1f << 8)
+#define RT5651_OG_MP3_SFT			8
+#define RT5651_HG_MP3_MASK			(0x3f)
+#define RT5651_HG_MP3_SFT			0
+
+/* 3D HP Control 1 (0xd2) */
+#define RT5651_3D_CF_MASK			(0x1 << 15)
+#define RT5651_3D_CF_SFT			15
+#define RT5651_3D_CF_DIS			(0x0 << 15)
+#define RT5651_3D_CF_EN				(0x1 << 15)
+#define RT5651_3D_HP_MASK			(0x1 << 14)
+#define RT5651_3D_HP_SFT			14
+#define RT5651_3D_HP_DIS			(0x0 << 14)
+#define RT5651_3D_HP_EN				(0x1 << 14)
+#define RT5651_3D_BT_MASK			(0x1 << 13)
+#define RT5651_3D_BT_SFT			13
+#define RT5651_3D_BT_DIS			(0x0 << 13)
+#define RT5651_3D_BT_EN				(0x1 << 13)
+#define RT5651_3D_1F_MIX_MASK			(0x3 << 11)
+#define RT5651_3D_1F_MIX_SFT			11
+#define RT5651_3D_HP_M_MASK			(0x1 << 10)
+#define RT5651_3D_HP_M_SFT			10
+#define RT5651_3D_HP_M_SUR			(0x0 << 10)
+#define RT5651_3D_HP_M_FRO			(0x1 << 10)
+#define RT5651_M_3D_HRTF_MASK			(0x1 << 9)
+#define RT5651_M_3D_HRTF_SFT			9
+#define RT5651_M_3D_D2H_MASK			(0x1 << 8)
+#define RT5651_M_3D_D2H_SFT			8
+#define RT5651_M_3D_D2R_MASK			(0x1 << 7)
+#define RT5651_M_3D_D2R_SFT			7
+#define RT5651_M_3D_REVB_MASK			(0x1 << 6)
+#define RT5651_M_3D_REVB_SFT			6
+
+/* Adjustable high pass filter control 1 (0xd3) */
+#define RT5651_2ND_HPF_MASK			(0x1 << 15)
+#define RT5651_2ND_HPF_SFT			15
+#define RT5651_2ND_HPF_DIS			(0x0 << 15)
+#define RT5651_2ND_HPF_EN			(0x1 << 15)
+#define RT5651_HPF_CF_L_MASK			(0x7 << 12)
+#define RT5651_HPF_CF_L_SFT			12
+#define RT5651_HPF_CF_R_MASK			(0x7 << 8)
+#define RT5651_HPF_CF_R_SFT			8
+#define RT5651_ZD_T_MASK			(0x3 << 6)
+#define RT5651_ZD_T_SFT				6
+#define RT5651_ZD_F_MASK			(0x3 << 4)
+#define RT5651_ZD_F_SFT				4
+#define RT5651_ZD_F_IM				(0x0 << 4)
+#define RT5651_ZD_F_ZC_IM			(0x1 << 4)
+#define RT5651_ZD_F_ZC_IOD			(0x2 << 4)
+#define RT5651_ZD_F_UN				(0x3 << 4)
+
+/* Adjustable high pass filter control 2 (0xd4) */
+#define RT5651_HPF_CF_L_NUM_MASK		(0x3f << 8)
+#define RT5651_HPF_CF_L_NUM_SFT			8
+#define RT5651_HPF_CF_R_NUM_MASK		(0x3f)
+#define RT5651_HPF_CF_R_NUM_SFT			0
+
+/* HP calibration control and Amp detection (0xd6) */
+#define RT5651_SI_DAC_MASK			(0x1 << 11)
+#define RT5651_SI_DAC_SFT			11
+#define RT5651_SI_DAC_AUTO			(0x0 << 11)
+#define RT5651_SI_DAC_TEST			(0x1 << 11)
+#define RT5651_DC_CAL_M_MASK			(0x1 << 10)
+#define RT5651_DC_CAL_M_SFT			10
+#define RT5651_DC_CAL_M_NOR			(0x0 << 10)
+#define RT5651_DC_CAL_M_CAL			(0x1 << 10)
+#define RT5651_DC_CAL_MASK			(0x1 << 9)
+#define RT5651_DC_CAL_SFT			9
+#define RT5651_DC_CAL_DIS			(0x0 << 9)
+#define RT5651_DC_CAL_EN			(0x1 << 9)
+#define RT5651_HPD_RCV_MASK			(0x7 << 6)
+#define RT5651_HPD_RCV_SFT			6
+#define RT5651_HPD_PS_MASK			(0x1 << 5)
+#define RT5651_HPD_PS_SFT			5
+#define RT5651_HPD_PS_DIS			(0x0 << 5)
+#define RT5651_HPD_PS_EN			(0x1 << 5)
+#define RT5651_CAL_M_MASK			(0x1 << 4)
+#define RT5651_CAL_M_SFT			4
+#define RT5651_CAL_M_DEP			(0x0 << 4)
+#define RT5651_CAL_M_CAL			(0x1 << 4)
+#define RT5651_CAL_MASK				(0x1 << 3)
+#define RT5651_CAL_SFT				3
+#define RT5651_CAL_DIS				(0x0 << 3)
+#define RT5651_CAL_EN				(0x1 << 3)
+#define RT5651_CAL_TEST_MASK			(0x1 << 2)
+#define RT5651_CAL_TEST_SFT			2
+#define RT5651_CAL_TEST_DIS			(0x0 << 2)
+#define RT5651_CAL_TEST_EN			(0x1 << 2)
+#define RT5651_CAL_P_MASK			(0x3)
+#define RT5651_CAL_P_SFT			0
+#define RT5651_CAL_P_NONE			(0x0)
+#define RT5651_CAL_P_CAL			(0x1)
+#define RT5651_CAL_P_DAC_CAL			(0x2)
+
+/* Soft volume and zero cross control 1 (0xd9) */
+#define RT5651_SV_MASK				(0x1 << 15)
+#define RT5651_SV_SFT				15
+#define RT5651_SV_DIS				(0x0 << 15)
+#define RT5651_SV_EN				(0x1 << 15)
+#define RT5651_OUT_SV_MASK			(0x1 << 13)
+#define RT5651_OUT_SV_SFT			13
+#define RT5651_OUT_SV_DIS			(0x0 << 13)
+#define RT5651_OUT_SV_EN			(0x1 << 13)
+#define RT5651_HP_SV_MASK			(0x1 << 12)
+#define RT5651_HP_SV_SFT			12
+#define RT5651_HP_SV_DIS			(0x0 << 12)
+#define RT5651_HP_SV_EN				(0x1 << 12)
+#define RT5651_ZCD_DIG_MASK			(0x1 << 11)
+#define RT5651_ZCD_DIG_SFT			11
+#define RT5651_ZCD_DIG_DIS			(0x0 << 11)
+#define RT5651_ZCD_DIG_EN			(0x1 << 11)
+#define RT5651_ZCD_MASK				(0x1 << 10)
+#define RT5651_ZCD_SFT				10
+#define RT5651_ZCD_PD				(0x0 << 10)
+#define RT5651_ZCD_PU				(0x1 << 10)
+#define RT5651_M_ZCD_MASK			(0x3f << 4)
+#define RT5651_M_ZCD_SFT			4
+#define RT5651_M_ZCD_OM_L			(0x1 << 7)
+#define RT5651_M_ZCD_OM_R			(0x1 << 6)
+#define RT5651_M_ZCD_RM_L			(0x1 << 5)
+#define RT5651_M_ZCD_RM_R			(0x1 << 4)
+#define RT5651_SV_DLY_MASK			(0xf)
+#define RT5651_SV_DLY_SFT			0
+
+/* Soft volume and zero cross control 2 (0xda) */
+#define RT5651_ZCD_HP_MASK			(0x1 << 15)
+#define RT5651_ZCD_HP_SFT			15
+#define RT5651_ZCD_HP_DIS			(0x0 << 15)
+#define RT5651_ZCD_HP_EN			(0x1 << 15)
+
+/* Digital Misc Control (0xfa) */
+#define RT5651_I2S2_MS_SP_MASK			(0x1 << 8)
+#define RT5651_I2S2_MS_SP_SEL			8
+#define RT5651_I2S2_MS_SP_64			(0x0 << 8)
+#define RT5651_I2S2_MS_SP_50			(0x1 << 8)
+#define RT5651_CLK_DET_EN			(0x1 << 3)
+#define RT5651_CLK_DET_EN_SFT			3
+#define RT5651_AMP_DET_EN			(0x1 << 1)
+#define RT5651_AMP_DET_EN_SFT			1
+#define RT5651_D_GATE_EN			(0x1)
+#define RT5651_D_GATE_EN_SFT			0
+
+/* Codec Private Register definition */
+/* 3D Speaker Control (0x63) */
+#define RT5651_3D_SPK_MASK			(0x1 << 15)
+#define RT5651_3D_SPK_SFT			15
+#define RT5651_3D_SPK_DIS			(0x0 << 15)
+#define RT5651_3D_SPK_EN			(0x1 << 15)
+#define RT5651_3D_SPK_M_MASK			(0x3 << 13)
+#define RT5651_3D_SPK_M_SFT			13
+#define RT5651_3D_SPK_CG_MASK			(0x1f << 8)
+#define RT5651_3D_SPK_CG_SFT			8
+#define RT5651_3D_SPK_SG_MASK			(0x1f)
+#define RT5651_3D_SPK_SG_SFT			0
+
+/* Wind Noise Detection Control 1 (0x6c) */
+#define RT5651_WND_MASK				(0x1 << 15)
+#define RT5651_WND_SFT				15
+#define RT5651_WND_DIS				(0x0 << 15)
+#define RT5651_WND_EN				(0x1 << 15)
+
+/* Wind Noise Detection Control 2 (0x6d) */
+#define RT5651_WND_FC_NW_MASK			(0x3f << 10)
+#define RT5651_WND_FC_NW_SFT			10
+#define RT5651_WND_FC_WK_MASK			(0x3f << 4)
+#define RT5651_WND_FC_WK_SFT			4
+
+/* Wind Noise Detection Control 3 (0x6e) */
+#define RT5651_HPF_FC_MASK			(0x3f << 6)
+#define RT5651_HPF_FC_SFT			6
+#define RT5651_WND_FC_ST_MASK			(0x3f)
+#define RT5651_WND_FC_ST_SFT			0
+
+/* Wind Noise Detection Control 4 (0x6f) */
+#define RT5651_WND_TH_LO_MASK			(0x3ff)
+#define RT5651_WND_TH_LO_SFT			0
+
+/* Wind Noise Detection Control 5 (0x70) */
+#define RT5651_WND_TH_HI_MASK			(0x3ff)
+#define RT5651_WND_TH_HI_SFT			0
+
+/* Wind Noise Detection Control 8 (0x73) */
+#define RT5651_WND_WIND_MASK			(0x1 << 13) /* Read-Only */
+#define RT5651_WND_WIND_SFT			13
+#define RT5651_WND_STRONG_MASK			(0x1 << 12) /* Read-Only */
+#define RT5651_WND_STRONG_SFT			12
+enum {
+	RT5651_NO_WIND,
+	RT5651_BREEZE,
+	RT5651_STORM,
+};
+
+/* Dipole Speaker Interface (0x75) */
+#define RT5651_DP_ATT_MASK			(0x3 << 14)
+#define RT5651_DP_ATT_SFT			14
+#define RT5651_DP_SPK_MASK			(0x1 << 10)
+#define RT5651_DP_SPK_SFT			10
+#define RT5651_DP_SPK_DIS			(0x0 << 10)
+#define RT5651_DP_SPK_EN			(0x1 << 10)
+
+/* EQ Pre Volume Control (0xb3) */
+#define RT5651_EQ_PRE_VOL_MASK			(0xffff)
+#define RT5651_EQ_PRE_VOL_SFT			0
+
+/* EQ Post Volume Control (0xb4) */
+#define RT5651_EQ_PST_VOL_MASK			(0xffff)
+#define RT5651_EQ_PST_VOL_SFT			0
+
+/* System Clock Source */
+enum {
+	RT5651_SCLK_S_MCLK,
+	RT5651_SCLK_S_PLL1,
+	RT5651_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+	RT5651_PLL1_S_MCLK,
+	RT5651_PLL1_S_BCLK1,
+	RT5651_PLL1_S_BCLK2,
+};
+
+enum {
+	RT5651_AIF1,
+	RT5651_AIF2,
+	RT5651_AIFS,
+};
+
+struct rt5651_pll_code {
+	bool m_bp; /* Indicates bypass m code or not. */
+	int m_code;
+	int n_code;
+	int k_code;
+};
+
+struct rt5651_priv {
+	struct snd_soc_codec *codec;
+	struct rt5651_platform_data pdata;
+	struct regmap *regmap;
+
+	int sysclk;
+	int sysclk_src;
+	int lrck[RT5651_AIFS];
+	int bclk[RT5651_AIFS];
+	int master[RT5651_AIFS];
+
+	struct rt5651_pll_code pll_code;
+	int pll_src;
+	int pll_in;
+	int pll_out;
+
+	int dmic_en;
+	bool hp_mute;
+};
+
+#endif /* __RT5651_H__ */

From 871c131dcbee80e9459bf695c8c5cfd6bf0d26d6 Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@linaro.org>
Date: Fri, 18 Apr 2014 20:02:06 +0100
Subject: [PATCH 53/86] ASoC: rt5651: Staticise non-exported symbols

Make the dai_ops const too since we can.

Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5651.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index a1577369c49cc..f785b81238aeb 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1736,14 +1736,14 @@ static int rt5651_resume(struct snd_soc_codec *codec)
 #define RT5651_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
 
-struct snd_soc_dai_ops rt5651_aif_dai_ops = {
+static const struct snd_soc_dai_ops rt5651_aif_dai_ops = {
 	.hw_params = rt5651_hw_params,
 	.set_fmt = rt5651_set_dai_fmt,
 	.set_sysclk = rt5651_set_dai_sysclk,
 	.set_pll = rt5651_set_dai_pll,
 };
 
-struct snd_soc_dai_driver rt5651_dai[] = {
+static struct snd_soc_dai_driver rt5651_dai[] = {
 	{
 		.name = "rt5651-aif1",
 		.id = RT5651_AIF1,
@@ -1882,7 +1882,7 @@ static int rt5651_i2c_remove(struct i2c_client *i2c)
 	return 0;
 }
 
-struct i2c_driver rt5651_i2c_driver = {
+static struct i2c_driver rt5651_i2c_driver = {
 	.driver = {
 		.name = "rt5651",
 		.owner = THIS_MODULE,

From a09f06401239ae4d52c4726f8469e7cd2eb2dae8 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
Date: Tue, 22 Apr 2014 10:30:33 +0300
Subject: [PATCH 54/86] ASoC: omap-hdmi: Remove excess curly bracket

Fix the error added by commit:
ASoC: omap-hdmi: Bind the platform driver to the dai driver when loading

Reported-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-hdmi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index 32614b49653cb..537a1ec8ad61a 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -330,7 +330,6 @@ static int omap_hdmi_probe(struct platform_device *pdev)
 
 	return omap_pcm_platform_register(&pdev->dev);
 }
-}
 
 static int omap_hdmi_remove(struct platform_device *pdev)
 {

From 8bfc6d2d1b6266e8da2a7cf89e8d05e2ea8b09e5 Mon Sep 17 00:00:00 2001
From: Bard Liao <bardliao@realtek.com>
Date: Thu, 17 Apr 2014 10:24:06 +0800
Subject: [PATCH 55/86] ASoC: rt5640: Add minimal support for RT5642

We have been using rt5640.c codec driver with RT5642 codec chip before commit
022d21f004c1 ("ASoC: rt5640: add rt5639 support"). That commits starts using
device ID reading in reset register for adding device specific controls and
routes runtime.

Now since device ID appears to be different between RT5640 and RT5642 the
driver doesn't add those controls and routes that are valid also on RT5642.

Fix this by adding a device ID found by debugging and minimal code for
supporting RT5642.

Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Bard Liao <bardliao@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c |  8 +++++---
 sound/soc/codecs/rt5640.h | 10 +++++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 6674372be12c0..79635ee42a61f 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1997,8 +1997,9 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 	snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030);
 	snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00);
 
-	switch (snd_soc_read(codec, RT5640_RESET)) {
-	case RT5640_RESET_ID:
+	switch (snd_soc_read(codec, RT5640_RESET) & RT5640_ID_MASK) {
+	case RT5640_ID_5640:
+	case RT5640_ID_5642:
 		snd_soc_add_codec_controls(codec,
 			rt5640_specific_snd_controls,
 			ARRAY_SIZE(rt5640_specific_snd_controls));
@@ -2009,7 +2010,7 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 			rt5640_specific_dapm_routes,
 			ARRAY_SIZE(rt5640_specific_dapm_routes));
 		break;
-	case RT5639_RESET_ID:
+	case RT5640_ID_5639:
 		snd_soc_dapm_new_controls(&codec->dapm,
 			rt5639_specific_dapm_widgets,
 			ARRAY_SIZE(rt5639_specific_dapm_widgets));
@@ -2149,6 +2150,7 @@ static const struct regmap_config rt5640_regmap = {
 static const struct i2c_device_id rt5640_i2c_id[] = {
 	{ "rt5640", 0 },
 	{ "rt5639", 0 },
+	{ "rt5642", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 3b50459a83b4b..ded20595e9ae9 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -14,9 +14,6 @@
 
 #include <sound/rt5640.h>
 
-#define RT5639_RESET_ID				0x0008
-#define RT5640_RESET_ID				0x000c
-
 /* Info */
 #define RT5640_RESET				0x00
 #define RT5640_VENDOR_ID			0xfd
@@ -195,6 +192,13 @@
 #define RT5640_R_VOL_MASK			(0x3f)
 #define RT5640_R_VOL_SFT			0
 
+/* SW Reset & Device ID (0x00) */
+#define RT5640_ID_MASK				(0x3 << 1)
+#define RT5640_ID_5639				(0x0 << 1)
+#define RT5640_ID_5640				(0x1 << 1)
+#define RT5640_ID_5642				(0x3 << 1)
+
+
 /* IN1 and IN2 Control (0x0d) */
 /* IN3 and IN4 Control (0x0e) */
 #define RT5640_BST_SFT1				12

From 33fcec2920bb07775a2adc4de77e928114e44b69 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Mon, 28 Apr 2014 16:55:21 +0800
Subject: [PATCH 56/86] ASoC: rt5640: Add the rt5639 support to the OF match
 table

The patch adds the rt5639 support to the OF match table.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 79635ee42a61f..2133fa0c51148 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2157,6 +2157,7 @@ MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
 
 #if defined(CONFIG_OF)
 static const struct of_device_id rt5640_of_match[] = {
+	{ .compatible = "realtek,rt5639", },
 	{ .compatible = "realtek,rt5640", },
 	{},
 };

From 441dc45aa21ea7e1a6283e62489b940fdb3969d8 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:19 +0200
Subject: [PATCH 57/86] ASoC: omap: rx51: Use static const char * const arrays

Mark the array and the string const by using "static const char * const
foo[]" instead of "static const char* foo[]".

Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/rx51.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index add0047ea6c5a..1a3f05ce39a51 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -258,9 +258,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
 	{"b Mic Bias", NULL, "HS Mic"}
 };
 
-static const char *spk_function[] = {"Off", "On"};
-static const char *input_function[] = {"ADC", "Digital Mic"};
-static const char *jack_function[] = {"Off", "TV-OUT", "Headphone", "Headset"};
+static const char * const spk_function[] = {"Off", "On"};
+static const char * const input_function[] = {"ADC", "Digital Mic"};
+static const char * const jack_function[] = {
+	"Off", "TV-OUT", "Headphone", "Headset"
+};
 
 static const struct soc_enum rx51_enum[] = {
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),

From beab3da1558a0b091fa9a6fd52755503f9c03eaf Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:20 +0200
Subject: [PATCH 58/86] ASoC: omap: rx51: Add module alias
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add module alias to support driver autoloading.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/rx51.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 1a3f05ce39a51..55713d08348d3 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -421,3 +421,4 @@ module_exit(rx51_soc_exit);
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_DESCRIPTION("ALSA SoC Nokia RX-51");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rx51-audio");

From a7d52028551b8be6eaeac93ade8fccba9783c682 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:21 +0200
Subject: [PATCH 59/86] ASoC: omap: rx51: Use devm_snd_soc_register_card
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch converts the rx51 ASoC module to use
devm_snd_soc_register_card.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/rx51.c | 42 ++++++++++++++++++++++--------------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 55713d08348d3..bbe3a66e91024 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -363,10 +363,9 @@ static struct snd_soc_card rx51_sound_card = {
 	.num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
-static struct platform_device *rx51_snd_device;
-
-static int __init rx51_soc_init(void)
+static int rx51_soc_probe(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = &rx51_sound_card;
 	int err;
 
 	if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900"))
@@ -381,22 +380,16 @@ static int __init rx51_soc_init(void)
 	if (err)
 		goto err_gpio_eci_sw;
 
-	rx51_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!rx51_snd_device) {
-		err = -ENOMEM;
-		goto err1;
-	}
-
-	platform_set_drvdata(rx51_snd_device, &rx51_sound_card);
+	card->dev = &pdev->dev;
 
-	err = platform_device_add(rx51_snd_device);
-	if (err)
-		goto err2;
+	err = devm_snd_soc_register_card(card->dev, card);
+	if (err) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err);
+		goto err_snd;
+	}
 
 	return 0;
-err2:
-	platform_device_put(rx51_snd_device);
-err1:
+err_snd:
 	gpio_free(RX51_ECI_SW_GPIO);
 err_gpio_eci_sw:
 	gpio_free(RX51_TVOUT_SEL_GPIO);
@@ -405,18 +398,27 @@ static int __init rx51_soc_init(void)
 	return err;
 }
 
-static void __exit rx51_soc_exit(void)
+static int rx51_soc_remove(struct platform_device *pdev)
 {
 	snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios),
 				rx51_av_jack_gpios);
 
-	platform_device_unregister(rx51_snd_device);
 	gpio_free(RX51_ECI_SW_GPIO);
 	gpio_free(RX51_TVOUT_SEL_GPIO);
+
+	return 0;
 }
 
-module_init(rx51_soc_init);
-module_exit(rx51_soc_exit);
+static struct platform_driver rx51_soc_driver = {
+	.driver = {
+		.name = "rx51-audio",
+		.owner = THIS_MODULE,
+	},
+	.probe = rx51_soc_probe,
+	.remove = rx51_soc_remove,
+};
+
+module_platform_driver(rx51_soc_driver);
 
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_DESCRIPTION("ALSA SoC Nokia RX-51");

From 4eefa0d850a834cf641892e10583f8081d3f8c60 Mon Sep 17 00:00:00 2001
From: Bard Liao <bardliao@realtek.com>
Date: Wed, 30 Apr 2014 14:08:45 +0800
Subject: [PATCH 60/86] ASoC: rt5640: correct 5640's device ID

This patch correct rt5640's device ID

Signed-off-by: Bard Liao <bardliao@realtek.com>
Tested-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index ded20595e9ae9..895ca149db2ec 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -195,7 +195,7 @@
 /* SW Reset & Device ID (0x00) */
 #define RT5640_ID_MASK				(0x3 << 1)
 #define RT5640_ID_5639				(0x0 << 1)
-#define RT5640_ID_5640				(0x1 << 1)
+#define RT5640_ID_5640				(0x2 << 1)
 #define RT5640_ID_5642				(0x3 << 1)
 
 

From 49e3c6418ba480d95a05814cceecc0eda8545179 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 29 Apr 2014 19:18:26 +0800
Subject: [PATCH 61/86] ASoC: nuc900: export nuc900_ac97_data

The symbol "nuc900_ac97_data" is used by the nuc900_pcm driver,
which may be a loadable module, so we should export it.

If one tries to build SND_SOC_NUC900 without SND_SOC_NUC900_AC97,
the kernel fails to link because of the reference to nuc900_ac97_data.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Xia Kaixu <kaixu.xia@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/nuc900/Kconfig       | 1 +
 sound/soc/nuc900/nuc900-ac97.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/sound/soc/nuc900/Kconfig b/sound/soc/nuc900/Kconfig
index a0ed1c618f608..7f0c954dff6f1 100644
--- a/sound/soc/nuc900/Kconfig
+++ b/sound/soc/nuc900/Kconfig
@@ -4,6 +4,7 @@
 config SND_SOC_NUC900
 	tristate "SoC Audio for NUC900 series"
 	depends on ARCH_W90X900
+	select SND_SOC_NUC900_AC97
 	help
 	  This option enables support for AC97 mode on the NUC900 SoC.
 
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index 8987bf987e584..f2f67942b2294 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -28,6 +28,7 @@
 
 static DEFINE_MUTEX(ac97_mutex);
 struct nuc900_audio *nuc900_ac97_data;
+EXPORT_SYMBOL_GPL(nuc900_ac97_data);
 
 static int nuc900_checkready(void)
 {

From 0a17a37046dbd55204b00fee6e270c8008ace56b Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:23 +0200
Subject: [PATCH 62/86] ASoC: omap: rx51: omap_mcbsp_st_add_controls: add id
 parameter

This is a preparation for DT based booting where the McBSP id
is set to -1 for all McBSP instances.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-mcbsp.c | 5 +++--
 sound/soc/omap/omap-mcbsp.h | 2 +-
 sound/soc/omap/rx51.c       | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index af2764adf2523..71d226626f7cb 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -693,7 +693,7 @@ OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \
 OMAP_MCBSP_ST_CONTROLS(2);
 OMAP_MCBSP_ST_CONTROLS(3);
 
-int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd, int port_id)
 {
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
@@ -703,7 +703,7 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
 		return 0;
 	}
 
-	switch (mcbsp->id) {
+	switch (port_id) {
 	case 2: /* McBSP 2 */
 		return snd_soc_add_dai_controls(cpu_dai,
 					omap_mcbsp2_st_controls,
@@ -713,6 +713,7 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
 					omap_mcbsp3_st_controls,
 					ARRAY_SIZE(omap_mcbsp3_st_controls));
 	default:
+		dev_err(mcbsp->dev, "Port %d not supported\n", port_id);
 		break;
 	}
 
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index ba8386a0d8dc5..2e3369c27be37 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -39,6 +39,6 @@ enum omap_mcbsp_div {
 	OMAP_MCBSP_CLKGDV,		/* Sample rate generator divider */
 };
 
-int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd, int port_id);
 
 #endif
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index bbe3a66e91024..e140b1b2bdf11 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -297,7 +297,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 		return err;
 	snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
 
-	err = omap_mcbsp_st_add_controls(rtd);
+	err = omap_mcbsp_st_add_controls(rtd, 2);
 	if (err < 0)
 		return err;
 

From 386e81ab3b4d6f50064d0ce0b3d82a4ea9a26296 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:24 +0200
Subject: [PATCH 63/86] ASoC: omap: rx51: get GPIO numbers via gpiod API

Update the driver to get GPIO numbers from the
devm gpiod API instead of requesting hardcoded
GPIO numbers.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/rx51.c | 114 +++++++++++++++++++++++++++++-------------
 1 file changed, 79 insertions(+), 35 deletions(-)

diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index e140b1b2bdf11..30cfac0231385 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <sound/core.h>
 #include <sound/jack.h>
@@ -38,15 +39,6 @@
 
 #include "omap-mcbsp.h"
 
-#define RX51_TVOUT_SEL_GPIO		40
-#define RX51_JACK_DETECT_GPIO		177
-#define RX51_ECI_SW_GPIO		182
-/*
- * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This
- * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c
- */
-#define RX51_SPEAKER_AMP_TWL_GPIO	(192 + 7)
-
 enum {
 	RX51_JACK_DISABLED,
 	RX51_JACK_TVOUT,		/* tv-out with stereo output */
@@ -54,12 +46,21 @@ enum {
 	RX51_JACK_HS,			/* headset: stereo output with mic */
 };
 
+struct rx51_audio_pdata {
+	struct gpio_desc *tvout_selection_gpio;
+	struct gpio_desc *jack_detection_gpio;
+	struct gpio_desc *eci_sw_gpio;
+	struct gpio_desc *speaker_amp_gpio;
+};
+
 static int rx51_spk_func;
 static int rx51_dmic_func;
 static int rx51_jack_func;
 
 static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
 {
+	struct snd_soc_card *card = dapm->card;
+	struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
 	int hp = 0, hs = 0, tvout = 0;
 
 	switch (rx51_jack_func) {
@@ -93,7 +94,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
 	else
 		snd_soc_dapm_disable_pin_unlocked(dapm, "HS Mic");
 
-	gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
+	gpiod_set_value(pdata->tvout_selection_gpio, tvout);
 
 	snd_soc_dapm_sync_unlocked(dapm);
 
@@ -154,10 +155,12 @@ static int rx51_set_spk(struct snd_kcontrol *kcontrol,
 static int rx51_spk_event(struct snd_soc_dapm_widget *w,
 			  struct snd_kcontrol *k, int event)
 {
-	if (SND_SOC_DAPM_EVENT_ON(event))
-		gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1);
-	else
-		gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0);
+	struct snd_soc_dapm_context *dapm = w->dapm;
+	struct snd_soc_card *card = dapm->card;
+	struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
+
+	gpiod_set_raw_value_cansleep(pdata->speaker_amp_gpio,
+				     !!SND_SOC_DAPM_EVENT_ON(event));
 
 	return 0;
 }
@@ -223,7 +226,6 @@ static struct snd_soc_jack rx51_av_jack;
 
 static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
 	{
-		.gpio = RX51_JACK_DETECT_GPIO,
 		.name = "avdet-gpio",
 		.report = SND_JACK_HEADSET,
 		.invert = 1,
@@ -284,6 +286,9 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
 static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = codec->card;
+	struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
+
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int err;
 
@@ -307,6 +312,11 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 			       &rx51_av_jack);
 	if (err)
 		return err;
+
+	/* prepare gpio for snd_soc_jack_add_gpios */
+	rx51_av_jack_gpios[0].gpio = desc_to_gpio(pdata->jack_detection_gpio);
+	devm_gpiod_put(card->dev, pdata->jack_detection_gpio);
+
 	err = snd_soc_jack_add_gpios(&rx51_av_jack,
 				     ARRAY_SIZE(rx51_av_jack_gpios),
 				     rx51_av_jack_gpios);
@@ -365,37 +375,74 @@ static struct snd_soc_card rx51_sound_card = {
 
 static int rx51_soc_probe(struct platform_device *pdev)
 {
+	struct rx51_audio_pdata *pdata;
 	struct snd_soc_card *card = &rx51_sound_card;
 	int err;
 
 	if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900"))
 		return -ENODEV;
 
-	err = gpio_request_one(RX51_TVOUT_SEL_GPIO,
-			       GPIOF_DIR_OUT | GPIOF_INIT_LOW, "tvout_sel");
-	if (err)
-		goto err_gpio_tvout_sel;
-	err = gpio_request_one(RX51_ECI_SW_GPIO,
-			       GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "eci_sw");
-	if (err)
-		goto err_gpio_eci_sw;
-
 	card->dev = &pdev->dev;
 
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (pdata == NULL) {
+		dev_err(card->dev, "failed to create private data\n");
+		return -ENOMEM;
+	}
+	snd_soc_card_set_drvdata(card, pdata);
+
+	pdata->tvout_selection_gpio = devm_gpiod_get(card->dev,
+						     "tvout-selection");
+	if (IS_ERR(pdata->tvout_selection_gpio)) {
+		dev_err(card->dev, "could not get tvout selection gpio\n");
+		return PTR_ERR(pdata->tvout_selection_gpio);
+	}
+
+	err = gpiod_direction_output(pdata->tvout_selection_gpio, 0);
+	if (err) {
+		dev_err(card->dev, "could not setup tvout selection gpio\n");
+		return err;
+	}
+
+	pdata->jack_detection_gpio = devm_gpiod_get(card->dev,
+						    "jack-detection");
+	if (IS_ERR(pdata->jack_detection_gpio)) {
+		dev_err(card->dev, "could not get jack detection gpio\n");
+		return PTR_ERR(pdata->jack_detection_gpio);
+	}
+
+	pdata->eci_sw_gpio = devm_gpiod_get(card->dev, "eci-switch");
+	if (IS_ERR(pdata->eci_sw_gpio)) {
+		dev_err(card->dev, "could not get eci switch gpio\n");
+		return PTR_ERR(pdata->eci_sw_gpio);
+	}
+
+	err = gpiod_direction_output(pdata->eci_sw_gpio, 1);
+	if (err) {
+		dev_err(card->dev, "could not setup eci switch gpio\n");
+		return err;
+	}
+
+	pdata->speaker_amp_gpio = devm_gpiod_get(card->dev,
+						 "speaker-amplifier");
+	if (IS_ERR(pdata->speaker_amp_gpio)) {
+		dev_err(card->dev, "could not get speaker enable gpio\n");
+		return PTR_ERR(pdata->speaker_amp_gpio);
+	}
+
+	err = gpiod_direction_output(pdata->speaker_amp_gpio, 0);
+	if (err) {
+		dev_err(card->dev, "could not setup speaker enable gpio\n");
+		return err;
+	}
+
 	err = devm_snd_soc_register_card(card->dev, card);
 	if (err) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", err);
-		goto err_snd;
+		return err;
 	}
 
 	return 0;
-err_snd:
-	gpio_free(RX51_ECI_SW_GPIO);
-err_gpio_eci_sw:
-	gpio_free(RX51_TVOUT_SEL_GPIO);
-err_gpio_tvout_sel:
-
-	return err;
 }
 
 static int rx51_soc_remove(struct platform_device *pdev)
@@ -403,9 +450,6 @@ static int rx51_soc_remove(struct platform_device *pdev)
 	snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios),
 				rx51_av_jack_gpios);
 
-	gpio_free(RX51_ECI_SW_GPIO);
-	gpio_free(RX51_TVOUT_SEL_GPIO);
-
 	return 0;
 }
 

From 0265e1ae64ebf1bb55a563599d11fb7376478ae1 Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:25 +0200
Subject: [PATCH 64/86] ASoC: omap: rx51: Add some error messages

Add more error messages making it easier to identify problems.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/rx51.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 30cfac0231385..110deca7fcbb7 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -298,20 +298,26 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_nc_pin(dapm, "LINE1R");
 
 	err = tpa6130a2_add_controls(codec);
-	if (err < 0)
+	if (err < 0) {
+		dev_err(card->dev, "Failed to add TPA6130A2 controls\n");
 		return err;
+	}
 	snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
 
 	err = omap_mcbsp_st_add_controls(rtd, 2);
-	if (err < 0)
+	if (err < 0) {
+		dev_err(card->dev, "Failed to add MCBSP controls\n");
 		return err;
+	}
 
 	/* AV jack detection */
 	err = snd_soc_jack_new(codec, "AV Jack",
 			       SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
 			       &rx51_av_jack);
-	if (err)
+	if (err) {
+		dev_err(card->dev, "Failed to add AV Jack\n");
 		return err;
+	}
 
 	/* prepare gpio for snd_soc_jack_add_gpios */
 	rx51_av_jack_gpios[0].gpio = desc_to_gpio(pdata->jack_detection_gpio);
@@ -320,6 +326,10 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	err = snd_soc_jack_add_gpios(&rx51_av_jack,
 				     ARRAY_SIZE(rx51_av_jack_gpios),
 				     rx51_av_jack_gpios);
+	if (err) {
+		dev_err(card->dev, "Failed to add GPIOs\n");
+		return err;
+	}
 
 	return err;
 }

From d052a3d6a7955f917fe940b1fecdaf20fa61efae Mon Sep 17 00:00:00 2001
From: Sebastian Reichel <sre@kernel.org>
Date: Mon, 28 Apr 2014 16:07:26 +0200
Subject: [PATCH 65/86] ASoC: omap: rx51: Add DT support

This patch adds device tree support to the Nokia N900 audio driver and
adds documentation for the DT binding.

Signed-off-by: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 .../devicetree/bindings/sound/nokia,rx51.txt  | 27 ++++++++++
 sound/soc/omap/rx51.c                         | 53 +++++++++++++++++++
 2 files changed, 80 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/nokia,rx51.txt

diff --git a/Documentation/devicetree/bindings/sound/nokia,rx51.txt b/Documentation/devicetree/bindings/sound/nokia,rx51.txt
new file mode 100644
index 0000000000000..72f93d9962736
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/nokia,rx51.txt
@@ -0,0 +1,27 @@
+* Nokia N900 audio setup
+
+Required properties:
+- compatible: Should contain "nokia,n900-audio"
+- nokia,cpu-dai: phandle for the McBSP node
+- nokia,audio-codec: phandles for the main TLV320AIC3X node and the
+                     auxiliary TLV320AIC3X node (in this order)
+- nokia,headphone-amplifier: phandle for the TPA6130A2 node
+- tvout-selection-gpios: GPIO for tvout selection
+- jack-detection-gpios: GPIO for jack detection
+- eci-switch-gpios: GPIO for ECI (Enhancement Control Interface) switch
+- speaker-amplifier-gpios: GPIO for speaker amplifier
+
+Example:
+
+sound {
+	compatible = "nokia,n900-audio";
+
+	nokia,cpu-dai = <&mcbsp2>;
+	nokia,audio-codec = <&tlv320aic3x>, <&tlv320aic3x_aux>;
+	nokia,headphone-amplifier = <&tpa6130a2>;
+
+	tvout-selection-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>; /* 40 */
+	jack-detection-gpios = <&gpio6 17 GPIO_ACTIVE_HIGH>; /* 177 */
+	eci-switch-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* 182 */
+	speaker-amplifier-gpios = <&twl_gpio 7 GPIO_ACTIVE_HIGH>;
+};
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 110deca7fcbb7..866578bcda558 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -386,6 +386,7 @@ static struct snd_soc_card rx51_sound_card = {
 static int rx51_soc_probe(struct platform_device *pdev)
 {
 	struct rx51_audio_pdata *pdata;
+	struct device_node *np = pdev->dev.of_node;
 	struct snd_soc_card *card = &rx51_sound_card;
 	int err;
 
@@ -394,6 +395,49 @@ static int rx51_soc_probe(struct platform_device *pdev)
 
 	card->dev = &pdev->dev;
 
+	if (np) {
+		struct device_node *dai_node;
+
+		dai_node = of_parse_phandle(np, "nokia,cpu-dai", 0);
+		if (!dai_node) {
+			dev_err(&pdev->dev, "McBSP node is not provided\n");
+			return -EINVAL;
+		}
+		rx51_dai[0].cpu_dai_name = NULL;
+		rx51_dai[0].platform_name = NULL;
+		rx51_dai[0].cpu_of_node = dai_node;
+		rx51_dai[0].platform_of_node = dai_node;
+
+		dai_node = of_parse_phandle(np, "nokia,audio-codec", 0);
+		if (!dai_node) {
+			dev_err(&pdev->dev, "Codec node is not provided\n");
+			return -EINVAL;
+		}
+		rx51_dai[0].codec_name = NULL;
+		rx51_dai[0].codec_of_node = dai_node;
+
+		dai_node = of_parse_phandle(np, "nokia,audio-codec", 1);
+		if (!dai_node) {
+			dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n");
+			return -EINVAL;
+		}
+		rx51_aux_dev[0].codec_name = NULL;
+		rx51_aux_dev[0].codec_of_node = dai_node;
+		rx51_codec_conf[0].dev_name = NULL;
+		rx51_codec_conf[0].of_node = dai_node;
+
+		dai_node = of_parse_phandle(np, "nokia,headphone-amplifier", 0);
+		if (!dai_node) {
+			dev_err(&pdev->dev, "Headphone amplifier node is not provided\n");
+			return -EINVAL;
+		}
+
+		/* TODO: tpa6130a2a driver supports only a single instance, so
+		 * this driver ignores the headphone-amplifier node for now.
+		 * It's already mandatory in the DT binding to be future proof.
+		 */
+	}
+
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (pdata == NULL) {
 		dev_err(card->dev, "failed to create private data\n");
@@ -463,10 +507,19 @@ static int rx51_soc_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id rx51_audio_of_match[] = {
+	{ .compatible = "nokia,n900-audio", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, rx51_audio_of_match);
+#endif
+
 static struct platform_driver rx51_soc_driver = {
 	.driver = {
 		.name = "rx51-audio",
 		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(rx51_audio_of_match),
 	},
 	.probe = rx51_soc_probe,
 	.remove = rx51_soc_remove,

From 36a26e1a9a2b7e966ea132bfcf778d84af288e51 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 29 Apr 2014 19:18:27 +0800
Subject: [PATCH 66/86] ASoC: omap: RX-51 audio needs I2C

The codec requires I2C to be enabled, so any other option
that selects it should also depend on I2C.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Xia Kaixu <kaixu.xia@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index e00659351a4e2..2796af9fa5e8b 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -26,7 +26,7 @@ config SND_OMAP_SOC_N810
 
 config SND_OMAP_SOC_RX51
 	tristate "SoC Audio support for Nokia RX-51"
-	depends on SND_OMAP_SOC && ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
+	depends on SND_OMAP_SOC && ARM && (MACH_NOKIA_RX51 || COMPILE_TEST) && I2C
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_TLV320AIC3X
 	select SND_SOC_TPA6130A2

From 482b91c7f1ca3442f5cd57525e82d8e7b2dff8c8 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 29 Apr 2014 19:18:29 +0800
Subject: [PATCH 67/86] ASoC: pxa: TTC DKB audio needs I2C

The missing dependency can lead to build errors, so
make it explicit in Kconfig.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Xia Kaixu <kaixu.xia@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/pxa/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 6473052b68996..6acb225ec6fdf 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -140,7 +140,7 @@ config SND_PXA910_SOC
 
 config SND_SOC_TTC_DKB
 	bool "SoC Audio support for TTC DKB"
-	depends on SND_PXA910_SOC && MACH_TTC_DKB
+	depends on SND_PXA910_SOC && MACH_TTC_DKB && I2C=y
 	select PXA_SSP
 	select SND_PXA_SOC_SSP
 	select SND_MMP_SOC

From b7a80379aa52d033d2a7c2390c8e80bd027758bf Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 29 Apr 2014 19:18:35 +0800
Subject: [PATCH 68/86] ASoC: omap: Amstrad E3 needs TTY support for codec

The cx20442 codec driver used here requires the TTY layer to
be enabled, or we get a link error:

sound/built-in.o: In function `cx20442_codec_remove':
cx20442.c:398: undefined reference to `tty_hangup'
sound/built-in.o: In function `ams_delta_remove':
ams-delta.c:613: undefined reference to `tty_unregister_ldisc'
sound/built-in.o: In function `ams_delta_cx20442_init':
ams-delta.c:559: undefined reference to `tty_register_ldisc'

This adds the missing dependency in the E3 configuration, there
was already one for the codec.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Xia Kaixu <kaixu.xia@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 2796af9fa5e8b..d44463a7b0fae 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -37,7 +37,7 @@ config SND_OMAP_SOC_RX51
 
 config SND_OMAP_SOC_AMS_DELTA
 	tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
-	depends on SND_OMAP_SOC && MACH_AMS_DELTA
+	depends on SND_OMAP_SOC && MACH_AMS_DELTA && TTY
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_CX20442
 	help

From 1319b2f6a565231ca2e3f368ab7f74fc4714c799 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Mon, 28 Apr 2014 19:59:10 +0800
Subject: [PATCH 69/86] ASoC: rt5645: Add codec driver

This patch adds the Realtek ALC5645 codec driver. It is the base
version that because the jack detect function is not implemented to
it, the headphone and AMIC1 are not workable. We will fill up the
further functions later.

Signed-off-by: Bard Liao <bardliao@realtek.com>
Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/rt5645.h    |   25 +
 sound/soc/codecs/Kconfig  |    4 +
 sound/soc/codecs/Makefile |    2 +
 sound/soc/codecs/rt5645.c | 2476 +++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/rt5645.h | 2188 ++++++++++++++++++++++++++++++++
 5 files changed, 4695 insertions(+)
 create mode 100644 include/sound/rt5645.h
 create mode 100644 sound/soc/codecs/rt5645.c
 create mode 100644 sound/soc/codecs/rt5645.h

diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h
new file mode 100644
index 0000000000000..1de744c242f62
--- /dev/null
+++ b/include/sound/rt5645.h
@@ -0,0 +1,25 @@
+/*
+ * linux/sound/rt5645.h -- Platform data for RT5645
+ *
+ * Copyright 2013 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_RT5645_H
+#define __LINUX_SND_RT5645_H
+
+struct rt5645_platform_data {
+	/* IN2 can optionally be differential */
+	bool in2_diff;
+
+	bool dmic_en;
+	unsigned int dmic1_data_pin;
+	/* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */
+	unsigned int dmic2_data_pin;
+	/* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */
+};
+
+#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index deba71bad6e9c..d29f19b446384 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -71,6 +71,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_PCM512x_SPI if SPI_MASTER
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5640 if I2C
+	select SND_SOC_RT5645 if I2C
 	select SND_SOC_RT5651 if I2C
 	select SND_SOC_SGTL5000 if I2C
 	select SND_SOC_SI476X if MFD_SI476X_CORE
@@ -397,6 +398,9 @@ config SND_SOC_RT5631
 config SND_SOC_RT5640
 	tristate
 
+config SND_SOC_RT5645
+        tristate
+
 config SND_SOC_RT5651
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index e76938ee82f4c..a3d12b4af1e7f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -60,6 +60,7 @@ snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
+snd-soc-rt5645-objs := rt5645.o
 snd-soc-rt5651-objs := rt5651.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
@@ -212,6 +213,7 @@ obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
+obj-$(CONFIG_SND_SOC_RT5645)	+= snd-soc-rt5645.o
 obj-$(CONFIG_SND_SOC_RT5651)	+= snd-soc-rt5651.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/rt5645.c b/sound/soc/codecs/rt5645.c
new file mode 100644
index 0000000000000..7d8cc1688fb56
--- /dev/null
+++ b/sound/soc/codecs/rt5645.c
@@ -0,0 +1,2476 @@
+/*
+ * rt5645.c  --  RT5645 ALSA SoC audio codec driver
+ *
+ * Copyright 2013 Realtek Semiconductor Corp.
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * 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/i2c.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/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rt5645.h"
+
+#define RT5645_DEVICE_ID 0x6308
+
+#define RT5645_PR_RANGE_BASE (0xff + 1)
+#define RT5645_PR_SPACING 0x100
+
+#define RT5645_PR_BASE (RT5645_PR_RANGE_BASE + (0 * RT5645_PR_SPACING))
+
+static const struct regmap_range_cfg rt5645_ranges[] = {
+	{
+		.name = "PR",
+		.range_min = RT5645_PR_BASE,
+		.range_max = RT5645_PR_BASE + 0xf8,
+		.selector_reg = RT5645_PRIV_INDEX,
+		.selector_mask = 0xff,
+		.selector_shift = 0x0,
+		.window_start = RT5645_PRIV_DATA,
+		.window_len = 0x1,
+	},
+};
+
+static const struct reg_default init_list[] = {
+	{RT5645_PR_BASE + 0x3d,	0x3600},
+};
+#define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
+
+static const struct reg_default rt5645_reg[] = {
+	{ 0x00, 0x0000 },
+	{ 0x01, 0xc8c8 },
+	{ 0x02, 0xc8c8 },
+	{ 0x03, 0xc8c8 },
+	{ 0x0a, 0x0002 },
+	{ 0x0b, 0x2827 },
+	{ 0x0c, 0xe000 },
+	{ 0x0d, 0x0000 },
+	{ 0x0e, 0x0000 },
+	{ 0x0f, 0x0808 },
+	{ 0x14, 0x3333 },
+	{ 0x16, 0x4b00 },
+	{ 0x18, 0x018b },
+	{ 0x19, 0xafaf },
+	{ 0x1a, 0xafaf },
+	{ 0x1b, 0x0001 },
+	{ 0x1c, 0x2f2f },
+	{ 0x1d, 0x2f2f },
+	{ 0x1e, 0x0000 },
+	{ 0x20, 0x0000 },
+	{ 0x27, 0x7060 },
+	{ 0x28, 0x7070 },
+	{ 0x29, 0x8080 },
+	{ 0x2a, 0x5656 },
+	{ 0x2b, 0x5454 },
+	{ 0x2c, 0xaaa0 },
+	{ 0x2f, 0x1002 },
+	{ 0x31, 0x5000 },
+	{ 0x32, 0x0000 },
+	{ 0x33, 0x0000 },
+	{ 0x34, 0x0000 },
+	{ 0x35, 0x0000 },
+	{ 0x3b, 0x0000 },
+	{ 0x3c, 0x007f },
+	{ 0x3d, 0x0000 },
+	{ 0x3e, 0x007f },
+	{ 0x3f, 0x0000 },
+	{ 0x40, 0x001f },
+	{ 0x41, 0x0000 },
+	{ 0x42, 0x001f },
+	{ 0x45, 0x6000 },
+	{ 0x46, 0x003e },
+	{ 0x47, 0x003e },
+	{ 0x48, 0xf807 },
+	{ 0x4a, 0x0004 },
+	{ 0x4d, 0x0000 },
+	{ 0x4e, 0x0000 },
+	{ 0x4f, 0x01ff },
+	{ 0x50, 0x0000 },
+	{ 0x51, 0x0000 },
+	{ 0x52, 0x01ff },
+	{ 0x53, 0xf000 },
+	{ 0x56, 0x0111 },
+	{ 0x57, 0x0064 },
+	{ 0x58, 0xef0e },
+	{ 0x59, 0xf0f0 },
+	{ 0x5a, 0xef0e },
+	{ 0x5b, 0xf0f0 },
+	{ 0x5c, 0xef0e },
+	{ 0x5d, 0xf0f0 },
+	{ 0x5e, 0xf000 },
+	{ 0x5f, 0x0000 },
+	{ 0x61, 0x0300 },
+	{ 0x62, 0x0000 },
+	{ 0x63, 0x00c2 },
+	{ 0x64, 0x0000 },
+	{ 0x65, 0x0000 },
+	{ 0x66, 0x0000 },
+	{ 0x6a, 0x0000 },
+	{ 0x6c, 0x0aaa },
+	{ 0x70, 0x8000 },
+	{ 0x71, 0x8000 },
+	{ 0x72, 0x8000 },
+	{ 0x73, 0x7770 },
+	{ 0x74, 0x3e00 },
+	{ 0x75, 0x2409 },
+	{ 0x76, 0x000a },
+	{ 0x77, 0x0c00 },
+	{ 0x78, 0x0000 },
+	{ 0x80, 0x0000 },
+	{ 0x81, 0x0000 },
+	{ 0x82, 0x0000 },
+	{ 0x83, 0x0000 },
+	{ 0x84, 0x0000 },
+	{ 0x85, 0x0000 },
+	{ 0x8a, 0x0000 },
+	{ 0x8e, 0x0004 },
+	{ 0x8f, 0x1100 },
+	{ 0x90, 0x0646 },
+	{ 0x91, 0x0c06 },
+	{ 0x93, 0x0000 },
+	{ 0x94, 0x0200 },
+	{ 0x95, 0x0000 },
+	{ 0x9a, 0x2184 },
+	{ 0x9b, 0x010a },
+	{ 0x9c, 0x0aea },
+	{ 0x9d, 0x000c },
+	{ 0x9e, 0x0400 },
+	{ 0xa0, 0xa0a8 },
+	{ 0xa1, 0x0059 },
+	{ 0xa2, 0x0001 },
+	{ 0xae, 0x6000 },
+	{ 0xaf, 0x0000 },
+	{ 0xb0, 0x6000 },
+	{ 0xb1, 0x0000 },
+	{ 0xb2, 0x0000 },
+	{ 0xb3, 0x001f },
+	{ 0xb4, 0x020c },
+	{ 0xb5, 0x1f00 },
+	{ 0xb6, 0x0000 },
+	{ 0xbb, 0x0000 },
+	{ 0xbc, 0x0000 },
+	{ 0xbd, 0x0000 },
+	{ 0xbe, 0x0000 },
+	{ 0xbf, 0x3100 },
+	{ 0xc0, 0x0000 },
+	{ 0xc1, 0x0000 },
+	{ 0xc2, 0x0000 },
+	{ 0xc3, 0x2000 },
+	{ 0xcd, 0x0000 },
+	{ 0xce, 0x0000 },
+	{ 0xcf, 0x1813 },
+	{ 0xd0, 0x0690 },
+	{ 0xd1, 0x1c17 },
+	{ 0xd3, 0xb320 },
+	{ 0xd4, 0x0000 },
+	{ 0xd6, 0x0400 },
+	{ 0xd9, 0x0809 },
+	{ 0xda, 0x0000 },
+	{ 0xdb, 0x0003 },
+	{ 0xdc, 0x0049 },
+	{ 0xdd, 0x001b },
+	{ 0xe6, 0x8000 },
+	{ 0xe7, 0x0200 },
+	{ 0xec, 0xb300 },
+	{ 0xed, 0x0000 },
+	{ 0xf0, 0x001f },
+	{ 0xf1, 0x020c },
+	{ 0xf2, 0x1f00 },
+	{ 0xf3, 0x0000 },
+	{ 0xf4, 0x4000 },
+	{ 0xf8, 0x0000 },
+	{ 0xf9, 0x0000 },
+	{ 0xfa, 0x2060 },
+	{ 0xfb, 0x4040 },
+	{ 0xfc, 0x0000 },
+	{ 0xfd, 0x0002 },
+	{ 0xfe, 0x10ec },
+	{ 0xff, 0x6308 },
+};
+
+static int rt5645_reset(struct snd_soc_codec *codec)
+{
+	return snd_soc_write(codec, RT5645_RESET, 0);
+}
+
+static bool rt5645_volatile_register(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rt5645_ranges); i++) {
+		if (reg >= rt5645_ranges[i].range_min &&
+			reg <= rt5645_ranges[i].range_max) {
+			return true;
+		}
+	}
+
+	switch (reg) {
+	case RT5645_RESET:
+	case RT5645_PRIV_DATA:
+	case RT5645_IN1_CTRL1:
+	case RT5645_IN1_CTRL2:
+	case RT5645_IN1_CTRL3:
+	case RT5645_A_JD_CTRL1:
+	case RT5645_ADC_EQ_CTRL1:
+	case RT5645_EQ_CTRL1:
+	case RT5645_ALC_CTRL_1:
+	case RT5645_IRQ_CTRL2:
+	case RT5645_IRQ_CTRL3:
+	case RT5645_INT_IRQ_ST:
+	case RT5645_IL_CMD:
+	case RT5645_VENDOR_ID:
+	case RT5645_VENDOR_ID1:
+	case RT5645_VENDOR_ID2:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static bool rt5645_readable_register(struct device *dev, unsigned int reg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rt5645_ranges); i++) {
+		if (reg >= rt5645_ranges[i].range_min &&
+			reg <= rt5645_ranges[i].range_max) {
+			return true;
+		}
+	}
+
+	switch (reg) {
+	case RT5645_RESET:
+	case RT5645_SPK_VOL:
+	case RT5645_HP_VOL:
+	case RT5645_LOUT1:
+	case RT5645_IN1_CTRL1:
+	case RT5645_IN1_CTRL2:
+	case RT5645_IN1_CTRL3:
+	case RT5645_IN2_CTRL:
+	case RT5645_INL1_INR1_VOL:
+	case RT5645_SPK_FUNC_LIM:
+	case RT5645_ADJ_HPF_CTRL:
+	case RT5645_DAC1_DIG_VOL:
+	case RT5645_DAC2_DIG_VOL:
+	case RT5645_DAC_CTRL:
+	case RT5645_STO1_ADC_DIG_VOL:
+	case RT5645_MONO_ADC_DIG_VOL:
+	case RT5645_ADC_BST_VOL1:
+	case RT5645_ADC_BST_VOL2:
+	case RT5645_STO1_ADC_MIXER:
+	case RT5645_MONO_ADC_MIXER:
+	case RT5645_AD_DA_MIXER:
+	case RT5645_STO_DAC_MIXER:
+	case RT5645_MONO_DAC_MIXER:
+	case RT5645_DIG_MIXER:
+	case RT5645_DIG_INF1_DATA:
+	case RT5645_PDM_OUT_CTRL:
+	case RT5645_REC_L1_MIXER:
+	case RT5645_REC_L2_MIXER:
+	case RT5645_REC_R1_MIXER:
+	case RT5645_REC_R2_MIXER:
+	case RT5645_HPMIXL_CTRL:
+	case RT5645_HPOMIXL_CTRL:
+	case RT5645_HPMIXR_CTRL:
+	case RT5645_HPOMIXR_CTRL:
+	case RT5645_HPO_MIXER:
+	case RT5645_SPK_L_MIXER:
+	case RT5645_SPK_R_MIXER:
+	case RT5645_SPO_MIXER:
+	case RT5645_SPO_CLSD_RATIO:
+	case RT5645_OUT_L1_MIXER:
+	case RT5645_OUT_R1_MIXER:
+	case RT5645_OUT_L_GAIN1:
+	case RT5645_OUT_L_GAIN2:
+	case RT5645_OUT_R_GAIN1:
+	case RT5645_OUT_R_GAIN2:
+	case RT5645_LOUT_MIXER:
+	case RT5645_HAPTIC_CTRL1:
+	case RT5645_HAPTIC_CTRL2:
+	case RT5645_HAPTIC_CTRL3:
+	case RT5645_HAPTIC_CTRL4:
+	case RT5645_HAPTIC_CTRL5:
+	case RT5645_HAPTIC_CTRL6:
+	case RT5645_HAPTIC_CTRL7:
+	case RT5645_HAPTIC_CTRL8:
+	case RT5645_HAPTIC_CTRL9:
+	case RT5645_HAPTIC_CTRL10:
+	case RT5645_PWR_DIG1:
+	case RT5645_PWR_DIG2:
+	case RT5645_PWR_ANLG1:
+	case RT5645_PWR_ANLG2:
+	case RT5645_PWR_MIXER:
+	case RT5645_PWR_VOL:
+	case RT5645_PRIV_INDEX:
+	case RT5645_PRIV_DATA:
+	case RT5645_I2S1_SDP:
+	case RT5645_I2S2_SDP:
+	case RT5645_ADDA_CLK1:
+	case RT5645_ADDA_CLK2:
+	case RT5645_DMIC_CTRL1:
+	case RT5645_DMIC_CTRL2:
+	case RT5645_TDM_CTRL_1:
+	case RT5645_TDM_CTRL_2:
+	case RT5645_GLB_CLK:
+	case RT5645_PLL_CTRL1:
+	case RT5645_PLL_CTRL2:
+	case RT5645_ASRC_1:
+	case RT5645_ASRC_2:
+	case RT5645_ASRC_3:
+	case RT5645_ASRC_4:
+	case RT5645_DEPOP_M1:
+	case RT5645_DEPOP_M2:
+	case RT5645_DEPOP_M3:
+	case RT5645_MICBIAS:
+	case RT5645_A_JD_CTRL1:
+	case RT5645_VAD_CTRL4:
+	case RT5645_CLSD_OUT_CTRL:
+	case RT5645_ADC_EQ_CTRL1:
+	case RT5645_ADC_EQ_CTRL2:
+	case RT5645_EQ_CTRL1:
+	case RT5645_EQ_CTRL2:
+	case RT5645_ALC_CTRL_1:
+	case RT5645_ALC_CTRL_2:
+	case RT5645_ALC_CTRL_3:
+	case RT5645_ALC_CTRL_4:
+	case RT5645_ALC_CTRL_5:
+	case RT5645_JD_CTRL:
+	case RT5645_IRQ_CTRL1:
+	case RT5645_IRQ_CTRL2:
+	case RT5645_IRQ_CTRL3:
+	case RT5645_INT_IRQ_ST:
+	case RT5645_GPIO_CTRL1:
+	case RT5645_GPIO_CTRL2:
+	case RT5645_GPIO_CTRL3:
+	case RT5645_BASS_BACK:
+	case RT5645_MP3_PLUS1:
+	case RT5645_MP3_PLUS2:
+	case RT5645_ADJ_HPF1:
+	case RT5645_ADJ_HPF2:
+	case RT5645_HP_CALIB_AMP_DET:
+	case RT5645_SV_ZCD1:
+	case RT5645_SV_ZCD2:
+	case RT5645_IL_CMD:
+	case RT5645_IL_CMD2:
+	case RT5645_IL_CMD3:
+	case RT5645_DRC1_HL_CTRL1:
+	case RT5645_DRC2_HL_CTRL1:
+	case RT5645_ADC_MONO_HP_CTRL1:
+	case RT5645_ADC_MONO_HP_CTRL2:
+	case RT5645_DRC2_CTRL1:
+	case RT5645_DRC2_CTRL2:
+	case RT5645_DRC2_CTRL3:
+	case RT5645_DRC2_CTRL4:
+	case RT5645_DRC2_CTRL5:
+	case RT5645_JD_CTRL3:
+	case RT5645_JD_CTRL4:
+	case RT5645_GEN_CTRL1:
+	case RT5645_GEN_CTRL2:
+	case RT5645_GEN_CTRL3:
+	case RT5645_VENDOR_ID:
+	case RT5645_VENDOR_ID1:
+	case RT5645_VENDOR_ID2:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+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),
+};
+
+static const char * const rt5645_tdm_data_swap_select[] = {
+	"L/R", "R/L", "L/L", "R/R"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot0_1_enum,
+	RT5645_TDM_CTRL_1, 6, rt5645_tdm_data_swap_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot2_3_enum,
+	RT5645_TDM_CTRL_1, 4, rt5645_tdm_data_swap_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot4_5_enum,
+	RT5645_TDM_CTRL_1, 2, rt5645_tdm_data_swap_select);
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot6_7_enum,
+	RT5645_TDM_CTRL_1, 0, rt5645_tdm_data_swap_select);
+
+static const char * const rt5645_tdm_adc_data_select[] = {
+	"1/2/R", "2/1/R", "R/1/2", "R/2/1"
+};
+
+static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_sel_enum,
+				RT5645_TDM_CTRL_1, 8,
+				rt5645_tdm_adc_data_select);
+
+static const struct snd_kcontrol_new rt5645_snd_controls[] = {
+	/* Speaker Output Volume */
+	SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL,
+		RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
+	SOC_DOUBLE_TLV("Speaker Playback Volume", RT5645_SPK_VOL,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+	/* Headphone Output Volume */
+	SOC_DOUBLE("HP Channel Switch", RT5645_HP_VOL,
+		RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
+	SOC_DOUBLE_TLV("HP Playback Volume", RT5645_HP_VOL,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+	/* OUTPUT Control */
+	SOC_DOUBLE("OUT Playback Switch", RT5645_LOUT1,
+		RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE("OUT Channel Switch", RT5645_LOUT1,
+		RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1),
+	SOC_DOUBLE_TLV("OUT Playback Volume", RT5645_LOUT1,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv),
+
+	/* DAC Digital Volume */
+	SOC_DOUBLE("DAC2 Playback Switch", RT5645_DAC_CTRL,
+		RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1),
+	SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5645_DAC1_DIG_VOL,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv),
+	SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5645_DAC2_DIG_VOL,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv),
+
+	/* IN1/IN2 Control */
+	SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
+		RT5645_BST_SFT1, 8, 0, bst_tlv),
+	SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
+		RT5645_BST_SFT2, 8, 0, bst_tlv),
+
+	/* INL/INR Volume Control */
+	SOC_DOUBLE_TLV("IN Capture Volume", RT5645_INL1_INR1_VOL,
+		RT5645_INL_VOL_SFT, RT5645_INR_VOL_SFT, 31, 1, in_vol_tlv),
+
+	/* ADC Digital Volume Control */
+	SOC_DOUBLE("ADC Capture Switch", RT5645_STO1_ADC_DIG_VOL,
+		RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_TLV("ADC Capture Volume", RT5645_STO1_ADC_DIG_VOL,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv),
+	SOC_DOUBLE("Mono ADC Capture Switch", RT5645_MONO_ADC_DIG_VOL,
+		RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
+	SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5645_MONO_ADC_DIG_VOL,
+		RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv),
+
+	/* ADC Boost Volume Control */
+	SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1,
+		RT5645_STO1_ADC_L_BST_SFT, RT5645_STO1_ADC_R_BST_SFT, 3, 0,
+		adc_bst_tlv),
+	SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5645_ADC_BST_VOL1,
+		RT5645_STO2_ADC_L_BST_SFT, RT5645_STO2_ADC_R_BST_SFT, 3, 0,
+		adc_bst_tlv),
+
+	/* I2S2 function select */
+	SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT,
+		1, 1),
+
+	/* TDM */
+	SOC_ENUM("TDM Adc Slot0 1 Data", rt5645_tdm_adc_slot0_1_enum),
+	SOC_ENUM("TDM Adc Slot2 3 Data", rt5645_tdm_adc_slot2_3_enum),
+	SOC_ENUM("TDM Adc Slot4 5 Data", rt5645_tdm_adc_slot4_5_enum),
+	SOC_ENUM("TDM Adc Slot6 7 Data", rt5645_tdm_adc_slot6_7_enum),
+	SOC_ENUM("TDM IF1 ADC DATA Sel", rt5645_tdm_adc_sel_enum),
+	SOC_SINGLE("TDM IF1_DAC1_L Sel", RT5645_TDM_CTRL_3, 12, 7, 0),
+	SOC_SINGLE("TDM IF1_DAC1_R Sel", RT5645_TDM_CTRL_3, 8, 7, 0),
+	SOC_SINGLE("TDM IF1_DAC2_L Sel", RT5645_TDM_CTRL_3, 4, 7, 0),
+	SOC_SINGLE("TDM IF1_DAC2_R Sel", RT5645_TDM_CTRL_3, 0, 7, 0),
+};
+
+/**
+ * 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 rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+	int div[] = {2, 3, 4, 6, 8, 12};
+	int idx = -EINVAL, i;
+	int rate, red, bound, temp;
+
+	rate = rt5645->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, RT5645_DMIC_CTRL1,
+			RT5645_DMIC_CLK_MASK, idx << RT5645_DMIC_CLK_SFT);
+	return idx;
+}
+
+static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int val;
+
+	val = snd_soc_read(source->codec, RT5645_GLB_CLK);
+	val &= RT5645_SCLK_SRC_MASK;
+	if (val == RT5645_SCLK_SRC_PLL1)
+		return 1;
+	else
+		return 0;
+}
+
+/* Digital Mixer */
+static const struct snd_kcontrol_new rt5645_sto1_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER,
+			RT5645_M_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5645_STO1_ADC_MIXER,
+			RT5645_M_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_sto1_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5645_STO1_ADC_MIXER,
+			RT5645_M_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5645_STO1_ADC_MIXER,
+			RT5645_M_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_adc_l_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5645_MONO_ADC_MIXER,
+			RT5645_M_MONO_ADC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5645_MONO_ADC_MIXER,
+			RT5645_M_MONO_ADC_L2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_adc_r_mix[] = {
+	SOC_DAPM_SINGLE("ADC1 Switch", RT5645_MONO_ADC_MIXER,
+			RT5645_M_MONO_ADC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("ADC2 Switch", RT5645_MONO_ADC_MIXER,
+			RT5645_M_MONO_ADC_R2_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
+			RT5645_M_ADCMIX_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+			RT5645_M_DAC1_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
+			RT5645_M_ADCMIX_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+			RT5645_M_DAC1_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_sto_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_STO_DAC_MIXER,
+			RT5645_M_DAC_L1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_STO_DAC_MIXER,
+			RT5645_M_DAC_L2_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_STO_DAC_MIXER,
+			RT5645_M_DAC_R1_STO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_sto_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_STO_DAC_MIXER,
+			RT5645_M_DAC_R1_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_STO_DAC_MIXER,
+			RT5645_M_DAC_R2_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_STO_DAC_MIXER,
+			RT5645_M_DAC_L1_STO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_dac_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_MONO_DAC_MIXER,
+			RT5645_M_DAC_L1_MONO_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_MONO_DAC_MIXER,
+			RT5645_M_DAC_L2_MONO_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_MONO_DAC_MIXER,
+			RT5645_M_DAC_R2_MONO_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_mono_dac_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_MONO_DAC_MIXER,
+			RT5645_M_DAC_R1_MONO_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_MONO_DAC_MIXER,
+			RT5645_M_DAC_R2_MONO_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_MONO_DAC_MIXER,
+			RT5645_M_DAC_L2_MONO_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dig_l_mix[] = {
+	SOC_DAPM_SINGLE("Sto DAC Mix L Switch", RT5645_DIG_MIXER,
+			RT5645_M_STO_L_DAC_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_DIG_MIXER,
+			RT5645_M_DAC_L2_DAC_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_DIG_MIXER,
+			RT5645_M_DAC_R2_DAC_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_dig_r_mix[] = {
+	SOC_DAPM_SINGLE("Sto DAC Mix R Switch", RT5645_DIG_MIXER,
+			RT5645_M_STO_R_DAC_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_DIG_MIXER,
+			RT5645_M_DAC_R2_DAC_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_DIG_MIXER,
+			RT5645_M_DAC_L2_DAC_R_SFT, 1, 1),
+};
+
+/* Analog Input Mixer */
+static const struct snd_kcontrol_new rt5645_rec_l_mix[] = {
+	SOC_DAPM_SINGLE("HPOL Switch", RT5645_REC_L2_MIXER,
+			RT5645_M_HP_L_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5645_REC_L2_MIXER,
+			RT5645_M_IN_L_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5645_REC_L2_MIXER,
+			RT5645_M_BST2_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5645_REC_L2_MIXER,
+			RT5645_M_BST1_RM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUT MIXL Switch", RT5645_REC_L2_MIXER,
+			RT5645_M_OM_L_RM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_rec_r_mix[] = {
+	SOC_DAPM_SINGLE("HPOR Switch", RT5645_REC_R2_MIXER,
+			RT5645_M_HP_R_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5645_REC_R2_MIXER,
+			RT5645_M_IN_R_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5645_REC_R2_MIXER,
+			RT5645_M_BST2_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5645_REC_R2_MIXER,
+			RT5645_M_BST1_RM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUT MIXR Switch", RT5645_REC_R2_MIXER,
+			RT5645_M_OM_R_RM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spk_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_SPK_L_MIXER,
+			RT5645_M_DAC_L1_SM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_SPK_L_MIXER,
+			RT5645_M_DAC_L2_SM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5645_SPK_L_MIXER,
+			RT5645_M_IN_L_SM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5645_SPK_L_MIXER,
+			RT5645_M_BST1_L_SM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spk_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_SPK_R_MIXER,
+			RT5645_M_DAC_R1_SM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_SPK_R_MIXER,
+			RT5645_M_DAC_R2_SM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5645_SPK_R_MIXER,
+			RT5645_M_IN_R_SM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5645_SPK_R_MIXER,
+			RT5645_M_BST2_R_SM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_out_l_mix[] = {
+	SOC_DAPM_SINGLE("BST1 Switch", RT5645_OUT_L1_MIXER,
+			RT5645_M_BST1_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5645_OUT_L1_MIXER,
+			RT5645_M_IN_L_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L2 Switch", RT5645_OUT_L1_MIXER,
+			RT5645_M_DAC_L2_OM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_OUT_L1_MIXER,
+			RT5645_M_DAC_L1_OM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_out_r_mix[] = {
+	SOC_DAPM_SINGLE("BST2 Switch", RT5645_OUT_R1_MIXER,
+			RT5645_M_BST2_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5645_OUT_R1_MIXER,
+			RT5645_M_IN_R_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R2 Switch", RT5645_OUT_R1_MIXER,
+			RT5645_M_DAC_R2_OM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_OUT_R1_MIXER,
+			RT5645_M_DAC_R1_OM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spo_l_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_SPO_MIXER,
+			RT5645_M_DAC_R1_SPM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_SPO_MIXER,
+			RT5645_M_DAC_L1_SPM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("SPKVOL R Switch", RT5645_SPO_MIXER,
+			RT5645_M_SV_R_SPM_L_SFT, 1, 1),
+	SOC_DAPM_SINGLE("SPKVOL L Switch", RT5645_SPO_MIXER,
+			RT5645_M_SV_L_SPM_L_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_spo_r_mix[] = {
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_SPO_MIXER,
+			RT5645_M_DAC_R1_SPM_R_SFT, 1, 1),
+	SOC_DAPM_SINGLE("SPKVOL R Switch", RT5645_SPO_MIXER,
+			RT5645_M_SV_R_SPM_R_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_hpo_mix[] = {
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5645_HPO_MIXER,
+			RT5645_M_DAC1_HM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("HPVOL Switch", RT5645_HPO_MIXER,
+			RT5645_M_HPVOL_HM_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_hpvoll_mix[] = {
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5645_HPOMIXL_CTRL,
+			RT5645_M_DAC1_HV_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC2 Switch", RT5645_HPOMIXL_CTRL,
+			RT5645_M_DAC2_HV_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INL Switch", RT5645_HPOMIXL_CTRL,
+			RT5645_M_IN_HV_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST1 Switch", RT5645_HPOMIXL_CTRL,
+			RT5645_M_BST1_HV_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_hpvolr_mix[] = {
+	SOC_DAPM_SINGLE("DAC1 Switch", RT5645_HPOMIXR_CTRL,
+			RT5645_M_DAC1_HV_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC2 Switch", RT5645_HPOMIXR_CTRL,
+			RT5645_M_DAC2_HV_SFT, 1, 1),
+	SOC_DAPM_SINGLE("INR Switch", RT5645_HPOMIXR_CTRL,
+			RT5645_M_IN_HV_SFT, 1, 1),
+	SOC_DAPM_SINGLE("BST2 Switch", RT5645_HPOMIXR_CTRL,
+			RT5645_M_BST2_HV_SFT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5645_lout_mix[] = {
+	SOC_DAPM_SINGLE("DAC L1 Switch", RT5645_LOUT_MIXER,
+			RT5645_M_DAC_L1_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("DAC R1 Switch", RT5645_LOUT_MIXER,
+			RT5645_M_DAC_R1_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUTMIX L Switch", RT5645_LOUT_MIXER,
+			RT5645_M_OV_L_LM_SFT, 1, 1),
+	SOC_DAPM_SINGLE("OUTMIX R Switch", RT5645_LOUT_MIXER,
+			RT5645_M_OV_R_LM_SFT, 1, 1),
+};
+
+/*DAC1 L/R source*/ /* MX-29 [9:8] [11:10] */
+static const char * const rt5645_dac1_src[] = {
+	"IF1 DAC", "IF2 DAC", "IF3 DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_dac1l_enum, RT5645_AD_DA_MIXER,
+	RT5645_DAC1_L_SEL_SFT, rt5645_dac1_src);
+
+static const struct snd_kcontrol_new rt5645_dac1l_mux =
+	SOC_DAPM_ENUM("DAC1 L source", rt5645_dac1l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_dac1r_enum, RT5645_AD_DA_MIXER,
+	RT5645_DAC1_R_SEL_SFT, rt5645_dac1_src);
+
+static const struct snd_kcontrol_new rt5645_dac1r_mux =
+	SOC_DAPM_ENUM("DAC1 R source", rt5645_dac1r_enum);
+
+/*DAC2 L/R source*/ /* MX-1B [6:4] [2:0] */
+static const char * const rt5645_dac12_src[] = {
+	"IF1 DAC", "IF2 DAC", "IF3 DAC", "Mono ADC", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_dac2l_enum, RT5645_DAC_CTRL,
+	RT5645_DAC2_L_SEL_SFT, rt5645_dac12_src);
+
+static const struct snd_kcontrol_new rt5645_dac_l2_mux =
+	SOC_DAPM_ENUM("DAC2 L source", rt5645_dac2l_enum);
+
+static const char * const rt5645_dacr2_src[] = {
+	"IF1 DAC", "IF2 DAC", "IF3 DAC", "Mono ADC", "Haptic"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_dac2r_enum, RT5645_DAC_CTRL,
+	RT5645_DAC2_R_SEL_SFT, rt5645_dacr2_src);
+
+static const struct snd_kcontrol_new rt5645_dac_r2_mux =
+	SOC_DAPM_ENUM("DAC2 R source", rt5645_dac2r_enum);
+
+
+/* INL/R source */
+static const char * const rt5645_inl_src[] = {
+	"IN2P", "MonoP"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_inl_enum, RT5645_INL1_INR1_VOL,
+	RT5645_INL_SEL_SFT, rt5645_inl_src);
+
+static const struct snd_kcontrol_new rt5645_inl_mux =
+	SOC_DAPM_ENUM("INL source", rt5645_inl_enum);
+
+static const char * const rt5645_inr_src[] = {
+	"IN2N", "MonoN"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_inr_enum, RT5645_INL1_INR1_VOL,
+	RT5645_INR_SEL_SFT, rt5645_inr_src);
+
+static const struct snd_kcontrol_new rt5645_inr_mux =
+	SOC_DAPM_ENUM("INR source", rt5645_inr_enum);
+
+/* Stereo1 ADC source */
+/* MX-27 [12] */
+static const char * const rt5645_stereo_adc1_src[] = {
+	"DAC MIX", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_stereo1_adc1_enum, RT5645_STO1_ADC_MIXER,
+	RT5645_ADC_1_SRC_SFT, rt5645_stereo_adc1_src);
+
+static const struct snd_kcontrol_new rt5645_sto_adc1_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC1 Mux", rt5645_stereo1_adc1_enum);
+
+/* MX-27 [11] */
+static const char * const rt5645_stereo_adc2_src[] = {
+	"DAC MIX", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_stereo1_adc2_enum, RT5645_STO1_ADC_MIXER,
+	RT5645_ADC_2_SRC_SFT, rt5645_stereo_adc2_src);
+
+static const struct snd_kcontrol_new rt5645_sto_adc2_mux =
+	SOC_DAPM_ENUM("Stereo1 ADC2 Mux", rt5645_stereo1_adc2_enum);
+
+/* MX-27 [8] */
+static const char * const rt5645_stereo_dmic_src[] = {
+	"DMIC1", "DMIC2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_stereo1_dmic_enum, RT5645_STO1_ADC_MIXER,
+	RT5645_DMIC_SRC_SFT, rt5645_stereo_dmic_src);
+
+static const struct snd_kcontrol_new rt5645_sto1_dmic_mux =
+	SOC_DAPM_ENUM("Stereo1 DMIC source", rt5645_stereo1_dmic_enum);
+
+/* Mono ADC source */
+/* MX-28 [12] */
+static const char * const rt5645_mono_adc_l1_src[] = {
+	"Mono DAC MIXL", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_mono_adc_l1_enum, RT5645_MONO_ADC_MIXER,
+	RT5645_MONO_ADC_L1_SRC_SFT, rt5645_mono_adc_l1_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_l1_mux =
+	SOC_DAPM_ENUM("Mono ADC1 left source", rt5645_mono_adc_l1_enum);
+/* MX-28 [11] */
+static const char * const rt5645_mono_adc_l2_src[] = {
+	"Mono DAC MIXL", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_mono_adc_l2_enum, RT5645_MONO_ADC_MIXER,
+	RT5645_MONO_ADC_L2_SRC_SFT, rt5645_mono_adc_l2_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_l2_mux =
+	SOC_DAPM_ENUM("Mono ADC2 left source", rt5645_mono_adc_l2_enum);
+
+/* MX-28 [8] */
+static const char * const rt5645_mono_dmic_src[] = {
+	"DMIC1", "DMIC2"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_mono_dmic_l_enum, RT5645_MONO_ADC_MIXER,
+	RT5645_MONO_DMIC_L_SRC_SFT, rt5645_mono_dmic_src);
+
+static const struct snd_kcontrol_new rt5645_mono_dmic_l_mux =
+	SOC_DAPM_ENUM("Mono DMIC left source", rt5645_mono_dmic_l_enum);
+/* MX-28 [1:0] */
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_mono_dmic_r_enum, RT5645_MONO_ADC_MIXER,
+	RT5645_MONO_DMIC_R_SRC_SFT, rt5645_mono_dmic_src);
+
+static const struct snd_kcontrol_new rt5645_mono_dmic_r_mux =
+	SOC_DAPM_ENUM("Mono DMIC Right source", rt5645_mono_dmic_r_enum);
+/* MX-28 [4] */
+static const char * const rt5645_mono_adc_r1_src[] = {
+	"Mono DAC MIXR", "ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_mono_adc_r1_enum, RT5645_MONO_ADC_MIXER,
+	RT5645_MONO_ADC_R1_SRC_SFT, rt5645_mono_adc_r1_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_r1_mux =
+	SOC_DAPM_ENUM("Mono ADC1 right source", rt5645_mono_adc_r1_enum);
+/* MX-28 [3] */
+static const char * const rt5645_mono_adc_r2_src[] = {
+	"Mono DAC MIXR", "DMIC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_mono_adc_r2_enum, RT5645_MONO_ADC_MIXER,
+	RT5645_MONO_ADC_R2_SRC_SFT, rt5645_mono_adc_r2_src);
+
+static const struct snd_kcontrol_new rt5645_mono_adc_r2_mux =
+	SOC_DAPM_ENUM("Mono ADC2 right source", rt5645_mono_adc_r2_enum);
+
+/* MX-77 [9:8] */
+static const char * const rt5645_if1_adc_in_src[] = {
+	"IF_ADC1", "IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_if1_adc_in_enum, RT5645_TDM_CTRL_1,
+	RT5645_IF1_ADC_IN_SFT, rt5645_if1_adc_in_src);
+
+static const struct snd_kcontrol_new rt5645_if1_adc_in_mux =
+	SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum);
+
+/* MX-2F [13:12] */
+static const char * const rt5645_if2_adc_in_src[] = {
+	"IF_ADC1", "IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_if2_adc_in_enum, RT5645_DIG_INF1_DATA,
+	RT5645_IF2_ADC_IN_SFT, rt5645_if2_adc_in_src);
+
+static const struct snd_kcontrol_new rt5645_if2_adc_in_mux =
+	SOC_DAPM_ENUM("IF2 ADC IN source", rt5645_if2_adc_in_enum);
+
+/* MX-2F [1:0] */
+static const char * const rt5645_if3_adc_in_src[] = {
+	"IF_ADC1", "IF_ADC2", "VAD_ADC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_if3_adc_in_enum, RT5645_DIG_INF1_DATA,
+	RT5645_IF3_ADC_IN_SFT, rt5645_if3_adc_in_src);
+
+static const struct snd_kcontrol_new rt5645_if3_adc_in_mux =
+	SOC_DAPM_ENUM("IF3 ADC IN source", rt5645_if3_adc_in_enum);
+
+/* MX-31 [15] [13] [11] [9] */
+static const char * const rt5645_pdm_src[] = {
+	"Mono DAC", "Stereo DAC"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_pdm1_l_enum, RT5645_PDM_OUT_CTRL,
+	RT5645_PDM1_L_SFT, rt5645_pdm_src);
+
+static const struct snd_kcontrol_new rt5645_pdm1_l_mux =
+	SOC_DAPM_ENUM("PDM1 L source", rt5645_pdm1_l_enum);
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_pdm1_r_enum, RT5645_PDM_OUT_CTRL,
+	RT5645_PDM1_R_SFT, rt5645_pdm_src);
+
+static const struct snd_kcontrol_new rt5645_pdm1_r_mux =
+	SOC_DAPM_ENUM("PDM1 R source", rt5645_pdm1_r_enum);
+
+/* MX-9D [9:8] */
+static const char * const rt5645_vad_adc_src[] = {
+	"Sto1 ADC L", "Mono ADC L", "Mono ADC R"
+};
+
+static SOC_ENUM_SINGLE_DECL(
+	rt5645_vad_adc_enum, RT5645_VAD_CTRL4,
+	RT5645_VAD_SEL_SFT, rt5645_vad_adc_src);
+
+static const struct snd_kcontrol_new rt5645_vad_adc_mux =
+	SOC_DAPM_ENUM("VAD ADC source", rt5645_vad_adc_enum);
+
+static const struct snd_kcontrol_new spk_l_vol_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_SPK_VOL,
+		RT5645_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new spk_r_vol_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_SPK_VOL,
+		RT5645_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hp_l_vol_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_HP_VOL,
+		RT5645_L_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new hp_r_vol_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_HP_VOL,
+		RT5645_R_MUTE_SFT, 1, 1);
+
+static const struct snd_kcontrol_new pdm1_l_vol_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_PDM_OUT_CTRL,
+		RT5645_M_PDM1_L, 1, 1);
+
+static const struct snd_kcontrol_new pdm1_r_vol_control =
+	SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5645_PDM_OUT_CTRL,
+		RT5645_M_PDM1_R, 1, 1);
+
+static void hp_amp_power(struct snd_soc_codec *codec, int on)
+{
+	static int hp_amp_power_count;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+	if (on) {
+		if (hp_amp_power_count <= 0) {
+			/* depop parameters */
+			snd_soc_update_bits(codec, RT5645_DEPOP_M2,
+				RT5645_DEPOP_MASK, RT5645_DEPOP_MAN);
+			snd_soc_write(codec, RT5645_DEPOP_M1, 0x000d);
+			regmap_write(rt5645->regmap, RT5645_PR_BASE +
+				RT5645_HP_DCC_INT1, 0x9f01);
+			mdelay(150);
+			/* headphone amp power on */
+			snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+				RT5645_PWR_FV1 | RT5645_PWR_FV2 , 0);
+			snd_soc_update_bits(codec, RT5645_PWR_VOL,
+				RT5645_PWR_HV_L | RT5645_PWR_HV_R,
+				RT5645_PWR_HV_L | RT5645_PWR_HV_R);
+			snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+				RT5645_PWR_HP_L | RT5645_PWR_HP_R |
+				RT5645_PWR_HA,
+				RT5645_PWR_HP_L | RT5645_PWR_HP_R |
+				RT5645_PWR_HA);
+			mdelay(5);
+			snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+				RT5645_PWR_FV1 | RT5645_PWR_FV2,
+				RT5645_PWR_FV1 | RT5645_PWR_FV2);
+
+			snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+				RT5645_HP_CO_MASK | RT5645_HP_SG_MASK,
+				RT5645_HP_CO_EN | RT5645_HP_SG_EN);
+			regmap_write(rt5645->regmap, RT5645_PR_BASE +
+				0x14, 0x1aaa);
+			regmap_write(rt5645->regmap, RT5645_PR_BASE +
+				0x24, 0x0430);
+		}
+		hp_amp_power_count++;
+	} else {
+		hp_amp_power_count--;
+		if (hp_amp_power_count <= 0) {
+			snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+				RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK |
+				RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS |
+				RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS);
+			/* headphone amp power down */
+			snd_soc_write(codec, RT5645_DEPOP_M1, 0x0000);
+			snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+				RT5645_PWR_HP_L | RT5645_PWR_HP_R |
+				RT5645_PWR_HA, 0);
+		}
+	}
+}
+
+static int rt5645_hp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		hp_amp_power(codec, 1);
+		/* headphone unmute sequence */
+		snd_soc_update_bits(codec, RT5645_DEPOP_M3, RT5645_CP_FQ1_MASK |
+			RT5645_CP_FQ2_MASK | RT5645_CP_FQ3_MASK,
+			(RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ1_SFT) |
+			(RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
+			(RT5645_CP_FQ_192_KHZ << RT5645_CP_FQ3_SFT));
+		regmap_write(rt5645->regmap,
+			RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_SMT_TRIG_MASK, RT5645_SMT_TRIG_EN);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_RSTN_MASK, RT5645_RSTN_EN);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_RSTN_MASK | RT5645_HP_L_SMT_MASK |
+			RT5645_HP_R_SMT_MASK, RT5645_RSTN_DIS |
+			RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN);
+		msleep(40);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_HP_SG_MASK | RT5645_HP_L_SMT_MASK |
+			RT5645_HP_R_SMT_MASK, RT5645_HP_SG_DIS |
+			RT5645_HP_L_SMT_DIS | RT5645_HP_R_SMT_DIS);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		/* headphone mute sequence */
+		snd_soc_update_bits(codec, RT5645_DEPOP_M3,
+			RT5645_CP_FQ1_MASK | RT5645_CP_FQ2_MASK |
+			RT5645_CP_FQ3_MASK,
+			(RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ1_SFT) |
+			(RT5645_CP_FQ_12_KHZ << RT5645_CP_FQ2_SFT) |
+			(RT5645_CP_FQ_96_KHZ << RT5645_CP_FQ3_SFT));
+		regmap_write(rt5645->regmap,
+			RT5645_PR_BASE + RT5645_MAMP_INT_REG2, 0xfc00);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_HP_SG_MASK, RT5645_HP_SG_EN);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_RSTP_MASK, RT5645_RSTP_EN);
+		snd_soc_update_bits(codec, RT5645_DEPOP_M1,
+			RT5645_RSTP_MASK | RT5645_HP_L_SMT_MASK |
+			RT5645_HP_R_SMT_MASK, RT5645_RSTP_DIS |
+			RT5645_HP_L_SMT_EN | RT5645_HP_R_SMT_EN);
+		msleep(30);
+		hp_amp_power(codec, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5645_PWR_DIG1,
+			RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
+			RT5645_PWR_CLS_D_L,
+			RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
+			RT5645_PWR_CLS_D_L);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5645_PWR_DIG1,
+			RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
+			RT5645_PWR_CLS_D_L, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5645_lout_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		hp_amp_power(codec, 1);
+		snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+			RT5645_PWR_LM, RT5645_PWR_LM);
+		snd_soc_update_bits(codec, RT5645_LOUT1,
+			RT5645_L_MUTE | RT5645_R_MUTE, 0);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5645_LOUT1,
+			RT5645_L_MUTE | RT5645_R_MUTE,
+			RT5645_L_MUTE | RT5645_R_MUTE);
+		snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+			RT5645_PWR_LM, 0);
+		hp_amp_power(codec, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int rt5645_bst2_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec, RT5645_PWR_ANLG2,
+			RT5645_PWR_BST2_P, RT5645_PWR_BST2_P);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, RT5645_PWR_ANLG2,
+			RT5645_PWR_BST2_P, 0);
+		break;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
+	SND_SOC_DAPM_SUPPLY("LDO2", RT5645_PWR_MIXER,
+		RT5645_PWR_LDO2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("PLL1", RT5645_PWR_ANLG2,
+		RT5645_PWR_PLL_BIT, 0, NULL, 0),
+
+	SND_SOC_DAPM_SUPPLY("JD Power", RT5645_PWR_ANLG2,
+		RT5645_PWR_JD1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5645_PWR_VOL,
+		RT5645_PWR_MIC_DET_BIT, 0, NULL, 0),
+
+	/* Input Side */
+	/* micbias */
+	SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2,
+			RT5645_PWR_MB1_BIT, 0),
+	SND_SOC_DAPM_MICBIAS("micbias2", RT5645_PWR_ANLG2,
+			RT5645_PWR_MB2_BIT, 0),
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("DMIC L1"),
+	SND_SOC_DAPM_INPUT("DMIC R1"),
+	SND_SOC_DAPM_INPUT("DMIC L2"),
+	SND_SOC_DAPM_INPUT("DMIC R2"),
+
+	SND_SOC_DAPM_INPUT("IN1P"),
+	SND_SOC_DAPM_INPUT("IN1N"),
+	SND_SOC_DAPM_INPUT("IN2P"),
+	SND_SOC_DAPM_INPUT("IN2N"),
+
+	SND_SOC_DAPM_INPUT("Haptic Generator"),
+
+	SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
+		set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_SUPPLY("DMIC1 Power", RT5645_DMIC_CTRL1,
+		RT5645_DMIC_1_EN_SFT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("DMIC2 Power", RT5645_DMIC_CTRL1,
+		RT5645_DMIC_2_EN_SFT, 0, NULL, 0),
+	/* Boost */
+	SND_SOC_DAPM_PGA("BST1", RT5645_PWR_ANLG2,
+		RT5645_PWR_BST1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA_E("BST2", RT5645_PWR_ANLG2,
+		RT5645_PWR_BST2_BIT, 0, NULL, 0, rt5645_bst2_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	/* Input Volume */
+	SND_SOC_DAPM_PGA("INL VOL", RT5645_PWR_VOL,
+		RT5645_PWR_IN_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("INR VOL", RT5645_PWR_VOL,
+		RT5645_PWR_IN_R_BIT, 0, NULL, 0),
+	/* REC Mixer */
+	SND_SOC_DAPM_MIXER("RECMIXL", RT5645_PWR_MIXER, RT5645_PWR_RM_L_BIT,
+			0, rt5645_rec_l_mix, ARRAY_SIZE(rt5645_rec_l_mix)),
+	SND_SOC_DAPM_MIXER("RECMIXR", RT5645_PWR_MIXER, RT5645_PWR_RM_R_BIT,
+			0, rt5645_rec_r_mix, ARRAY_SIZE(rt5645_rec_r_mix)),
+	/* ADCs */
+	SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_SUPPLY("ADC L power", RT5645_PWR_DIG1,
+		RT5645_PWR_ADC_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("ADC R power", RT5645_PWR_DIG1,
+		RT5645_PWR_ADC_R_BIT, 0, NULL, 0),
+
+	/* ADC Mux */
+	SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_sto1_dmic_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_sto_adc2_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_sto_adc2_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_sto_adc1_mux),
+	SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_sto_adc1_mux),
+	SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_mono_dmic_l_mux),
+	SND_SOC_DAPM_MUX("Mono DMIC R Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_mono_dmic_r_mux),
+	SND_SOC_DAPM_MUX("Mono ADC L2 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_mono_adc_l2_mux),
+	SND_SOC_DAPM_MUX("Mono ADC L1 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_mono_adc_l1_mux),
+	SND_SOC_DAPM_MUX("Mono ADC R1 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_mono_adc_r1_mux),
+	SND_SOC_DAPM_MUX("Mono ADC R2 Mux", SND_SOC_NOPM, 0, 0,
+		&rt5645_mono_adc_r2_mux),
+	/* ADC Mixer */
+
+	SND_SOC_DAPM_SUPPLY_S("adc stereo1 filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_ADC_S1F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("adc stereo2 filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_ADC_S2F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER_E("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5645_sto1_adc_l_mix, ARRAY_SIZE(rt5645_sto1_adc_l_mix),
+		NULL, 0),
+	SND_SOC_DAPM_MIXER_E("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5645_sto1_adc_r_mix, ARRAY_SIZE(rt5645_sto1_adc_r_mix),
+		NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("adc mono left filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_ADC_MF_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER_E("Mono ADC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5645_mono_adc_l_mix, ARRAY_SIZE(rt5645_mono_adc_l_mix),
+		NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("adc mono right filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_ADC_MF_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER_E("Mono ADC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5645_mono_adc_r_mix, ARRAY_SIZE(rt5645_mono_adc_r_mix),
+		NULL, 0),
+
+	/* ADC PGA */
+	SND_SOC_DAPM_PGA("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Sto2 ADC LR MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("VAD_ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* IF1 2 Mux */
+	SND_SOC_DAPM_MUX("IF1 ADC Mux", SND_SOC_NOPM,
+		0, 0, &rt5645_if1_adc_in_mux),
+	SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM,
+		0, 0, &rt5645_if2_adc_in_mux),
+
+	/* Digital Interface */
+	SND_SOC_DAPM_SUPPLY("I2S1", RT5645_PWR_DIG1,
+		RT5645_PWR_I2S1_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("I2S2", RT5645_PWR_DIG1,
+		RT5645_PWR_I2S2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("IF2 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	/* Digital Interface Select */
+	SND_SOC_DAPM_MUX("VAD ADC Mux", SND_SOC_NOPM,
+		0, 0, &rt5645_vad_adc_mux),
+
+	/* Audio Interface */
+	SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("AIF2RX", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+	/* Output Side */
+	/* DAC mixer before sound effect  */
+	SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0,
+		rt5645_dac_l_mix, ARRAY_SIZE(rt5645_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0,
+		rt5645_dac_r_mix, ARRAY_SIZE(rt5645_dac_r_mix)),
+
+	/* DAC2 channel Mux */
+	SND_SOC_DAPM_MUX("DAC L2 Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac_l2_mux),
+	SND_SOC_DAPM_MUX("DAC R2 Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac_r2_mux),
+	SND_SOC_DAPM_PGA("DAC L2 Volume", RT5645_PWR_DIG1,
+		RT5645_PWR_DAC_L2_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DAC R2 Volume", RT5645_PWR_DIG1,
+		RT5645_PWR_DAC_R2_BIT, 0, NULL, 0),
+
+	SND_SOC_DAPM_MUX("DAC1 L Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac1l_mux),
+	SND_SOC_DAPM_MUX("DAC1 R Mux", SND_SOC_NOPM, 0, 0, &rt5645_dac1r_mux),
+
+	/* DAC Mixer */
+	SND_SOC_DAPM_SUPPLY_S("dac stereo1 filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_DAC_S1F_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("dac mono left filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_DAC_MF_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("dac mono right filter", 1, RT5645_PWR_DIG2,
+		RT5645_PWR_DAC_MF_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5645_sto_dac_l_mix, ARRAY_SIZE(rt5645_sto_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5645_sto_dac_r_mix, ARRAY_SIZE(rt5645_sto_dac_r_mix)),
+	SND_SOC_DAPM_MIXER("Mono DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5645_mono_dac_l_mix, ARRAY_SIZE(rt5645_mono_dac_l_mix)),
+	SND_SOC_DAPM_MIXER("Mono DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5645_mono_dac_r_mix, ARRAY_SIZE(rt5645_mono_dac_r_mix)),
+	SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0,
+		rt5645_dig_l_mix, ARRAY_SIZE(rt5645_dig_l_mix)),
+	SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0,
+		rt5645_dig_r_mix, ARRAY_SIZE(rt5645_dig_r_mix)),
+
+	/* DACs */
+	SND_SOC_DAPM_DAC("DAC L1", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_L1_BIT,
+		0),
+	SND_SOC_DAPM_DAC("DAC L2", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_L2_BIT,
+		0),
+	SND_SOC_DAPM_DAC("DAC R1", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_R1_BIT,
+		0),
+	SND_SOC_DAPM_DAC("DAC R2", NULL, RT5645_PWR_DIG1, RT5645_PWR_DAC_R2_BIT,
+		0),
+	/* OUT Mixer */
+	SND_SOC_DAPM_MIXER("SPK MIXL", RT5645_PWR_MIXER, RT5645_PWR_SM_L_BIT,
+		0, rt5645_spk_l_mix, ARRAY_SIZE(rt5645_spk_l_mix)),
+	SND_SOC_DAPM_MIXER("SPK MIXR", RT5645_PWR_MIXER, RT5645_PWR_SM_R_BIT,
+		0, rt5645_spk_r_mix, ARRAY_SIZE(rt5645_spk_r_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXL", RT5645_PWR_MIXER, RT5645_PWR_OM_L_BIT,
+		0, rt5645_out_l_mix, ARRAY_SIZE(rt5645_out_l_mix)),
+	SND_SOC_DAPM_MIXER("OUT MIXR", RT5645_PWR_MIXER, RT5645_PWR_OM_R_BIT,
+		0, rt5645_out_r_mix, ARRAY_SIZE(rt5645_out_r_mix)),
+	/* Ouput Volume */
+	SND_SOC_DAPM_SWITCH("SPKVOL L", RT5645_PWR_VOL, RT5645_PWR_SV_L_BIT, 0,
+		&spk_l_vol_control),
+	SND_SOC_DAPM_SWITCH("SPKVOL R", RT5645_PWR_VOL, RT5645_PWR_SV_R_BIT, 0,
+		&spk_r_vol_control),
+	SND_SOC_DAPM_MIXER("HPOVOL MIXL", RT5645_PWR_VOL, RT5645_PWR_HV_L_BIT,
+		0, rt5645_hpvoll_mix, ARRAY_SIZE(rt5645_hpvoll_mix)),
+	SND_SOC_DAPM_MIXER("HPOVOL MIXR", RT5645_PWR_VOL, RT5645_PWR_HV_R_BIT,
+		0, rt5645_hpvolr_mix, ARRAY_SIZE(rt5645_hpvolr_mix)),
+	SND_SOC_DAPM_SUPPLY("HPOVOL MIXL Power", RT5645_PWR_MIXER,
+		RT5645_PWR_HM_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("HPOVOL MIXR Power", RT5645_PWR_MIXER,
+		RT5645_PWR_HM_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SWITCH("HPOVOL L", SND_SOC_NOPM, 0, 0, &hp_l_vol_control),
+	SND_SOC_DAPM_SWITCH("HPOVOL R", SND_SOC_NOPM, 0, 0, &hp_r_vol_control),
+
+	/* HPO/LOUT/Mono Mixer */
+	SND_SOC_DAPM_MIXER("SPOL MIX", SND_SOC_NOPM, 0, 0, rt5645_spo_l_mix,
+		ARRAY_SIZE(rt5645_spo_l_mix)),
+	SND_SOC_DAPM_MIXER("SPOR MIX", SND_SOC_NOPM, 0, 0, rt5645_spo_r_mix,
+		ARRAY_SIZE(rt5645_spo_r_mix)),
+	SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, rt5645_hpo_mix,
+		ARRAY_SIZE(rt5645_hpo_mix)),
+	SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0, rt5645_lout_mix,
+		ARRAY_SIZE(rt5645_lout_mix)),
+
+	SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0, rt5645_hp_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0, rt5645_lout_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_PGA_S("SPK amp", 2, SND_SOC_NOPM, 0, 0, rt5645_spk_event,
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+	/* PDM */
+	SND_SOC_DAPM_SUPPLY("PDM1 Power", RT5645_PWR_DIG2, RT5645_PWR_PDM1_BIT,
+		0, NULL, 0),
+	SND_SOC_DAPM_MUX("PDM1 L Mux", SND_SOC_NOPM, 0, 0, &rt5645_pdm1_l_mux),
+	SND_SOC_DAPM_MUX("PDM1 R Mux", SND_SOC_NOPM, 0, 0, &rt5645_pdm1_r_mux),
+
+	SND_SOC_DAPM_SWITCH("PDM1 L", SND_SOC_NOPM, 0, 0, &pdm1_l_vol_control),
+	SND_SOC_DAPM_SWITCH("PDM1 R", SND_SOC_NOPM, 0, 0, &pdm1_r_vol_control),
+
+	/* Output Lines */
+	SND_SOC_DAPM_OUTPUT("HPOL"),
+	SND_SOC_DAPM_OUTPUT("HPOR"),
+	SND_SOC_DAPM_OUTPUT("LOUTL"),
+	SND_SOC_DAPM_OUTPUT("LOUTR"),
+	SND_SOC_DAPM_OUTPUT("PDM1L"),
+	SND_SOC_DAPM_OUTPUT("PDM1R"),
+	SND_SOC_DAPM_OUTPUT("SPOL"),
+	SND_SOC_DAPM_OUTPUT("SPOR"),
+};
+
+static const struct snd_soc_dapm_route rt5645_dapm_routes[] = {
+	{ "IN1P", NULL, "LDO2" },
+	{ "IN2P", NULL, "LDO2" },
+
+	{ "DMIC1", NULL, "DMIC L1" },
+	{ "DMIC1", NULL, "DMIC R1" },
+	{ "DMIC2", NULL, "DMIC L2" },
+	{ "DMIC2", NULL, "DMIC R2" },
+
+	{ "BST1", NULL, "IN1P" },
+	{ "BST1", NULL, "IN1N" },
+	{ "BST1", NULL, "JD Power" },
+	{ "BST1", NULL, "Mic Det Power" },
+	{ "BST2", NULL, "IN2P" },
+	{ "BST2", NULL, "IN2N" },
+
+	{ "INL VOL", NULL, "IN2P" },
+	{ "INR VOL", NULL, "IN2N" },
+
+	{ "RECMIXL", "HPOL Switch", "HPOL" },
+	{ "RECMIXL", "INL Switch", "INL VOL" },
+	{ "RECMIXL", "BST2 Switch", "BST2" },
+	{ "RECMIXL", "BST1 Switch", "BST1" },
+	{ "RECMIXL", "OUT MIXL Switch", "OUT MIXL" },
+
+	{ "RECMIXR", "HPOR Switch", "HPOR" },
+	{ "RECMIXR", "INR Switch", "INR VOL" },
+	{ "RECMIXR", "BST2 Switch", "BST2" },
+	{ "RECMIXR", "BST1 Switch", "BST1" },
+	{ "RECMIXR", "OUT MIXR Switch", "OUT MIXR" },
+
+	{ "ADC L", NULL, "RECMIXL" },
+	{ "ADC L", NULL, "ADC L power" },
+	{ "ADC R", NULL, "RECMIXR" },
+	{ "ADC R", NULL, "ADC R power" },
+
+	{"DMIC L1", NULL, "DMIC CLK"},
+	{"DMIC L1", NULL, "DMIC1 Power"},
+	{"DMIC R1", NULL, "DMIC CLK"},
+	{"DMIC R1", NULL, "DMIC1 Power"},
+	{"DMIC L2", NULL, "DMIC CLK"},
+	{"DMIC L2", NULL, "DMIC2 Power"},
+	{"DMIC R2", NULL, "DMIC CLK"},
+	{"DMIC R2", NULL, "DMIC2 Power"},
+
+	{ "Stereo1 DMIC Mux", "DMIC1", "DMIC1" },
+	{ "Stereo1 DMIC Mux", "DMIC2", "DMIC2" },
+
+	{ "Mono DMIC L Mux", "DMIC1", "DMIC L1" },
+	{ "Mono DMIC L Mux", "DMIC2", "DMIC L2" },
+
+	{ "Mono DMIC R Mux", "DMIC1", "DMIC R1" },
+	{ "Mono DMIC R Mux", "DMIC2", "DMIC R2" },
+
+	{ "Stereo1 ADC L2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+	{ "Stereo1 ADC L2 Mux", "DAC MIX", "DAC MIXL" },
+	{ "Stereo1 ADC L1 Mux", "ADC", "ADC L" },
+	{ "Stereo1 ADC L1 Mux", "DAC MIX", "DAC MIXL" },
+
+	{ "Stereo1 ADC R1 Mux", "ADC", "ADC R" },
+	{ "Stereo1 ADC R1 Mux", "DAC MIX", "DAC MIXR" },
+	{ "Stereo1 ADC R2 Mux", "DMIC", "Stereo1 DMIC Mux" },
+	{ "Stereo1 ADC R2 Mux", "DAC MIX", "DAC MIXR" },
+
+	{ "Mono ADC L2 Mux", "DMIC", "Mono DMIC L Mux" },
+	{ "Mono ADC L2 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+	{ "Mono ADC L1 Mux", "Mono DAC MIXL", "Mono DAC MIXL" },
+	{ "Mono ADC L1 Mux", "ADC", "ADC L" },
+
+	{ "Mono ADC R1 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+	{ "Mono ADC R1 Mux", "ADC", "ADC R" },
+	{ "Mono ADC R2 Mux", "DMIC", "Mono DMIC R Mux" },
+	{ "Mono ADC R2 Mux", "Mono DAC MIXR", "Mono DAC MIXR" },
+
+	{ "Sto1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux" },
+	{ "Sto1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux" },
+	{ "Sto1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux" },
+	{ "Sto1 ADC MIXR", "ADC2 Switch", "Stereo1 ADC R2 Mux" },
+
+	{ "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" },
+	{ "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" },
+	{ "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" },
+	{ "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" },
+	{ "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Mono ADC MIXL", "ADC1 Switch", "Mono ADC L1 Mux" },
+	{ "Mono ADC MIXL", "ADC2 Switch", "Mono ADC L2 Mux" },
+	{ "Mono ADC MIXL", NULL, "adc mono left filter" },
+	{ "adc mono left filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "Mono ADC MIXR", "ADC1 Switch", "Mono ADC R1 Mux" },
+	{ "Mono ADC MIXR", "ADC2 Switch", "Mono ADC R2 Mux" },
+	{ "Mono ADC MIXR", NULL, "adc mono right filter" },
+	{ "adc mono right filter", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "VAD ADC Mux", "Sto1 ADC L", "Stereo1 ADC MIXL" },
+	{ "VAD ADC Mux", "Mono ADC L", "Mono ADC MIXL" },
+	{ "VAD ADC Mux", "Mono ADC R", "Mono ADC MIXR" },
+
+	{ "IF_ADC1", NULL, "Stereo1 ADC MIXL" },
+	{ "IF_ADC1", NULL, "Stereo1 ADC MIXR" },
+	{ "IF_ADC2", NULL, "Mono ADC MIXL" },
+	{ "IF_ADC2", NULL, "Mono ADC MIXR" },
+	{ "VAD_ADC", NULL, "VAD ADC Mux" },
+
+	{ "IF1 ADC Mux", "IF_ADC1", "IF_ADC1" },
+	{ "IF1 ADC Mux", "IF_ADC2", "IF_ADC2" },
+	{ "IF1 ADC Mux", "VAD_ADC", "VAD_ADC" },
+
+	{ "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" },
+	{ "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" },
+	{ "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" },
+
+	{ "IF1 ADC", NULL, "I2S1" },
+	{ "IF1 ADC", NULL, "IF1 ADC Mux" },
+	{ "IF2 ADC", NULL, "I2S2" },
+	{ "IF2 ADC", NULL, "IF2 ADC Mux" },
+
+	{ "AIF1TX", NULL, "IF1 ADC" },
+	{ "AIF1TX", NULL, "IF2 ADC" },
+	{ "AIF2TX", NULL, "IF2 ADC" },
+
+	{ "IF1 DAC1", NULL, "AIF1RX" },
+	{ "IF1 DAC2", NULL, "AIF1RX" },
+	{ "IF2 DAC", NULL, "AIF2RX" },
+
+	{ "IF1 DAC1", NULL, "I2S1" },
+	{ "IF1 DAC2", NULL, "I2S1" },
+	{ "IF2 DAC", NULL, "I2S2" },
+
+	{ "IF1 DAC2 L", NULL, "IF1 DAC2" },
+	{ "IF1 DAC2 R", NULL, "IF1 DAC2" },
+	{ "IF1 DAC1 L", NULL, "IF1 DAC1" },
+	{ "IF1 DAC1 R", NULL, "IF1 DAC1" },
+	{ "IF2 DAC L", NULL, "IF2 DAC" },
+	{ "IF2 DAC R", NULL, "IF2 DAC" },
+
+	{ "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" },
+	{ "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" },
+
+	{ "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" },
+	{ "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" },
+
+	{ "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" },
+	{ "DAC1 MIXL", "DAC1 Switch", "DAC1 L Mux" },
+	{ "DAC1 MIXL", NULL, "dac stereo1 filter" },
+	{ "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" },
+	{ "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" },
+	{ "DAC1 MIXR", NULL, "dac stereo1 filter" },
+
+	{ "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" },
+	{ "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" },
+	{ "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" },
+	{ "DAC L2 Mux", "VAD_ADC", "VAD_ADC" },
+	{ "DAC L2 Volume", NULL, "DAC L2 Mux" },
+	{ "DAC L2 Volume", NULL, "dac mono left filter" },
+
+	{ "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" },
+	{ "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" },
+	{ "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" },
+	{ "DAC R2 Mux", "Haptic", "Haptic Generator" },
+	{ "DAC R2 Volume", NULL, "DAC R2 Mux" },
+	{ "DAC R2 Volume", NULL, "dac mono right filter" },
+
+	{ "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+	{ "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" },
+	{ "Stereo DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "Stereo DAC MIXL", NULL, "dac stereo1 filter" },
+	{ "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+	{ "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" },
+	{ "Stereo DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "Stereo DAC MIXR", NULL, "dac stereo1 filter" },
+
+	{ "Mono DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
+	{ "Mono DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "Mono DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "Mono DAC MIXL", NULL, "dac mono left filter" },
+	{ "Mono DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
+	{ "Mono DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "Mono DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "Mono DAC MIXR", NULL, "dac mono right filter" },
+
+	{ "DAC MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
+	{ "DAC MIXL", "DAC L2 Switch", "DAC L2 Volume" },
+	{ "DAC MIXL", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "DAC MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
+	{ "DAC MIXR", "DAC R2 Switch", "DAC R2 Volume" },
+	{ "DAC MIXR", "DAC L2 Switch", "DAC L2 Volume" },
+
+	{ "DAC L1", NULL, "Stereo DAC MIXL" },
+	{ "DAC L1", NULL, "PLL1", is_sys_clk_from_pll },
+	{ "DAC R1", NULL, "Stereo DAC MIXR" },
+	{ "DAC R1", NULL, "PLL1", is_sys_clk_from_pll },
+	{ "DAC L2", NULL, "Mono DAC MIXL" },
+	{ "DAC L2", NULL, "PLL1", is_sys_clk_from_pll },
+	{ "DAC R2", NULL, "Mono DAC MIXR" },
+	{ "DAC R2", NULL, "PLL1", is_sys_clk_from_pll },
+
+	{ "SPK MIXL", "BST1 Switch", "BST1" },
+	{ "SPK MIXL", "INL Switch", "INL VOL" },
+	{ "SPK MIXL", "DAC L1 Switch", "DAC L1" },
+	{ "SPK MIXL", "DAC L2 Switch", "DAC L2" },
+	{ "SPK MIXR", "BST2 Switch", "BST2" },
+	{ "SPK MIXR", "INR Switch", "INR VOL" },
+	{ "SPK MIXR", "DAC R1 Switch", "DAC R1" },
+	{ "SPK MIXR", "DAC R2 Switch", "DAC R2" },
+
+	{ "OUT MIXL", "BST1 Switch", "BST1" },
+	{ "OUT MIXL", "INL Switch", "INL VOL" },
+	{ "OUT MIXL", "DAC L2 Switch", "DAC L2" },
+	{ "OUT MIXL", "DAC L1 Switch", "DAC L1" },
+
+	{ "OUT MIXR", "BST2 Switch", "BST2" },
+	{ "OUT MIXR", "INR Switch", "INR VOL" },
+	{ "OUT MIXR", "DAC R2 Switch", "DAC R2" },
+	{ "OUT MIXR", "DAC R1 Switch", "DAC R1" },
+
+	{ "HPOVOL MIXL", "DAC1 Switch", "DAC L1" },
+	{ "HPOVOL MIXL", "DAC2 Switch", "DAC L2" },
+	{ "HPOVOL MIXL", "INL Switch", "INL VOL" },
+	{ "HPOVOL MIXL", "BST1 Switch", "BST1" },
+	{ "HPOVOL MIXL", NULL, "HPOVOL MIXL Power" },
+	{ "HPOVOL MIXR", "DAC1 Switch", "DAC R1" },
+	{ "HPOVOL MIXR", "DAC2 Switch", "DAC R2" },
+	{ "HPOVOL MIXR", "INR Switch", "INR VOL" },
+	{ "HPOVOL MIXR", "BST2 Switch", "BST2" },
+	{ "HPOVOL MIXR", NULL, "HPOVOL MIXR Power" },
+
+	{ "DAC 2", NULL, "DAC L2" },
+	{ "DAC 2", NULL, "DAC R2" },
+	{ "DAC 1", NULL, "DAC L1" },
+	{ "DAC 1", NULL, "DAC R1" },
+	{ "HPOVOL L", "Switch", "HPOVOL MIXL" },
+	{ "HPOVOL R", "Switch", "HPOVOL MIXR" },
+	{ "HPOVOL", NULL, "HPOVOL L" },
+	{ "HPOVOL", NULL, "HPOVOL R" },
+	{ "HPO MIX", "DAC1 Switch", "DAC 1" },
+	{ "HPO MIX", "HPVOL Switch", "HPOVOL" },
+
+	{ "SPKVOL L", "Switch", "SPK MIXL" },
+	{ "SPKVOL R", "Switch", "SPK MIXR" },
+
+	{ "SPOL MIX", "DAC R1 Switch", "DAC R1" },
+	{ "SPOL MIX", "DAC L1 Switch", "DAC L1" },
+	{ "SPOL MIX", "SPKVOL R Switch", "SPKVOL R" },
+	{ "SPOL MIX", "SPKVOL L Switch", "SPKVOL L" },
+	{ "SPOR MIX", "DAC R1 Switch", "DAC R1" },
+	{ "SPOR MIX", "SPKVOL R Switch", "SPKVOL R" },
+
+	{ "LOUT MIX", "DAC L1 Switch", "DAC L1" },
+	{ "LOUT MIX", "DAC R1 Switch", "DAC R1" },
+	{ "LOUT MIX", "OUTMIX L Switch", "OUT MIXL" },
+	{ "LOUT MIX", "OUTMIX R Switch", "OUT MIXR" },
+
+	{ "PDM1 L Mux", "Stereo DAC", "Stereo DAC MIXL" },
+	{ "PDM1 L Mux", "Mono DAC", "Mono DAC MIXL" },
+	{ "PDM1 L Mux", NULL, "PDM1 Power" },
+	{ "PDM1 R Mux", "Stereo DAC", "Stereo DAC MIXR" },
+	{ "PDM1 R Mux", "Mono DAC", "Mono DAC MIXR" },
+	{ "PDM1 R Mux", NULL, "PDM1 Power" },
+
+	{ "HP amp", NULL, "HPO MIX" },
+	{ "HP amp", NULL, "JD Power" },
+	{ "HP amp", NULL, "Mic Det Power" },
+	{ "HP amp", NULL, "LDO2" },
+	{ "HPOL", NULL, "HP amp" },
+	{ "HPOR", NULL, "HP amp" },
+
+	{ "LOUT amp", NULL, "LOUT MIX" },
+	{ "LOUTL", NULL, "LOUT amp" },
+	{ "LOUTR", NULL, "LOUT amp" },
+
+	{ "PDM1 L", "Switch", "PDM1 L Mux" },
+	{ "PDM1 R", "Switch", "PDM1 R Mux" },
+
+	{ "PDM1L", NULL, "PDM1 L" },
+	{ "PDM1R", NULL, "PDM1 R" },
+
+	{ "SPK amp", NULL, "SPOL MIX" },
+	{ "SPK amp", NULL, "SPOR MIX" },
+	{ "SPOL", NULL, "SPK amp" },
+	{ "SPOR", NULL, "SPK amp" },
+};
+
+static int get_clk_info(int sclk, int rate)
+{
+	int i, pd[] = {1, 2, 3, 4, 6, 8, 12, 16};
+
+	if (sclk <= 0 || rate <= 0)
+		return -EINVAL;
+
+	rate = rate << 8;
+	for (i = 0; i < ARRAY_SIZE(pd); i++)
+		if (sclk == rate * pd[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int rt5645_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val_len = 0, val_clk, mask_clk;
+	int pre_div, bclk_ms, frame_size;
+
+	rt5645->lrck[dai->id] = params_rate(params);
+	pre_div = get_clk_info(rt5645->sysclk, rt5645->lrck[dai->id]);
+	if (pre_div < 0) {
+		dev_err(codec->dev, "Unsupported clock setting\n");
+		return -EINVAL;
+	}
+	frame_size = snd_soc_params_to_frame_size(params);
+	if (frame_size < 0) {
+		dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
+		return -EINVAL;
+	}
+	bclk_ms = frame_size > 32;
+	rt5645->bclk[dai->id] = rt5645->lrck[dai->id] * (32 << bclk_ms);
+
+	dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
+		rt5645->bclk[dai->id], rt5645->lrck[dai->id]);
+	dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
+				bclk_ms, pre_div, dai->id);
+
+	switch (params_width(params)) {
+	case 16:
+		break;
+	case 20:
+		val_len |= RT5645_I2S_DL_20;
+		break;
+	case 24:
+		val_len |= RT5645_I2S_DL_24;
+		break;
+	case 8:
+		val_len |= RT5645_I2S_DL_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (dai->id) {
+	case RT5645_AIF1:
+		mask_clk = RT5645_I2S_BCLK_MS1_MASK | RT5645_I2S_PD1_MASK;
+		val_clk = bclk_ms << RT5645_I2S_BCLK_MS1_SFT |
+			pre_div << RT5645_I2S_PD1_SFT;
+		snd_soc_update_bits(codec, RT5645_I2S1_SDP,
+			RT5645_I2S_DL_MASK, val_len);
+		snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk);
+		break;
+	case  RT5645_AIF2:
+		mask_clk = RT5645_I2S_BCLK_MS2_MASK | RT5645_I2S_PD2_MASK;
+		val_clk = bclk_ms << RT5645_I2S_BCLK_MS2_SFT |
+			pre_div << RT5645_I2S_PD2_SFT;
+		snd_soc_update_bits(codec, RT5645_I2S2_SDP,
+			RT5645_I2S_DL_MASK, val_len);
+		snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk);
+		break;
+	default:
+		dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rt5645_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		rt5645->master[dai->id] = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		reg_val |= RT5645_I2S_MS_S;
+		rt5645->master[dai->id] = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		reg_val |= RT5645_I2S_BP_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		reg_val |= RT5645_I2S_DF_LEFT;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		reg_val |= RT5645_I2S_DF_PCM_A;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		reg_val |= RT5645_I2S_DF_PCM_B;
+		break;
+	default:
+		return -EINVAL;
+	}
+	switch (dai->id) {
+	case RT5645_AIF1:
+		snd_soc_update_bits(codec, RT5645_I2S1_SDP,
+			RT5645_I2S_MS_MASK | RT5645_I2S_BP_MASK |
+			RT5645_I2S_DF_MASK, reg_val);
+		break;
+	case  RT5645_AIF2:
+		snd_soc_update_bits(codec, RT5645_I2S1_SDP,
+			RT5645_I2S_MS_MASK | RT5645_I2S_BP_MASK |
+			RT5645_I2S_DF_MASK, reg_val);
+		break;
+	default:
+		dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int rt5645_set_dai_sysclk(struct snd_soc_dai *dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+	unsigned int reg_val = 0;
+
+	if (freq == rt5645->sysclk && clk_id == rt5645->sysclk_src)
+		return 0;
+
+	switch (clk_id) {
+	case RT5645_SCLK_S_MCLK:
+		reg_val |= RT5645_SCLK_SRC_MCLK;
+		break;
+	case RT5645_SCLK_S_PLL1:
+		reg_val |= RT5645_SCLK_SRC_PLL1;
+		break;
+	case RT5645_SCLK_S_RCCLK:
+		reg_val |= RT5645_SCLK_SRC_RCCLK;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
+		return -EINVAL;
+	}
+	snd_soc_update_bits(codec, RT5645_GLB_CLK,
+		RT5645_SCLK_SRC_MASK, reg_val);
+	rt5645->sysclk = freq;
+	rt5645->sysclk_src = clk_id;
+
+	dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
+
+	return 0;
+}
+
+/**
+ * rt5645_pll_calc - Calcualte PLL M/N/K code.
+ * @freq_in: external clock provided to codec.
+ * @freq_out: target clock which codec works on.
+ * @pll_code: Pointer to structure with M, N, K and bypass flag.
+ *
+ * Calcualte M/N/K code to configure PLL for codec. And K is assigned to 2
+ * which make calculation more efficiently.
+ *
+ * Returns 0 for success or negative error code.
+ */
+static int rt5645_pll_calc(const unsigned int freq_in,
+	const unsigned int freq_out, struct rt5645_pll_code *pll_code)
+{
+	int max_n = RT5645_PLL_N_MAX, max_m = RT5645_PLL_M_MAX;
+	int k, n = 0, m = 0, red, n_t, m_t, pll_out, in_t, out_t;
+	int red_t = abs(freq_out - freq_in);
+	bool bypass = false;
+
+	if (RT5645_PLL_INP_MAX < freq_in || RT5645_PLL_INP_MIN > freq_in)
+		return -EINVAL;
+
+	k = 100000000 / freq_out - 2;
+	if (k > RT5645_PLL_K_MAX)
+		k = RT5645_PLL_K_MAX;
+	for (n_t = 0; n_t <= max_n; n_t++) {
+		in_t = freq_in / (k + 2);
+		pll_out = freq_out / (n_t + 2);
+		if (in_t < 0)
+			continue;
+		if (in_t == pll_out) {
+			bypass = true;
+			n = n_t;
+			goto code_find;
+		}
+		red = abs(in_t - pll_out);
+		if (red < red_t) {
+			bypass = true;
+			n = n_t;
+			m = m_t;
+			if (red == 0)
+				goto code_find;
+			red_t = red;
+		}
+		for (m_t = 0; m_t <= max_m; m_t++) {
+			out_t = in_t / (m_t + 2);
+			red = abs(out_t - pll_out);
+			if (red < red_t) {
+				bypass = false;
+				n = n_t;
+				m = m_t;
+				if (red == 0)
+					goto code_find;
+				red_t = red;
+			}
+		}
+	}
+	pr_debug("Only get approximation about PLL\n");
+
+code_find:
+
+	pll_code->m_bp = bypass;
+	pll_code->m_code = m;
+	pll_code->n_code = n;
+	pll_code->k_code = k;
+	return 0;
+}
+
+static int rt5645_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
+			unsigned int freq_in, unsigned int freq_out)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+	struct rt5645_pll_code pll_code;
+	int ret;
+
+	if (source == rt5645->pll_src && freq_in == rt5645->pll_in &&
+	    freq_out == rt5645->pll_out)
+		return 0;
+
+	if (!freq_in || !freq_out) {
+		dev_dbg(codec->dev, "PLL disabled\n");
+
+		rt5645->pll_in = 0;
+		rt5645->pll_out = 0;
+		snd_soc_update_bits(codec, RT5645_GLB_CLK,
+			RT5645_SCLK_SRC_MASK, RT5645_SCLK_SRC_MCLK);
+		return 0;
+	}
+
+	switch (source) {
+	case RT5645_PLL1_S_MCLK:
+		snd_soc_update_bits(codec, RT5645_GLB_CLK,
+			RT5645_PLL1_SRC_MASK, RT5645_PLL1_SRC_MCLK);
+		break;
+	case RT5645_PLL1_S_BCLK1:
+	case RT5645_PLL1_S_BCLK2:
+		switch (dai->id) {
+		case RT5645_AIF1:
+			snd_soc_update_bits(codec, RT5645_GLB_CLK,
+				RT5645_PLL1_SRC_MASK, RT5645_PLL1_SRC_BCLK1);
+			break;
+		case  RT5645_AIF2:
+			snd_soc_update_bits(codec, RT5645_GLB_CLK,
+				RT5645_PLL1_SRC_MASK, RT5645_PLL1_SRC_BCLK2);
+			break;
+		default:
+			dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
+			return -EINVAL;
+		}
+		break;
+	default:
+		dev_err(codec->dev, "Unknown PLL source %d\n", source);
+		return -EINVAL;
+	}
+
+	ret = rt5645_pll_calc(freq_in, freq_out, &pll_code);
+	if (ret < 0) {
+		dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
+		return ret;
+	}
+
+	dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
+		pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
+		pll_code.n_code, pll_code.k_code);
+
+	snd_soc_write(codec, RT5645_PLL_CTRL1,
+		pll_code.n_code << RT5645_PLL_N_SFT | pll_code.k_code);
+	snd_soc_write(codec, RT5645_PLL_CTRL2,
+		(pll_code.m_bp ? 0 : pll_code.m_code) << RT5645_PLL_M_SFT |
+		pll_code.m_bp << RT5645_PLL_M_BP_SFT);
+
+	rt5645->pll_in = freq_in;
+	rt5645->pll_out = freq_out;
+	rt5645->pll_src = source;
+
+	return 0;
+}
+
+static int rt5645_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+			unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	unsigned int val = 0;
+
+	if (rx_mask || tx_mask)
+		val |= (1 << 14);
+
+	switch (slots) {
+	case 4:
+		val |= (1 << 12);
+		break;
+	case 6:
+		val |= (2 << 12);
+		break;
+	case 8:
+		val |= (3 << 12);
+		break;
+	case 2:
+	default:
+		break;
+	}
+
+	switch (slot_width) {
+	case 20:
+		val |= (1 << 10);
+		break;
+	case 24:
+		val |= (2 << 10);
+		break;
+	case 32:
+		val |= (3 << 10);
+		break;
+	case 16:
+	default:
+		break;
+	}
+
+	snd_soc_update_bits(codec, RT5645_TDM_CTRL_1, 0x7c00, val);
+
+	return 0;
+}
+
+static int rt5645_set_bias_level(struct snd_soc_codec *codec,
+			enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_STANDBY:
+		if (SND_SOC_BIAS_OFF == codec->dapm.bias_level) {
+			snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+				RT5645_PWR_VREF1 | RT5645_PWR_MB |
+				RT5645_PWR_BG | RT5645_PWR_VREF2,
+				RT5645_PWR_VREF1 | RT5645_PWR_MB |
+				RT5645_PWR_BG | RT5645_PWR_VREF2);
+			mdelay(10);
+			snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
+				RT5645_PWR_FV1 | RT5645_PWR_FV2,
+				RT5645_PWR_FV1 | RT5645_PWR_FV2);
+			snd_soc_update_bits(codec, RT5645_GEN_CTRL1,
+				RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL);
+		}
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100);
+		snd_soc_write(codec, RT5645_GEN_CTRL1, 0x0128);
+		snd_soc_write(codec, RT5645_PWR_DIG1, 0x0000);
+		snd_soc_write(codec, RT5645_PWR_DIG2, 0x0000);
+		snd_soc_write(codec, RT5645_PWR_VOL, 0x0000);
+		snd_soc_write(codec, RT5645_PWR_MIXER, 0x0000);
+		snd_soc_write(codec, RT5645_PWR_ANLG1, 0x0000);
+		snd_soc_write(codec, RT5645_PWR_ANLG2, 0x0000);
+		break;
+
+	default:
+		break;
+	}
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static int rt5645_probe(struct snd_soc_codec *codec)
+{
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+	rt5645->codec = codec;
+
+	rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200);
+	snd_soc_write(codec, RT5645_PR_BASE + 0x1c, 0xfd20);
+	snd_soc_write(codec, RT5645_PR_BASE + 0x20, 0x611f);
+	snd_soc_write(codec, RT5645_PR_BASE + 0x21, 0x4040);
+	snd_soc_write(codec, RT5645_PR_BASE + 0x23, 0x0004);
+
+	return 0;
+}
+
+static int rt5645_remove(struct snd_soc_codec *codec)
+{
+	rt5645_reset(codec);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5645_suspend(struct snd_soc_codec *codec)
+{
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt5645->regmap, true);
+	regcache_mark_dirty(rt5645->regmap);
+
+	return 0;
+}
+
+static int rt5645_resume(struct snd_soc_codec *codec)
+{
+	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(rt5645->regmap, false);
+	snd_soc_cache_sync(codec);
+
+	return 0;
+}
+#else
+#define rt5645_suspend NULL
+#define rt5645_resume NULL
+#endif
+
+#define RT5645_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5645_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+
+struct snd_soc_dai_ops rt5645_aif_dai_ops = {
+	.hw_params = rt5645_hw_params,
+	.set_fmt = rt5645_set_dai_fmt,
+	.set_sysclk = rt5645_set_dai_sysclk,
+	.set_tdm_slot = rt5645_set_tdm_slot,
+	.set_pll = rt5645_set_dai_pll,
+};
+
+struct snd_soc_dai_driver rt5645_dai[] = {
+	{
+		.name = "rt5645-aif1",
+		.id = RT5645_AIF1,
+		.playback = {
+			.stream_name = "AIF1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5645_STEREO_RATES,
+			.formats = RT5645_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5645_STEREO_RATES,
+			.formats = RT5645_FORMATS,
+		},
+		.ops = &rt5645_aif_dai_ops,
+	},
+	{
+		.name = "rt5645-aif2",
+		.id = RT5645_AIF2,
+		.playback = {
+			.stream_name = "AIF2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5645_STEREO_RATES,
+			.formats = RT5645_FORMATS,
+		},
+		.capture = {
+			.stream_name = "AIF2 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = RT5645_STEREO_RATES,
+			.formats = RT5645_FORMATS,
+		},
+		.ops = &rt5645_aif_dai_ops,
+	},
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5645 = {
+	.probe = rt5645_probe,
+	.remove = rt5645_remove,
+	.suspend = rt5645_suspend,
+	.resume = rt5645_resume,
+	.set_bias_level = rt5645_set_bias_level,
+	.idle_bias_off = true,
+	.controls = rt5645_snd_controls,
+	.num_controls = ARRAY_SIZE(rt5645_snd_controls),
+	.dapm_widgets = rt5645_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rt5645_dapm_widgets),
+	.dapm_routes = rt5645_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rt5645_dapm_routes),
+};
+
+static const struct regmap_config rt5645_regmap = {
+	.reg_bits = 8,
+	.val_bits = 16,
+
+	.max_register = RT5645_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5645_ranges) *
+					       RT5645_PR_SPACING),
+	.volatile_reg = rt5645_volatile_register,
+	.readable_reg = rt5645_readable_register,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = rt5645_reg,
+	.num_reg_defaults = ARRAY_SIZE(rt5645_reg),
+	.ranges = rt5645_ranges,
+	.num_ranges = ARRAY_SIZE(rt5645_ranges),
+};
+
+static const struct i2c_device_id rt5645_i2c_id[] = {
+	{ "rt5645", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
+
+static int rt5645_i2c_probe(struct i2c_client *i2c,
+		    const struct i2c_device_id *id)
+{
+	struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev);
+	struct rt5645_priv *rt5645;
+	int ret;
+	unsigned int val;
+
+	rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv),
+				GFP_KERNEL);
+	if (rt5645 == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, rt5645);
+
+	if (pdata)
+		rt5645->pdata = *pdata;
+
+	rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
+	if (IS_ERR(rt5645->regmap)) {
+		ret = PTR_ERR(rt5645->regmap);
+		dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	regmap_read(rt5645->regmap, RT5645_VENDOR_ID2, &val);
+	if (val != RT5645_DEVICE_ID) {
+		dev_err(&i2c->dev,
+			"Device with ID register %x is not rt5645\n", val);
+		return -ENODEV;
+	}
+
+	regmap_write(rt5645->regmap, RT5645_RESET, 0);
+
+	ret = regmap_register_patch(rt5645->regmap, init_list,
+				    ARRAY_SIZE(init_list));
+	if (ret != 0)
+		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
+
+	if (rt5645->pdata.in2_diff)
+		regmap_update_bits(rt5645->regmap, RT5645_IN2_CTRL,
+					RT5645_IN_DF2, RT5645_IN_DF2);
+
+	if (rt5645->pdata.dmic_en) {
+		regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+			RT5645_GP2_PIN_MASK, RT5645_GP2_PIN_DMIC1_SCL);
+
+		switch (rt5645->pdata.dmic1_data_pin) {
+		case RT5645_DMIC_DATA_IN2N:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_IN2N);
+			break;
+
+		case RT5645_DMIC_DATA_GPIO5:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO5);
+			regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+				RT5645_GP5_PIN_MASK, RT5645_GP5_PIN_DMIC1_SDA);
+			break;
+
+		case RT5645_DMIC_DATA_GPIO11:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO11);
+			regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+				RT5645_GP11_PIN_MASK,
+				RT5645_GP11_PIN_DMIC1_SDA);
+			break;
+
+		default:
+			break;
+		}
+
+		switch (rt5645->pdata.dmic2_data_pin) {
+		case RT5645_DMIC_DATA_IN2P:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_IN2P);
+			break;
+
+		case RT5645_DMIC_DATA_GPIO6:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO6);
+			regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+				RT5645_GP6_PIN_MASK, RT5645_GP6_PIN_DMIC2_SDA);
+			break;
+
+		case RT5645_DMIC_DATA_GPIO10:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO10);
+			regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+				RT5645_GP10_PIN_MASK,
+				RT5645_GP10_PIN_DMIC2_SDA);
+			break;
+
+		case RT5645_DMIC_DATA_GPIO12:
+			regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
+				RT5645_DMIC_1_DP_MASK, RT5645_DMIC_2_DP_GPIO12);
+			regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+				RT5645_GP12_PIN_MASK,
+				RT5645_GP12_PIN_DMIC2_SDA);
+			break;
+
+		default:
+			break;
+		}
+
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645,
+			rt5645_dai, ARRAY_SIZE(rt5645_dai));
+	if (ret < 0)
+		goto err;
+
+	return 0;
+err:
+	return ret;
+}
+
+static int rt5645_i2c_remove(struct i2c_client *i2c)
+{
+	snd_soc_unregister_codec(&i2c->dev);
+
+	return 0;
+}
+
+struct i2c_driver rt5645_i2c_driver = {
+	.driver = {
+		.name = "rt5645",
+		.owner = THIS_MODULE,
+	},
+	.probe = rt5645_i2c_probe,
+	.remove   = rt5645_i2c_remove,
+	.id_table = rt5645_i2c_id,
+};
+module_i2c_driver(rt5645_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC RT5645 driver");
+MODULE_AUTHOR("Bard Liao <bardliao@realtek.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
new file mode 100644
index 0000000000000..345aa3f5d14fc
--- /dev/null
+++ b/sound/soc/codecs/rt5645.h
@@ -0,0 +1,2188 @@
+/*
+ * rt5645.h  --  RT5645 ALSA SoC audio driver
+ *
+ * Copyright 2013 Realtek Microelectronics
+ * Author: Bard Liao <bardliao@realtek.com>
+ *
+ * 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 __RT5645_H__
+#define __RT5645_H__
+
+#include <sound/rt5645.h>
+
+/* Info */
+#define RT5645_RESET				0x00
+#define RT5645_VENDOR_ID			0xfd
+#define RT5645_VENDOR_ID1			0xfe
+#define RT5645_VENDOR_ID2			0xff
+/*  I/O - Output */
+#define RT5645_SPK_VOL				0x01
+#define RT5645_HP_VOL				0x02
+#define RT5645_LOUT1				0x03
+#define RT5645_LOUT_CTRL			0x05
+/* I/O - Input */
+#define RT5645_IN1_CTRL1			0x0a
+#define RT5645_IN1_CTRL2			0x0b
+#define RT5645_IN1_CTRL3			0x0c
+#define RT5645_IN2_CTRL				0x0d
+#define RT5645_INL1_INR1_VOL			0x0f
+#define RT5645_SPK_FUNC_LIM			0x14
+#define RT5645_ADJ_HPF_CTRL			0x16
+/* I/O - ADC/DAC/DMIC */
+#define RT5645_DAC1_DIG_VOL			0x19
+#define RT5645_DAC2_DIG_VOL			0x1a
+#define RT5645_DAC_CTRL				0x1b
+#define RT5645_STO1_ADC_DIG_VOL			0x1c
+#define RT5645_MONO_ADC_DIG_VOL			0x1d
+#define RT5645_ADC_BST_VOL1			0x1e
+/* Mixer - D-D */
+#define RT5645_ADC_BST_VOL2			0x20
+#define RT5645_STO1_ADC_MIXER			0x27
+#define RT5645_MONO_ADC_MIXER			0x28
+#define RT5645_AD_DA_MIXER			0x29
+#define RT5645_STO_DAC_MIXER			0x2a
+#define RT5645_MONO_DAC_MIXER			0x2b
+#define RT5645_DIG_MIXER			0x2c
+#define RT5645_DIG_INF1_DATA			0x2f
+/* Mixer - PDM */
+#define RT5645_PDM_OUT_CTRL			0x31
+/* Mixer - ADC */
+#define RT5645_REC_L1_MIXER			0x3b
+#define RT5645_REC_L2_MIXER			0x3c
+#define RT5645_REC_R1_MIXER			0x3d
+#define RT5645_REC_R2_MIXER			0x3e
+/* Mixer - DAC */
+#define RT5645_HPMIXL_CTRL			0x3f
+#define RT5645_HPOMIXL_CTRL			0x40
+#define RT5645_HPMIXR_CTRL			0x41
+#define RT5645_HPOMIXR_CTRL			0x42
+#define RT5645_HPO_MIXER			0x45
+#define RT5645_SPK_L_MIXER			0x46
+#define RT5645_SPK_R_MIXER			0x47
+#define RT5645_SPO_MIXER			0x48
+#define RT5645_SPO_CLSD_RATIO			0x4a
+#define RT5645_OUT_L_GAIN1			0x4d
+#define RT5645_OUT_L_GAIN2			0x4e
+#define RT5645_OUT_L1_MIXER			0x4f
+#define RT5645_OUT_R_GAIN1			0x50
+#define RT5645_OUT_R_GAIN2			0x51
+#define RT5645_OUT_R1_MIXER			0x52
+#define RT5645_LOUT_MIXER			0x53
+/* Haptic */
+#define RT5645_HAPTIC_CTRL1			0x56
+#define RT5645_HAPTIC_CTRL2			0x57
+#define RT5645_HAPTIC_CTRL3			0x58
+#define RT5645_HAPTIC_CTRL4			0x59
+#define RT5645_HAPTIC_CTRL5			0x5a
+#define RT5645_HAPTIC_CTRL6			0x5b
+#define RT5645_HAPTIC_CTRL7			0x5c
+#define RT5645_HAPTIC_CTRL8			0x5d
+#define RT5645_HAPTIC_CTRL9			0x5e
+#define RT5645_HAPTIC_CTRL10			0x5f
+/* Power */
+#define RT5645_PWR_DIG1				0x61
+#define RT5645_PWR_DIG2				0x62
+#define RT5645_PWR_ANLG1			0x63
+#define RT5645_PWR_ANLG2			0x64
+#define RT5645_PWR_MIXER			0x65
+#define RT5645_PWR_VOL				0x66
+/* Private Register Control */
+#define RT5645_PRIV_INDEX			0x6a
+#define RT5645_PRIV_DATA			0x6c
+/* Format - ADC/DAC */
+#define RT5645_I2S1_SDP				0x70
+#define RT5645_I2S2_SDP				0x71
+#define RT5645_ADDA_CLK1			0x73
+#define RT5645_ADDA_CLK2			0x74
+#define RT5645_DMIC_CTRL1			0x75
+#define RT5645_DMIC_CTRL2			0x76
+/* Format - TDM Control */
+#define RT5645_TDM_CTRL_1			0x77
+#define RT5645_TDM_CTRL_2			0x78
+#define RT5645_TDM_CTRL_3			0x79
+
+/* Function - Analog */
+#define RT5645_GLB_CLK				0x80
+#define RT5645_PLL_CTRL1			0x81
+#define RT5645_PLL_CTRL2			0x82
+#define RT5645_ASRC_1				0x83
+#define RT5645_ASRC_2				0x84
+#define RT5645_ASRC_3				0x85
+#define RT5645_ASRC_4				0x8a
+#define RT5645_DEPOP_M1				0x8e
+#define RT5645_DEPOP_M2				0x8f
+#define RT5645_DEPOP_M3				0x90
+#define RT5645_CHARGE_PUMP			0x91
+#define RT5645_MICBIAS				0x93
+#define RT5645_A_JD_CTRL1			0x94
+#define RT5645_VAD_CTRL4			0x9d
+#define RT5645_CLSD_OUT_CTRL			0xa0
+/* Function - Digital */
+#define RT5645_ADC_EQ_CTRL1			0xae
+#define RT5645_ADC_EQ_CTRL2			0xaf
+#define RT5645_EQ_CTRL1				0xb0
+#define RT5645_EQ_CTRL2				0xb1
+#define RT5645_ALC_CTRL_1			0xb3
+#define RT5645_ALC_CTRL_2			0xb4
+#define RT5645_ALC_CTRL_3			0xb5
+#define RT5645_ALC_CTRL_4			0xb6
+#define RT5645_ALC_CTRL_5			0xb7
+#define RT5645_JD_CTRL				0xbb
+#define RT5645_IRQ_CTRL1			0xbc
+#define RT5645_IRQ_CTRL2			0xbd
+#define RT5645_IRQ_CTRL3			0xbe
+#define RT5645_INT_IRQ_ST			0xbf
+#define RT5645_GPIO_CTRL1			0xc0
+#define RT5645_GPIO_CTRL2			0xc1
+#define RT5645_GPIO_CTRL3			0xc2
+#define RT5645_BASS_BACK			0xcf
+#define RT5645_MP3_PLUS1			0xd0
+#define RT5645_MP3_PLUS2			0xd1
+#define RT5645_ADJ_HPF1				0xd3
+#define RT5645_ADJ_HPF2				0xd4
+#define RT5645_HP_CALIB_AMP_DET			0xd6
+#define RT5645_SV_ZCD1				0xd9
+#define RT5645_SV_ZCD2				0xda
+#define RT5645_IL_CMD				0xdb
+#define RT5645_IL_CMD2				0xdc
+#define RT5645_IL_CMD3				0xdd
+#define RT5645_DRC1_HL_CTRL1			0xe7
+#define RT5645_DRC2_HL_CTRL1			0xe9
+#define RT5645_MUTI_DRC_CTRL1			0xea
+#define RT5645_ADC_MONO_HP_CTRL1		0xec
+#define RT5645_ADC_MONO_HP_CTRL2		0xed
+#define RT5645_DRC2_CTRL1			0xf0
+#define RT5645_DRC2_CTRL2			0xf1
+#define RT5645_DRC2_CTRL3			0xf2
+#define RT5645_DRC2_CTRL4			0xf3
+#define RT5645_DRC2_CTRL5			0xf4
+#define RT5645_JD_CTRL3				0xf8
+#define RT5645_JD_CTRL4				0xf9
+/* General Control */
+#define RT5645_GEN_CTRL1			0xfa
+#define RT5645_GEN_CTRL2			0xfb
+#define RT5645_GEN_CTRL3			0xfc
+
+
+/* Index of Codec Private Register definition */
+#define RT5645_DIG_VOL				0x00
+#define RT5645_PR_ALC_CTRL_1			0x01
+#define RT5645_PR_ALC_CTRL_2			0x02
+#define RT5645_PR_ALC_CTRL_3			0x03
+#define RT5645_PR_ALC_CTRL_4			0x04
+#define RT5645_PR_ALC_CTRL_5			0x05
+#define RT5645_PR_ALC_CTRL_6			0x06
+#define RT5645_BIAS_CUR1			0x12
+#define RT5645_BIAS_CUR3			0x14
+#define RT5645_CLSD_INT_REG1			0x1c
+#define RT5645_MAMP_INT_REG2			0x37
+#define RT5645_CHOP_DAC_ADC			0x3d
+#define RT5645_MIXER_INT_REG			0x3f
+#define RT5645_3D_SPK				0x63
+#define RT5645_WND_1				0x6c
+#define RT5645_WND_2				0x6d
+#define RT5645_WND_3				0x6e
+#define RT5645_WND_4				0x6f
+#define RT5645_WND_5				0x70
+#define RT5645_WND_8				0x73
+#define RT5645_DIP_SPK_INF			0x75
+#define RT5645_HP_DCC_INT1			0x77
+#define RT5645_EQ_BW_LOP			0xa0
+#define RT5645_EQ_GN_LOP			0xa1
+#define RT5645_EQ_FC_BP1			0xa2
+#define RT5645_EQ_BW_BP1			0xa3
+#define RT5645_EQ_GN_BP1			0xa4
+#define RT5645_EQ_FC_BP2			0xa5
+#define RT5645_EQ_BW_BP2			0xa6
+#define RT5645_EQ_GN_BP2			0xa7
+#define RT5645_EQ_FC_BP3			0xa8
+#define RT5645_EQ_BW_BP3			0xa9
+#define RT5645_EQ_GN_BP3			0xaa
+#define RT5645_EQ_FC_BP4			0xab
+#define RT5645_EQ_BW_BP4			0xac
+#define RT5645_EQ_GN_BP4			0xad
+#define RT5645_EQ_FC_HIP1			0xae
+#define RT5645_EQ_GN_HIP1			0xaf
+#define RT5645_EQ_FC_HIP2			0xb0
+#define RT5645_EQ_BW_HIP2			0xb1
+#define RT5645_EQ_GN_HIP2			0xb2
+#define RT5645_EQ_PRE_VOL			0xb3
+#define RT5645_EQ_PST_VOL			0xb4
+
+
+/* global definition */
+#define RT5645_L_MUTE				(0x1 << 15)
+#define RT5645_L_MUTE_SFT			15
+#define RT5645_VOL_L_MUTE			(0x1 << 14)
+#define RT5645_VOL_L_SFT			14
+#define RT5645_R_MUTE				(0x1 << 7)
+#define RT5645_R_MUTE_SFT			7
+#define RT5645_VOL_R_MUTE			(0x1 << 6)
+#define RT5645_VOL_R_SFT			6
+#define RT5645_L_VOL_MASK			(0x3f << 8)
+#define RT5645_L_VOL_SFT			8
+#define RT5645_R_VOL_MASK			(0x3f)
+#define RT5645_R_VOL_SFT			0
+
+/* IN1 Control 1 (0x0a) */
+#define RT5645_CBJ_BST1_MASK			(0xf << 12)
+#define RT5645_CBJ_BST1_SFT			(12)
+#define RT5645_CBJ_JD_HP_EN			(0x1 << 9)
+#define RT5645_CBJ_JD_MIC_EN			(0x1 << 8)
+#define RT5645_CBJ_JD_MIC_SW_EN			(0x1 << 7)
+#define RT5645_CBJ_MIC_SEL_R			(0x1 << 6)
+#define RT5645_CBJ_MIC_SEL_L			(0x1 << 5)
+#define RT5645_CBJ_MIC_SW			(0x1 << 4)
+#define RT5645_CBJ_BST1_EN			(0x1 << 2)
+
+/* IN1 Control 2 (0x0b) */
+#define RT5645_CBJ_MN_JD			(0x1 << 12)
+#define RT5645_CAPLESS_EN			(0x1 << 11)
+#define RT5645_CBJ_DET_MODE			(0x1 << 7)
+
+/* IN1 Control 3 (0x0c) */
+#define RT5645_CBJ_TIE_G_L			(0x1 << 15)
+#define RT5645_CBJ_TIE_G_R			(0x1 << 14)
+
+/* IN2 Control (0x0d) */
+#define RT5645_BST_MASK1			(0xf<<12)
+#define RT5645_BST_SFT1				12
+#define RT5645_BST_MASK2			(0xf<<8)
+#define RT5645_BST_SFT2				8
+#define RT5645_IN_DF2				(0x1 << 6)
+#define RT5645_IN_SFT2				6
+
+/* INL and INR Volume Control (0x0f) */
+#define RT5645_INL_SEL_MASK			(0x1 << 15)
+#define RT5645_INL_SEL_SFT			15
+#define RT5645_INL_SEL_IN4P			(0x0 << 15)
+#define RT5645_INL_SEL_MONOP			(0x1 << 15)
+#define RT5645_INL_VOL_MASK			(0x1f << 8)
+#define RT5645_INL_VOL_SFT			8
+#define RT5645_INR_SEL_MASK			(0x1 << 7)
+#define RT5645_INR_SEL_SFT			7
+#define RT5645_INR_SEL_IN4N			(0x0 << 7)
+#define RT5645_INR_SEL_MONON			(0x1 << 7)
+#define RT5645_INR_VOL_MASK			(0x1f)
+#define RT5645_INR_VOL_SFT			0
+
+/* DAC1 Digital Volume (0x19) */
+#define RT5645_DAC_L1_VOL_MASK			(0xff << 8)
+#define RT5645_DAC_L1_VOL_SFT			8
+#define RT5645_DAC_R1_VOL_MASK			(0xff)
+#define RT5645_DAC_R1_VOL_SFT			0
+
+/* DAC2 Digital Volume (0x1a) */
+#define RT5645_DAC_L2_VOL_MASK			(0xff << 8)
+#define RT5645_DAC_L2_VOL_SFT			8
+#define RT5645_DAC_R2_VOL_MASK			(0xff)
+#define RT5645_DAC_R2_VOL_SFT			0
+
+/* DAC2 Control (0x1b) */
+#define RT5645_M_DAC_L2_VOL			(0x1 << 13)
+#define RT5645_M_DAC_L2_VOL_SFT			13
+#define RT5645_M_DAC_R2_VOL			(0x1 << 12)
+#define RT5645_M_DAC_R2_VOL_SFT			12
+#define RT5645_DAC2_L_SEL_MASK			(0x7 << 4)
+#define RT5645_DAC2_L_SEL_SFT			4
+#define RT5645_DAC2_R_SEL_MASK			(0x7 << 0)
+#define RT5645_DAC2_R_SEL_SFT			0
+
+/* ADC Digital Volume Control (0x1c) */
+#define RT5645_ADC_L_VOL_MASK			(0x7f << 8)
+#define RT5645_ADC_L_VOL_SFT			8
+#define RT5645_ADC_R_VOL_MASK			(0x7f)
+#define RT5645_ADC_R_VOL_SFT			0
+
+/* Mono ADC Digital Volume Control (0x1d) */
+#define RT5645_MONO_ADC_L_VOL_MASK		(0x7f << 8)
+#define RT5645_MONO_ADC_L_VOL_SFT		8
+#define RT5645_MONO_ADC_R_VOL_MASK		(0x7f)
+#define RT5645_MONO_ADC_R_VOL_SFT		0
+
+/* ADC Boost Volume Control (0x1e) */
+#define RT5645_STO1_ADC_L_BST_MASK		(0x3 << 14)
+#define RT5645_STO1_ADC_L_BST_SFT		14
+#define RT5645_STO1_ADC_R_BST_MASK		(0x3 << 12)
+#define RT5645_STO1_ADC_R_BST_SFT		12
+#define RT5645_STO1_ADC_COMP_MASK		(0x3 << 10)
+#define RT5645_STO1_ADC_COMP_SFT		10
+#define RT5645_STO2_ADC_L_BST_MASK		(0x3 << 8)
+#define RT5645_STO2_ADC_L_BST_SFT		8
+#define RT5645_STO2_ADC_R_BST_MASK		(0x3 << 6)
+#define RT5645_STO2_ADC_R_BST_SFT		6
+#define RT5645_STO2_ADC_COMP_MASK		(0x3 << 4)
+#define RT5645_STO2_ADC_COMP_SFT		4
+
+/* Stereo2 ADC Mixer Control (0x26) */
+#define RT5645_STO2_ADC_SRC_MASK		(0x1 << 15)
+#define RT5645_STO2_ADC_SRC_SFT			15
+
+/* Stereo ADC Mixer Control (0x27) */
+#define RT5645_M_ADC_L1				(0x1 << 14)
+#define RT5645_M_ADC_L1_SFT			14
+#define RT5645_M_ADC_L2				(0x1 << 13)
+#define RT5645_M_ADC_L2_SFT			13
+#define RT5645_ADC_1_SRC_MASK			(0x1 << 12)
+#define RT5645_ADC_1_SRC_SFT			12
+#define RT5645_ADC_1_SRC_ADC			(0x1 << 12)
+#define RT5645_ADC_1_SRC_DACMIX			(0x0 << 12)
+#define RT5645_ADC_2_SRC_MASK			(0x1 << 11)
+#define RT5645_ADC_2_SRC_SFT			11
+#define RT5645_DMIC_SRC_MASK			(0x1 << 8)
+#define RT5645_DMIC_SRC_SFT			8
+#define RT5645_M_ADC_R1				(0x1 << 6)
+#define RT5645_M_ADC_R1_SFT			6
+#define RT5645_M_ADC_R2				(0x1 << 5)
+#define RT5645_M_ADC_R2_SFT			5
+#define RT5645_DMIC3_SRC_MASK			(0x1 << 1)
+#define RT5645_DMIC3_SRC_SFT			0
+
+/* Mono ADC Mixer Control (0x28) */
+#define RT5645_M_MONO_ADC_L1			(0x1 << 14)
+#define RT5645_M_MONO_ADC_L1_SFT		14
+#define RT5645_M_MONO_ADC_L2			(0x1 << 13)
+#define RT5645_M_MONO_ADC_L2_SFT		13
+#define RT5645_MONO_ADC_L1_SRC_MASK		(0x1 << 12)
+#define RT5645_MONO_ADC_L1_SRC_SFT		12
+#define RT5645_MONO_ADC_L1_SRC_DACMIXL		(0x0 << 12)
+#define RT5645_MONO_ADC_L1_SRC_ADCL		(0x1 << 12)
+#define RT5645_MONO_ADC_L2_SRC_MASK		(0x1 << 11)
+#define RT5645_MONO_ADC_L2_SRC_SFT		11
+#define RT5645_MONO_DMIC_L_SRC_MASK		(0x1 << 8)
+#define RT5645_MONO_DMIC_L_SRC_SFT		8
+#define RT5645_M_MONO_ADC_R1			(0x1 << 6)
+#define RT5645_M_MONO_ADC_R1_SFT		6
+#define RT5645_M_MONO_ADC_R2			(0x1 << 5)
+#define RT5645_M_MONO_ADC_R2_SFT		5
+#define RT5645_MONO_ADC_R1_SRC_MASK		(0x1 << 4)
+#define RT5645_MONO_ADC_R1_SRC_SFT		4
+#define RT5645_MONO_ADC_R1_SRC_ADCR		(0x1 << 4)
+#define RT5645_MONO_ADC_R1_SRC_DACMIXR		(0x0 << 4)
+#define RT5645_MONO_ADC_R2_SRC_MASK		(0x1 << 3)
+#define RT5645_MONO_ADC_R2_SRC_SFT		3
+#define RT5645_MONO_DMIC_R_SRC_MASK		(0x3)
+#define RT5645_MONO_DMIC_R_SRC_SFT		0
+
+/* ADC Mixer to DAC Mixer Control (0x29) */
+#define RT5645_M_ADCMIX_L			(0x1 << 15)
+#define RT5645_M_ADCMIX_L_SFT			15
+#define RT5645_M_DAC1_L				(0x1 << 14)
+#define RT5645_M_DAC1_L_SFT			14
+#define RT5645_DAC1_R_SEL_MASK			(0x3 << 10)
+#define RT5645_DAC1_R_SEL_SFT			10
+#define RT5645_DAC1_R_SEL_IF1			(0x0 << 10)
+#define RT5645_DAC1_R_SEL_IF2			(0x1 << 10)
+#define RT5645_DAC1_R_SEL_IF3			(0x2 << 10)
+#define RT5645_DAC1_R_SEL_IF4			(0x3 << 10)
+#define RT5645_DAC1_L_SEL_MASK			(0x3 << 8)
+#define RT5645_DAC1_L_SEL_SFT			8
+#define RT5645_DAC1_L_SEL_IF1			(0x0 << 8)
+#define RT5645_DAC1_L_SEL_IF2			(0x1 << 8)
+#define RT5645_DAC1_L_SEL_IF3			(0x2 << 8)
+#define RT5645_DAC1_L_SEL_IF4			(0x3 << 8)
+#define RT5645_M_ADCMIX_R			(0x1 << 7)
+#define RT5645_M_ADCMIX_R_SFT			7
+#define RT5645_M_DAC1_R				(0x1 << 6)
+#define RT5645_M_DAC1_R_SFT			6
+
+/* Stereo DAC Mixer Control (0x2a) */
+#define RT5645_M_DAC_L1				(0x1 << 14)
+#define RT5645_M_DAC_L1_SFT			14
+#define RT5645_DAC_L1_STO_L_VOL_MASK		(0x1 << 13)
+#define RT5645_DAC_L1_STO_L_VOL_SFT		13
+#define RT5645_M_DAC_L2				(0x1 << 12)
+#define RT5645_M_DAC_L2_SFT			12
+#define RT5645_DAC_L2_STO_L_VOL_MASK		(0x1 << 11)
+#define RT5645_DAC_L2_STO_L_VOL_SFT		11
+#define RT5645_M_ANC_DAC_L			(0x1 << 10)
+#define RT5645_M_ANC_DAC_L_SFT			10
+#define RT5645_M_DAC_R1_STO_L			(0x1 << 9)
+#define RT5645_M_DAC_R1_STO_L_SFT			9
+#define RT5645_DAC_R1_STO_L_VOL_MASK		(0x1 << 8)
+#define RT5645_DAC_R1_STO_L_VOL_SFT		8
+#define RT5645_M_DAC_R1				(0x1 << 6)
+#define RT5645_M_DAC_R1_SFT			6
+#define RT5645_DAC_R1_STO_R_VOL_MASK		(0x1 << 5)
+#define RT5645_DAC_R1_STO_R_VOL_SFT		5
+#define RT5645_M_DAC_R2				(0x1 << 4)
+#define RT5645_M_DAC_R2_SFT			4
+#define RT5645_DAC_R2_STO_R_VOL_MASK		(0x1 << 3)
+#define RT5645_DAC_R2_STO_R_VOL_SFT		3
+#define RT5645_M_ANC_DAC_R			(0x1 << 2)
+#define RT5645_M_ANC_DAC_R_SFT			2
+#define RT5645_M_DAC_L1_STO_R			(0x1 << 1)
+#define RT5645_M_DAC_L1_STO_R_SFT			1
+#define RT5645_DAC_L1_STO_R_VOL_MASK		(0x1)
+#define RT5645_DAC_L1_STO_R_VOL_SFT		0
+
+/* Mono DAC Mixer Control (0x2b) */
+#define RT5645_M_DAC_L1_MONO_L			(0x1 << 14)
+#define RT5645_M_DAC_L1_MONO_L_SFT		14
+#define RT5645_DAC_L1_MONO_L_VOL_MASK		(0x1 << 13)
+#define RT5645_DAC_L1_MONO_L_VOL_SFT		13
+#define RT5645_M_DAC_L2_MONO_L			(0x1 << 12)
+#define RT5645_M_DAC_L2_MONO_L_SFT		12
+#define RT5645_DAC_L2_MONO_L_VOL_MASK		(0x1 << 11)
+#define RT5645_DAC_L2_MONO_L_VOL_SFT		11
+#define RT5645_M_DAC_R2_MONO_L			(0x1 << 10)
+#define RT5645_M_DAC_R2_MONO_L_SFT		10
+#define RT5645_DAC_R2_MONO_L_VOL_MASK		(0x1 << 9)
+#define RT5645_DAC_R2_MONO_L_VOL_SFT		9
+#define RT5645_M_DAC_R1_MONO_R			(0x1 << 6)
+#define RT5645_M_DAC_R1_MONO_R_SFT		6
+#define RT5645_DAC_R1_MONO_R_VOL_MASK		(0x1 << 5)
+#define RT5645_DAC_R1_MONO_R_VOL_SFT		5
+#define RT5645_M_DAC_R2_MONO_R			(0x1 << 4)
+#define RT5645_M_DAC_R2_MONO_R_SFT		4
+#define RT5645_DAC_R2_MONO_R_VOL_MASK		(0x1 << 3)
+#define RT5645_DAC_R2_MONO_R_VOL_SFT		3
+#define RT5645_M_DAC_L2_MONO_R			(0x1 << 2)
+#define RT5645_M_DAC_L2_MONO_R_SFT		2
+#define RT5645_DAC_L2_MONO_R_VOL_MASK		(0x1 << 1)
+#define RT5645_DAC_L2_MONO_R_VOL_SFT		1
+
+/* Digital Mixer Control (0x2c) */
+#define RT5645_M_STO_L_DAC_L			(0x1 << 15)
+#define RT5645_M_STO_L_DAC_L_SFT		15
+#define RT5645_STO_L_DAC_L_VOL_MASK		(0x1 << 14)
+#define RT5645_STO_L_DAC_L_VOL_SFT		14
+#define RT5645_M_DAC_L2_DAC_L			(0x1 << 13)
+#define RT5645_M_DAC_L2_DAC_L_SFT		13
+#define RT5645_DAC_L2_DAC_L_VOL_MASK		(0x1 << 12)
+#define RT5645_DAC_L2_DAC_L_VOL_SFT		12
+#define RT5645_M_STO_R_DAC_R			(0x1 << 11)
+#define RT5645_M_STO_R_DAC_R_SFT		11
+#define RT5645_STO_R_DAC_R_VOL_MASK		(0x1 << 10)
+#define RT5645_STO_R_DAC_R_VOL_SFT		10
+#define RT5645_M_DAC_R2_DAC_R			(0x1 << 9)
+#define RT5645_M_DAC_R2_DAC_R_SFT		9
+#define RT5645_DAC_R2_DAC_R_VOL_MASK		(0x1 << 8)
+#define RT5645_DAC_R2_DAC_R_VOL_SFT		8
+#define RT5645_M_DAC_R2_DAC_L			(0x1 << 7)
+#define RT5645_M_DAC_R2_DAC_L_SFT		7
+#define RT5645_DAC_R2_DAC_L_VOL_MASK		(0x1 << 6)
+#define RT5645_DAC_R2_DAC_L_VOL_SFT		6
+#define RT5645_M_DAC_L2_DAC_R			(0x1 << 5)
+#define RT5645_M_DAC_L2_DAC_R_SFT		5
+#define RT5645_DAC_L2_DAC_R_VOL_MASK		(0x1 << 4)
+#define RT5645_DAC_L2_DAC_R_VOL_SFT		4
+
+/* Digital Interface Data Control (0x2f) */
+#define RT5645_IF1_ADC2_IN_SEL			(0x1 << 15)
+#define RT5645_IF1_ADC2_IN_SFT			15
+#define RT5645_IF2_ADC_IN_MASK			(0x7 << 12)
+#define RT5645_IF2_ADC_IN_SFT			12
+#define RT5645_IF2_DAC_SEL_MASK			(0x3 << 10)
+#define RT5645_IF2_DAC_SEL_SFT			10
+#define RT5645_IF2_ADC_SEL_MASK			(0x3 << 8)
+#define RT5645_IF2_ADC_SEL_SFT			8
+#define RT5645_IF3_DAC_SEL_MASK			(0x3 << 6)
+#define RT5645_IF3_DAC_SEL_SFT			6
+#define RT5645_IF3_ADC_SEL_MASK			(0x3 << 4)
+#define RT5645_IF3_ADC_SEL_SFT			4
+#define RT5645_IF3_ADC_IN_MASK			(0x7)
+#define RT5645_IF3_ADC_IN_SFT			0
+
+/* PDM Output Control (0x31) */
+#define RT5645_PDM1_L_MASK			(0x1 << 15)
+#define RT5645_PDM1_L_SFT			15
+#define RT5645_M_PDM1_L				(0x1 << 14)
+#define RT5645_M_PDM1_L_SFT			14
+#define RT5645_PDM1_R_MASK			(0x1 << 13)
+#define RT5645_PDM1_R_SFT			13
+#define RT5645_M_PDM1_R				(0x1 << 12)
+#define RT5645_M_PDM1_R_SFT			12
+#define RT5645_PDM2_L_MASK			(0x1 << 11)
+#define RT5645_PDM2_L_SFT			11
+#define RT5645_M_PDM2_L				(0x1 << 10)
+#define RT5645_M_PDM2_L_SFT			10
+#define RT5645_PDM2_R_MASK			(0x1 << 9)
+#define RT5645_PDM2_R_SFT			9
+#define RT5645_M_PDM2_R				(0x1 << 8)
+#define RT5645_M_PDM2_R_SFT			8
+#define RT5645_PDM2_BUSY			(0x1 << 7)
+#define RT5645_PDM1_BUSY			(0x1 << 6)
+#define RT5645_PDM_PATTERN			(0x1 << 5)
+#define RT5645_PDM_GAIN				(0x1 << 4)
+#define RT5645_PDM_DIV_MASK			(0x3)
+
+/* REC Left Mixer Control 1 (0x3b) */
+#define RT5645_G_HP_L_RM_L_MASK			(0x7 << 13)
+#define RT5645_G_HP_L_RM_L_SFT			13
+#define RT5645_G_IN_L_RM_L_MASK			(0x7 << 10)
+#define RT5645_G_IN_L_RM_L_SFT			10
+#define RT5645_G_BST4_RM_L_MASK			(0x7 << 7)
+#define RT5645_G_BST4_RM_L_SFT			7
+#define RT5645_G_BST3_RM_L_MASK			(0x7 << 4)
+#define RT5645_G_BST3_RM_L_SFT			4
+#define RT5645_G_BST2_RM_L_MASK			(0x7 << 1)
+#define RT5645_G_BST2_RM_L_SFT			1
+
+/* REC Left Mixer Control 2 (0x3c) */
+#define RT5645_G_BST1_RM_L_MASK			(0x7 << 13)
+#define RT5645_G_BST1_RM_L_SFT			13
+#define RT5645_G_OM_L_RM_L_MASK			(0x7 << 10)
+#define RT5645_G_OM_L_RM_L_SFT			10
+#define RT5645_M_MM_L_RM_L			(0x1 << 6)
+#define RT5645_M_MM_L_RM_L_SFT			6
+#define RT5645_M_IN_L_RM_L			(0x1 << 5)
+#define RT5645_M_IN_L_RM_L_SFT			5
+#define RT5645_M_HP_L_RM_L			(0x1 << 4)
+#define RT5645_M_HP_L_RM_L_SFT			4
+#define RT5645_M_BST3_RM_L			(0x1 << 3)
+#define RT5645_M_BST3_RM_L_SFT			3
+#define RT5645_M_BST2_RM_L			(0x1 << 2)
+#define RT5645_M_BST2_RM_L_SFT			2
+#define RT5645_M_BST1_RM_L			(0x1 << 1)
+#define RT5645_M_BST1_RM_L_SFT			1
+#define RT5645_M_OM_L_RM_L			(0x1)
+#define RT5645_M_OM_L_RM_L_SFT			0
+
+/* REC Right Mixer Control 1 (0x3d) */
+#define RT5645_G_HP_R_RM_R_MASK			(0x7 << 13)
+#define RT5645_G_HP_R_RM_R_SFT			13
+#define RT5645_G_IN_R_RM_R_MASK			(0x7 << 10)
+#define RT5645_G_IN_R_RM_R_SFT			10
+#define RT5645_G_BST4_RM_R_MASK			(0x7 << 7)
+#define RT5645_G_BST4_RM_R_SFT			7
+#define RT5645_G_BST3_RM_R_MASK			(0x7 << 4)
+#define RT5645_G_BST3_RM_R_SFT			4
+#define RT5645_G_BST2_RM_R_MASK			(0x7 << 1)
+#define RT5645_G_BST2_RM_R_SFT			1
+
+/* REC Right Mixer Control 2 (0x3e) */
+#define RT5645_G_BST1_RM_R_MASK			(0x7 << 13)
+#define RT5645_G_BST1_RM_R_SFT			13
+#define RT5645_G_OM_R_RM_R_MASK			(0x7 << 10)
+#define RT5645_G_OM_R_RM_R_SFT			10
+#define RT5645_M_MM_R_RM_R			(0x1 << 6)
+#define RT5645_M_MM_R_RM_R_SFT			6
+#define RT5645_M_IN_R_RM_R			(0x1 << 5)
+#define RT5645_M_IN_R_RM_R_SFT			5
+#define RT5645_M_HP_R_RM_R			(0x1 << 4)
+#define RT5645_M_HP_R_RM_R_SFT			4
+#define RT5645_M_BST3_RM_R			(0x1 << 3)
+#define RT5645_M_BST3_RM_R_SFT			3
+#define RT5645_M_BST2_RM_R			(0x1 << 2)
+#define RT5645_M_BST2_RM_R_SFT			2
+#define RT5645_M_BST1_RM_R			(0x1 << 1)
+#define RT5645_M_BST1_RM_R_SFT			1
+#define RT5645_M_OM_R_RM_R			(0x1)
+#define RT5645_M_OM_R_RM_R_SFT			0
+
+/* HPOMIX Control (0x40) (0x42) */
+#define RT5645_M_BST1_HV			(0x1 << 4)
+#define RT5645_M_BST1_HV_SFT			4
+#define RT5645_M_BST2_HV			(0x1 << 4)
+#define RT5645_M_BST2_HV_SFT			4
+#define RT5645_M_BST3_HV			(0x1 << 3)
+#define RT5645_M_BST3_HV_SFT			3
+#define RT5645_M_IN_HV				(0x1 << 2)
+#define RT5645_M_IN_HV_SFT			2
+#define RT5645_M_DAC2_HV			(0x1 << 1)
+#define RT5645_M_DAC2_HV_SFT			1
+#define RT5645_M_DAC1_HV			(0x1 << 0)
+#define RT5645_M_DAC1_HV_SFT			0
+
+/* HPMIX Control (0x45) */
+#define RT5645_M_DAC1_HM			(0x1 << 14)
+#define RT5645_M_DAC1_HM_SFT			14
+#define RT5645_M_HPVOL_HM			(0x1 << 13)
+#define RT5645_M_HPVOL_HM_SFT			13
+
+/* SPK Left Mixer Control (0x46) */
+#define RT5645_G_RM_L_SM_L_MASK			(0x3 << 14)
+#define RT5645_G_RM_L_SM_L_SFT			14
+#define RT5645_G_IN_L_SM_L_MASK			(0x3 << 12)
+#define RT5645_G_IN_L_SM_L_SFT			12
+#define RT5645_G_DAC_L1_SM_L_MASK		(0x3 << 10)
+#define RT5645_G_DAC_L1_SM_L_SFT		10
+#define RT5645_G_DAC_L2_SM_L_MASK		(0x3 << 8)
+#define RT5645_G_DAC_L2_SM_L_SFT		8
+#define RT5645_G_OM_L_SM_L_MASK			(0x3 << 6)
+#define RT5645_G_OM_L_SM_L_SFT			6
+#define RT5645_M_BST1_L_SM_L			(0x1 << 5)
+#define RT5645_M_BST1_L_SM_L_SFT		5
+#define RT5645_M_IN_L_SM_L			(0x1 << 3)
+#define RT5645_M_IN_L_SM_L_SFT			3
+#define RT5645_M_DAC_L1_SM_L			(0x1 << 1)
+#define RT5645_M_DAC_L1_SM_L_SFT		1
+#define RT5645_M_DAC_L2_SM_L			(0x1 << 2)
+#define RT5645_M_DAC_L2_SM_L_SFT		2
+#define RT5645_M_BST3_L_SM_L			(0x1 << 4)
+#define RT5645_M_BST3_L_SM_L_SFT		4
+
+/* SPK Right Mixer Control (0x47) */
+#define RT5645_G_RM_R_SM_R_MASK			(0x3 << 14)
+#define RT5645_G_RM_R_SM_R_SFT			14
+#define RT5645_G_IN_R_SM_R_MASK			(0x3 << 12)
+#define RT5645_G_IN_R_SM_R_SFT			12
+#define RT5645_G_DAC_R1_SM_R_MASK		(0x3 << 10)
+#define RT5645_G_DAC_R1_SM_R_SFT		10
+#define RT5645_G_DAC_R2_SM_R_MASK		(0x3 << 8)
+#define RT5645_G_DAC_R2_SM_R_SFT		8
+#define RT5645_G_OM_R_SM_R_MASK			(0x3 << 6)
+#define RT5645_G_OM_R_SM_R_SFT			6
+#define RT5645_M_BST2_R_SM_R			(0x1 << 5)
+#define RT5645_M_BST2_R_SM_R_SFT		5
+#define RT5645_M_IN_R_SM_R			(0x1 << 3)
+#define RT5645_M_IN_R_SM_R_SFT			3
+#define RT5645_M_DAC_R1_SM_R			(0x1 << 1)
+#define RT5645_M_DAC_R1_SM_R_SFT		1
+#define RT5645_M_DAC_R2_SM_R			(0x1 << 2)
+#define RT5645_M_DAC_R2_SM_R_SFT		2
+#define RT5645_M_BST3_R_SM_R			(0x1 << 4)
+#define RT5645_M_BST3_R_SM_R_SFT		4
+
+/* SPOLMIX Control (0x48) */
+#define RT5645_M_DAC_L1_SPM_L			(0x1 << 15)
+#define RT5645_M_DAC_L1_SPM_L_SFT		15
+#define RT5645_M_DAC_R1_SPM_L			(0x1 << 14)
+#define RT5645_M_DAC_R1_SPM_L_SFT		14
+#define RT5645_M_SV_L_SPM_L			(0x1 << 13)
+#define RT5645_M_SV_L_SPM_L_SFT			13
+#define RT5645_M_SV_R_SPM_L			(0x1 << 12)
+#define RT5645_M_SV_R_SPM_L_SFT			12
+#define RT5645_M_BST3_SPM_L			(0x1 << 11)
+#define RT5645_M_BST3_SPM_L_SFT			11
+#define RT5645_M_DAC_R1_SPM_R			(0x1 << 2)
+#define RT5645_M_DAC_R1_SPM_R_SFT		2
+#define RT5645_M_BST3_SPM_R			(0x1 << 1)
+#define RT5645_M_BST3_SPM_R_SFT			1
+#define RT5645_M_SV_R_SPM_R			(0x1 << 0)
+#define RT5645_M_SV_R_SPM_R_SFT			0
+
+/* Mono Output Mixer Control (0x4c) */
+#define RT5645_M_OV_L_MM			(0x1 << 9)
+#define RT5645_M_OV_L_MM_SFT			9
+#define RT5645_M_DAC_L2_MA			(0x1 << 8)
+#define RT5645_M_DAC_L2_MA_SFT			8
+#define RT5645_G_MONOMIX_MASK			(0x1 << 10)
+#define RT5645_G_MONOMIX_SFT			10
+#define RT5645_M_BST2_MM			(0x1 << 4)
+#define RT5645_M_BST2_MM_SFT			4
+#define RT5645_M_DAC_R1_MM			(0x1 << 3)
+#define RT5645_M_DAC_R1_MM_SFT			3
+#define RT5645_M_DAC_R2_MM			(0x1 << 2)
+#define RT5645_M_DAC_R2_MM_SFT			2
+#define RT5645_M_DAC_L2_MM			(0x1 << 1)
+#define RT5645_M_DAC_L2_MM_SFT			1
+#define RT5645_M_BST3_MM			(0x1 << 0)
+#define RT5645_M_BST3_MM_SFT			0
+
+/* Output Left Mixer Control 1 (0x4d) */
+#define RT5645_G_BST3_OM_L_MASK			(0x7 << 13)
+#define RT5645_G_BST3_OM_L_SFT			13
+#define RT5645_G_BST2_OM_L_MASK			(0x7 << 10)
+#define RT5645_G_BST2_OM_L_SFT			10
+#define RT5645_G_BST1_OM_L_MASK			(0x7 << 7)
+#define RT5645_G_BST1_OM_L_SFT			7
+#define RT5645_G_IN_L_OM_L_MASK			(0x7 << 4)
+#define RT5645_G_IN_L_OM_L_SFT			4
+#define RT5645_G_RM_L_OM_L_MASK			(0x7 << 1)
+#define RT5645_G_RM_L_OM_L_SFT			1
+
+/* Output Left Mixer Control 2 (0x4e) */
+#define RT5645_G_DAC_R2_OM_L_MASK		(0x7 << 13)
+#define RT5645_G_DAC_R2_OM_L_SFT		13
+#define RT5645_G_DAC_L2_OM_L_MASK		(0x7 << 10)
+#define RT5645_G_DAC_L2_OM_L_SFT		10
+#define RT5645_G_DAC_L1_OM_L_MASK		(0x7 << 7)
+#define RT5645_G_DAC_L1_OM_L_SFT		7
+
+/* Output Left Mixer Control 3 (0x4f) */
+#define RT5645_M_BST3_OM_L			(0x1 << 4)
+#define RT5645_M_BST3_OM_L_SFT			4
+#define RT5645_M_BST1_OM_L			(0x1 << 3)
+#define RT5645_M_BST1_OM_L_SFT			3
+#define RT5645_M_IN_L_OM_L			(0x1 << 2)
+#define RT5645_M_IN_L_OM_L_SFT			2
+#define RT5645_M_DAC_L2_OM_L			(0x1 << 1)
+#define RT5645_M_DAC_L2_OM_L_SFT		1
+#define RT5645_M_DAC_L1_OM_L			(0x1)
+#define RT5645_M_DAC_L1_OM_L_SFT		0
+
+/* Output Right Mixer Control 1 (0x50) */
+#define RT5645_G_BST4_OM_R_MASK			(0x7 << 13)
+#define RT5645_G_BST4_OM_R_SFT			13
+#define RT5645_G_BST2_OM_R_MASK			(0x7 << 10)
+#define RT5645_G_BST2_OM_R_SFT			10
+#define RT5645_G_BST1_OM_R_MASK			(0x7 << 7)
+#define RT5645_G_BST1_OM_R_SFT			7
+#define RT5645_G_IN_R_OM_R_MASK			(0x7 << 4)
+#define RT5645_G_IN_R_OM_R_SFT			4
+#define RT5645_G_RM_R_OM_R_MASK			(0x7 << 1)
+#define RT5645_G_RM_R_OM_R_SFT			1
+
+/* Output Right Mixer Control 2 (0x51) */
+#define RT5645_G_DAC_L2_OM_R_MASK		(0x7 << 13)
+#define RT5645_G_DAC_L2_OM_R_SFT		13
+#define RT5645_G_DAC_R2_OM_R_MASK		(0x7 << 10)
+#define RT5645_G_DAC_R2_OM_R_SFT		10
+#define RT5645_G_DAC_R1_OM_R_MASK		(0x7 << 7)
+#define RT5645_G_DAC_R1_OM_R_SFT		7
+
+/* Output Right Mixer Control 3 (0x52) */
+#define RT5645_M_BST3_OM_R			(0x1 << 4)
+#define RT5645_M_BST3_OM_R_SFT			4
+#define RT5645_M_BST2_OM_R			(0x1 << 3)
+#define RT5645_M_BST2_OM_R_SFT			3
+#define RT5645_M_IN_R_OM_R			(0x1 << 2)
+#define RT5645_M_IN_R_OM_R_SFT			2
+#define RT5645_M_DAC_R2_OM_R			(0x1 << 1)
+#define RT5645_M_DAC_R2_OM_R_SFT		1
+#define RT5645_M_DAC_R1_OM_R			(0x1)
+#define RT5645_M_DAC_R1_OM_R_SFT		0
+
+/* LOUT Mixer Control (0x53) */
+#define RT5645_M_DAC_L1_LM			(0x1 << 15)
+#define RT5645_M_DAC_L1_LM_SFT			15
+#define RT5645_M_DAC_R1_LM			(0x1 << 14)
+#define RT5645_M_DAC_R1_LM_SFT			14
+#define RT5645_M_OV_L_LM			(0x1 << 13)
+#define RT5645_M_OV_L_LM_SFT			13
+#define RT5645_M_OV_R_LM			(0x1 << 12)
+#define RT5645_M_OV_R_LM_SFT			12
+#define RT5645_G_LOUTMIX_MASK			(0x1 << 11)
+#define RT5645_G_LOUTMIX_SFT			11
+
+/* Power Management for Digital 1 (0x61) */
+#define RT5645_PWR_I2S1				(0x1 << 15)
+#define RT5645_PWR_I2S1_BIT			15
+#define RT5645_PWR_I2S2				(0x1 << 14)
+#define RT5645_PWR_I2S2_BIT			14
+#define RT5645_PWR_I2S3				(0x1 << 13)
+#define RT5645_PWR_I2S3_BIT			13
+#define RT5645_PWR_DAC_L1			(0x1 << 12)
+#define RT5645_PWR_DAC_L1_BIT			12
+#define RT5645_PWR_DAC_R1			(0x1 << 11)
+#define RT5645_PWR_DAC_R1_BIT			11
+#define RT5645_PWR_CLS_D_R			(0x1 << 9)
+#define RT5645_PWR_CLS_D_R_BIT			9
+#define RT5645_PWR_CLS_D_L			(0x1 << 8)
+#define RT5645_PWR_CLS_D_L_BIT			8
+#define RT5645_PWR_ADC_R			(0x1 << 1)
+#define RT5645_PWR_ADC_R_BIT			1
+#define RT5645_PWR_DAC_L2			(0x1 << 7)
+#define RT5645_PWR_DAC_L2_BIT			7
+#define RT5645_PWR_DAC_R2			(0x1 << 6)
+#define RT5645_PWR_DAC_R2_BIT			6
+#define RT5645_PWR_ADC_L			(0x1 << 2)
+#define RT5645_PWR_ADC_L_BIT			2
+#define RT5645_PWR_ADC_R			(0x1 << 1)
+#define RT5645_PWR_ADC_R_BIT			1
+#define RT5645_PWR_CLS_D			(0x1)
+#define RT5645_PWR_CLS_D_BIT			0
+
+/* Power Management for Digital 2 (0x62) */
+#define RT5645_PWR_ADC_S1F			(0x1 << 15)
+#define RT5645_PWR_ADC_S1F_BIT			15
+#define RT5645_PWR_ADC_MF_L			(0x1 << 14)
+#define RT5645_PWR_ADC_MF_L_BIT			14
+#define RT5645_PWR_ADC_MF_R			(0x1 << 13)
+#define RT5645_PWR_ADC_MF_R_BIT			13
+#define RT5645_PWR_I2S_DSP			(0x1 << 12)
+#define RT5645_PWR_I2S_DSP_BIT			12
+#define RT5645_PWR_DAC_S1F			(0x1 << 11)
+#define RT5645_PWR_DAC_S1F_BIT			11
+#define RT5645_PWR_DAC_MF_L			(0x1 << 10)
+#define RT5645_PWR_DAC_MF_L_BIT			10
+#define RT5645_PWR_DAC_MF_R			(0x1 << 9)
+#define RT5645_PWR_DAC_MF_R_BIT			9
+#define RT5645_PWR_ADC_S2F			(0x1 << 8)
+#define RT5645_PWR_ADC_S2F_BIT			8
+#define RT5645_PWR_PDM1				(0x1 << 7)
+#define RT5645_PWR_PDM1_BIT			7
+#define RT5645_PWR_PDM2				(0x1 << 6)
+#define RT5645_PWR_PDM2_BIT			6
+#define RT5645_PWR_IPTV				(0x1 << 1)
+#define RT5645_PWR_IPTV_BIT			1
+#define RT5645_PWR_PAD				(0x1)
+#define RT5645_PWR_PAD_BIT			0
+
+/* Power Management for Analog 1 (0x63) */
+#define RT5645_PWR_VREF1			(0x1 << 15)
+#define RT5645_PWR_VREF1_BIT			15
+#define RT5645_PWR_FV1				(0x1 << 14)
+#define RT5645_PWR_FV1_BIT			14
+#define RT5645_PWR_MB				(0x1 << 13)
+#define RT5645_PWR_MB_BIT			13
+#define RT5645_PWR_LM				(0x1 << 12)
+#define RT5645_PWR_LM_BIT			12
+#define RT5645_PWR_BG				(0x1 << 11)
+#define RT5645_PWR_BG_BIT			11
+#define RT5645_PWR_MA				(0x1 << 10)
+#define RT5645_PWR_MA_BIT			10
+#define RT5645_PWR_HP_L				(0x1 << 7)
+#define RT5645_PWR_HP_L_BIT			7
+#define RT5645_PWR_HP_R				(0x1 << 6)
+#define RT5645_PWR_HP_R_BIT			6
+#define RT5645_PWR_HA				(0x1 << 5)
+#define RT5645_PWR_HA_BIT			5
+#define RT5645_PWR_VREF2			(0x1 << 4)
+#define RT5645_PWR_VREF2_BIT			4
+#define RT5645_PWR_FV2				(0x1 << 3)
+#define RT5645_PWR_FV2_BIT			3
+#define RT5645_LDO_SEL_MASK			(0x3)
+#define RT5645_LDO_SEL_SFT			0
+
+/* Power Management for Analog 2 (0x64) */
+#define RT5645_PWR_BST1				(0x1 << 15)
+#define RT5645_PWR_BST1_BIT			15
+#define RT5645_PWR_BST2				(0x1 << 14)
+#define RT5645_PWR_BST2_BIT			14
+#define RT5645_PWR_BST3				(0x1 << 13)
+#define RT5645_PWR_BST3_BIT			13
+#define RT5645_PWR_BST4				(0x1 << 12)
+#define RT5645_PWR_BST4_BIT			12
+#define RT5645_PWR_MB1				(0x1 << 11)
+#define RT5645_PWR_MB1_BIT			11
+#define RT5645_PWR_MB2				(0x1 << 10)
+#define RT5645_PWR_MB2_BIT			10
+#define RT5645_PWR_PLL				(0x1 << 9)
+#define RT5645_PWR_PLL_BIT			9
+#define RT5645_PWR_BST2_P			(0x1 << 5)
+#define RT5645_PWR_BST2_P_BIT			5
+#define RT5645_PWR_BST3_P			(0x1 << 4)
+#define RT5645_PWR_BST3_P_BIT			4
+#define RT5645_PWR_BST4_P			(0x1 << 3)
+#define RT5645_PWR_BST4_P_BIT			3
+#define RT5645_PWR_JD1				(0x1 << 2)
+#define RT5645_PWR_JD1_BIT			2
+#define RT5645_PWR_JD				(0x1 << 1)
+#define RT5645_PWR_JD_BIT			1
+
+/* Power Management for Mixer (0x65) */
+#define RT5645_PWR_OM_L				(0x1 << 15)
+#define RT5645_PWR_OM_L_BIT			15
+#define RT5645_PWR_OM_R				(0x1 << 14)
+#define RT5645_PWR_OM_R_BIT			14
+#define RT5645_PWR_SM_L				(0x1 << 13)
+#define RT5645_PWR_SM_L_BIT			13
+#define RT5645_PWR_SM_R				(0x1 << 12)
+#define RT5645_PWR_SM_R_BIT			12
+#define RT5645_PWR_RM_L				(0x1 << 11)
+#define RT5645_PWR_RM_L_BIT			11
+#define RT5645_PWR_RM_R				(0x1 << 10)
+#define RT5645_PWR_RM_R_BIT			10
+#define RT5645_PWR_MM				(0x1 << 8)
+#define RT5645_PWR_MM_BIT			8
+#define RT5645_PWR_HM_L				(0x1 << 7)
+#define RT5645_PWR_HM_L_BIT			7
+#define RT5645_PWR_HM_R				(0x1 << 6)
+#define RT5645_PWR_HM_R_BIT			6
+#define RT5645_PWR_LDO2				(0x1 << 1)
+#define RT5645_PWR_LDO2_BIT			1
+
+/* Power Management for Volume (0x66) */
+#define RT5645_PWR_SV_L				(0x1 << 15)
+#define RT5645_PWR_SV_L_BIT			15
+#define RT5645_PWR_SV_R				(0x1 << 14)
+#define RT5645_PWR_SV_R_BIT			14
+#define RT5645_PWR_HV_L				(0x1 << 11)
+#define RT5645_PWR_HV_L_BIT			11
+#define RT5645_PWR_HV_R				(0x1 << 10)
+#define RT5645_PWR_HV_R_BIT			10
+#define RT5645_PWR_IN_L				(0x1 << 9)
+#define RT5645_PWR_IN_L_BIT			9
+#define RT5645_PWR_IN_R				(0x1 << 8)
+#define RT5645_PWR_IN_R_BIT			8
+#define RT5645_PWR_MIC_DET			(0x1 << 5)
+#define RT5645_PWR_MIC_DET_BIT			5
+
+/* I2S1/2 Audio Serial Data Port Control (0x70 0x71) */
+#define RT5645_I2S_MS_MASK			(0x1 << 15)
+#define RT5645_I2S_MS_SFT			15
+#define RT5645_I2S_MS_M				(0x0 << 15)
+#define RT5645_I2S_MS_S				(0x1 << 15)
+#define RT5645_I2S_O_CP_MASK			(0x3 << 10)
+#define RT5645_I2S_O_CP_SFT			10
+#define RT5645_I2S_O_CP_OFF			(0x0 << 10)
+#define RT5645_I2S_O_CP_U_LAW			(0x1 << 10)
+#define RT5645_I2S_O_CP_A_LAW			(0x2 << 10)
+#define RT5645_I2S_I_CP_MASK			(0x3 << 8)
+#define RT5645_I2S_I_CP_SFT			8
+#define RT5645_I2S_I_CP_OFF			(0x0 << 8)
+#define RT5645_I2S_I_CP_U_LAW			(0x1 << 8)
+#define RT5645_I2S_I_CP_A_LAW			(0x2 << 8)
+#define RT5645_I2S_BP_MASK			(0x1 << 7)
+#define RT5645_I2S_BP_SFT			7
+#define RT5645_I2S_BP_NOR			(0x0 << 7)
+#define RT5645_I2S_BP_INV			(0x1 << 7)
+#define RT5645_I2S_DL_MASK			(0x3 << 2)
+#define RT5645_I2S_DL_SFT			2
+#define RT5645_I2S_DL_16			(0x0 << 2)
+#define RT5645_I2S_DL_20			(0x1 << 2)
+#define RT5645_I2S_DL_24			(0x2 << 2)
+#define RT5645_I2S_DL_8				(0x3 << 2)
+#define RT5645_I2S_DF_MASK			(0x3)
+#define RT5645_I2S_DF_SFT			0
+#define RT5645_I2S_DF_I2S			(0x0)
+#define RT5645_I2S_DF_LEFT			(0x1)
+#define RT5645_I2S_DF_PCM_A			(0x2)
+#define RT5645_I2S_DF_PCM_B			(0x3)
+
+/* I2S2 Audio Serial Data Port Control (0x71) */
+#define RT5645_I2S2_SDI_MASK			(0x1 << 6)
+#define RT5645_I2S2_SDI_SFT			6
+#define RT5645_I2S2_SDI_I2S1			(0x0 << 6)
+#define RT5645_I2S2_SDI_I2S2			(0x1 << 6)
+
+/* ADC/DAC Clock Control 1 (0x73) */
+#define RT5645_I2S_BCLK_MS1_MASK		(0x1 << 15)
+#define RT5645_I2S_BCLK_MS1_SFT			15
+#define RT5645_I2S_BCLK_MS1_32			(0x0 << 15)
+#define RT5645_I2S_BCLK_MS1_64			(0x1 << 15)
+#define RT5645_I2S_PD1_MASK			(0x7 << 12)
+#define RT5645_I2S_PD1_SFT			12
+#define RT5645_I2S_PD1_1			(0x0 << 12)
+#define RT5645_I2S_PD1_2			(0x1 << 12)
+#define RT5645_I2S_PD1_3			(0x2 << 12)
+#define RT5645_I2S_PD1_4			(0x3 << 12)
+#define RT5645_I2S_PD1_6			(0x4 << 12)
+#define RT5645_I2S_PD1_8			(0x5 << 12)
+#define RT5645_I2S_PD1_12			(0x6 << 12)
+#define RT5645_I2S_PD1_16			(0x7 << 12)
+#define RT5645_I2S_BCLK_MS2_MASK		(0x1 << 11)
+#define RT5645_I2S_BCLK_MS2_SFT			11
+#define RT5645_I2S_BCLK_MS2_32			(0x0 << 11)
+#define RT5645_I2S_BCLK_MS2_64			(0x1 << 11)
+#define RT5645_I2S_PD2_MASK			(0x7 << 8)
+#define RT5645_I2S_PD2_SFT			8
+#define RT5645_I2S_PD2_1			(0x0 << 8)
+#define RT5645_I2S_PD2_2			(0x1 << 8)
+#define RT5645_I2S_PD2_3			(0x2 << 8)
+#define RT5645_I2S_PD2_4			(0x3 << 8)
+#define RT5645_I2S_PD2_6			(0x4 << 8)
+#define RT5645_I2S_PD2_8			(0x5 << 8)
+#define RT5645_I2S_PD2_12			(0x6 << 8)
+#define RT5645_I2S_PD2_16			(0x7 << 8)
+#define RT5645_I2S_BCLK_MS3_MASK		(0x1 << 7)
+#define RT5645_I2S_BCLK_MS3_SFT			7
+#define RT5645_I2S_BCLK_MS3_32			(0x0 << 7)
+#define RT5645_I2S_BCLK_MS3_64			(0x1 << 7)
+#define RT5645_I2S_PD3_MASK			(0x7 << 4)
+#define RT5645_I2S_PD3_SFT			4
+#define RT5645_I2S_PD3_1			(0x0 << 4)
+#define RT5645_I2S_PD3_2			(0x1 << 4)
+#define RT5645_I2S_PD3_3			(0x2 << 4)
+#define RT5645_I2S_PD3_4			(0x3 << 4)
+#define RT5645_I2S_PD3_6			(0x4 << 4)
+#define RT5645_I2S_PD3_8			(0x5 << 4)
+#define RT5645_I2S_PD3_12			(0x6 << 4)
+#define RT5645_I2S_PD3_16			(0x7 << 4)
+#define RT5645_DAC_OSR_MASK			(0x3 << 2)
+#define RT5645_DAC_OSR_SFT			2
+#define RT5645_DAC_OSR_128			(0x0 << 2)
+#define RT5645_DAC_OSR_64			(0x1 << 2)
+#define RT5645_DAC_OSR_32			(0x2 << 2)
+#define RT5645_DAC_OSR_16			(0x3 << 2)
+#define RT5645_ADC_OSR_MASK			(0x3)
+#define RT5645_ADC_OSR_SFT			0
+#define RT5645_ADC_OSR_128			(0x0)
+#define RT5645_ADC_OSR_64			(0x1)
+#define RT5645_ADC_OSR_32			(0x2)
+#define RT5645_ADC_OSR_16			(0x3)
+
+/* ADC/DAC Clock Control 2 (0x74) */
+#define RT5645_DAC_L_OSR_MASK			(0x3 << 14)
+#define RT5645_DAC_L_OSR_SFT			14
+#define RT5645_DAC_L_OSR_128			(0x0 << 14)
+#define RT5645_DAC_L_OSR_64			(0x1 << 14)
+#define RT5645_DAC_L_OSR_32			(0x2 << 14)
+#define RT5645_DAC_L_OSR_16			(0x3 << 14)
+#define RT5645_ADC_R_OSR_MASK			(0x3 << 12)
+#define RT5645_ADC_R_OSR_SFT			12
+#define RT5645_ADC_R_OSR_128			(0x0 << 12)
+#define RT5645_ADC_R_OSR_64			(0x1 << 12)
+#define RT5645_ADC_R_OSR_32			(0x2 << 12)
+#define RT5645_ADC_R_OSR_16			(0x3 << 12)
+#define RT5645_DAHPF_EN				(0x1 << 11)
+#define RT5645_DAHPF_EN_SFT			11
+#define RT5645_ADHPF_EN				(0x1 << 10)
+#define RT5645_ADHPF_EN_SFT			10
+
+/* Digital Microphone Control (0x75) */
+#define RT5645_DMIC_1_EN_MASK			(0x1 << 15)
+#define RT5645_DMIC_1_EN_SFT			15
+#define RT5645_DMIC_1_DIS			(0x0 << 15)
+#define RT5645_DMIC_1_EN			(0x1 << 15)
+#define RT5645_DMIC_2_EN_MASK			(0x1 << 14)
+#define RT5645_DMIC_2_EN_SFT			14
+#define RT5645_DMIC_2_DIS			(0x0 << 14)
+#define RT5645_DMIC_2_EN			(0x1 << 14)
+#define RT5645_DMIC_1L_LH_MASK			(0x1 << 13)
+#define RT5645_DMIC_1L_LH_SFT			13
+#define RT5645_DMIC_1L_LH_FALLING		(0x0 << 13)
+#define RT5645_DMIC_1L_LH_RISING		(0x1 << 13)
+#define RT5645_DMIC_1R_LH_MASK			(0x1 << 12)
+#define RT5645_DMIC_1R_LH_SFT			12
+#define RT5645_DMIC_1R_LH_FALLING		(0x0 << 12)
+#define RT5645_DMIC_1R_LH_RISING		(0x1 << 12)
+#define RT5645_DMIC_2_DP_MASK			(0x3 << 10)
+#define RT5645_DMIC_2_DP_SFT			10
+#define RT5645_DMIC_2_DP_GPIO6			(0x0 << 10)
+#define RT5645_DMIC_2_DP_GPIO10			(0x1 << 10)
+#define RT5645_DMIC_2_DP_GPIO12			(0x2 << 10)
+#define RT5645_DMIC_2_DP_IN2P			(0x3 << 10)
+#define RT5645_DMIC_2L_LH_MASK			(0x1 << 9)
+#define RT5645_DMIC_2L_LH_SFT			9
+#define RT5645_DMIC_2L_LH_FALLING		(0x0 << 9)
+#define RT5645_DMIC_2L_LH_RISING		(0x1 << 9)
+#define RT5645_DMIC_2R_LH_MASK			(0x1 << 8)
+#define RT5645_DMIC_2R_LH_SFT			8
+#define RT5645_DMIC_2R_LH_FALLING		(0x0 << 8)
+#define RT5645_DMIC_2R_LH_RISING		(0x1 << 8)
+#define RT5645_DMIC_CLK_MASK			(0x7 << 5)
+#define RT5645_DMIC_CLK_SFT			5
+#define RT5645_DMIC_3_EN_MASK			(0x1 << 4)
+#define RT5645_DMIC_3_EN_SFT			4
+#define RT5645_DMIC_3_DIS			(0x0 << 4)
+#define RT5645_DMIC_3_EN			(0x1 << 4)
+#define RT5645_DMIC_1_DP_MASK			(0x3 << 0)
+#define RT5645_DMIC_1_DP_SFT			0
+#define RT5645_DMIC_1_DP_GPIO5			(0x0 << 0)
+#define RT5645_DMIC_1_DP_IN2N			(0x1 << 0)
+#define RT5645_DMIC_1_DP_GPIO11			(0x2 << 0)
+
+/* TDM Control 1 (0x77) */
+#define RT5645_IF1_ADC_IN_MASK			(0x3 << 8)
+#define RT5645_IF1_ADC_IN_SFT			8
+
+/* Global Clock Control (0x80) */
+#define RT5645_SCLK_SRC_MASK			(0x3 << 14)
+#define RT5645_SCLK_SRC_SFT			14
+#define RT5645_SCLK_SRC_MCLK			(0x0 << 14)
+#define RT5645_SCLK_SRC_PLL1			(0x1 << 14)
+#define RT5645_SCLK_SRC_RCCLK			(0x2 << 14) /* 15MHz */
+#define RT5645_PLL1_SRC_MASK			(0x3 << 12)
+#define RT5645_PLL1_SRC_SFT			12
+#define RT5645_PLL1_SRC_MCLK			(0x0 << 12)
+#define RT5645_PLL1_SRC_BCLK1			(0x1 << 12)
+#define RT5645_PLL1_SRC_BCLK2			(0x2 << 12)
+#define RT5645_PLL1_SRC_BCLK3			(0x3 << 12)
+#define RT5645_PLL1_PD_MASK			(0x1 << 3)
+#define RT5645_PLL1_PD_SFT			3
+#define RT5645_PLL1_PD_1			(0x0 << 3)
+#define RT5645_PLL1_PD_2			(0x1 << 3)
+
+#define RT5645_PLL_INP_MAX			40000000
+#define RT5645_PLL_INP_MIN			256000
+/* PLL M/N/K Code Control 1 (0x81) */
+#define RT5645_PLL_N_MAX			0x1ff
+#define RT5645_PLL_N_MASK			(RT5645_PLL_N_MAX << 7)
+#define RT5645_PLL_N_SFT			7
+#define RT5645_PLL_K_MAX			0x1f
+#define RT5645_PLL_K_MASK			(RT5645_PLL_K_MAX)
+#define RT5645_PLL_K_SFT			0
+
+/* PLL M/N/K Code Control 2 (0x82) */
+#define RT5645_PLL_M_MAX			0xf
+#define RT5645_PLL_M_MASK			(RT5645_PLL_M_MAX << 12)
+#define RT5645_PLL_M_SFT			12
+#define RT5645_PLL_M_BP				(0x1 << 11)
+#define RT5645_PLL_M_BP_SFT			11
+
+/* ASRC Control 1 (0x83) */
+#define RT5645_STO_T_MASK			(0x1 << 15)
+#define RT5645_STO_T_SFT			15
+#define RT5645_STO_T_SCLK			(0x0 << 15)
+#define RT5645_STO_T_LRCK1			(0x1 << 15)
+#define RT5645_M1_T_MASK			(0x1 << 14)
+#define RT5645_M1_T_SFT				14
+#define RT5645_M1_T_I2S2			(0x0 << 14)
+#define RT5645_M1_T_I2S2_D3			(0x1 << 14)
+#define RT5645_I2S2_F_MASK			(0x1 << 12)
+#define RT5645_I2S2_F_SFT			12
+#define RT5645_I2S2_F_I2S2_D2			(0x0 << 12)
+#define RT5645_I2S2_F_I2S1_TCLK			(0x1 << 12)
+#define RT5645_DMIC_1_M_MASK			(0x1 << 9)
+#define RT5645_DMIC_1_M_SFT			9
+#define RT5645_DMIC_1_M_NOR			(0x0 << 9)
+#define RT5645_DMIC_1_M_ASYN			(0x1 << 9)
+#define RT5645_DMIC_2_M_MASK			(0x1 << 8)
+#define RT5645_DMIC_2_M_SFT			8
+#define RT5645_DMIC_2_M_NOR			(0x0 << 8)
+#define RT5645_DMIC_2_M_ASYN			(0x1 << 8)
+
+/* ASRC Control 2 (0x84) */
+#define RT5645_MDA_L_M_MASK			(0x1 << 15)
+#define RT5645_MDA_L_M_SFT			15
+#define RT5645_MDA_L_M_NOR			(0x0 << 15)
+#define RT5645_MDA_L_M_ASYN			(0x1 << 15)
+#define RT5645_MDA_R_M_MASK			(0x1 << 14)
+#define RT5645_MDA_R_M_SFT			14
+#define RT5645_MDA_R_M_NOR			(0x0 << 14)
+#define RT5645_MDA_R_M_ASYN			(0x1 << 14)
+#define RT5645_MAD_L_M_MASK			(0x1 << 13)
+#define RT5645_MAD_L_M_SFT			13
+#define RT5645_MAD_L_M_NOR			(0x0 << 13)
+#define RT5645_MAD_L_M_ASYN			(0x1 << 13)
+#define RT5645_MAD_R_M_MASK			(0x1 << 12)
+#define RT5645_MAD_R_M_SFT			12
+#define RT5645_MAD_R_M_NOR			(0x0 << 12)
+#define RT5645_MAD_R_M_ASYN			(0x1 << 12)
+#define RT5645_ADC_M_MASK			(0x1 << 11)
+#define RT5645_ADC_M_SFT			11
+#define RT5645_ADC_M_NOR			(0x0 << 11)
+#define RT5645_ADC_M_ASYN			(0x1 << 11)
+#define RT5645_STO_DAC_M_MASK			(0x1 << 5)
+#define RT5645_STO_DAC_M_SFT			5
+#define RT5645_STO_DAC_M_NOR			(0x0 << 5)
+#define RT5645_STO_DAC_M_ASYN			(0x1 << 5)
+#define RT5645_I2S1_R_D_MASK			(0x1 << 4)
+#define RT5645_I2S1_R_D_SFT			4
+#define RT5645_I2S1_R_D_DIS			(0x0 << 4)
+#define RT5645_I2S1_R_D_EN			(0x1 << 4)
+#define RT5645_I2S2_R_D_MASK			(0x1 << 3)
+#define RT5645_I2S2_R_D_SFT			3
+#define RT5645_I2S2_R_D_DIS			(0x0 << 3)
+#define RT5645_I2S2_R_D_EN			(0x1 << 3)
+#define RT5645_PRE_SCLK_MASK			(0x3)
+#define RT5645_PRE_SCLK_SFT			0
+#define RT5645_PRE_SCLK_512			(0x0)
+#define RT5645_PRE_SCLK_1024			(0x1)
+#define RT5645_PRE_SCLK_2048			(0x2)
+
+/* ASRC Control 3 (0x85) */
+#define RT5645_I2S1_RATE_MASK			(0xf << 12)
+#define RT5645_I2S1_RATE_SFT			12
+#define RT5645_I2S2_RATE_MASK			(0xf << 8)
+#define RT5645_I2S2_RATE_SFT			8
+
+/* ASRC Control 4 (0x89) */
+#define RT5645_I2S1_PD_MASK			(0x7 << 12)
+#define RT5645_I2S1_PD_SFT			12
+#define RT5645_I2S2_PD_MASK			(0x7 << 8)
+#define RT5645_I2S2_PD_SFT			8
+
+/* HPOUT Over Current Detection (0x8b) */
+#define RT5645_HP_OVCD_MASK			(0x1 << 10)
+#define RT5645_HP_OVCD_SFT			10
+#define RT5645_HP_OVCD_DIS			(0x0 << 10)
+#define RT5645_HP_OVCD_EN			(0x1 << 10)
+#define RT5645_HP_OC_TH_MASK			(0x3 << 8)
+#define RT5645_HP_OC_TH_SFT			8
+#define RT5645_HP_OC_TH_90			(0x0 << 8)
+#define RT5645_HP_OC_TH_105			(0x1 << 8)
+#define RT5645_HP_OC_TH_120			(0x2 << 8)
+#define RT5645_HP_OC_TH_135			(0x3 << 8)
+
+/* Class D Over Current Control (0x8c) */
+#define RT5645_CLSD_OC_MASK			(0x1 << 9)
+#define RT5645_CLSD_OC_SFT			9
+#define RT5645_CLSD_OC_PU			(0x0 << 9)
+#define RT5645_CLSD_OC_PD			(0x1 << 9)
+#define RT5645_AUTO_PD_MASK			(0x1 << 8)
+#define RT5645_AUTO_PD_SFT			8
+#define RT5645_AUTO_PD_DIS			(0x0 << 8)
+#define RT5645_AUTO_PD_EN			(0x1 << 8)
+#define RT5645_CLSD_OC_TH_MASK			(0x3f)
+#define RT5645_CLSD_OC_TH_SFT			0
+
+/* Class D Output Control (0x8d) */
+#define RT5645_CLSD_RATIO_MASK			(0xf << 12)
+#define RT5645_CLSD_RATIO_SFT			12
+#define RT5645_CLSD_OM_MASK			(0x1 << 11)
+#define RT5645_CLSD_OM_SFT			11
+#define RT5645_CLSD_OM_MONO			(0x0 << 11)
+#define RT5645_CLSD_OM_STO			(0x1 << 11)
+#define RT5645_CLSD_SCH_MASK			(0x1 << 10)
+#define RT5645_CLSD_SCH_SFT			10
+#define RT5645_CLSD_SCH_L			(0x0 << 10)
+#define RT5645_CLSD_SCH_S			(0x1 << 10)
+
+/* Depop Mode Control 1 (0x8e) */
+#define RT5645_SMT_TRIG_MASK			(0x1 << 15)
+#define RT5645_SMT_TRIG_SFT			15
+#define RT5645_SMT_TRIG_DIS			(0x0 << 15)
+#define RT5645_SMT_TRIG_EN			(0x1 << 15)
+#define RT5645_HP_L_SMT_MASK			(0x1 << 9)
+#define RT5645_HP_L_SMT_SFT			9
+#define RT5645_HP_L_SMT_DIS			(0x0 << 9)
+#define RT5645_HP_L_SMT_EN			(0x1 << 9)
+#define RT5645_HP_R_SMT_MASK			(0x1 << 8)
+#define RT5645_HP_R_SMT_SFT			8
+#define RT5645_HP_R_SMT_DIS			(0x0 << 8)
+#define RT5645_HP_R_SMT_EN			(0x1 << 8)
+#define RT5645_HP_CD_PD_MASK			(0x1 << 7)
+#define RT5645_HP_CD_PD_SFT			7
+#define RT5645_HP_CD_PD_DIS			(0x0 << 7)
+#define RT5645_HP_CD_PD_EN			(0x1 << 7)
+#define RT5645_RSTN_MASK			(0x1 << 6)
+#define RT5645_RSTN_SFT				6
+#define RT5645_RSTN_DIS				(0x0 << 6)
+#define RT5645_RSTN_EN				(0x1 << 6)
+#define RT5645_RSTP_MASK			(0x1 << 5)
+#define RT5645_RSTP_SFT				5
+#define RT5645_RSTP_DIS				(0x0 << 5)
+#define RT5645_RSTP_EN				(0x1 << 5)
+#define RT5645_HP_CO_MASK			(0x1 << 4)
+#define RT5645_HP_CO_SFT			4
+#define RT5645_HP_CO_DIS			(0x0 << 4)
+#define RT5645_HP_CO_EN				(0x1 << 4)
+#define RT5645_HP_CP_MASK			(0x1 << 3)
+#define RT5645_HP_CP_SFT			3
+#define RT5645_HP_CP_PD				(0x0 << 3)
+#define RT5645_HP_CP_PU				(0x1 << 3)
+#define RT5645_HP_SG_MASK			(0x1 << 2)
+#define RT5645_HP_SG_SFT			2
+#define RT5645_HP_SG_DIS			(0x0 << 2)
+#define RT5645_HP_SG_EN				(0x1 << 2)
+#define RT5645_HP_DP_MASK			(0x1 << 1)
+#define RT5645_HP_DP_SFT			1
+#define RT5645_HP_DP_PD				(0x0 << 1)
+#define RT5645_HP_DP_PU				(0x1 << 1)
+#define RT5645_HP_CB_MASK			(0x1)
+#define RT5645_HP_CB_SFT			0
+#define RT5645_HP_CB_PD				(0x0)
+#define RT5645_HP_CB_PU				(0x1)
+
+/* Depop Mode Control 2 (0x8f) */
+#define RT5645_DEPOP_MASK			(0x1 << 13)
+#define RT5645_DEPOP_SFT			13
+#define RT5645_DEPOP_AUTO			(0x0 << 13)
+#define RT5645_DEPOP_MAN			(0x1 << 13)
+#define RT5645_RAMP_MASK			(0x1 << 12)
+#define RT5645_RAMP_SFT				12
+#define RT5645_RAMP_DIS				(0x0 << 12)
+#define RT5645_RAMP_EN				(0x1 << 12)
+#define RT5645_BPS_MASK				(0x1 << 11)
+#define RT5645_BPS_SFT				11
+#define RT5645_BPS_DIS				(0x0 << 11)
+#define RT5645_BPS_EN				(0x1 << 11)
+#define RT5645_FAST_UPDN_MASK			(0x1 << 10)
+#define RT5645_FAST_UPDN_SFT			10
+#define RT5645_FAST_UPDN_DIS			(0x0 << 10)
+#define RT5645_FAST_UPDN_EN			(0x1 << 10)
+#define RT5645_MRES_MASK			(0x3 << 8)
+#define RT5645_MRES_SFT				8
+#define RT5645_MRES_15MO			(0x0 << 8)
+#define RT5645_MRES_25MO			(0x1 << 8)
+#define RT5645_MRES_35MO			(0x2 << 8)
+#define RT5645_MRES_45MO			(0x3 << 8)
+#define RT5645_VLO_MASK				(0x1 << 7)
+#define RT5645_VLO_SFT				7
+#define RT5645_VLO_3V				(0x0 << 7)
+#define RT5645_VLO_32V				(0x1 << 7)
+#define RT5645_DIG_DP_MASK			(0x1 << 6)
+#define RT5645_DIG_DP_SFT			6
+#define RT5645_DIG_DP_DIS			(0x0 << 6)
+#define RT5645_DIG_DP_EN			(0x1 << 6)
+#define RT5645_DP_TH_MASK			(0x3 << 4)
+#define RT5645_DP_TH_SFT			4
+
+/* Depop Mode Control 3 (0x90) */
+#define RT5645_CP_SYS_MASK			(0x7 << 12)
+#define RT5645_CP_SYS_SFT			12
+#define RT5645_CP_FQ1_MASK			(0x7 << 8)
+#define RT5645_CP_FQ1_SFT			8
+#define RT5645_CP_FQ2_MASK			(0x7 << 4)
+#define RT5645_CP_FQ2_SFT			4
+#define RT5645_CP_FQ3_MASK			(0x7)
+#define RT5645_CP_FQ3_SFT			0
+#define RT5645_CP_FQ_1_5_KHZ			0
+#define RT5645_CP_FQ_3_KHZ			1
+#define RT5645_CP_FQ_6_KHZ			2
+#define RT5645_CP_FQ_12_KHZ			3
+#define RT5645_CP_FQ_24_KHZ			4
+#define RT5645_CP_FQ_48_KHZ			5
+#define RT5645_CP_FQ_96_KHZ			6
+#define RT5645_CP_FQ_192_KHZ			7
+
+/* PV detection and SPK gain control (0x92) */
+#define RT5645_PVDD_DET_MASK			(0x1 << 15)
+#define RT5645_PVDD_DET_SFT			15
+#define RT5645_PVDD_DET_DIS			(0x0 << 15)
+#define RT5645_PVDD_DET_EN			(0x1 << 15)
+#define RT5645_SPK_AG_MASK			(0x1 << 14)
+#define RT5645_SPK_AG_SFT			14
+#define RT5645_SPK_AG_DIS			(0x0 << 14)
+#define RT5645_SPK_AG_EN			(0x1 << 14)
+
+/* Micbias Control (0x93) */
+#define RT5645_MIC1_BS_MASK			(0x1 << 15)
+#define RT5645_MIC1_BS_SFT			15
+#define RT5645_MIC1_BS_9AV			(0x0 << 15)
+#define RT5645_MIC1_BS_75AV			(0x1 << 15)
+#define RT5645_MIC2_BS_MASK			(0x1 << 14)
+#define RT5645_MIC2_BS_SFT			14
+#define RT5645_MIC2_BS_9AV			(0x0 << 14)
+#define RT5645_MIC2_BS_75AV			(0x1 << 14)
+#define RT5645_MIC1_CLK_MASK			(0x1 << 13)
+#define RT5645_MIC1_CLK_SFT			13
+#define RT5645_MIC1_CLK_DIS			(0x0 << 13)
+#define RT5645_MIC1_CLK_EN			(0x1 << 13)
+#define RT5645_MIC2_CLK_MASK			(0x1 << 12)
+#define RT5645_MIC2_CLK_SFT			12
+#define RT5645_MIC2_CLK_DIS			(0x0 << 12)
+#define RT5645_MIC2_CLK_EN			(0x1 << 12)
+#define RT5645_MIC1_OVCD_MASK			(0x1 << 11)
+#define RT5645_MIC1_OVCD_SFT			11
+#define RT5645_MIC1_OVCD_DIS			(0x0 << 11)
+#define RT5645_MIC1_OVCD_EN			(0x1 << 11)
+#define RT5645_MIC1_OVTH_MASK			(0x3 << 9)
+#define RT5645_MIC1_OVTH_SFT			9
+#define RT5645_MIC1_OVTH_600UA			(0x0 << 9)
+#define RT5645_MIC1_OVTH_1500UA			(0x1 << 9)
+#define RT5645_MIC1_OVTH_2000UA			(0x2 << 9)
+#define RT5645_MIC2_OVCD_MASK			(0x1 << 8)
+#define RT5645_MIC2_OVCD_SFT			8
+#define RT5645_MIC2_OVCD_DIS			(0x0 << 8)
+#define RT5645_MIC2_OVCD_EN			(0x1 << 8)
+#define RT5645_MIC2_OVTH_MASK			(0x3 << 6)
+#define RT5645_MIC2_OVTH_SFT			6
+#define RT5645_MIC2_OVTH_600UA			(0x0 << 6)
+#define RT5645_MIC2_OVTH_1500UA			(0x1 << 6)
+#define RT5645_MIC2_OVTH_2000UA			(0x2 << 6)
+#define RT5645_PWR_MB_MASK			(0x1 << 5)
+#define RT5645_PWR_MB_SFT			5
+#define RT5645_PWR_MB_PD			(0x0 << 5)
+#define RT5645_PWR_MB_PU			(0x1 << 5)
+#define RT5645_PWR_CLK25M_MASK			(0x1 << 4)
+#define RT5645_PWR_CLK25M_SFT			4
+#define RT5645_PWR_CLK25M_PD			(0x0 << 4)
+#define RT5645_PWR_CLK25M_PU			(0x1 << 4)
+
+/* VAD Control 4 (0x9d) */
+#define RT5645_VAD_SEL_MASK			(0x3 << 8)
+#define RT5645_VAD_SEL_SFT			8
+
+/* EQ Control 1 (0xb0) */
+#define RT5645_EQ_SRC_MASK			(0x1 << 15)
+#define RT5645_EQ_SRC_SFT			15
+#define RT5645_EQ_SRC_DAC			(0x0 << 15)
+#define RT5645_EQ_SRC_ADC			(0x1 << 15)
+#define RT5645_EQ_UPD				(0x1 << 14)
+#define RT5645_EQ_UPD_BIT			14
+#define RT5645_EQ_CD_MASK			(0x1 << 13)
+#define RT5645_EQ_CD_SFT			13
+#define RT5645_EQ_CD_DIS			(0x0 << 13)
+#define RT5645_EQ_CD_EN				(0x1 << 13)
+#define RT5645_EQ_DITH_MASK			(0x3 << 8)
+#define RT5645_EQ_DITH_SFT			8
+#define RT5645_EQ_DITH_NOR			(0x0 << 8)
+#define RT5645_EQ_DITH_LSB			(0x1 << 8)
+#define RT5645_EQ_DITH_LSB_1			(0x2 << 8)
+#define RT5645_EQ_DITH_LSB_2			(0x3 << 8)
+
+/* EQ Control 2 (0xb1) */
+#define RT5645_EQ_HPF1_M_MASK			(0x1 << 8)
+#define RT5645_EQ_HPF1_M_SFT			8
+#define RT5645_EQ_HPF1_M_HI			(0x0 << 8)
+#define RT5645_EQ_HPF1_M_1ST			(0x1 << 8)
+#define RT5645_EQ_LPF1_M_MASK			(0x1 << 7)
+#define RT5645_EQ_LPF1_M_SFT			7
+#define RT5645_EQ_LPF1_M_LO			(0x0 << 7)
+#define RT5645_EQ_LPF1_M_1ST			(0x1 << 7)
+#define RT5645_EQ_HPF2_MASK			(0x1 << 6)
+#define RT5645_EQ_HPF2_SFT			6
+#define RT5645_EQ_HPF2_DIS			(0x0 << 6)
+#define RT5645_EQ_HPF2_EN			(0x1 << 6)
+#define RT5645_EQ_HPF1_MASK			(0x1 << 5)
+#define RT5645_EQ_HPF1_SFT			5
+#define RT5645_EQ_HPF1_DIS			(0x0 << 5)
+#define RT5645_EQ_HPF1_EN			(0x1 << 5)
+#define RT5645_EQ_BPF4_MASK			(0x1 << 4)
+#define RT5645_EQ_BPF4_SFT			4
+#define RT5645_EQ_BPF4_DIS			(0x0 << 4)
+#define RT5645_EQ_BPF4_EN			(0x1 << 4)
+#define RT5645_EQ_BPF3_MASK			(0x1 << 3)
+#define RT5645_EQ_BPF3_SFT			3
+#define RT5645_EQ_BPF3_DIS			(0x0 << 3)
+#define RT5645_EQ_BPF3_EN			(0x1 << 3)
+#define RT5645_EQ_BPF2_MASK			(0x1 << 2)
+#define RT5645_EQ_BPF2_SFT			2
+#define RT5645_EQ_BPF2_DIS			(0x0 << 2)
+#define RT5645_EQ_BPF2_EN			(0x1 << 2)
+#define RT5645_EQ_BPF1_MASK			(0x1 << 1)
+#define RT5645_EQ_BPF1_SFT			1
+#define RT5645_EQ_BPF1_DIS			(0x0 << 1)
+#define RT5645_EQ_BPF1_EN			(0x1 << 1)
+#define RT5645_EQ_LPF_MASK			(0x1)
+#define RT5645_EQ_LPF_SFT			0
+#define RT5645_EQ_LPF_DIS			(0x0)
+#define RT5645_EQ_LPF_EN			(0x1)
+#define RT5645_EQ_CTRL_MASK			(0x7f)
+
+/* Memory Test (0xb2) */
+#define RT5645_MT_MASK				(0x1 << 15)
+#define RT5645_MT_SFT				15
+#define RT5645_MT_DIS				(0x0 << 15)
+#define RT5645_MT_EN				(0x1 << 15)
+
+/* DRC/AGC Control 1 (0xb4) */
+#define RT5645_DRC_AGC_P_MASK			(0x1 << 15)
+#define RT5645_DRC_AGC_P_SFT			15
+#define RT5645_DRC_AGC_P_DAC			(0x0 << 15)
+#define RT5645_DRC_AGC_P_ADC			(0x1 << 15)
+#define RT5645_DRC_AGC_MASK			(0x1 << 14)
+#define RT5645_DRC_AGC_SFT			14
+#define RT5645_DRC_AGC_DIS			(0x0 << 14)
+#define RT5645_DRC_AGC_EN			(0x1 << 14)
+#define RT5645_DRC_AGC_UPD			(0x1 << 13)
+#define RT5645_DRC_AGC_UPD_BIT			13
+#define RT5645_DRC_AGC_AR_MASK			(0x1f << 8)
+#define RT5645_DRC_AGC_AR_SFT			8
+#define RT5645_DRC_AGC_R_MASK			(0x7 << 5)
+#define RT5645_DRC_AGC_R_SFT			5
+#define RT5645_DRC_AGC_R_48K			(0x1 << 5)
+#define RT5645_DRC_AGC_R_96K			(0x2 << 5)
+#define RT5645_DRC_AGC_R_192K			(0x3 << 5)
+#define RT5645_DRC_AGC_R_441K			(0x5 << 5)
+#define RT5645_DRC_AGC_R_882K			(0x6 << 5)
+#define RT5645_DRC_AGC_R_1764K			(0x7 << 5)
+#define RT5645_DRC_AGC_RC_MASK			(0x1f)
+#define RT5645_DRC_AGC_RC_SFT			0
+
+/* DRC/AGC Control 2 (0xb5) */
+#define RT5645_DRC_AGC_POB_MASK			(0x3f << 8)
+#define RT5645_DRC_AGC_POB_SFT			8
+#define RT5645_DRC_AGC_CP_MASK			(0x1 << 7)
+#define RT5645_DRC_AGC_CP_SFT			7
+#define RT5645_DRC_AGC_CP_DIS			(0x0 << 7)
+#define RT5645_DRC_AGC_CP_EN			(0x1 << 7)
+#define RT5645_DRC_AGC_CPR_MASK			(0x3 << 5)
+#define RT5645_DRC_AGC_CPR_SFT			5
+#define RT5645_DRC_AGC_CPR_1_1			(0x0 << 5)
+#define RT5645_DRC_AGC_CPR_1_2			(0x1 << 5)
+#define RT5645_DRC_AGC_CPR_1_3			(0x2 << 5)
+#define RT5645_DRC_AGC_CPR_1_4			(0x3 << 5)
+#define RT5645_DRC_AGC_PRB_MASK			(0x1f)
+#define RT5645_DRC_AGC_PRB_SFT			0
+
+/* DRC/AGC Control 3 (0xb6) */
+#define RT5645_DRC_AGC_NGB_MASK			(0xf << 12)
+#define RT5645_DRC_AGC_NGB_SFT			12
+#define RT5645_DRC_AGC_TAR_MASK			(0x1f << 7)
+#define RT5645_DRC_AGC_TAR_SFT			7
+#define RT5645_DRC_AGC_NG_MASK			(0x1 << 6)
+#define RT5645_DRC_AGC_NG_SFT			6
+#define RT5645_DRC_AGC_NG_DIS			(0x0 << 6)
+#define RT5645_DRC_AGC_NG_EN			(0x1 << 6)
+#define RT5645_DRC_AGC_NGH_MASK			(0x1 << 5)
+#define RT5645_DRC_AGC_NGH_SFT			5
+#define RT5645_DRC_AGC_NGH_DIS			(0x0 << 5)
+#define RT5645_DRC_AGC_NGH_EN			(0x1 << 5)
+#define RT5645_DRC_AGC_NGT_MASK			(0x1f)
+#define RT5645_DRC_AGC_NGT_SFT			0
+
+/* ANC Control 1 (0xb8) */
+#define RT5645_ANC_M_MASK			(0x1 << 15)
+#define RT5645_ANC_M_SFT			15
+#define RT5645_ANC_M_NOR			(0x0 << 15)
+#define RT5645_ANC_M_REV			(0x1 << 15)
+#define RT5645_ANC_MASK				(0x1 << 14)
+#define RT5645_ANC_SFT				14
+#define RT5645_ANC_DIS				(0x0 << 14)
+#define RT5645_ANC_EN				(0x1 << 14)
+#define RT5645_ANC_MD_MASK			(0x3 << 12)
+#define RT5645_ANC_MD_SFT			12
+#define RT5645_ANC_MD_DIS			(0x0 << 12)
+#define RT5645_ANC_MD_67MS			(0x1 << 12)
+#define RT5645_ANC_MD_267MS			(0x2 << 12)
+#define RT5645_ANC_MD_1067MS			(0x3 << 12)
+#define RT5645_ANC_SN_MASK			(0x1 << 11)
+#define RT5645_ANC_SN_SFT			11
+#define RT5645_ANC_SN_DIS			(0x0 << 11)
+#define RT5645_ANC_SN_EN			(0x1 << 11)
+#define RT5645_ANC_CLK_MASK			(0x1 << 10)
+#define RT5645_ANC_CLK_SFT			10
+#define RT5645_ANC_CLK_ANC			(0x0 << 10)
+#define RT5645_ANC_CLK_REG			(0x1 << 10)
+#define RT5645_ANC_ZCD_MASK			(0x3 << 8)
+#define RT5645_ANC_ZCD_SFT			8
+#define RT5645_ANC_ZCD_DIS			(0x0 << 8)
+#define RT5645_ANC_ZCD_T1			(0x1 << 8)
+#define RT5645_ANC_ZCD_T2			(0x2 << 8)
+#define RT5645_ANC_ZCD_WT			(0x3 << 8)
+#define RT5645_ANC_CS_MASK			(0x1 << 7)
+#define RT5645_ANC_CS_SFT			7
+#define RT5645_ANC_CS_DIS			(0x0 << 7)
+#define RT5645_ANC_CS_EN			(0x1 << 7)
+#define RT5645_ANC_SW_MASK			(0x1 << 6)
+#define RT5645_ANC_SW_SFT			6
+#define RT5645_ANC_SW_NOR			(0x0 << 6)
+#define RT5645_ANC_SW_AUTO			(0x1 << 6)
+#define RT5645_ANC_CO_L_MASK			(0x3f)
+#define RT5645_ANC_CO_L_SFT			0
+
+/* ANC Control 2 (0xb6) */
+#define RT5645_ANC_FG_R_MASK			(0xf << 12)
+#define RT5645_ANC_FG_R_SFT			12
+#define RT5645_ANC_FG_L_MASK			(0xf << 8)
+#define RT5645_ANC_FG_L_SFT			8
+#define RT5645_ANC_CG_R_MASK			(0xf << 4)
+#define RT5645_ANC_CG_R_SFT			4
+#define RT5645_ANC_CG_L_MASK			(0xf)
+#define RT5645_ANC_CG_L_SFT			0
+
+/* ANC Control 3 (0xb6) */
+#define RT5645_ANC_CD_MASK			(0x1 << 6)
+#define RT5645_ANC_CD_SFT			6
+#define RT5645_ANC_CD_BOTH			(0x0 << 6)
+#define RT5645_ANC_CD_IND			(0x1 << 6)
+#define RT5645_ANC_CO_R_MASK			(0x3f)
+#define RT5645_ANC_CO_R_SFT			0
+
+/* Jack Detect Control (0xbb) */
+#define RT5645_JD_MASK				(0x7 << 13)
+#define RT5645_JD_SFT				13
+#define RT5645_JD_DIS				(0x0 << 13)
+#define RT5645_JD_GPIO1				(0x1 << 13)
+#define RT5645_JD_JD1_IN4P			(0x2 << 13)
+#define RT5645_JD_JD2_IN4N			(0x3 << 13)
+#define RT5645_JD_GPIO2				(0x4 << 13)
+#define RT5645_JD_GPIO3				(0x5 << 13)
+#define RT5645_JD_GPIO4				(0x6 << 13)
+#define RT5645_JD_HP_MASK			(0x1 << 11)
+#define RT5645_JD_HP_SFT			11
+#define RT5645_JD_HP_DIS			(0x0 << 11)
+#define RT5645_JD_HP_EN				(0x1 << 11)
+#define RT5645_JD_HP_TRG_MASK			(0x1 << 10)
+#define RT5645_JD_HP_TRG_SFT			10
+#define RT5645_JD_HP_TRG_LO			(0x0 << 10)
+#define RT5645_JD_HP_TRG_HI			(0x1 << 10)
+#define RT5645_JD_SPL_MASK			(0x1 << 9)
+#define RT5645_JD_SPL_SFT			9
+#define RT5645_JD_SPL_DIS			(0x0 << 9)
+#define RT5645_JD_SPL_EN			(0x1 << 9)
+#define RT5645_JD_SPL_TRG_MASK			(0x1 << 8)
+#define RT5645_JD_SPL_TRG_SFT			8
+#define RT5645_JD_SPL_TRG_LO			(0x0 << 8)
+#define RT5645_JD_SPL_TRG_HI			(0x1 << 8)
+#define RT5645_JD_SPR_MASK			(0x1 << 7)
+#define RT5645_JD_SPR_SFT			7
+#define RT5645_JD_SPR_DIS			(0x0 << 7)
+#define RT5645_JD_SPR_EN			(0x1 << 7)
+#define RT5645_JD_SPR_TRG_MASK			(0x1 << 6)
+#define RT5645_JD_SPR_TRG_SFT			6
+#define RT5645_JD_SPR_TRG_LO			(0x0 << 6)
+#define RT5645_JD_SPR_TRG_HI			(0x1 << 6)
+#define RT5645_JD_MO_MASK			(0x1 << 5)
+#define RT5645_JD_MO_SFT			5
+#define RT5645_JD_MO_DIS			(0x0 << 5)
+#define RT5645_JD_MO_EN				(0x1 << 5)
+#define RT5645_JD_MO_TRG_MASK			(0x1 << 4)
+#define RT5645_JD_MO_TRG_SFT			4
+#define RT5645_JD_MO_TRG_LO			(0x0 << 4)
+#define RT5645_JD_MO_TRG_HI			(0x1 << 4)
+#define RT5645_JD_LO_MASK			(0x1 << 3)
+#define RT5645_JD_LO_SFT			3
+#define RT5645_JD_LO_DIS			(0x0 << 3)
+#define RT5645_JD_LO_EN				(0x1 << 3)
+#define RT5645_JD_LO_TRG_MASK			(0x1 << 2)
+#define RT5645_JD_LO_TRG_SFT			2
+#define RT5645_JD_LO_TRG_LO			(0x0 << 2)
+#define RT5645_JD_LO_TRG_HI			(0x1 << 2)
+#define RT5645_JD1_IN4P_MASK			(0x1 << 1)
+#define RT5645_JD1_IN4P_SFT			1
+#define RT5645_JD1_IN4P_DIS			(0x0 << 1)
+#define RT5645_JD1_IN4P_EN			(0x1 << 1)
+#define RT5645_JD2_IN4N_MASK			(0x1)
+#define RT5645_JD2_IN4N_SFT			0
+#define RT5645_JD2_IN4N_DIS			(0x0)
+#define RT5645_JD2_IN4N_EN			(0x1)
+
+/* Jack detect for ANC (0xbc) */
+#define RT5645_ANC_DET_MASK			(0x3 << 4)
+#define RT5645_ANC_DET_SFT			4
+#define RT5645_ANC_DET_DIS			(0x0 << 4)
+#define RT5645_ANC_DET_MB1			(0x1 << 4)
+#define RT5645_ANC_DET_MB2			(0x2 << 4)
+#define RT5645_ANC_DET_JD			(0x3 << 4)
+#define RT5645_AD_TRG_MASK			(0x1 << 3)
+#define RT5645_AD_TRG_SFT			3
+#define RT5645_AD_TRG_LO			(0x0 << 3)
+#define RT5645_AD_TRG_HI			(0x1 << 3)
+#define RT5645_ANCM_DET_MASK			(0x3 << 4)
+#define RT5645_ANCM_DET_SFT			4
+#define RT5645_ANCM_DET_DIS			(0x0 << 4)
+#define RT5645_ANCM_DET_MB1			(0x1 << 4)
+#define RT5645_ANCM_DET_MB2			(0x2 << 4)
+#define RT5645_ANCM_DET_JD			(0x3 << 4)
+#define RT5645_AMD_TRG_MASK			(0x1 << 3)
+#define RT5645_AMD_TRG_SFT			3
+#define RT5645_AMD_TRG_LO			(0x0 << 3)
+#define RT5645_AMD_TRG_HI			(0x1 << 3)
+
+/* IRQ Control 1 (0xbd) */
+#define RT5645_IRQ_JD_MASK			(0x1 << 15)
+#define RT5645_IRQ_JD_SFT			15
+#define RT5645_IRQ_JD_BP			(0x0 << 15)
+#define RT5645_IRQ_JD_NOR			(0x1 << 15)
+#define RT5645_IRQ_OT_MASK			(0x1 << 14)
+#define RT5645_IRQ_OT_SFT			14
+#define RT5645_IRQ_OT_BP			(0x0 << 14)
+#define RT5645_IRQ_OT_NOR			(0x1 << 14)
+#define RT5645_JD_STKY_MASK			(0x1 << 13)
+#define RT5645_JD_STKY_SFT			13
+#define RT5645_JD_STKY_DIS			(0x0 << 13)
+#define RT5645_JD_STKY_EN			(0x1 << 13)
+#define RT5645_OT_STKY_MASK			(0x1 << 12)
+#define RT5645_OT_STKY_SFT			12
+#define RT5645_OT_STKY_DIS			(0x0 << 12)
+#define RT5645_OT_STKY_EN			(0x1 << 12)
+#define RT5645_JD_P_MASK			(0x1 << 11)
+#define RT5645_JD_P_SFT				11
+#define RT5645_JD_P_NOR				(0x0 << 11)
+#define RT5645_JD_P_INV				(0x1 << 11)
+#define RT5645_OT_P_MASK			(0x1 << 10)
+#define RT5645_OT_P_SFT				10
+#define RT5645_OT_P_NOR				(0x0 << 10)
+#define RT5645_OT_P_INV				(0x1 << 10)
+
+/* IRQ Control 2 (0xbe) */
+#define RT5645_IRQ_MB1_OC_MASK			(0x1 << 15)
+#define RT5645_IRQ_MB1_OC_SFT			15
+#define RT5645_IRQ_MB1_OC_BP			(0x0 << 15)
+#define RT5645_IRQ_MB1_OC_NOR			(0x1 << 15)
+#define RT5645_IRQ_MB2_OC_MASK			(0x1 << 14)
+#define RT5645_IRQ_MB2_OC_SFT			14
+#define RT5645_IRQ_MB2_OC_BP			(0x0 << 14)
+#define RT5645_IRQ_MB2_OC_NOR			(0x1 << 14)
+#define RT5645_MB1_OC_STKY_MASK			(0x1 << 13)
+#define RT5645_MB1_OC_STKY_SFT			13
+#define RT5645_MB1_OC_STKY_DIS			(0x0 << 13)
+#define RT5645_MB1_OC_STKY_EN			(0x1 << 13)
+#define RT5645_MB2_OC_STKY_MASK			(0x1 << 12)
+#define RT5645_MB2_OC_STKY_SFT			12
+#define RT5645_MB2_OC_STKY_DIS			(0x0 << 12)
+#define RT5645_MB2_OC_STKY_EN			(0x1 << 12)
+#define RT5645_MB1_OC_P_MASK			(0x1 << 7)
+#define RT5645_MB1_OC_P_SFT			7
+#define RT5645_MB1_OC_P_NOR			(0x0 << 7)
+#define RT5645_MB1_OC_P_INV			(0x1 << 7)
+#define RT5645_MB2_OC_P_MASK			(0x1 << 6)
+#define RT5645_MB2_OC_P_SFT			6
+#define RT5645_MB2_OC_P_NOR			(0x0 << 6)
+#define RT5645_MB2_OC_P_INV			(0x1 << 6)
+#define RT5645_MB1_OC_CLR			(0x1 << 3)
+#define RT5645_MB1_OC_CLR_SFT			3
+#define RT5645_MB2_OC_CLR			(0x1 << 2)
+#define RT5645_MB2_OC_CLR_SFT			2
+
+/* GPIO Control 1 (0xc0) */
+#define RT5645_GP1_PIN_MASK			(0x1 << 15)
+#define RT5645_GP1_PIN_SFT			15
+#define RT5645_GP1_PIN_GPIO1			(0x0 << 15)
+#define RT5645_GP1_PIN_IRQ			(0x1 << 15)
+#define RT5645_GP2_PIN_MASK			(0x1 << 14)
+#define RT5645_GP2_PIN_SFT			14
+#define RT5645_GP2_PIN_GPIO2			(0x0 << 14)
+#define RT5645_GP2_PIN_DMIC1_SCL		(0x1 << 14)
+#define RT5645_GP3_PIN_MASK			(0x3 << 12)
+#define RT5645_GP3_PIN_SFT			12
+#define RT5645_GP3_PIN_GPIO3			(0x0 << 12)
+#define RT5645_GP3_PIN_DMIC1_SDA		(0x1 << 12)
+#define RT5645_GP3_PIN_IRQ			(0x2 << 12)
+#define RT5645_GP4_PIN_MASK			(0x1 << 11)
+#define RT5645_GP4_PIN_SFT			11
+#define RT5645_GP4_PIN_GPIO4			(0x0 << 11)
+#define RT5645_GP4_PIN_DMIC2_SDA		(0x1 << 11)
+#define RT5645_DP_SIG_MASK			(0x1 << 10)
+#define RT5645_DP_SIG_SFT			10
+#define RT5645_DP_SIG_TEST			(0x0 << 10)
+#define RT5645_DP_SIG_AP			(0x1 << 10)
+#define RT5645_GPIO_M_MASK			(0x1 << 9)
+#define RT5645_GPIO_M_SFT			9
+#define RT5645_GPIO_M_FLT			(0x0 << 9)
+#define RT5645_GPIO_M_PH			(0x1 << 9)
+#define RT5645_I2S2_SEL				(0x1 << 8)
+#define RT5645_I2S2_SEL_SFT			8
+#define RT5645_GP5_PIN_MASK			(0x1 << 7)
+#define RT5645_GP5_PIN_SFT			7
+#define RT5645_GP5_PIN_GPIO5			(0x0 << 7)
+#define RT5645_GP5_PIN_DMIC1_SDA		(0x1 << 7)
+#define RT5645_GP6_PIN_MASK			(0x1 << 6)
+#define RT5645_GP6_PIN_SFT			6
+#define RT5645_GP6_PIN_GPIO6			(0x0 << 6)
+#define RT5645_GP6_PIN_DMIC2_SDA		(0x1 << 6)
+#define RT5645_GP8_PIN_MASK			(0x1 << 3)
+#define RT5645_GP8_PIN_SFT			3
+#define RT5645_GP8_PIN_GPIO8			(0x0 << 3)
+#define RT5645_GP8_PIN_DMIC2_SDA		(0x1 << 3)
+#define RT5645_GP12_PIN_MASK			(0x1 << 2)
+#define RT5645_GP12_PIN_SFT			2
+#define RT5645_GP12_PIN_GPIO12			(0x0 << 2)
+#define RT5645_GP12_PIN_DMIC2_SDA		(0x1 << 2)
+#define RT5645_GP11_PIN_MASK			(0x1 << 1)
+#define RT5645_GP11_PIN_SFT			1
+#define RT5645_GP11_PIN_GPIO11			(0x0 << 1)
+#define RT5645_GP11_PIN_DMIC1_SDA		(0x1 << 1)
+#define RT5645_GP10_PIN_MASK			(0x1)
+#define RT5645_GP10_PIN_SFT			0
+#define RT5645_GP10_PIN_GPIO10			(0x0)
+#define RT5645_GP10_PIN_DMIC2_SDA		(0x1)
+
+/* GPIO Control 3 (0xc2) */
+#define RT5645_GP4_PF_MASK			(0x1 << 11)
+#define RT5645_GP4_PF_SFT			11
+#define RT5645_GP4_PF_IN			(0x0 << 11)
+#define RT5645_GP4_PF_OUT			(0x1 << 11)
+#define RT5645_GP4_OUT_MASK			(0x1 << 10)
+#define RT5645_GP4_OUT_SFT			10
+#define RT5645_GP4_OUT_LO			(0x0 << 10)
+#define RT5645_GP4_OUT_HI			(0x1 << 10)
+#define RT5645_GP4_P_MASK			(0x1 << 9)
+#define RT5645_GP4_P_SFT			9
+#define RT5645_GP4_P_NOR			(0x0 << 9)
+#define RT5645_GP4_P_INV			(0x1 << 9)
+#define RT5645_GP3_PF_MASK			(0x1 << 8)
+#define RT5645_GP3_PF_SFT			8
+#define RT5645_GP3_PF_IN			(0x0 << 8)
+#define RT5645_GP3_PF_OUT			(0x1 << 8)
+#define RT5645_GP3_OUT_MASK			(0x1 << 7)
+#define RT5645_GP3_OUT_SFT			7
+#define RT5645_GP3_OUT_LO			(0x0 << 7)
+#define RT5645_GP3_OUT_HI			(0x1 << 7)
+#define RT5645_GP3_P_MASK			(0x1 << 6)
+#define RT5645_GP3_P_SFT			6
+#define RT5645_GP3_P_NOR			(0x0 << 6)
+#define RT5645_GP3_P_INV			(0x1 << 6)
+#define RT5645_GP2_PF_MASK			(0x1 << 5)
+#define RT5645_GP2_PF_SFT			5
+#define RT5645_GP2_PF_IN			(0x0 << 5)
+#define RT5645_GP2_PF_OUT			(0x1 << 5)
+#define RT5645_GP2_OUT_MASK			(0x1 << 4)
+#define RT5645_GP2_OUT_SFT			4
+#define RT5645_GP2_OUT_LO			(0x0 << 4)
+#define RT5645_GP2_OUT_HI			(0x1 << 4)
+#define RT5645_GP2_P_MASK			(0x1 << 3)
+#define RT5645_GP2_P_SFT			3
+#define RT5645_GP2_P_NOR			(0x0 << 3)
+#define RT5645_GP2_P_INV			(0x1 << 3)
+#define RT5645_GP1_PF_MASK			(0x1 << 2)
+#define RT5645_GP1_PF_SFT			2
+#define RT5645_GP1_PF_IN			(0x0 << 2)
+#define RT5645_GP1_PF_OUT			(0x1 << 2)
+#define RT5645_GP1_OUT_MASK			(0x1 << 1)
+#define RT5645_GP1_OUT_SFT			1
+#define RT5645_GP1_OUT_LO			(0x0 << 1)
+#define RT5645_GP1_OUT_HI			(0x1 << 1)
+#define RT5645_GP1_P_MASK			(0x1)
+#define RT5645_GP1_P_SFT			0
+#define RT5645_GP1_P_NOR			(0x0)
+#define RT5645_GP1_P_INV			(0x1)
+
+/* Programmable Register Array Control 1 (0xc8) */
+#define RT5645_REG_SEQ_MASK			(0xf << 12)
+#define RT5645_REG_SEQ_SFT			12
+#define RT5645_SEQ1_ST_MASK			(0x1 << 11) /*RO*/
+#define RT5645_SEQ1_ST_SFT			11
+#define RT5645_SEQ1_ST_RUN			(0x0 << 11)
+#define RT5645_SEQ1_ST_FIN			(0x1 << 11)
+#define RT5645_SEQ2_ST_MASK			(0x1 << 10) /*RO*/
+#define RT5645_SEQ2_ST_SFT			10
+#define RT5645_SEQ2_ST_RUN			(0x0 << 10)
+#define RT5645_SEQ2_ST_FIN			(0x1 << 10)
+#define RT5645_REG_LV_MASK			(0x1 << 9)
+#define RT5645_REG_LV_SFT			9
+#define RT5645_REG_LV_MX			(0x0 << 9)
+#define RT5645_REG_LV_PR			(0x1 << 9)
+#define RT5645_SEQ_2_PT_MASK			(0x1 << 8)
+#define RT5645_SEQ_2_PT_BIT			8
+#define RT5645_REG_IDX_MASK			(0xff)
+#define RT5645_REG_IDX_SFT			0
+
+/* Programmable Register Array Control 2 (0xc9) */
+#define RT5645_REG_DAT_MASK			(0xffff)
+#define RT5645_REG_DAT_SFT			0
+
+/* Programmable Register Array Control 3 (0xca) */
+#define RT5645_SEQ_DLY_MASK			(0xff << 8)
+#define RT5645_SEQ_DLY_SFT			8
+#define RT5645_PROG_MASK			(0x1 << 7)
+#define RT5645_PROG_SFT				7
+#define RT5645_PROG_DIS				(0x0 << 7)
+#define RT5645_PROG_EN				(0x1 << 7)
+#define RT5645_SEQ1_PT_RUN			(0x1 << 6)
+#define RT5645_SEQ1_PT_RUN_BIT			6
+#define RT5645_SEQ2_PT_RUN			(0x1 << 5)
+#define RT5645_SEQ2_PT_RUN_BIT			5
+
+/* Programmable Register Array Control 4 (0xcb) */
+#define RT5645_SEQ1_START_MASK			(0xf << 8)
+#define RT5645_SEQ1_START_SFT			8
+#define RT5645_SEQ1_END_MASK			(0xf)
+#define RT5645_SEQ1_END_SFT			0
+
+/* Programmable Register Array Control 5 (0xcc) */
+#define RT5645_SEQ2_START_MASK			(0xf << 8)
+#define RT5645_SEQ2_START_SFT			8
+#define RT5645_SEQ2_END_MASK			(0xf)
+#define RT5645_SEQ2_END_SFT			0
+
+/* Scramble Function (0xcd) */
+#define RT5645_SCB_KEY_MASK			(0xff)
+#define RT5645_SCB_KEY_SFT			0
+
+/* Scramble Control (0xce) */
+#define RT5645_SCB_SWAP_MASK			(0x1 << 15)
+#define RT5645_SCB_SWAP_SFT			15
+#define RT5645_SCB_SWAP_DIS			(0x0 << 15)
+#define RT5645_SCB_SWAP_EN			(0x1 << 15)
+#define RT5645_SCB_MASK				(0x1 << 14)
+#define RT5645_SCB_SFT				14
+#define RT5645_SCB_DIS				(0x0 << 14)
+#define RT5645_SCB_EN				(0x1 << 14)
+
+/* Baseback Control (0xcf) */
+#define RT5645_BB_MASK				(0x1 << 15)
+#define RT5645_BB_SFT				15
+#define RT5645_BB_DIS				(0x0 << 15)
+#define RT5645_BB_EN				(0x1 << 15)
+#define RT5645_BB_CT_MASK			(0x7 << 12)
+#define RT5645_BB_CT_SFT			12
+#define RT5645_BB_CT_A				(0x0 << 12)
+#define RT5645_BB_CT_B				(0x1 << 12)
+#define RT5645_BB_CT_C				(0x2 << 12)
+#define RT5645_BB_CT_D				(0x3 << 12)
+#define RT5645_M_BB_L_MASK			(0x1 << 9)
+#define RT5645_M_BB_L_SFT			9
+#define RT5645_M_BB_R_MASK			(0x1 << 8)
+#define RT5645_M_BB_R_SFT			8
+#define RT5645_M_BB_HPF_L_MASK			(0x1 << 7)
+#define RT5645_M_BB_HPF_L_SFT			7
+#define RT5645_M_BB_HPF_R_MASK			(0x1 << 6)
+#define RT5645_M_BB_HPF_R_SFT			6
+#define RT5645_G_BB_BST_MASK			(0x3f)
+#define RT5645_G_BB_BST_SFT			0
+
+/* MP3 Plus Control 1 (0xd0) */
+#define RT5645_M_MP3_L_MASK			(0x1 << 15)
+#define RT5645_M_MP3_L_SFT			15
+#define RT5645_M_MP3_R_MASK			(0x1 << 14)
+#define RT5645_M_MP3_R_SFT			14
+#define RT5645_M_MP3_MASK			(0x1 << 13)
+#define RT5645_M_MP3_SFT			13
+#define RT5645_M_MP3_DIS			(0x0 << 13)
+#define RT5645_M_MP3_EN				(0x1 << 13)
+#define RT5645_EG_MP3_MASK			(0x1f << 8)
+#define RT5645_EG_MP3_SFT			8
+#define RT5645_MP3_HLP_MASK			(0x1 << 7)
+#define RT5645_MP3_HLP_SFT			7
+#define RT5645_MP3_HLP_DIS			(0x0 << 7)
+#define RT5645_MP3_HLP_EN			(0x1 << 7)
+#define RT5645_M_MP3_ORG_L_MASK			(0x1 << 6)
+#define RT5645_M_MP3_ORG_L_SFT			6
+#define RT5645_M_MP3_ORG_R_MASK			(0x1 << 5)
+#define RT5645_M_MP3_ORG_R_SFT			5
+
+/* MP3 Plus Control 2 (0xd1) */
+#define RT5645_MP3_WT_MASK			(0x1 << 13)
+#define RT5645_MP3_WT_SFT			13
+#define RT5645_MP3_WT_1_4			(0x0 << 13)
+#define RT5645_MP3_WT_1_2			(0x1 << 13)
+#define RT5645_OG_MP3_MASK			(0x1f << 8)
+#define RT5645_OG_MP3_SFT			8
+#define RT5645_HG_MP3_MASK			(0x3f)
+#define RT5645_HG_MP3_SFT			0
+
+/* 3D HP Control 1 (0xd2) */
+#define RT5645_3D_CF_MASK			(0x1 << 15)
+#define RT5645_3D_CF_SFT			15
+#define RT5645_3D_CF_DIS			(0x0 << 15)
+#define RT5645_3D_CF_EN				(0x1 << 15)
+#define RT5645_3D_HP_MASK			(0x1 << 14)
+#define RT5645_3D_HP_SFT			14
+#define RT5645_3D_HP_DIS			(0x0 << 14)
+#define RT5645_3D_HP_EN				(0x1 << 14)
+#define RT5645_3D_BT_MASK			(0x1 << 13)
+#define RT5645_3D_BT_SFT			13
+#define RT5645_3D_BT_DIS			(0x0 << 13)
+#define RT5645_3D_BT_EN				(0x1 << 13)
+#define RT5645_3D_1F_MIX_MASK			(0x3 << 11)
+#define RT5645_3D_1F_MIX_SFT			11
+#define RT5645_3D_HP_M_MASK			(0x1 << 10)
+#define RT5645_3D_HP_M_SFT			10
+#define RT5645_3D_HP_M_SUR			(0x0 << 10)
+#define RT5645_3D_HP_M_FRO			(0x1 << 10)
+#define RT5645_M_3D_HRTF_MASK			(0x1 << 9)
+#define RT5645_M_3D_HRTF_SFT			9
+#define RT5645_M_3D_D2H_MASK			(0x1 << 8)
+#define RT5645_M_3D_D2H_SFT			8
+#define RT5645_M_3D_D2R_MASK			(0x1 << 7)
+#define RT5645_M_3D_D2R_SFT			7
+#define RT5645_M_3D_REVB_MASK			(0x1 << 6)
+#define RT5645_M_3D_REVB_SFT			6
+
+/* Adjustable high pass filter control 1 (0xd3) */
+#define RT5645_2ND_HPF_MASK			(0x1 << 15)
+#define RT5645_2ND_HPF_SFT			15
+#define RT5645_2ND_HPF_DIS			(0x0 << 15)
+#define RT5645_2ND_HPF_EN			(0x1 << 15)
+#define RT5645_HPF_CF_L_MASK			(0x7 << 12)
+#define RT5645_HPF_CF_L_SFT			12
+#define RT5645_1ST_HPF_MASK			(0x1 << 11)
+#define RT5645_1ST_HPF_SFT			11
+#define RT5645_1ST_HPF_DIS			(0x0 << 11)
+#define RT5645_1ST_HPF_EN			(0x1 << 11)
+#define RT5645_HPF_CF_R_MASK			(0x7 << 8)
+#define RT5645_HPF_CF_R_SFT			8
+#define RT5645_ZD_T_MASK			(0x3 << 6)
+#define RT5645_ZD_T_SFT				6
+#define RT5645_ZD_F_MASK			(0x3 << 4)
+#define RT5645_ZD_F_SFT				4
+#define RT5645_ZD_F_IM				(0x0 << 4)
+#define RT5645_ZD_F_ZC_IM			(0x1 << 4)
+#define RT5645_ZD_F_ZC_IOD			(0x2 << 4)
+#define RT5645_ZD_F_UN				(0x3 << 4)
+
+/* HP calibration control and Amp detection (0xd6) */
+#define RT5645_SI_DAC_MASK			(0x1 << 11)
+#define RT5645_SI_DAC_SFT			11
+#define RT5645_SI_DAC_AUTO			(0x0 << 11)
+#define RT5645_SI_DAC_TEST			(0x1 << 11)
+#define RT5645_DC_CAL_M_MASK			(0x1 << 10)
+#define RT5645_DC_CAL_M_SFT			10
+#define RT5645_DC_CAL_M_CAL			(0x0 << 10)
+#define RT5645_DC_CAL_M_NOR			(0x1 << 10)
+#define RT5645_DC_CAL_MASK			(0x1 << 9)
+#define RT5645_DC_CAL_SFT			9
+#define RT5645_DC_CAL_DIS			(0x0 << 9)
+#define RT5645_DC_CAL_EN			(0x1 << 9)
+#define RT5645_HPD_RCV_MASK			(0x7 << 6)
+#define RT5645_HPD_RCV_SFT			6
+#define RT5645_HPD_PS_MASK			(0x1 << 5)
+#define RT5645_HPD_PS_SFT			5
+#define RT5645_HPD_PS_DIS			(0x0 << 5)
+#define RT5645_HPD_PS_EN			(0x1 << 5)
+#define RT5645_CAL_M_MASK			(0x1 << 4)
+#define RT5645_CAL_M_SFT			4
+#define RT5645_CAL_M_DEP			(0x0 << 4)
+#define RT5645_CAL_M_CAL			(0x1 << 4)
+#define RT5645_CAL_MASK				(0x1 << 3)
+#define RT5645_CAL_SFT				3
+#define RT5645_CAL_DIS				(0x0 << 3)
+#define RT5645_CAL_EN				(0x1 << 3)
+#define RT5645_CAL_TEST_MASK			(0x1 << 2)
+#define RT5645_CAL_TEST_SFT			2
+#define RT5645_CAL_TEST_DIS			(0x0 << 2)
+#define RT5645_CAL_TEST_EN			(0x1 << 2)
+#define RT5645_CAL_P_MASK			(0x3)
+#define RT5645_CAL_P_SFT			0
+#define RT5645_CAL_P_NONE			(0x0)
+#define RT5645_CAL_P_CAL			(0x1)
+#define RT5645_CAL_P_DAC_CAL			(0x2)
+
+/* Soft volume and zero cross control 1 (0xd9) */
+#define RT5645_SV_MASK				(0x1 << 15)
+#define RT5645_SV_SFT				15
+#define RT5645_SV_DIS				(0x0 << 15)
+#define RT5645_SV_EN				(0x1 << 15)
+#define RT5645_SPO_SV_MASK			(0x1 << 14)
+#define RT5645_SPO_SV_SFT			14
+#define RT5645_SPO_SV_DIS			(0x0 << 14)
+#define RT5645_SPO_SV_EN			(0x1 << 14)
+#define RT5645_OUT_SV_MASK			(0x1 << 13)
+#define RT5645_OUT_SV_SFT			13
+#define RT5645_OUT_SV_DIS			(0x0 << 13)
+#define RT5645_OUT_SV_EN			(0x1 << 13)
+#define RT5645_HP_SV_MASK			(0x1 << 12)
+#define RT5645_HP_SV_SFT			12
+#define RT5645_HP_SV_DIS			(0x0 << 12)
+#define RT5645_HP_SV_EN				(0x1 << 12)
+#define RT5645_ZCD_DIG_MASK			(0x1 << 11)
+#define RT5645_ZCD_DIG_SFT			11
+#define RT5645_ZCD_DIG_DIS			(0x0 << 11)
+#define RT5645_ZCD_DIG_EN			(0x1 << 11)
+#define RT5645_ZCD_MASK				(0x1 << 10)
+#define RT5645_ZCD_SFT				10
+#define RT5645_ZCD_PD				(0x0 << 10)
+#define RT5645_ZCD_PU				(0x1 << 10)
+#define RT5645_M_ZCD_MASK			(0x3f << 4)
+#define RT5645_M_ZCD_SFT			4
+#define RT5645_M_ZCD_RM_L			(0x1 << 9)
+#define RT5645_M_ZCD_RM_R			(0x1 << 8)
+#define RT5645_M_ZCD_SM_L			(0x1 << 7)
+#define RT5645_M_ZCD_SM_R			(0x1 << 6)
+#define RT5645_M_ZCD_OM_L			(0x1 << 5)
+#define RT5645_M_ZCD_OM_R			(0x1 << 4)
+#define RT5645_SV_DLY_MASK			(0xf)
+#define RT5645_SV_DLY_SFT			0
+
+/* Soft volume and zero cross control 2 (0xda) */
+#define RT5645_ZCD_HP_MASK			(0x1 << 15)
+#define RT5645_ZCD_HP_SFT			15
+#define RT5645_ZCD_HP_DIS			(0x0 << 15)
+#define RT5645_ZCD_HP_EN			(0x1 << 15)
+
+
+/* Codec Private Register definition */
+/* 3D Speaker Control (0x63) */
+#define RT5645_3D_SPK_MASK			(0x1 << 15)
+#define RT5645_3D_SPK_SFT			15
+#define RT5645_3D_SPK_DIS			(0x0 << 15)
+#define RT5645_3D_SPK_EN			(0x1 << 15)
+#define RT5645_3D_SPK_M_MASK			(0x3 << 13)
+#define RT5645_3D_SPK_M_SFT			13
+#define RT5645_3D_SPK_CG_MASK			(0x1f << 8)
+#define RT5645_3D_SPK_CG_SFT			8
+#define RT5645_3D_SPK_SG_MASK			(0x1f)
+#define RT5645_3D_SPK_SG_SFT			0
+
+/* Wind Noise Detection Control 1 (0x6c) */
+#define RT5645_WND_MASK				(0x1 << 15)
+#define RT5645_WND_SFT				15
+#define RT5645_WND_DIS				(0x0 << 15)
+#define RT5645_WND_EN				(0x1 << 15)
+
+/* Wind Noise Detection Control 2 (0x6d) */
+#define RT5645_WND_FC_NW_MASK			(0x3f << 10)
+#define RT5645_WND_FC_NW_SFT			10
+#define RT5645_WND_FC_WK_MASK			(0x3f << 4)
+#define RT5645_WND_FC_WK_SFT			4
+
+/* Wind Noise Detection Control 3 (0x6e) */
+#define RT5645_HPF_FC_MASK			(0x3f << 6)
+#define RT5645_HPF_FC_SFT			6
+#define RT5645_WND_FC_ST_MASK			(0x3f)
+#define RT5645_WND_FC_ST_SFT			0
+
+/* Wind Noise Detection Control 4 (0x6f) */
+#define RT5645_WND_TH_LO_MASK			(0x3ff)
+#define RT5645_WND_TH_LO_SFT			0
+
+/* Wind Noise Detection Control 5 (0x70) */
+#define RT5645_WND_TH_HI_MASK			(0x3ff)
+#define RT5645_WND_TH_HI_SFT			0
+
+/* Wind Noise Detection Control 8 (0x73) */
+#define RT5645_WND_WIND_MASK			(0x1 << 13) /* Read-Only */
+#define RT5645_WND_WIND_SFT			13
+#define RT5645_WND_STRONG_MASK			(0x1 << 12) /* Read-Only */
+#define RT5645_WND_STRONG_SFT			12
+enum {
+	RT5645_NO_WIND,
+	RT5645_BREEZE,
+	RT5645_STORM,
+};
+
+/* Dipole Speaker Interface (0x75) */
+#define RT5645_DP_ATT_MASK			(0x3 << 14)
+#define RT5645_DP_ATT_SFT			14
+#define RT5645_DP_SPK_MASK			(0x1 << 10)
+#define RT5645_DP_SPK_SFT			10
+#define RT5645_DP_SPK_DIS			(0x0 << 10)
+#define RT5645_DP_SPK_EN			(0x1 << 10)
+
+/* EQ Pre Volume Control (0xb3) */
+#define RT5645_EQ_PRE_VOL_MASK			(0xffff)
+#define RT5645_EQ_PRE_VOL_SFT			0
+
+/* EQ Post Volume Control (0xb4) */
+#define RT5645_EQ_PST_VOL_MASK			(0xffff)
+#define RT5645_EQ_PST_VOL_SFT			0
+
+/* Jack Detect Control 3 (0xf8) */
+#define RT5645_CMP_MIC_IN_DET_MASK		(0x7 << 12)
+#define RT5645_JD_CBJ_EN			(0x1 << 7)
+#define RT5645_JD_CBJ_POL			(0x1 << 6)
+#define RT5645_JD_TRI_CBJ_SEL_MASK		(0x7 << 3)
+#define RT5645_JD_TRI_CBJ_SEL_SFT		(3)
+#define RT5645_JD_TRI_HPO_SEL_MASK		(0x7)
+#define RT5645_JD_TRI_HPO_SEL_SFT		(0)
+#define RT5645_JD_F_GPIO_JD1			(0x0)
+#define RT5645_JD_F_JD1_1			(0x1)
+#define RT5645_JD_F_JD1_2			(0x2)
+#define RT5645_JD_F_JD2				(0x3)
+#define RT5645_JD_F_JD3				(0x4)
+#define RT5645_JD_F_GPIO_JD2			(0x5)
+#define RT5645_JD_F_MX0B_12			(0x6)
+
+/* Digital Misc Control (0xfa) */
+#define RT5645_RST_DSP				(0x1 << 13)
+#define RT5645_IF1_ADC1_IN1_SEL			(0x1 << 12)
+#define RT5645_IF1_ADC1_IN1_SFT			12
+#define RT5645_IF1_ADC1_IN2_SEL			(0x1 << 11)
+#define RT5645_IF1_ADC1_IN2_SFT			11
+#define RT5645_IF1_ADC2_IN1_SEL			(0x1 << 10)
+#define RT5645_IF1_ADC2_IN1_SFT			10
+#define RT5645_DIG_GATE_CTRL			0x1
+
+/* General Control2 (0xfb) */
+#define RT5645_RXDC_SRC_MASK			(0x1 << 7)
+#define RT5645_RXDC_SRC_STO			(0x0 << 7)
+#define RT5645_RXDC_SRC_MONO			(0x1 << 7)
+#define RT5645_RXDC_SRC_SFT			(7)
+#define RT5645_RXDP2_SEL_MASK			(0x1 << 3)
+#define RT5645_RXDP2_SEL_IF2			(0x0 << 3)
+#define RT5645_RXDP2_SEL_ADC			(0x1 << 3)
+#define RT5645_RXDP2_SEL_SFT			(3)
+
+
+/* Vendor ID (0xfd) */
+#define RT5645_VER_C				0x2
+#define RT5645_VER_D				0x3
+
+
+/* Volume Rescale */
+#define RT5645_VOL_RSCL_MAX 0x27
+#define RT5645_VOL_RSCL_RANGE 0x1F
+/* Debug String Length */
+#define RT5645_REG_DISP_LEN 23
+
+
+/* System Clock Source */
+enum {
+	RT5645_SCLK_S_MCLK,
+	RT5645_SCLK_S_PLL1,
+	RT5645_SCLK_S_RCCLK,
+};
+
+/* PLL1 Source */
+enum {
+	RT5645_PLL1_S_MCLK,
+	RT5645_PLL1_S_BCLK1,
+	RT5645_PLL1_S_BCLK2,
+};
+
+enum {
+	RT5645_AIF1,
+	RT5645_AIF2,
+	RT5645_AIFS,
+};
+
+enum {
+	RT5645_DMIC_DATA_IN2P,
+	RT5645_DMIC_DATA_GPIO6,
+	RT5645_DMIC_DATA_GPIO10,
+	RT5645_DMIC_DATA_GPIO12,
+};
+
+enum {
+	RT5645_DMIC_DATA_IN2N,
+	RT5645_DMIC_DATA_GPIO5,
+	RT5645_DMIC_DATA_GPIO11,
+};
+
+struct rt5645_pll_code {
+	bool m_bp; /* Indicates bypass m code or not. */
+	int m_code;
+	int n_code;
+	int k_code;
+};
+
+struct rt5645_priv {
+	struct snd_soc_codec *codec;
+	struct rt5645_platform_data pdata;
+	struct regmap *regmap;
+
+	int sysclk;
+	int sysclk_src;
+	int lrck[RT5645_AIFS];
+	int bclk[RT5645_AIFS];
+	int master[RT5645_AIFS];
+
+	int pll_src;
+	int pll_in;
+	int pll_out;
+};
+
+#endif /* __RT5645_H__ */

From 92e160ddf677566c0119c9dcac0e53989ea2a1ac Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 8 May 2014 14:47:34 +0800
Subject: [PATCH 70/86] ASoC: rt5645: Remove the unused variable

The patch is for removing the unused variable.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5645.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 7d8cc1688fb56..37ec468ab0e74 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -1166,7 +1166,6 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:

From 9e22f7826a6f2c255dd2ee96515597ed7a189022 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 8 May 2014 14:47:35 +0800
Subject: [PATCH 71/86] ASoC: rt5645: Staticise non-exported symbols

The patch is for staticising non-exported symbols

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5645.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 37ec468ab0e74..9d8c7c8332348 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -2248,7 +2248,7 @@ static int rt5645_resume(struct snd_soc_codec *codec)
 #define RT5645_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
 			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
 
-struct snd_soc_dai_ops rt5645_aif_dai_ops = {
+static struct snd_soc_dai_ops rt5645_aif_dai_ops = {
 	.hw_params = rt5645_hw_params,
 	.set_fmt = rt5645_set_dai_fmt,
 	.set_sysclk = rt5645_set_dai_sysclk,
@@ -2256,7 +2256,7 @@ struct snd_soc_dai_ops rt5645_aif_dai_ops = {
 	.set_pll = rt5645_set_dai_pll,
 };
 
-struct snd_soc_dai_driver rt5645_dai[] = {
+static struct snd_soc_dai_driver rt5645_dai[] = {
 	{
 		.name = "rt5645-aif1",
 		.id = RT5645_AIF1,
@@ -2459,7 +2459,7 @@ static int rt5645_i2c_remove(struct i2c_client *i2c)
 	return 0;
 }
 
-struct i2c_driver rt5645_i2c_driver = {
+static struct i2c_driver rt5645_i2c_driver = {
 	.driver = {
 		.name = "rt5645",
 		.owner = THIS_MODULE,

From 4809b96ebb301a8e6c9b61665bef70191fedd2dc Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 8 May 2014 14:47:36 +0800
Subject: [PATCH 72/86] ASoC: rt5645: Move settings from probe() to reg_default
 struct

The patch moves the private register settings from probe() to reg_default
struct.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5645.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 9d8c7c8332348..0165e07f09ab7 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -50,6 +50,10 @@ static const struct regmap_range_cfg rt5645_ranges[] = {
 
 static const struct reg_default init_list[] = {
 	{RT5645_PR_BASE + 0x3d,	0x3600},
+	{RT5645_PR_BASE + 0x1c,	0xfd20},
+	{RT5645_PR_BASE + 0x20,	0x611f},
+	{RT5645_PR_BASE + 0x21,	0x4040},
+	{RT5645_PR_BASE + 0x23,	0x0004},
 };
 #define RT5645_INIT_REG_LEN ARRAY_SIZE(init_list)
 
@@ -2205,10 +2209,6 @@ static int rt5645_probe(struct snd_soc_codec *codec)
 	rt5645_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200);
-	snd_soc_write(codec, RT5645_PR_BASE + 0x1c, 0xfd20);
-	snd_soc_write(codec, RT5645_PR_BASE + 0x20, 0x611f);
-	snd_soc_write(codec, RT5645_PR_BASE + 0x21, 0x4040);
-	snd_soc_write(codec, RT5645_PR_BASE + 0x23, 0x0004);
 
 	return 0;
 }

From 0f776efd86282ec750c26dbb1c2fd04b94949a28 Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 8 May 2014 14:47:37 +0800
Subject: [PATCH 73/86] ASoC: rt5645: Correct the cache sync function

The patch corrects the cache sync function

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5645.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 0165e07f09ab7..30410eb5b982e 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -2235,7 +2235,7 @@ static int rt5645_resume(struct snd_soc_codec *codec)
 	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
 
 	regcache_cache_only(rt5645->regmap, false);
-	snd_soc_cache_sync(codec);
+	regcache_sync(rt5645->regmap);
 
 	return 0;
 }

From 71bfa9b4d6d11c093e0db5d27b1d05803cbbaffc Mon Sep 17 00:00:00 2001
From: Oder Chiou <oder_chiou@realtek.com>
Date: Thu, 8 May 2014 15:42:37 +0800
Subject: [PATCH 74/86] ASoC: rt5645: fix coccinelle warnings

Return statements in functions returning bool should use
true/false instead of 1/0.

Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5645.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 30410eb5b982e..68923eca7d9c5 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -242,9 +242,9 @@ static bool rt5645_volatile_register(struct device *dev, unsigned int reg)
 	case RT5645_VENDOR_ID:
 	case RT5645_VENDOR_ID1:
 	case RT5645_VENDOR_ID2:
-		return 1;
+		return true;
 	default:
-		return 0;
+		return false;
 	}
 }
 
@@ -391,9 +391,9 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg)
 	case RT5645_VENDOR_ID:
 	case RT5645_VENDOR_ID1:
 	case RT5645_VENDOR_ID2:
-		return 1;
+		return true;
 	default:
-		return 0;
+		return false;
 	}
 }
 

From 5e392ea0da04d4206d56ec1479565fb42a044b57 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 01:59:00 -0700
Subject: [PATCH 75/86] ASoC: rsnd: remove old clock style support

All platform which used old style was
switched to new style.
R-Car sound can remove old style clock support,
use device dependent clock now.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/sh/rcar/adg.c | 39 +++------------------------------------
 1 file changed, 3 insertions(+), 36 deletions(-)

diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 69c44269ebdb9..41556b2ef21e8 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -397,9 +397,8 @@ int rsnd_adg_probe(struct platform_device *pdev,
 {
 	struct rsnd_adg *adg;
 	struct device *dev = rsnd_priv_to_dev(priv);
-	struct clk *clk, *clk_orig;
+	struct clk *clk;
 	int i;
-	bool use_old_style = false;
 
 	adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
 	if (!adg) {
@@ -407,45 +406,13 @@ int rsnd_adg_probe(struct platform_device *pdev,
 		return -ENOMEM;
 	}
 
-	clk_orig	= devm_clk_get(dev, NULL);
 	adg->clk[CLKA]	= devm_clk_get(dev, "clk_a");
 	adg->clk[CLKB]	= devm_clk_get(dev, "clk_b");
 	adg->clk[CLKC]	= devm_clk_get(dev, "clk_c");
 	adg->clk[CLKI]	= devm_clk_get(dev, "clk_i");
 
-	/*
-	 * It request device dependent audio clock.
-	 * But above all clks will indicate rsnd module clock
-	 * if platform doesn't it
-	 */
-	for_each_rsnd_clk(clk, adg, i) {
-		if (clk_orig == clk) {
-			dev_warn(dev,
-				 "doesn't have device dependent clock, use independent clock\n");
-			use_old_style = true;
-			break;
-		}
-	}
-
-	/*
-	 * note:
-	 * these exist in order to keep compatible with
-	 * platform which has device independent audio clock,
-	 * but will be removed soon
-	 */
-	if (use_old_style) {
-		adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a");
-		adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b");
-		adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c");
-		adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal");
-	}
-
-	for_each_rsnd_clk(clk, adg, i) {
-		if (IS_ERR(clk)) {
-			dev_err(dev, "Audio clock failed\n");
-			return -EIO;
-		}
-	}
+	for_each_rsnd_clk(clk, adg, i)
+		dev_dbg(dev, "clk %d : %p\n", i, clk);
 
 	rsnd_adg_ssi_clk_init(priv, adg);
 

From 29e69fd2cd6f55233f64f600ad55ce2b661784d1 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 01:59:26 -0700
Subject: [PATCH 76/86] ASoC: rsnd: remove compatibility code

Now, all platform is using new style rsnd_dai_platform_info.
Keeping compatibility is no longer needed.
We can cleanup code.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/rcar_snd.h | 22 ++-----------
 sound/soc/sh/rcar/core.c | 54 +++++++------------------------
 sound/soc/sh/rcar/rsnd.h |  3 --
 sound/soc/sh/rcar/src.c  | 69 ++++++++++++----------------------------
 sound/soc/sh/rcar/ssi.c  | 51 +----------------------------
 5 files changed, 36 insertions(+), 163 deletions(-)

diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
index 34a3c02a4576d..a03268ec59c37 100644
--- a/include/sound/rcar_snd.h
+++ b/include/sound/rcar_snd.h
@@ -34,40 +34,24 @@
  * B : SSI direction
  */
 #define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
-#define RSND_SSI_PLAY			(1 << 24)
 
 #define RSND_SSI(_dma_id, _pio_irq, _flags)		\
 { .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
-#define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags)	\
-{ .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
 #define RSND_SSI_UNUSED \
-{ .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 }
+{ .dma_id = -1, .pio_irq = -1, .flags = 0 }
 
 struct rsnd_ssi_platform_info {
-	int dai_id;	/* will be removed */
 	int dma_id;
 	int pio_irq;
 	u32 flags;
 };
 
-/*
- * flags
- */
-#define RSND_SCU_USE_HPBIF		(1 << 31) /* it needs RSND_SSI_DEPENDENT */
-
 #define RSND_SRC(rate, _dma_id)						\
-{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
-#define RSND_SRC_SET(rate, _dma_id)		\
-	{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, }
+{ .convert_rate = rate, .dma_id = _dma_id, }
 #define RSND_SRC_UNUSED				\
-	{ .flags = 0, .convert_rate = 0, .dma_id = 0, }
-
-#define rsnd_scu_platform_info	rsnd_src_platform_info
-#define src_info		scu_info
-#define src_info_nr		scu_info_nr
+{ .convert_rate = 0, .dma_id = -1, }
 
 struct rsnd_src_platform_info {
-	u32 flags;
 	u32 convert_rate; /* sampling rate convert */
 	int dma_id; /* for Gen2 SCU */
 };
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 215b668166be6..8ed84703b280e 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -468,10 +468,7 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 	struct rsnd_priv *priv = snd_soc_dai_get_drvdata(dai);
 	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
 	struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
-	struct rsnd_mod *mod = rsnd_ssi_mod_get_frm_dai(priv,
-						rsnd_dai_id(priv, rdai),
-						rsnd_dai_is_play(rdai, io));
-	int ssi_id = rsnd_mod_id(mod);
+	int ssi_id = rsnd_mod_id(rsnd_io_to_mod_ssi(io));
 	int ret;
 	unsigned long flags;
 
@@ -584,7 +581,6 @@ static int rsnd_path_init(struct rsnd_priv *priv,
 			  struct rsnd_dai_stream *io)
 {
 	struct rsnd_mod *mod;
-	struct rsnd_dai_platform_info *dai_info = rdai->info;
 	int ret;
 	int ssi_id = -1;
 	int src_id = -1;
@@ -599,20 +595,10 @@ static int rsnd_path_init(struct rsnd_priv *priv,
 	 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
 	 * using fixed path.
 	 */
-	if (dai_info) {
-		if (rsnd_is_enable_path(io, ssi))
-			ssi_id = rsnd_info_id(priv, io, ssi);
-		if (rsnd_is_enable_path(io, src))
-			src_id = rsnd_info_id(priv, io, src);
-	} else {
-		/* get SSI's ID */
-		mod = rsnd_ssi_mod_get_frm_dai(priv,
-					       rsnd_dai_id(priv, rdai),
-					       rsnd_dai_is_play(rdai, io));
-		if (!mod)
-			return 0;
-		ssi_id = src_id = rsnd_mod_id(mod);
-	}
+	if (rsnd_is_enable_path(io, ssi))
+		ssi_id = rsnd_info_id(priv, io, ssi);
+	if (rsnd_is_enable_path(io, src))
+		src_id = rsnd_info_id(priv, io, src);
 
 	ret = 0;
 
@@ -726,29 +712,14 @@ static int rsnd_dai_probe(struct platform_device *pdev,
 	struct snd_soc_dai_driver *drv;
 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
 	struct rsnd_dai *rdai;
-	struct rsnd_mod *pmod, *cmod;
+	struct rsnd_ssi_platform_info *pmod, *cmod;
 	struct device *dev = rsnd_priv_to_dev(priv);
 	int dai_nr;
 	int i;
 
 	rsnd_of_parse_dai(pdev, of_data, priv);
 
-	/*
-	 * dai_nr should be set via dai_info_nr,
-	 * but allow it to keeping compatible
-	 */
 	dai_nr = info->dai_info_nr;
-	if (!dai_nr) {
-		/* get max dai nr */
-		for (dai_nr = 0; dai_nr < 32; dai_nr++) {
-			pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1);
-			cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0);
-
-			if (!pmod && !cmod)
-				break;
-		}
-	}
-
 	if (!dai_nr) {
 		dev_err(dev, "no dai\n");
 		return -EIO;
@@ -766,11 +737,10 @@ static int rsnd_dai_probe(struct platform_device *pdev,
 	priv->rdai	= rdai;
 
 	for (i = 0; i < dai_nr; i++) {
-		if (info->dai_info)
-			rdai[i].info = &info->dai_info[i];
+		rdai[i].info = &info->dai_info[i];
 
-		pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1);
-		cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0);
+		pmod = rdai[i].info->playback.ssi;
+		cmod = rdai[i].info->capture.ssi;
 
 		/*
 		 *	init rsnd_dai
@@ -788,8 +758,7 @@ static int rsnd_dai_probe(struct platform_device *pdev,
 			drv[i].playback.channels_min	= 2;
 			drv[i].playback.channels_max	= 2;
 
-			if (info->dai_info)
-				rdai[i].playback.info = &info->dai_info[i].playback;
+			rdai[i].playback.info = &info->dai_info[i].playback;
 			rsnd_path_init(priv, &rdai[i], &rdai[i].playback);
 		}
 		if (cmod) {
@@ -798,8 +767,7 @@ static int rsnd_dai_probe(struct platform_device *pdev,
 			drv[i].capture.channels_min	= 2;
 			drv[i].capture.channels_max	= 2;
 
-			if (info->dai_info)
-				rdai[i].capture.info = &info->dai_info[i].capture;
+			rdai[i].capture.info = &info->dai_info[i].capture;
 			rsnd_path_init(priv, &rdai[i], &rdai[i].capture);
 		}
 
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 619d198c7d2e8..061b04cbd7d52 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -379,9 +379,6 @@ int rsnd_ssi_probe(struct platform_device *pdev,
 		   const struct rsnd_of_data *of_data,
 		   struct rsnd_priv *priv);
 struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
-struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
-					  int dai_id, int is_play);
 int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
-int rsnd_ssi_is_play(struct rsnd_mod *mod);
 
 #endif
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 6232b7d307aab..d51c59bf7c474 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -27,12 +27,9 @@ struct rsnd_src {
 #define OTBL_18		(6 << 16)
 #define OTBL_16		(8 << 16)
 
-#define rsnd_src_mode_flags(p) ((p)->info->flags)
 #define rsnd_src_convert_rate(p) ((p)->info->convert_rate)
 #define rsnd_mod_to_src(_mod)				\
 	container_of((_mod), struct rsnd_src, mod)
-#define rsnd_src_hpbif_is_enable(src)	\
-	(rsnd_src_mode_flags(src) & RSND_SCU_USE_HPBIF)
 #define rsnd_src_dma_available(src) \
 	rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod))
 
@@ -80,34 +77,35 @@ struct rsnd_src {
  *
  * This driver request
  * struct rsnd_src_platform_info {
- *	u32 flags;
  *	u32 convert_rate;
+ *	int dma_id;
  * }
  *
- * rsnd_src_hpbif_is_enable() will be true
- * if flags had RSND_SRC_USE_HPBIF,
- * and it controls whether SSIU is used or not.
- *
  * rsnd_src_convert_rate() indicates
  * above convert_rate, and it controls
  * whether SRC is used or not.
  *
  * ex) doesn't use SRC
- * struct rsnd_src_platform_info info = {
- *	.flags = 0,
- *	.convert_rate = 0,
+ * static struct rsnd_dai_platform_info rsnd_dai = {
+ *	.playback = { .ssi = &rsnd_ssi[0], },
  * };
  *
  * ex) uses SRC
- * struct rsnd_src_platform_info info = {
- *	.flags = RSND_SRC_USE_HPBIF,
- *	.convert_rate = 48000,
+ * static struct rsnd_src_platform_info rsnd_src[] = {
+ *	RSND_SCU(48000, 0),
+ *	...
+ * };
+ * static struct rsnd_dai_platform_info rsnd_dai = {
+ *	.playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] },
  * };
  *
  * ex) uses SRC bypass mode
- * struct rsnd_src_platform_info info = {
- *	.flags = RSND_SRC_USE_HPBIF,
- *	.convert_rate = 0,
+ * static struct rsnd_src_platform_info rsnd_src[] = {
+ *	RSND_SCU(0, 0),
+ *	...
+ * };
+ * static struct rsnd_dai_platform_info rsnd_dai = {
+ *	.playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0] },
  * };
  *
  */
@@ -119,24 +117,14 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
 			   struct rsnd_dai *rdai,
 			   struct rsnd_dai_stream *io)
 {
-	struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
-	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
 	int ssi_id = rsnd_mod_id(ssi_mod);
-	int has_src = 0;
 
 	/*
 	 * SSI_MODE0
 	 */
-	if (info->dai_info) {
-		has_src = !!src_mod;
-	} else {
-		struct rsnd_src *src = rsnd_mod_to_src(src_mod);
-		has_src = rsnd_src_hpbif_is_enable(src);
-	}
-
 	rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id),
-		      has_src ? 0 : (1 << ssi_id));
+		      src_mod ? 0 : (1 << ssi_id));
 
 	/*
 	 * SSI_MODE1
@@ -534,21 +522,13 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
 			       struct rsnd_dai_stream *io)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
-	struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod));
 	struct device *dev = rsnd_priv_to_dev(priv);
 	int ret;
-	int is_play;
-
-	if (info->dai_info)
-		is_play = rsnd_info_is_playback(priv, src);
-	else
-		is_play = rsnd_ssi_is_play(ssi);
 
 	ret = rsnd_dma_init(priv,
 			    rsnd_mod_to_dma(mod),
-			    is_play,
+			    rsnd_info_is_playback(priv, src),
 			    src->info->dma_id);
 	if (ret < 0)
 		dev_err(dev, "SRC DMA failed\n");
@@ -699,11 +679,6 @@ int rsnd_src_probe(struct platform_device *pdev,
 		snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i);
 
 		clk = devm_clk_get(dev, name);
-		if (IS_ERR(clk)) {
-			snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i);
-			clk = devm_clk_get(dev, name);
-		}
-
 		if (IS_ERR(clk))
 			return PTR_ERR(clk);
 
@@ -711,12 +686,10 @@ int rsnd_src_probe(struct platform_device *pdev,
 		src->clk = clk;
 
 		ops = &rsnd_src_non_ops;
-		if (rsnd_src_hpbif_is_enable(src)) {
-			if (rsnd_is_gen1(priv))
-				ops = &rsnd_src_gen1_ops;
-			if (rsnd_is_gen2(priv))
-				ops = &rsnd_src_gen2_ops;
-		}
+		if (rsnd_is_gen1(priv))
+			ops = &rsnd_src_gen1_ops;
+		if (rsnd_is_gen2(priv))
+			ops = &rsnd_src_gen2_ops;
 
 		rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i);
 
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 4b7e20603dd7b..77b7b60325c1c 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -422,20 +422,13 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
 	struct device *dev = rsnd_priv_to_dev(priv);
 	int dma_id = ssi->info->dma_id;
-	int is_play;
 	int ret;
 
-	if (info->dai_info)
-		is_play = rsnd_info_is_playback(priv, ssi);
-	else
-		is_play = rsnd_ssi_is_play(&ssi->mod);
-
 	ret = rsnd_dma_init(
 		priv, rsnd_mod_to_dma(mod),
-		is_play,
+		rsnd_info_is_playback(priv, ssi),
 		dma_id);
 
 	if (ret < 0)
@@ -512,41 +505,6 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = {
 /*
  *		ssi mod function
  */
-struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
-					  int dai_id, int is_play)
-{
-	struct rsnd_dai_platform_info *dai_info = NULL;
-	struct rsnd_dai_path_info *path_info = NULL;
-	struct rsnd_ssi_platform_info *target_info = NULL;
-	struct rsnd_ssi *ssi;
-	int i, has_play;
-
-	if (priv->rdai)
-		dai_info = priv->rdai[dai_id].info;
-	if (dai_info)
-		path_info = (is_play) ? &dai_info->playback : &dai_info->capture;
-	if (path_info)
-		target_info = path_info->ssi;
-
-	is_play = !!is_play;
-
-	for_each_rsnd_ssi(ssi, priv, i) {
-		if (target_info == ssi->info)
-			return &ssi->mod;
-
-		/* for compatible */
-		if (rsnd_ssi_dai_id(ssi) != dai_id)
-			continue;
-
-		has_play = rsnd_ssi_is_play(&ssi->mod);
-
-		if (is_play == has_play)
-			return &ssi->mod;
-	}
-
-	return NULL;
-}
-
 struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
 {
 	if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
@@ -562,13 +520,6 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
 	return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
 }
 
-int rsnd_ssi_is_play(struct rsnd_mod *mod)
-{
-	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
-	return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY);
-}
-
 static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi)
 {
 	if (!rsnd_ssi_is_pin_sharing(&ssi->mod))

From 57f174f47e73b4e6f325c9374c17f5fe1602e496 Mon Sep 17 00:00:00 2001
From: Bard Liao <bardliao@realtek.com>
Date: Tue, 6 May 2014 15:56:06 +0800
Subject: [PATCH 77/86] ASoC: rt5640: add default case for unexpected ID

We may read an unexpected value when detemining which codec is attached.
In that case, either a unsupported codec is attached or something wrong
with I2C. The driver will not work properly on both cases. So we return
an error for that.

Signed-off-by: Bard Liao <bardliao@realtek.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5640.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 2133fa0c51148..ddefd5a476d04 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2018,6 +2018,10 @@ static int rt5640_probe(struct snd_soc_codec *codec)
 			rt5639_specific_dapm_routes,
 			ARRAY_SIZE(rt5639_specific_dapm_routes));
 		break;
+	default:
+		dev_err(codec->dev,
+			"The driver is for RT5639 RT5640 or RT5642 only\n");
+		return -ENODEV;
 	}
 
 	return 0;

From 739f9502fdd7c7202123ded842415a0392b7dc40 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 17:43:26 -0700
Subject: [PATCH 78/86] ASoC: rsnd: add rsnd_path_parse() macro

Current R-Car sound supports only SRC/SSI,
but, other module will be supported.
This patch adds rsnd_path_parse() macro to share code

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/sh/rcar/core.c | 43 ++++++++++++++++++++--------------------
 1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 8ed84703b280e..f74d02cb70f1c 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -576,14 +576,27 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
 	.set_fmt	= rsnd_soc_dai_set_fmt,
 };
 
+#define rsnd_path_parse(priv, io, type)				\
+({								\
+	struct rsnd_mod *mod;					\
+	int ret = 0;						\
+	int id = -1;						\
+								\
+	if (rsnd_is_enable_path(io, type)) {			\
+		id = rsnd_info_id(priv, io, type);		\
+		if (id >= 0) {					\
+			mod = rsnd_##type##_mod_get(priv, id);	\
+			ret = rsnd_dai_connect(mod, io);	\
+		}						\
+	}							\
+	ret;							\
+})
+
 static int rsnd_path_init(struct rsnd_priv *priv,
 			  struct rsnd_dai *rdai,
 			  struct rsnd_dai_stream *io)
 {
-	struct rsnd_mod *mod;
 	int ret;
-	int ssi_id = -1;
-	int src_id = -1;
 
 	/*
 	 * Gen1 is created by SRU/SSI, and this SRU is base module of
@@ -595,28 +608,16 @@ static int rsnd_path_init(struct rsnd_priv *priv,
 	 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
 	 * using fixed path.
 	 */
-	if (rsnd_is_enable_path(io, ssi))
-		ssi_id = rsnd_info_id(priv, io, ssi);
-	if (rsnd_is_enable_path(io, src))
-		src_id = rsnd_info_id(priv, io, src);
-
-	ret = 0;
 
 	/* SRC */
-	if (src_id >= 0) {
-		mod = rsnd_src_mod_get(priv, src_id);
-		ret = rsnd_dai_connect(mod, io);
-		if (ret < 0)
-			return ret;
-	}
+	ret = rsnd_path_parse(priv, io, src);
+	if (ret < 0)
+		return ret;
 
 	/* SSI */
-	if (ssi_id >= 0) {
-		mod = rsnd_ssi_mod_get(priv, ssi_id);
-		ret = rsnd_dai_connect(mod, io);
-		if (ret < 0)
-			return ret;
-	}
+	ret = rsnd_path_parse(priv, io, ssi);
+	if (ret < 0)
+		return ret;
 
 	return ret;
 }

From d7bdbc5d9e4e813522f46632527826211270b9d0 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 17:44:14 -0700
Subject: [PATCH 79/86] ASoC: rsnd: add rsnd_get_adinr()

SRC module needs ADINR register settings,
but, it has many similar xxx_ADINR register,
and needs same settings.
This patch adds rsnd_get_adinr() to sharing code.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/sh/rcar/core.c | 26 ++++++++++++++++++++++++++
 sound/soc/sh/rcar/rsnd.h |  1 +
 sound/soc/sh/rcar/src.c  | 26 +++-----------------------
 3 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index f74d02cb70f1c..e47aa53471b11 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -309,6 +309,32 @@ void  rsnd_dma_quit(struct rsnd_priv *priv,
 	dma->chan = NULL;
 }
 
+/*
+ *	settting function
+ */
+u32 rsnd_get_adinr(struct rsnd_mod *mod)
+{
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 adinr = runtime->channels;
+
+	switch (runtime->sample_bits) {
+	case 16:
+		adinr |= (8 << 16);
+		break;
+	case 32:
+		adinr |= (0 << 16);
+		break;
+	default:
+		dev_warn(dev, "not supported sample bits\n");
+		return 0;
+	}
+
+	return adinr;
+}
+
 /*
  *	rsnd_dai functions
  */
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 061b04cbd7d52..fee3ec21aaeb6 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -136,6 +136,7 @@ void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
 		enum rsnd_reg reg, u32 data);
 void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
 		    u32 mask, u32 data);
+u32 rsnd_get_adinr(struct rsnd_mod *mod);
 
 /*
  *	R-Car DMA
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index d51c59bf7c474..c90c36d41799f 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -18,15 +18,6 @@ struct rsnd_src {
 
 #define RSND_SRC_NAME_SIZE 16
 
-/*
- * ADINR
- */
-#define OTBL_24		(0 << 16)
-#define OTBL_22		(2 << 16)
-#define OTBL_20		(4 << 16)
-#define OTBL_18		(6 << 16)
-#define OTBL_16		(8 << 16)
-
 #define rsnd_src_convert_rate(p) ((p)->info->convert_rate)
 #define rsnd_mod_to_src(_mod)				\
 	container_of((_mod), struct rsnd_src, mod)
@@ -197,7 +188,6 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 	u32 convert_rate = rsnd_src_convert_rate(src);
-	u32 adinr = runtime->channels;
 	u32 fsrate = 0;
 
 	if (convert_rate)
@@ -214,17 +204,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
 	rsnd_mod_write(mod, SRC_SRCIR, 1);
 
 	/* Set channel number and output bit length */
-	switch (runtime->sample_bits) {
-	case 16:
-		adinr |= OTBL_16;
-		break;
-	case 32:
-		adinr |= OTBL_24;
-		break;
-	default:
-		return -EIO;
-	}
-	rsnd_mod_write(mod, SRC_ADINR, adinr);
+	rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod));
 
 	/* Enable the initial value of IFS */
 	if (fsrate) {
@@ -487,8 +467,8 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
-	rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR));
-	rsnd_mod_write(mod, SSI_BUSIF_MODE,  rsnd_mod_read(mod, SRC_BUSIF_MODE));
+	rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod));
+	rsnd_mod_write(mod, SSI_BUSIF_MODE,  1);
 
 	rsnd_mod_write(mod, SRC_SRCCR, 0x00011110);
 

From b42fccf69cd7153d1158c85137ec718d7309e074 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 17:44:29 -0700
Subject: [PATCH 80/86] ASoC: rsnd: remove duplicate parameter from
 rsnd_mod_ops

Now, it can get rsnd_dai_stream pointer from rsnd_mod.
Remove duplicate parameter from rsnd_mod_ops

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/sh/rcar/core.c | 10 ++---
 sound/soc/sh/rcar/rsnd.h | 24 ++++-------
 sound/soc/sh/rcar/src.c  | 91 +++++++++++++++++-----------------------
 sound/soc/sh/rcar/ssi.c  | 34 +++++++--------
 4 files changed, 65 insertions(+), 94 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index e47aa53471b11..86c9b78d8df13 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -338,19 +338,19 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 /*
  *	rsnd_dai functions
  */
-#define __rsnd_mod_call(mod, func, rdai, io)			\
+#define __rsnd_mod_call(mod, func, rdai)			\
 ({								\
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);		\
 	struct device *dev = rsnd_priv_to_dev(priv);		\
 	dev_dbg(dev, "%s [%d] %s\n",				\
 		rsnd_mod_name(mod), rsnd_mod_id(mod), #func);	\
-	(mod)->ops->func(mod, rdai, io);			\
+	(mod)->ops->func(mod, rdai);				\
 })
 
-#define rsnd_mod_call(mod, func, rdai, io)	\
+#define rsnd_mod_call(mod, func, rdai)	\
 	(!(mod) ? -ENODEV :			\
 	 !((mod)->ops->func) ? 0 :		\
-	 __rsnd_mod_call(mod, func, (rdai), (io)))
+	 __rsnd_mod_call(mod, func, (rdai)))
 
 #define rsnd_dai_call(rdai, io, fn)				\
 ({								\
@@ -360,7 +360,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 		mod = (io)->mod[i];				\
 		if (!mod)					\
 			continue;				\
-		ret = rsnd_mod_call(mod, fn, (rdai), (io));	\
+		ret = rsnd_mod_call(mod, fn, (rdai));		\
 		if (ret < 0)					\
 			break;					\
 	}							\
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index fee3ec21aaeb6..6156ceebd58be 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -172,23 +172,17 @@ enum rsnd_mod_type {
 struct rsnd_mod_ops {
 	char *name;
 	int (*probe)(struct rsnd_mod *mod,
-		     struct rsnd_dai *rdai,
-		     struct rsnd_dai_stream *io);
+		     struct rsnd_dai *rdai);
 	int (*remove)(struct rsnd_mod *mod,
-		      struct rsnd_dai *rdai,
-		      struct rsnd_dai_stream *io);
+		      struct rsnd_dai *rdai);
 	int (*init)(struct rsnd_mod *mod,
-		    struct rsnd_dai *rdai,
-		    struct rsnd_dai_stream *io);
+		    struct rsnd_dai *rdai);
 	int (*quit)(struct rsnd_mod *mod,
-		    struct rsnd_dai *rdai,
-		    struct rsnd_dai_stream *io);
+		    struct rsnd_dai *rdai);
 	int (*start)(struct rsnd_mod *mod,
-		     struct rsnd_dai *rdai,
-		     struct rsnd_dai_stream *io);
+		     struct rsnd_dai *rdai);
 	int (*stop)(struct rsnd_mod *mod,
-		    struct rsnd_dai *rdai,
-		    struct rsnd_dai_stream *io);
+		    struct rsnd_dai *rdai);
 };
 
 struct rsnd_dai_stream;
@@ -365,11 +359,9 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
 				   struct rsnd_dai_stream *io,
 				   struct snd_pcm_runtime *runtime);
 int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
-			   struct rsnd_dai *rdai,
-			   struct rsnd_dai_stream *io);
+			   struct rsnd_dai *rdai);
 int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod,
-			    struct rsnd_dai *rdai,
-			    struct rsnd_dai_stream *io);
+			    struct rsnd_dai *rdai);
 
 #define rsnd_src_nr(priv) ((priv)->src_nr)
 
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index c90c36d41799f..035eda2de239d 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -105,9 +105,9 @@ struct rsnd_src {
  *		Gen1/Gen2 common functions
  */
 int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
-			   struct rsnd_dai *rdai,
-			   struct rsnd_dai_stream *io)
+			   struct rsnd_dai *rdai)
 {
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod);
 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
 	int ssi_id = rsnd_mod_id(ssi_mod);
 
@@ -145,8 +145,7 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
 }
 
 int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod,
-			    struct rsnd_dai *rdai,
-			    struct rsnd_dai_stream *io)
+			    struct rsnd_dai *rdai)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
 
@@ -182,9 +181,9 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
 }
 
 static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
-				     struct rsnd_dai *rdai,
-				     struct rsnd_dai_stream *io)
+				     struct rsnd_dai *rdai)
 {
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 	u32 convert_rate = rsnd_src_convert_rate(src);
@@ -221,8 +220,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_init(struct rsnd_mod *mod,
-			 struct rsnd_dai *rdai,
-			 struct rsnd_dai_stream *io)
+			 struct rsnd_dai *rdai)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
@@ -232,8 +230,7 @@ static int rsnd_src_init(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_quit(struct rsnd_mod *mod,
-			 struct rsnd_dai *rdai,
-			 struct rsnd_dai_stream *io)
+			 struct rsnd_dai *rdai)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
@@ -243,8 +240,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_start(struct rsnd_mod *mod,
-			  struct rsnd_dai *rdai,
-			  struct rsnd_dai_stream *io)
+			  struct rsnd_dai *rdai)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
@@ -262,8 +258,7 @@ static int rsnd_src_start(struct rsnd_mod *mod,
 
 
 static int rsnd_src_stop(struct rsnd_mod *mod,
-			 struct rsnd_dai *rdai,
-			 struct rsnd_dai_stream *io)
+			 struct rsnd_dai *rdai)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
@@ -281,9 +276,9 @@ static struct rsnd_mod_ops rsnd_src_non_ops = {
  *		Gen1 functions
  */
 static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
-				   struct rsnd_dai *rdai,
-				   struct rsnd_dai_stream *io)
+				   struct rsnd_dai *rdai)
 {
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	struct src_route_config {
 		u32 mask;
 		int shift;
@@ -319,9 +314,9 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod,
-					    struct rsnd_dai *rdai,
-					    struct rsnd_dai_stream *io)
+					    struct rsnd_dai *rdai)
 {
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
@@ -378,12 +373,11 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod,
-					  struct rsnd_dai *rdai,
-					  struct rsnd_dai_stream *io)
+					  struct rsnd_dai *rdai)
 {
 	int ret;
 
-	ret = rsnd_src_set_convert_rate(mod, rdai, io);
+	ret = rsnd_src_set_convert_rate(mod, rdai);
 	if (ret < 0)
 		return ret;
 
@@ -400,24 +394,23 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_init_gen1(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	int ret;
 
-	ret = rsnd_src_init(mod, rdai, io);
+	ret = rsnd_src_init(mod, rdai);
 	if (ret < 0)
 		return ret;
 
-	ret = rsnd_src_set_route_gen1(mod, rdai, io);
+	ret = rsnd_src_set_route_gen1(mod, rdai);
 	if (ret < 0)
 		return ret;
 
-	ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io);
+	ret = rsnd_src_set_convert_rate_gen1(mod, rdai);
 	if (ret < 0)
 		return ret;
 
-	ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io);
+	ret = rsnd_src_set_convert_timing_gen1(mod, rdai);
 	if (ret < 0)
 		return ret;
 
@@ -425,25 +418,23 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_start_gen1(struct rsnd_mod *mod,
-			       struct rsnd_dai *rdai,
-			       struct rsnd_dai_stream *io)
+			       struct rsnd_dai *rdai)
 {
 	int id = rsnd_mod_id(mod);
 
 	rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id));
 
-	return rsnd_src_start(mod, rdai, io);
+	return rsnd_src_start(mod, rdai);
 }
 
 static int rsnd_src_stop_gen1(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	int id = rsnd_mod_id(mod);
 
 	rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0);
 
-	return rsnd_src_stop(mod, rdai, io);
+	return rsnd_src_stop(mod, rdai);
 }
 
 static struct rsnd_mod_ops rsnd_src_gen1_ops = {
@@ -458,12 +449,11 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
  *		Gen2 functions
  */
 static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
-					  struct rsnd_dai *rdai,
-					  struct rsnd_dai_stream *io)
+					  struct rsnd_dai *rdai)
 {
 	int ret;
 
-	ret = rsnd_src_set_convert_rate(mod, rdai, io);
+	ret = rsnd_src_set_convert_rate(mod, rdai);
 	if (ret < 0)
 		return ret;
 
@@ -479,9 +469,9 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod,
-					    struct rsnd_dai *rdai,
-					    struct rsnd_dai_stream *io)
+					    struct rsnd_dai *rdai)
 {
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 	u32 convert_rate = rsnd_src_convert_rate(src);
@@ -498,8 +488,7 @@ static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
-			       struct rsnd_dai *rdai,
-			       struct rsnd_dai_stream *io)
+			       struct rsnd_dai *rdai)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -517,8 +506,7 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_remove_gen2(struct rsnd_mod *mod,
-				struct rsnd_dai *rdai,
-				struct rsnd_dai_stream *io)
+				struct rsnd_dai *rdai)
 {
 	rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
 
@@ -526,20 +514,19 @@ static int rsnd_src_remove_gen2(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_init_gen2(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	int ret;
 
-	ret = rsnd_src_init(mod, rdai, io);
+	ret = rsnd_src_init(mod, rdai);
 	if (ret < 0)
 		return ret;
 
-	ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io);
+	ret = rsnd_src_set_convert_rate_gen2(mod, rdai);
 	if (ret < 0)
 		return ret;
 
-	ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io);
+	ret = rsnd_src_set_convert_timing_gen2(mod, rdai);
 	if (ret < 0)
 		return ret;
 
@@ -547,8 +534,7 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod,
 }
 
 static int rsnd_src_start_gen2(struct rsnd_mod *mod,
-			       struct rsnd_dai *rdai,
-			       struct rsnd_dai_stream *io)
+			       struct rsnd_dai *rdai)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
@@ -557,12 +543,11 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
 	rsnd_mod_write(mod, SSI_CTRL, 0x1);
 	rsnd_mod_write(mod, SRC_CTRL, 0x11);
 
-	return rsnd_src_start(mod, rdai, io);
+	return rsnd_src_start(mod, rdai);
 }
 
 static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
 
@@ -571,7 +556,7 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
 
 	rsnd_dma_stop(rsnd_mod_to_dma(&src->mod));
 
-	return rsnd_src_stop(mod, rdai, io);
+	return rsnd_src_stop(mod, rdai);
 }
 
 static struct rsnd_mod_ops rsnd_src_gen2_ops = {
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 77b7b60325c1c..4b13edb26c4ae 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -240,10 +240,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
  *	SSI mod common functions
  */
 static int rsnd_ssi_init(struct rsnd_mod *mod,
-			 struct rsnd_dai *rdai,
-			 struct rsnd_dai_stream *io)
+			 struct rsnd_dai *rdai)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	u32 cr;
 
@@ -287,14 +287,13 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
 	ssi->cr_own	= cr;
 	ssi->err	= -1; /* ignore 1st error */
 
-	rsnd_src_ssi_mode_init(mod, rdai, io);
+	rsnd_src_ssi_mode_init(mod, rdai);
 
 	return 0;
 }
 
 static int rsnd_ssi_quit(struct rsnd_mod *mod,
-			 struct rsnd_dai *rdai,
-			 struct rsnd_dai_stream *io)
+			 struct rsnd_dai *rdai)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
@@ -359,8 +358,7 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
 }
 
 static int rsnd_ssi_pio_probe(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 	struct device *dev = rsnd_priv_to_dev(priv);
@@ -379,15 +377,15 @@ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod,
 }
 
 static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 
 	/* enable PIO IRQ */
 	ssi->cr_etc = UIEN | OIEN | DIEN;
 
-	rsnd_src_enable_ssi_irq(mod, rdai, io);
+	rsnd_src_enable_ssi_irq(mod, rdai);
 
 	rsnd_ssi_hw_start(ssi, rdai, io);
 
@@ -395,8 +393,7 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
 }
 
 static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
-			     struct rsnd_dai *rdai,
-			     struct rsnd_dai_stream *io)
+			     struct rsnd_dai *rdai)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 
@@ -417,8 +414,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
 };
 
 static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
-			  struct rsnd_dai *rdai,
-			  struct rsnd_dai_stream *io)
+			  struct rsnd_dai *rdai)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
@@ -438,8 +434,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
 }
 
 static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
-			       struct rsnd_dai *rdai,
-			       struct rsnd_dai_stream *io)
+			       struct rsnd_dai *rdai)
 {
 	rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
 
@@ -447,11 +442,11 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
 }
 
 static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
-			      struct rsnd_dai *rdai,
-			      struct rsnd_dai_stream *io)
+			      struct rsnd_dai *rdai)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 	struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 
 	/* enable DMA transfer */
 	ssi->cr_etc = DMEN;
@@ -468,8 +463,7 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
 }
 
 static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
-			     struct rsnd_dai *rdai,
-			     struct rsnd_dai_stream *io)
+			     struct rsnd_dai *rdai)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 	struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);

From 68b6af3656a1f3303cca094a19e26653fad1853a Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 17:44:41 -0700
Subject: [PATCH 81/86] ASoC: rsnd: enable to use multi parameter on
 rsnd_dai_call/rsnd_mod_call

rsnd_mod_ops would like to come to use multi parameter.
modify macro to enable it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/sh/rcar/core.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 86c9b78d8df13..378985b028ef6 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -338,7 +338,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 /*
  *	rsnd_dai functions
  */
-#define __rsnd_mod_call(mod, func, rdai)			\
+#define __rsnd_mod_call(mod, func, rdai...)			\
 ({								\
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);		\
 	struct device *dev = rsnd_priv_to_dev(priv);		\
@@ -347,12 +347,12 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 	(mod)->ops->func(mod, rdai);				\
 })
 
-#define rsnd_mod_call(mod, func, rdai)	\
+#define rsnd_mod_call(mod, func, rdai...)	\
 	(!(mod) ? -ENODEV :			\
 	 !((mod)->ops->func) ? 0 :		\
-	 __rsnd_mod_call(mod, func, (rdai)))
+	 __rsnd_mod_call(mod, func, rdai))
 
-#define rsnd_dai_call(rdai, io, fn)				\
+#define rsnd_dai_call(fn, io, rdai...)				\
 ({								\
 	struct rsnd_mod *mod;					\
 	int ret = 0, i;						\
@@ -360,7 +360,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod)
 		mod = (io)->mod[i];				\
 		if (!mod)					\
 			continue;				\
-		ret = rsnd_mod_call(mod, fn, (rdai));		\
+		ret = rsnd_mod_call(mod, fn, rdai);		\
 		if (ret < 0)					\
 			break;					\
 	}							\
@@ -510,20 +510,20 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (ret < 0)
 			goto dai_trigger_end;
 
-		ret = rsnd_dai_call(rdai, io, init);
+		ret = rsnd_dai_call(init, io, rdai);
 		if (ret < 0)
 			goto dai_trigger_end;
 
-		ret = rsnd_dai_call(rdai, io, start);
+		ret = rsnd_dai_call(start, io, rdai);
 		if (ret < 0)
 			goto dai_trigger_end;
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		ret = rsnd_dai_call(rdai, io, stop);
+		ret = rsnd_dai_call(stop, io, rdai);
 		if (ret < 0)
 			goto dai_trigger_end;
 
-		ret = rsnd_dai_call(rdai, io, quit);
+		ret = rsnd_dai_call(quit, io, rdai);
 		if (ret < 0)
 			goto dai_trigger_end;
 
@@ -951,11 +951,11 @@ static int rsnd_probe(struct platform_device *pdev)
 	}
 
 	for_each_rsnd_dai(rdai, priv, i) {
-		ret = rsnd_dai_call(rdai, &rdai->playback, probe);
+		ret = rsnd_dai_call(probe, &rdai->playback, rdai);
 		if (ret)
 			return ret;
 
-		ret = rsnd_dai_call(rdai, &rdai->capture, probe);
+		ret = rsnd_dai_call(probe, &rdai->capture, rdai);
 		if (ret)
 			return ret;
 	}
@@ -998,11 +998,11 @@ static int rsnd_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 
 	for_each_rsnd_dai(rdai, priv, i) {
-		ret = rsnd_dai_call(rdai, &rdai->playback, remove);
+		ret = rsnd_dai_call(remove, &rdai->playback, rdai);
 		if (ret)
 			return ret;
 
-		ret = rsnd_dai_call(rdai, &rdai->capture, remove);
+		ret = rsnd_dai_call(remove, &rdai->capture, rdai);
 		if (ret)
 			return ret;
 	}

From bff58ea4f43d9b4a9fd6fb05fabc8f50f68131f5 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 8 May 2014 17:44:49 -0700
Subject: [PATCH 82/86] ASoC: rsnd: add DVC support

This patch adds DVC (Digital Volume Controller)
support which is member of CMD unit.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/rcar_snd.h   |  10 ++
 sound/soc/sh/rcar/Makefile |   2 +-
 sound/soc/sh/rcar/adg.c    |  18 +++
 sound/soc/sh/rcar/core.c   |  20 +++
 sound/soc/sh/rcar/dvc.c    | 273 +++++++++++++++++++++++++++++++++++++
 sound/soc/sh/rcar/gen.c    |  11 ++
 sound/soc/sh/rcar/rsnd.h   |  40 ++++++
 sound/soc/sh/rcar/src.c    |   4 +-
 8 files changed, 376 insertions(+), 2 deletions(-)
 create mode 100644 sound/soc/sh/rcar/dvc.c

diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
index a03268ec59c37..f4a706f82cb73 100644
--- a/include/sound/rcar_snd.h
+++ b/include/sound/rcar_snd.h
@@ -56,9 +56,17 @@ struct rsnd_src_platform_info {
 	int dma_id; /* for Gen2 SCU */
 };
 
+/*
+ * flags
+ */
+struct rsnd_dvc_platform_info {
+	u32 flags;
+};
+
 struct rsnd_dai_path_info {
 	struct rsnd_ssi_platform_info *ssi;
 	struct rsnd_src_platform_info *src;
+	struct rsnd_dvc_platform_info *dvc;
 };
 
 struct rsnd_dai_platform_info {
@@ -83,6 +91,8 @@ struct rcar_snd_info {
 	int ssi_info_nr;
 	struct rsnd_src_platform_info *src_info;
 	int src_info_nr;
+	struct rsnd_dvc_platform_info *dvc_info;
+	int dvc_info_nr;
 	struct rsnd_dai_platform_info *dai_info;
 	int dai_info_nr;
 	int (*start)(int id);
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
index 7d0051ced8383..9ac536429800d 100644
--- a/sound/soc/sh/rcar/Makefile
+++ b/sound/soc/sh/rcar/Makefile
@@ -1,2 +1,2 @@
-snd-soc-rcar-objs	:= core.o gen.o src.o adg.o ssi.o
+snd-soc-rcar-objs	:= core.o gen.o src.o adg.o ssi.o dvc.o
 obj-$(CONFIG_SND_SOC_RCAR)	+= snd-soc-rcar.o
\ No newline at end of file
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 41556b2ef21e8..fc41a0e8b09fd 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -57,6 +57,24 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
 	return (0x6 + ws) << 8;
 }
 
+int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai,
+				 struct rsnd_mod *mod,
+				 struct rsnd_dai_stream *io)
+{
+	int id = rsnd_mod_id(mod);
+	int shift = (id % 2) ? 16 : 0;
+	u32 mask, val;
+
+	val = rsnd_adg_ssi_ws_timing_gen2(io);
+
+	val  = val	<< shift;
+	mask = 0xffff	<< shift;
+
+	rsnd_mod_bset(mod, CMDOUT_TIMSEL, mask, val);
+
+	return 0;
+}
+
 static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai,
 					struct rsnd_mod *mod,
 					struct rsnd_dai_stream *io,
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 378985b028ef6..1f6981a563542 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -645,6 +645,11 @@ static int rsnd_path_init(struct rsnd_priv *priv,
 	if (ret < 0)
 		return ret;
 
+	/* DVC */
+	ret = rsnd_path_parse(priv, io, dvc);
+	if (ret < 0)
+		return ret;
+
 	return ret;
 }
 
@@ -869,6 +874,20 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
 
 static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+	struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+	struct rsnd_dai *rdai;
+	int i, ret;
+
+	for_each_rsnd_dai(rdai, priv, i) {
+		ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd);
+		if (ret)
+			return ret;
+
+		ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd);
+		if (ret)
+			return ret;
+	}
+
 	return snd_pcm_lib_preallocate_pages_for_all(
 		rtd->pcm,
 		SNDRV_DMA_TYPE_DEV,
@@ -908,6 +927,7 @@ static int rsnd_probe(struct platform_device *pdev)
 		rsnd_gen_probe,
 		rsnd_ssi_probe,
 		rsnd_src_probe,
+		rsnd_dvc_probe,
 		rsnd_adg_probe,
 		rsnd_dai_probe,
 	};
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
new file mode 100644
index 0000000000000..74769b1be005d
--- /dev/null
+++ b/sound/soc/sh/rcar/dvc.c
@@ -0,0 +1,273 @@
+/*
+ * Renesas R-Car DVC support
+ *
+ * Copyright (C) 2014 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * 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 "rsnd.h"
+
+#define RSND_DVC_NAME_SIZE	16
+#define RSND_DVC_VOLUME_MAX	100
+#define RSND_DVC_VOLUME_NUM	2
+struct rsnd_dvc {
+	struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
+	struct rsnd_mod mod;
+	struct clk *clk;
+	long volume[RSND_DVC_VOLUME_NUM];
+};
+
+#define rsnd_mod_to_dvc(_mod)	\
+	container_of((_mod), struct rsnd_dvc, mod)
+
+#define for_each_rsnd_dvc(pos, priv, i)				\
+	for ((i) = 0;						\
+	     ((i) < rsnd_dvc_nr(priv)) &&			\
+	     ((pos) = (struct rsnd_dvc *)(priv)->dvc + i);	\
+	     i++)
+
+static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
+{
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	u32 max = (0x00800000 - 1);
+	u32 vol[RSND_DVC_VOLUME_NUM];
+	int i;
+
+	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
+		vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i];
+
+	rsnd_mod_write(mod, DVC_VOL0R, vol[0]);
+	rsnd_mod_write(mod, DVC_VOL1R, vol[1]);
+}
+
+static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
+			 struct rsnd_dai *rdai)
+{
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod);
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod);
+	struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod);
+	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	int dvc_id = rsnd_mod_id(dvc_mod);
+	int src_id = rsnd_mod_id(src_mod);
+	u32 route[] = {
+		[0] = 0x30000,
+		[1] = 0x30001,
+		[2] = 0x40000,
+		[3] = 0x10000,
+		[4] = 0x20000,
+		[5] = 0x40100
+	};
+
+	if (src_id >= ARRAY_SIZE(route)) {
+		dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id);
+		return -EINVAL;
+	}
+
+	clk_prepare_enable(dvc->clk);
+
+	/*
+	 * fixme
+	 * it doesn't support CTU/MIX
+	 */
+	rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]);
+
+	rsnd_mod_write(dvc_mod, DVC_SWRSR, 0);
+	rsnd_mod_write(dvc_mod, DVC_SWRSR, 1);
+
+	rsnd_mod_write(dvc_mod, DVC_DVUIR, 1);
+
+	rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod));
+
+	/*  enable Volume  */
+	rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100);
+
+	/* ch0/ch1 Volume */
+	rsnd_dvc_volume_update(dvc_mod);
+
+	rsnd_mod_write(dvc_mod, DVC_DVUIR, 0);
+
+	rsnd_mod_write(dvc_mod, DVC_DVUER, 1);
+
+	rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io);
+
+	return 0;
+}
+
+static int rsnd_dvc_quit(struct rsnd_mod *mod,
+			 struct rsnd_dai *rdai)
+{
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+
+	clk_disable_unprepare(dvc->clk);
+
+	return 0;
+}
+
+static int rsnd_dvc_start(struct rsnd_mod *mod,
+			  struct rsnd_dai *rdai)
+{
+	rsnd_mod_write(mod, CMD_CTRL, 0x10);
+
+	return 0;
+}
+
+static int rsnd_dvc_stop(struct rsnd_mod *mod,
+			 struct rsnd_dai *rdai)
+{
+	rsnd_mod_write(mod, CMD_CTRL, 0);
+
+	return 0;
+}
+
+static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
+			       struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = RSND_DVC_VOLUME_NUM;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = RSND_DVC_VOLUME_MAX;
+
+	return 0;
+}
+
+static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	int i;
+
+	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
+		ucontrol->value.integer.value[i] = dvc->volume[i];
+
+	return 0;
+}
+
+static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
+	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+	int i, change = 0;
+
+	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
+		if (ucontrol->value.integer.value[i] < 0 ||
+		    ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX)
+			return -EINVAL;
+
+		change |= (ucontrol->value.integer.value[i] != dvc->volume[i]);
+	}
+
+	if (change) {
+		for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
+			dvc->volume[i] = ucontrol->value.integer.value[i];
+
+		rsnd_dvc_volume_update(mod);
+	}
+
+	return change;
+}
+
+static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
+			    struct rsnd_dai *rdai,
+			    struct snd_soc_pcm_runtime *rtd)
+{
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_kcontrol *kctrl;
+	static struct snd_kcontrol_new knew = {
+		.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name		= "Playback Volume",
+		.info		= rsnd_dvc_volume_info,
+		.get		= rsnd_dvc_volume_get,
+		.put		= rsnd_dvc_volume_put,
+	};
+	int ret;
+
+	if (!rsnd_dai_is_play(rdai, io)) {
+		dev_err(dev, "DVC%d is connected to Capture DAI\n",
+			rsnd_mod_id(mod));
+		return -EINVAL;
+	}
+
+	kctrl = snd_ctl_new1(&knew, mod);
+	if (!kctrl)
+		return -ENOMEM;
+
+	ret = snd_ctl_add(card, kctrl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct rsnd_mod_ops rsnd_dvc_ops = {
+	.name		= "dvc (gen2)",
+	.init		= rsnd_dvc_init,
+	.quit		= rsnd_dvc_quit,
+	.start		= rsnd_dvc_start,
+	.stop		= rsnd_dvc_stop,
+	.pcm_new	= rsnd_dvc_pcm_new,
+};
+
+struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
+{
+	if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
+		id = 0;
+
+	return &((struct rsnd_dvc *)(priv->dvc) + id)->mod;
+}
+
+int rsnd_dvc_probe(struct platform_device *pdev,
+		   const struct rsnd_of_data *of_data,
+		   struct rsnd_priv *priv)
+{
+	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct rsnd_dvc *dvc;
+	struct clk *clk;
+	char name[RSND_DVC_NAME_SIZE];
+	int i, nr;
+
+	nr = info->dvc_info_nr;
+	if (!nr)
+		return 0;
+
+	/* This driver doesn't support Gen1 at this point */
+	if (rsnd_is_gen1(priv)) {
+		dev_warn(dev, "CMD is not supported on Gen1\n");
+		return -EINVAL;
+	}
+
+	dvc	= devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
+	if (!dvc) {
+		dev_err(dev, "CMD allocate failed\n");
+		return -ENOMEM;
+	}
+
+	priv->dvc_nr	= nr;
+	priv->dvc	= dvc;
+
+	for_each_rsnd_dvc(dvc, priv, i) {
+		snprintf(name, RSND_DVC_NAME_SIZE, "dvc.%d", i);
+
+		clk = devm_clk_get(dev, name);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+
+		dvc->info = &info->dvc_info[i];
+		dvc->clk  = clk;
+
+		rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i);
+
+		dev_dbg(dev, "CMD%d probed\n", i);
+	}
+
+	return 0;
+}
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 50a1ef3eb1c6e..a135d4c9d0803 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -181,6 +181,8 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
 		RSND_GEN2_M_REG(gen, SCU,	SRC_BUSIF_MODE,	0x0,	0x20),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_ROUTE_MODE0,0xc,	0x20),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_CTRL,	0x10,	0x20),
+		RSND_GEN2_M_REG(gen, SCU,	CMD_ROUTE_SLCT,	0x18c,	0x20),
+		RSND_GEN2_M_REG(gen, SCU,	CMD_CTRL,	0x190,	0x20),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_SWRSR,	0x200,	0x40),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_SRCIR,	0x204,	0x40),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_ADINR,	0x214,	0x40),
@@ -189,6 +191,14 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
 		RSND_GEN2_M_REG(gen, SCU,	SRC_SRCCR,	0x224,	0x40),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_BSDSR,	0x22c,	0x40),
 		RSND_GEN2_M_REG(gen, SCU,	SRC_BSISR,	0x238,	0x40),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_SWRSR,	0xe00,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUIR,	0xe04,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_ADINR,	0xe08,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUCR,	0xe10,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_ZCMCR,	0xe14,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_VOL0R,	0xe28,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_VOL1R,	0xe2c,	0x100),
+		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUER,	0xe48,	0x100),
 
 		RSND_GEN2_S_REG(gen, ADG,	BRRA,		0x00),
 		RSND_GEN2_S_REG(gen, ADG,	BRRB,		0x04),
@@ -207,6 +217,7 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
 		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL2,	0x50),
 		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL3,	0x54),
 		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL4,	0x58),
+		RSND_GEN2_S_REG(gen, ADG,	CMDOUT_TIMSEL,	0x5c),
 
 		RSND_GEN2_M_REG(gen, SSI,	SSICR,		0x00,	0x40),
 		RSND_GEN2_M_REG(gen, SSI,	SSISR,		0x04,	0x40),
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 6156ceebd58be..5aa790170b01a 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -44,6 +44,15 @@ enum rsnd_reg {
 	RSND_REG_SRC_IFSCR,
 	RSND_REG_SRC_IFSVR,
 	RSND_REG_SRC_SRCCR,
+	RSND_REG_CMD_ROUTE_SLCT,
+	RSND_REG_DVC_SWRSR,
+	RSND_REG_DVC_DVUIR,
+	RSND_REG_DVC_ADINR,
+	RSND_REG_DVC_DVUCR,
+	RSND_REG_DVC_ZCMCR,
+	RSND_REG_DVC_VOL0R,
+	RSND_REG_DVC_VOL1R,
+	RSND_REG_DVC_DVUER,
 
 	/* ADG */
 	RSND_REG_BRRA,
@@ -79,6 +88,8 @@ enum rsnd_reg {
 	RSND_REG_SHARE17,
 	RSND_REG_SHARE18,
 	RSND_REG_SHARE19,
+	RSND_REG_SHARE20,
+	RSND_REG_SHARE21,
 
 	RSND_REG_MAX,
 };
@@ -114,6 +125,8 @@ enum rsnd_reg {
 #define RSND_REG_SRCOUT_TIMSEL3		RSND_REG_SHARE17
 #define RSND_REG_SRCOUT_TIMSEL4		RSND_REG_SHARE18
 #define RSND_REG_AUDIO_CLK_SEL2		RSND_REG_SHARE19
+#define RSND_REG_CMD_CTRL		RSND_REG_SHARE20
+#define RSND_REG_CMDOUT_TIMSEL		RSND_REG_SHARE21
 
 struct rsnd_of_data;
 struct rsnd_priv;
@@ -166,6 +179,7 @@ void  rsnd_dma_quit(struct rsnd_priv *priv,
 enum rsnd_mod_type {
 	RSND_MOD_SRC = 0,
 	RSND_MOD_SSI,
+	RSND_MOD_DVC,
 	RSND_MOD_MAX,
 };
 
@@ -183,6 +197,9 @@ struct rsnd_mod_ops {
 		     struct rsnd_dai *rdai);
 	int (*stop)(struct rsnd_mod *mod,
 		    struct rsnd_dai *rdai);
+	int (*pcm_new)(struct rsnd_mod *mod,
+		       struct rsnd_dai *rdai,
+		       struct snd_soc_pcm_runtime *rtd);
 };
 
 struct rsnd_dai_stream;
@@ -223,6 +240,7 @@ struct rsnd_dai_stream {
 };
 #define rsnd_io_to_mod_ssi(io)	((io)->mod[RSND_MOD_SSI])
 #define rsnd_io_to_mod_src(io)	((io)->mod[RSND_MOD_SRC])
+#define rsnd_io_to_mod_dvc(io)	((io)->mod[RSND_MOD_DVC])
 
 struct rsnd_dai {
 	char name[RSND_DAI_NAME_SIZE];
@@ -286,6 +304,9 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
 int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
 				     struct rsnd_dai *rdai,
 				     struct rsnd_dai_stream *io);
+int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai,
+				 struct rsnd_mod *mod,
+				 struct rsnd_dai_stream *io);
 
 /*
  *	R-Car sound priv
@@ -322,6 +343,12 @@ struct rsnd_priv {
 	void *ssi;
 	int ssi_nr;
 
+	/*
+	 * below value will be filled on rsnd_dvc_probe()
+	 */
+	void *dvc;
+	int dvc_nr;
+
 	/*
 	 * below value will be filled on rsnd_dai_probe()
 	 */
@@ -374,4 +401,17 @@ int rsnd_ssi_probe(struct platform_device *pdev,
 struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
 int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
 
+/*
+ *	R-Car DVC
+ */
+int rsnd_dvc_probe(struct platform_device *pdev,
+		   const struct rsnd_of_data *of_data,
+		   struct rsnd_priv *priv);
+void rsnd_dvc_remove(struct platform_device *pdev,
+		     struct rsnd_priv *priv);
+struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
+
+#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
+
+
 #endif
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 035eda2de239d..7da87cde0bc32 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -536,12 +536,14 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod,
 static int rsnd_src_start_gen2(struct rsnd_mod *mod,
 			       struct rsnd_dai *rdai)
 {
+	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
 	struct rsnd_src *src = rsnd_mod_to_src(mod);
+	u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11;
 
 	rsnd_dma_start(rsnd_mod_to_dma(&src->mod));
 
 	rsnd_mod_write(mod, SSI_CTRL, 0x1);
-	rsnd_mod_write(mod, SRC_CTRL, 0x11);
+	rsnd_mod_write(mod, SRC_CTRL, val);
 
 	return rsnd_src_start(mod, rdai);
 }

From e6b0d896ab0597d37422cae3cef3e789431549eb Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Tue, 13 May 2014 01:10:20 +0200
Subject: [PATCH 83/86] ASoC: rsnd: Fix warnings due to improper printk formats

Use the %pap printk specifier to print resource_size_t variables. This
fixes warnings on platforms where resource_size_t has a different size
than int.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/sh/rcar/gen.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index a135d4c9d0803..a1583b57bf8d2 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -263,13 +263,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
 		return ret;
 
 	dev_dbg(dev, "Gen2 device probed\n");
-	dev_dbg(dev, "SCU  : %08x => %p\n", scu_res->start,
+	dev_dbg(dev, "SCU  : %pap => %p\n", &scu_res->start,
 		gen->base[RSND_GEN2_SCU]);
-	dev_dbg(dev, "ADG  : %08x => %p\n", adg_res->start,
+	dev_dbg(dev, "ADG  : %pap => %p\n", &adg_res->start,
 		gen->base[RSND_GEN2_ADG]);
-	dev_dbg(dev, "SSIU : %08x => %p\n", ssiu_res->start,
+	dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start,
 		gen->base[RSND_GEN2_SSIU]);
-	dev_dbg(dev, "SSI  : %08x => %p\n", ssi_res->start,
+	dev_dbg(dev, "SSI  : %pap => %p\n", &ssi_res->start,
 		gen->base[RSND_GEN2_SSI]);
 
 	return 0;
@@ -356,11 +356,11 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
 		return ret;
 
 	dev_dbg(dev, "Gen1 device probed\n");
-	dev_dbg(dev, "SRU : %08x => %p\n",	sru_res->start,
+	dev_dbg(dev, "SRU : %pap => %p\n",	&sru_res->start,
 						gen->base[RSND_GEN1_SRU]);
-	dev_dbg(dev, "ADG : %08x => %p\n",	adg_res->start,
+	dev_dbg(dev, "ADG : %pap => %p\n",	&adg_res->start,
 						gen->base[RSND_GEN1_ADG]);
-	dev_dbg(dev, "SSI : %08x => %p\n",	ssi_res->start,
+	dev_dbg(dev, "SSI : %pap => %p\n",	&ssi_res->start,
 						gen->base[RSND_GEN1_SSI]);
 
 	return 0;

From 8c32570441f92244848c5e87f5d613465650aeee Mon Sep 17 00:00:00 2001
From: Axel Lin <axel.lin@ingics.com>
Date: Sat, 17 May 2014 19:17:32 +0800
Subject: [PATCH 84/86] ASoC: rt5645: Fix updating wrong register for
 T5645_AIF2 case

This looks like a copy-paste bug, fix it.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
Tested-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/codecs/rt5645.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 68923eca7d9c5..ab97d722e15d8 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -1932,8 +1932,8 @@ static int rt5645_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 			RT5645_I2S_MS_MASK | RT5645_I2S_BP_MASK |
 			RT5645_I2S_DF_MASK, reg_val);
 		break;
-	case  RT5645_AIF2:
-		snd_soc_update_bits(codec, RT5645_I2S1_SDP,
+	case RT5645_AIF2:
+		snd_soc_update_bits(codec, RT5645_I2S2_SDP,
 			RT5645_I2S_MS_MASK | RT5645_I2S_BP_MASK |
 			RT5645_I2S_DF_MASK, reg_val);
 		break;

From 0596f70069bb5ab34eea980c14fad1041f2abae5 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Mon, 19 May 2014 11:41:46 +0200
Subject: [PATCH 85/86] ASoC: omap: Replace instances of rtd->codec->card with
 rtd->card

No need to go via the CODEC to get a pointer to the card. This will help to
eventually remove the card field from the snd_soc_codec struct.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Jarkko Nikula <jarkko.nikula@bitmer.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/omap/omap-abe-twl6040.c | 5 ++---
 sound/soc/omap/omap-twl4030.c     | 5 ++---
 sound/soc/omap/rx51.c             | 2 +-
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index 1a89e5b1be163..cec836ed0c01e 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -47,8 +47,7 @@ static int omap_abe_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
 	int clk_id, freq;
 	int ret;
@@ -168,7 +167,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
 static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
 	int hs_trim;
 	int ret = 0;
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index 0c83e206e9574..64141db311b2a 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -55,8 +55,7 @@ static int omap_twl4030_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	unsigned int fmt;
 	int ret;
 
@@ -179,7 +178,7 @@ static inline void twl4030_disconnect_pin(struct snd_soc_dapm_context *dapm,
 static int omap_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	struct omap_tw4030_pdata *pdata = dev_get_platdata(card->dev);
 	struct omap_twl4030 *priv = snd_soc_card_get_drvdata(card);
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 866578bcda558..6951dc812055c 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -286,7 +286,7 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
 static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_card *card = codec->card;
+	struct snd_soc_card *card = rtd->card;
 	struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
 
 	struct snd_soc_dapm_context *dapm = &codec->dapm;

From b45281412a6334ab2be5d7e449c98f50fb424a78 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Sun, 4 May 2014 11:25:21 +0800
Subject: [PATCH 86/86] ASoC: pxa: remove mach header dependency

As we are moving the mmp platform towards multiplatform support,
we have to stop including platform header files.

This changes the pxa-ssp sound driver file to no longer depend
on mach/hardware.h and mach/dma.h. The code using the definitions
from those headers is actually gone already, the only thing
that was still being used was the pxa_dma_desc typedef, which
we can easily work around by using the normal 'struct pxa_dma_desc'
name.

The pxa2xx-dma driver still uses this header, so we include it
explicitly there, which is ok because that is only used on pxa,
not on mmp.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Xia Kaixu <kaixu.xia@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/arm/pxa2xx-pcm.c     | 2 ++
 sound/arm/pxa2xx-pcm.h     | 3 +--
 sound/soc/pxa/pxa-ssp.c    | 2 --
 sound/soc/pxa/pxa2xx-pcm.c | 2 ++
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index e6c727b317fbd..83be8e3f095ef 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -14,6 +14,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 
+#include <mach/dma.h>
+
 #include <sound/core.h>
 #include <sound/pxa2xx-lib.h>
 #include <sound/dmaengine_pcm.h>
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 2a8fc08d52a17..00330985beec1 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -9,12 +9,11 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <mach/dma.h>
 
 struct pxa2xx_runtime_data {
 	int dma_ch;
 	struct snd_dmaengine_dai_dma_data *params;
-	pxa_dma_desc *dma_desc_array;
+	struct pxa_dma_desc *dma_desc_array;
 	dma_addr_t dma_desc_array_phys;
 };
 
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index a3119a00d8fac..9b19ee70291ff 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -34,8 +34,6 @@
 #include <sound/pxa2xx-lib.h>
 #include <sound/dmaengine_pcm.h>
 
-#include <mach/hardware.h>
-
 #include "../../arm/pxa2xx-pcm.h"
 #include "pxa-ssp.h"
 
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index d58b09f4f7a42..42f2f0175981a 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -15,6 +15,8 @@
 #include <linux/dmaengine.h>
 #include <linux/of.h>
 
+#include <mach/dma.h>
+
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/pxa2xx-lib.h>