Add Audio drivers for FP3 [1/4]

Enable the config and add all audio driver components
for 'aw8898' codec.

Issue: FP3-A11#202
Change-Id: I96364baea71fe221eaa9086a312e131e66f1d75c
(cherry picked from commit 327728b215c33dcc18766f9980b5f2e88b314b3e)
diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
old mode 100644
new mode 100755
index bb05a2e..bd1c232
--- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -115,19 +115,20 @@
 			qcom,msm-mi2s-tx-lines = <2>;
 		};
 
-		dai_mi2s4: qcom,msm-dai-q6-mi2s-quin {
+		dai_mi2s4: qcom,msm-dai-q6-mi2s-senary {
 			compatible = "qcom,msm-dai-q6-mi2s";
 			qcom,msm-dai-q6-mi2s-dev-id = <4>;
-			qcom,msm-mi2s-rx-lines = <1>;
-			qcom,msm-mi2s-tx-lines = <2>;
+			qcom,msm-mi2s-rx-lines = <3>;
+			qcom,msm-mi2s-tx-lines = <0>;
 		};
 
-		dai_mi2s5: qcom,msm-dai-q6-mi2s-senary {
+		dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
 			compatible = "qcom,msm-dai-q6-mi2s";
-			qcom,msm-dai-q6-mi2s-dev-id = <6>;
-			qcom,msm-mi2s-rx-lines = <0>;
-			qcom,msm-mi2s-tx-lines = <3>;
+			qcom,msm-dai-q6-mi2s-dev-id = <4>;
+			qcom,msm-mi2s-rx-lines = <3>;
+			qcom,msm-mi2s-tx-lines = <0>;
 		};
+
 	};
 
 	lsm: qcom,msm-lsm-client {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi b/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
old mode 100644
new mode 100755
index 9e07534..b812f89
--- a/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
@@ -36,7 +36,7 @@
 	};
 
 	int_codec: sound {
-		status = "okay";
+		status = "disabled";
 		compatible = "qcom,msm8952-audio-codec";
 		qcom,model = "msm8953-snd-card-mtp";
 		reg = <0xc051000 0x4>,
@@ -76,10 +76,10 @@
 				"WSA_SPK OUT", "VDD_WSA_SWITCH",
 				"SpkrMono WSA_IN", "WSA_SPK OUT";
 
-		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
-		qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
-		qcom,cdc-comp-gpios = <&cdc_comp_gpios>;
-		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		//qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+		//qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
+		//qcom,cdc-comp-gpios = <&cdc_comp_gpios>;
+		//qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
 		qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
 
 		qcom,afe-rxtx-lb;
@@ -136,14 +136,8 @@
 		qcom,msm-vdd-wsa-switch-current = <10000>;
 	};
 
-	cdc_us_euro_sw: msm_cdc_pinctrl_us_euro_sw {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&cross_conn_det_act>;
-		pinctrl-1 = <&cross_conn_det_sus>;
-	};
-
 	cdc_comp_gpios: cdc_comp_pinctrl {
+		status = "disabled";
 		compatible = "qcom,msm-cdc-pinctrl";
 		pinctrl-names = "aud_active", "aud_sleep";
 		pinctrl-0 = <&cdc_pdm_comp_lines_act>;
@@ -151,6 +145,7 @@
 	};
 
 	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		status = "disabled";
 		compatible = "qcom,msm-cdc-pinctrl";
 		pinctrl-names = "aud_active", "aud_sleep";
 		pinctrl-0 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act>;
@@ -170,7 +165,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		wsa881x_i2c_f: wsa881x-i2c-codec@f {
-			status = "okay";
+			status = "disabled";
 			compatible = "qcom,wsa881x-i2c-codec";
 			reg = <0x0f>;
 			qcom,wsa-analog-vi-gpio = <&wsa881x_analog_vi_gpio>;
@@ -179,7 +174,7 @@
 				<&wsa881x_analog_reset_gpio>;
 		};
 		wsa881x_i2c_45: wsa881x-i2c-codec@45 {
-			status = "okay";
+			status = "disabled";
 			compatible = "qcom,wsa881x-i2c-codec";
 			reg = <0x45>;
 		};
@@ -198,25 +193,34 @@
 		pinctrl-1 = <&wsa_clk_off>;
 	};
 	wsa881x_analog_reset_gpio: wsa881x_analog_reset_pctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&wsa_reset_on>;
-		pinctrl-1 = <&wsa_reset_off>;
+		status = "disabled";
+		//compatible = "qcom,msm-cdc-pinctrl";
+		//pinctrl-names = "aud_active", "aud_sleep";
+		//pinctrl-0 = <&wsa_reset_on>;
+		//pinctrl-1 = <&wsa_reset_off>;
 	};
 
 	ext_codec: sound-9335 {
-		status = "disabled";
+		status = "okay";
 		compatible = "qcom,msm8952-audio-slim-codec";
 		qcom,model = "msm8953-tasha-snd-card";
 
 		reg = <0xc051000 0x4>,
 			<0xc051004 0x4>,
 			<0xc055000 0x4>,
-			<0xc052000 0x4>;
+			<0xc052000 0x4>,
+			<0x0c056000 0x4>,
+			<0x0c054000 0x4>,
+			<0x0c053000 0x4>;
 		reg-names = "csr_gp_io_mux_mic_ctl",
 			"csr_gp_io_mux_spkr_ctl",
 			"csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
-			"csr_gp_io_mux_quin_ctl";
+			"csr_gp_io_mux_quin_ctl",
+			"csr_gp_io_lpaif_qui_pcm_sec_mode_muxsel",
+			"csr_gp_io_mux_mic_ext_clk_ctl",
+			"csr_gp_io_mux_sec_tlmm_ctl";
+
+		qcom,msm-ext-pa = "quinary";
 
 		qcom,audio-routing =
 			"AIF4 VI", "MCLK",
@@ -254,10 +258,8 @@
 			"SpkrRight IN", "SPK2 OUT";
 
 		qcom,tasha-mclk-clk-freq = <9600000>;
-		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
-		qcom,msm-mbhc-hphl-swh = <0>;
-		qcom,msm-mbhc-gnd-swh = <0>;
-		qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
+		qcom,msm-mbhc-hphl-swh = <1>;
+		qcom,msm-mbhc-gnd-swh = <1>;
 		qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
 
 		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
@@ -302,10 +304,10 @@
 				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.16396",
 				"msm-dai-q6-dev.8194", "msm-dai-q6-dev.8195";
 
-		asoc-codec = <&stub_codec>, <&hdmi_dba>;
-		asoc-codec-names = "msm-stub-codec.1", "msm-hdmi-dba-codec-rx";
+		asoc-codec = <&stub_codec>, <&dai_mi2s5>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-dai-q6-mi2s.5";
 
-		qcom,wsa-max-devs = <2>;
+		qcom,wsa-max-devs = <0>;
 		qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
 				<&wsa881x_213>, <&wsa881x_214>;
 		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
@@ -317,7 +319,7 @@
 	};
 
 	wcd9xxx_intc: wcd9xxx-irq {
-		status = "disabled";
+		status = "okay";
 		compatible = "qcom,wcd9xxx-irq";
 		interrupt-controller;
 		#interrupt-cells = <1>;
@@ -328,7 +330,7 @@
 	};
 
 	clock_audio: audio_ext_clk {
-		status = "disabled";
+		status = "okay";
 		compatible = "qcom,audio-ref-clk";
 		clock-names = "osr_clk";
 		qcom,node_has_rpm_clock;
@@ -341,7 +343,7 @@
 	};
 
 	wcd_rst_gpio: msm_cdc_pinctrl@67 {
-		status = "disabled";
+		status = "okay";
 		compatible = "qcom,msm-cdc-pinctrl";
 		pinctrl-names = "aud_active", "aud_sleep";
 		pinctrl-0 = <&cdc_reset_active>;
@@ -350,16 +352,16 @@
 };
 
 &slim_msm {
-	status = "disabled";
+	status = "okay";
 
 	dai_slim: msm_dai_slim {
-		status = "disabled";
+		status = "okay";
 		compatible = "qcom,msm-dai-slim";
 		elemental-addr = [ff ff ff fe 17 02];
 	};
 
 	wcd9335: tasha_codec {
-		status = "disabled";
+		status = "okay";
 		compatible = "qcom,tasha-slim-pgd";
 		elemental-addr = [00 01 A0 01 17 02];
 
@@ -385,7 +387,7 @@
 
 		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
 		qcom,cdc-micbias1-mv = <1800>;
-		qcom,cdc-micbias2-mv = <1800>;
+		qcom,cdc-micbias2-mv = <2800>;
 		qcom,cdc-micbias3-mv = <1800>;
 		qcom,cdc-micbias4-mv = <1800>;
 
@@ -442,7 +444,7 @@
 
 &pm8953_1 {
 	pmic_analog_codec: analog-codec@f000 {
-		status = "okay";
+		status = "disabled";
 		compatible = "qcom,pmic-analog-codec";
 		reg = <0xf000 0x200>;
 		#address-cells = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
index 4ff1f75..70050ef 100755
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
@@ -58,6 +58,19 @@
 	};
 };
 
+&i2c_6 { /* BLSP2 QUP2 (smart amp) */
+	    status = "ok";
+	    /* AWINIC AW8898 Smart PA */
+	    aw8898_smartpa@34{
+	        compatible = "awinic,aw8898_smartpa";
+	        reg = <0x34>;
+	        reset-gpio = <&tlmm 21 0>;
+	        irq-gpio = <&tlmm 20 0>;
+	        status = "okay";
+	    };
+	    /* AWINIC AW8898 Smart PA End */
+};
+
 &sdhc_1 {
 	/* device core power supply */
 	vdd-supply = <&pm8953_l8>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index 2232b0f..7c74b29 100755
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -50,32 +50,6 @@
 					bias-pull-down;
 				};
 			};
-
-			uart1_console_active: uart1_console_active {
-				mux {
-					pins = "gpio20", "gpio21";
-					function = "blsp_uart6";
-				};
-
-				config {
-					pins = "gpio20", "gpio21";
-					drive-strength = <2>;
-					bias-disable;
-				};
-			};
-
-			uart1_console_sleep: uart1_console_sleep {
-				mux {
-					pins = "gpio20", "gpio21";
-					function = "blsp_uart6";
-				};
-
-				config {
-					pins = "gpio20", "gpio21";
-					drive-strength = <2>;
-					bias-pull-down;
-				};
-			};
 		};
 		cci {
 			cci0_active: cci0_active {
@@ -684,32 +658,6 @@
 			};
 		};
 
-		blsp2_uart1_active: blsp2_uart1_active {
-			mux {
-				pins = "gpio20", "gpio21", "gpio22", "gpio23";
-				function = "blsp_uart6";
-			};
-
-			config {
-				pins = "gpio20", "gpio21", "gpio22", "gpio23";
-				drive-strength = <16>;
-				bias-disable;
-			};
-		};
-
-		blsp2_uart1_sleep: blsp2_uart1_sleep {
-			mux {
-				pins = "gpio20", "gpio21", "gpio22", "gpio23";
-				function = "gpio";
-			};
-
-			config {
-				pins = "gpio20", "gpio21", "gpio22", "gpio23";
-				drive-strength = <2>;
-				bias-disable;
-			};
-		};
-
 		/* SDC pin type */
 		sdc1_clk_on: sdc1_clk_on {
 			config {
@@ -964,6 +912,36 @@
 			};
 		};
 
+		i2c_6 {
+			i2c_6_active: i2c_6_active {
+				/* active state */
+				mux {
+					pins = "gpio22", "gpio23";
+					function = "blsp_i2c6";
+				};
+
+				config {
+					pins = "gpio22", "gpio23";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_6_sleep: i2c_6_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio22", "gpio23";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio22", "gpio23";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
 		nfc {
 			nfc_int_active: nfc_int_active {
 				/* active state */
@@ -1254,35 +1232,6 @@
 			};
 		};
 
-		cross-conn-det {
-			cross_conn_det_act: lines_on {
-				mux {
-					pins = "gpio63";
-					function = "gpio";
-				};
-
-				config {
-					pins = "gpio63";
-					drive-strength = <8>;
-					output-low;
-					bias-pull-down;
-				};
-			};
-
-			cross_conn_det_sus: lines_off {
-				mux {
-					pins = "gpio63";
-					function = "gpio";
-				};
-
-				config {
-					pins = "gpio63";
-					drive-strength = <2>;
-					bias-pull-down;
-				};
-			};
-		};
-
 		/* WSA VI sense */
 		wsa-vi {
 			wsa_vi_on: wsa_vi_on {
@@ -1370,24 +1319,24 @@
 		pri-tlmm-lines {
 			pri_tlmm_lines_act: pri_tlmm_lines_act {
 				mux {
-					pins = "gpio91", "gpio93";
+					pins = "gpio91", "gpio93", "gpio88";
 					function = "pri_mi2s";
 				};
 
 				config {
-					pins = "gpio91", "gpio93";
+					pins = "gpio91", "gpio93", "gpio88";
 					drive-strength = <8>;
 				};
 			};
 
 			pri_tlmm_lines_sus: pri_tlmm_lines_sus {
 				mux {
-					pins = "gpio91", "gpio93";
+					pins = "gpio91", "gpio93", "gpio88";
 					function = "pri_mi2s";
 				};
 
 				config {
-					pins = "gpio91", "gpio93";
+					pins = "gpio91", "gpio93", "gpio88";
 					drive-strength = <2>;
 					bias-pull-down;
 				};
@@ -1421,66 +1370,6 @@
 			};
 		};
 
-		spi6 {
-			spi6_default: spi6_default {
-				/* active state */
-				mux {
-					/* MOSI, MISO, CLK */
-					pins = "gpio20", "gpio21", "gpio23";
-					function = "blsp_spi6";
-				};
-
-				config {
-					pins = "gpio20", "gpio21", "gpio23";
-					drive-strength = <12>; /* 12 MA */
-					bias-disable = <0>; /* No PULL */
-				};
-			};
-
-			spi6_sleep: spi6_sleep {
-				/* suspended state */
-				mux {
-					/* MOSI, MISO, CLK */
-					pins = "gpio20", "gpio21", "gpio23";
-					function = "gpio";
-				};
-
-				config {
-					pins = "gpio20", "gpio21", "gpio23";
-					drive-strength = <2>; /* 2 MA */
-					bias-pull-down; /* PULL Down */
-				};
-			};
-
-			spi6_cs0_active: cs0_active {
-				/* CS */
-				mux {
-					pins = "gpio22";
-					function = "blsp_spi6";
-				};
-
-				config {
-					pins = "gpio22";
-					drive-strength = <2>;
-					bias-disable = <0>;
-				};
-			};
-
-			spi6_cs0_sleep: cs0_sleep {
-				/* CS */
-				mux {
-					pins = "gpio22";
-					function = "gpio";
-				};
-
-				config {
-					pins = "gpio22";
-					drive-strength = <2>;
-					bias-disable = <0>;
-				};
-			};
-		};
-
 		/* add pingrp for touchscreen */
 		ts_int_default: ts_int_default {
 			mux {
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 871b1d4..5f11113 100755
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -188,8 +188,7 @@
 		i2c2 = &i2c_2;
 		i2c3 = &i2c_3;
 		i2c5 = &i2c_5;
-//		spi3 = &spi_3;
-		spi6 = &spi_6;
+		i2c6 = &i2c_6;
 	};
 
 	soc: soc {
@@ -625,42 +624,6 @@
 		status = "disabled";
 	};
 
-	blsp2_uart1: uart@7af0000 {
-		compatible = "qcom,msm-hsuart-v14";
-		reg = <0x7af0000 0x200>,
-			<0x7ac4000 0x1f000>;
-		reg-names = "core_mem", "bam_mem";
-
-		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
-		#address-cells = <0>;
-		interrupt-parent = <&blsp2_uart1>;
-		interrupts = <0 1 2>;
-		#interrupt-cells = <1>;
-		interrupt-map-mask = <0xffffffff>;
-		interrupt-map = <0 &intc 0 307 0
-				1 &intc 0 239 0
-				2 &tlmm 21 0>;
-
-		qcom,inject-rx-on-wakeup;
-		qcom,rx-char-to-inject = <0xFD>;
-		qcom,master-id = <84>;
-		clock-names = "core_clk", "iface_clk";
-		clocks = <&clock_gcc clk_gcc_blsp2_uart2_apps_clk>,
-			<&clock_gcc clk_gcc_blsp2_ahb_clk>;
-		pinctrl-names = "sleep", "default";
-		pinctrl-0 = <&blsp2_uart1_sleep>;
-		pinctrl-1 = <&blsp2_uart1_active>;
-		qcom,bam-tx-ep-pipe-index = <2>;
-		qcom,bam-rx-ep-pipe-index = <3>;
-		qcom,msm-bus,name = "blsp2_uart1";
-		qcom,msm-bus,num-cases = <2>;
-		qcom,msm-bus,num-paths = <1>;
-		qcom,msm-bus,vectors-KBps =
-				<84 512 0 0>,
-				<84 512 500 800>;
-		status = "disabled";
-	};
-
 	blsp1_serial1: serial@78b0000 {
 		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 		reg = <0x78b0000 0x200>;
@@ -687,32 +650,6 @@
 		qcom,summing-threshold = <10>;
 	};
 
-	spi_6: spi@7af6000 { /* BLSP2 QUP2 */
-		compatible = "qcom,spi-qup-v2";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		reg-names = "spi_physical", "spi_bam_physical";
-		reg = <0x7af6000 0x600>,
-			<0x7ac4000 0x1f000>;
-		interrupt-names = "spi_irq", "spi_bam_irq";
-		interrupts = <0 300 0>, <0 239 0>;
-		spi-max-frequency = <19200000>;
-		pinctrl-names = "spi_default", "spi_sleep";
-		pinctrl-0 = <&spi6_default &spi6_cs0_active>;
-		pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>;
-		clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
-			<&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>;
-		clock-names = "iface_clk", "core_clk";
-		qcom,infinite-mode = <0>;
-		qcom,use-bam;
-		qcom,use-pinctrl;
-		qcom,ver-reg-exists;
-		qcom,bam-consumer-pipe-index = <6>;
-		qcom,bam-producer-pipe-index = <7>;
-		qcom,master-id = <84>;
-		status = "disabled";
-	};
-
 	i2c_1: i2c@78b5000 { /* BLSP1 QUP1 */
 		compatible = "qcom,i2c-msm-v2";
 		#address-cells = <1>;
@@ -816,6 +753,32 @@
 		status = "disabled";
 	};
 
+	i2c_6: i2c@7af6000 { /* BLSP2 QUP2 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x7af6000 0x600>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 300 0>;
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp2_qup2_i2c_apps_clk>;
+
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_6_active>;
+		pinctrl-1 = <&i2c_6_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		qcom,master-id = <84>;
+		dmas = <&dma_blsp2 6 64 0x20000020 0x20>,
+			<&dma_blsp2 7 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		status = "ok";
+	};
+
 	slim_msm: slim@c140000{
 		cell-index = <1>;
 		compatible = "qcom,slim-ngd";
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index f5d85ba..5764ea4 100755
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -684,3 +684,4 @@
 CONFIG_CRYPTO_CRC32_ARM64=y
 CONFIG_QMI_ENCDEC=y
 CONFIG_ELAN_FINGERPRINT=y
+CONFIG_SND_SMARTPA_AW8898=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index cba4f0c..121ae13 100755
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -748,3 +748,4 @@
 CONFIG_CRYPTO_CRC32_ARM64=y
 CONFIG_QMI_ENCDEC=y
 CONFIG_ELAN_FINGERPRINT=y
+CONFIG_SND_SMARTPA_AW8898=y
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
old mode 100644
new mode 100755
index 813a191..d49131b
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -294,6 +294,7 @@
 static char fw_path_para[256];
 static const char * const fw_path[] = {
 	fw_path_para,
+	"/system/vendor/firmware",
 	"/lib/firmware/updates/" UTS_RELEASE,
 	"/lib/firmware/updates",
 	"/lib/firmware/" UTS_RELEASE,
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 91a76bd..9bd501c 100755
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -533,10 +533,8 @@
 		//Move "pull low TP reset pin" from mdss_dsi.c,
 		//it have to same with LCM reset pin pull low
 		
-		/*[Fairphone_8901][Jialong]To reduce power,pull down Touch reset pin when panel off start*/
 		//TP reset pin pull low with LCD reset pin at same time.
 		gpio_direction_output(64, 0);
-		/*[Fairphone_8901][Jialong]To reduce power,pull down Touch reset pin when panel off end*/
 		
 		msleep(1);
 		
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
old mode 100644
new mode 100755
index b4c914c..75304d2
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1097,6 +1097,12 @@
 	help
 	  Enables support for aw8896 series Smart PA.
 
+config SND_SMARTPA_AW8898
+	tristate "SoC Audio for awinic aw8898 series"
+	depends on I2C
+	help
+		This option enables support for aw8898 series Smart PA.
+
 config SND_SOC_TFA98XX
 	tristate "NXP Semiconductors TFA98XX amplifier"
 	depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
old mode 100644
new mode 100755
index cf30a19..64ea987
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -447,3 +447,5 @@
 obj-$(CONFIG_SND_SOC_TPA6130A2)	+= snd-soc-tpa6130a2.o
 obj-$(CONFIG_SND_SOC_AW8896)	+= snd-soc-aw8896.o
 obj-$(CONFIG_SND_SOC_TFA98XX)	+= snd-soc-tfa98xx.o
+#for AWINIC AW8898 Smart PA
+obj-y += aw/aw8898.o
diff --git a/sound/soc/codecs/aw/aw8898.c b/sound/soc/codecs/aw/aw8898.c
new file mode 100755
index 0000000..dc565ed
--- /dev/null
+++ b/sound/soc/codecs/aw/aw8898.c
@@ -0,0 +1,1612 @@
+/*
+ * aw8898.c   aw8898 codec module
+ *
+ * Version: v1.1.3
+ *
+ * Copyright (c) 2018 AWINIC Technology CO., LTD
+ *
+ * Author: Nick Li <liweilei@awinic.com.cn>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/debugfs.h>
+#include <linux/version.h>
+#include <linux/input.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/hrtimer.h>
+#include <linux/syscalls.h>
+#include <sound/tlv.h>
+#include "aw8898.h"
+#include "aw8898_reg.h"
+
+/******************************************************
+ *
+ * Marco
+ *
+ ******************************************************/
+#define AW8898_I2C_NAME "aw8898_smartpa"
+
+
+#define AW8898_VERSION "v1.1.3"
+
+#define AW8898_RATES SNDRV_PCM_RATE_8000_48000
+#define AW8898_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+                                    SNDRV_PCM_FMTBIT_S24_LE | \
+                                    SNDRV_PCM_FMTBIT_S32_LE)
+
+//#define AWINIC_I2C_REGMAP
+
+#define AW_I2C_RETRIES 5
+#define AW_I2C_RETRY_DELAY 5  // 5ms
+#define AW_READ_CHIPID_RETRIES 5
+#define AW_READ_CHIPID_RETRY_DELAY 5
+
+static int aw8898_spk_control = 0;
+static int aw8898_rcv_control = 0;
+
+#define AW8898_MAX_FIRMWARE_LOAD_CNT 20
+static char *aw8898_cfg_name = "aw8898_cfg.bin";
+
+#ifdef AW8898_VBAT_MONITOR
+static int aw8898_vbat_monitor_start(struct aw8898 *aw8898);
+static int aw8898_vbat_monitor_stop(struct aw8898 *aw8898);
+#endif
+ /******************************************************
+ *
+ * aw8898 i2c write/read
+ *
+ ******************************************************/
+#ifndef AWINIC_I2C_REGMAP
+static int i2c_write(struct aw8898 *aw8898,
+        unsigned char addr, unsigned int reg_data)
+{
+    int ret = -1;
+    u8 wbuf[512] = {0};
+
+    struct i2c_msg msgs[] = {
+        {
+            .addr   = aw8898->i2c->addr,
+            .flags  = 0,
+            .len    = 3,
+            .buf    = wbuf,
+        },
+    };
+
+    wbuf[0] = addr;
+    wbuf[1] = (unsigned char)((reg_data & 0xff00)>>8);
+    wbuf[2] = (unsigned char)(reg_data & 0x00ff);
+
+    ret = i2c_transfer(aw8898->i2c->adapter, msgs, 1);
+    if (ret < 0) {
+        pr_err("%s: i2c write error: %d\n", __func__, ret);
+    }
+
+    return ret;
+}
+
+static int i2c_read(struct aw8898 *aw8898,
+        unsigned char addr, unsigned int *reg_data)
+{
+    int ret = -1;
+    unsigned char rbuf[512] = {0};
+    unsigned int get_data = 0;
+
+    struct i2c_msg msgs[] = {
+        {
+            .addr   = aw8898->i2c->addr,
+            .flags  = 0,
+            .len    = 1,
+            .buf    = &addr,
+        },
+        {
+            .addr   = aw8898->i2c->addr,
+            .flags  = I2C_M_RD,
+            .len    = 2,
+            .buf    = rbuf,
+        },
+    };
+
+    ret = i2c_transfer(aw8898->i2c->adapter, msgs, 2);
+    if (ret < 0) {
+        pr_err("%s: i2c read error: %d\n", __func__, ret);
+        return ret;
+    }
+
+    get_data = (unsigned int)(rbuf[0] & 0x00ff);
+    get_data <<= 8;
+    get_data |= (unsigned int)rbuf[1];
+
+    *reg_data = get_data;
+
+    return ret;
+}
+#endif
+
+static int aw8898_i2c_write(struct aw8898 *aw8898,
+        unsigned char reg_addr, unsigned int reg_data)
+{
+    int ret = -1;
+    unsigned char cnt = 0;
+
+    while(cnt < AW_I2C_RETRIES) {
+#ifdef AWINIC_I2C_REGMAP
+    ret = regmap_write(aw8898->regmap, reg_addr, reg_data);
+    if(ret < 0) {
+        pr_err("%s: regmap_write cnt=%d error=%d\n", __func__, cnt, ret);
+    } else {
+        break;
+    }
+#else
+    ret = i2c_write(aw8898, reg_addr, reg_data);
+    if(ret < 0) {
+        pr_err("%s: i2c_write cnt=%d error=%d\n", __func__, cnt, ret);
+    } else {
+        break;
+    }
+#endif
+        cnt ++;
+    }
+
+    return ret;
+}
+
+static int aw8898_i2c_read(struct aw8898 *aw8898,
+        unsigned char reg_addr, unsigned int *reg_data)
+{
+    int ret = -1;
+    unsigned char cnt = 0;
+
+    while(cnt < AW_I2C_RETRIES) {
+#ifdef AWINIC_I2C_REGMAP
+    ret = regmap_read(aw8898->regmap, reg_addr, reg_data);
+    if(ret < 0) {
+        pr_err("%s: regmap_read cnt=%d error=%d\n", __func__, cnt, ret);
+    } else {
+        break;
+    }
+#else
+    ret = i2c_read(aw8898, reg_addr, reg_data);
+    if(ret < 0) {
+        pr_err("%s: i2c_read cnt=%d error=%d\n", __func__, cnt, ret);
+    } else {
+        break;
+    }
+#endif
+        cnt ++;
+    }
+
+    return ret;
+}
+
+static int aw8898_i2c_write_bits(struct aw8898 *aw8898,
+        unsigned char reg_addr, unsigned int mask, unsigned int reg_data)
+{
+    unsigned int reg_val;
+
+    aw8898_i2c_read(aw8898, reg_addr, &reg_val);
+    reg_val &= mask;
+    reg_val |= reg_data;
+    aw8898_i2c_write(aw8898, reg_addr, reg_val);
+
+    return 0;
+}
+
+/******************************************************
+ *
+ * aw8898 control
+ *
+ ******************************************************/
+static void aw8898_run_mute(struct aw8898 *aw8898, bool mute)
+{
+    pr_debug("%s enter\n", __func__);
+
+    if(mute) {
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_PWMCTRL,
+                AW8898_BIT_PWMCTRL_HMUTE_MASK, AW8898_BIT_PWMCTRL_HMUTE_ENABLE);
+    } else {
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_PWMCTRL,
+                AW8898_BIT_PWMCTRL_HMUTE_MASK, AW8898_BIT_PWMCTRL_HMUTE_DISABLE);
+    }
+}
+
+static void aw8898_run_pwd(struct aw8898 *aw8898, bool pwd)
+{
+    pr_debug("%s enter\n", __func__);
+
+    if(pwd) {
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_SYSCTRL,
+                AW8898_BIT_SYSCTRL_PW_MASK, AW8898_BIT_SYSCTRL_PW_PDN);
+    } else {
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_SYSCTRL,
+                AW8898_BIT_SYSCTRL_PW_MASK, AW8898_BIT_SYSCTRL_PW_ACTIVE);
+    }
+}
+
+static void aw8898_spk_rcv_mode(struct aw8898 *aw8898)
+{
+    pr_debug("%s spk_rcv=%d\n", __func__, aw8898->spk_rcv_mode);
+
+    if(aw8898->spk_rcv_mode == AW8898_SPEAKER_MODE) {
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_SYSCTRL,
+                AW8898_BIT_SYSCTRL_MODE_MASK, AW8898_BIT_SYSCTRL_SPK_MODE);
+    } else if(aw8898->spk_rcv_mode == AW8898_RECEIVER_MODE){
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_SYSCTRL,
+                AW8898_BIT_SYSCTRL_MODE_MASK, AW8898_BIT_SYSCTRL_RCV_MODE);
+    } else {
+    }
+}
+
+
+static void aw8898_start(struct aw8898 *aw8898)
+{
+    unsigned int reg_val = 0;
+    unsigned int iis_check_max = 5;
+    unsigned int i = 0;
+
+    pr_debug("%s enter\n", __func__);
+
+    aw8898_run_pwd(aw8898, false);
+    msleep(2);
+    for(i=0; i<iis_check_max; i++) {
+        aw8898_i2c_read(aw8898, AW8898_REG_SYSST, &reg_val);
+        if(reg_val & AW8898_BIT_SYSST_PLLS) {
+              aw8898_run_mute(aw8898, false);
+              pr_debug("%s iis signal check pass!\n", __func__);
+#ifdef AW8898_VBAT_MONITOR
+            aw8898_vbat_monitor_start(aw8898);
+#endif
+            return;
+        }
+        msleep(2);
+    }
+    aw8898_run_pwd(aw8898, true);
+    pr_err("%s: iis signal check error\n", __func__);
+}
+static void aw8898_stop(struct aw8898 *aw8898)
+{
+    pr_debug("%s enter\n", __func__);
+
+    aw8898_run_mute(aw8898, true);
+    aw8898_run_pwd(aw8898, true);
+#ifdef AW8898_VBAT_MONITOR
+    aw8898_vbat_monitor_stop(aw8898);
+#endif
+}
+
+static void aw8898_container_update(struct aw8898 *aw8898,
+        struct aw8898_container *aw8898_cont)
+{
+    int i = 0;
+    int reg_addr = 0;
+    int reg_val = 0;
+
+    pr_debug("%s enter\n", __func__);
+
+    for(i=0; i<aw8898_cont->len; i+=4) {
+        reg_addr = (aw8898_cont->data[i+1]<<8) + aw8898_cont->data[i+0];
+        reg_val = (aw8898_cont->data[i+3]<<8) + aw8898_cont->data[i+2];
+        pr_info("%s: reg=0x%04x, val = 0x%04x\n", __func__, reg_addr, reg_val);
+        aw8898_i2c_write(aw8898, (unsigned char)reg_addr, (unsigned int)reg_val);
+    }
+
+    pr_debug("%s exit\n", __func__);
+}
+
+static void aw8898_cfg_loaded(const struct firmware *cont, void *context)
+{
+    struct aw8898 *aw8898 = context;
+    struct aw8898_container *aw8898_cfg;
+    unsigned int i = 0;
+
+    if (!cont) {
+        pr_err("%s: failed to read %s\n", __func__, aw8898_cfg_name);
+        release_firmware(cont);
+        return;
+    }
+
+    pr_info("%s: loaded %s - size: %zu\n", __func__, aw8898_cfg_name,
+            cont ? cont->size : 0);
+
+    for(i=0; i<cont->size; i++) {
+        pr_info("%s: addr:0x%04x, data:0x%02x\n", __func__, i, *(cont->data+i));
+    }
+
+    aw8898_cfg = kzalloc(cont->size+sizeof(int), GFP_KERNEL);
+    if (!aw8898_cfg) {
+        release_firmware(cont);
+        pr_err("%s: error allocating memory\n", __func__);
+        return;
+    }
+    aw8898_cfg->len = cont->size;
+    memcpy(aw8898_cfg->data, cont->data, cont->size);
+    release_firmware(cont);
+
+    aw8898_container_update(aw8898, aw8898_cfg);
+
+    kfree(aw8898_cfg);
+
+    aw8898->init = 1;
+    pr_info("%s: cfg update complete\n", __func__);
+
+    aw8898_spk_rcv_mode(aw8898);
+    aw8898_start(aw8898);
+}
+
+static int aw8898_load_cfg(struct aw8898 *aw8898)
+{
+    pr_info("%s enter\n", __func__);
+
+    return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+            aw8898_cfg_name, aw8898->dev, GFP_KERNEL,
+            aw8898, aw8898_cfg_loaded);
+}
+
+static void aw8898_cold_start(struct aw8898 *aw8898)
+{
+    int ret = -1;
+
+    pr_info("%s enter\n", __func__);
+
+    ret = aw8898_load_cfg(aw8898);
+    if(ret) {
+        pr_err("%s: cfg loading requested failed: %d\n", __func__, ret);
+    }
+}
+
+static void aw8898_smartpa_cfg(struct aw8898 *aw8898, bool flag)
+{
+    pr_info("%s, flag = %d\n", __func__, flag);
+
+    if(flag == true) {
+        if(aw8898->init == 0) {
+            pr_info("%s, init = %d\n", __func__, aw8898->init);
+            aw8898_cold_start(aw8898);
+        } else {
+            aw8898_spk_rcv_mode(aw8898);
+            aw8898_start(aw8898);
+        }
+    } else {
+        aw8898_stop(aw8898);
+    }
+}
+
+/******************************************************
+ *
+ * kcontrol
+ *
+ ******************************************************/
+ static const char *const spk_function[] = { "Off", "On" };
+ static const char *const rcv_function[] = { "Off", "On" };
+ static const DECLARE_TLV_DB_SCALE(digital_gain,0,50,0);
+
+ struct soc_mixer_control aw8898_mixer ={
+    .reg    = AW8898_REG_HAGCCFG7,
+    .shift  = AW8898_VOL_REG_SHIFT,
+    .max    = AW8898_VOLUME_MAX,
+    .min    = AW8898_VOLUME_MIN,
+ };
+
+static int aw8898_volume_info(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_info *uinfo)
+{
+    struct soc_mixer_control *mc = (struct soc_mixer_control*) kcontrol->private_value;
+
+    //set kcontrol info
+    uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+    uinfo->count = 1;
+    uinfo->value.integer.min = 0;
+    uinfo->value.integer.max = mc->max - mc->min;
+    return 0;
+}
+
+static int aw8898_volume_get(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol)
+{
+    struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+    unsigned int reg_val = 0;
+    unsigned int value = 0;
+    struct soc_mixer_control *mc = (struct soc_mixer_control*) kcontrol->private_value;
+
+    aw8898_i2c_read(aw8898, AW8898_REG_HAGCCFG7, &reg_val);
+    ucontrol->value.integer.value[0] = (value >> mc->shift)\
+            &(AW8898_BIT_HAGCCFG7_VOL_MASK);
+    return 0;
+}
+
+static int aw8898_volume_put(struct snd_kcontrol *kcontrol,struct snd_ctl_elem_value *ucontrol)
+{
+    struct soc_mixer_control *mc = (struct soc_mixer_control*) kcontrol->private_value;
+    struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+    unsigned int value = 0;
+    unsigned int reg_value = 0;
+
+    //value is right
+    value = ucontrol->value.integer.value[0];
+    if(value > (mc->max-mc->min)|| value <0){
+      pr_err("%s:value over range \n",__func__);
+      return -1;
+    }
+
+    //smartpa have clk
+    aw8898_i2c_read(aw8898, AW8898_REG_SYSST, &reg_value);
+    if(!(reg_value&AW8898_BIT_SYSST_PLLS)){
+      pr_err("%s: NO I2S CLK ,cat not write reg \n",__func__);
+      return 0;
+    }
+    //cal real value
+    value = value << mc->shift&AW8898_BIT_HAGCCFG7_VOL_MASK;
+    aw8898_i2c_read(aw8898, AW8898_REG_HAGCCFG7, &reg_value);
+    value = value | (reg_value&0x00ff);
+
+    //write value
+    aw8898_i2c_write(aw8898, AW8898_REG_HAGCCFG7, value);
+
+    return 0;
+}
+
+static struct snd_kcontrol_new aw8898_volume = {
+    .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+    .name  = "aw8898_rx_volume",
+    .access= SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_READWRITE,
+    .tlv.p  = (digital_gain),
+    .info = aw8898_volume_info,
+    .get =  aw8898_volume_get,
+    .put =  aw8898_volume_put,
+    .private_value = (unsigned long)&aw8898_mixer,
+};
+
+static int aw8898_spk_get(struct snd_kcontrol *kcontrol,
+        struct snd_ctl_elem_value *ucontrol)
+{
+    pr_debug("%s: aw8898_spk_control=%d\n", __func__, aw8898_spk_control);
+    ucontrol->value.integer.value[0] = aw8898_spk_control;
+    return 0;
+}
+
+static int aw8898_spk_set(struct snd_kcontrol *kcontrol,
+        struct snd_ctl_elem_value *ucontrol)
+{
+    struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+
+    pr_debug("%s: ucontrol->value.integer.value[0]=%ld\n ",
+            __func__, ucontrol->value.integer.value[0]);
+    if(ucontrol->value.integer.value[0] == aw8898_spk_control)
+        return 1;
+
+    aw8898_spk_control = ucontrol->value.integer.value[0];
+
+    aw8898->spk_rcv_mode = AW8898_SPEAKER_MODE;
+
+    aw8898_spk_rcv_mode(aw8898);
+
+    return 0;
+}
+
+static int aw8898_rcv_get(struct snd_kcontrol *kcontrol,
+        struct snd_ctl_elem_value *ucontrol)
+{
+    pr_debug("%s: aw8898_rcv_control=%d\n", __func__, aw8898_rcv_control);
+    ucontrol->value.integer.value[0] = aw8898_rcv_control;
+    return 0;
+}
+static int aw8898_rcv_set(struct snd_kcontrol *kcontrol,
+        struct snd_ctl_elem_value *ucontrol)
+{
+    struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+    pr_debug("%s: ucontrol->value.integer.value[0]=%ld\n ",
+            __func__, ucontrol->value.integer.value[0]);
+    if(ucontrol->value.integer.value[0] == aw8898_rcv_control)
+        return 1;
+
+    aw8898_rcv_control = ucontrol->value.integer.value[0];
+
+    aw8898->spk_rcv_mode = AW8898_RECEIVER_MODE;
+
+    aw8898_spk_rcv_mode(aw8898);
+
+    return 0;
+}
+static const struct soc_enum aw8898_snd_enum[] = {
+    SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
+    SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rcv_function), rcv_function),
+};
+
+static struct snd_kcontrol_new aw8898_controls[] = {
+    SOC_ENUM_EXT("aw8898_speaker_switch", aw8898_snd_enum[0],
+            aw8898_spk_get, aw8898_spk_set),
+    SOC_ENUM_EXT("aw8898_receiver_switch", aw8898_snd_enum[1],
+            aw8898_rcv_get, aw8898_rcv_set),
+};
+
+static void aw8898_add_codec_controls(struct aw8898 *aw8898)
+{
+    pr_info("%s enter\n", __func__);
+
+    snd_soc_add_codec_controls(aw8898->codec, aw8898_controls,
+            ARRAY_SIZE(aw8898_controls));
+
+    snd_soc_add_codec_controls(aw8898->codec, &aw8898_volume,1);
+}
+
+/******************************************************
+ *
+ * DAPM Widget & Route
+ *
+ ******************************************************/
+#if 0
+static struct snd_soc_dapm_widget aw8898_dapm_widgets_common[] = {
+    /* Stream widgets */
+    SND_SOC_DAPM_AIF_IN("AIF_IN", "AW89xx_AIF_Playback", 0, SND_SOC_NOPM, 0, 0),
+    SND_SOC_DAPM_AIF_OUT("AIF_OUT", "AW89xx_AIF_Capture", 0, SND_SOC_NOPM, 0, 0),
+
+    SND_SOC_DAPM_OUTPUT("OUTL"),
+    SND_SOC_DAPM_INPUT("AEC_Loopback"),
+};
+
+static const struct snd_soc_dapm_route aw8898_dapm_routes_common[] = {
+    { "OUTL", NULL, "AIF_IN" },
+    { "AIF_OUT", NULL, "AEC_Loopback" },
+};
+
+static void aw8898_add_widgets(struct aw8898 *aw8898)
+{
+    //struct snd_soc_dapm_context *dapm = &aw8898->codec->dapm;
+    struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(aw8898->codec);
+    struct snd_soc_dapm_widget *widgets;
+
+    pr_info("%s enter\n", __func__);
+    widgets = devm_kzalloc(&aw8898->i2c->dev,
+            sizeof(struct snd_soc_dapm_widget) *
+            ARRAY_SIZE(aw8898_dapm_widgets_common),
+            GFP_KERNEL);
+    if (!widgets)
+        return;
+
+    memcpy(widgets, aw8898_dapm_widgets_common,
+            sizeof(struct snd_soc_dapm_widget) *
+            ARRAY_SIZE(aw8898_dapm_widgets_common));
+
+    snd_soc_dapm_new_controls(dapm, widgets,
+            ARRAY_SIZE(aw8898_dapm_widgets_common));
+    snd_soc_dapm_add_routes(dapm, aw8898_dapm_routes_common,
+            ARRAY_SIZE(aw8898_dapm_routes_common));
+}
+#endif
+/******************************************************
+ *
+ * Digital Audio Interface
+ *
+ ******************************************************/
+static int aw8898_startup(struct snd_pcm_substream *substream,
+        struct snd_soc_dai *dai)
+{
+    struct snd_soc_codec *codec = dai->codec;
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+
+    pr_info("%s: enter\n", __func__);
+    aw8898_run_pwd(aw8898, false);
+
+    return 0;
+}
+
+static int aw8898_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+    //struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(dai->codec);
+    struct snd_soc_codec *codec = dai->codec;
+
+    pr_info("%s: fmt=0x%x\n", __func__, fmt);
+
+    /* Supported mode: regular I2S, slave, or PDM */
+    switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+    case SND_SOC_DAIFMT_I2S:
+        if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+            dev_err(codec->dev, "%s: invalid codec master mode\n", __func__);
+            return -EINVAL;
+        }
+        break;
+    default:
+        dev_err(codec->dev, "%s: unsupported DAI format %d\n", __func__,
+                fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+        return -EINVAL;
+    }
+    return 0;
+}
+
+static int aw8898_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+        int clk_id, unsigned int freq, int dir)
+{
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec_dai->codec);
+
+    pr_info("%s: freq=%d\n", __func__, freq);
+
+    aw8898->sysclk = freq;
+    return 0;
+}
+
+static int aw8898_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 aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+    unsigned int rate = 0;
+    int reg_value = 0;
+    int width = 0;
+    /* Supported */
+
+    //get rate param
+    aw8898->rate=rate = params_rate(params);
+    pr_debug("%s: requested rate: %d, sample size: %d\n", __func__, rate,
+            snd_pcm_format_width(params_format(params)));
+    //match rate
+    switch(rate)
+    {
+        case 8000:
+            reg_value = AW8898_BIT_I2SCTRL_SR_8K;
+            break;
+        case 16000:
+            reg_value = AW8898_BIT_I2SCTRL_SR_16K;
+            break;
+        case 32000:
+            reg_value = AW8898_BIT_I2SCTRL_SR_32K;
+            break;
+        case 44100:
+            reg_value = AW8898_BIT_I2SCTRL_SR_44P1K;
+            break;
+        case 48000:
+            reg_value = AW8898_BIT_I2SCTRL_SR_48K;
+            break;
+        default:
+            reg_value = AW8898_BIT_I2SCTRL_SR_48K;
+            pr_err("%s: rate can not support\n", __func__);
+            break;
+    }
+    //set chip rate
+    if(-1 != reg_value){
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_I2SCTRL,
+                AW8898_BIT_I2SCTRL_SR_MASK, reg_value);
+    }
+
+    //get bit width
+    width = params_width(params);
+    pr_debug("%s: width = %d \n",__func__,width);
+    switch(width)
+    {
+        case 16:
+            reg_value = AW8898_BIT_I2SCTRL_FMS_16BIT;
+            break;
+        case 20:
+            reg_value = AW8898_BIT_I2SCTRL_FMS_20BIT;
+            break;
+        case 24:
+            reg_value = AW8898_BIT_I2SCTRL_FMS_24BIT;
+            break;
+        case 32:
+            reg_value = AW8898_BIT_I2SCTRL_FMS_32BIT;
+            break;
+        default:
+            reg_value = AW8898_BIT_I2SCTRL_FMS_16BIT;
+            pr_err("%s: width can not support\n", __func__);
+            break;
+    }
+    //set width
+    if(-1 != reg_value){
+        aw8898_i2c_write_bits(aw8898, AW8898_REG_I2SCTRL,
+                AW8898_BIT_I2SCTRL_FMS_MASK, reg_value);
+    }
+
+    return 0;
+}
+
+static int aw8898_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+    struct snd_soc_codec *codec = dai->codec;
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+
+    pr_info("%s: mute state=%d\n", __func__, mute);
+
+    if (!(aw8898->flags & AW8898_FLAG_START_ON_MUTE))
+        return 0;
+
+    if (mute) {
+        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+            aw8898->pstream = 0;
+        else
+            aw8898->cstream = 0;
+        if (aw8898->pstream != 0 || aw8898->cstream != 0)
+            return 0;
+
+        mutex_lock(&aw8898->cfg_lock);
+        aw8898_smartpa_cfg(aw8898, false);
+        mutex_unlock(&aw8898->cfg_lock);
+    } else {
+        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+            aw8898->pstream = 1;
+        else
+            aw8898->cstream = 1;
+
+        mutex_lock(&aw8898->cfg_lock);
+        aw8898_smartpa_cfg(aw8898, true);
+        mutex_unlock(&aw8898->cfg_lock);
+    }
+
+    return 0;
+}
+
+static void aw8898_shutdown(struct snd_pcm_substream *substream,
+        struct snd_soc_dai *dai)
+{
+    struct snd_soc_codec *codec = dai->codec;
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+
+    aw8898->rate = 0;
+    aw8898_run_pwd(aw8898, true);
+}
+
+static const struct snd_soc_dai_ops aw8898_dai_ops = {
+    .startup = aw8898_startup,
+    .set_fmt = aw8898_set_fmt,
+    .set_sysclk = aw8898_set_dai_sysclk,
+    .hw_params = aw8898_hw_params,
+    .mute_stream = aw8898_mute,
+    .shutdown = aw8898_shutdown,
+};
+
+static struct snd_soc_dai_driver aw8898_dai[] = {
+    {
+        .name = "aw8898-aif",
+        .id = 1,
+        .playback = {
+            .stream_name = "Speaker_Playback",
+            .channels_min = 1,
+            .channels_max = 2,
+            .rates = AW8898_RATES,
+            .formats = AW8898_FORMATS,
+        },
+        .capture = {
+            .stream_name = "Speaker_Capture",
+            .channels_min = 1,
+            .channels_max = 2,
+            .rates = AW8898_RATES,
+            .formats = AW8898_FORMATS,
+         },
+        .ops = &aw8898_dai_ops,
+        .symmetric_rates = 1,
+        .symmetric_channels = 1,
+        .symmetric_samplebits = 1,
+    },
+};
+
+/*****************************************************
+ *
+ * codec driver
+ *
+ *****************************************************/
+static int aw8898_probe(struct snd_soc_codec *codec)
+{
+    struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+    int ret = 0;
+
+    pr_info("%s enter\n", __func__);
+
+    aw8898->codec = codec;
+
+    //aw8898_add_widgets(aw8898);
+
+    aw8898_add_codec_controls(aw8898);
+
+    if (codec->dev->of_node)
+        dev_set_name(codec->dev, "%s", "aw8898_smartpa");
+
+    pr_info("%s exit\n", __func__);
+
+    return ret;
+}
+
+static int aw8898_remove(struct snd_soc_codec *codec)
+{
+    //struct aw8898 *aw8898 = snd_soc_codec_get_drvdata(codec);
+    pr_info("%s enter\n", __func__);
+
+    //aw8898_inputdev_unregister(aw8898);
+
+    return 0;
+}
+
+/*
+struct regmap *aw8898_get_regmap(struct device *dev)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+
+    return aw8898->regmap;
+}
+*/
+
+static unsigned int aw8898_codec_read(struct snd_soc_codec *codec,unsigned int reg)
+{
+    struct aw8898 *aw8898=snd_soc_codec_get_drvdata(codec);
+    unsigned int value =0;
+    int ret;
+    pr_debug("%s:enter \n",__func__);
+
+    if(aw8898_reg_access[reg]&REG_RD_ACCESS){
+        ret=aw8898_i2c_read(aw8898,reg,&value);
+    if(ret<0){
+        pr_debug("%s: read register failed \n",__func__);
+        return ret;
+    }
+    }else{
+        pr_debug("%s:Register 0x%x NO read access\n",__func__,reg);
+        return -1;
+    }
+    return value;
+}
+
+static int aw8898_codec_write(struct snd_soc_codec *codec,unsigned int reg,unsigned int value)
+{
+    int ret ;
+    struct aw8898 *aw8898=snd_soc_codec_get_drvdata(codec);
+    pr_debug("%s:enter ,reg is 0x%x value is 0x%x\n",__func__,reg,value);
+
+    if(aw8898_reg_access[reg]&REG_WR_ACCESS){
+        ret=aw8898_i2c_write(aw8898,reg,value);
+        return ret;
+    }else{
+        pr_debug("%s: Register 0x%x NO write access \n",__func__,reg);
+    }
+
+    return -1;
+}
+/*
+static int aw8898_codec_readable(struct snd_soc_codec *codec,unsigned int reg)
+{
+    return aw8898_reg_access[reg]&REG_RD_ACCESS;
+}
+*/
+static struct snd_soc_codec_driver soc_codec_dev_aw8898 = {
+    .probe = aw8898_probe,
+    .remove = aw8898_remove,
+    //.get_regmap = aw8898_get_regmap,
+    .read = aw8898_codec_read,
+    .write= aw8898_codec_write,
+    .reg_cache_size= AW8898_REG_MAX,
+    .reg_word_size=2,
+};
+
+/*****************************************************
+ *
+ * regmap
+ *
+ *****************************************************/
+bool aw8898_writeable_register(struct device *dev, unsigned int reg)
+{
+    /* enable read access for all registers */
+    return 1;
+}
+
+bool aw8898_readable_register(struct device *dev, unsigned int reg)
+{
+    /* enable read access for all registers */
+    return 1;
+}
+
+bool aw8898_volatile_register(struct device *dev, unsigned int reg)
+{
+    /* enable read access for all registers */
+    return 1;
+}
+
+static const struct regmap_config aw8898_regmap = {
+    .reg_bits = 8,
+    .val_bits = 16,
+
+    .max_register = AW8898_MAX_REGISTER,
+    .writeable_reg = aw8898_writeable_register,
+    .readable_reg = aw8898_readable_register,
+    .volatile_reg = aw8898_volatile_register,
+    .cache_type = REGCACHE_RBTREE,
+};
+
+/******************************************************
+ *
+ * irq
+ *
+ ******************************************************/
+static void aw8898_interrupt_setup(struct aw8898 *aw8898)
+{
+    unsigned int reg_val;
+
+    pr_info("%s enter\n", __func__);
+
+    aw8898_i2c_read(aw8898, AW8898_REG_SYSINTM, &reg_val);
+    reg_val &= (~AW8898_BIT_SYSINTM_PLLM);
+    reg_val &= (~AW8898_BIT_SYSINTM_OTHM);
+    reg_val &= (~AW8898_BIT_SYSINTM_OCDM);
+    aw8898_i2c_write(aw8898, AW8898_REG_SYSINTM, reg_val);
+}
+
+static void aw8898_interrupt_clear(struct aw8898 *aw8898)
+{
+    unsigned int reg_val = 0;
+
+    pr_info("%s enter\n", __func__);
+
+    aw8898_i2c_read(aw8898, AW8898_REG_SYSST, &reg_val);
+    pr_info("%s: reg SYSST=0x%x\n", __func__, reg_val);
+
+    aw8898_i2c_read(aw8898, AW8898_REG_SYSINT, &reg_val);
+    pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
+
+    aw8898_i2c_read(aw8898, AW8898_REG_SYSINTM, &reg_val);
+    pr_info("%s: reg SYSINTM=0x%x\n", __func__, reg_val);
+}
+
+static irqreturn_t aw8898_irq(int irq, void *data)
+{
+    struct aw8898 *aw8898 = data;
+
+    pr_info("%s enter\n", __func__);
+
+    aw8898_interrupt_clear(aw8898);
+
+    pr_info("%s exit\n", __func__);
+
+    return IRQ_HANDLED;
+}
+
+/*****************************************************
+ *
+ * device tree
+ *
+ *****************************************************/
+static int aw8898_parse_dt(struct device *dev, struct aw8898 *aw8898,
+        struct device_node *np)
+{
+    aw8898->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+    if (aw8898->reset_gpio < 0) {
+        dev_err(dev, "%s: no reset gpio provided, will not HW reset device\n", __func__);
+        return -1;
+    } else {
+        dev_info(dev, "%s: reset gpio provided ok\n", __func__);
+    }
+    aw8898->irq_gpio =  of_get_named_gpio(np, "irq-gpio", 0);
+    if (aw8898->irq_gpio < 0) {
+        dev_info(dev, "%s: no irq gpio provided.\n", __func__);
+    } else {
+        dev_info(dev, "%s: irq gpio provided ok.\n", __func__);
+    }
+
+    return 0;
+}
+
+int aw8898_hw_reset(struct aw8898 *aw8898)
+{
+    pr_info("%s enter\n", __func__);
+
+    if (aw8898 && gpio_is_valid(aw8898->reset_gpio)) {
+        gpio_set_value_cansleep(aw8898->reset_gpio, 0);
+        msleep(1);
+        gpio_set_value_cansleep(aw8898->reset_gpio, 1);
+        msleep(1);
+    } else {
+        dev_err(aw8898->dev, "%s:  failed\n", __func__);
+    }
+    return 0;
+}
+
+/*****************************************************
+ *
+ * check chip id
+ *
+ *****************************************************/
+int aw8898_read_chipid(struct aw8898 *aw8898)
+{
+    int ret = -1;
+    unsigned int cnt = 0;
+    unsigned int reg = 0;
+
+    while(cnt < AW_READ_CHIPID_RETRIES) {
+        ret = aw8898_i2c_read(aw8898, AW8898_REG_ID, &reg);
+        if (ret < 0) {
+            dev_err(aw8898->dev, "%s: failed to read register AW8898_REG_ID: %d\n", __func__, ret);
+            return -EIO;
+        }
+        switch (reg) {
+        case 0x1702:
+            pr_info("%s aw8898 detected\n", __func__);
+            aw8898->flags |= AW8898_FLAG_SKIP_INTERRUPTS;
+            aw8898->flags |= AW8898_FLAG_START_ON_MUTE;
+            aw8898->chipid = AW8898_ID;
+            pr_info("%s aw8898->flags=0x%x\n", __func__, aw8898->flags);
+            return 0;
+        default:
+            pr_info("%s unsupported device revision (0x%x)\n", __func__, reg );
+            break;
+        }
+        cnt ++;
+
+        msleep(AW_READ_CHIPID_RETRY_DELAY);
+    }
+
+    return -EINVAL;
+}
+
+/*****************************************************
+ *
+ * vbat monitor
+ *
+ *****************************************************/
+#ifdef AW8898_VBAT_MONITOR
+static int aw8898_vbat_monitor_stop(struct aw8898 *aw8898)
+{
+    pr_info("%s enter\n", __func__);
+
+    if(hrtimer_active(&aw8898->vbat_monitor_timer)) {
+        pr_info("%s: cancel vbat monitor\n", __func__);
+        hrtimer_cancel(&aw8898->vbat_monitor_timer);
+    }
+    return 0;
+}
+
+static int aw8898_vbat_monitor_start(struct aw8898 *aw8898)
+{
+    int ram_timer_val = 30000;
+
+    pr_info("%s enter\n", __func__);
+
+    if(hrtimer_active(&aw8898->vbat_monitor_timer)) {
+    } else {
+        pr_info("%s: start vbat monitor\n", __func__);
+        hrtimer_start(&aw8898->vbat_monitor_timer,
+                ktime_set(ram_timer_val/1000, (ram_timer_val%1000)*1000000),
+                HRTIMER_MODE_REL);
+    }
+    return 0;
+}
+
+static enum hrtimer_restart aw8898_vbat_monitor_timer_func(struct hrtimer *timer)
+{
+    struct aw8898 *aw8898 = container_of(timer, struct aw8898, vbat_monitor_timer);
+
+    pr_info("%s enter\n", __func__);
+
+    schedule_work(&aw8898->vbat_monitor_work);
+
+    return HRTIMER_NORESTART;
+}
+
+static int aw8898_get_sys_battery_info(char *dev)
+{
+    int fd;
+    int eCheck;
+    int nReadSize;
+    char buf[64],*pvalue;
+    mm_segment_t oldfs;
+
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+    fd = sys_open(dev, O_RDONLY, 0);
+    if (fd < 0) {
+        pr_err("%s: open fail dev:%s fd:%d\n", __func__, dev, fd);
+        set_fs(oldfs);
+        return fd;
+    }
+
+    nReadSize = sys_read(fd, buf, sizeof(buf) - 1);
+    pr_debug("%s: nReadSize:%d\n", __func__, nReadSize);
+
+    eCheck = simple_strtoul(buf,&pvalue,10);
+    pr_debug("%s: eCheck = %d\n", __func__, eCheck);
+
+    set_fs(oldfs);
+    sys_close(fd);
+
+    if (eCheck > 0)
+        return eCheck;
+    else
+        return 0;
+}
+
+static void aw8898_vbat_monitor_work_routine(struct work_struct *work)
+{
+    struct aw8898 *aw8898 = container_of(work, struct aw8898, vbat_monitor_work);
+    unsigned int reg_val = 0;
+    int sys_vbat_vol = 0;
+
+    pr_info("%s enter\n", __func__);
+
+    aw8898_i2c_read(aw8898, AW8898_REG_PWMCTRL, &reg_val);
+    if((reg_val&AW8898_BIT_PWMCTRL_HMUTE_ENABLE) == AW8898_BIT_PWMCTRL_HMUTE_DISABLE) {
+        sys_vbat_vol = aw8898_get_sys_battery_info(SYS_BAT_DEV);
+        pr_info("%s: get sys battery = %d\n", __func__, sys_vbat_vol);
+        if((sys_vbat_vol < AW8898_SYS_VBAT_LIMIT) && (sys_vbat_vol > AW8898_SYS_VBAT_MIN)) {
+            aw8898_i2c_write_bits(aw8898, AW8898_REG_GENCTRL,
+                AW8898_BIT_GENCTRL_BST_ILIMIT_MASK, (aw8898->bst_ilimit<<4));
+        }
+        aw8898_vbat_monitor_start(aw8898);
+    }
+}
+
+static int aw8898_vbat_monitor_init(struct aw8898 *aw8898)
+{
+    pr_info("%s enter\n", __func__);
+
+    aw8898->bst_ilimit = 0x00;
+
+    hrtimer_init(&aw8898->vbat_monitor_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+    aw8898->vbat_monitor_timer.function = aw8898_vbat_monitor_timer_func;
+    INIT_WORK(&aw8898->vbat_monitor_work, aw8898_vbat_monitor_work_routine);
+    return 0;
+}
+#endif
+/******************************************************
+ *
+ * sys bin attribute
+ *
+ *****************************************************/
+static ssize_t aw8898_reg_write(struct file *filp, struct kobject *kobj,
+        struct bin_attribute *bin_attr,
+        char *buf, loff_t off, size_t count)
+{
+    struct device *dev = container_of(kobj, struct device, kobj);
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+
+    if (count != 1) {
+        pr_info("invalid register address");
+        return -EINVAL;
+    }
+
+    aw8898->reg = buf[0];
+
+    return 1;
+}
+
+static ssize_t aw8898_rw_write(struct file *filp, struct kobject *kobj,
+        struct bin_attribute *bin_attr,
+        char *buf, loff_t off, size_t count)
+{
+    struct device *dev = container_of(kobj, struct device, kobj);
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+    u8 *data;
+    int ret;
+    int retries = AW_I2C_RETRIES;
+
+    data = kmalloc(count+1, GFP_KERNEL);
+    if (data == NULL) {
+        pr_err("can not allocate memory\n");
+        return  -ENOMEM;
+    }
+
+    data[0] = aw8898->reg;
+    memcpy(&data[1], buf, count);
+
+    retry:
+    ret = i2c_master_send(aw8898->i2c, data, count+1);
+    if (ret < 0) {
+        pr_warn("i2c error, retries left: %d\n", retries);
+        if (retries) {
+              retries--;
+              msleep(AW_I2C_RETRY_DELAY);
+              goto retry;
+        }
+    }
+
+    kfree(data);
+    return ret;
+}
+
+static ssize_t aw8898_rw_read(struct file *filp, struct kobject *kobj,
+        struct bin_attribute *bin_attr,
+        char *buf, loff_t off, size_t count)
+{
+    struct device *dev = container_of(kobj, struct device, kobj);
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+    struct i2c_msg msgs[] = {
+        {
+            .addr = aw8898->i2c->addr,
+            .flags = 0,
+            .len = 1,
+            .buf = &aw8898->reg,
+        },
+        {
+            .addr = aw8898->i2c->addr,
+            .flags = I2C_M_RD,
+            .len = count,
+            .buf = buf,
+        },
+    };
+    int ret;
+    int retries = AW_I2C_RETRIES;
+    retry:
+    ret = i2c_transfer(aw8898->i2c->adapter, msgs, ARRAY_SIZE(msgs));
+    if (ret < 0) {
+        pr_warn("i2c error, retries left: %d\n", retries);
+        if (retries) {
+            retries--;
+            msleep(AW_I2C_RETRY_DELAY);
+            goto retry;
+        }
+        return ret;
+    }
+    /* ret contains the number of i2c messages send */
+    return 1 + ((ret > 1) ? count : 0);
+}
+
+static struct bin_attribute dev_attr_rw = {
+    .attr = {
+        .name = "rw",
+        .mode = S_IRUSR | S_IWUSR,
+    },
+    .size = 0,
+    .read = aw8898_rw_read,
+    .write = aw8898_rw_write,
+};
+
+static struct bin_attribute dev_attr_regaddr = {
+    .attr = {
+        .name = "regaddr",
+        .mode = S_IWUSR,
+    },
+    .size = 0,
+    .read = NULL,
+    .write = aw8898_reg_write,
+};
+
+/******************************************************
+ *
+ * sys group attribute: reg
+ *
+ ******************************************************/
+static ssize_t aw8898_reg_store(struct device *dev, struct device_attribute *attr,
+        const char *buf, size_t count)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+
+    unsigned int databuf[2] = {0};
+
+    if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) {
+        aw8898_i2c_write(aw8898, databuf[0], databuf[1]);
+    }
+
+    return count;
+}
+
+static ssize_t aw8898_reg_show(struct device *dev, struct device_attribute *attr,
+        char *buf)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+    ssize_t len = 0;
+    unsigned char i = 0;
+    unsigned int reg_val = 0;
+    for(i = 0; i < AW8898_REG_MAX; i ++) {
+    if(!(aw8898_reg_access[i]&REG_RD_ACCESS))
+       continue;
+        aw8898_i2c_read(aw8898, i, &reg_val);
+        len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%02x=0x%04x \n", i, reg_val);
+    }
+    return len;
+}
+
+static ssize_t aw8898_spk_rcv_store(struct device *dev, struct device_attribute *attr,
+        const char *buf, size_t count)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+
+    unsigned int databuf[2] = {0};
+
+    if(1 == sscanf(buf, "%d", &databuf[0])) {
+        aw8898->spk_rcv_mode = databuf[0];
+    }
+
+    return count;
+}
+
+static ssize_t aw8898_spk_rcv_show(struct device *dev, struct device_attribute *attr,
+        char *buf)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+    ssize_t len = 0;
+    if(aw8898->spk_rcv_mode == AW8898_SPEAKER_MODE) {
+        len += snprintf(buf+len, PAGE_SIZE-len, "aw8898 spk_rcv: %d, speaker mode\n", aw8898->spk_rcv_mode);
+    } else if (aw8898->spk_rcv_mode == AW8898_RECEIVER_MODE) {
+        len += snprintf(buf+len, PAGE_SIZE-len, "aw8898 spk_rcv: %d, receiver mode\n", aw8898->spk_rcv_mode);
+    } else {
+        len += snprintf(buf+len, PAGE_SIZE-len, "aw8898 spk_rcv: %d, unknown mode\n", aw8898->spk_rcv_mode);
+    }
+
+    return len;
+}
+
+static ssize_t aw8898_bst_ilimit_store(struct device *dev, struct device_attribute *attr,
+        const char *buf, size_t count)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+
+    unsigned int databuf[2] = {0};
+
+    if(1 == sscanf(buf, "%x", &databuf[0])) {
+        aw8898->bst_ilimit = databuf[0];
+    }
+
+    return count;
+}
+
+static ssize_t aw8898_bst_ilimit_show(struct device *dev, struct device_attribute *attr,
+        char *buf)
+{
+    struct aw8898 *aw8898 = dev_get_drvdata(dev);
+    ssize_t len = 0;
+
+    len += snprintf(buf+len, PAGE_SIZE-len, "aw8898 bst_ilimit=0x%02x\n", aw8898->bst_ilimit);
+
+    return len;
+}
+static DEVICE_ATTR(reg, S_IWUSR | S_IRUGO, aw8898_reg_show, aw8898_reg_store);
+static DEVICE_ATTR(spk_rcv, S_IWUSR | S_IRUGO, aw8898_spk_rcv_show, aw8898_spk_rcv_store);
+static DEVICE_ATTR(bst_ilimit, S_IWUSR | S_IRUGO, aw8898_bst_ilimit_show, aw8898_bst_ilimit_store);
+
+static struct attribute *aw8898_attributes[] = {
+    &dev_attr_reg.attr,
+    &dev_attr_spk_rcv.attr,
+    &dev_attr_bst_ilimit.attr,
+    NULL
+};
+
+static struct attribute_group aw8898_attribute_group = {
+    .attrs = aw8898_attributes
+};
+
+
+/******************************************************
+ *
+ * i2c driver
+ *
+ ******************************************************/
+static int aw8898_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+    struct snd_soc_dai_driver *dai;
+    struct aw8898 *aw8898;
+    struct device_node *np = i2c->dev.of_node;
+    int irq_flags = 0;
+    int ret = -1;
+
+    pr_info("%s enter\n", __func__);
+
+    if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
+        dev_err(&i2c->dev, "check_functionality failed\n");
+        return -EIO;
+    }
+
+    aw8898 = devm_kzalloc(&i2c->dev, sizeof(struct aw8898), GFP_KERNEL);
+    if (aw8898 == NULL)
+        return -ENOMEM;
+
+    aw8898->dev = &i2c->dev;
+    aw8898->i2c = i2c;
+
+    /* aw8898 regmap */
+    aw8898->regmap = devm_regmap_init_i2c(i2c, &aw8898_regmap);
+    if (IS_ERR(aw8898->regmap)) {
+        ret = PTR_ERR(aw8898->regmap);
+        dev_err(&i2c->dev, "%s: failed to allocate register map: %d\n", __func__, ret);
+        goto err_regmap;
+    }
+
+    i2c_set_clientdata(i2c, aw8898);
+    mutex_init(&aw8898->cfg_lock);
+
+    /* aw8898 rst & int */
+    if (np) {
+        ret = aw8898_parse_dt(&i2c->dev, aw8898, np);
+        if (ret) {
+              dev_err(&i2c->dev, "%s: failed to parse device tree node\n", __func__);
+              goto err_parse_dt;
+        }
+    } else {
+        aw8898->reset_gpio = -1;
+        aw8898->irq_gpio = -1;
+    }
+
+    if (gpio_is_valid(aw8898->reset_gpio)) {
+        ret = devm_gpio_request_one(&i2c->dev, aw8898->reset_gpio,
+              GPIOF_OUT_INIT_LOW, "aw8898_rst");
+        if (ret){
+              dev_err(&i2c->dev, "%s: rst request failed\n", __func__);
+              goto err_gpio_request;
+        }
+    }
+
+    if (gpio_is_valid(aw8898->irq_gpio)) {
+        ret = devm_gpio_request_one(&i2c->dev, aw8898->irq_gpio,
+              GPIOF_DIR_IN, "aw8898_int");
+        if (ret){
+              dev_err(&i2c->dev, "%s: int request failed\n", __func__);
+              goto err_gpio_request;
+        }
+    }
+
+    /* hardware reset */
+    aw8898_hw_reset(aw8898);
+
+    /* aw8898 chip id */
+    ret = aw8898_read_chipid(aw8898);
+    if (ret < 0) {
+        dev_err(&i2c->dev, "%s: aw8898_read_chipid failed ret=%d\n", __func__, ret);
+        goto err_id;
+    }
+
+    /* aw8898 device name */
+    if (i2c->dev.of_node) {
+        dev_set_name(&i2c->dev, "%s", "aw8898_smartpa");
+    } else {
+        dev_err(&i2c->dev, "%s failed to set device name: %d\n", __func__, ret);
+    }
+
+    /* register codec */
+    dai = devm_kzalloc(&i2c->dev, sizeof(aw8898_dai), GFP_KERNEL);
+    if (!dai) {
+        goto err_dai_kzalloc;
+    }
+    memcpy(dai, aw8898_dai, sizeof(aw8898_dai));
+    pr_info("%s dai->name(%s)\n", __func__, dai->name);
+
+    ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aw8898,
+            dai, ARRAY_SIZE(aw8898_dai));
+    if (ret < 0) {
+        dev_err(&i2c->dev, "%s failed to register aw8898: %d\n", __func__, ret);
+        goto err_register_codec;
+    }
+
+    /* aw8898 irq */
+    if (gpio_is_valid(aw8898->irq_gpio) &&
+        !(aw8898->flags & AW8898_FLAG_SKIP_INTERRUPTS)) {
+        aw8898_interrupt_setup(aw8898);
+        /* register irq handler */
+        irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+        ret = devm_request_threaded_irq(&i2c->dev,
+                          gpio_to_irq(aw8898->irq_gpio),
+                          NULL, aw8898_irq, irq_flags,
+                          "aw8898", aw8898);
+        if (ret != 0) {
+              dev_err(&i2c->dev, "failed to request IRQ %d: %d\n",
+                          gpio_to_irq(aw8898->irq_gpio), ret);
+              goto err_irq;
+        }
+    } else {
+        dev_info(&i2c->dev, "%s skipping IRQ registration\n", __func__);
+        /* disable feature support if gpio was invalid */
+        aw8898->flags |= AW8898_FLAG_SKIP_INTERRUPTS;
+    }
+
+    /* Register the sysfs files for climax backdoor access */
+    ret = device_create_bin_file(&i2c->dev, &dev_attr_rw);
+    if (ret)
+        dev_info(&i2c->dev, "%s error creating sysfs files: rw\n", __func__);
+    ret = device_create_bin_file(&i2c->dev, &dev_attr_regaddr);
+    if (ret)
+        dev_info(&i2c->dev, "%s error creating sysfs files: regaddr\n", __func__);
+
+    dev_set_drvdata(&i2c->dev, aw8898);
+    ret = sysfs_create_group(&i2c->dev.kobj, &aw8898_attribute_group);
+    if (ret < 0) {
+        dev_info(&i2c->dev, "%s error creating sysfs attr files\n", __func__);
+        goto err_sysfs;
+    }
+
+#ifdef AW8898_VBAT_MONITOR
+    aw8898_vbat_monitor_init(aw8898);
+#endif
+    pr_info("%s probe completed successfully!\n", __func__);
+
+    return 0;
+
+err_sysfs:
+    device_remove_bin_file(&i2c->dev, &dev_attr_regaddr);
+    device_remove_bin_file(&i2c->dev, &dev_attr_rw);
+    devm_free_irq(&i2c->dev, gpio_to_irq(aw8898->irq_gpio), aw8898);
+err_irq:
+    snd_soc_unregister_codec(&i2c->dev);
+err_register_codec:
+    devm_kfree(&i2c->dev, dai);
+    dai = NULL;
+err_dai_kzalloc:
+err_id:
+    if (gpio_is_valid(aw8898->reset_gpio))
+        devm_gpio_free(&i2c->dev, aw8898->reset_gpio);
+    if (gpio_is_valid(aw8898->irq_gpio))
+        devm_gpio_free(&i2c->dev, aw8898->irq_gpio);
+err_gpio_request:
+err_parse_dt:
+err_regmap:
+    devm_kfree(&i2c->dev, aw8898);
+    aw8898 = NULL;
+    return ret;
+}
+
+static int aw8898_i2c_remove(struct i2c_client *i2c)
+{
+    struct aw8898 *aw8898 = i2c_get_clientdata(i2c);
+
+    pr_info("%s enter\n", __func__);
+
+    device_remove_bin_file(&i2c->dev, &dev_attr_regaddr);
+    device_remove_bin_file(&i2c->dev, &dev_attr_rw);
+    devm_free_irq(&i2c->dev, gpio_to_irq(aw8898->irq_gpio), aw8898);
+
+    snd_soc_unregister_codec(&i2c->dev);
+
+    if (gpio_is_valid(aw8898->irq_gpio))
+        devm_gpio_free(&i2c->dev, aw8898->irq_gpio);
+    if (gpio_is_valid(aw8898->reset_gpio))
+        devm_gpio_free(&i2c->dev, aw8898->reset_gpio);
+
+    return 0;
+}
+
+static const struct i2c_device_id aw8898_i2c_id[] = {
+    { AW8898_I2C_NAME, 0 },
+    { }
+};
+MODULE_DEVICE_TABLE(i2c, aw8898_i2c_id);
+
+static struct of_device_id aw8898_dt_match[] = {
+    { .compatible = "awinic,aw8898_smartpa" },
+    { },
+};
+
+static struct i2c_driver aw8898_i2c_driver = {
+    .driver = {
+        .name = AW8898_I2C_NAME,
+        .owner = THIS_MODULE,
+        .of_match_table = of_match_ptr(aw8898_dt_match),
+    },
+    .probe = aw8898_i2c_probe,
+    .remove = aw8898_i2c_remove,
+    .id_table = aw8898_i2c_id,
+};
+
+
+static int __init aw8898_i2c_init(void)
+{
+    int ret = 0;
+
+    pr_info("aw8898 driver version %s\n", AW8898_VERSION);
+
+    ret = i2c_add_driver(&aw8898_i2c_driver);
+    if(ret){
+        pr_err("fail to add aw8898 device into i2c\n");
+        return ret;
+    }
+
+    return 0;
+}
+module_init(aw8898_i2c_init);
+
+
+static void __exit aw8898_i2c_exit(void)
+{
+    i2c_del_driver(&aw8898_i2c_driver);
+}
+module_exit(aw8898_i2c_exit);
+
+
+MODULE_DESCRIPTION("ASoC AW8898 Smart PA Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/aw/aw8898.h b/sound/soc/codecs/aw/aw8898.h
new file mode 100755
index 0000000..2042f5e
--- /dev/null
+++ b/sound/soc/codecs/aw/aw8898.h
@@ -0,0 +1,72 @@
+#ifndef _AW8898_H_
+#define _AW8898_H_
+
+
+/*
+ * i2c transaction on Linux limited to 64k
+ * (See Linux kernel documentation: Documentation/i2c/writing-clients)
+*/
+#define MAX_I2C_BUFFER_SIZE 65536
+
+#define AW8898_FLAG_START_ON_MUTE   (1 << 0)
+#define AW8898_FLAG_SKIP_INTERRUPTS     (1 << 1)
+#define AW8898_FLAG_SAAM_AVAILABLE      (1 << 2)
+#define AW8898_FLAG_STEREO_DEVICE       (1 << 3)
+#define AW8898_FLAG_MULTI_MIC_INPUTS    (1 << 4)
+
+#define AW8898_NUM_RATES                9
+
+#define AW8898_MAX_REGISTER             0xff
+
+//#define AW8898_VBAT_MONITOR
+#ifdef AW8898_VBAT_MONITOR
+#define SYS_BAT_DEV "/sys/class/power_supply/battery/voltage_now"
+#define AW8898_SYS_VBAT_LIMIT           3600000
+#define AW8898_SYS_VBAT_MIN             3000000
+#endif
+enum aw8898_chipid{
+    AW8898_ID,
+};
+
+enum aw8898_mode_spk_rcv{
+    AW8898_SPEAKER_MODE = 0,
+    AW8898_RECEIVER_MODE = 1,
+};
+
+struct aw8898 {
+    struct regmap *regmap;
+    struct i2c_client *i2c;
+    struct snd_soc_codec *codec;
+    struct device *dev;
+    struct mutex cfg_lock;
+#ifdef AW8898_VBAT_MONITOR
+    struct hrtimer vbat_monitor_timer;
+    struct work_struct vbat_monitor_work;
+#endif
+    int sysclk;
+    int rate;
+    int pstream;
+    int cstream;
+
+    int reset_gpio;
+    int irq_gpio;
+
+#ifdef CONFIG_DEBUG_FS
+    struct dentry *dbg_dir;
+#endif
+    u8 reg;
+
+    unsigned int flags;
+    unsigned int chipid;
+    unsigned int init;
+    unsigned int spk_rcv_mode;
+    unsigned int bst_ilimit;
+};
+
+struct aw8898_container{
+    int len;
+    unsigned char data[];
+};
+
+
+#endif
diff --git a/sound/soc/codecs/aw/aw8898_reg.h b/sound/soc/codecs/aw/aw8898_reg.h
new file mode 100755
index 0000000..c66927c
--- /dev/null
+++ b/sound/soc/codecs/aw/aw8898_reg.h
@@ -0,0 +1,448 @@
+#ifndef _AW8898_REG_H_
+#define _AW8898_REG_H_
+
+/********************************************
+ * Register List
+ *******************************************/
+#define AW8898_REG_ID           0x00
+#define AW8898_REG_SYSST        0x01
+#define AW8898_REG_SYSINT       0x02
+#define AW8898_REG_SYSINTM      0x03
+#define AW8898_REG_SYSCTRL      0x04
+#define AW8898_REG_I2SCTRL      0x05
+#define AW8898_REG_I2STXCFG     0x06
+#define AW8898_REG_PWMCTRL      0x08
+#define AW8898_REG_HAGCCFG1     0x09
+#define AW8898_REG_HAGCCFG2     0x0A
+#define AW8898_REG_HAGCCFG3     0x0B
+#define AW8898_REG_HAGCCFG4     0x0C
+#define AW8898_REG_HAGCCFG5     0x0D
+#define AW8898_REG_HAGCCFG6     0x0E
+#define AW8898_REG_HAGCCFG7     0x0F
+#define AW8898_REG_HAGCST       0x10
+#define AW8898_REG_DBGCTRL      0x20
+#define AW8898_REG_I2SCFG       0x21
+#define AW8898_REG_I2SSTAT      0x22
+#define AW8898_REG_I2SCAPCNT    0x23
+#define AW8898_REG_GENCTRL      0x60
+#define AW8898_REG_BSTCTRL1     0x61
+#define AW8898_REG_BSTCTRL2     0x62
+#define AW8898_REG_PLLCTRL1     0x63
+#define AW8898_REG_PLLCTRL2     0x64
+#define AW8898_REG_TESTCTRL     0x65
+#define AW8898_REG_AMPDBG1      0x66
+#define AW8898_REG_AMPDBG2      0x67
+#define AW8898_REG_BSTDBG1      0x68
+#define AW8898_REG_CDACTRL1     0x69
+#define AW8898_REG_CDACTRL2     0x6A
+#define AW8898_REG_TESTCTRL2    0x6B
+
+#define AW8898_REG_MAX          0x6F
+
+/********************************************
+ * Register Access
+ *******************************************/
+#define REG_NONE_ACCESS 0
+#define REG_RD_ACCESS  1 << 0
+#define REG_WR_ACCESS  1 << 1
+
+const unsigned char aw8898_reg_access[AW8898_REG_MAX]={
+  [AW8898_REG_ID        ]= REG_RD_ACCESS,
+  [AW8898_REG_SYSST     ]= REG_RD_ACCESS,
+  [AW8898_REG_SYSINT    ]= REG_RD_ACCESS,
+  [AW8898_REG_SYSINTM   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_SYSCTRL   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_I2SCTRL   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_I2STXCFG  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_PWMCTRL   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG1  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG2  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG3  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG4  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG5  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG6  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCCFG7  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_HAGCST    ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_DBGCTRL   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_I2SCFG    ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_I2SSTAT   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_I2SCAPCNT ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_GENCTRL   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_BSTCTRL1  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_BSTCTRL2  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_PLLCTRL1  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_PLLCTRL2  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_TESTCTRL  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_AMPDBG1   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_AMPDBG2   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_BSTDBG1   ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_CDACTRL1  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_CDACTRL2  ]= REG_RD_ACCESS|REG_WR_ACCESS,
+  [AW8898_REG_TESTCTRL2 ]= REG_RD_ACCESS|REG_WR_ACCESS,
+};
+
+/******************************************************
+ * Register Detail
+ *****************************************************/
+// SYSST
+#define AW8898_BIT_SYSST_UVLOS                      ( 1<<14)
+#define AW8898_BIT_SYSST_ADPS                       ( 1<<13)
+#define AW8898_BIT_SYSST_DSPS                       ( 1<<12)
+#define AW8898_BIT_SYSST_BSTOCS                     ( 1<<11)
+#define AW8898_BIT_SYSST_OVPS                       ( 1<<10)
+#define AW8898_BIT_SYSST_BSTS                       ( 1<< 9)
+#define AW8898_BIT_SYSST_SWS                        ( 1<< 8)
+#define AW8898_BIT_SYSST_CLIPS                      ( 1<< 7)
+#define AW8898_BIT_SYSST_WDS                        ( 1<< 6)
+#define AW8898_BIT_SYSST_NOCLKS                     ( 1<< 5)
+#define AW8898_BIT_SYSST_CLKS                       ( 1<< 4)
+#define AW8898_BIT_SYSST_OCDS                       ( 1<< 3)
+#define AW8898_BIT_SYSST_OTLS                       ( 1<< 2)
+#define AW8898_BIT_SYSST_OTHS                       ( 1<< 1)
+#define AW8898_BIT_SYSST_PLLS                       ( 1<< 0)
+
+// SYSINT
+#define AW8898_BIT_SYSINT_UVLOI                     ( 1<<14)
+#define AW8898_BIT_SYSINT_ADPI                      ( 1<<13)
+#define AW8898_BIT_SYSINT_DSPI                      ( 1<<12)
+#define AW8898_BIT_SYSINT_BSTOCI                    ( 1<<11)
+#define AW8898_BIT_SYSINT_OVPI                      ( 1<<10)
+#define AW8898_BIT_SYSINT_BSTI                      ( 1<< 9)
+#define AW8898_BIT_SYSINT_SWI                       ( 1<< 8)
+#define AW8898_BIT_SYSINT_CLIPI                     ( 1<< 7)
+#define AW8898_BIT_SYSINT_WDI                       ( 1<< 6)
+#define AW8898_BIT_SYSINT_NOCLKI                    ( 1<< 5)
+#define AW8898_BIT_SYSINT_CLKI                      ( 1<< 4)
+#define AW8898_BIT_SYSINT_OCDI                      ( 1<< 3)
+#define AW8898_BIT_SYSINT_OTLI                      ( 1<< 2)
+#define AW8898_BIT_SYSINT_OTHI                      ( 1<< 1)
+#define AW8898_BIT_SYSINT_PLLI                      ( 1<< 0)
+
+// SYSINTM
+#define AW8898_BIT_SYSINTM_UVLOM                    ( 1<<14)
+#define AW8898_BIT_SYSINTM_ADPM                     ( 1<<13)
+#define AW8898_BIT_SYSINTM_DSPM                     ( 1<<12)
+#define AW8898_BIT_SYSINTM_BSTOCM                   ( 1<<11)
+#define AW8898_BIT_SYSINTM_OVPM                     ( 1<<10)
+#define AW8898_BIT_SYSINTM_BSTM                     ( 1<< 9)
+#define AW8898_BIT_SYSINTM_SWM                      ( 1<< 8)
+#define AW8898_BIT_SYSINTM_CLIPM                    ( 1<< 7)
+#define AW8898_BIT_SYSINTM_WDM                      ( 1<< 6)
+#define AW8898_BIT_SYSINTM_NOCLKM                   ( 1<< 5)
+#define AW8898_BIT_SYSINTM_CLKM                     ( 1<< 4)
+#define AW8898_BIT_SYSINTM_OCDM                     ( 1<< 3)
+#define AW8898_BIT_SYSINTM_OTLM                     ( 1<< 2)
+#define AW8898_BIT_SYSINTM_OTHM                     ( 1<< 1)
+#define AW8898_BIT_SYSINTM_PLLM                     ( 1<< 0)
+
+// SYSCTRL
+#define AW8898_BIT_SYSCTRL_INTMODE_MASK             (~( 3<< 8))
+#define AW8898_BIT_SYSCTRL_INT_HIGH_PP              ( 3<< 8)
+#define AW8898_BIT_SYSCTRL_INT_LOW_PP               ( 2<< 8)
+#define AW8898_BIT_SYSCTRL_INT_HIGH_OD              ( 1<< 8)
+#define AW8898_BIT_SYSCTRL_INT_LOW_OD               ( 0<< 8)
+#define AW8898_BIT_SYSCTRL_MODE_MASK                (~( 1<< 7))
+#define AW8898_BIT_SYSCTRL_RCV_MODE                 ( 1<< 7)
+#define AW8898_BIT_SYSCTRL_SPK_MODE                 ( 0<< 7)
+#define AW8898_BIT_SYSCTRL_I2SEN_MASK               (~( 1<< 6))
+#define AW8898_BIT_SYSCTRL_I2S_ENABLE               ( 1<< 6)
+#define AW8898_BIT_SYSCTRL_I2S_DISABLE              ( 0<< 6)
+#define AW8898_BIT_SYSCTRL_WSINV_MASK               (~( 1<< 5))
+#define AW8898_BIT_SYSCTRL_WS_INVERT                ( 1<< 5)
+#define AW8898_BIT_SYSCTRL_WS_NO_INVERT             ( 0<< 5)
+#define AW8898_BIT_SYSCTRL_BCKINV_MASK              (~( 1<< 4))
+#define AW8898_BIT_SYSCTRL_BCK_INVERT               ( 1<< 4)
+#define AW8898_BIT_SYSCTRL_BCK_NO_INVERT            ( 0<< 4)
+#define AW8898_BIT_SYSCTRL_IPLL_MASK                (~( 1<< 3))
+#define AW8898_BIT_SYSCTRL_PLL_WORD                 ( 1<< 3)
+#define AW8898_BIT_SYSCTRL_PLL_BIT                  ( 0<< 3)
+#define AW8898_BIT_SYSCTRL_DSPBY_MASK               (~( 1<< 2))
+#define AW8898_BIT_SYSCTRL_DSP_BYPASS               ( 1<< 2)
+#define AW8898_BIT_SYSCTRL_DSP_WORK                 ( 0<< 2)
+#define AW8898_BIT_SYSCTRL_CP_MASK                  (~( 1<< 1))
+#define AW8898_BIT_SYSCTRL_CP_PDN                   ( 1<< 1)
+#define AW8898_BIT_SYSCTRL_CP_ACTIVE                ( 0<< 1)
+#define AW8898_BIT_SYSCTRL_PW_MASK                  (~( 1<< 0))
+#define AW8898_BIT_SYSCTRL_PW_PDN                   ( 1<< 0)
+#define AW8898_BIT_SYSCTRL_PW_ACTIVE                ( 0<< 0)
+
+// I2SCTRL
+#define AW8898_BIT_I2SCTRL_INPLEV_MASK              (~( 1<<13))
+#define AW8898_BIT_I2SCTRL_INPLEV_0DB               ( 1<<13)
+#define AW8898_BIT_I2SCTRL_INPLEV_NEG_6DB           ( 0<<13)
+#define AW8898_BIT_I2SCTRL_STEREO_MASK              (~( 1<<12))
+#define AW8898_BIT_I2SCTRL_STEREO_ENABLE            ( 1<<12)
+#define AW8898_BIT_I2SCTRL_STEREO_DISABLE           ( 0<<12)
+#define AW8898_BIT_I2SCTRL_CHS_MASK                 (~( 3<<10))
+#define AW8898_BIT_I2SCTRL_CHS_MONO                 ( 3<<10)
+#define AW8898_BIT_I2SCTRL_CHS_RIGHT                ( 2<<10)
+#define AW8898_BIT_I2SCTRL_CHS_LEFT                 ( 1<<10)
+#define AW8898_BIT_I2SCTRL_MD_MASK                  (~( 3<< 8))
+#define AW8898_BIT_I2SCTRL_MD_LSB                   ( 2<< 8)
+#define AW8898_BIT_I2SCTRL_MD_MSB                   ( 1<< 8)
+#define AW8898_BIT_I2SCTRL_MD_STD                   ( 0<< 8)
+#define AW8898_BIT_I2SCTRL_FMS_MASK                 (~( 3<< 6))
+#define AW8898_BIT_I2SCTRL_FMS_32BIT                ( 3<< 6)
+#define AW8898_BIT_I2SCTRL_FMS_24BIT                ( 2<< 6)
+#define AW8898_BIT_I2SCTRL_FMS_20BIT                ( 1<< 6)
+#define AW8898_BIT_I2SCTRL_FMS_16BIT                ( 0<< 6)
+#define AW8898_BIT_I2SCTRL_BCK_MASK                 (~( 3<< 4))
+#define AW8898_BIT_I2SCTRL_BCK_64FS                 ( 2<< 4)
+#define AW8898_BIT_I2SCTRL_BCK_48FS                 ( 1<< 4)
+#define AW8898_BIT_I2SCTRL_BCK_32FS                 ( 0<< 4)
+#define AW8898_BIT_I2SCTRL_SR_MASK                  (~(15<< 0))
+#define AW8898_BIT_I2SCTRL_SR_192K                  (10<< 0)
+#define AW8898_BIT_I2SCTRL_SR_96K                   ( 9<< 0)
+#define AW8898_BIT_I2SCTRL_SR_48K                   ( 8<< 0)
+#define AW8898_BIT_I2SCTRL_SR_44P1K                 ( 7<< 0)
+#define AW8898_BIT_I2SCTRL_SR_32K                   ( 6<< 0)
+#define AW8898_BIT_I2SCTRL_SR_24K                   ( 5<< 0)
+#define AW8898_BIT_I2SCTRL_SR_22K                   ( 4<< 0)
+#define AW8898_BIT_I2SCTRL_SR_16K                   ( 3<< 0)
+#define AW8898_BIT_I2SCTRL_SR_12K                   ( 2<< 0)
+#define AW8898_BIT_I2SCTRL_SR_11K                   ( 1<< 0)
+#define AW8898_BIT_I2SCTRL_SR_8K                    ( 0<< 0)
+
+
+// I2STXCFG
+#define AW8898_BIT_I2STXCFG_FSYNC_MASK              (~( 1<<15))
+#define AW8898_BIT_I2STXCFG_FSYNC_BCK_CYCLE         ( 1<<15)
+#define AW8898_BIT_I2STXCFG_FSYNC_ONE_SLOT          ( 0<<15)
+#define AW8898_BIT_I2STXCFG_SLOT_NUM_MASK           (~( 1<<14))
+#define AW8898_BIT_I2STXCFG_SLOT_NUM_4_TIMES        ( 1<<14)
+#define AW8898_BIT_I2STXCFG_SLOT_NUM_2_TIMES        ( 0<<14)
+#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_MASK        (~(15<<12))
+#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_3           ( 3<<12)
+#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_2           ( 2<<12)
+#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_1           ( 1<<12)
+#define AW8898_BIT_I2STXCFG_TX_SLOT_VLD_0           ( 0<<12)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_MASK        (~(15<< 8))
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3_2         (12<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3_1         (10<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3_0         ( 9<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_2_1         ( 6<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_2_0         ( 5<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_1_0         ( 3<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_3           ( 8<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_2           ( 4<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_1           ( 2<< 8)
+#define AW8898_BIT_I2STXCFG_RX_SLOT_VLD_0           ( 1<< 8)
+#define AW8898_BIT_I2STXCFG_DRVSTREN_MASK           (~( 1<< 5))
+#define AW8898_BIT_I2STXCFG_DRVSTREN_8MA            ( 1<< 5)
+#define AW8898_BIT_I2STXCFG_DRVSTREN_2MA            ( 0<< 5)
+#define AW8898_BIT_I2STXCFG_DOHZ_MASK               (~( 1<< 4))
+#define AW8898_BIT_I2STXCFG_DOHZ_HIZ                ( 1<< 4)
+#define AW8898_BIT_I2STXCFG_DOHZ_GND                ( 0<< 4)
+#define AW8898_BIT_I2STXCFG_DSEL_MASK               (~( 3<< 2))
+#define AW8898_BIT_I2STXCFG_DSEL_DSP                ( 2<< 2)
+#define AW8898_BIT_I2STXCFG_DSEL_GAIN               ( 1<< 2)
+#define AW8898_BIT_I2STXCFG_DSEL_ZERO               ( 0<< 2)
+#define AW8898_BIT_I2STXCFG_CHS_MASK                (~( 1<< 1))
+#define AW8898_BIT_I2STXCFG_CHS_RIGHT               ( 1<< 1)
+#define AW8898_BIT_I2STXCFG_CHS_LEFT                ( 0<< 1)
+#define AW8898_BIT_I2STXCFG_TX_MASK                 (~( 1<< 0))
+#define AW8898_BIT_I2STXCFG_TX_ENABLE               ( 1<< 0)
+#define AW8898_BIT_I2STXCFG_TX_DISABLE              ( 0<< 0)
+
+// PWMCTRL
+#define AW8898_BIT_PWMCTRL_DSMZTH_MASK              (~(15<<12))
+#define AW8898_BIT_PWMCTRL_DSMZTH_UNIT              ( 1<<12)
+#define AW8898_BIT_PWMCTRL_PWMDELA_MASK             (~(15<< 8))
+#define AW8898_BIT_PWMCTRL_PWMDELA_UNIT             ( 1<< 8)
+#define AW8898_BIT_PWMCTRL_PWMDELB_MASK             (~(15<< 4))
+#define AW8898_BIT_PWMCTRL_PWMDELB_UNIT             ( 1<< 4)
+#define AW8898_BIT_PWMCTRL_PWMSH_MASK               (~( 1<< 3))
+#define AW8898_BIT_PWMCTRL_PWMSH_TRIANGLE           ( 1<< 3)
+#define AW8898_BIT_PWMCTRL_PWMSH_SAWTOOTH           ( 0<< 3)
+#define AW8898_BIT_PWMCTRL_PWMRES_MASK              (~( 1<< 2))
+#define AW8898_BIT_PWMCTRL_PWMRES_8BIT              ( 1<< 2)
+#define AW8898_BIT_PWMCTRL_PWMRES_7BIT              ( 0<< 2)
+#define AW8898_BIT_PWMCTRL_HDCCE_MASK               (~( 1<< 1))
+#define AW8898_BIT_PWMCTRL_HDCCE_ENABLE             ( 1<< 1)
+#define AW8898_BIT_PWMCTRL_HDCCE_DISABLE            ( 0<< 1)
+#define AW8898_BIT_PWMCTRL_HMUTE_MASK               (~( 1<< 0))
+#define AW8898_BIT_PWMCTRL_HMUTE_ENABLE             ( 1<< 0)
+#define AW8898_BIT_PWMCTRL_HMUTE_DISABLE            ( 0<< 0)
+
+// HAGCCFG1
+#define AW8898_BIT_HAGCCFG1_RVTH_MASK               (~(255<<8))
+#define AW8898_BIT_HAGCCFG1_RVTH_UNIT               ( 1<< 8)
+#define AW8898_BIT_HAGCCFG1_AVTH_MASK               (~(255<<0))
+#define AW8898_BIT_HAGCCFG1_AVTH_UNIT               ( 1<< 0)
+
+// HAGCCFG2
+#define AW8898_BIT_HAGCCFG2_ATTH_UNIT               ( 1<< 0)
+
+// HAGCCFG3
+#define AW8898_BIT_HAGCCFG3_RTTH_UNIT               ( 1<< 0)
+
+// HAGCCFG4
+#define AW8898_BIT_HAGCCFG4_MPD_MASK                (~( 1<<14))
+#define AW8898_BIT_HAGCCFG4_MPD_ENABLE              ( 1<<14)
+#define AW8898_BIT_HAGCCFG4_MPD_DISABLE             ( 0<<14)
+#define AW8898_BIT_HAGCCFG4_MPD_TTH_MASK            (~( 3<<12))
+#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P047           ( 3<<12)
+#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P032           ( 2<<12)
+#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P016           ( 1<<12)
+#define AW8898_BIT_HAGCCFG4_MPD_TTH_0P008           ( 0<<12)
+#define AW8898_BIT_HAGCCFG4_MPD_RTH_MASK            (~( 3<<10))
+#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P047           ( 3<<10)
+#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P032           ( 2<<10)
+#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P016           ( 1<<10)
+#define AW8898_BIT_HAGCCFG4_MPD_RTH_0P008           ( 0<<10)
+#define AW8898_BIT_HAGCCFG4_MPD_ATH_MASK            (~( 3<< 8))
+#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P047           ( 3<< 8)
+#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P032           ( 2<< 8)
+#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P016           ( 1<< 8)
+#define AW8898_BIT_HAGCCFG4_MPD_ATH_0P008           ( 0<< 8)
+#define AW8898_BIT_HAGCCFG4_HOLDTH_MASK             (~(255<< 0))
+
+// HAGCCFG5
+
+// HAGCCFG6
+
+// HAGCCFG7
+#define AW8898_BIT_HAGCCFG7_VOL_MASK                (~(255< 8))
+#define AW8898_VOLUME_MAX                           (0)
+#define AW8898_VOLUME_MIN                           (-255)
+#define AW8898_VOL_REG_SHIFT                        (8)
+
+// HAGCST
+#define AW8898_BIT_BSTVOUT_ST_10P25V                (15<< 0)
+#define AW8898_BIT_BSTVOUT_ST_10V                   (14<< 0)
+#define AW8898_BIT_BSTVOUT_ST_9P75V                 (13<< 0)
+#define AW8898_BIT_BSTVOUT_ST_9P5V                  (12<< 0)
+#define AW8898_BIT_BSTVOUT_ST_9P25V                 (11<< 0)
+#define AW8898_BIT_BSTVOUT_ST_9V                    (10<< 0)
+#define AW8898_BIT_BSTVOUT_ST_8P75V                 ( 9<< 0)
+#define AW8898_BIT_BSTVOUT_ST_8P5V                  ( 8<< 0)
+#define AW8898_BIT_BSTVOUT_ST_8P25V                 ( 7<< 0)
+#define AW8898_BIT_BSTVOUT_ST_8V                    ( 6<< 0)
+#define AW8898_BIT_BSTVOUT_ST_7P75V                 ( 5<< 0)
+#define AW8898_BIT_BSTVOUT_ST_7P5V                  ( 4<< 0)
+#define AW8898_BIT_BSTVOUT_ST_7P25V                 ( 3<< 0)
+#define AW8898_BIT_BSTVOUT_ST_7V                    ( 2<< 0)
+#define AW8898_BIT_BSTVOUT_ST_6P75V                 ( 1<< 0)
+#define AW8898_BIT_BSTVOUT_ST_6P5V                  ( 0<< 0)
+
+// DBGCTRL
+#define AW8898_BIT_DBGCTRL_LPBK_FAR_MASK            (~( 1<<15))
+#define AW8898_BIT_DBGCTRL_LPBK_FAR_ENABLE          ( 1<<15)
+#define AW8898_BIT_DBGCTRL_LPBK_FAR_DISABLE         ( 0<<15)
+#define AW8898_BIT_DBGCTRL_LPBK_NEAR_MASK           (~( 1<<14))
+#define AW8898_BIT_DBGCTRL_LPBK_NEAR_ENABLE         ( 1<<14)
+#define AW8898_BIT_DBGCTRL_LPBK_NEAR_DISABLE        ( 0<<14)
+#define AW8898_BIT_DBGCTRL_PDUVL_MASK               (~( 1<<13))
+#define AW8898_BIT_DBGCTRL_PDUVL_DISABLE            ( 1<<13)
+#define AW8898_BIT_DBGCTRL_PDUVL_ENABLE             ( 0<<13)
+#define AW8898_BIT_DBGCTRL_MUTE_MASK                (~( 1<<12))
+#define AW8898_BIT_DBGCTRL_MUTE_NO_AUTO             ( 1<<12)
+#define AW8898_BIT_DBGCTRL_MUTE_AUTO                ( 0<<12)
+#define AW8898_BIT_DBGCTRL_NOCLK_RESET_MASK         (~( 1<<11))
+#define AW8898_BIT_DBGCTRL_NOCLK_NO_RESET           ( 1<<11)
+#define AW8898_BIT_DBGCTRL_NOCLK_RESET              ( 0<<11)
+#define AW8898_BIT_DBGCTRL_PLL_UNLOCK_RESET_MASK    (~( 1<<10))
+#define AW8898_BIT_DBGCTRL_PLL_UNLOCK_NO_RESET      ( 1<<10)
+#define AW8898_BIT_DBGCTRL_PLL_UNLOCK_RESET         ( 0<<10)
+#define AW8898_BIT_DBGCTRL_CLKMD_MASK               (~( 1<< 9))
+#define AW8898_BIT_DBGCTRL_CLKMD_HALF               ( 1<< 9)
+#define AW8898_BIT_DBGCTRL_CLKMD_NORMAL             ( 0<< 9)
+#define AW8898_BIT_DBGCTRL_OSCPD_MASK               (~( 1<< 8))
+#define AW8898_BIT_DBGCTRL_OSCPD_ENABLE             ( 1<< 8)
+#define AW8898_BIT_DBGCTRL_OSCPD_DISABLE            ( 0<< 8)
+#define AW8898_BIT_DBGCTRL_AMPPD_MASK               (~( 1<< 7))
+#define AW8898_BIT_DBGCTRL_AMPPD_PDN                ( 1<< 7)
+#define AW8898_BIT_DBGCTRL_AMPPD_ACTIVE             ( 0<< 7)
+#define AW8898_BIT_DBGCTRL_PLLPD_MASK               (~( 1<< 6))
+#define AW8898_BIT_DBGCTRL_PLLPD_PDN                ( 1<< 6)
+#define AW8898_BIT_DBGCTRL_PLLPD_ACTIVE             ( 0<< 6)
+#define AW8898_BIT_DBGCTRL_I2SRST_MASK              (~( 1<< 5))
+#define AW8898_BIT_DBGCTRL_I2SRST_RESET             ( 1<< 5)
+#define AW8898_BIT_DBGCTRL_I2SRST_WORK              ( 0<< 5)
+#define AW8898_BIT_DBGCTRL_SYSRST_MASK              (~( 1<< 4))
+#define AW8898_BIT_DBGCTRL_SYSRST_RESET             ( 1<< 4)
+#define AW8898_BIT_DBGCTRL_SYSRST_WORK              ( 0<< 4)
+#define AW8898_BIT_DBGCTRL_SYSCE_MASK               (~( 1<< 0))
+#define AW8898_BIT_DBGCTRL_SYSCE_ENABLE             ( 1<< 0)
+#define AW8898_BIT_DBGCTRL_SYSCE_DISABLE            ( 0<< 0)
+
+
+// I2SCFG
+#define AW8898_BIT_I2SCFG_I2SRX_MASK                (~( 1<< 0))
+#define AW8898_BIT_I2SCFG_I2SRX_ENABLE              ( 1<< 0)
+#define AW8898_BIT_I2SCFG_I2SRX_DISABLE             ( 0<< 0)
+
+// I2SSAT
+#define AW8898_BIT_I2SSAT_DPSTAT                    ( 1<< 2)
+#define AW8898_BIT_I2SSAT_I2SROVS                   ( 1<< 1)
+#define AW8898_BIT_I2SSAT_I2STOVS                   ( 1<< 0)
+
+// GENCTRL
+#define AW8898_BIT_GENCTRL_BURST_PEAK_MASK          (~( 3<<14))
+#define AW8898_BIT_GENCTRL_BURST_PEAK_200MA         ( 3<<14)
+#define AW8898_BIT_GENCTRL_BURST_PEAK_160MA         ( 2<<14)
+#define AW8898_BIT_GENCTRL_BURST_PEAK_100MA         ( 1<<14)
+#define AW8898_BIT_GENCTRL_BURST_PEAK_130MA         ( 0<<14)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_MASK           (~( 7<< 9))
+#define AW8898_BIT_GENCTRL_BST_TDEG2_2P7S           ( 7<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_1P3S           ( 6<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_672MS          ( 5<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_336MS          ( 4<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_168MS          ( 3<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_84MS           ( 2<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_42MS           ( 1<< 9)
+#define AW8898_BIT_GENCTRL_BST_TDEG2_21MS           ( 0<< 9)
+#define AW8898_BIT_GENCTRL_BST_OCAP_MASK            (~( 1<< 8))
+#define AW8898_BIT_GENCTRL_BST_OCAP_SLOW            ( 1<< 8)
+#define AW8898_BIT_GENCTRL_BST_OCAP_FAST            ( 0<< 8)
+#define AW8898_BIT_GENCTRL_BST_EN_MASK              (~( 1<< 7))
+#define AW8898_BIT_GENCTRL_BST_ENABLE               ( 1<< 7)
+#define AW8898_BIT_GENCTRL_BST_DISABLE              ( 0<< 7)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_MASK          (~( 7<< 4))
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_4P5A          ( 7<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_4P25A         ( 6<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_4A            ( 5<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_3P75A         ( 4<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_3P5A          ( 3<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_3P25A         ( 2<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_3A            ( 1<< 4)
+#define AW8898_BIT_GENCTRL_BST_ILIMIT_2P75A         ( 0<< 4)
+#define AW8898_BIT_GENCTRL_BST_VOUT_MASK            (~(15<< 0))
+#define AW8898_BIT_GENCTRL_BST_VOUT_10P25V          (15<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_10V             (14<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_9P75V           (13<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_9P5V            (12<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_9P25V           (11<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_9V              (10<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_8P75V           ( 9<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_8P5V            ( 8<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_8P25V           ( 7<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_8V              ( 6<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_7P75V           ( 5<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_7P5V            ( 4<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_7P25V           ( 3<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_7V              ( 2<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_6P75V           ( 1<< 0)
+#define AW8898_BIT_GENCTRL_BST_VOUT_6P5V            ( 0<< 0)
+
+// BSTCTRL1
+#define AW8898_BIT_BSTCTRL1_RTH_MASK                (~(64<< 8))
+#define AW8898_BIT_BSTCTRL1_ATH_MASK                (~(64<< 0))
+
+// BSTCTRL2
+#define AW8898_BIT_BST_MODE_MASK                    (~( 7<< 3))
+#define AW8898_BIT_BST_MODE_SMART_BOOST             ( 6<< 3)
+#define AW8898_BIT_BST_MODE_ADAPT_BOOST             ( 5<< 3)
+#define AW8898_BIT_BST_MODE_FORCE_BOOST             ( 1<< 3)
+#define AW8898_BIT_BST_MODE_TRANSP_BOOST            ( 0<< 3)
+#define AW8898_BIT_BST_TDEG_MASK                    (~( 7<< 0))
+#define AW8898_BIT_BST_TDEG_2P7S                    ( 7<< 0)
+#define AW8898_BIT_BST_TDEG_1P3S                    ( 6<< 0)
+#define AW8898_BIT_BST_TDEG_672MS                   ( 5<< 0)
+#define AW8898_BIT_BST_TDEG_336MS                   ( 4<< 0)
+#define AW8898_BIT_BST_TDEG_168MS                   ( 3<< 0)
+#define AW8898_BIT_BST_TDEG_84MS                    ( 2<< 0)
+#define AW8898_BIT_BST_TDEG_42MS                    ( 1<< 0)
+#define AW8898_BIT_BST_TDEG_21MS                    ( 0<< 0)
+
+#endif