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, ®_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, ®_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, ®_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, ®_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, ®_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]®_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]®_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]®_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, ®_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, ®_val);
+ pr_info("%s: reg SYSST=0x%x\n", __func__, reg_val);
+
+ aw8898_i2c_read(aw8898, AW8898_REG_SYSINT, ®_val);
+ pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val);
+
+ aw8898_i2c_read(aw8898, AW8898_REG_SYSINTM, ®_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, ®);
+ 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, ®_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]®_RD_ACCESS))
+ continue;
+ aw8898_i2c_read(aw8898, i, ®_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