dotfiles/system/hardware/oneplus-enchilada/linux_6_8.patch
2024-05-03 16:56:29 +07:00

50590 lines
2.4 MiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
index fa745a6f445..9d90cf72578 100644
--- a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
+++ b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
@@ -17,7 +17,9 @@ allOf:
properties:
compatible:
- const: visionox,rm69299-1080p-display
+ enum:
+ - visionox,rm69299-1080p-display
+ - visionox,rm69299-shift
reg: true
diff --git a/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml b/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
new file mode 100644
index 00000000000..8ef9b4ec3a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2020 Unisoc Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/qcom,spmi-haptics.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies Inc PMI8998 spmi haptics
+
+maintainers:
+ - Caleb Connolly <caleb@connolly.tech>
+
+description: |
+ Qualcomm SPMI haptics is a peripheral on some QTI PMICs. It supports linear resonant
+ actuators and eccentric rotating mass type haptics commonly found in mobile devices.
+ It supports multiple sources of wave data such as an internal buffer, direct play
+ (from kernel or userspace) as well as an audio output mode.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - qcom,pmi8998-haptics
+ - qcom,pmi8996-haptics
+ - qcom,pmi8941-haptics
+ - const: qcom,spmi-haptics
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: short circuit interrupt
+ - description: play interrupt
+
+ interrupt-names:
+ items:
+ - const: short
+ - const: play
+
+ qcom,actuator-type:
+ description: |
+ The type of actuator attached to the hardware.
+ Allowed values are,
+ 0 - HAP_TYPE_LRA
+ 1 - HAP_TYPE_ERM
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1 ]
+ default: 0
+
+ qcom,wave-shape:
+ description: |
+ Selects the wave shape to use.
+ Allowed values are,
+ 0 - HAP_WAVE_SINE
+ 1 - HAP_WAVE_SQUARE
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1 ]
+ default: 0
+
+ qcom,play-mode:
+ description: |
+ Selects the play mode to use.
+ Allowed values are,
+ 0 - HAP_PLAY_DIRECT
+ 1 - HAP_PLAY_BUFFER
+ 2 - HAP_PLAY_AUDIO
+ 3 - HAP_PLAY_PWM
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2, 3 ]
+ default: 2
+
+ qcom,wave-play-rate-us:
+ description: |
+ Wave sample durection in microseconds, 1/f where f
+ is the resonant frequency of the actuator.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 20475
+
+ qcom,brake-pattern:
+ minItems: 4
+ maxItems: 4
+ description: |
+ The brake pattern are the strengths of the pattern
+ used to brake the haptics. Allowed values are,
+ 0 - 0V
+ 1 - Vmax/4
+ 2 - Vmax/2
+ 3 - Vmax
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ default: [0x3, 0x3, 0x2, 0x1]
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - qcom,wave-play-rate-us
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/spmi/spmi.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/input/qcom,spmi-haptics.h>
+
+ pmi8998_lsid1: pmic@3 {
+ compatible = "qcom,pmi8998", "qcom,spmi-pmic";
+ reg = <0x3 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmi8998_haptics: haptics@c000 {
+ compatible = "qcom,pmi8998-haptics", "qcom,spmi-haptics";
+ reg = <0xc000>;
+
+ interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "short", "play";
+
+ qcom,wave-shape = <HAP_WAVE_SINE>;
+ qcom,play-mode = <HAP_PLAY_BUFFER>;
+ qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
+
+ status = "disabled";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
index b522c8d3ce0..04ce256300c 100644
--- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
+++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
@@ -49,6 +49,16 @@ properties:
description:
Delay to wait after powering on the device.
+ syna,pdt-fallback-desc:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description:
+ An array of pairs of function number and version. These are used
+ on some devices with replacement displays that use unofficial touch
+ controllers. These controllers do report the properties of their PDT
+ entries, but leave the function_number and function_version registers
+ blank. These values should match exactly the 5th and 4th bytes of each
+ PDT entry from the original display's touch controller.
+
vdd-supply: true
vio-supply: true
diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
index f2808cb4d99..745e57c0517 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
@@ -39,7 +39,9 @@ properties:
- edt,edt-ft5406
- edt,edt-ft5506
- evervision,ev-ft5726
+ - focaltech,ft5452
- focaltech,ft6236
+ - focaltech,ft8719
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml b/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml
index 1ba607685f5..7868569ab6d 100644
--- a/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml
+++ b/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml
@@ -23,11 +23,11 @@ properties:
items:
- enum:
- qcom,pm6150l-flash-led
+ - qcom,pmi8998-flash-led
- qcom,pm8150c-flash-led
- qcom,pm8150l-flash-led
- qcom,pm8350c-flash-led
- qcom,pm8550-flash-led
- - qcom,pmi8998-flash-led
- const: qcom,spmi-flash-led
reg:
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
index 7758a55dd32..874ca4157fb 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
@@ -138,6 +138,12 @@ properties:
description:
Quirk specifying that the firmware expects the 8bit version
of the host capability QMI request
+
+ qcom,snoc-host-cap-skip-quirk:
+ type: boolean
+ description:
+ Quirk specifying that the firmware wants to skip the host
+ capability QMI request
qcom,xo-cal-data:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/power/supply/lenovo,yoga-c630-ec.yaml b/Documentation/devicetree/bindings/power/supply/lenovo,yoga-c630-ec.yaml
new file mode 100644
index 00000000000..37977344f15
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/lenovo,yoga-c630-ec.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/lenovo,yoga-c630-ec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lenovo Yoga C630 Embedded Controller.
+
+maintainers:
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description:
+ The Qualcomm Snapdragon-based Lenovo Yoga C630 has an Embedded Controller
+ (EC) which handles things such as battery and USB Type-C. This binding
+ describes the interface, on an I2C bus, to this EC.
+
+properties:
+ compatible:
+ const: lenovo,yoga-c630-ec
+
+ reg:
+ const: 0x70
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ interrupts:
+ maxItems: 1
+
+patternProperties:
+ '^connector@[01]$':
+ $ref: /schemas/connector/usb-connector.yaml#
+
+ properties:
+ reg:
+ maxItems: 1
+
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |+
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c1 {
+ clock-frequency = <400000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ embedded-controller@70 {
+ compatible = "lenovo,yoga-c630-ec";
+ reg = <0x70>;
+
+ interrupts-extended = <&tlmm 20 IRQ_TYPE_LEVEL_HIGH>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "source";
+ data-role = "host";
+ };
+
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "source";
+ data-role = "host";
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/power/supply/qcom,fg.yaml b/Documentation/devicetree/bindings/power/supply/qcom,fg.yaml
new file mode 100644
index 00000000000..29af7aa8379
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom,fg.yaml
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: (GPL-2.0-only or BSD-3-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/qcom,fg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm PMIC Fuel Gauge
+
+maintainers:
+ - Caleb Connolly <caleb@connolly.tech>
+ - Joel Selvaraj <jo@jsfamily.in>
+ - Yassine Oudjana <y.oudjana@protonmail.com>
+
+properties:
+ compatible:
+ enum:
+ - qcom,pm8994-fg
+ - qcom,pm8998-fg
+
+ reg:
+ maxItems: 1
+
+ monitored-battery:
+ description: |
+ phandle of battery characteristics node.
+ The fuel gauge uses the following battery properties:
+ - charge-full-design-microamp-hours
+ - voltage-min-design-microvolt
+ - voltage-max-design-microvolt
+ See Documentation/devicetree/bindings/power/supply/battery.yaml
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,pm8994-fg
+
+ then:
+ properties:
+ interrupts:
+ items:
+ - description: State of charge change interrupt
+ - description: SRAM availability change interrupt
+
+ interrupt-names:
+ items:
+ - const: soc-delta
+ - const: mem-avail
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - qcom,pm8998-fg
+
+ then:
+ properties:
+ interrupts:
+ items:
+ - description: State of charge change interrupt
+
+ interrupt-names:
+ items:
+ - const: soc-delta
+
+required:
+ - compatible
+ - reg
+ - monitored-battery
+ - interrupts
+ - interrupt-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ battery: battery {
+ compatible = "simple-battery";
+
+ charge-full-design-microamp-hours = <4070000>;
+ voltage-min-design-microvolt = <3400000>;
+ voltage-max-design-microvolt = <4400000>;
+ };
+
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fuel-gauge@4000 {
+ compatible = "qcom,pmi8994-fg";
+ reg = <0x4000>;
+
+ interrupts = <0x2 0x40 0x4 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x44 0x0 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "soc-delta", "mem-avail";
+
+ monitored-battery = <&battery>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/samsung,s2dos05.yaml b/Documentation/devicetree/bindings/regulator/samsung,s2dos05.yaml
new file mode 100644
index 00000000000..690537738e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/samsung,s2dos05.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/samsung,s2dos05.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung s2dos05 regulator
+
+maintainers:
+ - Dzmitry Sankouski <dsankouski@gmail.com>
+
+description: |
+ The S2DOS05 is a companion power management IC for the smart phones.
+ Has 4 LDO and 1 BUCK regulators, and has capability to measure
+ current and power. Can detect short circuit on outputs.
+
+properties:
+ compatible:
+ const: samsung,s2dos05
+ reg:
+ maxItems: 1
+
+ regulators:
+ type: object
+ description: List of regulators and its properties
+
+ patternProperties:
+ "^s2dos05-buck1|s2dos05-ldo[1-4]$":
+ type: object
+ $ref: "regulator.yaml#"
+ unevaluatedProperties: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - regulators
+
+additionalProperties: false
+
+examples:
+ - |
+ regulator@60 {
+ compatible = "samsung,s2dos05";
+ reg = <0x60>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&s2dos05_irq>;
+ s2dos05,s2dos05_int = <&tlmm 0x31 0x0>;
+
+ regulators {
+ s2dos05_ldo1: s2dos05-ldo1 {
+ regulator-name = "s2dos05-ldo1";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ s2dos05_ldo2: s2dos05-ldo2 {
+ regulator-name = "s2dos05-ldo2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ s2dos05_ldo3: s2dos05-ldo3 {
+ regulator-name = "s2dos05-ldo3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ s2dos05_ldo4: s2dos05-ldo4 {
+ regulator-name = "s2dos05-ldo4";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3775000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ s2dos05_buck1: s2dos05-buck1 {
+ regulator-name = "s2dos05-buck1";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-active-discharge = <0x1>;
+ };
+ };
+ };
diff --git a/Documentation/input/event-codes.rst b/Documentation/input/event-codes.rst
index b4557462edd..d43336e64d6 100644
--- a/Documentation/input/event-codes.rst
+++ b/Documentation/input/event-codes.rst
@@ -241,6 +241,12 @@ A few EV_ABS codes have special meanings:
emitted only when the selected profile changes, indicating the newly
selected profile value.
+* ABS_SND_PROFILE:
+
+ - Used to describe the state of a multi-value sound profile switch.
+ An event is emitted only when the selected profile changes,
+ indicating the newly selected profile value.
+
* ABS_MT_<name>:
- Used to describe multitouch input events. Please see
diff --git a/MAINTAINERS b/MAINTAINERS
index 1aabf1c15bb..b8b4d2e0a2c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6879,6 +6879,11 @@ S: Maintained
F: Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
F: drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
+DRM DRIVER FOR SAMSUNG S6E3FC2X01 PANELS
+M: Nia Espera <a5b6@riseup.net>
+S: Maintained
+F: drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c
+
DRM DRIVER FOR SITRONIX ST7586 PANELS
M: David Lechner <david@lechnology.com>
S: Maintained
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index cd3f0790fd4..2ceee5ff81b 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/input/qcom,spmi-haptics.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
@@ -44,6 +45,17 @@ pmi8998_rradc: adc@4500 {
reg = <0x4500>;
#io-channel-cells = <1>;
};
+
+ pmi8998_fg: fuel-gauge@4000 {
+ compatible = "qcom,pmi8998-fg";
+ reg = <0x4000>;
+
+ interrupts = <0x2 0x40 0x3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "soc-delta";
+
+ status = "disabled";
+ };
+
};
pmi8998_lsid1: pmic@3 {
@@ -94,5 +106,20 @@ pmi8998_wled: leds@d800 {
status = "disabled";
};
+
+ pmi8998_haptics: haptics@c000 {
+ compatible = "qcom,pmi8998-haptics", "qcom,spmi-haptics";
+ reg = <0xc000>;
+
+ interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "short", "play";
+
+ qcom,wave-shape = <HAP_WAVE_SINE>;
+ qcom,play-mode = <HAP_PLAY_BUFFER>;
+ qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
index 89beac833d4..9ee1af73d74 100644
--- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
@@ -175,33 +175,35 @@ psci {
CPU_PD0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
CPU_PD1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
CPU_PD2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
CPU_PD3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
+#if 0
CLUSTER_PD: power-domain-cpu-cluster {
#power-domain-cells = <0>;
power-domains = <&mpm>;
domain-idle-states = <&CLUSTER_SLEEP>;
};
+#endif
};
rpm: remoteproc {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
index 1f517328199..49b1d93db1e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -194,6 +194,7 @@ pcie0_3p3v_dual: vldo-3v3-regulator {
regulator-max-microvolt = <3300000>;
gpio = <&tlmm 90 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
enable-active-high;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
index 99dafc6716e..57ed447409d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
@@ -93,12 +93,6 @@ spss_mem: memory@99000000 {
no-map;
};
- /* Framebuffer region */
- memory@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x2400000>;
- no-map;
- };
-
/* rmtfs lower guard */
memory@f0800000 {
reg = <0 0xf0800000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
index 46e25c53829..f4dd0712f6f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
@@ -12,6 +12,8 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
+#include <dt-bindings/leds/common.h>
#include "sdm845.dtsi"
#include "sdm845-wcd9340.dtsi"
@@ -21,6 +23,41 @@
/delete-node/ &rmtfs_mem;
/ {
+ alert-slider {
+ compatible = "gpio-keys";
+ label = "Alert slider";
+
+ pinctrl-0 = <&alert_slider_default>;
+ pinctrl-names = "default";
+
+ switch-top {
+ label = "Silent";
+ linux,input-type = <EV_ABS>;
+ linux,code = <ABS_SND_PROFILE>;
+ linux,input-value = <SND_PROFILE_SILENT>;
+ gpios = <&tlmm 126 GPIO_ACTIVE_LOW>;
+ linux,can-disable;
+ };
+
+ switch-middle {
+ label = "Vibrate";
+ linux,input-type = <EV_ABS>;
+ linux,code = <ABS_SND_PROFILE>;
+ linux,input-value = <SND_PROFILE_VIBRATE>;
+ gpios = <&tlmm 52 GPIO_ACTIVE_LOW>;
+ linux,can-disable;
+ };
+
+ switch-bottom {
+ label = "Ring";
+ linux,input-type = <EV_ABS>;
+ linux,code = <ABS_SND_PROFILE>;
+ linux,input-value = <SND_PROFILE_RING>;
+ gpios = <&tlmm 24 GPIO_ACTIVE_LOW>;
+ linux,can-disable;
+ };
+ };
+
aliases {
serial0 = &uart9;
serial1 = &uart6;
@@ -253,7 +290,6 @@ vreg_l14a_1p88: ldo14 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-always-on;
};
vreg_l17a_1p3: ldo17 {
@@ -389,6 +425,8 @@ synaptics-rmi4-i2c@20 {
syna,reset-delay-ms = <200>;
syna,startup-delay-ms = <200>;
+ syna,pdt-fallback-desc = [34 41 01 01 12 01];
+
rmi4-f01@1 {
reg = <0x01>;
syna,nosleep-mode = <1>;
@@ -397,7 +435,7 @@ rmi4-f01@1 {
rmi4_f12: rmi4-f12@12 {
reg = <0x12>;
touchscreen-x-mm = <68>;
- touchscreen-y-mm = <144>;
+ syna,clip-x-high = <1079>;
syna,sensor-type = <1>;
syna,rezero-wait-ms = <200>;
};
@@ -507,6 +545,24 @@ led-1 {
};
};
+&pmi8998_haptics {
+ status = "okay";
+
+ qcom,wave-play-rate-us = <4255>;
+};
+
+&q6cvp {
+ status = "okay";
+};
+
+&q6cvs {
+ status = "okay";
+};
+
+&q6mvm {
+ status = "okay";
+};
+
&q6afedai {
dai@22 {
reg = <QUATERNARY_MI2S_RX>;
@@ -626,6 +682,13 @@ cpu {
};
};
+ voicemmode1-dai-link {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+
speaker_playback_dai: speaker-dai-link {
link-name = "Speaker Playback";
cpu {
@@ -803,8 +866,9 @@ hall_sensor_default: hall-sensor-default-state {
bias-disable;
};
- tri_state_key_default: tri-state-key-default-state {
- pins = "gpio40", "gpio42", "gpio26";
+
+ alert_slider_default: alert-slider-default-state {
+ pins = "gpio126", "gpio52", "gpio24";
function = "gpio";
drive-strength = <2>;
bias-disable;
@@ -872,4 +936,5 @@ &wifi {
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "oneplus_sdm845";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts b/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts
index 4005e04d998..476f0810fbc 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts
@@ -6,6 +6,7 @@
*/
#include "sdm845-oneplus-common.dtsi"
+#include <dt-bindings/leds/common.h>
/ {
model = "OnePlus 6";
@@ -55,6 +56,33 @@ &pmi8998_charger {
monitored-battery = <&battery>;
};
+&pmi8998_lpg {
+ status = "okay";
+
+ multi-led {
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@3 {
+ reg = <3>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@4 {
+ reg = <4>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@5 {
+ reg = <5>;
+ color = <LED_COLOR_ID_RED>;
+ };
+ };
+};
+
&sound {
model = "OnePlus 6";
audio-routing = "RX_BIAS", "MCLK",
@@ -70,6 +98,11 @@ codec {
};
};
+&rmi4_f12 {
+ touchscreen-y-mm = <144>;
+ syna,clip-y-high = <2279>;
+};
+
&wcd9340 {
qcom,micbias1-microvolt = <1800000>;
qcom,micbias2-microvolt = <2700000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts b/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts
index 9471ada0d6a..5a81287fa6d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts
@@ -30,7 +30,16 @@ &display_panel {
};
&i2c4 {
- /* nxp,tfa9894 @ 0x34 */
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tfa9894_codec: tfa9894@34 {
+ #sound-dai-cells = <1>;
+ compatible = "nxp,tfa9894";
+ reg = <0x34>;
+ reset-gpio = <&tlmm 69 0>;
+ };
+
};
&bq27441_fg {
@@ -51,15 +60,15 @@ &pmi8998_charger {
monitored-battery = <&battery>;
};
-/*
- * The TFA9894 codec is currently unsupported.
- * We need to delete the node to allow the soundcard
- * to probe for headphones/earpiece.
- */
-/delete-node/ &speaker_playback_dai;
+&speaker_playback_dai {
+ codec {
+ sound-dai = <&tfa9894_codec 0>;
+ };
+};
&rmi4_f12 {
touchscreen-y-mm = <148>;
+ syna,clip-y-high = <2339>;
};
&wcd9340 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index d37a433130b..a3b0aff86c8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -11,11 +11,17 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sdm845.dtsi"
+/delete-node/ &rmtfs_mem;
+
/ {
chassis-type = "handset";
model = "Samsung Galaxy S9 SM-G9600";
compatible = "samsung,starqltechn", "qcom,sdm845";
+ aliases {
+ serial0 = &uart9;
+ };
+
chosen {
#address-cells = <2>;
#size-cells = <2>;
@@ -27,6 +33,9 @@ framebuffer: framebuffer@9d400000 {
height = <2960>;
stride = <(1440 * 4)>;
format = "a8r8g8b8";
+ vci-supply = <&s2dos05_ldo4>;
+ vddr-supply = <&s2dos05_buck1>;
+ vdd3-supply = <&s2dos05_ldo1>;
};
};
@@ -55,11 +64,6 @@ vreg_s4a_1p8: pm8998-smps4 {
};
reserved-memory {
- memory@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x02400000>;
- no-map;
- };
-
memory@a1300000 {
compatible = "ramoops";
reg = <0x0 0xa1300000 0x0 0x100000>;
@@ -68,6 +72,93 @@ memory@a1300000 {
ftrace-size = <0x40000>;
pmsg-size = <0x40000>;
};
+
+ /* The rmtfs_mem needs to be guarded due to "XPU limitations"
+ * it is otherwise possible for an allocation adjacent to the
+ * rmtfs_mem region to trigger an XPU violation, causing a crash.
+ */
+ rmtfs_lower_guard: memory@fde00000 {
+ no-map;
+ reg = <0 0xfde00000 0 0x1000>;
+ };
+
+ rmtfs_mem: rmtfs-mem@fde01000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0 0xfde01000 0 0x200000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
+ rmtfs_upper_guard: rmtfs-upper-guard@fe001000 {
+ no-map;
+ reg = <0 0xfe001000 0 0x1000>;
+ };
+
+ /*
+ * It seems like reserving the old rmtfs_mem region is also needed to prevent
+ * random crashes which are most likely modem related, more testing needed.
+ */
+ removed_region: removed-region@88f00000 {
+ no-map;
+ reg = <0 0x88f00000 0 0x1c00000>;
+ };
+ };
+
+ i2c@21 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&tlmm 127 0x0>;
+ scl-gpios = <&tlmm 128 0x0>;
+ i2c-gpio,delay-us = <0x2>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c21_sda_state &i2c21_scl_state>;
+
+ regulator@60 {
+ compatible = "samsung,s2dos05";
+ reg = <0x60>;
+
+ regulators {
+ s2dos05_ldo1: s2dos05-ldo1 {
+ regulator-name = "s2dos05-ldo1";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ s2dos05_ldo2: s2dos05-ldo2 {
+ regulator-name = "s2dos05-ldo2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ s2dos05_ldo3: s2dos05-ldo3 {
+ regulator-name = "s2dos05-ldo3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ s2dos05_ldo4: s2dos05-ldo4 {
+ regulator-name = "s2dos05-ldo4";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3775000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ s2dos05_buck1: s2dos05-buck1 {
+ regulator-name = "s2dos05-buck1";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-active-discharge = <0x1>;
+ };
+ };
+ };
};
};
@@ -135,8 +226,6 @@ vdda_pll_cc_ebi23:
vdda_sp_sensor:
vdda_ufs1_core:
vdda_ufs2_core:
- vdda_usb1_ss_core:
- vdda_usb2_ss_core:
vreg_l1a_0p875: ldo1 {
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
@@ -157,6 +246,7 @@ vreg_l3a_1p0: ldo3 {
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vdda_usb1_ss_core:
vdd_wcss_cx:
vdd_wcss_mx:
vdda_wcss_pll:
@@ -365,6 +455,10 @@ &qupv3_id_1 {
status = "okay";
};
+&gpi_dma1 {
+ status = "okay";
+};
+
&uart9 {
status = "okay";
};
@@ -391,13 +485,55 @@ &sdhc_2 {
status = "okay";
};
+&i2c11 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ touchscreen@48 {
+ compatible = "samsung,s6sy761";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <120 0x0>;
+ vdd-supply = <&s2dos05_ldo2>;
+ avdd-supply = <&s2dos05_ldo3>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_irq_state>;
+ };
+};
+
+&crypto {
+ /* FIXME: qce_start triggers an SError */
+ status = "disable";
+};
+
+/* Modem/wifi*/
+&mss_pil {
+ status = "okay";
+ firmware-name = "qcom/sdm845/starqltechn/mba.mbn", "qcom/sdm845/starqltechn/modem.mbn";
+};
+
+&ipa {
+ qcom,gsi-loader = "self";
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sdm845/starqltechn/ipa_fws.mbn";
+ status = "okay";
+};
+
&usb_1 {
status = "okay";
+ /*
+ * disable USB3 clock requirement as the device only supports
+ * USB2.
+ */
+ qcom,select-utmi-as-pipe-clk;
};
&usb_1_dwc3 {
/* Until we have Type C hooked up we'll force this as peripheral. */
dr_mode = "peripheral";
+
+ maximum-speed = "high-speed";
};
&usb_1_hsphy {
@@ -418,14 +554,6 @@ &usb_1_qmpphy {
status = "okay";
};
-&wifi {
- vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
- vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
- vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
- vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
- status = "okay";
-};
-
&tlmm {
gpio-reserved-ranges = <0 4>, <27 4>, <81 4>, <85 4>;
@@ -457,4 +585,40 @@ sd_card_det_n_state: sd-card-det-n-state {
function = "gpio";
bias-pull-up;
};
+
+ i2c21_sda_state: i2c-sda-state {
+ pins = "gpio127";
+ function = "gpio";
+ drive-strength = <0x2>;
+ bias-disable;
+ };
+
+ i2c21_scl_state: i2c-scl-state {
+ pins = "gpio128";
+ function = "gpio";
+ drive-strength = <0x2>;
+ bias-disable;
+ };
+
+ touch_irq_state: touch-irq-state {
+ pins = "gpio120";
+ function = "gpio";
+ bias-disable;
+ output-disable;
+ };
+};
+
+&qup_uart9_tx {
+ drive-strength = <0x2>;
+ bias-pull-up;
+};
+
+&qup_uart9_rx {
+ drive-strength = <0x2>;
+ bias-pull-up;
+};
+
+&qup_i2c11_default {
+ drive-strength = <2>;
+ bias-disable;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
index fbb8655653f..3fd0d3fd669 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
@@ -10,7 +10,11 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
#include "sdm845.dtsi"
+#include "sdm845-wcd9340.dtsi"
#include "pm8998.dtsi"
#include "pmi8998.dtsi"
@@ -22,6 +26,7 @@ / {
aliases {
display0 = &framebuffer0;
+ hsuart0 = &uart6;
serial0 = &uart9;
serial1 = &uart6;
};
@@ -60,11 +65,6 @@ key-vol-up {
};
reserved-memory {
- framebuffer_region@9d400000 {
- reg = <0x0 0x9d400000 0x0 (1080 * 2160 * 4)>;
- no-map;
- };
-
ramoops: ramoops@b0000000 {
compatible = "ramoops";
reg = <0 0xb0000000 0 0x00400000>;
@@ -434,25 +434,24 @@ zap-shader {
&i2c5 {
status = "okay";
+ clock-frequency = <400000>;
touchscreen@38 {
- compatible = "focaltech,fts8719";
+ compatible = "focaltech,ft5452";
reg = <0x38>;
- wakeup-source;
- interrupt-parent = <&tlmm>;
- interrupts = <125 IRQ_TYPE_EDGE_FALLING>;
- vdd-supply = <&vreg_l28a_3p0>;
- vcc-i2c-supply = <&vreg_l14a_1p88>;
- pinctrl-names = "default", "suspend";
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l28a_3p0>;
+ iovcc-supply = <&vreg_l14a_1p88>;
+
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ pinctrl-names = "default", "suspend";
- reset-gpio = <&tlmm 99 GPIO_ACTIVE_HIGH>;
- irq-gpio = <&tlmm 125 GPIO_TRANSITORY>;
touchscreen-size-x = <1080>;
touchscreen-size-y = <2160>;
- focaltech,max-touch-number = <5>;
};
};
@@ -460,6 +459,19 @@ &i2c10 {
/* SMB1355@0x0C */
};
+&i2c11 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tfa9890_codec: audio-codec@34 {
+ compatible = "nxp,tfa9890";
+ reg = <0x34>;
+ vddd-supply = <&vreg_s4a_1p8>;
+ sound-name-prefix = "Speaker";
+ #sound-dai-cells = <0>;
+ };
+};
+
&ipa {
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
@@ -485,7 +497,7 @@ panel@0 {
#address-cells = <1>;
#size-cells = <0>;
- reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sde_dsi_active &sde_te_active>;
@@ -532,6 +544,18 @@ &pmi8998_charger {
status = "okay";
};
+&pmi8998_fg {
+ status = "okay";
+ monitored-battery = <&battery>;
+ power-supplies = <&pmi8998_charger>;
+};
+
+&pmi8998_haptics {
+ status = "okay";
+
+ qcom,wave-play-rate-us = <4255>;
+};
+
&pm8998_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -586,6 +610,103 @@ led-1 {
};
};
+&q6cvp {
+ status = "okay";
+};
+
+&q6cvs {
+ status = "okay";
+};
+
+&q6mvm {
+ status = "okay";
+};
+
+&q6afedai {
+ qi2s@22 {
+ reg = <22>;
+ qcom,sd-lines = <0>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
+
+ dai@2 {
+ reg = <2>;
+ };
+
+ dai@3 {
+ reg = <3>;
+ };
+
+ dai@4 {
+ reg = <4>;
+ };
+
+ dai@5 {
+ reg = <5>;
+ };
+};
+
+/*
+ * Prevent garbage data on bluetooth UART lines
+ */
+&qup_uart6_default {
+ pinmux {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
+ function = "qup6";
+ };
+
+ cts {
+ pins = "gpio45";
+ bias-pull-down;
+ };
+
+ rts-tx {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio48";
+ bias-pull-up;
+ };
+};
+
+/*
+ * Prevent garbage data on bluetooth UART lines
+ */
+&qup_uart6_default {
+ pinmux {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
+ function = "qup6";
+ };
+
+ cts {
+ pins = "gpio45";
+ bias-pull-down;
+ };
+
+ rts-tx {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio48";
+ bias-pull-up;
+ };
+};
+
&qup_uart9_rx {
drive-strength = <2>;
bias-pull-up;
@@ -604,14 +725,219 @@ &qupv3_id_1 {
status = "okay";
};
+&sdhc_2 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdc2_default_state &sdc2_card_det_n>;
+
+ vmmc-supply = <&vreg_l21a_2p95>;
+ vqmmc-supply = <&vreg_l13a_2p95>;
+
+ bus-width = <4>;
+ /* card detection is broken, but because the battery must be removed
+ * to insert the card, we use this rather than the broken-cd property
+ * which would just waste CPU cycles polling.
+ */
+ non-removable;
+};
+
&slpi_pas {
firmware-name = "qcom/sdm845/axolotl/slpi.mbn";
status = "okay";
};
+&sound {
+ model = "SHIFT6mq";
+ compatible = "qcom,sdm845-sndcard";
+ pinctrl-0 = <&quat_mi2s_active &quat_mi2s_sd0_active>;
+ pinctrl-names = "default";
+
+ audio-routing = "RX_BIAS", "MCLK",
+ "AMIC1", "MIC BIAS1",
+ "AMIC2", "MIC BIAS2",
+ "AMIC3", "MIC BIAS3",
+ "MM_DL1", "MultiMedia1 Playback",
+ "MM_DL3", "MultiMedia3 Playback",
+ "MM_DL5", "MultiMedia5 Playback",
+ "MultiMedia2 Capture", "MM_UL2",
+ "MultiMedia4 Capture", "MM_UL4",
+ "MultiMedia6 Capture", "MM_UL6";
+
+ mm1-dai-link {
+ link-name = "MultiMedia1";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ mm2-dai-link {
+ link-name = "MultiMedia2";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ };
+ };
+
+ mm3-dai-link {
+ link-name = "MultiMedia3";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ mm4-dai-link {
+ link-name = "MultiMedia4";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ mm5-dai-link {
+ link-name = "MultiMedia5";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA5>;
+ };
+ };
+
+ mm6-dai-link {
+ link-name = "MultiMedia6";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA6>;
+ };
+ };
+
+ speaker-dai-link {
+ link-name = "Speaker Playback";
+ codec {
+ sound-dai = <&tfa9890_codec>;
+ };
+
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slimcap-wcd-dai-link {
+ link-name = "SLIM WCD Capture 1";
+ codec {
+ sound-dai = <&wcd9340 1>; /* AIF1_CAP */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_1_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slim-dai-link {
+ link-name = "SLIM WCD Playback 1";
+ codec {
+ sound-dai = <&wcd9340 0>; /* AIF1_PB */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_0_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slimcap-dai-link {
+ link-name = "SLIM WCD Capture 2";
+ codec {
+ sound-dai = <&wcd9340 3>; /* AIF2_CAP */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_0_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slim-wcd-dai-link {
+ link-name = "SLIM WCD Playback 2";
+ codec {
+ sound-dai = <&wcd9340 2>; /* AIF2_PB */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_1_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slimcap2-wcd-dai-link {
+ link-name = "SLIM WCD Capture 3";
+ codec {
+ sound-dai = <&wcd9340 5>; /* AIF3_CAP */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_2_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ voicemmode1-dai-link {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
+ sdc2_default_state: sdc2-default-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ bias-disable;
+
+ /*
+ * It seems that mmc_test reports errors if drive
+ * strength is not 16 on clk, cmd, and data pins.
+ */
+ drive-strength = <16>;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+ };
+
+ sdc2_card_det_n: sd-card-det-n-state {
+ pins = "gpio126";
+ function = "gpio";
+ bias-pull-up;
+ };
+
sde_dsi_active: sde-dsi-active-state {
pins = "gpio6", "gpio11";
function = "gpio";
@@ -739,6 +1065,22 @@ &venus {
firmware-name = "qcom/sdm845/axolotl/venus.mbn";
};
+&wcd9340 {
+ pinctrl-0 = <&wcd_intr_default>;
+ pinctrl-names = "default";
+ reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
+ vdd-buck-supply = <&vreg_s4a_1p8>;
+ vdd-buck-sido-supply = <&vreg_s4a_1p8>;
+ vdd-tx-supply = <&vreg_s4a_1p8>;
+ vdd-rx-supply = <&vreg_s4a_1p8>;
+ vdd-io-supply = <&vreg_s4a_1p8>;
+
+ qcom,micbias1-microvolt = <2700000>;
+ qcom,micbias2-microvolt = <2700000>;
+ qcom,micbias3-microvolt = <2700000>;
+ qcom,micbias4-microvolt = <2700000>;
+};
+
&wifi {
status = "okay";
@@ -749,4 +1091,5 @@ &wifi {
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "shift_axolotl";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
index b02a1dc5fec..c4845b0e3b1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
@@ -118,12 +118,6 @@ vreg_s4a_1p8: pm8998-smps4 {
};
reserved-memory {
- /* SONY was cool and didn't diverge from MTP this time, yay! */
- cont_splash_mem: memory@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x2400000>;
- no-map;
- };
-
ramoops@ffc00000 {
compatible = "ramoops";
reg = <0x0 0xffc00000 0x0 0x100000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index 617b17b2d7d..3b2177bb175 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -7,6 +7,9 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
#include "sdm845.dtsi"
#include "sdm845-wcd9340.dtsi"
#include "pm8998.dtsi"
@@ -99,12 +102,6 @@ spss_mem: memory@97f00000 {
no-map;
};
- /* Cont splash region set up by the bootloader */
- cont_splash_mem: framebuffer@9d400000 {
- reg = <0 0x9d400000 0 0x2400000>;
- no-map;
- };
-
rmtfs_mem: memory@f6301000 {
compatible = "qcom,rmtfs-mem";
reg = <0 0xf6301000 0 0x200000>;
@@ -243,6 +240,14 @@ &gmu {
status = "okay";
};
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
&gpu {
status = "okay";
@@ -264,7 +269,7 @@ &ibb {
&lab {
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <6000000>;
- regulator-over-current-protection;
+ // regulator-over-current-protection;
regulator-pull-down;
regulator-soft-start;
};
@@ -318,6 +323,26 @@ &ipa {
status = "okay";
};
+&i2c5 {
+ #dma-cells = <3>;
+ status="okay";
+
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+
+ /*smart PA*/
+ tas2559_codec: tas2559@4c{
+ #sound-dai-cells = <1>;
+ compatible = "ti,tas2559";
+ reg = <0x4c>;
+ ti,tas2559-reset-gpio = <&tlmm 12 0>;
+ ti,tas2560-reset-gpio = <&tlmm 76 0>;
+ ti,tas2559-addr = <0x4c>;
+ ti,tas2560-addr = <0x4d>;
+ };
+};
+
&pm8998_gpios {
vol_up_pin_a: vol-up-active-state {
pins = "gpio6";
@@ -377,6 +402,13 @@ led-1 {
};
};
+&pmi8998_fg {
+ status = "okay";
+
+ power-supplies = <&pmi8998_charger>;
+ monitored-battery = <&battery>;
+};
+
&pm8998_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -402,12 +434,37 @@ dai@1 {
dai@2 {
reg = <2>;
};
+
+ dai@3 {
+ reg = <3>;
+ };
+};
+
+&pmi8998_haptics {
+ status = "okay";
+ qcom,wave-play-rate-us = <4878>;
+};
+
+&q6cvp {
+ status = "okay";
+};
+
+&q6cvs {
+ status = "okay";
+};
+
+&q6mvm {
+ status = "okay";
};
&qupv3_id_0 {
status = "okay";
};
+&qupv3_id_1 {
+ status = "okay";
+};
+
&sdhc_2 {
status = "okay";
@@ -436,21 +493,50 @@ &sound {
mm1-dai-link {
link-name = "MultiMedia1";
cpu {
- sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
mm2-dai-link {
link-name = "MultiMedia2";
cpu {
- sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
};
};
mm3-dai-link {
link-name = "MultiMedia3";
cpu {
- sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ mm4-dai-link {
+ link-name = "MultiMedia4";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ dai-link-voicemmode1 {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+
+ tas2559-dai-link {
+ link-name = "Primary Spkr Playback";
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&tas2559_codec 0>;
};
};
@@ -470,7 +556,7 @@ codec {
};
slimcap-dai-link {
- link-name = "SLIM Capture";
+ link-name = "SLIM WCD Capture";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_TX>;
};
@@ -480,7 +566,22 @@ platform {
};
codec {
- sound-dai = <&wcd9340 1>;
+ sound-dai = <&wcd9340 1>; /* AIF1_CAP */
+ };
+ };
+
+ slimcap2-dai-link {
+ link-name = "SLIM WCD Capture 2";
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_1_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&wcd9340 3>; /* AIF2_CAP */
};
};
};
@@ -513,6 +614,37 @@ sdc2_card_det_n: sd-card-det-n-state {
function = "gpio";
bias-pull-up;
};
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-pull-down;
+ input-enable;
+ };
+
+ ts_reset_default: ts-reset-default-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <16>;
+ output-high;
+ };
+
+ ts_int_sleep: ts-int-sleep-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ input-enable;
+ };
+
+ ts_reset_sleep: ts-reset-sleep-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
};
&uart6 {
@@ -601,4 +733,7 @@ &wifi {
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
+
+ qcom,snoc-host-cap-skip-quirk;
+ qcom,ath10k-calibration-variant = "xiaomi_beryllium";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
index 76931ebad06..74b4284b5f5 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
@@ -13,3 +13,24 @@ &display_panel {
compatible = "ebbg,ft8719";
status = "okay";
};
+
+&i2c14 {
+ status = "okay";
+
+ touchscreen@38 {
+ compatible = "focaltech,ft8719";
+ reg = <0x38>;
+
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+
+ iovcc-supply = <&vreg_l14a_1p8>;
+
+ pinctrl-0 = <&ts_int_default &ts_reset_default>;
+ pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2246>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
index e9427851eba..0ca1997f934 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
@@ -13,3 +13,24 @@ &display_panel {
compatible = "tianma,fhd-video", "novatek,nt36672a";
status = "okay";
};
+
+&i2c14 {
+ status = "okay";
+
+ touchscreen@1 {
+ compatible = "novatek,nvt-ts";
+ reg = <0x01>;
+
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+
+ iovcc-supply = <&vreg_l14a_1p8>;
+
+ pinctrl-0 = <&ts_int_default &ts_reset_default>;
+ pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2246>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 237d4048614..bedf09590a1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -888,6 +888,11 @@ mdata_mem: mpss-metadata {
no-map;
};
+ cont_splash_mem: framebuffer@9d400000 {
+ reg = <0 0x9d400000 0 0x2400000>;
+ no-map;
+ };
+
fastrpc_mem: fastrpc {
compatible = "shared-dma-pool";
alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>;
@@ -974,6 +979,32 @@ q6routing: routing {
#sound-dai-cells = <0>;
};
};
+
+ q6mvm: apr-service@9 {
+ compatible = "qcom,q6mvm";
+ reg = <APR_SVC_ADSP_MVM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ status = "disabled";
+
+ q6voicedai: dais {
+ compatible = "qcom,q6voice-dais";
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ q6cvs: apr-service@a {
+ compatible = "qcom,q6cvs";
+ reg = <APR_SVC_ADSP_CVS>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ status = "disabled";
+ };
+
+ q6cvp: apr-service@b {
+ compatible = "qcom,q6cvp";
+ reg = <APR_SVC_ADSP_CVP>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ status = "disabled";
+ };
};
fastrpc {
@@ -4433,6 +4464,8 @@ mdss: display-subsystem@ae00000 {
power-domains = <&dispcc MDSS_GDSC>;
+ //resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
+
clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
clock-names = "iface", "core";
diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
index 47dc42f6e93..47a28baa0ec 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -37,6 +37,10 @@ aliases {
serial1 = &uart6;
};
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
gpio-keys {
compatible = "gpio-keys";
@@ -370,6 +374,33 @@ zap-shader {
&i2c1 {
status = "okay";
clock-frequency = <400000>;
+
+ embedded-controller@70 {
+ compatible = "lenovo,yoga-c630-ec";
+ reg = <0x70>;
+
+ interrupts-extended = <&tlmm 20 IRQ_TYPE_LEVEL_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&ec_int_state>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ connector@0 {
+ compatible = "usb-c-connector";
+ reg = <0>;
+ power-role = "source";
+ data-role = "host";
+ };
+
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "source";
+ data-role = "host";
+ };
+ };
};
&i2c3 {
@@ -567,6 +598,11 @@ dai@2 {
};
};
+&slpi_pas {
+ firmware-name = "qcom/sdm850/LENOVO/81JL/qcslpi850.mbn";
+ status = "okay";
+};
+
&sound {
compatible = "lenovo,yoga-c630-sndcard", "qcom,sdm845-sndcard";
model = "Lenovo-YOGA-C630-13Q50";
@@ -694,6 +730,14 @@ mode_pin_active: mode-pin-state {
bias-disable;
};
+
+ ec_int_state: ec-int-state {
+ pins = "gpio20";
+ function = "gpio";
+
+ input-enable;
+ bias-disable;
+ };
};
&uart6 {
diff --git a/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts b/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
index 26217836c27..bec0033aeca 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
@@ -61,12 +61,6 @@ aliases {
/* Reserved memory changes */
reserved-memory {
- /* Bootloader display framebuffer region */
- cont_splash_mem: memory@80400000 {
- reg = <0x0 0x80400000 0x0 0x960000>;
- no-map;
- };
-
qseecom_mem: memory@8b500000 {
reg = <0 0x8b500000 0 0xa00000>;
no-map;
diff --git a/arch/arm64/boot/dts/qcom/sdm850.dtsi b/arch/arm64/boot/dts/qcom/sdm850.dtsi
index da9f6fbe32f..89eda97daa5 100644
--- a/arch/arm64/boot/dts/qcom/sdm850.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm850.dtsi
@@ -7,6 +7,17 @@
#include "sdm845.dtsi"
+/delete-node/ &cont_splash_mem;
+
+/ {
+ reserved-memory {
+ cont_splash_mem: framebuffer@80400000 {
+ reg = <0x0 0x80400000 0x0 0x960000>;
+ no-map;
+ };
+ };
+};
+
&cpu4_opp_table {
cpu4_opp33: opp-2841600000 {
opp-hz = /bits/ 64 <2841600000>;
diff --git a/arch/arm64/configs/sdm845.config b/arch/arm64/configs/sdm845.config
new file mode 100644
index 00000000000..cab91545104
--- /dev/null
+++ b/arch/arm64/configs/sdm845.config
@@ -0,0 +1,1019 @@
+# Qualcomm Snapdragon 845 (SDM845) config fragment
+CONFIG_LOCALVERSION="-sdm845"
+
+# OnePlus 6
+CONFIG_DRM_PANEL_SAMSUNG_SOFEF00=y
+CONFIG_BATTERY_BQ27XXX=m
+CONFIG_HID_RMI=m
+CONFIG_RMI4_CORE=m
+CONFIG_RMI4_I2C=m
+CONFIG_RMI4_F55=y
+
+# OnePlus 6T
+CONFIG_DRM_PANEL_SAMSUNG_S6E3FC2X01=y
+CONFIG_SND_SOC_TFA98XX=m
+
+# Pocophone F1
+CONFIG_DRM_PANEL_NOVATEK_NT36672A=y
+CONFIG_DRM_PANEL_EBBG_FT8719=y
+CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS=m
+CONFIG_QCOM_GPI_DMA=m
+CONFIG_SND_SOC_TAS2559=m
+
+# Samsung S9 SM-G9600(starqltechn)
+CONFIG_TOUCHSCREEN_S6SY761=m
+CONFIG_REGULATOR_S2DOS05=m
+
+# SHIFT6mq
+CONFIG_DRM_PANEL_VISIONOX_RM69299_SHIFT=y
+CONFIG_SND_SOC_TFA989X=m
+
+# Odin
+# Driver has been dropped
+CONFIG_DRM_PANEL_INNOLUX_TD4328=y
+
+# Mi Mix 2S
+CONFIG_DRM_PANEL_NOVATEK_NT35596S=y
+
+# C630
+CONFIG_DRM_TI_SN65DSI86=y
+CONFIG_DRM_PANEL_EDP=y
+CONFIG_PHY_QCOM_EDP=y
+CONFIG_I2C_HID_OF_ELAN=m
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_LENOVO_YOGA_C630_EC=m
+
+# SOC
+CONFIG_FORCE_NR_CPUS=y
+CONFIG_NR_CPUS=8
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_QCOM_GSBI=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_OCMEM=y
+CONFIG_QCOM_RMTFS_MEM=y
+CONFIG_QCOM_SOCINFO=y
+CONFIG_QCOM_WCNSS_CTRL=y
+CONFIG_QCOM_APR=y
+CONFIG_POWER_RESET_QCOM_PON=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_QCOM_LMH=y
+CONFIG_SCHED_CLUSTER=y
+CONFIG_SND_SOC_QDSP6_Q6VOICE=m
+CONFIG_SCSI_UFS_BSG=y
+CONFIG_PHY_QCOM_QMP_PCIE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_INTERCONNECT_QCOM_OSM_L3=y
+# Notification LED
+# Must be builtin as it won't be automatically modprobed
+CONFIG_LEDS_TRIGGER_PATTERN=y
+CONFIG_LEDS_CLASS_MULTICOLOR=m
+CONFIG_LEDS_QCOM_LPG=m
+CONFIG_I2C_QCOM_GENI=y
+
+# Flash LED
+CONFIG_LEDS_QCOM_FLASH=m
+
+# Touchscreen - Pocophone F1 / SHIFT6mq
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+
+# Remoteproc
+CONFIG_SLIMBUS=y
+CONFIG_SLIM_QCOM_CTRL=y
+CONFIG_SLIM_QCOM_NGD_CTRL=y
+CONFIG_REMOTEPROC_CDEV=y
+
+# Battery
+CONFIG_BATTERY_QCOM_FG=m
+CONFIG_CHARGER_QCOM_SMB2=m
+CONFIG_QCOM_SPMI_RRADC=m
+
+# Graphics
+CONFIG_DRM=y
+CONFIG_FB_SIMPLE=y
+CONFIG_DRM_MSM=y
+# Virtual video test driver
+CONFIG_VIDEO_VIVID=m
+
+# Brightness Control
+CONFIG_REGULATOR_QCOM_LABIBB=y
+CONFIG_BACKLIGHT_QCOM_WLED=y
+
+# Haptics
+CONFIG_FF_MEMLESS=y
+CONFIG_INPUT_QCOM_SPMI_HAPTICS=m
+
+# Power management
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+
+# MGLRU
+CONFIG_LRU_GEN=y
+CONFIG_LRU_GEN_ENABLED=y
+
+# Misc useful things
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_UDMABUF=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
+CONFIG_HZ_1000=y
+CONFIG_MODULE_COMPRESS_ZSTD=y
+# Alpine can't seem to handle this
+CONFIG_MODULE_DECOMPRESS=y
+
+# Usage clamping (scale CPU for specific tasks)
+CONFIG_UCLAMP_TASK=y
+CONFIG_UCLAMP_TASK_GROUP=y
+
+# Needed for mounting userdata on android
+CONFIG_QFMT_V2=y
+
+# HID/Input
+CONFIG_I2C_HID=y
+CONFIG_HID_GENERIC=m
+CONFIG_UHID=m
+CONFIG_USB_HID=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_BT_HIDP=m
+CONFIG_INPUT_JOYDEV=m
+
+# Persistent store
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_PMSG=y
+CONFIG_PSTORE_RAM=y
+CONFIG_PSTORE_DEFLATE_COMPRESS=y
+
+# USB
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_HID=y
+
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_ACTIVITY=y
+
+# Platform
+CONFIG_EFI_GENERIC_STUB=y
+CONFIG_EFI_ZBOOT=y
+# Causes issues with u-boot
+CONFIG_FB_EFI=n
+
+# sm8250
+CONFIG_INTERCONNECT_QCOM_SM8250=y
+CONFIG_PHY_QCOM_QMP_USB=y
+
+# Qcom stuff
+CONFIG_RPMSG_CHAR=y
+CONFIG_QCOM_Q6V5_ADSP=m
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HS=y
+CONFIG_BT_LE=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_QCOM_COINCELL=m
+CONFIG_QCOM_FASTRPC=m
+CONFIG_QCOM_SPMI_VADC=y
+CONFIG_QCOM_SPMI_ADC5=y
+CONFIG_PHY_QCOM_QMP=y
+CONFIG_PHY_QCOM_QUSB2=y
+CONFIG_PHY_QCOM_QMP_UFS=y
+CONFIG_TYPEC=y
+CONFIG_PHY_QCOM_QMP_COMBO=y
+CONFIG_LEDS_CLASS_FLASH=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_DEFAULT_WESTWOOD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BTRFS_FS=y
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_F2FS_FS=y
+CONFIG_NLS_UTF8=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_EXFAT_FS=m
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_SYN_COOKIES=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+# Qcomlt
+CONFIG_BLK_INLINE_ENCRYPTION=y
+CONFIG_QCOM_QMI_COOLING=m
+CONFIG_PHY_QCOM_SNPS_EUSB2=m
+CONFIG_MFD_QCOM_QCA639X=y
+CONFIG_MFD_QCOM_RPM=y
+CONFIG_USB_DWC3_ULPI=y
+CONFIG_USB_REPEATER=y
+CONFIG_SCSI_UFS_CRYPTO=y
+CONFIG_PHY_QCOM_USB_HS=y
+CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=y
+CONFIG_INTERCONNECT_QCOM_SM6115=y
+CONFIG_SM_DISPCC_6115=y
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
+CONFIG_CRYPTO_USER_API_AEAD=y
+CONFIG_CRYPTO_DEV_QCE=y
+CONFIG_DMA_CMA=y
+CONFIG_SM_GPUCC_6115=y
+CONFIG_USB_ONBOARD_HUB=n # Breaks USB on rb2
+CONFIG_INTERCONNECT_QCOM_QCM2290=y
+
+# Anbox
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NETLINK_DIAG=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_ASHMEM=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+
+# Waydroid
+CONFIG_PSI=y
+
+# WLAN debugging
+CONFIG_ATH10K_DEBUG=y
+CONFIG_ATH10K_DEBUGFS=y
+CONFIG_ATH10K_SPECTRAL=y
+
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+
+# Debugging stuff
+CONFIG_STACKTRACE=y
+
+#pmOS Related
+CONFIG_VT=y
+CONFIG_CRYPTO_XTS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_USB_MASS_STORAGE is not set
+
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_CT=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_COMPAT=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_MASQ=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_REJECT=m
+CONFIG_NF_TABLES_IPV4=y
+CONFIG_NF_TABLES_IPV6=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_CIFS=y
+
+CONFIG_DRM_GUD=m
+CONFIG_UCLAMP_TASK=y
+CONFIG_UCLAMP_TASK_GROUP=y
+
+# pmos containers kconfig
+CONFIG_CGROUP_FREEZER=y
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_DUMMY=m
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_RR=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_DM_THIN_PROVISIONING=y
+CONFIG_VXLAN=m
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_IPVLAN=m
+
+# pmOS ZRAM kconfig
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_ZRAM=m
+CONFIG_ZRAM_DEF_COMP_ZSTD=y
+CONFIG_ZRAM_DEF_COMP="zstd"
+CONFIG_ZRAM_MEMORY_TRACKING=y
+CONFIG_ZRAM_MULTI_COMP=y
+CONFIG_CRYPTO_LZ4=m
+CONFIG_LZ4_COMPRESS=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_ZSTD=m
+
+# pmOS iwd kconfig
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_KEY_DH_OPERATIONS=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=y
+
+# pmOS wireguard kconfig
+CONFIG_WIREGUARD=m
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NFT_FIB=m
+CONFIG_NFT_FIB_IPV4=m
+CONFIG_NFT_FIB_IPV6=m
+CONFIG_FIB_RULES=y
+
+# pmOS community kconfig
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+# LEDs
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+# Game controllers, etc
+CONFIG_HID_SONY=m
+CONFIG_SONY_FF=y
+CONFIG_HID_NINTENDO=m
+
+# Disable all unrelated stuffs afaik
+CONFIG_HIBERNATION=n
+CONFIG_FW_LOADER_USER_HELPER=n
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n
+CONFIG_BLK_DEV_NVME=n
+CONFIG_ATA=n
+CONFIG_MTD=n
+CONFIG_SRAM=n
+CONFIG_MEGARAID_SAS=n
+CONFIG_EEPROM_AT25=n
+CONFIG_SCSI_MPT3SAS=n
+CONFIG_BLK_DEV_MD=n
+CONFIG_DM_MIRROR=n
+CONFIG_DM_ZERO=n
+CONFIG_EXT2_FS=n
+CONFIG_EXT3_FS=n
+CONFIG_USB_DWC2=n
+CONFIG_USB_CHIPIDEA=n
+CONFIG_USB_MUSB_HDRC=n
+CONFIG_USB_ISP1760=n
+CONFIG_USB_HSIC_USB3503=n
+CONFIG_USB_NET_PLUSB=n
+CONFIG_TYPEC_FUSB302=n
+CONFIG_EXTCON_PTN5150=n
+CONFIG_REALTEK_PHY=n
+CONFIG_NET_VENDOR_NI=n
+CONFIG_NET_9P=n
+CONFIG_CAN=n
+CONFIG_BNX2X=n
+CONFIG_MACB=n
+CONFIG_IGB=n
+CONFIG_IGBVF=n
+CONFIG_SMC91X=n
+CONFIG_MLX4_EN=n
+CONFIG_MLX5_CORE=n
+CONFIG_STMMAC_ETH=n
+CONFIG_ATL1C=n
+CONFIG_BRCMFMAC=n
+CONFIG_WL18XX=n
+CONFIG_WLCORE=n
+CONFIG_ATH10K_PCI=n
+CONFIG_NET_SCH_CBS=n
+CONFIG_NET_SCH_ETF=n
+CONFIG_NET_SCH_TAPRIO=n
+CONFIG_NET_SCH_MQPRIO=n
+CONFIG_NET_CLS_BASIC=n
+CONFIG_NET_CLS_FLOWER=n
+CONFIG_NET_CLS_ACT=n
+CONFIG_NET_ACT_GACT=n
+CONFIG_NET_ACT_MIRRED=n
+CONFIG_NET_ACT_GATE=n
+CONFIG_MDIO_BUS_MUX_MMIOREG=n
+CONFIG_MDIO_BUS_MUX_MULTIPLEXER=n
+CONFIG_SND_SOC_ES7134=n
+CONFIG_SND_SOC_ES7241=n
+CONFIG_SND_SOC_TAS571X=n
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER=n
+CONFIG_GPIO_DWAPB=n
+CONFIG_COMMON_CLK_XGENE=n
+CONFIG_SENSORS_ARM_SCPI=n
+CONFIG_TCG_TPM=n
+CONFIG_BATTERY_SBS=n
+CONFIG_REGULATOR_VCTRL=n
+CONFIG_SND_SOC_MAX98357A=n
+CONFIG_SND_SOC_RL6231=n
+CONFIG_THUNDER_NIC_BGX=n
+CONFIG_THUNDER_NIC_RGX=n
+CONFIG_MDIO_THUNDER=n
+CONFIG_CAVIUM_ERRATUM_22375=n
+CONFIG_CAVIUM_ERRATUM_23154=n
+CONFIG_CAVIUM_ERRATUM_27456=n
+CONFIG_CAVIUM_ERRATUM_30115=n
+CONFIG_CAVIUM_TX2_ERRATUM_219=n
+CONFIG_HW_RANDOM_CAVIUM=n
+CONFIG_EEPROM_AT24=n
+CONFIG_NET_DSA=n
+CONFIG_AQUANTIA_PHY=n
+CONFIG_MICROSEMI_PHY=n
+CONFIG_VITESSE_PHY=n
+CONFIG_I2C_MUX_PCA954x=n
+CONFIG_SND_SOC_PCM3168A_I2C=n
+CONFIG_SENSORS_LM90=n
+CONFIG_SENSORS_INA2XX=n
+CONFIG_RTC_DRV_DS3232=n
+CONFIG_SPI_NXP_FLEXSPI=n
+CONFIG_GPIO_MAX732X=n
+CONFIG_SENSORS_ISL29018=n
+CONFIG_MPL3115=n
+CONFIG_MFD_ROHM_BD718XX=n
+CONFIG_ARM_SBSA_WATCHDOG=n
+CONFIG_ARM_SMC_WATCHDOG=n
+CONFIG_REGULATOR_PCA9450=n
+CONFIG_REGULATOR_PFUZE100=n
+CONFIG_DRM_PANEL_RAYDIUM_RM67191=n
+CONFIG_DRM_PANEL_SITRONIX_ST7703=n
+CONFIG_PHY_MIXEL_MIPI_DPHY=n
+CONFIG_DRM_NWL_MIPI_DSI=n
+CONFIG_DRM_MXSFB=n
+CONFIG_SND_SOC_FSL_SAI=n
+CONFIG_SND_SOC_FSL_ASRC=n
+CONFIG_SND_SOC_FSL_MICFIL=n
+CONFIG_SND_SOC_FSL_AUDMIX=n
+CONFIG_SND_SOC_FSL_SPDIF=n
+CONFIG_SND_SOC_WM8904=n
+CONFIG_RTC_DRV_RV8803=n
+CONFIG_RTC_DRV_DS1307=n
+CONFIG_RTC_DRV_PCF85363=n
+CONFIG_RTC_DRV_PCF2127=n
+CONFIG_PHY_FSL_IMX8MQ_USB=n
+CONFIG_FUJITSU_ERRATUM_010001=n
+CONFIG_PCI_PASID=n
+CONFIG_UACCE=n
+CONFIG_SPI_CADENCE_QUADSPI=n
+CONFIG_DW_WATCHDOG=n
+CONFIG_NOP_USB_XCEIV=n
+CONFIG_SURFACE_PLATFORMS=n
+CONFIG_GPIO_PCA953X=n
+CONFIG_BACKLIGHT_LP855X=n
+CONFIG_MFD_MAX77620=n
+CONFIG_SENSORS_PWM_FAN=n
+CONFIG_SENSORS_INA3221=n
+CONFIG_REGULATOR_MAX8973=n
+CONFIG_USB_CONN_GPIO=n
+CONFIG_MICREL_PHY=n
+CONFIG_MFD_BD9571MWV=n
+CONFIG_DRM_PANEL_LVDS=n
+CONFIG_DRM_RCAR_LVDS=n
+CONFIG_COMMON_CLK_VC5=n
+CONFIG_CRYPTO_DEV_CCREE=n
+CONFIG_VIDEO_IMX219=n
+CONFIG_VIDEO_OV5645=n
+CONFIG_SND_SOC_AK4613=n
+CONFIG_SND_SIMPLE_CARD=n
+CONFIG_SND_SIMPLE_CARD_UTILS=n
+CONFIG_SND_AUDIO_GRAPH_CARD=n
+CONFIG_TYPEC_HD3SS3220=n
+CONFIG_RTC_DRV_RX8581=n
+CONFIG_COMMON_CLK_CS2000_CP=n
+CONFIG_KEYBOARD_ADC=n
+CONFIG_REGULATOR_FAN53555=n
+CONFIG_TOUCHSCREEN_ATMEL_MXT=n
+CONFIG_RTC_DRV_HYM8563=n
+CONFIG_MFD_SEC_CORE=n
+CONFIG_PL330_DMA=n
+CONFIG_GPIO_MB86S7X=n
+CONFIG_MMC_SDHCI_F_SDH30=n
+CONFIG_MMC_SDHCI_CADENCE=n
+CONFIG_SOCIONEXT_SYNQUACER_PREITS=n
+CONFIG_NET_VENDOR_SOCIONEXT=n
+CONFIG_ARCH_ACTIONS=n
+CONFIG_ARCH_AGILEX=n
+CONFIG_ARCH_N5X=n
+CONFIG_ARCH_SUNXI=n
+CONFIG_ARCH_ALPINE=n
+CONFIG_ARCH_APPLE=n
+CONFIG_ARCH_BCM2835=n
+CONFIG_ARCH_BCM4908=n
+CONFIG_ARCH_BCM_IPROC=n
+CONFIG_ARCH_BERLIN=n
+CONFIG_ARCH_BRCMSTB=n
+CONFIG_ARCH_EXYNOS=n
+CONFIG_ARCH_K3=n
+CONFIG_ARCH_LAYERSCAPE=n
+CONFIG_ARCH_LG1K=n
+CONFIG_ARCH_HISI=n
+CONFIG_ARCH_KEEMBAY=n
+CONFIG_ARCH_MEDIATEK=n
+CONFIG_ARCH_MESON=n
+CONFIG_ARCH_MVEBU=n
+CONFIG_ARCH_MXC=n
+CONFIG_ARCH_RENESAS=n
+CONFIG_ARCH_ROCKCHIP=n
+CONFIG_ARCH_S32=n
+CONFIG_ARCH_SEATTLE=n
+CONFIG_ARCH_INTEL_SOCFPGA=n
+CONFIG_ARCH_SYNQUACER=n
+CONFIG_ARCH_TEGRA=n
+CONFIG_ARCH_SPRD=n
+CONFIG_ARCH_THUNDER=n
+CONFIG_ARCH_THUNDER2=n
+CONFIG_ARCH_UNIPHIER=n
+CONFIG_ARCH_VEXPRESS=n
+CONFIG_ARCH_VISCONTI=n
+CONFIG_ARCH_XGENE=n
+CONFIG_ARCH_ZX=n
+CONFIG_ARCH_ZYNQMP=n
+CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM=n
+CONFIG_ARM_ARMADA_37XX_CPUFREQ=n
+CONFIG_ARM_IMX_CPUFREQ_DT=n
+CONFIG_ARM_RASPBERRYPI_CPUFREQ=n
+CONFIG_ARM_TEGRA186_CPUFREQ=n
+CONFIG_QORIQ_CPUFREQ=n
+CONFIG_RASPBERRYPI_FIRMWARE=n
+CONFIG_INTEL_STRATIX10_SERVICE=n
+CONFIG_INTEL_STRATIX10_RSU=n
+CONFIG_IMX_SCU=n
+CONFIG_IMX_SCU_PD=n
+CONFIG_CAN_RCAR=n
+CONFIG_CAN_RCAR_CANFD=n
+CONFIG_CAN_FLEXCAN=n
+CONFIG_PCI_AARDVARK=n
+CONFIG_PCI_TEGRA=n
+CONFIG_PCIE_RCAR_HOST=n
+CONFIG_PCIE_RCAR_EP=n
+CONFIG_PCI_XGENE=n
+CONFIG_PCIE_ALTERA=n
+CONFIG_PCIE_ALTERA_MSI=n
+CONFIG_PCI_HOST_THUNDER_PEM=n
+CONFIG_PCI_HOST_THUNDER_ECAM=n
+CONFIG_PCIE_ROCKCHIP_HOST=n
+CONFIG_PCIE_BRCMSTB=n
+CONFIG_PCI_IMX6=n
+CONFIG_PCI_LAYERSCAPE=n
+CONFIG_PCIE_LAYERSCAPE_GEN4=n
+CONFIG_PCI_HISI=n
+CONFIG_PCIE_ARMADA_8K=n
+CONFIG_PCIE_KIRIN=n
+CONFIG_PCIE_HISI_STB=n
+CONFIG_PCIE_TEGRA194_HOST=n
+CONFIG_HISILICON_LPC=n
+CONFIG_FSL_MC_BUS=n
+CONFIG_TEGRA_ACONNECT=n
+CONFIG_MTD_CFI_INTELEXT=n
+CONFIG_MTD_CFI_AMDSTD=n
+CONFIG_MTD_CFI_STAA=n
+CONFIG_MTD_SST25L=n
+CONFIG_MTD_NAND_DENALI_DT=n
+CONFIG_MTD_NAND_MARVELL=n
+CONFIG_MTD_NAND_FSL_IFC=n
+CONFIG_SCSI_HISI_SAS=n
+CONFIG_SCSI_HISI_SAS_PCI=n
+CONFIG_SCSI_UFS_HISI=n
+CONFIG_SCSI_UFS_EXYNOS=n
+CONFIG_AHCI_CEVA=n
+CONFIG_AHCI_MVEBU=n
+CONFIG_AHCI_XGENE=n
+CONFIG_AHCI_QORIQ=n
+CONFIG_SATA_SIL24=n
+CONFIG_SATA_RCAR=n
+CONFIG_FSL_FMAN=n
+CONFIG_FSL_DPAA_ETH=n
+CONFIG_FSL_DPAA2_ETH=n
+CONFIG_FSL_ENETC=n
+CONFIG_FSL_ENETC_VF=n
+CONFIG_FSL_ENETC_QOS=n
+CONFIG_HIX5HD2_GMAC=n
+CONFIG_HNS_DSAF=n
+CONFIG_HNS_ENET=n
+CONFIG_HNS3=n
+CONFIG_HNS3_HCLGE=n
+CONFIG_HNS3_ENET=n
+CONFIG_SERIAL_MESON=n
+CONFIG_SERIAL_MESON_CONSOLE=n
+CONFIG_SERIAL_SAMSUNG=n
+CONFIG_SERIAL_SAMSUNG_CONSOLE=n
+CONFIG_SERIAL_TEGRA=n
+CONFIG_SERIAL_TEGRA_TCU=n
+CONFIG_SERIAL_IMX=n
+CONFIG_SERIAL_IMX_CONSOLE=n
+CONFIG_SERIAL_XILINX_PS_UART=n
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=n
+CONFIG_SERIAL_FSL_LPUART=n
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=n
+CONFIG_SERIAL_FSL_LINFLEXUART=n
+CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=n
+CONFIG_SERIAL_MVEBU_UART=n
+CONFIG_SERIAL_OWL=n
+CONFIG_I2C_BCM2835=n
+CONFIG_I2C_DESIGNWARE_PLATFORM=n
+CONFIG_I2C_IMX=n
+CONFIG_I2C_IMX_LPI2C=n
+CONFIG_I2C_MESON=n
+CONFIG_I2C_MT65XX=n
+CONFIG_I2C_MV64XXX=n
+CONFIG_I2C_OMAP=n
+CONFIG_I2C_OWL=n
+CONFIG_I2C_PXA=n
+CONFIG_I2C_RK3X=n
+CONFIG_I2C_SH_MOBILE=n
+CONFIG_I2C_TEGRA=n
+CONFIG_I2C_UNIPHIER_F=n
+CONFIG_I2C_RCAR=n
+CONFIG_SPI_ARMADA_3700=n
+CONFIG_SPI_BCM2835=n
+CONFIG_SPI_BCM2835AUX=n
+CONFIG_SPI_DESIGNWARE=n
+CONFIG_SPI_DW_DMA=n
+CONFIG_SPI_DW_MMIO=n
+CONFIG_SPI_FSL_LPSPI=n
+CONFIG_SPI_FSL_QUADSPI=n
+CONFIG_SPI_IMX=n
+CONFIG_SPI_FSL_DSPI=n
+CONFIG_SPI_MESON_SPICC=n
+CONFIG_SPI_MESON_SPIFC=n
+CONFIG_SPI_ORION=n
+CONFIG_SPI_PL022=n
+CONFIG_SPI_ROCKCHIP=n
+CONFIG_SPI_RPCIF=n
+CONFIG_SPI_S3C64XX=n
+CONFIG_SPI_SH_MSIOF=n
+CONFIG_SPI_SUN6I=n
+CONFIG_PINCTRL_MAX77620=n
+CONFIG_PINCTRL_OWL=n
+CONFIG_PINCTRL_S700=n
+CONFIG_PINCTRL_S900=n
+CONFIG_PINCTRL_IMX8MM=n
+CONFIG_PINCTRL_IMX8MN=n
+CONFIG_PINCTRL_IMX8MP=n
+CONFIG_PINCTRL_IMX8MQ=n
+CONFIG_PINCTRL_IMX8QM=n
+CONFIG_PINCTRL_IMX8QXP=n
+CONFIG_PINCTRL_IMX8DXL=n
+CONFIG_GPIO_ALTERA=n
+CONFIG_GPIO_DAVINCI=n
+CONFIG_GPIO_MPC8XXX=n
+CONFIG_GPIO_MXC=n
+CONFIG_GPIO_PL061=n
+CONFIG_GPIO_RCAR=n
+CONFIG_GPIO_UNIPHIER=n
+CONFIG_GPIO_VISCONTI=n
+CONFIG_GPIO_XGENE=n
+CONFIG_GPIO_XGENE_SB=n
+CONFIG_GPIO_PCA953X_IRQ=n
+CONFIG_GPIO_BD9571MWV=n
+CONFIG_GPIO_MAX77620=n
+CONFIG_GPIO_SL28CPLD=n
+CONFIG_ROCKCHIP_IODOMAIN=n
+CONFIG_POWER_RESET_XGENE=n
+CONFIG_POWER_RESET_SYSCON=n
+CONFIG_GNSS_MTK_SERIAL=n
+CONFIG_SENSORS_RASPBERRYPI_HWMON=n
+CONFIG_SENSORS_SL28CPLD=n
+CONFIG_QORIQ_THERMAL=n
+CONFIG_SUN8I_THERMAL=n
+CONFIG_IMX_SC_THERMAL=n
+CONFIG_IMX8MM_THERMAL=n
+CONFIG_ROCKCHIP_THERMAL=n
+CONFIG_RCAR_THERMAL=n
+CONFIG_RCAR_GEN3_THERMAL=n
+CONFIG_ARMADA_THERMAL=n
+CONFIG_BCM2711_THERMAL=n
+CONFIG_BCM2835_THERMAL=n
+CONFIG_BRCMSTB_THERMAL=n
+CONFIG_EXYNOS_THERMAL=n
+CONFIG_TEGRA_BPMP_THERMAL=n
+CONFIG_TEGRA_SOCTHERM=n
+CONFIG_UNIPHIER_THERMAL=n
+CONFIG_SL28CPLD_WATCHDOG=n
+CONFIG_ARM_SP805_WATCHDOG=n
+CONFIG_S3C2410_WATCHDOG=n
+CONFIG_SUNXI_WATCHDOG=n
+CONFIG_IMX2_WDT=n
+CONFIG_IMX_SC_WDT=n
+CONFIG_MESON_GXBB_WATCHDOG=n
+CONFIG_MESON_WATCHDOG=n
+CONFIG_RENESAS_WDT=n
+CONFIG_UNIPHIER_WATCHDOG=n
+CONFIG_BCM2835_WDT=n
+CONFIG_MFD_ALTERA_SYSMGR=n
+CONFIG_MFD_AXP20X_I2C=n
+CONFIG_MFD_AXP20X_RSB=n
+CONFIG_MFD_EXYNOS_LPASS=n
+CONFIG_MFD_HI6421_PMIC=n
+CONFIG_MFD_HI655X_PMIC=n
+CONFIG_MFD_MT6397=n
+CONFIG_MFD_RK808=n
+CONFIG_MFD_SL28CPLD=n
+CONFIG_REGULATOR_AXP20X=n
+CONFIG_REGULATOR_BD718XX=n
+CONFIG_REGULATOR_BD9571MWV=n
+CONFIG_REGULATOR_HI6421V530=n
+CONFIG_REGULATOR_HI655X=n
+CONFIG_REGULATOR_MAX77620=n
+CONFIG_REGULATOR_MP8859=n
+CONFIG_REGULATOR_MT6358=n
+CONFIG_REGULATOR_MT6397=n
+CONFIG_REGULATOR_PF8X00=n
+CONFIG_REGULATOR_RK808=n
+CONFIG_REGULATOR_S2MPS11=n
+CONFIG_REGULATOR_TPS65132=n
+CONFIG_IR_MESON=n
+CONFIG_IR_SUNXI=n
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=n
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=n
+CONFIG_MEDIA_SDR_SUPPORT=n
+CONFIG_VIDEO_RCAR_CSI2=n
+CONFIG_VIDEO_RCAR_VIN=n
+CONFIG_VIDEO_SUN6I_CSI=n
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=n
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=n
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=n
+CONFIG_VIDEO_RENESAS_FDP1=n
+CONFIG_VIDEO_RENESAS_FCP=n
+CONFIG_VIDEO_RENESAS_VSP1=n
+CONFIG_SDR_PLATFORM_DRIVERS=n
+CONFIG_VIDEO_RCAR_DRIF=n
+CONFIG_DRM_I2C_NXP_TDA998X=n
+CONFIG_DRM_MALI_DISPLAY=n
+CONFIG_DRM_NOUVEAU=n
+CONFIG_DRM_EXYNOS=n
+CONFIG_DRM_EXYNOS5433_DECON=n
+CONFIG_DRM_EXYNOS7_DECON=n
+CONFIG_DRM_EXYNOS_DSI=n
+CONFIG_DRM_EXYNOS_HDMI=n
+CONFIG_DRM_EXYNOS_MIC=n
+CONFIG_DRM_ROCKCHIP=n
+CONFIG_ROCKCHIP_ANALOGIX_DP=n
+CONFIG_ROCKCHIP_CDN_DP=n
+CONFIG_ROCKCHIP_DW_HDMI=n
+CONFIG_ROCKCHIP_DW_MIPI_DSI=n
+CONFIG_ROCKCHIP_INNO_HDMI=n
+CONFIG_ROCKCHIP_LVDS=n
+CONFIG_DRM_RCAR_DU=n
+CONFIG_DRM_RCAR_DW_HDMI=n
+CONFIG_DRM_SUN4I=n
+CONFIG_DRM_SUN6I_DSI=n
+CONFIG_DRM_SUN8I_DW_HDMI=n
+CONFIG_DRM_SUN8I_MIXER=n
+CONFIG_DRM_TEGRA=n
+CONFIG_DRM_PARADE_PS8640=n
+CONFIG_DRM_SII902X=n
+CONFIG_DRM_THINE_THC63LVD1024=n
+CONFIG_DRM_VC4=n
+CONFIG_DRM_ETNAVIV=n
+CONFIG_DRM_HISI_HIBMC=n
+CONFIG_DRM_HISI_KIRIN=n
+CONFIG_DRM_MEDIATEK=n
+CONFIG_DRM_MEDIATEK_HDMI=n
+CONFIG_DRM_MESON=n
+CONFIG_DRM_PL111=n
+CONFIG_DRM_LIMA=n
+CONFIG_DRM_PANFROST=n
+CONFIG_SND_HDA_TEGRA=n
+CONFIG_SND_HDA_CODEC_HDMI=n
+CONFIG_SND_BCM2835_SOC_I2S=n
+CONFIG_SND_SOC_FSL_EASRC=n
+CONFIG_SND_IMX_SOC=n
+CONFIG_SND_SOC_IMX_SGTL5000=n
+CONFIG_SND_SOC_IMX_SPDIF=n
+CONFIG_SND_SOC_IMX_AUDMIX=n
+CONFIG_SND_SOC_FSL_ASOC_CARD=n
+CONFIG_SND_MESON_AXG_SOUND_CARD=n
+CONFIG_SND_MESON_GX_SOUND_CARD=n
+CONFIG_SND_SOC_ROCKCHIP=n
+CONFIG_SND_SOC_ROCKCHIP_SPDIF=n
+CONFIG_SND_SOC_ROCKCHIP_RT5645=n
+CONFIG_SND_SOC_RK3399_GRU_SOUND=n
+CONFIG_SND_SOC_SAMSUNG=n
+CONFIG_SND_SOC_RCAR=n
+CONFIG_SND_SUN4I_I2S=n
+CONFIG_SND_SUN4I_SPDIF=n
+CONFIG_SND_SOC_TEGRA=n
+CONFIG_SND_SOC_TEGRA210_AHUB=n
+CONFIG_SND_SOC_TEGRA210_DMIC=n
+CONFIG_SND_SOC_TEGRA210_I2S=n
+CONFIG_SND_SOC_TEGRA186_DSPK=n
+CONFIG_SND_SOC_TEGRA210_ADMAIF=n
+CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=n
+CONFIG_SND_SOC_GTM601=n
+CONFIG_SND_SOC_RT5659=n
+CONFIG_SND_SOC_WM8960=n
+CONFIG_SND_SOC_WM8962=n
+CONFIG_USB_XHCI_PCI_RENESAS=n
+CONFIG_USB_XHCI_TEGRA=n
+CONFIG_USB_EHCI_EXYNOS=n
+CONFIG_USB_OHCI_EXYNOS=n
+CONFIG_USB_RENESAS_USBHS_HCD=n
+CONFIG_USB_RENESAS_USBHS=n
+CONFIG_USB_CHIPIDEA_UDC=n
+CONFIG_USB_CHIPIDEA_HOST=n
+CONFIG_USB_RENESAS_USBHS_UDC=n
+CONFIG_USB_RENESAS_USB3=n
+CONFIG_USB_TEGRA_XUDC=n
+CONFIG_MMC_SDHCI_OF_ARASAN=n
+CONFIG_MMC_SDHCI_OF_ESDHC=n
+CONFIG_MMC_SDHCI_ESDHC_IMX=n
+CONFIG_MMC_SDHCI_TEGRA=n
+CONFIG_MMC_MESON_GX=n
+CONFIG_MMC_DW_EXYNOS=n
+CONFIG_MMC_DW_HI3798CV200=n
+CONFIG_MMC_DW_K3=n
+CONFIG_MMC_DW_ROCKCHIP=n
+CONFIG_MMC_SUNXI=n
+CONFIG_MMC_BCM2835=n
+CONFIG_MMC_MTK=n
+CONFIG_MMC_SDHCI_XENON=n
+CONFIG_MMC_SDHCI_AM654=n
+CONFIG_MMC_OWL=n
+CONFIG_RTC_DRV_MAX77686=n
+CONFIG_RTC_DRV_RK808=n
+CONFIG_RTC_DRV_M41T80=n
+CONFIG_RTC_DRV_RV3028=n
+CONFIG_RTC_DRV_S5M=n
+CONFIG_RTC_DRV_FSL_FTM_ALARM=n
+CONFIG_RTC_DRV_S3C=n
+CONFIG_RTC_DRV_PL031=n
+CONFIG_RTC_DRV_SUN6I=n
+CONFIG_RTC_DRV_ARMADA38X=n
+CONFIG_RTC_DRV_TEGRA=n
+CONFIG_RTC_DRV_SNVS=n
+CONFIG_RTC_DRV_IMX_SC=n
+CONFIG_RTC_DRV_XGENE=n
+CONFIG_DMA_BCM2835=n
+CONFIG_DMA_SUN6I=n
+CONFIG_FSL_EDMA=n
+CONFIG_IMX_SDMA=n
+CONFIG_K3_DMA=n
+CONFIG_MV_XOR=n
+CONFIG_MV_XOR_V2=n
+CONFIG_OWL_DMA=n
+CONFIG_TEGRA20_APB_DMA=n
+CONFIG_TEGRA210_ADMA=n
+CONFIG_RCAR_DMAC=n
+CONFIG_RENESAS_USB_DMAC=n
+CONFIG_TI_K3_UDMA=n
+CONFIG_TI_K3_UDMA_GLUE_LAYER=n
+CONFIG_COMMON_CLK_RK808=n
+CONFIG_COMMON_CLK_FSL_SAI=n
+CONFIG_COMMON_CLK_S2MPS11=n
+CONFIG_COMMON_CLK_ZYNQMP=n
+CONFIG_COMMON_CLK_BD718XX=n
+CONFIG_CLK_RASPBERRYPI=n
+CONFIG_CLK_IMX8MM=n
+CONFIG_CLK_IMX8MN=n
+CONFIG_CLK_IMX8MP=n
+CONFIG_CLK_IMX8MQ=n
+CONFIG_CLK_IMX8QXP=n
+CONFIG_TI_SCI_CLK=n
+CONFIG_IMX_MBOX=n
+CONFIG_BCM2835_MBOX=n
+CONFIG_ROCKCHIP_IOMMU=n
+CONFIG_TEGRA_IOMMU_SMMU=n
+CONFIG_MTK_IOMMU=n
+CONFIG_OWL_PM_DOMAINS=n
+CONFIG_RASPBERRYPI_POWER=n
+CONFIG_FSL_DPAA=n
+CONFIG_FSL_MC_DPIO=n
+CONFIG_FSL_RCPM=n
+CONFIG_MTK_PMIC_WRAP=n
+CONFIG_ARCH_R8A774A1=n
+CONFIG_ARCH_R8A774B1=n
+CONFIG_ARCH_R8A774C0=n
+CONFIG_ARCH_R8A774E1=n
+CONFIG_ARCH_R8A77950=n
+CONFIG_ARCH_R8A77951=n
+CONFIG_ARCH_R8A77960=n
+CONFIG_ARCH_R8A77961=n
+CONFIG_ARCH_R8A77965=n
+CONFIG_ARCH_R8A77970=n
+CONFIG_ARCH_R8A77980=n
+CONFIG_ARCH_R8A77990=n
+CONFIG_ARCH_R8A77995=n
+CONFIG_ARCH_R8A779A0=n
+CONFIG_ARCH_R9A07G044=n
+CONFIG_ROCKCHIP_PM_DOMAINS=n
+CONFIG_ARCH_TEGRA_132_SOC=n
+CONFIG_ARCH_TEGRA_210_SOC=n
+CONFIG_ARCH_TEGRA_186_SOC=n
+CONFIG_ARCH_TEGRA_194_SOC=n
+CONFIG_ARCH_TEGRA_234_SOC=n
+CONFIG_TI_SCI_PM_DOMAINS=n
+CONFIG_ARM_IMX_BUS_DEVFREQ=n
+CONFIG_ARM_IMX8M_DDRC_DEVFREQ=n
+CONFIG_RENESAS_RPCIF=n
+CONFIG_EXYNOS_ADC=n
+CONFIG_MAX9611=n
+CONFIG_ROCKCHIP_SARADC=n
+CONFIG_PWM_BCM2835=n
+CONFIG_PWM_IMX27=n
+CONFIG_PWM_MESON=n
+CONFIG_PWM_MTK_DISP=n
+CONFIG_PWM_MEDIATEK=n
+CONFIG_PWM_RCAR=n
+CONFIG_PWM_ROCKCHIP=n
+CONFIG_PWM_SAMSUNG=n
+CONFIG_PWM_SL28CPLD=n
+CONFIG_PWM_SUN4I=n
+CONFIG_PWM_TEGRA=n
+CONFIG_PWM_VISCONTI=n
+CONFIG_SL28CPLD_INTC=n
+CONFIG_RESET_IMX7=n
+CONFIG_RESET_TI_SCI=n
+CONFIG_PHY_XGENE=n
+CONFIG_PHY_SUN4I_USB=n
+CONFIG_PHY_HI6220_USB=n
+CONFIG_PHY_HISTB_COMBPHY=n
+CONFIG_PHY_HISI_INNO_USB2=n
+CONFIG_PHY_MVEBU_CP110_COMPHY=n
+CONFIG_PHY_MTK_TPHY=n
+CONFIG_PHY_RCAR_GEN3_PCIE=n
+CONFIG_PHY_RCAR_GEN3_USB2=n
+CONFIG_PHY_RCAR_GEN3_USB3=n
+CONFIG_PHY_ROCKCHIP_EMMC=n
+CONFIG_PHY_ROCKCHIP_INNO_HDMI=n
+CONFIG_PHY_ROCKCHIP_INNO_USB2=n
+CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=n
+CONFIG_PHY_ROCKCHIP_PCIE=n
+CONFIG_PHY_ROCKCHIP_TYPEC=n
+CONFIG_PHY_SAMSUNG_UFS=n
+CONFIG_PHY_UNIPHIER_USB2=n
+CONFIG_PHY_UNIPHIER_USB3=n
+CONFIG_PHY_TEGRA_XUSB=n
+CONFIG_FSL_IMX8_DDR_PMU=n
+CONFIG_HISI_PMU=n
+CONFIG_NVMEM_IMX_OCOTP=n
+CONFIG_NVMEM_IMX_OCOTP_SCU=n
+CONFIG_MTK_EFUSE=n
+CONFIG_ROCKCHIP_EFUSE=n
+CONFIG_NVMEM_SUNXI_SID=n
+CONFIG_UNIPHIER_EFUSE=n
+CONFIG_MESON_EFUSE=n
+CONFIG_NVMEM_RMEM=n
+CONFIG_FPGA=n
+CONFIG_FPGA_MGR_STRATIX10_SOC=n
+CONFIG_FPGA_BRIDGE=n
+CONFIG_ALTERA_FREEZE_BRIDGE=n
+CONFIG_FPGA_REGION=n
+CONFIG_OF_FPGA_REGION=n
+CONFIG_INTERCONNECT_IMX=n
+CONFIG_INTERCONNECT_IMX8MQ=n
+CONFIG_INTERCONNECT_QCOM_MSM8996=n
+CONFIG_INTERCONNECT_QCOM_QCS404=n
+CONFIG_INTERCONNECT_QCOM_SC7180=n
+CONFIG_INTERCONNECT_QCOM_SM8150=n
+CONFIG_INTERCONNECT_QCOM_SM8350=n
+CONFIG_INTERCONNECT_QCOM_SM8450=n
+CONFIG_INTERCONNECT_QCOM_SM8550=n
+CONFIG_INTERCONNECT_QCOM_SC8280XP=n
+CONFIG_ARCH_BCMBCA=n
+CONFIG_ARCH_NPCM=n
+CONFIG_SERIAL_BCM63XX=n
+CONFIG_PINCTRL_SC8280XP=n
+CONFIG_SC_GCC_8280XP=n
+CONFIG_BCM_SBA_RAID=n
+CONFIG_DMA_ENGINE_RAID=n
+CONFIG_SENSORS_GPIO_FAN=n
+CONFIG_ARCH_BCM=n
+CONFIG_ARCH_NXP=n
+CONFIG_NET_VENDOR_ADI=n
+CONFIG_PINCTRL_SC8180X=n
+CONFIG_SND_SOC_SC7180=n
+CONFIG_SND_SOC_SC7280=n
+CONFIG_SND_SOC_ADAU7002=n
+CONFIG_SND_SOC_RT5682=n
+CONFIG_SND_SOC_RT5682_I2C=n
+CONFIG_SND_SOC_RT5682S=n
+CONFIG_SND_SOC_WCD938X=n
+CONFIG_SND_SOC_WCD938X_SDW=n
+CONFIG_MMC_SDHCI_OF_DWCMSHC=n
+CONFIG_CROS_TYPEC_SWITCH=n
+CONFIG_SC_GCC_8180X=n
+CONFIG_IOMMU_IO_PGTABLE_DART=n
+CONFIG_INTERCONNECT_QCOM_SC8180X=n
+CONFIG_MEMORY_HOTPLUG=n
+CONFIG_MELLANOX_PLATFORM=n
+CONFIG_CHROME_PLATFORMS=n
+CONFIG_PINCTRL_SM8150=n
+CONFIG_SM_GCC_8150=n
+CONFIG_SM_GPUCC_8150=n
+CONFIG_PINCTRL_SM8350=n
+CONFIG_SM_GCC_8350=n
+CONFIG_SM_DISPCC_8450=n
+CONFIG_SM_GCC_8450=n
+CONFIG_PINCTRL_SM8550=n
+CONFIG_PINCTRL_SM8550_LPASS_LPI=n
+CONFIG_SM_DISPCC_8550=n
+CONFIG_SM_GCC_8550=n
+CONFIG_SM_TCSRCC_8550=n
diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c
index e792e0b130d..d045da84d7d 100644
--- a/drivers/clk/qcom/dispcc-sdm845.c
+++ b/drivers/clk/qcom/dispcc-sdm845.c
@@ -816,6 +816,7 @@ static struct clk_regmap *disp_cc_sdm845_clocks[] = {
static const struct qcom_reset_map disp_cc_sdm845_resets[] = {
[DISP_CC_MDSS_RSCC_BCR] = { 0x5000 },
+ [DISP_CC_MDSS_CORE_BCR] = { 0x2000 },
};
static struct gdsc *disp_cc_sdm845_gdscs[] = {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index fd60e49b8ec..d1936cb016c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2014,12 +2014,7 @@ static void a6xx_recover(struct msm_gpu *gpu)
dev_pm_genpd_add_notifier(gmu->cxpd, &gmu->pd_nb);
dev_pm_genpd_synced_poweroff(gmu->cxpd);
- /* Drop the rpm refcount from active submits */
- if (active_submits)
- pm_runtime_put(&gpu->pdev->dev);
-
- /* And the final one from recover worker */
- pm_runtime_put_sync(&gpu->pdev->dev);
+ pm_runtime_force_suspend(&gpu->pdev->dev);
if (!wait_for_completion_timeout(&gmu->pd_gate, msecs_to_jiffies(1000)))
DRM_DEV_ERROR(&gpu->pdev->dev, "cx gdsc didn't collapse\n");
@@ -2028,10 +2023,7 @@ static void a6xx_recover(struct msm_gpu *gpu)
pm_runtime_use_autosuspend(&gpu->pdev->dev);
- if (active_submits)
- pm_runtime_get(&gpu->pdev->dev);
-
- pm_runtime_get_sync(&gpu->pdev->dev);
+ pm_runtime_force_resume(&gpu->pdev->dev);
gpu->active_submits = active_submits;
mutex_unlock(&gpu->active_lock);
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 35423d10aaf..40d0991f645 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -333,6 +333,8 @@ static int msm_mdss_reset(struct device *dev)
"failed to acquire mdss reset\n");
}
+ dev_info(dev, "toggle reset\n");
+
reset_control_assert(reset);
/*
* Tests indicate that reset has to be held for some period of time,
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 8f378374220..bf38b22f5ea 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -407,6 +407,16 @@ config DRM_PANEL_NOVATEK_NT35560
mode. This supports several panels such as Sony ACX424AKM and
ACX424AKP.
+config DRM_PANEL_NOVATEK_NT35596S
+ tristate "Novatek NT35596S DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for the panels built
+ around the Novatek NT35596S display controller, such as some
+ JDI panels used in a few Xiaomi Mi Mix 2S mobile phones.
+
config DRM_PANEL_NOVATEK_NT35950
tristate "Novatek NT35950 DSI panel"
depends on OF
@@ -655,16 +665,28 @@ config DRM_PANEL_SAMSUNG_S6E8AA0
select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_SOFEF00
- tristate "Samsung sofef00/s6e3fc2x01 OnePlus 6/6T DSI cmd mode panels"
+ tristate "Samsung sofef00 OnePlus 6 DSI cmd mode panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
+ help
+ Say Y or M here if you want to enable support for the Samsung AMOLED
+ command mode panel found in the OnePlus 6 smartphone.
+
+ The panel is 2280x1080@60Hz
+
+config DRM_PANEL_SAMSUNG_S6E3FC2X01
+ tristate "Samsung s6e3fc2x01 OnePlus 6T DSI cmd mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y or M here if you want to enable support for the Samsung AMOLED
- command mode panels found in the OnePlus 6/6T smartphones.
+ command mode panel found in the OnePlus 6T smartphone.
- The panels are 2280x1080@60Hz and 2340x1080@60Hz respectively
+ The panel is 2340x1080@60Hz
config DRM_PANEL_SEIKO_43WVF1G
tristate "Seiko 43WVF1G panel"
@@ -845,6 +867,15 @@ config DRM_PANEL_VISIONOX_RM69299
Say Y here if you want to enable support for Visionox
RM69299 DSI Video Mode panel.
+config DRM_PANEL_VISIONOX_RM69299_SHIFT
+ tristate "Visionox RM69299 SHIFT6mq"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Visionox
+ RM69299 command mode panel variant found in the SHIFT6mq.
+
config DRM_PANEL_VISIONOX_VTDR6130
tristate "Visionox VTDR6130"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index d94a644d0a6..8c0ed8b54bf 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35560) += panel-novatek-nt35560.o
+obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35596S) += panel-novatek-nt35596s.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
@@ -67,6 +68,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_DSI) += panel-samsung-s6e63m0-dsi.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
obj-$(CONFIG_DRM_PANEL_SAMSUNG_SOFEF00) += panel-samsung-sofef00.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FC2X01) += panel-samsung-s6e3fc2x01.o
obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
@@ -86,6 +88,7 @@ obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
+obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299_SHIFT) += panel-visionox-rm69299-shift.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_VTDR6130) += panel-visionox-vtdr6130.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_R66451) += panel-visionox-r66451.o
obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o
diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c
index e85d63a176d..2ad37758079 100644
--- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c
+++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c
@@ -87,22 +87,22 @@ static int ebbg_ft8719_on(struct ebbg_ft8719 *ctx)
return 0;
}
-static int ebbg_ft8719_off(struct ebbg_ft8719 *ctx)
+static int ebbg_ft8719_disable(struct drm_panel *panel)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
+ struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel);
+ struct device *dev = &ctx->dsi->dev;
int ret;
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ret = mipi_dsi_dcs_set_display_off(dsi);
+ ret = mipi_dsi_dcs_set_display_off(ctx->dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display off: %d\n", ret);
return ret;
}
usleep_range(10000, 11000);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ ret = mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
if (ret < 0) {
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
@@ -137,13 +137,8 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel)
static int ebbg_ft8719_unprepare(struct drm_panel *panel)
{
struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel);
- struct device *dev = &ctx->dsi->dev;
int ret;
- ret = ebbg_ft8719_off(ctx);
- if (ret < 0)
- dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
-
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
@@ -188,6 +183,7 @@ static int ebbg_ft8719_get_modes(struct drm_panel *panel,
static const struct drm_panel_funcs ebbg_ft8719_panel_funcs = {
.prepare = ebbg_ft8719_prepare,
+ .disable = ebbg_ft8719_disable,
.unprepare = ebbg_ft8719_unprepare,
.get_modes = ebbg_ft8719_get_modes,
};
@@ -233,6 +229,7 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi)
drm_panel_init(&ctx->panel, dev, &ebbg_ft8719_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
ret = drm_panel_of_backlight(&ctx->panel);
if (ret)
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35596s.c b/drivers/gpu/drm/panel/panel-novatek-nt35596s.c
new file mode 100644
index 00000000000..b1c724ebf8f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-novatek-nt35596s.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Linaro Ltd
+ * Author: Sumit Semwal <sumit.semwal@linaro.org>
+ * Copyright (C) 2023 Arnaud Ferraris <arnaud.ferraris@collabora.com>
+ *
+ * This driver is for the DSI interface to panels using the NT35596S display driver IC
+ * from Novatek.
+ * Currently supported are the JDI FHD panels found in some Xiaomi phones, including
+ * some variants of the Mi Mix 2S phone.
+ *
+ * Panels using the Novatek NT35596S IC should add appropriate configuration per-panel and
+ * use this driver.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+struct nt35596s_panel_cmd {
+ const char data[2];
+};
+
+static const char * const nt35596s_regulator_names[] = {
+ "vddio",
+ "vddpos",
+ "vddneg",
+};
+
+static unsigned long const nt35596s_regulator_enable_loads[] = {
+ 62000,
+ 100000,
+ 100000
+};
+
+struct nt35596s_panel_desc {
+ const struct drm_display_mode *display_mode;
+ const char *panel_name;
+
+ unsigned int width_mm;
+ unsigned int height_mm;
+
+ unsigned long mode_flags;
+ enum mipi_dsi_pixel_format format;
+ unsigned int lanes;
+
+ unsigned int num_on_cmds;
+ const struct nt35596s_panel_cmd *on_cmds;
+};
+
+struct nt35596s_panel {
+ struct drm_panel base;
+ struct mipi_dsi_device *link;
+ const struct nt35596s_panel_desc *desc;
+
+ struct regulator_bulk_data supplies[ARRAY_SIZE(nt35596s_regulator_names)];
+
+ struct gpio_desc *reset_gpio;
+
+ bool prepared;
+};
+
+static inline struct nt35596s_panel *to_nt35596s_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct nt35596s_panel, base);
+}
+
+static int nt35596s_send_cmds(struct drm_panel *panel, const struct nt35596s_panel_cmd *cmds,
+ int num)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < num; i++) {
+ const struct nt35596s_panel_cmd *cmd = &cmds[i];
+
+ err = mipi_dsi_dcs_write(pinfo->link, cmd->data[0], cmd->data + 1, 1);
+
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int nt35596s_panel_power_off(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int ret = 0;
+
+ gpiod_set_value(pinfo->reset_gpio, 1);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(pinfo->supplies), pinfo->supplies);
+ if (ret)
+ dev_err(panel->dev, "regulator_bulk_disable failed %d\n", ret);
+
+ return ret;
+}
+
+static int nt35596s_panel_disable(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int ret;
+
+ if (!pinfo->prepared)
+ return 0;
+
+ ret = mipi_dsi_dcs_set_display_off(pinfo->link);
+ if (ret < 0)
+ dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+
+ /* 120ms delay required here as per DCS spec */
+ msleep(120);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
+ if (ret < 0)
+ dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+
+ /* 0x3C = 60ms delay */
+ msleep(60);
+
+ return ret;
+}
+
+static int nt35596s_panel_unprepare(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int ret;
+
+ ret = nt35596s_panel_power_off(panel);
+ if (ret < 0)
+ dev_err(panel->dev, "power_off failed ret = %d\n", ret);
+
+ pinfo->prepared = false;
+
+ return ret;
+}
+
+static int nt35596s_panel_power_on(struct nt35596s_panel *pinfo)
+{
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pinfo->supplies), pinfo->supplies);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * As per downstream kernel, Reset sequence of Tianma FHD panel requires the panel to
+ * be out of reset for 10ms, followed by being held in reset for 10ms. But for Android
+ * AOSP, we needed to bump it upto 200ms otherwise we get white screen sometimes.
+ * FIXME: Try to reduce this 200ms to a lesser value.
+ */
+ gpiod_set_value(pinfo->reset_gpio, 1);
+ msleep(200);
+ gpiod_set_value(pinfo->reset_gpio, 0);
+ msleep(200);
+
+ return 0;
+}
+
+static int nt35596s_panel_prepare(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int err;
+
+ if (pinfo->prepared)
+ return 0;
+
+ err = nt35596s_panel_power_on(pinfo);
+ if (err < 0)
+ goto poweroff;
+
+ /* send first part of init cmds */
+ err = nt35596s_send_cmds(panel, pinfo->desc->on_cmds,
+ pinfo->desc->num_on_cmds);
+
+ if (err < 0) {
+ dev_err(panel->dev, "failed to send DCS Init 1st Code: %d\n", err);
+ goto poweroff;
+ }
+
+ err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
+ if (err < 0) {
+ dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);
+ goto poweroff;
+ }
+
+ /* 0x46 = 70 ms delay */
+ msleep(70);
+
+ err = mipi_dsi_dcs_set_display_on(pinfo->link);
+ if (err < 0) {
+ dev_err(panel->dev, "failed to Set Display ON: %d\n", err);
+ goto poweroff;
+ }
+
+ msleep(120);
+
+ pinfo->prepared = true;
+
+ return 0;
+
+poweroff:
+ gpiod_set_value(pinfo->reset_gpio, 0);
+ return err;
+}
+
+static int nt35596s_panel_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ const struct drm_display_mode *m = pinfo->desc->display_mode;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, m);
+ if (!mode) {
+ dev_err(panel->dev, "failed to add mode %ux%u@%u\n", m->hdisplay,
+ m->vdisplay, drm_mode_vrefresh(m));
+ return -ENOMEM;
+ }
+
+ connector->display_info.width_mm = pinfo->desc->width_mm;
+ connector->display_info.height_mm = pinfo->desc->height_mm;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs panel_funcs = {
+ .disable = nt35596s_panel_disable,
+ .unprepare = nt35596s_panel_unprepare,
+ .prepare = nt35596s_panel_prepare,
+ .get_modes = nt35596s_panel_get_modes,
+};
+
+static const struct nt35596s_panel_cmd jdi_nt35596s_video_on_cmds[] = {
+ { .data = { 0xff, 0x24 } },
+ { .data = { 0x9d, 0x34 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0xc4, 0x25 } },
+ { .data = { 0xd1, 0x08 } },
+ { .data = { 0xd2, 0x84 } },
+ { .data = { 0xff, 0x26 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0x03, 0x1c } },
+ { .data = { 0x3b, 0x08 } },
+ { .data = { 0x6b, 0x08 } },
+ { .data = { 0x97, 0x08 } },
+ { .data = { 0xc5, 0x08 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0xff, 0x23 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0x01, 0x84 } },
+ { .data = { 0x05, 0x2d } },
+ { .data = { 0x06, 0x00 } },
+ { .data = { 0x33, 0x07 } },
+ { .data = { 0x21, 0xee } },
+ { .data = { 0x22, 0xed } },
+ { .data = { 0x23, 0xea } },
+ { .data = { 0x24, 0xe8 } },
+ { .data = { 0x25, 0xe5 } },
+ { .data = { 0x26, 0xe2 } },
+ { .data = { 0x27, 0xde } },
+ { .data = { 0x28, 0xbb } },
+ { .data = { 0x29, 0x87 } },
+ { .data = { 0x2a, 0x77 } },
+ { .data = { 0x32, 0x0c } },
+ { .data = { 0x13, 0x3f } },
+ { .data = { 0x14, 0x34 } },
+ { .data = { 0x15, 0x2a } },
+ { .data = { 0x16, 0x25 } },
+ { .data = { 0x17, 0x9d } },
+ { .data = { 0x18, 0x9a } },
+ { .data = { 0x19, 0x97 } },
+ { .data = { 0x1a, 0x94 } },
+ { .data = { 0x1b, 0x91 } },
+ { .data = { 0x1c, 0x8e } },
+ { .data = { 0x1d, 0x8b } },
+ { .data = { 0x1e, 0x89 } },
+ { .data = { 0x1f, 0x86 } },
+ { .data = { 0x20, 0x83 } },
+ { .data = { 0xff, 0x22 } },
+ { .data = { 0x00, 0x0a } },
+ { .data = { 0x01, 0x43 } },
+ { .data = { 0x02, 0x5b } },
+ { .data = { 0x03, 0x6a } },
+ { .data = { 0x04, 0x7a } },
+ { .data = { 0x05, 0x82 } },
+ { .data = { 0x06, 0x85 } },
+ { .data = { 0x07, 0x80 } },
+ { .data = { 0x08, 0x7c } },
+ { .data = { 0x09, 0x7c } },
+ { .data = { 0x0a, 0x74 } },
+ { .data = { 0x0b, 0x71 } },
+ { .data = { 0x0c, 0x6e } },
+ { .data = { 0x0d, 0x68 } },
+ { .data = { 0x0e, 0x65 } },
+ { .data = { 0x0f, 0x5c } },
+ { .data = { 0x10, 0x32 } },
+ { .data = { 0x11, 0x18 } },
+ { .data = { 0x12, 0x00 } },
+ { .data = { 0x13, 0x00 } },
+ { .data = { 0x1a, 0x00 } },
+ { .data = { 0x1b, 0x00 } },
+ { .data = { 0x1c, 0x00 } },
+ { .data = { 0x1d, 0x00 } },
+ { .data = { 0x1e, 0x00 } },
+ { .data = { 0x1f, 0x00 } },
+ { .data = { 0x20, 0x00 } },
+ { .data = { 0x21, 0x00 } },
+ { .data = { 0x22, 0x00 } },
+ { .data = { 0x23, 0x00 } },
+ { .data = { 0x24, 0x00 } },
+ { .data = { 0x25, 0x00 } },
+ { .data = { 0x26, 0x00 } },
+ { .data = { 0x27, 0x00 } },
+ { .data = { 0x28, 0x00 } },
+ { .data = { 0x29, 0x00 } },
+ { .data = { 0x2a, 0x00 } },
+ { .data = { 0x2b, 0x00 } },
+ { .data = { 0x2f, 0x00 } },
+ { .data = { 0x30, 0x00 } },
+ { .data = { 0x31, 0x00 } },
+ { .data = { 0x32, 0x0c } },
+ { .data = { 0x33, 0x0c } },
+ { .data = { 0x34, 0x0c } },
+ { .data = { 0x35, 0x0b } },
+ { .data = { 0x36, 0x09 } },
+ { .data = { 0x37, 0x09 } },
+ { .data = { 0x38, 0x08 } },
+ { .data = { 0x39, 0x05 } },
+ { .data = { 0x3a, 0x03 } },
+ { .data = { 0x3b, 0x00 } },
+ { .data = { 0x3f, 0x00 } },
+ { .data = { 0x40, 0x00 } },
+ { .data = { 0x41, 0x00 } },
+ { .data = { 0x42, 0x00 } },
+ { .data = { 0x43, 0x00 } },
+ { .data = { 0x44, 0x00 } },
+ { .data = { 0x45, 0x00 } },
+ { .data = { 0x46, 0x00 } },
+ { .data = { 0x47, 0x00 } },
+ { .data = { 0x48, 0x00 } },
+ { .data = { 0x49, 0x03 } },
+ { .data = { 0x4a, 0x06 } },
+ { .data = { 0x4b, 0x07 } },
+ { .data = { 0x4c, 0x07 } },
+ { .data = { 0x53, 0x01 } },
+ { .data = { 0x54, 0x01 } },
+ { .data = { 0x55, 0x89 } },
+ { .data = { 0x56, 0x00 } },
+ { .data = { 0x58, 0x00 } },
+ { .data = { 0x68, 0x00 } },
+ { .data = { 0x84, 0xff } },
+ { .data = { 0x85, 0xff } },
+ { .data = { 0x86, 0x03 } },
+ { .data = { 0x87, 0x00 } },
+ { .data = { 0x88, 0x00 } },
+ { .data = { 0xa2, 0x20 } },
+ { .data = { 0xa9, 0x01 } },
+ { .data = { 0xaa, 0x12 } },
+ { .data = { 0xab, 0x13 } },
+ { .data = { 0xac, 0x0a } },
+ { .data = { 0xad, 0x74 } },
+ { .data = { 0xaf, 0x33 } },
+ { .data = { 0xb0, 0x03 } },
+ { .data = { 0xb1, 0x14 } },
+ { .data = { 0xb2, 0x42 } },
+ { .data = { 0xb3, 0x40 } },
+ { .data = { 0xb4, 0xa5 } },
+ { .data = { 0xb6, 0x44 } },
+ { .data = { 0xb7, 0x04 } },
+ { .data = { 0xb8, 0x14 } },
+ { .data = { 0xb9, 0x42 } },
+ { .data = { 0xba, 0x40 } },
+ { .data = { 0xbb, 0xa5 } },
+ { .data = { 0xbd, 0x44 } },
+ { .data = { 0xbe, 0x04 } },
+ { .data = { 0xbf, 0x00 } },
+ { .data = { 0xc0, 0x75 } },
+ { .data = { 0xc1, 0x6a } },
+ { .data = { 0xc2, 0xa5 } },
+ { .data = { 0xc4, 0x22 } },
+ { .data = { 0xc5, 0x02 } },
+ { .data = { 0xc6, 0x00 } },
+ { .data = { 0xc7, 0x95 } },
+ { .data = { 0xc8, 0x8a } },
+ { .data = { 0xc9, 0xa5 } },
+ { .data = { 0xcb, 0x22 } },
+ { .data = { 0xcc, 0x02 } },
+ { .data = { 0xcd, 0x00 } },
+ { .data = { 0xce, 0xb5 } },
+ { .data = { 0xcf, 0xaa } },
+ { .data = { 0xd0, 0xa5 } },
+ { .data = { 0xd2, 0x22 } },
+ { .data = { 0xd3, 0x02 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0xff, 0x10 } },
+ { .data = { 0x26, 0x02 } },
+ { .data = { 0x35, 0x00 } },
+ { .data = { 0x51, 0xff } },
+ { .data = { 0x53, 0x24 } },
+ { .data = { 0x55, 0x00 } },
+ { .data = { 0xb0, 0x00 } },
+};
+
+static const struct drm_display_mode jdi_nt35596s_video_panel_mode = {
+ .clock = (1080 + 16 + 28 + 40) * (2160 + 7 + 4 + 24) * 60 / 1000,
+
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 16,
+ .hsync_end = 1080 + 16 + 28,
+ .htotal = 1080 + 16 + 28 + 40,
+
+ .vdisplay = 2160,
+ .vsync_start = 2160 + 7,
+ .vsync_end = 2160 + 7 + 4,
+ .vtotal = 2160 + 7 + 4 + 24,
+
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct nt35596s_panel_desc jdi_nt35596s_video_panel_desc = {
+ .display_mode = &jdi_nt35596s_video_panel_mode,
+
+ .width_mm = 68,
+ .height_mm = 136,
+
+ .mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_VIDEO_BURST,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+ .on_cmds = jdi_nt35596s_video_on_cmds,
+ .num_on_cmds = ARRAY_SIZE(jdi_nt35596s_video_on_cmds),
+};
+
+static int nt35596s_panel_add(struct nt35596s_panel *pinfo)
+{
+ struct device *dev = &pinfo->link->dev;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++)
+ pinfo->supplies[i].supply = nt35596s_regulator_names[i];
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pinfo->supplies),
+ pinfo->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++) {
+ ret = regulator_set_load(pinfo->supplies[i].consumer,
+ nt35596s_regulator_enable_loads[i]);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set regulator enable loads\n");
+ }
+
+ pinfo->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(pinfo->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(pinfo->reset_gpio),
+ "failed to get reset gpio from DT\n");
+
+ drm_panel_init(&pinfo->base, dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
+
+ drm_panel_add(&pinfo->base);
+
+ return 0;
+}
+
+static int nt35596s_panel_probe(struct mipi_dsi_device *dsi)
+{
+ struct nt35596s_panel *pinfo;
+ const struct nt35596s_panel_desc *desc;
+ int err;
+
+ pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
+ if (!pinfo)
+ return -ENOMEM;
+
+ desc = of_device_get_match_data(&dsi->dev);
+ dsi->mode_flags = desc->mode_flags;
+ dsi->format = desc->format;
+ dsi->lanes = desc->lanes;
+ pinfo->desc = desc;
+ pinfo->link = dsi;
+
+ mipi_dsi_set_drvdata(dsi, pinfo);
+
+ err = nt35596s_panel_add(pinfo);
+ if (err < 0)
+ return err;
+
+ err = mipi_dsi_attach(dsi);
+ if (err < 0) {
+ drm_panel_remove(&pinfo->base);
+ return err;
+ }
+
+ return 0;
+}
+
+static void nt35596s_panel_remove(struct mipi_dsi_device *dsi)
+{
+ struct nt35596s_panel *pinfo = mipi_dsi_get_drvdata(dsi);
+ int err;
+
+ err = drm_panel_unprepare(&pinfo->base);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
+
+ err = drm_panel_disable(&pinfo->base);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
+
+ err = mipi_dsi_detach(dsi);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
+
+ drm_panel_remove(&pinfo->base);
+}
+
+static void nt35596s_panel_shutdown(struct mipi_dsi_device *dsi)
+{
+ struct nt35596s_panel *pinfo = mipi_dsi_get_drvdata(dsi);
+
+ drm_panel_disable(&pinfo->base);
+ drm_panel_unprepare(&pinfo->base);
+}
+
+static const struct of_device_id jdi_fhd_video_of_match[] = {
+ { .compatible = "jdi,fhd-nt35596s", .data = &jdi_nt35596s_video_panel_desc },
+ { },
+};
+MODULE_DEVICE_TABLE(of, jdi_fhd_video_of_match);
+
+static struct mipi_dsi_driver nt35596s_panel_driver = {
+ .driver = {
+ .name = "panel-jdi-nt35596s",
+ .of_match_table = jdi_fhd_video_of_match,
+ },
+ .probe = nt35596s_panel_probe,
+ .remove = nt35596s_panel_remove,
+ .shutdown = nt35596s_panel_shutdown,
+};
+module_mipi_dsi_driver(nt35596s_panel_driver);
+
+MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
+MODULE_DESCRIPTION("NOVATEK NT35596s based MIPI-DSI LCD panel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
index 33fb3d715e5..6e764cfbeb5 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
@@ -114,7 +114,7 @@ static int nt36672a_panel_power_off(struct drm_panel *panel)
return ret;
}
-static int nt36672a_panel_unprepare(struct drm_panel *panel)
+static int nt36672a_panel_disable(struct drm_panel *panel)
{
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
int ret;
@@ -143,6 +143,14 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel)
/* 0x3C = 60ms delay */
msleep(60);
+ return ret;
+}
+
+static int nt36672a_panel_unprepare(struct drm_panel *panel)
+{
+ struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
+ int ret;
+
ret = nt36672a_panel_power_off(panel);
if (ret < 0)
dev_err(panel->dev, "power_off failed ret = %d\n", ret);
@@ -254,6 +262,7 @@ static int nt36672a_panel_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs panel_funcs = {
+ .disable = nt36672a_panel_disable,
.unprepare = nt36672a_panel_unprepare,
.prepare = nt36672a_panel_prepare,
.get_modes = nt36672a_panel_get_modes,
@@ -626,6 +635,7 @@ static int nt36672a_panel_add(struct nt36672a_panel *pinfo)
"failed to get reset gpio from DT\n");
drm_panel_init(&pinfo->base, dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
+ pinfo->base.prepare_prev_first = true;
ret = drm_panel_of_backlight(&pinfo->base);
if (ret)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c b/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c
new file mode 100644
index 00000000000..32714e276b6
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c
@@ -0,0 +1,385 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2022 Nia Espera <a5b6@riseup.net>
+ * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+ * Copyright (c) 2022, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/swab.h>
+#include <linux/backlight.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct samsung_s6e3fc2x01 {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+ const struct drm_display_mode *mode;
+ bool prepared;
+};
+
+static inline
+struct samsung_s6e3fc2x01 *to_samsung_s6e3fc2x01(struct drm_panel *panel)
+{
+ return container_of(panel, struct samsung_s6e3fc2x01, panel);
+}
+
+static void samsung_s6e3fc2x01_reset(struct samsung_s6e3fc2x01 *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(2000, 3000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+static int samsung_s6e3fc2x01_on(struct samsung_s6e3fc2x01 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xcd, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ usleep_range(15000, 16000);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set tear on: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x17, 0x41, 0x92, 0x0e, 0x10, 0x82, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_column_address(dsi, 0x0000, 0x0437);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set column address: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_page_address(dsi, 0x0000, 0x0923);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set page address: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x09);
+ mipi_dsi_dcs_write_seq(dsi, 0xe8, 0x10, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x12);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x88);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xed, 0x67);
+ mipi_dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+ usleep_range(1000, 2000);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(10000, 11000);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_disable(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display off: %d\n", ret);
+ return ret;
+ }
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ usleep_range(16000, 17000);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x50);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x82);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ usleep_range(16000, 17000);
+ msleep(40);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ msleep(160);
+
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_prepare(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ if (ctx->prepared)
+ return 0;
+
+ ret = regulator_enable(ctx->supply);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable regulator: %d\n", ret);
+ return ret;
+ }
+
+ samsung_s6e3fc2x01_reset(ctx);
+
+ ret = samsung_s6e3fc2x01_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_disable(ctx->supply);
+ return ret;
+ }
+
+ ctx->prepared = true;
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_unprepare(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+
+ if (!ctx->prepared)
+ return 0;
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_disable(ctx->supply);
+
+ ctx->prepared = false;
+ return 0;
+}
+
+static const struct drm_display_mode samsung_s6e3fc2x01_mode = {
+ .clock = (1080 + 72 + 16 + 36) * (2340 + 32 + 4 + 18) * 60 / 1000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 72,
+ .hsync_end = 1080 + 72 + 16,
+ .htotal = 1080 + 72 + 16 + 36,
+ .vdisplay = 2340,
+ .vsync_start = 2340 + 32,
+ .vsync_end = 2340 + 32 + 4,
+ .vtotal = 2340 + 32 + 4 + 18,
+ .width_mm = 68,
+ .height_mm = 145,
+};
+
+static int samsung_s6e3fc2x01_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+
+ mode = drm_mode_duplicate(connector->dev, ctx->mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs samsung_s6e3fc2x01_panel_funcs = {
+ .prepare = samsung_s6e3fc2x01_prepare,
+ .disable = samsung_s6e3fc2x01_disable,
+ .unprepare = samsung_s6e3fc2x01_unprepare,
+ .get_modes = samsung_s6e3fc2x01_get_modes,
+};
+
+static int s6e3fc2x01_panel_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ int err;
+ u16 brightness;
+
+ brightness = (u16)backlight_get_brightness(bl);
+ // This panel needs the high and low bytes swapped for the brightness value
+ brightness = __swab16(brightness);
+
+ err = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static const struct backlight_ops s6e3fc2x01_panel_bl_ops = {
+ .update_status = s6e3fc2x01_panel_bl_update_status,
+};
+
+static struct backlight_device *
+s6e3fc2x01_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_PLATFORM,
+ .brightness = 1023,
+ .max_brightness = 1023,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &s6e3fc2x01_panel_bl_ops, &props);
+}
+
+static int samsung_s6e3fc2x01_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct samsung_s6e3fc2x01 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->mode = of_device_get_match_data(dev);
+
+ if (!ctx->mode) {
+ dev_err(dev, "Missing device mode\n");
+ return -ENODEV;
+ }
+
+ ctx->supply = devm_regulator_get(dev, "vddio");
+ if (IS_ERR(ctx->supply))
+ return dev_err_probe(dev, PTR_ERR(ctx->supply),
+ "Failed to get vddio regulator\n");
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_NO_EOT_PACKET |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+ drm_panel_init(&ctx->panel, dev, &samsung_s6e3fc2x01_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
+
+ ctx->panel.backlight = s6e3fc2x01_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void samsung_s6e3fc2x01_remove(struct mipi_dsi_device *dsi)
+{
+ struct samsung_s6e3fc2x01 *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+
+ return;
+}
+
+static const struct of_device_id samsung_s6e3fc2x01_of_match[] = {
+ {
+ .compatible = "samsung,s6e3fc2x01",
+ .data = &samsung_s6e3fc2x01_mode,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, samsung_s6e3fc2x01_of_match);
+
+static struct mipi_dsi_driver samsung_s6e3fc2x01_driver = {
+ .probe = samsung_s6e3fc2x01_probe,
+ .remove = samsung_s6e3fc2x01_remove,
+ .driver = {
+ .name = "panel-samsung-s6e3fc2x01",
+ .of_match_table = samsung_s6e3fc2x01_of_match,
+ },
+};
+module_mipi_dsi_driver(samsung_s6e3fc2x01_driver);
+
+MODULE_AUTHOR("Nia Espera <a5b6@riseup.net>");
+MODULE_DESCRIPTION("DRM driver for OnePlus 6T Panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-samsung-sofef00.c b/drivers/gpu/drm/panel/panel-samsung-sofef00.c
index 04ce925b3d9..d7df52a25fb 100644
--- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c
+++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c
@@ -81,24 +81,24 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
return 0;
}
-static int sofef00_panel_off(struct sofef00_panel *ctx)
+static int sofef00_panel_disable(struct drm_panel *panel)
{
+ struct sofef00_panel *ctx = to_sofef00_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
- dev_err(dev, "Failed to set display off: %d\n", ret);
+ dev_err(&dsi->dev, "Failed to set display off: %d\n", ret);
return ret;
}
msleep(40);
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret < 0) {
- dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+ dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
}
msleep(160);
@@ -133,12 +133,6 @@ static int sofef00_panel_prepare(struct drm_panel *panel)
static int sofef00_panel_unprepare(struct drm_panel *panel)
{
struct sofef00_panel *ctx = to_sofef00_panel(panel);
- struct device *dev = &ctx->dsi->dev;
- int ret;
-
- ret = sofef00_panel_off(ctx);
- if (ret < 0)
- dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
regulator_disable(ctx->supply);
@@ -159,20 +153,6 @@ static const struct drm_display_mode enchilada_panel_mode = {
.height_mm = 145,
};
-static const struct drm_display_mode fajita_panel_mode = {
- .clock = (1080 + 72 + 16 + 36) * (2340 + 32 + 4 + 18) * 60 / 1000,
- .hdisplay = 1080,
- .hsync_start = 1080 + 72,
- .hsync_end = 1080 + 72 + 16,
- .htotal = 1080 + 72 + 16 + 36,
- .vdisplay = 2340,
- .vsync_start = 2340 + 32,
- .vsync_end = 2340 + 32 + 4,
- .vtotal = 2340 + 32 + 4 + 18,
- .width_mm = 68,
- .height_mm = 145,
-};
-
static int sofef00_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
{
struct drm_display_mode *mode;
@@ -194,6 +174,7 @@ static int sofef00_panel_get_modes(struct drm_panel *panel, struct drm_connector
static const struct drm_panel_funcs sofef00_panel_panel_funcs = {
.prepare = sofef00_panel_prepare,
+ .disable = sofef00_panel_disable,
.unprepare = sofef00_panel_unprepare,
.get_modes = sofef00_panel_get_modes,
};
@@ -264,6 +245,7 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi)
drm_panel_init(&ctx->panel, dev, &sofef00_panel_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
ctx->panel.backlight = sofef00_create_backlight(dsi);
if (IS_ERR(ctx->panel.backlight))
@@ -299,10 +281,6 @@ static const struct of_device_id sofef00_panel_of_match[] = {
.compatible = "samsung,sofef00",
.data = &enchilada_panel_mode,
},
- { // OnePlus 6T / fajita
- .compatible = "samsung,s6e3fc2x01",
- .data = &fajita_panel_mode,
- },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sofef00_panel_of_match);
diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299-shift.c b/drivers/gpu/drm/panel/panel-visionox-rm69299-shift.c
new file mode 100644
index 00000000000..c9d760dc992
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-visionox-rm69299-shift.c
@@ -0,0 +1,757 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2023 Caleb Connolly <caleb.connolly@linaro.org>
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+// Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct shift6mq_rm69299 {
+ struct drm_panel panel;
+ struct regulator_bulk_data supplies[2];
+ struct mipi_dsi_device *dsi;
+ struct gpio_desc *reset_gpio;
+ bool prepared;
+};
+
+static inline
+struct shift6mq_rm69299 *to_shift6mq_rm69299(struct drm_panel *panel)
+{
+ return container_of(panel, struct shift6mq_rm69299, panel);
+}
+
+static void shift6mq_rm69299_reset(struct shift6mq_rm69299 *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(20);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ msleep(20);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(20);
+}
+
+static int shift6mq_rm69299_on(struct shift6mq_rm69299 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x08, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x09, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x0b, 0xcc);
+ mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x90);
+ mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x87);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x8d);
+ mipi_dsi_dcs_write_seq(dsi, 0x21, 0x8d);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x28, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_LUT, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x32);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x32);
+ mipi_dsi_dcs_write_seq(dsi, 0x37, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x38, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0x39, 0xa8);
+ mipi_dsi_dcs_write_seq(dsi, 0x46, 0x48);
+ mipi_dsi_dcs_write_seq(dsi, 0x47, 0x48);
+ mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x74, 0x2b);
+ mipi_dsi_dcs_write_seq(dsi, 0x80, 0x1c);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0x93, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x85, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x84, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x86, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x87, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x88, 0x2e);
+ mipi_dsi_dcs_write_seq(dsi, 0x89, 0x2e);
+ mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x09);
+ mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x91, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x90, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x8d, 0xd0);
+ mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x13, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x33);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x1e);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x88);
+ mipi_dsi_dcs_write_seq(dsi, 0x32, 0x88);
+ mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf1);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x50);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x01, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x02, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x03, 0x7c);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x7c);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0x8e);
+ mipi_dsi_dcs_write_seq(dsi, 0x08, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x09, 0xd3);
+ mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x0b, 0xfd);
+ mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x22);
+ mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x5e);
+ mipi_dsi_dcs_write_seq(dsi, 0x10, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x11, 0x99);
+ mipi_dsi_dcs_write_seq(dsi, 0x12, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x13, 0xd3);
+ mipi_dsi_dcs_write_seq(dsi, 0x14, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x15, 0xf3);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x17, 0x33);
+ mipi_dsi_dcs_write_seq(dsi, 0x18, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x72);
+ mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x1b, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x1d, 0xd7);
+ mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x09);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x21, 0x41);
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x23, 0x79);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0xb1);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0xcc);
+ mipi_dsi_dcs_write_seq(dsi, 0x28, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x29, 0xe8);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0x32, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x3c);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x35, 0x58);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x37, 0x73);
+ mipi_dsi_dcs_write_seq(dsi, 0x38, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x39, 0x8f);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x05);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x9d);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_VSYNC_TIMING, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x41, 0xab);
+ mipi_dsi_dcs_write_seq(dsi, 0x42, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x43, 0xb2);
+ mipi_dsi_dcs_write_seq(dsi, 0x44, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_GET_SCANLINE, 0xb5);
+ mipi_dsi_dcs_write_seq(dsi, 0x46, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x47, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x48, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x49, 0x7c);
+ mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x4b, 0xae);
+ mipi_dsi_dcs_write_seq(dsi, 0x4c, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x4d, 0xc6);
+ mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x4f, 0xee);
+ mipi_dsi_dcs_write_seq(dsi, 0x50, 0x02);
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x0014);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display brightness: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x52, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x31);
+ mipi_dsi_dcs_write_seq(dsi, 0x58, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x59, 0x68);
+ mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x9f);
+ mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x5d, 0xd5);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_CABC_MIN_BRIGHTNESS, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x5f, 0xf5);
+ mipi_dsi_dcs_write_seq(dsi, 0x60, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x61, 0x33);
+ mipi_dsi_dcs_write_seq(dsi, 0x62, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x63, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x64, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x65, 0xa2);
+ mipi_dsi_dcs_write_seq(dsi, 0x66, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x67, 0xd4);
+ mipi_dsi_dcs_write_seq(dsi, 0x68, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x69, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x3b);
+ mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x71);
+ mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x6f, 0xa7);
+ mipi_dsi_dcs_write_seq(dsi, 0x70, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x71, 0xc2);
+ mipi_dsi_dcs_write_seq(dsi, 0x72, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x73, 0xdc);
+ mipi_dsi_dcs_write_seq(dsi, 0x74, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x75, 0xf7);
+ mipi_dsi_dcs_write_seq(dsi, 0x76, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x77, 0x12);
+ mipi_dsi_dcs_write_seq(dsi, 0x78, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x79, 0x2d);
+ mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x48);
+ mipi_dsi_dcs_write_seq(dsi, 0x7c, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x63);
+ mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x7e);
+ mipi_dsi_dcs_write_seq(dsi, 0x80, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x81, 0x8b);
+ mipi_dsi_dcs_write_seq(dsi, 0x82, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x83, 0x98);
+ mipi_dsi_dcs_write_seq(dsi, 0x84, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x85, 0x9f);
+ mipi_dsi_dcs_write_seq(dsi, 0x86, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x87, 0xa2);
+ mipi_dsi_dcs_write_seq(dsi, 0x88, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x89, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x7c);
+ mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x8d, 0xae);
+ mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x90, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x91, 0x2e);
+ mipi_dsi_dcs_write_seq(dsi, 0x92, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x93, 0x4e);
+ mipi_dsi_dcs_write_seq(dsi, 0x94, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x95, 0x6e);
+ mipi_dsi_dcs_write_seq(dsi, 0x96, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x97, 0xaa);
+ mipi_dsi_dcs_write_seq(dsi, 0x98, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x99, 0xe5);
+ mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x41);
+ mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x84);
+ mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xa5, 0xc6);
+ mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xa7, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0xac, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xad, 0x37);
+ mipi_dsi_dcs_write_seq(dsi, 0xae, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xaf, 0x6e);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xb1, 0xac);
+ mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0xe9);
+ mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x26);
+ mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x44);
+ mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x63);
+ mipi_dsi_dcs_write_seq(dsi, 0xba, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x81);
+ mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xbd, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0xbe, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xbf, 0xbe);
+ mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xc1, 0xdd);
+ mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xc3, 0xfb);
+ mipi_dsi_dcs_write_seq(dsi, 0xc4, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xc5, 0x1a);
+ mipi_dsi_dcs_write_seq(dsi, 0xc6, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xc7, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x38);
+ mipi_dsi_dcs_write_seq(dsi, 0xca, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0xcc, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xcd, 0x43);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0xcc);
+ mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x02, 0xff);
+ mipi_dsi_dcs_write_seq(dsi, 0x03, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x09, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x10, 0x71);
+ mipi_dsi_dcs_write_seq(dsi, 0x12, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x13, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x14, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x15, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x17, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0x18, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x71);
+ mipi_dsi_dcs_write_seq(dsi, 0x1b, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0x21, 0x66);
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0xb4);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x28, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x29, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x66);
+ mipi_dsi_dcs_write_seq(dsi, 0x2b, 0xb4);
+ mipi_dsi_dcs_write_seq(dsi, 0x2f, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_ROWS, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_PARTIAL_COLUMNS, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x32, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0x03);
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set tear on: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x71);
+ mipi_dsi_dcs_write_seq(dsi, 0x38, 0xc4);
+ mipi_dsi_dcs_write_seq(dsi, 0x39, 0x00);
+
+ ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x04);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set pixel format: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x3b, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_3D_CONTROL, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x3f, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_VSYNC_TIMING, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x41, 0x71);
+ mipi_dsi_dcs_write_seq(dsi, 0x83, 0xce);
+ mipi_dsi_dcs_write_seq(dsi, 0x84, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x85, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0x86, 0xdc);
+ mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x88, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x89, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x8a, 0xbb);
+ mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0xc7, 0x0e);
+ mipi_dsi_dcs_write_seq(dsi, 0xc8, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xca, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xcc, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xcd, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xce, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd0, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd1, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd3, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd5, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x17);
+ mipi_dsi_dcs_write_seq(dsi, 0xd8, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x16);
+ mipi_dsi_dcs_write_seq(dsi, 0xda, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xdb, 0x0e);
+ mipi_dsi_dcs_write_seq(dsi, 0xdc, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xdd, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xde, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xe0, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xe1, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xe2, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe7, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe8, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xea, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x17);
+ mipi_dsi_dcs_write_seq(dsi, 0xec, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xed, 0x16);
+ mipi_dsi_dcs_write_seq(dsi, 0xee, 0x1f);
+ mipi_dsi_dcs_write_seq(dsi, 0xef, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x0b);
+ mipi_dsi_dcs_write_seq(dsi, 0x5b, 0x0b);
+ mipi_dsi_dcs_write_seq(dsi, 0x5c, 0x55);
+ mipi_dsi_dcs_write_seq(dsi, 0x5d, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x90);
+ mipi_dsi_dcs_write_seq(dsi, 0x12, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0x13, 0x49);
+ mipi_dsi_dcs_write_seq(dsi, 0x14, 0x92);
+ mipi_dsi_dcs_write_seq(dsi, 0x15, 0x86);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x61);
+ mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
+ mipi_dsi_dcs_write_seq(dsi, 0x18, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0x19, 0x49);
+ mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x92);
+ mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x86);
+ mipi_dsi_dcs_write_seq(dsi, 0x1c, 0x61);
+ mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x18);
+ mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x24);
+ mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x49);
+ mipi_dsi_dcs_write_seq(dsi, 0x20, 0x92);
+ mipi_dsi_dcs_write_seq(dsi, 0x21, 0x86);
+ mipi_dsi_dcs_write_seq(dsi, 0x22, 0x61);
+ mipi_dsi_dcs_write_seq(dsi, 0x23, 0x18);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0x0e, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0xa0);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x16, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_SET_GAMMA_CURVE, 0x10);
+ mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x37);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0xd0);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x0f);
+ mipi_dsi_dcs_write_seq(dsi, 0x4b, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x56, 0x4a);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x08);
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set tear on: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x61);
+ mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x4e);
+ mipi_dsi_dcs_write_seq(dsi, 0x52, 0x2c);
+ mipi_dsi_dcs_write_seq(dsi, 0x49, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x4a, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x4b, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x4c, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x4d, 0xe8);
+ mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x25);
+ mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x6e);
+ mipi_dsi_dcs_write_seq(dsi, 0x50, 0xae);
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x002f);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display brightness: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xad, 0xf4);
+ mipi_dsi_dcs_write_seq(dsi, 0xae, 0x8f);
+ mipi_dsi_dcs_write_seq(dsi, 0xaf, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x54);
+ mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x3a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x18);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x4a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x98);
+ mipi_dsi_dcs_write_seq(dsi, 0xba, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0xbc, 0x50);
+ mipi_dsi_dcs_write_seq(dsi, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xbe, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xbf, 0x39);
+ mipi_dsi_dcs_write_seq(dsi, 0xfe, 0x00);
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00df);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display brightness: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+ msleep(120);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+ msleep(20);
+
+ return 0;
+}
+
+static int shift6mq_rm69299_off(struct shift6mq_rm69299 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display off: %d\n", ret);
+ return ret;
+ }
+ msleep(20);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+ return ret;
+ }
+ msleep(120);
+
+ return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);;
+}
+
+static int shift6mq_rm69299_prepare(struct drm_panel *panel)
+{
+ struct shift6mq_rm69299 *ctx = to_shift6mq_rm69299(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ if (ctx->prepared)
+ return 0;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ shift6mq_rm69299_reset(ctx);
+
+ ret = shift6mq_rm69299_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ return ret;
+ }
+
+ ctx->prepared = true;
+ return 0;
+}
+
+static int shift6mq_rm69299_disable(struct drm_panel *panel)
+{
+ struct shift6mq_rm69299 *ctx = to_shift6mq_rm69299(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ ret = shift6mq_rm69299_off(ctx);
+ if (ret < 0)
+ dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+ return 0;
+}
+
+static int shift6mq_rm69299_unprepare(struct drm_panel *panel)
+{
+ struct shift6mq_rm69299 *ctx = to_shift6mq_rm69299(panel);
+
+ if (!ctx->prepared)
+ return 0;
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+ ctx->prepared = false;
+ return 0;
+}
+
+static const struct drm_display_mode shift6mq_rm69299_mode = {
+ .clock = (1080 + 26 + 2 + 36) * (2160 + 8 + 4 + 4) * 60 / 1000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 26,
+ .hsync_end = 1080 + 26 + 2,
+ .htotal = 1080 + 26 + 2 + 36,
+ .vdisplay = 2160,
+ .vsync_start = 2160 + 8,
+ .vsync_end = 2160 + 8 + 4,
+ .vtotal = 2160 + 8 + 4 + 4,
+ .width_mm = 74,
+ .height_mm = 131,
+};
+
+static int shift6mq_rm69299_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, &shift6mq_rm69299_mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs shift6mq_rm69299_panel_funcs = {
+ .disable = shift6mq_rm69299_disable,
+ .prepare = shift6mq_rm69299_prepare,
+ .unprepare = shift6mq_rm69299_unprepare,
+ .get_modes = shift6mq_rm69299_get_modes,
+};
+
+static int shift6mq_rm69299_panel_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_brightness(dsi,
+ backlight_get_brightness(bl));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct backlight_ops shift6mq_rm69299_panel_bl_ops = {
+ .update_status = shift6mq_rm69299_panel_bl_update_status,
+};
+
+static struct backlight_device *
+shift6mq_rm69299_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_PLATFORM,
+ .brightness = 50,
+ .max_brightness = 255,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &shift6mq_rm69299_panel_bl_ops, &props);
+}
+
+static int shift6mq_rm69299_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct shift6mq_rm69299 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ctx->supplies[0].supply = "vdda";
+ ctx->supplies[1].supply = "vdd3p3";
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+ ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_NO_EOT_PACKET;
+
+ drm_panel_init(&ctx->panel, dev, &shift6mq_rm69299_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.backlight = shift6mq_rm69299_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+ ctx->panel.prepare_prev_first = true;
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void shift6mq_rm69299_remove(struct mipi_dsi_device *dsi)
+{
+ struct shift6mq_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+}
+
+static const struct of_device_id shift6mq_rm69299_of_match[] = {
+ { .compatible = "visionox,rm69299-shift" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, shift6mq_rm69299_of_match);
+
+static struct mipi_dsi_driver shift6mq_rm69299_driver = {
+ .probe = shift6mq_rm69299_probe,
+ .remove = shift6mq_rm69299_remove,
+ .driver = {
+ .name = "panel-shift6mq-rm69299",
+ .of_match_table = shift6mq_rm69299_of_match,
+ },
+};
+module_mipi_dsi_driver(shift6mq_rm69299_driver);
+
+MODULE_DESCRIPTION("DRM driver for SHIFT6mq RM69299 1080p panel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 7dd83ec74f8..2c63ea3e6f8 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -1019,6 +1019,7 @@ static const char *absolutes[ABS_CNT] = {
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth",
[ABS_VOLUME] = "Volume", [ABS_PROFILE] = "Profile",
+ [ABS_SND_PROFILE] = "SoundProfile",
[ABS_MISC] = "Misc",
[ABS_MT_TOUCH_MAJOR] = "MTMajor",
[ABS_MT_TOUCH_MINOR] = "MTMinor",
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 6ba984d7f0b..6ed273a9b3c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -197,6 +197,18 @@ config INPUT_PMIC8XXX_PWRKEY
To compile this driver as a module, choose M here: the
module will be called pmic8xxx-pwrkey.
+config INPUT_QCOM_SPMI_HAPTICS
+ tristate "Qualcomm SPMI HAPTICS"
+ depends on ARCH_QCOM
+ depends on SPMI
+ select INPUT_FF_MEMLESS
+ help
+ This option enables support for the haptics found in pmi8998 and
+ related PMICs. Based on the ff-memless interface.
+
+ To compile this driver as module, choose M here: the
+ module will be called qcom_spmi_haptics.
+
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 04296a4abe8..9c2967a5972 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o
+obj-$(CONFIG_INPUT_QCOM_SPMI_HAPTICS) += qcom-spmi-haptics.o
obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o
diff --git a/drivers/input/misc/qcom-spmi-haptics.c b/drivers/input/misc/qcom-spmi-haptics.c
new file mode 100644
index 00000000000..aad8a0be679
--- /dev/null
+++ b/drivers/input/misc/qcom-spmi-haptics.c
@@ -0,0 +1,981 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, Caleb Connolly <caleb@connolly.tech>
+ * Qualcomm QPMI haptics driver for pmi8998 and related PMICs.
+ */
+
+#include <dt-bindings/input/qcom,spmi-haptics.h>
+
+#include <linux/atomic.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+
+#define HAP_STATUS_1_REG 0x0A
+#define HAP_BUSY_BIT BIT(1)
+#define SC_FLAG_BIT BIT(3)
+#define AUTO_RES_ERROR_BIT BIT(4)
+
+#define HAP_LRA_AUTO_RES_LO_REG 0x0B
+#define HAP_LRA_AUTO_RES_HI_REG 0x0C
+
+#define HAP_EN_CTL_REG 0x46
+#define HAP_EN_BIT BIT(7)
+
+#define HAP_EN_CTL2_REG 0x48
+#define BRAKE_EN_BIT BIT(0)
+
+#define HAP_AUTO_RES_CTRL_REG 0x4B
+#define AUTO_RES_EN_BIT BIT(7)
+#define AUTO_RES_ERR_RECOVERY_BIT BIT(3)
+#define AUTO_RES_EN_FLAG_BIT BIT(0)
+
+#define HAP_CFG1_REG 0x4C
+#define HAP_ACT_TYPE_MASK BIT(0)
+
+#define HAP_CFG2_REG 0x4D
+#define HAP_LRA_RES_TYPE_MASK BIT(0)
+
+#define HAP_SEL_REG 0x4E
+#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
+#define HAP_WF_SOURCE_SHIFT 4
+
+#define HAP_LRA_AUTO_RES_REG 0x4F
+#define LRA_AUTO_RES_MODE_MASK GENMASK(6, 4)
+#define LRA_AUTO_RES_MODE_SHIFT 4
+#define LRA_HIGH_Z_MASK GENMASK(3, 2)
+#define LRA_HIGH_Z_SHIFT 2
+#define LRA_RES_CAL_MASK GENMASK(1, 0)
+#define HAP_RES_CAL_PERIOD_MIN 4
+#define HAP_RES_CAL_PERIOD_MAX 32
+
+#define HAP_VMAX_CFG_REG 0x51
+#define HAP_VMAX_OVD_BIT BIT(6)
+#define HAP_VMAX_MASK GENMASK(5, 1)
+#define HAP_VMAX_SHIFT 1
+
+#define HAP_ILIM_CFG_REG 0x52
+#define HAP_ILIM_SEL_MASK BIT(0)
+#define HAP_ILIM_400_MA 0
+#define HAP_ILIM_800_MA 1
+
+#define HAP_SC_DEB_REG 0x53
+#define HAP_SC_DEB_MASK GENMASK(2, 0)
+#define HAP_SC_DEB_CYCLES_MIN 0
+#define HAP_DEF_SC_DEB_CYCLES 8
+#define HAP_SC_DEB_CYCLES_MAX 32
+
+#define HAP_RATE_CFG1_REG 0x54
+#define HAP_RATE_CFG1_MASK GENMASK(7, 0)
+#define HAP_RATE_CFG2_SHIFT 8 // As CFG2 is the most significant byte
+
+#define HAP_RATE_CFG2_REG 0x55
+#define HAP_RATE_CFG2_MASK GENMASK(3, 0)
+
+#define HAP_SC_CLR_REG 0x59
+#define SC_CLR_BIT BIT(0)
+
+#define HAP_BRAKE_REG 0x5C
+#define HAP_BRAKE_PAT_MASK 0x3
+
+#define HAP_WF_REPEAT_REG 0x5E
+#define WF_REPEAT_MASK GENMASK(6, 4)
+#define WF_REPEAT_SHIFT 4
+#define WF_REPEAT_MIN 1
+#define WF_REPEAT_MAX 128
+#define WF_S_REPEAT_MASK GENMASK(1, 0)
+#define WF_S_REPEAT_MIN 1
+#define WF_S_REPEAT_MAX 8
+
+#define HAP_WF_S1_REG 0x60
+#define HAP_WF_SIGN_BIT BIT(7)
+#define HAP_WF_OVD_BIT BIT(6)
+#define HAP_WF_SAMP_MAX GENMASK(5, 1)
+#define HAP_WF_SAMPLE_LEN 8
+
+#define HAP_PLAY_REG 0x70
+#define HAP_PLAY_BIT BIT(7)
+#define HAP_PAUSE_BIT BIT(0)
+
+#define HAP_SEC_ACCESS_REG 0xD0
+#define HAP_SEC_ACCESS_UNLOCK 0xA5
+
+#define HAP_TEST2_REG 0xE3
+
+
+#define HAP_VMAX_MIN_MV 116
+#define HAP_VMAX_MAX_MV 3596
+#define HAP_VMAX_MAX_MV_STRONG 3596
+
+#define HAP_WAVE_PLAY_RATE_MIN_US 0
+#define HAP_WAVE_PLAY_RATE_MAX_US 20475
+#define HAP_WAVE_PLAY_TIME_MAX_MS 15000
+
+#define AUTO_RES_ERR_POLL_TIME_NS (20 * NSEC_PER_MSEC)
+#define HAPTICS_BACK_EMF_DELAY_US 20000
+
+#define HAP_BRAKE_PAT_LEN 4
+#define HAP_WAVE_SAMP_LEN 8
+#define NUM_WF_SET 4
+#define HAP_WAVE_SAMP_SET_LEN (HAP_WAVE_SAMP_LEN * NUM_WF_SET)
+#define HAP_RATE_CFG_STEP_US 5
+
+#define SC_MAX_COUNT 5
+#define SC_COUNT_RST_DELAY_US 1000000
+
+enum hap_play_control {
+ HAP_STOP,
+ HAP_PAUSE,
+ HAP_PLAY,
+};
+
+/**
+ * struct spmi_haptics - struct for spmi haptics data.
+ *
+ * @dev: Our device parent.
+ * @regmap: Register map for the hardware block.
+ * @input_dev: The input device used to receive events.
+ * @work: Work struct to play effects.
+ * @base: Base address of the regmap.
+ * @active: Atomic value used to track if haptics are currently playing.
+ * @play_irq: Fired to load the next wave pattern.
+ * @sc_irq: Short circuit irq.
+ * @last_sc_time: Time since the short circuit IRQ last fired.
+ * @sc_count: Number of times the short circuit IRQ has fired in this interval.
+ * @actuator_type: The type of actuator in use.
+ * @wave_shape: The shape of the waves to use (sine or square).
+ * @play_mode: The play mode to use (direct, buffer, pwm, audio).
+ * @magnitude: The strength we should be playing at.
+ * @vmax: Max voltage to use when playing.
+ * @current_limit: The current limit for this hardware (400mA or 800mA).
+ * @play_wave_rate: The wave rate to use for this hardware.
+ * @wave_samp: The array of wave samples to write for buffer mode.
+ * @brake_pat: The pattern to apply when braking.
+ * @play_lock: Lock to be held when updating the hardware state.
+ */
+struct spmi_haptics {
+ struct device *dev;
+ struct regmap *regmap;
+ struct input_dev *haptics_input_dev;
+ struct work_struct work;
+ u32 base;
+
+ atomic_t active;
+
+ int play_irq;
+ int sc_irq;
+ ktime_t last_sc_time;
+ u8 sc_count;
+
+ u8 actuator_type;
+ u8 wave_shape;
+ u8 play_mode;
+ int magnitude;
+ u32 vmax;
+ u32 current_limit;
+ u32 play_wave_rate;
+
+ u32 wave_samp[HAP_WAVE_SAMP_SET_LEN];
+ u8 brake_pat[HAP_BRAKE_PAT_LEN];
+
+ struct mutex play_lock;
+};
+
+static inline bool is_secure_addr(u16 addr)
+{
+ return (addr & 0xFF) > 0xD0;
+}
+
+static int spmi_haptics_read(struct spmi_haptics *haptics,
+ u16 addr, u8 *val, int len)
+{
+ int ret;
+
+ ret = regmap_bulk_read(haptics->regmap, addr, val, len);
+ if (ret < 0)
+ dev_err(haptics->dev, "Error reading address: 0x%x, ret %d\n", addr, ret);
+
+ return ret;
+}
+
+static int spmi_haptics_write(struct spmi_haptics *haptics,
+ u16 addr, u8 *val, int len)
+{
+ int ret, i;
+
+ if (is_secure_addr(addr)) {
+ for (i = 0; i < len; i++) {
+ dev_dbg(haptics->dev, "%s: unlocking for addr: 0x%x, val: 0x%x", __func__,
+ addr, val[i]);
+ ret = regmap_write(haptics->regmap,
+ haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error writing unlock code, ret %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = regmap_write(haptics->regmap, addr + i, val[i]);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error writing address 0x%x, ret %d\n",
+ addr + i, ret);
+ return ret;
+ }
+ }
+ } else {
+ if (len > 1)
+ ret = regmap_bulk_write(haptics->regmap, addr, val, len);
+ else
+ ret = regmap_write(haptics->regmap, addr, *val);
+ }
+
+ if (ret < 0)
+ dev_err(haptics->dev, "%s: Error writing address: 0x%x, ret %d\n",
+ __func__, addr, ret);
+
+ return ret;
+}
+
+static int spmi_haptics_write_masked(struct spmi_haptics *haptics,
+ u16 addr, u8 mask, u8 val)
+{
+ int ret;
+
+ if (is_secure_addr(addr)) {
+ ret = regmap_write(haptics->regmap,
+ haptics->base + HAP_SEC_ACCESS_REG, HAP_SEC_ACCESS_UNLOCK);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error writing unlock code - ret %d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = regmap_update_bits(haptics->regmap, addr, mask, val);
+ if (ret < 0)
+ dev_err(haptics->dev, "Error writing address: 0x%x - ret %d\n", addr, ret);
+
+ return ret;
+}
+
+static bool is_haptics_idle(struct spmi_haptics *haptics)
+{
+ int ret;
+ u8 val;
+
+ if (haptics->play_mode == HAP_PLAY_DIRECT ||
+ haptics->play_mode == HAP_PLAY_PWM)
+ return true;
+
+ ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
+ if (ret < 0 || (val & HAP_BUSY_BIT))
+ return false;
+
+ return true;
+}
+
+static int spmi_haptics_module_enable(struct spmi_haptics *haptics, bool enable)
+{
+ u8 val;
+
+ dev_dbg(haptics->dev, "Setting module enable: %d", enable);
+
+ val = enable ? HAP_EN_BIT : 0;
+ return spmi_haptics_write(haptics, haptics->base + HAP_EN_CTL_REG, &val, 1);
+}
+
+static int spmi_haptics_write_vmax(struct spmi_haptics *haptics)
+{
+ u8 val = 0;
+ u32 vmax_mv = haptics->vmax;
+
+ vmax_mv = clamp_t(u32, vmax_mv, HAP_VMAX_MIN_MV, HAP_VMAX_MAX_MV);
+
+ dev_dbg(haptics->dev, "Setting vmax to: %d", vmax_mv);
+
+ val = DIV_ROUND_CLOSEST(vmax_mv, HAP_VMAX_MIN_MV);
+ val = FIELD_PREP(HAP_VMAX_MASK, val);
+
+ // TODO: pm660 can enable overdrive here
+
+ return spmi_haptics_write_masked(haptics, haptics->base + HAP_VMAX_CFG_REG,
+ HAP_VMAX_MASK | HAP_WF_OVD_BIT, val);
+}
+
+static int spmi_haptics_write_current_limit(struct spmi_haptics *haptics)
+{
+ haptics->current_limit = clamp_t(u32, haptics->current_limit,
+ HAP_ILIM_400_MA, HAP_ILIM_800_MA);
+
+ dev_dbg(haptics->dev, "Setting current_limit to: 0x%x", haptics->current_limit);
+
+ return spmi_haptics_write_masked(haptics, haptics->base + HAP_ILIM_CFG_REG,
+ HAP_ILIM_SEL_MASK, haptics->current_limit);
+}
+
+static int spmi_haptics_write_play_mode(struct spmi_haptics *haptics)
+{
+ u8 val = 0;
+
+ if (!is_haptics_idle(haptics))
+ return -EBUSY;
+
+ dev_dbg(haptics->dev, "Setting play_mode to: 0x%x", haptics->play_mode);
+
+ val = FIELD_PREP(HAP_WF_SOURCE_MASK, haptics->play_mode);
+ return spmi_haptics_write_masked(haptics, haptics->base + HAP_SEL_REG,
+ HAP_WF_SOURCE_MASK, val);
+
+}
+
+static int spmi_haptics_write_play_rate(struct spmi_haptics *haptics, u16 play_rate)
+{
+ u8 val[2];
+
+ dev_dbg(haptics->dev, "Setting play_rate to: %d", play_rate);
+
+ val[0] = FIELD_PREP(HAP_RATE_CFG1_MASK, play_rate);
+ val[1] = FIELD_PREP(HAP_RATE_CFG2_MASK, play_rate >> HAP_RATE_CFG2_SHIFT);
+ return spmi_haptics_write(haptics, haptics->base + HAP_RATE_CFG1_REG, val, 2);
+}
+
+/*
+ * spmi_haptics_set_auto_res() - Auto resonance
+ * allows the haptics to automatically adjust the
+ * speed of the oscillation in order to maintain
+ * the resonant frequency.
+ */
+static int spmi_haptics_set_auto_res(struct spmi_haptics *haptics, bool enable)
+{
+ u8 val;
+
+ // LRAs are the only type to support auto res
+ if (haptics->actuator_type != HAP_TYPE_LRA)
+ return 0;
+
+ val = enable ? AUTO_RES_EN_BIT : 0;
+
+ return spmi_haptics_write_masked(haptics, haptics->base + HAP_TEST2_REG,
+ AUTO_RES_EN_BIT, val);
+}
+
+static int spmi_haptics_write_brake(struct spmi_haptics *haptics)
+{
+ int ret, i;
+ u8 val;
+
+ dev_dbg(haptics->dev, "Configuring brake pattern");
+
+ ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_EN_CTL2_REG,
+ BRAKE_EN_BIT, 1);
+ if (ret < 0)
+ return ret;
+
+ for (i = HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) {
+ u8 p = haptics->brake_pat[i] & HAP_BRAKE_PAT_MASK;
+
+ val |= p << (i * 2);
+ }
+
+ return spmi_haptics_write(haptics, haptics->base + HAP_BRAKE_REG, &val, 1);
+}
+
+static int spmi_haptics_write_buffer_config(struct spmi_haptics *haptics)
+{
+ u8 buf[HAP_WAVE_SAMP_LEN];
+ int i;
+
+ dev_dbg(haptics->dev, "Writing buffer config");
+
+ for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
+ buf[i] = haptics->wave_samp[i];
+
+ return spmi_haptics_write(haptics, haptics->base + HAP_WF_S1_REG, buf,
+ HAP_WAVE_SAMP_LEN);
+}
+
+/*
+ * spmi_haptics_write_wave_repeat() - write wave repeat values.
+ */
+static int spmi_haptics_write_wave_repeat(struct spmi_haptics *haptics)
+{
+ u8 val, mask;
+
+ /* The number of times to repeat each wave */
+ mask = WF_REPEAT_MASK | WF_S_REPEAT_MASK;
+ val = FIELD_PREP(WF_REPEAT_MASK, 0) |
+ FIELD_PREP(WF_S_REPEAT_MASK, 0);
+
+ return spmi_haptics_write_masked(haptics, haptics->base + HAP_WF_REPEAT_REG,
+ mask, val);
+}
+
+static int spmi_haptics_write_play_control(struct spmi_haptics *haptics,
+ enum hap_play_control ctrl)
+{
+ u8 val;
+
+ switch (ctrl) {
+ case HAP_STOP:
+ val = 0;
+ break;
+ case HAP_PAUSE:
+ val = HAP_PAUSE_BIT;
+ break;
+ case HAP_PLAY:
+ val = HAP_PLAY_BIT;
+ break;
+ default:
+ return 0;
+ }
+
+ dev_dbg(haptics->dev, "haptics play ctrl: %d\n", ctrl);
+ return spmi_haptics_write(haptics, haptics->base + HAP_PLAY_REG, &val, 1);
+}
+
+/*
+ * This IRQ is fired to tell us to load the next wave sample set.
+ * As we only currently support a single sample set, it's unused.
+ */
+static irqreturn_t spmi_haptics_play_irq_handler(int irq, void *data)
+{
+ struct spmi_haptics *haptics = data;
+
+ dev_dbg(haptics->dev, "play_irq triggered");
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Fires every ~50ms whilst the haptics are active.
+ * If the SC_FLAG_BIT is set then that means there isn't a short circuit
+ * and we just need to clear the IRQ to indicate that the device should
+ * keep vibrating.
+ *
+ * Otherwise, it means a short circuit situation has occurred.
+ */
+static irqreturn_t spmi_haptics_sc_irq_handler(int irq, void *data)
+{
+ struct spmi_haptics *haptics = data;
+ int ret;
+ u8 val;
+ s64 sc_delta_time_us;
+ ktime_t temp;
+
+ ret = spmi_haptics_read(haptics, haptics->base + HAP_STATUS_1_REG, &val, 1);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ if (!(val & SC_FLAG_BIT)) {
+ haptics->sc_count = 0;
+ return IRQ_HANDLED;
+ }
+
+ temp = ktime_get();
+ sc_delta_time_us = ktime_us_delta(temp, haptics->last_sc_time);
+ haptics->last_sc_time = temp;
+
+ if (sc_delta_time_us > SC_COUNT_RST_DELAY_US)
+ haptics->sc_count = 0;
+ else
+ haptics->sc_count++;
+
+ // Clear the interrupt flag
+ val = SC_CLR_BIT;
+ ret = spmi_haptics_write(haptics, haptics->base + HAP_SC_CLR_REG, &val, 1);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ if (haptics->sc_count > SC_MAX_COUNT) {
+ dev_crit(haptics->dev, "Short circuit persists, disabling haptics\n");
+ ret = spmi_haptics_module_enable(haptics, false);
+ if (ret < 0)
+ dev_err(haptics->dev, "Error disabling module, rc=%d\n", ret);
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/**
+ * spmi_haptics_init() - Initialise haptics hardware for use
+ * @haptics: haptics device
+ * Returns: 0 on success, < 0 on error
+ */
+static int spmi_haptics_init(struct spmi_haptics *haptics)
+{
+ int ret;
+ u8 val, mask;
+ u16 play_rate;
+
+ ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG1_REG,
+ HAP_ACT_TYPE_MASK, haptics->actuator_type);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Configure auto resonance
+ * see spmi_haptics_lra_auto_res_config downstream
+ * This is greatly simplified.
+ */
+ val = FIELD_PREP(LRA_RES_CAL_MASK, ilog2(32 / HAP_RES_CAL_PERIOD_MIN)) |
+ FIELD_PREP(LRA_AUTO_RES_MODE_MASK, HAP_AUTO_RES_ZXD_EOP) |
+ FIELD_PREP(LRA_HIGH_Z_MASK, 1);
+
+ mask = LRA_AUTO_RES_MODE_MASK | LRA_HIGH_Z_MASK | LRA_RES_CAL_MASK;
+
+ ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_LRA_AUTO_RES_REG,
+ mask, val);
+
+ /* Configure the PLAY MODE register */
+ ret = spmi_haptics_write_play_mode(haptics);
+ if (ret < 0)
+ return ret;
+
+ ret = spmi_haptics_write_vmax(haptics);
+ if (ret < 0)
+ return ret;
+
+ /* Configure the ILIM register */
+ ret = spmi_haptics_write_current_limit(haptics);
+ if (ret < 0)
+ return ret;
+
+ // Configure the debounce for short-circuit detection.
+ ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_SC_DEB_REG,
+ HAP_SC_DEB_MASK, HAP_SC_DEB_CYCLES_MAX);
+ if (ret < 0)
+ return ret;
+
+ // write the wave shape
+ ret = spmi_haptics_write_masked(haptics, haptics->base + HAP_CFG2_REG,
+ HAP_LRA_RES_TYPE_MASK, haptics->wave_shape);
+ if (ret < 0)
+ return ret;
+
+ play_rate = haptics->play_wave_rate / HAP_RATE_CFG_STEP_US;
+
+ /*
+ * Configure RATE_CFG1 and RATE_CFG2 registers.
+ * Note: For ERM these registers act as play rate and
+ * for LRA these represent resonance period
+ */
+ ret = spmi_haptics_write_play_rate(haptics, play_rate);
+ if (ret < 0)
+ return ret;
+
+ ret = spmi_haptics_write_brake(haptics);
+ if (ret < 0)
+ return ret;
+
+ if (haptics->play_mode == HAP_PLAY_BUFFER) {
+ ret = spmi_haptics_write_wave_repeat(haptics);
+ if (ret < 0)
+ return ret;
+
+ ret = spmi_haptics_write_buffer_config(haptics);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (haptics->play_irq >= 0) {
+ dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
+ haptics->play_irq);
+ ret = devm_request_threaded_irq(haptics->dev, haptics->play_irq,
+ NULL, spmi_haptics_play_irq_handler, IRQF_ONESHOT,
+ "haptics_play_irq", haptics);
+
+ if (ret < 0) {
+ dev_err(haptics->dev, "Unable to request play IRQ ret=%d\n", ret);
+ return ret;
+ }
+
+ /* use play_irq only for buffer mode */
+ if (haptics->play_mode != HAP_PLAY_BUFFER)
+ disable_irq(haptics->play_irq);
+ }
+
+ if (haptics->sc_irq >= 0) {
+ dev_dbg(haptics->dev, "%s: Requesting play IRQ, irq: %d", __func__,
+ haptics->play_irq);
+ ret = devm_request_threaded_irq(haptics->dev, haptics->sc_irq,
+ NULL, spmi_haptics_sc_irq_handler, IRQF_ONESHOT,
+ "haptics_sc_irq", haptics);
+
+ if (ret < 0) {
+ dev_err(haptics->dev, "Unable to request sc IRQ ret=%d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * spmi_haptics_enable - handler to start/stop vibration
+ * @haptics: pointer to haptics struct
+ * @enable: state to set
+ * Returns: 0 on success, < 0 on failure
+ */
+static int spmi_haptics_enable(struct spmi_haptics *haptics)
+{
+ int ret;
+
+ mutex_lock(&haptics->play_lock);
+ if (haptics->sc_count > SC_MAX_COUNT) {
+ dev_err(haptics->dev, "Can't play while in short circuit");
+ ret = -1;
+ goto out;
+ }
+ ret = spmi_haptics_set_auto_res(haptics, false);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error disabling auto_res, ret=%d\n", ret);
+ goto out;
+ }
+
+ ret = spmi_haptics_module_enable(haptics, true);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error enabling module, ret=%d\n", ret);
+ goto out;
+ }
+
+ ret = spmi_haptics_write_play_control(haptics, HAP_PLAY);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error enabling play, ret=%d\n", ret);
+ goto out;
+ }
+
+ ret = spmi_haptics_set_auto_res(haptics, true);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error enabling auto_res, ret=%d\n", ret);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&haptics->play_lock);
+ return ret;
+}
+
+/**
+ * spmi_haptics_enable - handler to start/stop vibration
+ * @haptics: pointer to haptics struct
+ * @enable: state to set
+ * Returns: 0 on success, < 0 on failure
+ */
+static int spmi_haptics_disable(struct spmi_haptics *haptics)
+{
+ int ret;
+
+ mutex_lock(&haptics->play_lock);
+
+ ret = spmi_haptics_write_play_control(haptics, HAP_STOP);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error disabling play, ret=%d\n", ret);
+ goto out;
+ }
+
+ ret = spmi_haptics_module_enable(haptics, false);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Error disabling module, ret=%d\n", ret);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&haptics->play_lock);
+ return ret;
+}
+
+/*
+ * Threaded function to update the haptics state.
+ */
+static void spmi_haptics_work(struct work_struct *work)
+{
+ struct spmi_haptics *haptics = container_of(work, struct spmi_haptics, work);
+
+ int ret;
+ bool enable;
+
+ enable = atomic_read(&haptics->active);
+ dev_dbg(haptics->dev, "%s: state: %d\n", __func__, enable);
+
+ if (enable)
+ ret = spmi_haptics_enable(haptics);
+ else
+ ret = spmi_haptics_disable(haptics);
+ if (ret < 0)
+ dev_err(haptics->dev, "Error setting haptics, ret=%d", ret);
+}
+
+/**
+ * spmi_haptics_close - callback for input device close
+ * @dev: input device pointer
+ *
+ * Turns off the vibrator.
+ */
+static void spmi_haptics_close(struct input_dev *dev)
+{
+ struct spmi_haptics *haptics = input_get_drvdata(dev);
+
+ cancel_work_sync(&haptics->work);
+ if (atomic_read(&haptics->active)) {
+ atomic_set(&haptics->active, 0);
+ schedule_work(&haptics->work);
+ }
+}
+
+/**
+ * spmi_haptics_play_effect - play haptics effects
+ * @dev: input device pointer
+ * @data: data of effect
+ * @effect: effect to play
+ */
+static int spmi_haptics_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct spmi_haptics *haptics = input_get_drvdata(dev);
+
+ dev_dbg(haptics->dev, "%s: Rumbling with strong: %d and weak: %d", __func__,
+ effect->u.rumble.strong_magnitude, effect->u.rumble.weak_magnitude);
+
+ haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
+ if (!haptics->magnitude)
+ haptics->magnitude = effect->u.rumble.weak_magnitude >> 10;
+
+ if (!haptics->magnitude) {
+ atomic_set(&haptics->active, 0);
+ goto end;
+ }
+
+ atomic_set(&haptics->active, 1);
+
+ haptics->vmax = ((HAP_VMAX_MAX_MV - HAP_VMAX_MIN_MV) * haptics->magnitude) / 100 +
+ HAP_VMAX_MIN_MV;
+
+ dev_dbg(haptics->dev, "%s: magnitude: %d, vmax: %d", __func__,
+ haptics->magnitude, haptics->vmax);
+
+ spmi_haptics_write_vmax(haptics);
+
+end:
+ schedule_work(&haptics->work);
+
+ return 0;
+}
+
+static int spmi_haptics_probe(struct platform_device *pdev)
+{
+ struct spmi_haptics *haptics;
+ struct device_node *node;
+ struct input_dev *input_dev;
+ int ret;
+ u32 val;
+ int i;
+
+ haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
+ if (!haptics)
+ return -ENOMEM;
+
+ haptics->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!haptics->regmap)
+ return -ENODEV;
+
+ node = pdev->dev.of_node;
+
+ haptics->dev = &pdev->dev;
+
+ ret = of_property_read_u32(node, "reg", &haptics->base);
+ if (ret < 0) {
+ dev_err(haptics->dev, "Couldn't find reg in node = %s ret = %d\n",
+ node->full_name, ret);
+ return ret;
+ }
+
+ haptics->play_irq = platform_get_irq_byname(pdev, "play");
+ if (haptics->play_irq < 0) {
+ dev_err(&pdev->dev, "Unable to get play irq\n");
+ ret = haptics->play_irq;
+ goto register_fail;
+ }
+
+ haptics->sc_irq = platform_get_irq_byname(pdev, "short");
+ if (haptics->sc_irq < 0) {
+ dev_err(&pdev->dev, "Unable to get sc irq\n");
+ ret = haptics->sc_irq;
+ goto register_fail;
+ }
+
+ // We only support LRAs for now
+ haptics->actuator_type = HAP_TYPE_LRA;
+ ret = of_property_read_u32(node, "qcom,actuator-type", &val);
+ if (!ret) {
+ if (val != HAP_TYPE_LRA) {
+ dev_err(&pdev->dev, "qcom,actuator-type (%d) isn't supported\n", val);
+ ret = -EINVAL;
+ goto register_fail;
+ }
+ haptics->actuator_type = val;
+ }
+
+ // Only buffer mode is currently supported
+ haptics->play_mode = HAP_PLAY_BUFFER;
+ ret = of_property_read_u32(node, "qcom,play-mode", &val);
+ if (!ret) {
+ if (val != HAP_PLAY_BUFFER) {
+ dev_err(&pdev->dev, "qcom,play-mode (%d) isn't supported\n", val);
+ ret = -EINVAL;
+ goto register_fail;
+ }
+ haptics->play_mode = val;
+ }
+
+ ret = of_property_read_u32(node, "qcom,wave-play-rate-us", &val);
+ if (!ret) {
+ haptics->play_wave_rate = val;
+ } else if (ret != -EINVAL) {
+ dev_err(haptics->dev, "Unable to read play rate ret=%d\n", ret);
+ goto register_fail;
+ }
+
+ haptics->play_wave_rate =
+ clamp_t(u32, haptics->play_wave_rate,
+ HAP_WAVE_PLAY_RATE_MIN_US, HAP_WAVE_PLAY_RATE_MAX_US);
+
+ haptics->wave_shape = HAP_WAVE_SINE;
+ ret = of_property_read_u32(node, "qcom,wave-shape", &val);
+ if (!ret) {
+ if (val != HAP_WAVE_SINE && val != HAP_WAVE_SQUARE) {
+ dev_err(&pdev->dev, "qcom,wave-shape is invalid: %d\n", val);
+ ret = -EINVAL;
+ goto register_fail;
+ }
+ haptics->wave_shape = val;
+ }
+
+ haptics->brake_pat[0] = 0x3;
+ haptics->brake_pat[1] = 0x3;
+ haptics->brake_pat[2] = 0x2;
+ haptics->brake_pat[3] = 0x1;
+
+ ret = of_property_read_u8_array(node, "qcom,brake-pattern", haptics->brake_pat, 4);
+ if (ret < 0 && ret != -EINVAL) {
+ dev_err(&pdev->dev, "qcom,brake-pattern is invalid, ret = %d\n", ret);
+ goto register_fail;
+ }
+
+ haptics->current_limit = HAP_ILIM_400_MA;
+
+ for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
+ haptics->wave_samp[i] = HAP_WF_SAMP_MAX;
+
+ ret = spmi_haptics_init(haptics);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error initialising haptics, ret=%d\n",
+ ret);
+ goto register_fail;
+ }
+
+ platform_set_drvdata(pdev, haptics);
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ INIT_WORK(&haptics->work, spmi_haptics_work);
+ haptics->haptics_input_dev = input_dev;
+
+ input_dev->name = "spmi_haptics";
+ input_dev->id.version = 1;
+ input_dev->close = spmi_haptics_close;
+ input_set_drvdata(input_dev, haptics);
+ // Figure out how to make this FF_PERIODIC
+ input_set_capability(haptics->haptics_input_dev, EV_FF, FF_RUMBLE);
+
+ ret = input_ff_create_memless(input_dev, NULL,
+ spmi_haptics_play_effect);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "couldn't register vibrator as FF device\n");
+ goto register_fail;
+ }
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "couldn't register input device\n");
+ goto register_fail;
+ }
+
+ return 0;
+
+register_fail:
+ cancel_work_sync(&haptics->work);
+ mutex_destroy(&haptics->play_lock);
+
+ return ret;
+}
+
+static int __maybe_unused spmi_haptics_suspend(struct device *dev)
+{
+ struct spmi_haptics *haptics = dev_get_drvdata(dev);
+
+ cancel_work_sync(&haptics->work);
+ spmi_haptics_disable(haptics);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(spmi_haptics_pm_ops, spmi_haptics_suspend, NULL);
+
+static int spmi_haptics_remove(struct platform_device *pdev)
+{
+ struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
+
+ cancel_work_sync(&haptics->work);
+ mutex_destroy(&haptics->play_lock);
+ input_unregister_device(haptics->haptics_input_dev);
+
+ return 0;
+}
+
+static void spmi_haptics_shutdown(struct platform_device *pdev)
+{
+ struct spmi_haptics *haptics = dev_get_drvdata(&pdev->dev);
+
+ cancel_work_sync(&haptics->work);
+
+ spmi_haptics_disable(haptics);
+}
+
+static const struct of_device_id spmi_haptics_match_table[] = {
+ { .compatible = "qcom,spmi-haptics" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, spmi_haptics_match_table);
+
+static struct platform_driver spmi_haptics_driver = {
+ .probe = spmi_haptics_probe,
+ .remove = spmi_haptics_remove,
+ .shutdown = spmi_haptics_shutdown,
+ .driver = {
+ .name = "spmi-haptics",
+ .pm = &spmi_haptics_pm_ops,
+ .of_match_table = spmi_haptics_match_table,
+ },
+};
+module_platform_driver(spmi_haptics_driver);
+
+MODULE_DESCRIPTION("spmi haptics driver using ff-memless framework");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 42eaebb3bf5..18ecbe882eb 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -136,9 +136,14 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
return 0;
if (!data->attn_data.data) {
+ /*
+ * Read the device status register as well and ignore it.
+ * Some aftermarket ICs have issues with interrupt requests
+ * otherwise.
+ */
error = rmi_read_block(rmi_dev,
- data->f01_container->fd.data_base_addr + 1,
- data->irq_status, data->num_of_irq_regs);
+ data->f01_container->fd.data_base_addr,
+ (u8*)data->irq_status - 1, data->num_of_irq_regs + 1);
if (error < 0) {
dev_err(dev, "Failed to read irqs, code=%d\n", error);
return error;
@@ -456,9 +461,10 @@ static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
return 0;
}
-static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
- struct pdt_entry *entry, u16 pdt_address)
+static int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
+ struct pdt_scan_state *state, u16 pdt_address)
{
+ const struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
u8 buf[RMI_PDT_ENTRY_SIZE];
int error;
@@ -469,6 +475,21 @@ static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
return error;
}
+ if (pdata->pdt_fallback_size > state->pdt_count * RMI_OF_PDT_DESC_CELLS + 1) {
+ /* Use the description bytes from DT */
+ buf[5] = pdata->pdt_fallback_desc[state->pdt_count * RMI_OF_PDT_DESC_CELLS];
+ buf[4] = pdata->pdt_fallback_desc[state->pdt_count * RMI_OF_PDT_DESC_CELLS + 1];
+
+ error = rmi_read_block(rmi_dev, pdt_address, buf,
+ RMI_PDT_ENTRY_SIZE - 2);
+ if (error) {
+ dev_err(&rmi_dev->dev,
+ "Read PDT entry at %#06x failed, code: %d.\n",
+ pdt_address, error);
+ return error;
+ }
+ }
+
entry->page_start = pdt_address & RMI4_PAGE_MASK;
entry->query_base_addr = buf[0];
entry->command_base_addr = buf[1];
@@ -493,12 +514,44 @@ static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
fd->function_version = pdt->function_version;
}
+static bool rmi_pdt_entry_is_valid(struct rmi_device *rmi_dev,
+ struct pdt_scan_state *state, u8 fn)
+{
+ int i;
+
+ switch (fn) {
+ case 0x01:
+ case 0x03:
+ case 0x11:
+ case 0x12:
+ case 0x30:
+ case 0x34:
+ case 0x3a:
+ case 0x54:
+ case 0x55:
+ break;
+
+ default:
+ rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+ "PDT has unknown function number %#02x\n", fn);
+ return false;
+ }
+
+ for (i = 0; i < state->pdt_count; i++) {
+ if (state->pdts[i] == fn)
+ return false;
+ }
+
+ state->pdts[state->pdt_count++] = fn;
+ return true;
+}
+
#define RMI_SCAN_CONTINUE 0
#define RMI_SCAN_DONE 1
static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
int page,
- int *empty_pages,
+ struct pdt_scan_state *state,
void *ctx,
int (*callback)(struct rmi_device *rmi_dev,
void *ctx,
@@ -514,13 +567,16 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
int retval;
for (addr = pdt_start; addr >= pdt_end; addr -= RMI_PDT_ENTRY_SIZE) {
- error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, addr);
+ error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, state, addr);
if (error)
return error;
if (RMI4_END_OF_PDT(pdt_entry.function_number))
break;
+ if (!rmi_pdt_entry_is_valid(rmi_dev, state, pdt_entry.function_number))
+ continue;
+
retval = callback(rmi_dev, ctx, &pdt_entry);
if (retval != RMI_SCAN_CONTINUE)
return retval;
@@ -531,11 +587,11 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
* or more is found, stop scanning.
*/
if (addr == pdt_start)
- ++*empty_pages;
+ ++state->empty_pages;
else
- *empty_pages = 0;
+ state->empty_pages = 0;
- return (data->bootloader_mode || *empty_pages >= 2) ?
+ return (data->bootloader_mode || state->empty_pages >= 2) ?
RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
}
@@ -544,11 +600,11 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
void *ctx, const struct pdt_entry *entry))
{
int page;
- int empty_pages = 0;
+ struct pdt_scan_state state = {0, 0, {0}};
int retval = RMI_SCAN_DONE;
for (page = 0; page <= RMI4_MAX_PAGE; page++) {
- retval = rmi_scan_pdt_page(rmi_dev, page, &empty_pages,
+ retval = rmi_scan_pdt_page(rmi_dev, page, &state,
ctx, callback);
if (retval != RMI_SCAN_CONTINUE)
break;
@@ -988,9 +1044,11 @@ static int rmi_driver_remove(struct device *dev)
}
#ifdef CONFIG_OF
-static int rmi_driver_of_probe(struct device *dev,
+static int rmi_driver_of_probe(struct rmi_device *rmi_dev,
struct rmi_device_platform_data *pdata)
{
+ struct device *dev = rmi_dev->xport->dev;
+ u8 buf[RMI_PDT_ENTRY_SIZE];
int retval;
retval = rmi_of_property_read_u32(dev, &pdata->reset_delay_ms,
@@ -998,6 +1056,45 @@ static int rmi_driver_of_probe(struct device *dev,
if (retval)
return retval;
+ /*
+ * In some aftermerket touch ICs, the first PDT entry is empty and
+ * the function number register is 0. If so, the platform
+ * may have provided backup PDT entries in the device tree.
+ */
+
+ retval = rmi_read_block(rmi_dev, PDT_START_SCAN_LOCATION,
+ buf, RMI_PDT_ENTRY_SIZE);
+ if (retval) {
+ dev_err(dev, "Read PDT entry at %#06x failed, code: %d.\n",
+ PDT_START_SCAN_LOCATION, retval);
+ return retval;
+ }
+
+ if (!RMI4_END_OF_PDT(buf[5]))
+ return 0;
+
+ pdata->pdt_fallback_size = of_property_count_u8_elems(dev->of_node,
+ "syna,pdt-fallback-desc");
+
+ /* The rmi4 driver would fail later anyway, so just error out now. */
+ if (pdata->pdt_fallback_size == -EINVAL) {
+ dev_err(dev, "First PDT entry is empty and no backup values provided\n");
+ return -EINVAL;
+ }
+
+ if (pdata->pdt_fallback_size < 0) {
+ dev_err(dev, "syna,ptd-desc property was not specified properly: %d\n",
+ pdata->pdt_fallback_size);
+ return pdata->pdt_fallback_size;
+ }
+
+ pdata->pdt_fallback_desc = devm_kzalloc(dev, pdata->pdt_fallback_size, GFP_KERNEL);
+
+ retval = of_property_read_u8_array(dev->of_node, "syna,pdt-fallback-desc",
+ pdata->pdt_fallback_desc, pdata->pdt_fallback_size);
+ if (retval < 0)
+ return retval;
+
return 0;
}
#else
@@ -1048,16 +1145,17 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
data->num_of_irq_regs = (data->irq_count + 7) / 8;
size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
- data->irq_memory = devm_kcalloc(dev, size, 4, GFP_KERNEL);
+ data->irq_memory = devm_kzalloc(dev, size * 4 + 1, GFP_KERNEL);
if (!data->irq_memory) {
dev_err(dev, "Failed to allocate memory for irq masks.\n");
return -ENOMEM;
}
- data->irq_status = data->irq_memory + size * 0;
- data->fn_irq_bits = data->irq_memory + size * 1;
- data->current_irq_mask = data->irq_memory + size * 2;
- data->new_irq_mask = data->irq_memory + size * 3;
+ /* The first byte is reserved for the device status register */
+ data->irq_status = data->irq_memory + size * 0 + 1;
+ data->fn_irq_bits = data->irq_memory + size * 1 + 1;
+ data->current_irq_mask = data->irq_memory + size * 2 + 1;
+ data->new_irq_mask = data->irq_memory + size * 3 + 1;
return retval;
}
@@ -1122,7 +1220,7 @@ static int rmi_driver_probe(struct device *dev)
pdata = rmi_get_platform_data(rmi_dev);
if (rmi_dev->xport->dev->of_node) {
- retval = rmi_driver_of_probe(rmi_dev->xport->dev, pdata);
+ retval = rmi_driver_of_probe(rmi_dev, pdata);
if (retval)
return retval;
}
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 1c6c6086c0e..2531c32d616 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -31,6 +31,8 @@
#define RMI_PDT_FUNCTION_VERSION_MASK 0x60
#define RMI_PDT_INT_SOURCE_COUNT_MASK 0x07
+#define RMI_OF_PDT_DESC_CELLS 2
+
#define PDT_START_SCAN_LOCATION 0x00e9
#define PDT_END_SCAN_LOCATION 0x0005
#define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
@@ -46,6 +48,12 @@ struct pdt_entry {
u8 function_number;
};
+struct pdt_scan_state {
+ u8 empty_pages;
+ u8 pdt_count;
+ u8 pdts[254];
+};
+
#define RMI_REG_DESC_PRESENSE_BITS (32 * BITS_PER_BYTE)
#define RMI_REG_DESC_SUBPACKET_BITS (37 * BITS_PER_BYTE)
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index cc1d4b42464..a5b14e13838 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -250,6 +250,20 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
}
}
+ /*
+ * Some aftermarket ICs put garbage into the product id field unless
+ * we read directly from the product id register.
+ */
+ if (props->product_id[0] < 0x20) {
+ ret = rmi_read_block(rmi_dev, query_base_addr + 11,
+ props->product_id, RMI_PRODUCT_ID_LENGTH);
+ if (ret) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read product id: %d\n", ret);
+ return ret;
+ }
+ }
+
return 0;
}
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 7e97944f761..719ee3b4255 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -195,6 +195,41 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
}
+static void rmi_f12_set_hardcoded_desc(struct rmi_function *fn, struct f12_data *f12)
+{
+ struct rmi_2d_sensor *sensor = &f12->sensor;
+ struct rmi_register_desc_item *reg_desc;
+
+ /* We have no f12->data_reg_desc, so the pkt_size is 0, override it with
+ * a somewhat sensible default (this corresponds to 10 fingers).
+ */
+ sensor->pkt_size = 88;
+
+ /*
+ * There are no register descriptors to get these values from.
+ * We set them to high values to either be overwritten by the clip
+ * properties from devicetree, or to just not get in the way.
+ */
+ sensor->max_x = 65535;
+ sensor->max_y = 65535;
+
+ /*
+ * Create the Data1 register descriptor so that touch events
+ * can work properly.
+ */
+ reg_desc = devm_kcalloc(&fn->dev, 1,
+ sizeof(struct rmi_register_desc_item), GFP_KERNEL);
+ reg_desc->reg = 1;
+ reg_desc->reg_size = 80;
+ reg_desc->num_subpackets = 10;
+
+ f12->data1 = reg_desc;
+ f12->data1_offset = 0;
+ sensor->nbr_fingers = reg_desc->num_subpackets;
+ sensor->report_abs = 1;
+ sensor->attn_size += reg_desc->reg_size;
+}
+
static irqreturn_t rmi_f12_attention(int irq, void *ctx)
{
int retval;
@@ -315,6 +350,40 @@ static int rmi_f12_config(struct rmi_function *fn)
return 0;
}
+static int rmi_f12_sensor_init(struct rmi_function *fn, struct f12_data *f12)
+{
+ struct rmi_2d_sensor *sensor = &f12->sensor;
+
+ sensor->fn = fn;
+ f12->data_addr = fn->fd.data_base_addr;
+
+ /* On quirky devices that don't have a data_reg_desc we hardcode the packet
+ * in rmi_f12_set_hardcoded_desc(). Make sure not to set it to 0 here.
+ */
+ if (!sensor->pkt_size)
+ sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+
+ sensor->axis_align =
+ f12->sensor_pdata.axis_align;
+
+ sensor->x_mm = f12->sensor_pdata.x_mm;
+ sensor->y_mm = f12->sensor_pdata.y_mm;
+ sensor->dribble = f12->sensor_pdata.dribble;
+
+ if (sensor->sensor_type == rmi_sensor_default)
+ sensor->sensor_type =
+ f12->sensor_pdata.sensor_type;
+
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
+ sensor->pkt_size);
+
+ sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
+ if (!sensor->data_pkt)
+ return -ENOMEM;
+
+ return 0;
+}
+
static int rmi_f12_probe(struct rmi_function *fn)
{
struct f12_data *f12;
@@ -328,6 +397,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
u16 data_offset = 0;
int mask_size;
+ bool hardcoded_desc_quirk = false;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
@@ -342,9 +412,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
++query_addr;
if (!(buf & BIT(0))) {
- dev_err(&fn->dev,
- "Behavior of F12 without register descriptors is undefined.\n");
- return -ENODEV;
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "No register descriptors defined for F12, using fallback\n");
+ hardcoded_desc_quirk = true;
}
f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
@@ -352,6 +422,8 @@ static int rmi_f12_probe(struct rmi_function *fn)
if (!f12)
return -ENOMEM;
+ dev_set_drvdata(&fn->dev, f12);
+
f12->abs_mask = (unsigned long *)((char *)f12
+ sizeof(struct f12_data));
f12->rel_mask = (unsigned long *)((char *)f12
@@ -370,6 +442,18 @@ static int rmi_f12_probe(struct rmi_function *fn)
f12->sensor_pdata = pdata->sensor_pdata;
}
+ sensor = &f12->sensor;
+
+ if (hardcoded_desc_quirk) {
+ rmi_f12_set_hardcoded_desc(fn, f12);
+
+ ret = rmi_f12_sensor_init(fn, f12);
+ if (ret)
+ return ret;
+
+ goto skip_register_desc;
+ }
+
ret = rmi_read_register_desc(rmi_dev, query_addr,
&f12->query_reg_desc);
if (ret) {
@@ -400,29 +484,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
query_addr += 3;
- sensor = &f12->sensor;
- sensor->fn = fn;
- f12->data_addr = fn->fd.data_base_addr;
- sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
-
- sensor->axis_align =
- f12->sensor_pdata.axis_align;
-
- sensor->x_mm = f12->sensor_pdata.x_mm;
- sensor->y_mm = f12->sensor_pdata.y_mm;
- sensor->dribble = f12->sensor_pdata.dribble;
-
- if (sensor->sensor_type == rmi_sensor_default)
- sensor->sensor_type =
- f12->sensor_pdata.sensor_type;
-
- rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
- sensor->pkt_size);
- sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
- if (!sensor->data_pkt)
- return -ENOMEM;
-
- dev_set_drvdata(&fn->dev, f12);
+ ret = rmi_f12_sensor_init(fn, f12);
+ if (ret)
+ return ret;
ret = rmi_f12_read_sensor_tuning(f12);
if (ret)
@@ -520,6 +584,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
data_offset += item->reg_size;
}
+skip_register_desc:
/* allocate the in-kernel tracking buffers */
sensor->tracking_pos = devm_kcalloc(&fn->dev,
sensor->nbr_fingers, sizeof(struct input_mt_pos),
diff --git a/drivers/input/rmi4/rmi_f55.c b/drivers/input/rmi4/rmi_f55.c
index 488adaca4dd..ad2ef14ae9f 100644
--- a/drivers/input/rmi4/rmi_f55.c
+++ b/drivers/input/rmi4/rmi_f55.c
@@ -52,6 +52,11 @@ static int rmi_f55_detect(struct rmi_function *fn)
f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
+ if (!f55->num_rx_electrodes || !f55->num_tx_electrodes) {
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "F55 query returned no electrodes, giving up\n");
+ return 0;
+ }
f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 2a1db113447..06ec0f2e18a 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -1462,6 +1462,10 @@ static const struct edt_i2c_chip_data edt_ft5x06_data = {
.max_support_points = 5,
};
+static const struct edt_i2c_chip_data edt_ft5452_data = {
+ .max_support_points = 5,
+};
+
static const struct edt_i2c_chip_data edt_ft5506_data = {
.max_support_points = 10,
};
@@ -1470,12 +1474,18 @@ static const struct edt_i2c_chip_data edt_ft6236_data = {
.max_support_points = 2,
};
+static const struct edt_i2c_chip_data edt_ft8719_data = {
+ .max_support_points = 10,
+};
+
static const struct i2c_device_id edt_ft5x06_ts_id[] = {
{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
{ .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
{ .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data },
+ { .name = "ft5452", .driver_data = (long)&edt_ft5452_data },
/* Note no edt- prefix for compatibility with the ft6236.c driver */
{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
+ { .name = "ft8719", .driver_data = (long)&edt_ft8719_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
@@ -1486,8 +1496,10 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
{ .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
{ .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
{ .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data },
+ { .compatible = "focaltech,ft5452", .data = &edt_ft5452_data },
/* Note focaltech vendor prefix for compatibility with ft6236.c */
{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
+ { .compatible = "focaltech,ft8719", .data = &edt_ft8719_data },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 1a797e410a3..8baedae9361 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -31,9 +31,6 @@
#define NVT_TS_PARAMS_CHIP_ID 0x0e
#define NVT_TS_PARAMS_SIZE 0x0f
-#define NVT_TS_SUPPORTED_WAKE_TYPE 0x05
-#define NVT_TS_SUPPORTED_CHIP_ID 0x05
-
#define NVT_TS_MAX_TOUCHES 10
#define NVT_TS_MAX_SIZE 4096
@@ -55,6 +52,7 @@ struct nvt_ts_data {
struct i2c_client *client;
struct input_dev *input;
struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data regulators[2];
struct touchscreen_properties prop;
int max_touches;
u8 buf[NVT_TS_TOUCH_SIZE * NVT_TS_MAX_TOUCHES];
@@ -139,9 +137,23 @@ static irqreturn_t nvt_ts_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void nvt_ts_disable_regulators(void *_data)
+{
+ struct nvt_ts_data *data = _data;
+
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
+}
+
static int nvt_ts_start(struct input_dev *dev)
{
struct nvt_ts_data *data = input_get_drvdata(dev);
+ int error;
+
+ error = regulator_bulk_enable(ARRAY_SIZE(data->regulators), data->regulators);
+ if (error) {
+ dev_err(&data->client->dev, "failed to enable regulators\n");
+ return error;
+ }
enable_irq(data->client->irq);
gpiod_set_value_cansleep(data->reset_gpio, 0);
@@ -155,6 +167,7 @@ static void nvt_ts_stop(struct input_dev *dev)
disable_irq(data->client->irq);
gpiod_set_value_cansleep(data->reset_gpio, 1);
+ nvt_ts_disable_regulators(data);
}
static int nvt_ts_suspend(struct device *dev)
@@ -202,6 +215,30 @@ static int nvt_ts_probe(struct i2c_client *client)
data->client = client;
i2c_set_clientdata(client, data);
+ /*
+ * VCC is the analog voltage supply
+ * IOVCC is the digital voltage supply
+ */
+ data->regulators[0].supply = "vcc";
+ data->regulators[1].supply = "iovcc";
+ error = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators), data->regulators);
+ if (error) {
+ dev_err(dev, "cannot get regulators: %d\n", error);
+ return error;
+ }
+
+ error = regulator_bulk_enable(ARRAY_SIZE(data->regulators), data->regulators);
+ if (error) {
+ dev_err(dev, "failed to enable regulators\n");
+ return error;
+ }
+
+ error = devm_add_action_or_reset(dev, nvt_ts_disable_regulators, data);
+ if (error) {
+ dev_err(dev, "failed to install regulator disable handler\n");
+ return error;
+ }
+
data->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
error = PTR_ERR_OR_ZERO(data->reset_gpio);
if (error) {
@@ -224,9 +261,7 @@ static int nvt_ts_probe(struct i2c_client *client)
if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE ||
data->max_touches > NVT_TS_MAX_TOUCHES ||
- irq_type >= ARRAY_SIZE(nvt_ts_irq_type) ||
- data->buf[NVT_TS_PARAMS_WAKE_TYPE] != NVT_TS_SUPPORTED_WAKE_TYPE ||
- data->buf[NVT_TS_PARAMS_CHIP_ID] != NVT_TS_SUPPORTED_CHIP_ID) {
+ irq_type >= ARRAY_SIZE(nvt_ts_irq_type)) {
dev_err(dev, "Unsupported touchscreen parameters: %*ph\n",
NVT_TS_PARAMS_SIZE, data->buf);
return -EIO;
@@ -277,6 +312,12 @@ static int nvt_ts_probe(struct i2c_client *client)
return 0;
}
+static const struct of_device_id nvt_ts_of_match[] = {
+ { .compatible = "novatek,nvt-ts" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, nvt_ts_of_match);
+
static const struct i2c_device_id nvt_ts_i2c_id[] = {
{ "NVT-ts" },
{ }
@@ -287,6 +328,7 @@ static struct i2c_driver nvt_ts_driver = {
.driver = {
.name = "novatek-nvt-ts",
.pm = pm_sleep_ptr(&nvt_ts_pm_ops),
+ .of_match_table = nvt_ts_of_match,
},
.probe = nvt_ts_probe,
.id_table = nvt_ts_i2c_id,
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index dbd26c3b245..51f469fc85c 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -953,7 +953,10 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
ctx->msg_sz = pkt_size;
- err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
+ if (ctx->fl->sctx->sid)
+ err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
+ else
+ err = fastrpc_remote_heap_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
if (err)
return err;
@@ -2257,6 +2260,8 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
int i, err, domain_id = -1, vmcount;
const char *domain;
bool secure_dsp;
+ struct device_node *rmem_node;
+ struct reserved_mem *rmem;
unsigned int vmids[FASTRPC_MAX_VMIDS];
err = of_property_read_string(rdev->of_node, "label", &domain);
@@ -2299,6 +2304,22 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
}
}
+ rmem_node = of_parse_phandle(rdev->of_node, "memory-region", 0);
+ if (domain_id == SDSP_DOMAIN_ID && rmem_node) {
+ u64 src_perms;
+ rmem = of_reserved_mem_lookup(rmem_node);
+ if (!rmem) {
+ err = -EINVAL;
+ goto fdev_error;
+ }
+
+ src_perms = BIT(QCOM_SCM_VMID_HLOS) | BIT(QCOM_SCM_VMID_SSC_Q6);
+
+ qcom_scm_assign_mem(rmem->base, rmem->size, &src_perms,
+ data->vmperms, data->vmcount);
+
+ }
+
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
data->secure = secure_dsp;
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 38e939f572a..21dbc3e1903 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -808,6 +808,7 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
{
struct ath10k *ar = qmi->ar;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
int ret;
ret = ath10k_qmi_ind_register_send_sync_msg(qmi);
@@ -819,9 +820,15 @@ static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
return;
}
- ret = ath10k_qmi_host_cap_send_sync(qmi);
- if (ret)
- return;
+ /*
+ * Skip the host capability request for the firmware versions which
+ * do not support this feature.
+ */
+ if (!test_bit(ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK, &ar_snoc->flags)) {
+ ret = ath10k_qmi_host_cap_send_sync(qmi);
+ if (ret)
+ return;
+ }
ret = ath10k_qmi_msa_mem_info_send_sync_msg(qmi);
if (ret)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 2c39bad7ebf..aa0feb01f52 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1340,6 +1340,9 @@ static void ath10k_snoc_quirks_init(struct ath10k *ar)
if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
+
+ if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-skip-quirk"))
+ set_bit(ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK, &ar_snoc->flags);
}
int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index d4bce170769..403f35af34c 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -50,6 +50,7 @@ enum ath10k_snoc_flags {
ATH10K_SNOC_FLAG_MODEM_STOPPED,
ATH10K_SNOC_FLAG_RECOVERY,
ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
+ ATH10K_SNOC_FLAG_SKIP_HOST_CAP_QUIRK,
};
struct clk_bulk_data;
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 3e31375491d..a6eb7d1c3d5 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -966,6 +966,14 @@ config BATTERY_UG3105
device is off or suspended, the functionality of this driver is
limited to reporting capacity only.
+config BATTERY_QCOM_FG
+ tristate "Qualcomm PMIC fuel gauge driver"
+ depends on MFD_SPMI_PMIC
+ help
+ Say Y here to enable the Qualcomm PMIC Fuel Gauge driver. This
+ adds support for battery fuel gauging and state of charge of
+ battery connected to the fuel gauge.
+
config CHARGER_QCOM_SMB2
tristate "Qualcomm PMI8998 PMIC charger driver"
depends on MFD_SPMI_PMIC
@@ -985,4 +993,18 @@ config FUEL_GAUGE_MM8013
the state of charge, temperature, cycle count, actual and design
capacity, etc.
+config LENOVO_YOGA_C630_EC
+ tristate "Lenovo Yoga C630 EC battery driver"
+ depends on I2C
+ help
+ Driver for the Embedded Controller in the Qualcomm Snapdragon-based
+ Lenovo Yoga C630, which provides battery and power adapter
+ information.
+
+ This driver provides battery and AC status support for the mentioned
+ laptop where this information is not properly exposed via the
+ standard ACPI devices.
+
+ Say M or Y here to include this support.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 58b56727803..655b583eb9d 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -112,5 +112,7 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
+obj-$(CONFIG_BATTERY_QCOM_FG) += qcom_fg.o
obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o
obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o
+obj-$(CONFIG_LENOVO_YOGA_C630_EC) += yoga-c630-ec.o
diff --git a/drivers/power/supply/qcom_fg.c b/drivers/power/supply/qcom_fg.c
new file mode 100644
index 00000000000..f8dd93aa23c
--- /dev/null
+++ b/drivers/power/supply/qcom_fg.c
@@ -0,0 +1,1320 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+/* SOC */
+#define BATT_MONOTONIC_SOC 0x009
+
+/* BATT */
+#define PARAM_ADDR_BATT_TEMP 0x150
+#define BATT_INFO_JEITA_COLD 0x162
+#define BATT_INFO_JEITA_COOL 0x163
+#define BATT_INFO_JEITA_WARM 0x164
+#define BATT_INFO_JEITA_HOT 0x165
+#define PARAM_ADDR_BATT_VOLTAGE 0x1a0
+#define PARAM_ADDR_BATT_CURRENT 0x1a2
+
+/* MEMIF */
+#define MEM_INTF_STS 0x410
+#define MEM_INTF_CFG 0x450
+#define MEM_INTF_CTL 0x451
+#define MEM_INTF_IMA_CFG 0x452
+#define MEM_INTF_IMA_EXP_STS 0x455
+#define MEM_INTF_IMA_HW_STS 0x456
+#define MEM_INTF_IMA_ERR_STS 0x45f
+#define MEM_INTF_IMA_BYTE_EN 0x460
+#define MEM_INTF_ADDR_LSB 0x461
+#define MEM_INTF_RD_DATA0 0x467
+#define MEM_INTF_WR_DATA0 0x463
+#define MEM_IF_DMA_STS 0x470
+#define MEM_IF_DMA_CTL 0x471
+
+/* SRAM addresses */
+#define TEMP_THRESHOLD 0x454
+#define BATT_TEMP 0x550
+#define BATT_VOLTAGE_CURRENT 0x5cc
+
+#define BATT_TEMP_LSB_MASK GENMASK(7, 0)
+#define BATT_TEMP_MSB_MASK GENMASK(2, 0)
+
+#define BATT_TEMP_JEITA_COLD 100
+#define BATT_TEMP_JEITA_COOL 50
+#define BATT_TEMP_JEITA_WARM 400
+#define BATT_TEMP_JEITA_HOT 450
+
+#define MEM_INTF_AVAIL BIT(0)
+#define MEM_INTF_CTL_BURST BIT(7)
+#define MEM_INTF_CTL_WR_EN BIT(6)
+#define RIF_MEM_ACCESS_REQ BIT(7)
+
+#define MEM_IF_TIMEOUT_MS 5000
+#define SRAM_ACCESS_RELEASE_DELAY_MS 500
+
+struct qcom_fg_chip;
+
+struct qcom_fg_ops {
+ int (*get_capacity)(struct qcom_fg_chip *chip, int *);
+ int (*get_temperature)(struct qcom_fg_chip *chip, int *);
+ int (*get_current)(struct qcom_fg_chip *chip, int *);
+ int (*get_voltage)(struct qcom_fg_chip *chip, int *);
+ int (*get_temp_threshold)(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int *);
+ int (*set_temp_threshold)(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int);
+};
+
+struct qcom_fg_chip {
+ struct device *dev;
+ unsigned int base;
+ struct regmap *regmap;
+ const struct qcom_fg_ops *ops;
+ struct notifier_block nb;
+
+ struct power_supply *batt_psy;
+ struct power_supply_battery_info *batt_info;
+ struct power_supply *chg_psy;
+ int status;
+ struct delayed_work status_changed_work;
+
+ struct completion sram_access_granted;
+ struct completion sram_access_revoked;
+ struct workqueue_struct *sram_wq;
+ struct delayed_work sram_release_access_work;
+ spinlock_t sram_request_lock;
+ spinlock_t sram_rw_lock;
+ int sram_requests;
+};
+
+/************************
+ * IO FUNCTIONS
+ * **********************/
+
+/**
+ * @brief qcom_fg_read() - Read multiple registers with regmap_bulk_read
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to read values into
+ * @param addr Address to read from
+ * @param len Number of registers (bytes) to read
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_read(struct qcom_fg_chip *chip, u8 *val, u16 addr, int len)
+{
+ if (((chip->base + addr) & 0xff00) == 0)
+ return -EINVAL;
+
+ dev_vdbg(chip->dev, "%s: Reading 0x%x bytes from 0x%x", __func__, len, addr);
+
+ return regmap_bulk_read(chip->regmap, chip->base + addr, val, len);
+}
+
+/**
+ * @brief qcom_fg_write() - Write multiple registers with regmap_bulk_write
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to write values from
+ * @param addr Address to write to
+ * @param len Number of registers (bytes) to write
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_write(struct qcom_fg_chip *chip, u8 *val, u16 addr, int len)
+{
+ bool sec_access = (addr & 0xff) > 0xd0;
+ u8 sec_addr_val = 0xa5;
+ int ret;
+
+ if (((chip->base + addr) & 0xff00) == 0)
+ return -EINVAL;
+
+ dev_vdbg(chip->dev, "%s: Writing 0x%x to 0x%x", __func__, *val, addr);
+
+ if (sec_access) {
+ ret = regmap_bulk_write(chip->regmap,
+ ((chip->base + addr) & 0xff00) | 0xd0,
+ &sec_addr_val, 1);
+ if (ret)
+ return ret;
+ }
+
+ return regmap_bulk_write(chip->regmap, chip->base + addr, val, len);
+}
+
+/**
+ * @brief qcom_fg_masked_write() - like qcom_fg_write but applies
+ * a mask first.
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to write values from
+ * @param addr Address to write to
+ * @param len Number of registers (bytes) to write
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_masked_write(struct qcom_fg_chip *chip, u16 addr, u8 mask, u8 val)
+{
+ u8 reg;
+ int ret;
+
+ ret = qcom_fg_read(chip, &reg, addr, 1);
+ if (ret)
+ return ret;
+
+ reg &= ~mask;
+ reg |= val & mask;
+
+ return qcom_fg_write(chip, &reg, addr, 1);
+}
+
+/************************
+ * SRAM FUNCTIONS
+ * **********************/
+
+/**
+ * @brief qcom_fg_sram_check_access() - Check if SRAM is accessible
+ *
+ * @param chip Pointer to chip
+ * @return bool true if accessible, false otherwise
+ */
+static bool qcom_fg_sram_check_access(struct qcom_fg_chip *chip)
+{
+ u8 mem_if_status;
+ int ret;
+
+ ret = qcom_fg_read(chip, &mem_if_status,
+ MEM_INTF_STS, 1);
+
+ if (ret || !(mem_if_status & MEM_INTF_AVAIL))
+ return false;
+
+ ret = qcom_fg_read(chip, &mem_if_status,
+ MEM_INTF_CFG, 1);
+
+ if (ret)
+ return false;
+
+ return !!(mem_if_status & RIF_MEM_ACCESS_REQ);
+}
+
+/**
+ * @brief qcom_fg_sram_request_access() - Request access to SRAM and wait for it
+ *
+ * @param chip Pointer to chip
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_request_access(struct qcom_fg_chip *chip)
+{
+ bool sram_accessible;
+ int ret;
+
+ spin_lock(&chip->sram_request_lock);
+
+ sram_accessible = qcom_fg_sram_check_access(chip);
+
+ dev_vdbg(chip->dev, "Requesting SRAM access, current state: %d, requests: %d\n",
+ sram_accessible, chip->sram_requests);
+
+ if (!sram_accessible && chip->sram_requests == 0) {
+ ret = qcom_fg_masked_write(chip, MEM_INTF_CFG,
+ RIF_MEM_ACCESS_REQ, RIF_MEM_ACCESS_REQ);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set SRAM access request bit: %d\n", ret);
+
+ spin_unlock(&chip->sram_request_lock);
+ return ret;
+ }
+ }
+
+ chip->sram_requests++;
+
+ spin_unlock(&chip->sram_request_lock);
+
+ /* Wait to get access to SRAM, and try again if interrupted */
+ do {
+ ret = wait_for_completion_interruptible_timeout(
+ &chip->sram_access_granted,
+ msecs_to_jiffies(MEM_IF_TIMEOUT_MS));
+ } while(ret == -ERESTARTSYS);
+
+ if (ret <= 0) {
+ ret = -ETIMEDOUT;
+
+ spin_lock(&chip->sram_request_lock);
+ chip->sram_requests--;
+ spin_unlock(&chip->sram_request_lock);
+ } else {
+ ret = 0;
+
+ reinit_completion(&chip->sram_access_revoked);
+ }
+
+ return ret;
+}
+
+/**
+ * @brief qcom_fg_sram_release_access() - Release access to SRAM
+ *
+ * @param chip Pointer to chip
+ * @return int 0 on success, negative errno on error
+ */
+static void qcom_fg_sram_release_access(struct qcom_fg_chip *chip)
+{
+ spin_lock(&chip->sram_request_lock);
+
+ chip->sram_requests--;
+
+ if(WARN(chip->sram_requests < 0,
+ "sram_requests=%d, cannot be negative! resetting to 0.\n",
+ chip->sram_requests))
+ chip->sram_requests = 0;
+
+ if(chip->sram_requests == 0)
+ /* Schedule access release */
+ queue_delayed_work(chip->sram_wq, &chip->sram_release_access_work,
+ msecs_to_jiffies(SRAM_ACCESS_RELEASE_DELAY_MS));
+
+ spin_unlock(&chip->sram_request_lock);
+}
+
+static void qcom_fg_sram_release_access_worker(struct work_struct *work)
+{
+ struct qcom_fg_chip *chip;
+ bool wait = false;
+ int ret;
+
+ chip = container_of(work, struct qcom_fg_chip, sram_release_access_work.work);
+
+ spin_lock(&chip->sram_request_lock);
+
+ /* Request access release if there are still no access requests */
+ if(chip->sram_requests == 0) {
+ qcom_fg_masked_write(chip, MEM_INTF_CFG, RIF_MEM_ACCESS_REQ, 0);
+ wait = true;
+ }
+
+ spin_unlock(&chip->sram_request_lock);
+
+ if(!wait)
+ return;
+
+ /* Wait for SRAM access to be released, and try again if interrupted */
+ do {
+ ret = wait_for_completion_interruptible_timeout(
+ &chip->sram_access_revoked,
+ msecs_to_jiffies(MEM_IF_TIMEOUT_MS));
+ } while(ret == -ERESTARTSYS);
+
+ reinit_completion(&chip->sram_access_granted);
+}
+
+/**
+ * @brief qcom_fg_sram_config_access() - Configure access to SRAM
+ *
+ * @param chip Pointer to chip
+ * @param write 0 for read access, 1 for write access
+ * @param burst 1 to access mutliple addresses successively
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_config_access(struct qcom_fg_chip *chip,
+ bool write, bool burst)
+{
+ u8 intf_ctl;
+ int ret;
+
+ intf_ctl = (write ? MEM_INTF_CTL_WR_EN : 0)
+ | (burst ? MEM_INTF_CTL_BURST : 0);
+
+ ret = qcom_fg_write(chip, &intf_ctl,
+ MEM_INTF_CTL, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to configure SRAM access: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_sram_read() - Read data from SRAM
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to read values into
+ * @param addr Address to read from
+ * @param len Number of bytes to read
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_read(struct qcom_fg_chip *chip,
+ u8 *val, u16 addr, int len, int offset)
+{
+ u8 *rd_data = val;
+ int ret = 0;
+
+ ret = qcom_fg_sram_request_access(chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request SRAM access: %d", ret);
+ return ret;
+ }
+
+ spin_lock(&chip->sram_rw_lock);
+
+ dev_vdbg(chip->dev,
+ "Reading address 0x%x with offset %d of length %d from SRAM",
+ addr, len, offset);
+
+ ret = qcom_fg_sram_config_access(chip, 0, (len > 4));
+ if (ret) {
+ dev_err(chip->dev, "Failed to configure SRAM access: %d", ret);
+ goto out;
+ }
+
+ while(len > 0) {
+ /* Set SRAM address register */
+ ret = qcom_fg_write(chip, (u8 *) &addr,
+ MEM_INTF_ADDR_LSB, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to set SRAM address: %d", ret);
+ goto out;
+ }
+
+ ret = qcom_fg_read(chip, rd_data,
+ MEM_INTF_RD_DATA0 + offset, len);
+
+ addr += 4;
+
+ if (ret)
+ goto out;
+
+ rd_data += 4 - offset;
+ len -= 4 - offset;
+ offset = 0;
+ }
+out:
+ spin_unlock(&chip->sram_rw_lock);
+ qcom_fg_sram_release_access(chip);
+
+ return ret;
+}
+
+/**
+ * @brief qcom_fg_sram_write() - Write data to SRAM
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to write values from
+ * @param addr Address to write to
+ * @param len Number of bytes to write
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_write(struct qcom_fg_chip *chip,
+ u8 *val, u16 addr, int len, int offset)
+{
+ u8 *wr_data = val;
+ int ret;
+
+ ret = qcom_fg_sram_request_access(chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request SRAM access: %d", ret);
+ return ret;
+ }
+
+ spin_lock(&chip->sram_rw_lock);
+
+ dev_vdbg(chip->dev,
+ "Wrtiting address 0x%x with offset %d of length %d to SRAM",
+ addr, len, offset);
+
+ ret = qcom_fg_sram_config_access(chip, 1, (len > 4));
+ if (ret) {
+ dev_err(chip->dev, "Failed to configure SRAM access: %d", ret);
+ goto out;
+ }
+
+ while(len > 0) {
+ /* Set SRAM address register */
+ ret = qcom_fg_write(chip, (u8 *) &addr,
+ MEM_INTF_ADDR_LSB, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to set SRAM address: %d", ret);
+ goto out;
+ }
+
+ ret = qcom_fg_write(chip, wr_data,
+ MEM_INTF_WR_DATA0 + offset, len);
+
+ addr += 4;
+
+ if (ret)
+ goto out;
+
+ wr_data += 4 - offset;
+ len -= 4 - offset;
+ offset = 0;
+ }
+out:
+ spin_unlock(&chip->sram_rw_lock);
+ qcom_fg_sram_release_access(chip);
+
+ return ret;
+}
+
+/*************************
+ * BATTERY STATUS
+ * ***********************/
+
+/**
+ * @brief qcom_fg_get_capacity() - Get remaining capacity of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_capacity(struct qcom_fg_chip *chip, int *val)
+{
+ u8 cap[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, cap, BATT_MONOTONIC_SOC, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read capacity: %d", ret);
+ return ret;
+ }
+
+ if (cap[0] != cap[1]) {
+ cap[0] = cap[0] < cap[1] ? cap[0] : cap[1];
+ }
+
+ *val = DIV_ROUND_CLOSEST((cap[0] - 1) * 98, 0xff - 2) + 1;
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_temperature() - Get temperature of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_temperature(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_sram_read(chip, readval, BATT_TEMP, 2, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp = readval[1] << 8 | readval[0];
+ *val = temp * 625 / 1000 - 2730;
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_current() - Get current being drawn from battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_current(struct qcom_fg_chip *chip, int *val)
+{
+ s16 temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_sram_read(chip, readval, BATT_VOLTAGE_CURRENT, 2, 3);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read current: %d", ret);
+ return ret;
+ }
+
+ temp = (s16)(readval[1] << 8 | readval[0]);
+ *val = div_s64((s64)temp * 152587, 1000);
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_voltage() - Get voltage of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_voltage(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_sram_read(chip, readval, BATT_VOLTAGE_CURRENT, 2, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read voltage: %d", ret);
+ return ret;
+ }
+
+ temp = readval[1] << 8 | readval[0];
+ *val = div_u64((u64)temp * 152587, 1000);
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_temp_threshold() - Get configured temperature thresholds
+ *
+ * @param chip Pointer to chip
+ * @param psp Power supply property of temperature limit
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_temp_threshold(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int *val)
+{
+ u8 temp;
+ int offset;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ offset = 0;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ offset = 1;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ offset = 2;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ offset = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = qcom_fg_sram_read(chip, &temp, TEMP_THRESHOLD, 1, offset);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read JEITA property %d level: %d\n", psp, ret);
+ return ret;
+ }
+
+ *val = (temp - 30) * 10;
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_set_temp_threshold() - Configure temperature thresholds
+ *
+ * @param chip Pointer to chip
+ * @param psp Power supply property of temperature limit
+ * @param val Pointer to get value from
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_set_temp_threshold(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int val)
+{
+ u8 temp;
+ int offset;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ offset = 0;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ offset = 1;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ offset = 2;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ offset = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ temp = val / 10 + 30;
+
+ ret = qcom_fg_sram_write(chip, &temp, TEMP_THRESHOLD, 1, offset);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to write JEITA property %d level: %d\n", psp, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*************************
+ * BATTERY STATUS, GEN3
+ * ***********************/
+
+/**
+ * @brief qcom_fg_gen3_get_temperature() - Get temperature of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_temperature(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, readval, PARAM_ADDR_BATT_TEMP, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read temperature: %d\n", ret);
+ return ret;
+ }
+
+ temp = ((readval[1] & BATT_TEMP_MSB_MASK) << 8) |
+ (readval[0] & BATT_TEMP_LSB_MASK);
+ temp = DIV_ROUND_CLOSEST(temp * 10, 4);
+
+ *val = temp -2730;
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_gen3_get_current() - Get current being drawn from battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_current(struct qcom_fg_chip *chip, int *val)
+{
+ s16 temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, readval, PARAM_ADDR_BATT_CURRENT, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read current: %d\n", ret);
+ return ret;
+ }
+
+ //handle rev 1 too
+ temp = (s16)(readval[1] << 8 | readval[0]);
+ *val = div_s64((s64)temp * 488281, 1000);
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_gen3_get_voltage() - Get voltage of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_voltage(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, readval, PARAM_ADDR_BATT_VOLTAGE, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read voltage: %d\n", ret);
+ return ret;
+ }
+
+ //handle rev 1 too
+ temp = readval[1] << 8 | readval[0];
+ *val = div_u64((u64)temp * 122070, 1000);
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_gen3_get_temp_threshold() - Get configured temperature thresholds
+ *
+ * @param chip Pointer to chip
+ * @param psp Power supply property of temperature limit
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_temp_threshold(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int *val)
+{
+ u8 temp;
+ u16 reg;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ reg = BATT_INFO_JEITA_COLD;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ reg = BATT_INFO_JEITA_HOT;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ reg = BATT_INFO_JEITA_COOL;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ reg = BATT_INFO_JEITA_WARM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = qcom_fg_read(chip, &temp, reg, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read JEITA property %d level: %d\n", psp, ret);
+ return ret;
+ }
+
+ /* Resolution is 0.5C. Base is -30C. */
+ *val = (((5 * temp) / 10) - 30) * 10;
+ return 0;
+}
+
+/************************
+ * BATTERY POWER SUPPLY
+ * **********************/
+
+/* Pre-Gen3 fuel gauge. PMI8996 and older */
+static const struct qcom_fg_ops ops_fg = {
+ .get_capacity = qcom_fg_get_capacity,
+ .get_temperature = qcom_fg_get_temperature,
+ .get_current = qcom_fg_get_current,
+ .get_voltage = qcom_fg_get_voltage,
+ .get_temp_threshold = qcom_fg_get_temp_threshold,
+ .set_temp_threshold = qcom_fg_set_temp_threshold,
+};
+
+/* Gen3 fuel gauge. PMI8998 and newer */
+static const struct qcom_fg_ops ops_fg_gen3 = {
+ .get_capacity = qcom_fg_get_capacity,
+ .get_temperature = qcom_fg_gen3_get_temperature,
+ .get_current = qcom_fg_gen3_get_current,
+ .get_voltage = qcom_fg_gen3_get_voltage,
+ .get_temp_threshold = qcom_fg_gen3_get_temp_threshold,
+};
+
+static enum power_supply_property qcom_fg_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_MIN,
+ POWER_SUPPLY_PROP_TEMP_MAX,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+};
+
+static int qcom_fg_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct qcom_fg_chip *chip = power_supply_get_drvdata(psy);
+ int temp, ret = 0;
+
+ dev_dbg(chip->dev, "Getting property: %d", psp);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ /* Get status from charger if available */
+ if (chip->chg_psy &&
+ chip->status != POWER_SUPPLY_STATUS_UNKNOWN) {
+ val->intval = chip->status;
+ break;
+ } else {
+ /*
+ * Fall back to capacity and current-based
+ * status checking
+ */
+ ret = chip->ops->get_capacity(chip, &temp);
+ if (ret) {
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+ }
+ if (temp == 100) {
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ }
+
+ ret = chip->ops->get_current(chip, &temp);
+ if (ret) {
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+ }
+ if (temp < 0)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (temp > 0)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = chip->ops->get_capacity(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = chip->ops->get_current(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = chip->ops->get_voltage(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = chip->batt_info->voltage_min_design_uv;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = chip->batt_info->voltage_max_design_uv;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = chip->batt_info->charge_full_design_uah;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = chip->ops->get_temperature(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ ret = chip->ops->get_temp_threshold(chip, psp, &val->intval);
+ break;
+ default:
+ dev_err(chip->dev, "invalid property: %d\n", psp);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct power_supply_desc batt_psy_desc = {
+ .name = "qcom-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = qcom_fg_props,
+ .num_properties = ARRAY_SIZE(qcom_fg_props),
+ .get_property = qcom_fg_get_property,
+};
+
+/********************
+ * INIT FUNCTIONS
+ * ******************/
+
+static int qcom_fg_iacs_clear_sequence(struct qcom_fg_chip *chip)
+{
+ u8 temp;
+ int ret;
+
+ /* clear the error */
+ ret = qcom_fg_masked_write(chip, MEM_INTF_IMA_CFG, BIT(2), BIT(2));
+ if (ret) {
+ dev_err(chip->dev, "Failed to write IMA_CFG: %d\n", ret);
+ return ret;
+ }
+
+ temp = 0x4;
+ ret = qcom_fg_write(chip, &temp, MEM_INTF_ADDR_LSB + 1, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write MEM_INTF_ADDR_MSB: %d\n", ret);
+ return ret;
+ }
+
+ temp = 0x0;
+ ret = qcom_fg_write(chip, &temp, MEM_INTF_WR_DATA0 + 3, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write WR_DATA3: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_read(chip, &temp, MEM_INTF_RD_DATA0 + 3, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write RD_DATA3: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_masked_write(chip, MEM_INTF_IMA_CFG, BIT(2), 0);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write IMA_CFG: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int qcom_fg_clear_ima(struct qcom_fg_chip *chip,
+ bool check_hw_sts)
+{
+ u8 err_sts, exp_sts, hw_sts;
+ bool run_err_clr_seq = false;
+ int ret;
+
+ ret = qcom_fg_read(chip, &err_sts,
+ MEM_INTF_IMA_ERR_STS, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read IMA_ERR_STS: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_read(chip, &exp_sts,
+ MEM_INTF_IMA_EXP_STS, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read IMA_EXP_STS: %d\n", ret);
+ return ret;
+ }
+
+ if (check_hw_sts) {
+ ret = qcom_fg_read(chip, &hw_sts,
+ MEM_INTF_IMA_HW_STS, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read IMA_HW_STS: %d\n", ret);
+ return ret;
+ }
+ /*
+ * Lower nibble should be equal to upper nibble before SRAM
+ * transactions begins from SW side.
+ */
+ if ((hw_sts & 0x0f) != hw_sts >> 4) {
+ dev_dbg(chip->dev, "IMA HW not in correct state, hw_sts=%x\n",
+ hw_sts);
+ run_err_clr_seq = true;
+ }
+ }
+
+ if (exp_sts & (BIT(0) | BIT(1) | BIT(3) |
+ BIT(4) | BIT(5) | BIT(6) |
+ BIT(7))) {
+ dev_dbg(chip->dev, "IMA exception bit set, exp_sts=%x\n", exp_sts);
+ run_err_clr_seq = true;
+ }
+
+ if (run_err_clr_seq) {
+ ret = qcom_fg_iacs_clear_sequence(chip);
+ if (!ret)
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+irqreturn_t qcom_fg_handle_soc_delta(int irq, void *data)
+{
+ struct qcom_fg_chip *chip = data;
+
+ /* Signal change in state of charge */
+ power_supply_changed(chip->batt_psy);
+ dev_dbg(chip->dev, "SOC changed");
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t qcom_fg_handle_mem_avail(int irq, void *data)
+{
+ struct qcom_fg_chip *chip = data;
+
+ if (qcom_fg_sram_check_access(chip)) {
+ complete_all(&chip->sram_access_granted);
+ dev_dbg(chip->dev, "SRAM access granted");
+ } else {
+ complete_all(&chip->sram_access_revoked);
+ dev_dbg(chip->dev, "SRAM access revoked");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void qcom_fg_status_changed_worker(struct work_struct *work)
+{
+ struct qcom_fg_chip *chip = container_of(work, struct qcom_fg_chip,
+ status_changed_work.work);
+
+ power_supply_changed(chip->batt_psy);
+}
+
+static int qcom_fg_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct qcom_fg_chip *chip = container_of(nb, struct qcom_fg_chip, nb);
+ struct power_supply *psy = v;
+ union power_supply_propval propval;
+ int ret;
+
+ if (psy == chip->chg_psy) {
+ ret = power_supply_get_property(psy,
+ POWER_SUPPLY_PROP_STATUS, &propval);
+ if (ret)
+ chip->status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ chip->status = propval.intval;
+
+ power_supply_changed(chip->batt_psy);
+
+ if (chip->status == POWER_SUPPLY_STATUS_UNKNOWN) {
+ /*
+ * REVISIT: Find better solution or remove current-based
+ * status checking once checking is properly implemented
+ * in charger drivers
+
+ * Sometimes it take a while for current to stabilize,
+ * so signal property change again later to make sure
+ * current-based status is properly detected.
+ */
+ cancel_delayed_work_sync(&chip->status_changed_work);
+ schedule_delayed_work(&chip->status_changed_work,
+ msecs_to_jiffies(1000));
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static int qcom_fg_probe(struct platform_device *pdev)
+{
+ struct power_supply_config supply_config = {};
+ struct qcom_fg_chip *chip;
+ const __be32 *prop_addr;
+ int irq;
+ u8 dma_status;
+ bool error_present;
+ int ret;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->dev = &pdev->dev;
+ chip->ops = of_device_get_match_data(&pdev->dev);
+
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(chip->dev, "Failed to locate the regmap\n");
+ return -ENODEV;
+ }
+
+ /* Get base address */
+ prop_addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
+ if (!prop_addr) {
+ dev_err(chip->dev, "Failed to read SOC base address from dt\n");
+ return -EINVAL;
+ }
+ chip->base = be32_to_cpu(*prop_addr);
+
+ /*
+ * Change the FG_MEM_INT interrupt to track IACS_READY
+ * condition instead of end-of-transaction. This makes sure
+ * that the next transaction starts only after the hw is ready.
+ * IACS_INTR_SRC_SLCT is BIT(3)
+ */
+ ret = qcom_fg_masked_write(chip,
+ MEM_INTF_IMA_CFG, BIT(3), BIT(3));
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to configure interrupt sourete: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_clear_ima(chip, true);
+ if (ret && ret != -EAGAIN) {
+ dev_err(chip->dev, "Failed to clear IMA exception: %d\n", ret);
+ return ret;
+ }
+
+ /* Check and clear DMA errors */
+ ret = qcom_fg_read(chip, &dma_status, MEM_IF_DMA_STS, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read dma_status: %d\n", ret);
+ return ret;
+ }
+
+ error_present = dma_status & (BIT(1) | BIT(2));
+ ret = qcom_fg_masked_write(chip, MEM_IF_DMA_CTL, BIT(0),
+ error_present ? BIT(0) : 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to write dma_ctl: %d\n", ret);
+ return ret;
+ }
+
+ supply_config.drv_data = chip;
+ supply_config.of_node = pdev->dev.of_node;
+
+ chip->batt_psy = devm_power_supply_register(chip->dev,
+ &batt_psy_desc, &supply_config);
+ if (IS_ERR(chip->batt_psy)) {
+ if (PTR_ERR(chip->batt_psy) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to register battery\n");
+ return PTR_ERR(chip->batt_psy);
+ }
+
+ platform_set_drvdata(pdev, chip);
+
+ ret = power_supply_get_battery_info(chip->batt_psy, &chip->batt_info);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to get battery info: %d\n", ret);
+ return ret;
+ }
+
+ /* Initialize SRAM */
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,pmi8994-fg")) {
+ irq = of_irq_get_byname(pdev->dev.of_node, "mem-avail");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq mem-avail byname: %d\n",
+ irq);
+ return irq;
+ }
+
+ init_completion(&chip->sram_access_granted);
+ init_completion(&chip->sram_access_revoked);
+
+ chip->sram_wq = create_singlethread_workqueue("qcom_fg");
+ INIT_DELAYED_WORK(&chip->sram_release_access_work,
+ qcom_fg_sram_release_access_worker);
+
+ ret = devm_request_threaded_irq(chip->dev, irq, NULL,
+ qcom_fg_handle_mem_avail,
+ IRQF_ONESHOT, "mem-avail", chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request mem-avail IRQ: %d\n", ret);
+ return ret;
+ }
+
+ spin_lock_init(&chip->sram_request_lock);
+ spin_lock_init(&chip->sram_rw_lock);
+ chip->sram_requests = 0;
+ }
+
+ /* Set default temperature thresholds */
+ if (chip->ops->set_temp_threshold) {
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_MIN,
+ BATT_TEMP_JEITA_COLD);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set cold threshold: %d\n", ret);
+ return ret;
+ }
+
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_MAX,
+ BATT_TEMP_JEITA_WARM);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set warm threshold: %d\n", ret);
+ return ret;
+ }
+
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+ BATT_TEMP_JEITA_COOL);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set cool threshold: %d\n", ret);
+ return ret;
+ }
+
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+ BATT_TEMP_JEITA_HOT);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set hot threshold: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* Get soc-delta IRQ */
+ irq = of_irq_get_byname(pdev->dev.of_node, "soc-delta");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq soc-delta byname: %d\n",
+ irq);
+ return irq;
+ }
+
+ ret = devm_request_threaded_irq(chip->dev, irq, NULL,
+ qcom_fg_handle_soc_delta,
+ IRQF_ONESHOT, "soc-delta", chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request soc-delta IRQ: %d\n", ret);
+ return ret;
+ }
+
+ /* Optional: Get charger power supply for status checking */
+ chip->chg_psy = power_supply_get_by_phandle(chip->dev->of_node,
+ "power-supplies");
+ if (IS_ERR(chip->chg_psy)) {
+ ret = PTR_ERR(chip->chg_psy);
+ dev_warn(chip->dev, "Failed to get charger supply: %d\n", ret);
+ chip->chg_psy = NULL;
+ }
+
+ if (chip->chg_psy) {
+ INIT_DELAYED_WORK(&chip->status_changed_work,
+ qcom_fg_status_changed_worker);
+
+ chip->nb.notifier_call = qcom_fg_notifier_call;
+ ret = power_supply_reg_notifier(&chip->nb);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to register notifier: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int qcom_fg_remove(struct platform_device *pdev)
+{
+ struct qcom_fg_chip *chip = platform_get_drvdata(pdev);
+
+ power_supply_put_battery_info(chip->chg_psy, chip->batt_info);
+
+ if(chip->sram_wq)
+ destroy_workqueue(chip->sram_wq);
+
+ return 0;
+}
+
+static const struct of_device_id fg_match_id_table[] = {
+ { .compatible = "qcom,pmi8994-fg", .data = &ops_fg },
+ { .compatible = "qcom,pmi8998-fg", .data = &ops_fg_gen3 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fg_match_id_table);
+
+static struct platform_driver qcom_fg_driver = {
+ .probe = qcom_fg_probe,
+ .remove = qcom_fg_remove,
+ .driver = {
+ .name = "qcom-fg",
+ .of_match_table = fg_match_id_table,
+ },
+};
+
+module_platform_driver(qcom_fg_driver);
+
+MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
+MODULE_AUTHOR("Joel Selvaraj <jo@jsfamily.in>");
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm PMIC Fuel Gauge Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/yoga-c630-ec.c b/drivers/power/supply/yoga-c630-ec.c
new file mode 100644
index 00000000000..f070e56dc87
--- /dev/null
+++ b/drivers/power/supply/yoga-c630-ec.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022-2023 Linaro Ltd.
+ */
+#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+
+#define LENOVO_EC_CACHE_TIME (10 * HZ)
+
+#define LENOVO_EC_RESPONSE_REG 0x1
+#define LENOVO_EC_REQUEST_REG 0x2
+
+#define LENOVO_EC_READ_REG 0xb0
+#define LENOVO_EC_QUERY_USB_EVENT 0x8
+#define LENOVO_EC_USB_EVENT_MUX GENMASK(1, 0)
+#define LENOVO_EC_USB_EVENT_ORIENTATION BIT(7)
+#define LENOVO_EC_ADPT_STATUS 0xa3
+#define LENOVO_EC_ADPT_PRESENT BIT(7)
+#define LENOVO_EC_BAT_STATUS 0xc1
+#define LENOVO_EC_BAT_VOLTAGE 0xc6
+#define LENOVO_EC_BAT_CURRENT 0xd2
+#define LENOVO_EC_BAT_PRESENT 0xda
+#define LENOVO_EC_BAT_ATTRIBUTES 0xc0
+#define LENOVO_EC_BAT_ATTR_UNIT_IS_MA BIT(1)
+#define LENOVO_EC_BAT_REMAIN_CAPACITY 0xc2
+#define LENOVO_EC_BAT_DESIGN_VOLTAGE 0xc8
+#define LENOVO_EC_BAT_DESIGN_CAPACITY 0xca
+#define LENOVO_EC_BAT_FULL_CAPACITY 0xcc
+#define LENOVO_EC_BAT_FULL_FACTORY 0xd6
+#define LENOVO_EC_BAT_FULL_REGISTER 0xdb
+
+#define LENOVO_EC_REQUEST_NEXT_EVENT 0x84
+#define LENOVO_EC_EVENT_USB 0x20
+#define LENOVO_EC_EVENT_UCSI 0x21
+#define LENOVO_EC_EVENT_HPD 0x22
+#define LENOVO_EC_EVENT_BAT_STATUS 0x24
+#define LENOVO_EC_EVENT_BAT_INFO 0x25
+#define LENOVO_EC_EVENT_BAT_ADPT_STATUS 0x37
+
+struct yoga_c630_ec {
+ struct i2c_client *client;
+ struct mutex lock;
+
+ struct power_supply *adp_psy;
+ struct power_supply *bat_psy;
+
+ unsigned long last_status_update;
+
+ bool adapter_online;
+
+ bool unit_ma;
+
+ unsigned int scale;
+
+ bool bat_present;
+ unsigned int bat_status;
+
+ unsigned int design_capacity;
+ unsigned int design_voltage;
+ unsigned int full_charge_capacity;
+
+ unsigned int capacity_now;
+ unsigned int voltage_now;
+
+ int rate_now;
+};
+
+static int yoga_c630_ec_request(struct yoga_c630_ec *ec, u8 *req, size_t req_len,
+ u8 *resp, size_t resp_len)
+{
+ int ret;
+
+ WARN_ON(!mutex_is_locked(&ec->lock));
+
+ ret = i2c_smbus_write_i2c_block_data(ec->client, LENOVO_EC_REQUEST_REG,
+ req_len, req);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_read_i2c_block_data(ec->client, LENOVO_EC_RESPONSE_REG,
+ resp_len, resp);
+}
+
+static int yoga_c630_ec_read8(struct yoga_c630_ec *ec, u8 addr)
+{
+ int ret;
+ u8 val;
+
+ ret = yoga_c630_ec_request(ec, (u8[]) { LENOVO_EC_READ_REG, addr }, 2,
+ &val, 1);
+ if (ret < 0)
+ return ret;
+
+ return val;
+}
+
+static int yoga_c630_ec_read16(struct yoga_c630_ec *ec, u8 addr)
+{
+ int ret;
+ u8 msb;
+ u8 lsb;
+
+ ret = yoga_c630_ec_request(ec, (u8[]) { LENOVO_EC_READ_REG, addr }, 2,
+ &lsb, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = yoga_c630_ec_request(ec, (u8[]) { LENOVO_EC_READ_REG, addr + 1 }, 2,
+ &msb, 1);
+ if (ret < 0)
+ return ret;
+
+ return msb << 8 | lsb;
+}
+
+static void yoga_c630_ec_update_bat_info(struct yoga_c630_ec *ec)
+{
+ int val;
+
+ mutex_lock(&ec->lock);
+
+ val = yoga_c630_ec_read8(ec, LENOVO_EC_BAT_PRESENT);
+ if (val < 0)
+ goto out_unlock;
+ ec->bat_present = !!(val & BIT(0));
+ if (!ec->bat_present)
+ goto out_unlock;
+
+ val = yoga_c630_ec_read8(ec, LENOVO_EC_BAT_ATTRIBUTES);
+ if (val < 0)
+ goto out_unlock;
+ ec->unit_ma = val & LENOVO_EC_BAT_ATTR_UNIT_IS_MA;
+ if (!ec->unit_ma)
+ ec->scale = 1000;
+ else
+ ec->scale = 1;
+
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_DESIGN_CAPACITY);
+ if (val < 0)
+ goto out_unlock;
+ ec->design_capacity = val * ec->scale;
+
+ msleep(50);
+
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_DESIGN_VOLTAGE);
+ if (val < 0)
+ goto out_unlock;
+ ec->design_voltage = val;
+
+ msleep(50);
+
+ val = yoga_c630_ec_read8(ec, LENOVO_EC_BAT_FULL_REGISTER);
+ if (val < 0)
+ goto out_unlock;
+ if (val & BIT(0))
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_FULL_FACTORY);
+ else
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_FULL_CAPACITY);
+ if (val < 0)
+ goto out_unlock;
+ ec->full_charge_capacity = val * ec->scale;
+
+out_unlock:
+ mutex_unlock(&ec->lock);
+}
+
+static void yoga_c630_ec_maybe_update_bat_status(struct yoga_c630_ec *ec)
+{
+ int val = 0;
+
+ mutex_lock(&ec->lock);
+
+ if (time_before(jiffies, ec->last_status_update + LENOVO_EC_CACHE_TIME))
+ goto out_unlock;
+
+ val = yoga_c630_ec_read8(ec, LENOVO_EC_BAT_STATUS);
+ if (val < 0)
+ goto out_unlock;
+ ec->bat_status = val;
+
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_REMAIN_CAPACITY);
+ if (val < 0)
+ goto out_unlock;
+ ec->capacity_now = val * ec->scale;
+
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_VOLTAGE);
+ if (val < 0)
+ goto out_unlock;
+ ec->voltage_now = val;
+
+ val = yoga_c630_ec_read16(ec, LENOVO_EC_BAT_CURRENT);
+ if (val < 0)
+ goto out_unlock;
+ ec->rate_now = sign_extend32(val, 15) * ec->scale;
+
+ if (ec->unit_ma)
+ ec->rate_now = ec->rate_now * ec->voltage_now / 1000;
+
+ ec->last_status_update = jiffies;
+
+out_unlock:
+ mutex_unlock(&ec->lock);
+}
+
+static int yoga_c630_ec_update_adapter_status(struct yoga_c630_ec *ec)
+{
+ int val;
+
+ mutex_lock(&ec->lock);
+
+ val = yoga_c630_ec_read8(ec, LENOVO_EC_ADPT_STATUS);
+ if (val > 0)
+ ec->adapter_online = FIELD_GET(LENOVO_EC_ADPT_PRESENT, val);
+
+ mutex_unlock(&ec->lock);
+
+ return val;
+}
+
+static bool yoga_c630_ec_is_charged(struct yoga_c630_ec *ec)
+{
+ if (ec->bat_status != 0)
+ return false;
+
+ if (ec->full_charge_capacity == ec->capacity_now)
+ return true;
+
+ if (ec->design_capacity == ec->capacity_now)
+ return true;
+
+ return false;
+}
+
+static int yoga_c630_ec_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct yoga_c630_ec *ec = power_supply_get_drvdata(psy);
+ int rc = 0;
+
+ if (ec->bat_present)
+ yoga_c630_ec_maybe_update_bat_status(ec);
+ else if (psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (ec->bat_status & BIT(0))
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec->bat_status & BIT(1))
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (yoga_c630_ec_is_charged(ec))
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = ec->bat_present;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = ec->design_voltage;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = ec->design_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = ec->full_charge_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = ec->capacity_now;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = ec->rate_now;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = ec->voltage_now;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = "PABAS0241231";
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = "Compal";
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static enum power_supply_property yoga_c630_ec_bat_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static const struct power_supply_desc yoga_c630_ec_bat_psy_desc = {
+ .name = "yoga-c630-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = yoga_c630_ec_bat_properties,
+ .num_properties = ARRAY_SIZE(yoga_c630_ec_bat_properties),
+ .get_property = yoga_c630_ec_bat_get_property,
+};
+
+static int yoga_c630_ec_adpt_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct yoga_c630_ec *ec = power_supply_get_drvdata(psy);
+ int rc = 0;
+
+ yoga_c630_ec_update_adapter_status(ec);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = ec->adapter_online;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static enum power_supply_property yoga_c630_ec_adpt_properties[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static const struct power_supply_desc yoga_c630_ec_adpt_psy_desc = {
+ .name = "yoga-c630-adapter",
+ .type = POWER_SUPPLY_TYPE_USB_TYPE_C,
+ .properties = yoga_c630_ec_adpt_properties,
+ .num_properties = ARRAY_SIZE(yoga_c630_ec_adpt_properties),
+ .get_property = yoga_c630_ec_adpt_get_property,
+};
+
+static int yoga_c630_ec_query_usb_event(struct yoga_c630_ec *ec)
+{
+ struct device *dev = &ec->client->dev;
+ int event;
+
+ mutex_lock(&ec->lock);
+ event = yoga_c630_ec_read8(ec, LENOVO_EC_QUERY_USB_EVENT);
+ mutex_unlock(&ec->lock);
+ if (event < 0) {
+ dev_err(dev, "unable to query USB event\n");
+ return event;
+ }
+
+ /* FIXME: handle the returned event to set the Type-C properties */
+
+ return 0;
+}
+
+static irqreturn_t yoga_c630_ec_intr(int irq, void *data)
+{
+ struct yoga_c630_ec *ec = data;
+ u8 event;
+ int ret;
+
+ mutex_lock(&ec->lock);
+ ret = yoga_c630_ec_request(ec, (u8[]){ LENOVO_EC_REQUEST_NEXT_EVENT }, 1,
+ &event, 1);
+ mutex_unlock(&ec->lock);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ switch (event) {
+ case LENOVO_EC_EVENT_USB:
+ case LENOVO_EC_EVENT_HPD:
+ yoga_c630_ec_query_usb_event(ec);
+ break;
+ case LENOVO_EC_EVENT_BAT_INFO:
+ yoga_c630_ec_update_bat_info(ec);
+ break;
+ case LENOVO_EC_EVENT_BAT_ADPT_STATUS:
+ power_supply_changed(ec->adp_psy);
+ fallthrough;
+ case LENOVO_EC_EVENT_BAT_STATUS:
+ power_supply_changed(ec->bat_psy);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int yoga_c630_ec_probe(struct i2c_client *client)
+{
+ struct power_supply_config adp_cfg = {};
+ struct power_supply_config bat_cfg = {};
+ struct yoga_c630_ec *ec;
+ struct device *dev = &client->dev;
+ int ret;
+
+ ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
+ if (!ec)
+ return -ENOMEM;
+
+ mutex_init(&ec->lock);
+ ec->client = client;
+
+ adp_cfg.drv_data = ec;
+ adp_cfg.of_node = client->dev.of_node;
+ ec->adp_psy = devm_power_supply_register(dev, &yoga_c630_ec_adpt_psy_desc, &adp_cfg);
+ if (IS_ERR(ec->adp_psy)) {
+ dev_err(dev, "failed to register AC adapter supply\n");
+ return PTR_ERR(ec->adp_psy);
+ }
+
+ bat_cfg.drv_data = ec;
+ bat_cfg.of_node = client->dev.of_node;
+ ec->bat_psy = devm_power_supply_register(dev, &yoga_c630_ec_bat_psy_desc, &bat_cfg);
+ if (IS_ERR(ec->bat_psy)) {
+ dev_err(dev, "failed to register battery supply\n");
+ return PTR_ERR(ec->bat_psy);
+ }
+
+ ret = devm_request_threaded_irq(dev, client->irq,
+ NULL, yoga_c630_ec_intr,
+ IRQF_ONESHOT, "yoga_c630_ec", ec);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "unable to request irq\n");
+
+ yoga_c630_ec_update_bat_info(ec);
+
+ return 0;
+}
+
+static const struct of_device_id yoga_c630_ec_of_match[] = {
+ { .compatible = "lenovo,yoga-c630-ec" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, yoga_c630_ec_of_match);
+
+static const struct i2c_device_id yoga_c630_ec_i2c_id_table[] = {
+ { "yoga-c630-ec", },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, yoga_c630_ec_i2c_id_table);
+
+static struct i2c_driver yoga_c630_ec_i2c_driver = {
+ .driver = {
+ .name = "yoga-c630-ec",
+ .of_match_table = yoga_c630_ec_of_match,
+ },
+ .probe = yoga_c630_ec_probe,
+ .id_table = yoga_c630_ec_i2c_id_table,
+};
+module_i2c_driver(yoga_c630_ec_i2c_driver);
+
+MODULE_DESCRIPTION("Lenovo Yoga C630 EC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 550145f8272..ef5af5fc3e4 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1297,6 +1297,14 @@ config REGULATOR_RTQ2208
and two ldos. It features wide output voltage range from 0.4V to 2.05V
and the capability to configure the corresponding power stages.
+config REGULATOR_S2DOS05
+ tristate "SLSI S2DOS05 regulator"
+ depends on I2C
+ help
+ This driver provides support for the voltage regulators of the S2DOS05.
+ The S2DOS05 is a companion power management IC for the smart phones.
+ The S2DOS05 handles LDO and BUCK control
+
config REGULATOR_S2MPA01
tristate "Samsung S2MPA01 voltage regulator"
depends on MFD_SEC_CORE || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 46fb569e6be..924350885a9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -151,6 +151,7 @@ obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o
obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o
obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o
obj-$(CONFIG_REGULATOR_RTQ2208) += rtq2208-regulator.o
+obj-$(CONFIG_REGULATOR_S2DOS05) += s2dos05.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
diff --git a/drivers/regulator/s2dos05.c b/drivers/regulator/s2dos05.c
new file mode 100644
index 00000000000..05e1caae1e5
--- /dev/null
+++ b/drivers/regulator/s2dos05.c
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * s2dos05.c - Regulator driver for the Samsung s2dos05
+ *
+ * Copyright (C) 2016 Samsung Electronics
+ * Copyright (C) 2023 Dzmitry Sankouski <dsankouski@gmail.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/of_gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/s2dos05.h>
+#include <linux/i2c.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/debugfs.h>
+
+struct s2dos05_data {
+ struct s2dos05_dev *iodev;
+ int num_regulators;
+ struct regulator_dev *rdev[S2DOS05_REGULATOR_MAX];
+ int opmode[S2DOS05_REGULATOR_MAX];
+};
+
+int s2dos05_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
+{
+ struct s2dos05_dev *s2dos05 = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&s2dos05->i2c_lock);
+ ret = i2c_smbus_read_byte_data(i2c, reg);
+ mutex_unlock(&s2dos05->i2c_lock);
+ if (ret < 0) {
+ pr_info("%s:%s reg(0x%x), ret(%d)\n",
+ MFD_DEV_NAME, __func__, reg, ret);
+ return ret;
+ }
+
+ ret &= 0xff;
+ *dest = ret;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s2dos05_read_reg);
+
+int s2dos05_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
+{
+ struct s2dos05_dev *s2dos05 = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&s2dos05->i2c_lock);
+ ret = i2c_smbus_write_byte_data(i2c, reg, value);
+ mutex_unlock(&s2dos05->i2c_lock);
+ if (ret < 0)
+ pr_info("%s:%s reg(0x%x), ret(%d)\n",
+ MFD_DEV_NAME, __func__, reg, ret);
+
+ return ret;
+}
+
+int s2dos05_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
+{
+ struct s2dos05_dev *s2dos05 = i2c_get_clientdata(i2c);
+ int ret;
+ u8 old_val, new_val;
+
+ mutex_lock(&s2dos05->i2c_lock);
+ ret = i2c_smbus_read_byte_data(i2c, reg);
+ if (ret >= 0) {
+ old_val = ret & 0xff;
+ new_val = (val & mask) | (old_val & (~mask));
+ ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
+ }
+ mutex_unlock(&s2dos05->i2c_lock);
+ return ret;
+}
+
+int s2dos05_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
+{
+ struct s2dos05_dev *s2dos05 = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&s2dos05->i2c_lock);
+ ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
+ mutex_unlock(&s2dos05->i2c_lock);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int s2dos05_read_word(struct i2c_client *i2c, u8 reg)
+{
+ struct s2dos05_dev *s2dos05 = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&s2dos05->i2c_lock);
+ ret = i2c_smbus_read_word_data(i2c, reg);
+ mutex_unlock(&s2dos05->i2c_lock);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+int s2dos05_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
+{
+ struct s2dos05_dev *s2dos05 = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&s2dos05->i2c_lock);
+ ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
+ mutex_unlock(&s2dos05->i2c_lock);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int s2dos05_regdump_show(struct seq_file *s, void *unused)
+{
+ struct s2dos05_dev *s2dos05_dev = s->private;
+ u8 i, val = 0;
+
+ for (i = S2DOS05_REG_STAT; i <= S2DOS05_REG_IRQ; i++) {
+ s2dos05_read_reg(s2dos05_dev->i2c, i, &val);
+ seq_printf(s, "0x%x: 0x%x\n", i, val);
+ }
+
+ return 0;
+}
+
+static int s2dos05_regdump_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s2dos05_regdump_show, inode->i_private);
+}
+
+static const struct file_operations s2dos05_regdump_operations = {
+ .open = s2dos05_regdump_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void s2dos05_debugfs_init(struct s2dos05_dev *s2dos05)
+{
+ debugfs_create_file("s2dos05_regdump", 0440,
+ NULL, s2dos05, &s2dos05_regdump_operations);
+}
+#endif
+
+static int s2m_enable(struct regulator_dev *rdev)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+
+ return s2dos05_update_reg(i2c, rdev->desc->enable_reg,
+ info->opmode[rdev_get_id(rdev)],
+ rdev->desc->enable_mask);
+}
+
+static int s2m_disable_regmap(struct regulator_dev *rdev)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+ u8 val;
+
+ if (rdev->desc->enable_is_inverted)
+ val = rdev->desc->enable_mask;
+ else
+ val = 0;
+
+ return s2dos05_update_reg(i2c, rdev->desc->enable_reg,
+ val, rdev->desc->enable_mask);
+}
+
+static int s2m_is_enabled_regmap(struct regulator_dev *rdev)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+ int ret;
+ u8 val;
+
+ ret = s2dos05_read_reg(i2c, rdev->desc->enable_reg, &val);
+ if (ret < 0)
+ return ret;
+
+ if (rdev->desc->enable_is_inverted)
+ return (val & rdev->desc->enable_mask) == 0;
+ else
+ return (val & rdev->desc->enable_mask) != 0;
+}
+
+static int s2m_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+ int ret;
+ u8 val;
+
+ ret = s2dos05_read_reg(i2c, rdev->desc->vsel_reg, &val);
+ if (ret < 0)
+ return ret;
+
+ val &= rdev->desc->vsel_mask;
+
+ return val;
+}
+
+static int s2m_set_voltage_sel_regmap(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+ int ret;
+
+ ret = s2dos05_update_reg(i2c, rdev->desc->vsel_reg,
+ sel, rdev->desc->vsel_mask);
+ if (ret < 0)
+ goto out;
+
+ if (rdev->desc->apply_bit)
+ ret = s2dos05_update_reg(i2c, rdev->desc->apply_reg,
+ rdev->desc->apply_bit,
+ rdev->desc->apply_bit);
+ return ret;
+out:
+ pr_warn("%s: failed to set voltage_sel_regmap\n", rdev->desc->name);
+ return ret;
+}
+
+static int s2m_set_voltage_sel_regmap_buck(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+ int ret;
+
+ ret = s2dos05_write_reg(i2c, rdev->desc->vsel_reg, sel);
+ if (ret < 0)
+ goto out;
+
+ if (rdev->desc->apply_bit)
+ ret = s2dos05_update_reg(i2c, rdev->desc->apply_reg,
+ rdev->desc->apply_bit,
+ rdev->desc->apply_bit);
+ return ret;
+out:
+ pr_warn("%s: failed to set voltage_sel_regmap\n", rdev->desc->name);
+ return ret;
+}
+
+static int s2m_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ int old_volt, new_volt;
+
+ /* sanity check */
+ if (!rdev->desc->ops->list_voltage)
+ return -EINVAL;
+
+ old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
+ new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
+
+ if (old_selector < new_selector)
+ return DIV_ROUND_UP(new_volt - old_volt, S2DOS05_RAMP_DELAY);
+
+ return 0;
+}
+
+static int s2m_set_active_discharge(struct regulator_dev *rdev,
+ bool enable)
+{
+ struct s2dos05_data *info = rdev_get_drvdata(rdev);
+ struct i2c_client *i2c = info->iodev->i2c;
+ int ret;
+ u8 val;
+
+ if (enable)
+ val = rdev->desc->active_discharge_on;
+ else
+ val = rdev->desc->active_discharge_off;
+
+ ret = s2dos05_update_reg(i2c, rdev->desc->active_discharge_reg,
+ val, rdev->desc->active_discharge_mask);
+ return ret;
+}
+
+static const struct regulator_ops s2dos05_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = s2m_is_enabled_regmap,
+ .enable = s2m_enable,
+ .disable = s2m_disable_regmap,
+ .get_voltage_sel = s2m_get_voltage_sel_regmap,
+ .set_voltage_sel = s2m_set_voltage_sel_regmap,
+ .set_voltage_time_sel = s2m_set_voltage_time_sel,
+ .set_active_discharge = s2m_set_active_discharge,
+};
+
+static const struct regulator_ops s2dos05_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .is_enabled = s2m_is_enabled_regmap,
+ .enable = s2m_enable,
+ .disable = s2m_disable_regmap,
+ .get_voltage_sel = s2m_get_voltage_sel_regmap,
+ .set_voltage_sel = s2m_set_voltage_sel_regmap_buck,
+ .set_voltage_time_sel = s2m_set_voltage_time_sel,
+ .set_active_discharge = s2m_set_active_discharge,
+};
+
+#define _BUCK(macro) S2DOS05_BUCK##macro
+#define _buck_ops(num) s2dos05_buck_ops##num
+
+#define _LDO(macro) S2DOS05_LDO##macro
+#define _REG(ctrl) S2DOS05_REG##ctrl
+#define _ldo_ops(num) s2dos05_ldo_ops##num
+#define _MASK(macro) S2DOS05_ENABLE_MASK##macro
+#define _TIME(macro) S2DOS05_ENABLE_TIME##macro
+
+#define BUCK_DESC(_name, _id, _ops, m, s, v, e, em, t, a) { \
+ .name = _name, \
+ .id = _id, \
+ .ops = _ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = m, \
+ .uV_step = s, \
+ .n_voltages = S2DOS05_BUCK_N_VOLTAGES, \
+ .vsel_reg = v, \
+ .vsel_mask = S2DOS05_BUCK_VSEL_MASK, \
+ .enable_reg = e, \
+ .enable_mask = em, \
+ .enable_time = t, \
+ .active_discharge_off = 0, \
+ .active_discharge_on = S2DOS05_BUCK_FD_MASK, \
+ .active_discharge_reg = a, \
+ .active_discharge_mask = S2DOS05_BUCK_FD_MASK \
+}
+
+#define LDO_DESC(_name, _id, _ops, m, s, v, e, em, t, a) { \
+ .name = _name, \
+ .id = _id, \
+ .ops = _ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = m, \
+ .uV_step = s, \
+ .n_voltages = S2DOS05_LDO_N_VOLTAGES, \
+ .vsel_reg = v, \
+ .vsel_mask = S2DOS05_LDO_VSEL_MASK, \
+ .enable_reg = e, \
+ .enable_mask = em, \
+ .enable_time = t, \
+ .active_discharge_off = 0, \
+ .active_discharge_on = S2DOS05_LDO_FD_MASK, \
+ .active_discharge_reg = a, \
+ .active_discharge_mask = S2DOS05_LDO_FD_MASK \
+}
+
+static struct regulator_desc regulators[S2DOS05_REGULATOR_MAX] = {
+ /* name, id, ops, min_uv, uV_step, vsel_reg, enable_reg */
+ LDO_DESC("s2dos05-ldo1", _LDO(1), &_ldo_ops(), _LDO(_MIN1),
+ _LDO(_STEP1), _REG(_LDO1_CFG),
+ _REG(_EN), _MASK(_L1), _TIME(_LDO), _REG(_LDO1_CFG)),
+ LDO_DESC("s2dos05-ldo2", _LDO(2), &_ldo_ops(), _LDO(_MIN1),
+ _LDO(_STEP1), _REG(_LDO2_CFG),
+ _REG(_EN), _MASK(_L2), _TIME(_LDO), _REG(_LDO2_CFG)),
+ LDO_DESC("s2dos05-ldo3", _LDO(3), &_ldo_ops(), _LDO(_MIN2),
+ _LDO(_STEP1), _REG(_LDO3_CFG),
+ _REG(_EN), _MASK(_L3), _TIME(_LDO), _REG(_LDO3_CFG)),
+ LDO_DESC("s2dos05-ldo4", _LDO(4), &_ldo_ops(), _LDO(_MIN2),
+ _LDO(_STEP1), _REG(_LDO4_CFG),
+ _REG(_EN), _MASK(_L4), _TIME(_LDO), _REG(_LDO4_CFG)),
+ BUCK_DESC("s2dos05-buck1", _BUCK(1), &_buck_ops(), _BUCK(_MIN1),
+ _BUCK(_STEP1), _REG(_BUCK_VOUT),
+ _REG(_EN), _MASK(_B1), _TIME(_BUCK), _REG(_BUCK_CFG)),
+};
+
+#ifdef CONFIG_OF
+static int s2dos05_pmic_dt_parse_pdata(struct device *dev,
+ struct s2dos05_platform_data *pdata)
+{
+ struct device_node *pmic_np, *regulators_np, *reg_np;
+ struct s2dos05_regulator_data *rdata;
+ unsigned int i;
+
+ pmic_np = dev->of_node;
+ if (!pmic_np) {
+ dev_err(dev, "could not find pmic sub-node\n");
+ return -ENODEV;
+ }
+
+ regulators_np = of_find_node_by_name(pmic_np, "regulators");
+ if (!regulators_np) {
+ dev_err(dev, "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ /* count the number of regulators to be supported in pmic */
+ pdata->num_regulators = 0;
+ for_each_child_of_node(regulators_np, reg_np) {
+ pdata->num_regulators++;
+ }
+
+ rdata = devm_kzalloc(dev, sizeof(*rdata) *
+ pdata->num_regulators, GFP_KERNEL);
+ if (!rdata)
+ return -ENOMEM;
+
+ pdata->regulators = rdata;
+ for_each_child_of_node(regulators_np, reg_np) {
+ for (i = 0; i < ARRAY_SIZE(regulators); i++)
+ if (!of_node_cmp(reg_np->name,
+ regulators[i].name))
+ break;
+
+ if (i == ARRAY_SIZE(regulators)) {
+ dev_warn(dev,
+ "don't know how to configure regulator %s\n",
+ reg_np->name);
+ continue;
+ }
+
+ rdata->id = i;
+ rdata->initdata = of_get_regulator_init_data(
+ dev, reg_np,
+ &regulators[i]);
+ rdata->reg_node = reg_np;
+ rdata++;
+ }
+ of_node_put(regulators_np);
+
+ return 0;
+}
+#else
+static int s2dos05_pmic_dt_parse_pdata(struct s2dos05_dev *iodev,
+ struct s2dos05_platform_data *pdata)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+static int s2dos05_pmic_probe(struct i2c_client *i2c)
+{
+ struct s2dos05_dev *iodev;
+ struct device *dev = &i2c->dev;
+ struct s2dos05_platform_data *pdata = i2c->dev.platform_data;
+ struct regulator_config config = { };
+ struct s2dos05_data *s2dos05;
+ int i;
+ int ret = 0;
+
+ pr_info("%s:%s\n", MFD_DEV_NAME, __func__);
+
+ iodev = kzalloc(sizeof(struct s2dos05_dev), GFP_KERNEL);
+ if (!iodev)
+ return -ENOMEM;
+
+ if (i2c->dev.of_node) {
+ pdata = devm_kzalloc(&i2c->dev,
+ sizeof(struct s2dos05_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ ret = -ENOMEM;
+ goto err_pdata;
+ }
+ ret = s2dos05_pmic_dt_parse_pdata(&i2c->dev, pdata);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to get device of_node\n");
+ goto err_dt;
+ }
+
+ i2c->dev.platform_data = pdata;
+ } else
+ pdata = i2c->dev.platform_data;
+
+ iodev->dev = &i2c->dev;
+ iodev->i2c = i2c;
+
+ if (pdata) {
+ iodev->pdata = pdata;
+ iodev->wakeup = pdata->wakeup;
+ } else {
+ ret = -EINVAL;
+ goto err_dt;
+ }
+ mutex_init(&iodev->i2c_lock);
+ i2c_set_clientdata(i2c, iodev);
+
+ s2dos05 = devm_kzalloc(&i2c->dev, sizeof(struct s2dos05_data),
+ GFP_KERNEL);
+ if (!s2dos05) {
+ ret = -EINVAL;
+ goto err_data;
+ }
+
+ s2dos05->iodev = iodev;
+ s2dos05->num_regulators = pdata->num_regulators;
+
+ for (i = 0; i < pdata->num_regulators; i++) {
+ int id = pdata->regulators[i].id;
+
+ config.dev = &i2c->dev;
+ config.init_data = pdata->regulators[i].initdata;
+ config.driver_data = s2dos05;
+ config.of_node = pdata->regulators[i].reg_node;
+ s2dos05->opmode[id] = regulators[id].enable_mask;
+ s2dos05->rdev[i] = regulator_register(dev, &regulators[id], &config);
+ if (IS_ERR(s2dos05->rdev[i])) {
+ ret = PTR_ERR(s2dos05->rdev[i]);
+ dev_err(&i2c->dev, "regulator init failed for %d\n",
+ id);
+ s2dos05->rdev[i] = NULL;
+ goto err_rdata;
+ }
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ s2dos05_debugfs_init(iodev);
+#endif
+
+ return ret;
+
+err_rdata:
+ pr_info("[%s:%d] err:\n", __FILE__, __LINE__);
+ for (i = 0; i < s2dos05->num_regulators; i++)
+ if (s2dos05->rdev[i])
+ regulator_unregister(s2dos05->rdev[i]);
+err_data:
+ mutex_destroy(&iodev->i2c_lock);
+ devm_kfree(&i2c->dev, (void *)s2dos05);
+err_dt:
+ devm_kfree(&i2c->dev, (void *)pdata);
+err_pdata:
+ kfree(iodev);
+
+ return ret;
+}
+
+static void s2dos05_pmic_remove(struct i2c_client *i2c)
+{
+ struct s2dos05_data *s2dos05 = i2c_get_clientdata(i2c);
+ int i;
+
+ for (i = 0; i < s2dos05->num_regulators; i++)
+ if (s2dos05->rdev[i])
+ regulator_unregister(s2dos05->rdev[i]);
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id s2dos05_i2c_dt_ids[] = {
+ { .compatible = "samsung,s2dos05" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, s2dos05_i2c_dt_ids);
+#endif /* CONFIG_OF */
+
+#if defined(CONFIG_OF)
+static const struct i2c_device_id s2dos05_pmic_id[] = {
+ {"s2dos05", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, s2dos05_pmic_id);
+#endif /* CONFIG_OF */
+
+static struct i2c_driver s2dos05_i2c_driver = {
+ .driver = {
+ .name = "s2dos05",
+#if defined(CONFIG_OF)
+ .of_match_table = s2dos05_i2c_dt_ids,
+#endif /* CONFIG_OF */
+ .suppress_bind_attrs = true,
+ },
+ .probe = s2dos05_pmic_probe,
+ .remove = s2dos05_pmic_remove,
+ .id_table = s2dos05_pmic_id,
+};
+module_i2c_driver(s2dos05_i2c_driver);
+
+MODULE_DESCRIPTION("SAMSUNG s2dos05 Regulator Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index 82d460ff477..a01671fb621 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -944,6 +944,9 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
channel->buf = NULL;
qcom_glink_rx_done(glink, channel, intent);
+
+ if (channel->ept.rpdev)
+ pm_wakeup_ws_event(channel->ept.rpdev->dev.power.wakeup, 0, true);
}
advance_rx:
@@ -1578,6 +1581,17 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid,
if (ret)
goto rcid_remove;
+ /*
+ * Declare all channels as wakeup capable, but don't enable
+ * waking up by default.
+ *
+ * Userspace may wish to be woken up for incoming messages on a
+ * specific channel, for example to handle incoming calls or SMS
+ * messages on the IPCRTR channel. This can be done be enabling
+ * the wakeup source via sysfs.
+ */
+ device_set_wakeup_capable(&rpdev->dev, true);
+
channel->rpdev = rpdev;
}
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 3c5a6f6ac34..0f79e888cd6 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -1202,7 +1202,7 @@ void gether_disconnect(struct gether *link)
DBG(dev, "%s\n", __func__);
- netif_device_detach(dev->net);
+ netif_stop_queue(dev->net);
netif_carrier_off(dev->net);
/* disable endpoints, forcing (synchronous) completion
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
index 10129095a4c..6d3016e008e 100644
--- a/drivers/video/backlight/qcom-wled.c
+++ b/drivers/video/backlight/qcom-wled.c
@@ -197,6 +197,7 @@ struct wled {
bool disabled_by_short;
bool has_short_detect;
bool cabc_disabled;
+ bool ovp_irq_disabled;
int short_irq;
int ovp_irq;
@@ -294,7 +295,10 @@ static void wled_ovp_work(struct work_struct *work)
{
struct wled *wled = container_of(work,
struct wled, ovp_work.work);
- enable_irq(wled->ovp_irq);
+ if (wled->ovp_irq_disabled) {
+ enable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = false;
+ }
}
static int wled_module_enable(struct wled *wled, int val)
@@ -321,8 +325,11 @@ static int wled_module_enable(struct wled *wled, int val)
*/
schedule_delayed_work(&wled->ovp_work, HZ / 100);
} else {
- if (!cancel_delayed_work_sync(&wled->ovp_work))
+ if (!cancel_delayed_work_sync(&wled->ovp_work) &&
+ !wled->ovp_irq_disabled) {
disable_irq(wled->ovp_irq);
+ wled->ovp_irq_disabled = true;
+ }
}
}
@@ -1725,6 +1732,8 @@ static void wled_remove(struct platform_device *pdev)
cancel_delayed_work_sync(&wled->ovp_work);
disable_irq(wled->short_irq);
disable_irq(wled->ovp_irq);
+
+ wled->ovp_irq_disabled = true;
}
static const struct of_device_id wled_match_table[] = {
diff --git a/include/dt-bindings/clock/qcom,dispcc-sdm845.h b/include/dt-bindings/clock/qcom,dispcc-sdm845.h
index 4016fd1d5b4..f3e088b450b 100644
--- a/include/dt-bindings/clock/qcom,dispcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,dispcc-sdm845.h
@@ -49,6 +49,7 @@
/* DISP_CC Reset */
#define DISP_CC_MDSS_RSCC_BCR 0
+#define DISP_CC_MDSS_CORE_BCR 1
/* DISP_CC GDSCR */
#define MDSS_GDSC 0
diff --git a/include/dt-bindings/input/qcom,spmi-haptics.h b/include/dt-bindings/input/qcom,spmi-haptics.h
new file mode 100644
index 00000000000..14a7e7d1471
--- /dev/null
+++ b/include/dt-bindings/input/qcom,spmi-haptics.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * This header provides constants for pmi8998 SPMI haptics options.
+ */
+
+#ifndef _DT_BINDINGS_QCOM_PMIC_SPMI_HAPTICS_
+#define _DT_BINDINGS_QCOM_PMIC_SPMI_HAPTICS_
+
+// Actuator types
+#define HAP_TYPE_LRA 0
+#define HAP_TYPE_ERM 1
+
+// LRA Wave type
+#define HAP_WAVE_SINE 0
+#define HAP_WAVE_SQUARE 1
+
+// Play modes
+#define HAP_PLAY_DIRECT 0
+#define HAP_PLAY_BUFFER 1
+#define HAP_PLAY_AUDIO 2
+#define HAP_PLAY_PWM 3
+
+#define HAP_PLAY_MAX HAP_PLAY_PWM
+
+// Auto resonance type
+#define HAP_AUTO_RES_NONE 0
+#define HAP_AUTO_RES_ZXD 1
+#define HAP_AUTO_RES_QWD 2
+#define HAP_AUTO_RES_MAX_QWD 3
+#define HAP_AUTO_RES_ZXD_EOP 4
+
+#endif /* _DT_BINDINGS_QCOM_PMIC_SPMI_HAPTICS_ */
diff --git a/include/dt-bindings/sound/qcom,q6voice.h b/include/dt-bindings/sound/qcom,q6voice.h
new file mode 100644
index 00000000000..825bf7d47fe
--- /dev/null
+++ b/include/dt-bindings/sound/qcom,q6voice.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_Q6_VOICE_H__
+#define __DT_BINDINGS_Q6_VOICE_H__
+
+#define CS_VOICE 0
+#define VOICEMMODE1 1
+
+#endif /* __DT_BINDINGS_Q6_VOICE_H__ */
diff --git a/include/linux/regulator/s2dos05.h b/include/linux/regulator/s2dos05.h
new file mode 100644
index 00000000000..e33e8625758
--- /dev/null
+++ b/include/linux/regulator/s2dos05.h
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ * s2dos05.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ */
+
+#ifndef __LINUX_MFD_S2DOS05_H
+#define __LINUX_MFD_S2DOS05_H
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define MFD_DEV_NAME "s2dos05"
+
+/**
+ * sec_regulator_data - regulator data
+ * @id: regulator id
+ * @initdata: regulator init data (constraints, supplies, ...)
+ */
+
+struct s2dos05_dev {
+ struct device *dev;
+ struct i2c_client *i2c; /* 0xB2; PMIC, Flash LED */
+ struct mutex i2c_lock;
+
+ int type;
+ u8 rev_num; /* pmic Rev */
+ bool wakeup;
+ int dp_irq;
+ int adc_mode;
+ int adc_sync_mode;
+ u8 adc_en_val;
+
+ struct s2dos05_platform_data *pdata;
+};
+
+struct s2dos05_regulator_data {
+ int id;
+ struct regulator_init_data *initdata;
+ struct device_node *reg_node;
+};
+
+struct s2dos05_platform_data {
+ bool wakeup;
+ int num_regulators;
+ struct s2dos05_regulator_data *regulators;
+ int device_type;
+ int dp_irq;
+
+ /* adc_mode
+ * 0 : not use
+ * 1 : current meter
+ * 2 : power meter
+ */
+ int adc_mode;
+ /* 1 : sync mode, 2 : async mode */
+ int adc_sync_mode;
+};
+
+struct s2dos05 {
+ struct regmap *regmap;
+};
+
+/* S2DOS05 registers */
+/* Slave Addr : 0xC0 */
+enum S2DOS05_reg {
+ S2DOS05_REG_DEV_ID,
+ S2DOS05_REG_TOPSYS_STAT,
+ S2DOS05_REG_STAT,
+ S2DOS05_REG_EN,
+ S2DOS05_REG_LDO1_CFG,
+ S2DOS05_REG_LDO2_CFG,
+ S2DOS05_REG_LDO3_CFG,
+ S2DOS05_REG_LDO4_CFG,
+ S2DOS05_REG_BUCK_CFG,
+ S2DOS05_REG_BUCK_VOUT,
+ S2DOS05_REG_IRQ_MASK = 0x0D,
+ S2DOS05_REG_SSD_TSD = 0x0E,
+ S2DOS05_REG_OCL = 0x10,
+ S2DOS05_REG_IRQ = 0x11
+};
+
+/* S2DOS05 regulator ids */
+enum S2DOS05_regulators {
+ S2DOS05_LDO1,
+ S2DOS05_LDO2,
+ S2DOS05_LDO3,
+ S2DOS05_LDO4,
+ S2DOS05_BUCK1,
+ S2DOS05_REG_MAX,
+};
+
+#define S2DOS05_IRQ_PWRMT_MASK (1 << 5)
+#define S2DOS05_IRQ_TSD_MASK (1 << 4)
+#define S2DOS05_IRQ_SSD_MASK (1 << 3)
+#define S2DOS05_IRQ_SCP_MASK (1 << 2)
+#define S2DOS05_IRQ_UVLO_MASK (1 << 1)
+#define S2DOS05_IRQ_OCD_MASK (1 << 0)
+
+#define S2DOS05_BUCK_MIN1 506250
+#define S2DOS05_LDO_MIN1 1500000
+#define S2DOS05_LDO_MIN2 2700000
+#define S2DOS05_BUCK_STEP1 6250
+#define S2DOS05_LDO_STEP1 25000
+#define S2DOS05_LDO_VSEL_MASK 0x7F
+#define S2DOS05_LDO_FD_MASK 0x80
+#define S2DOS05_BUCK_VSEL_MASK 0xFF
+#define S2DOS05_BUCK_FD_MASK 0x08
+
+#define S2DOS05_ENABLE_MASK_L1 (1 << 0)
+#define S2DOS05_ENABLE_MASK_L2 (1 << 1)
+#define S2DOS05_ENABLE_MASK_L3 (1 << 2)
+#define S2DOS05_ENABLE_MASK_L4 (1 << 3)
+#define S2DOS05_ENABLE_MASK_B1 (1 << 4)
+
+#define S2DOS05_RAMP_DELAY 12000
+
+#define S2DOS05_ENABLE_TIME_LDO 50
+#define S2DOS05_ENABLE_TIME_BUCK 350
+
+#define S2DOS05_ENABLE_SHIFT 0x06
+#define S2DOS05_LDO_N_VOLTAGES (S2DOS05_LDO_VSEL_MASK + 1)
+#define S2DOS05_BUCK_N_VOLTAGES (S2DOS05_BUCK_VSEL_MASK + 1)
+
+#define S2DOS05_PMIC_EN_SHIFT 6
+#define S2DOS05_REGULATOR_MAX (S2DOS05_REG_MAX)
+
+/* ----------power meter ----------*/
+#define S2DOS05_REG_PWRMT_CTRL1 0x0A
+#define S2DOS05_REG_PWRMT_CTRL2 0x0B
+#define S2DOS05_REG_PWRMT_DATA 0x0C
+#define S2DOS05_REG_IRQ_MASK 0x0D
+
+#define CURRENT_ELVDD 2450
+#define CURRENT_ELVSS 2450
+#define CURRENT_AVDD 612
+#define CURRENT_BUCK 1220
+#define CURRENT_L1 2000
+#define CURRENT_L2 2000
+#define CURRENT_L3 2000
+#define CURRENT_L4 2000
+
+#define POWER_ELVDD 24500
+#define POWER_ELVSS 24500
+#define POWER_AVDD 3060
+#define POWER_BUCK 1525
+#define POWER_L1 5000
+#define POWER_L2 5000
+#define POWER_L3 5000
+#define POWER_L4 5000
+
+#define ADC_EN_MASK 0x80
+#define ADC_ASYNCRD_MASK 0x80
+#define ADC_PTR_MASK 0x0F
+#define ADC_PGEN_MASK 0x30
+#define CURRENT_MODE 0x00
+#define POWER_MODE 0x10
+#define RAWCURRENT_MODE 0x20
+#define SMPNUM_MASK 0x0F
+
+#define S2DOS05_MAX_ADC_CHANNEL 8
+
+void s2dos05_powermeter_init(struct s2dos05_dev *s2dos05);
+void s2dos05_powermeter_deinit(struct s2dos05_dev *s2dos05);
+
+/* S2DOS05 shared i2c API function */
+int s2dos05_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
+int s2dos05_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
+int s2dos05_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
+
+
+#endif /* __LINUX_MFD_S2DOS05_H */
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index ab7eea01ab4..974597960b5 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -214,6 +214,9 @@ struct rmi_device_platform_data {
int reset_delay_ms;
int irq;
+ u8 *pdt_fallback_desc;
+ int pdt_fallback_size;
+
struct rmi_device_platform_data_spi spi_data;
/* function handler pdata */
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 022a520e31f..e8d5ee027b4 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -866,6 +866,7 @@
#define ABS_VOLUME 0x20
#define ABS_PROFILE 0x21
+#define ABS_SND_PROFILE 0x22
#define ABS_MISC 0x28
@@ -974,4 +975,12 @@
#define SND_MAX 0x07
#define SND_CNT (SND_MAX+1)
+/*
+ * ABS_SND_PROFILE values
+ */
+
+#define SND_PROFILE_SILENT 0x00
+#define SND_PROFILE_VIBRATE 0x01
+#define SND_PROFILE_RING 0x02
+
#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 59f9742e9ff..965bdde6bd9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -252,6 +252,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_TAS5720
imply SND_SOC_TAS6424
imply SND_SOC_TDA7419
+ imply SND_SOC_TFA98xx
imply SND_SOC_TFA9879
imply SND_SOC_TFA989X
imply SND_SOC_TLV320ADC3XXX
@@ -338,6 +339,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_WSA883X
imply SND_SOC_WSA884X
imply SND_SOC_ZL38060
+ imply SND_SOC_TAS2559
help
Normally ASoC codec drivers are only built if a machine driver which
uses them is also built since they are only usable with a machine
@@ -1886,6 +1888,14 @@ config SND_SOC_TDA7419
depends on I2C
select REGMAP_I2C
+config SND_SOC_TFA98XX
+ tristate "NXP/Goodix TFA98XX"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Enable support for NXP (now Goodix) TFA98XX speaker amplifiers, e.g. TFA98XX.
+ Downstream driver, needs rewrite and upstreaming to mainline.
+
config SND_SOC_TFA9879
tristate "NXP Semiconductors TFA9879 amplifier"
depends on I2C
@@ -2435,6 +2445,9 @@ config SND_SOC_LPASS_VA_MACRO
select REGMAP_MMIO
select SND_SOC_LPASS_MACRO_COMMON
tristate "Qualcomm VA Macro in LPASS(Low Power Audio SubSystem)"
+config SND_SOC_TAS2559
+ tristate "Texas Instruments TAS2559 speaker amplifier"
+ depends on I2C
config SND_SOC_LPASS_RX_MACRO
depends on COMMON_CLK
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index f53baa2b956..3e1be95d326 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -284,6 +284,10 @@ snd-soc-tas2770-objs := tas2770.o
snd-soc-tas2781-comlib-objs := tas2781-comlib.o
snd-soc-tas2781-fmwlib-objs := tas2781-fmwlib.o
snd-soc-tas2781-i2c-objs := tas2781-i2c.o
+snd-soc-tfa98xx-objs += tfa98xx-downstream/tfa98xx.o
+snd-soc-tfa98xx-objs += tfa98xx-downstream/tfa_container.o
+snd-soc-tfa98xx-objs += tfa98xx-downstream/tfa_dsp.o
+snd-soc-tfa98xx-objs += tfa98xx-downstream/tfa_init.o
snd-soc-tfa9879-objs := tfa9879.o
snd-soc-tfa989x-objs := tfa989x.o
snd-soc-tlv320adc3xxx-objs := tlv320adc3xxx.o
@@ -388,6 +392,10 @@ snd-soc-tas2780-objs := tas2780.o
# Mux
snd-soc-simple-mux-objs := simple-mux.o
+snd-soc-tas2559-objs := tas2559.o
+ccflags-y += -DDEBUG
+obj-$(CONFIG_SND_SOC_TAS2559) += snd-soc-tas2559.o
+
obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
@@ -671,6 +679,7 @@ obj-$(CONFIG_SND_SOC_TAS5805M) += snd-soc-tas5805m.o
obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
+obj-$(CONFIG_SND_SOC_TFA98XX) += snd-soc-tfa98xx.o
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TFA989X) += snd-soc-tfa989x.o
obj-$(CONFIG_SND_SOC_TLV320ADC3XXX) += snd-soc-tlv320adc3xxx.o
diff --git a/sound/soc/codecs/tas2559.c b/sound/soc/codecs/tas2559.c
new file mode 100644
index 00000000000..8a5994eb3a9
--- /dev/null
+++ b/sound/soc/codecs/tas2559.c
@@ -0,0 +1,2289 @@
+/*
+** =============================================================================
+** Copyright (c) 2016 Texas Instruments Inc.
+**
+** 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; version 2.
+**
+** This program is distributed in the hope that it will be useful, but WITHOUT
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+**
+** File:
+** tas2559.c
+**
+** Description:
+** ALSA SoC driver for Texas Instruments TAS2559 High Performance 4W Smart Amplifier
+**
+** =============================================================================
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/syscalls.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#include <linux/crc8.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "tas2559.h"
+
+struct TBlock {
+ unsigned int mnType;
+ unsigned char mbPChkSumPresent;
+ unsigned char mnPChkSum;
+ unsigned int mnCommands;
+ unsigned char *mpData;
+};
+
+struct TData {
+ char mpName[64];
+ char *mpDescription;
+ unsigned int mnBlocks;
+ struct TBlock *mpBlocks;
+};
+
+struct TProgram {
+ char mpName[64];
+ char *mpDescription;
+ unsigned char mnAppMode;
+ unsigned short mnBoost;
+ struct TData mData;
+};
+
+struct TPLL {
+ char mpName[64];
+ char *mpDescription;
+ struct TBlock mBlock;
+};
+
+struct TConfiguration {
+ char mpName[64];
+ char *mpDescription;
+ unsigned int mnDevices;
+ unsigned int mnProgram;
+ unsigned int mnPLL;
+ unsigned int mnSamplingRate;
+ unsigned char mnPLLSrc;
+ unsigned int mnPLLSrcRate;
+ struct TData mData;
+};
+
+struct TCalibration {
+ char mpName[64];
+ char *mpDescription;
+ unsigned int mnProgram;
+ unsigned int mnConfiguration;
+ struct TData mData;
+};
+
+struct TFirmware {
+ unsigned int mnFWSize;
+ unsigned int mnChecksum;
+ unsigned int mnPPCVersion;
+ unsigned int mnFWVersion;
+ unsigned int mnDriverVersion;
+ unsigned int mnTimeStamp;
+ char mpDDCName[64];
+ char *mpDescription;
+ unsigned int mnDeviceFamily;
+ unsigned int mnDevice;
+ unsigned int mnPLLs;
+ struct TPLL *mpPLLs;
+ unsigned int mnPrograms;
+ struct TProgram *mpPrograms;
+ unsigned int mnConfigurations;
+ struct TConfiguration *mpConfigurations;
+ unsigned int mnCalibrations;
+ struct TCalibration *mpCalibrations;
+};
+
+struct tas2559_register {
+ int book;
+ int page;
+ int reg;
+};
+
+enum channel {
+ DevA = 0x01,
+ DevB = 0x02,
+ DevBoth = (DevA | DevB),
+};
+
+struct tas2559_priv {
+ struct device *dev;
+ struct regmap *mpRegmap;
+ struct i2c_client *client;
+ struct mutex dev_lock;
+ struct TFirmware *mpFirmware;
+ unsigned int mnCurrentProgram;
+ unsigned int mnCurrentSampleRate;
+ unsigned int mnCurrentConfiguration;
+ unsigned int mnNewConfiguration;
+ unsigned int mnCurrentCalibration;
+ bool mbPowerUp;
+ bool mbLoadConfigurationPrePowerUp;
+
+ /* parameters for TAS2559 */
+ struct gpio_desc *mnDevAGPIORST;
+ unsigned char mnDevAAddr;
+ unsigned char mnDevACurrentBook;
+ unsigned char mnDevACurrentPage;
+
+ /* parameters for TAS2560 */
+ struct gpio_desc *mnDevBGPIORST;
+ unsigned char mnDevBAddr;
+ unsigned char mnDevBCurrentBook;
+ unsigned char mnDevBCurrentPage;
+
+ unsigned int mnErrCode;
+ unsigned int mnRestart;
+ struct mutex codec_lock;
+};
+
+static unsigned int p_tas2559_default_data[] = {
+ DevA, TAS2559_SAR_ADC2_REG, 0x05,/* enable SAR ADC */
+ DevA, TAS2559_CLK_ERR_CTRL2, 0x21,/*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/
+ DevA, TAS2559_CLK_ERR_CTRL3, 0x21,/*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */
+ DevB, TAS2560_CLK_ERR_CTRL2, 0x21,/*rampDown 15dB/us, clock1 hysteresis, 0.34ms; clock2 hysteresis, 10.6us */
+ DevA, TAS2559_SAFE_GUARD_REG, TAS2559_SAFE_GUARD_PATTERN,/* safe guard */
+ DevA, TAS2559_CLK_ERR_CTRL, 0x00,/*enable clock error detection*/
+ DevB, TAS2560_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_startup_data[] = {
+ DevA, TAS2559_GPIO1_PIN_REG, 0x01,/* enable BCLK */
+ DevA, TAS2559_GPIO2_PIN_REG, 0x01,/* enable WCLK */
+ DevA, TAS2559_POWER_CTRL2_REG, 0xA0,/*Class-D, Boost power up*/
+ DevA, TAS2559_POWER_CTRL2_REG, 0xA3,/*Class-D, Boost, IV sense power up*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0xF8,/*PLL, DSP, clock dividers power up*/
+ DevBoth, TAS2559_UDELAY, 2000,/*delay*/
+ DevB, TAS2560_DEV_MODE_REG, 0x02,
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevBoth, TAS2559_UDELAY, 2000,/*delay*/
+ DevA, TAS2559_CLK_ERR_CTRL, 0x2B,/*enable clock error detection*/
+ DevB, TAS2560_CLK_ERR_CTRL, 0x0B,/* disable clock error detection */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_mute_data[] = {
+ DevA, TAS2559_SOFT_MUTE_REG, 0x01,/*soft mute*/
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevA, TAS2559_MDELAY, 10,/*delay 10ms*/
+ DevA, TAS2559_MUTE_REG, 0x03,/*mute*/
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_unmute_data[] = {
+ DevA, TAS2559_MUTE_REG, 0x00, /*unmute*/
+ DevB, TAS2560_MUTE_REG, 0x40,
+ DevA, TAS2559_SOFT_MUTE_REG, 0x00, /*soft unmute*/
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_shutdown_data[] = {
+ DevA, TAS2559_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevB, TAS2560_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevA, TAS2559_SOFT_MUTE_REG, 0x01,/*soft mute*/
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevB, TAS2560_MUTE_REG, 0x01,
+ DevBoth, TAS2559_MDELAY, 10,/*delay 10ms*/
+ DevB, TAS2559_MDELAY, 20,/*delay 20ms*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0x60,/*DSP power down*/
+ DevA, TAS2559_MDELAY, 2,/*delay 20ms*/
+ DevA, TAS2559_MUTE_REG, 0x03,/*mute*/
+ DevA, TAS2559_POWER_CTRL2_REG, 0x00,/*Class-D, Boost power down*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0x00,/*all power down*/
+ DevB, TAS2560_DEV_MODE_REG, 0x01,
+ DevA, TAS2559_GPIO1_PIN_REG, 0x00,/* disable BCLK */
+ DevA, TAS2559_GPIO2_PIN_REG, 0x00,/* disable WCLK */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_shutdown_DevB_data[] = {
+ DevA, TAS2559_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevB, TAS2560_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevB, TAS2560_MUTE_REG, 0x01,
+ DevA, TAS2559_POWER_CTRL1_REG, 0x60,/*DSP power down*/
+ DevBoth, TAS2559_MDELAY, 30,/*delay 2ms*/
+ DevB, TAS2560_DEV_MODE_REG, 0x01,
+ DevA, TAS2559_POWER_CTRL2_REG, 0x00,/*Class-D, Boost power down*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0x00,/*all power down*/
+ DevA, TAS2559_GPIO1_PIN_REG, 0x00,/* disable BCLK */
+ DevA, TAS2559_GPIO2_PIN_REG, 0x00,/* disable WCLK */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static int tas2559_i2c_read_device(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char *p_value)
+{
+ int nResult = 0;
+ unsigned int val = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_read(pTAS2559->mpRegmap, reg, &val);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+ else
+ *p_value = (unsigned char)val;
+
+ return nResult;
+}
+
+static int tas2559_i2c_write_device(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char value)
+{
+ int nResult = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_write(pTAS2559->mpRegmap, reg, value);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+
+ return nResult;
+}
+
+static int tas2559_i2c_update_bits(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char mask,
+ unsigned char value)
+{
+ int nResult = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_update_bits(pTAS2559->mpRegmap, reg, mask, value);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+
+ return nResult;
+}
+
+static int tas2559_i2c_bulkwrite_device(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char *pBuf,
+ unsigned int len)
+{
+ int nResult = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_bulk_write(pTAS2559->mpRegmap, reg, pBuf, len);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+
+ return nResult;
+}
+
+static int tas2559_change_book_page(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned char nBook,
+ unsigned char nPage)
+{
+ int nResult = 0;
+
+ if (chn & DevA) {
+ if (pTAS2559->mnDevACurrentBook == nBook) {
+ if (pTAS2559->mnDevACurrentPage != nPage) {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_PAGE, nPage);
+
+ if (nResult >= 0)
+ pTAS2559->mnDevACurrentPage = nPage;
+ }
+ } else {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_PAGE, 0);
+
+ if (nResult >= 0) {
+ pTAS2559->mnDevACurrentPage = 0;
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_REG, nBook);
+ pTAS2559->mnDevACurrentBook = nBook;
+
+ if (nPage != 0) {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_PAGE, nPage);
+ pTAS2559->mnDevACurrentPage = nPage;
+ }
+ }
+ }
+ }
+
+ if (chn & DevB) {
+ if (pTAS2559->mnDevBCurrentBook == nBook) {
+ if (pTAS2559->mnDevBCurrentPage != nPage) {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_PAGE, nPage);
+
+ if (nResult >= 0)
+ pTAS2559->mnDevBCurrentPage = nPage;
+ }
+ } else {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_PAGE, 0);
+
+ if (nResult >= 0) {
+ pTAS2559->mnDevBCurrentPage = 0;
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_REG, nBook);
+ pTAS2559->mnDevBCurrentBook = nBook;
+
+ if (nPage != 0) {
+ tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_PAGE, nPage);
+ pTAS2559->mnDevBCurrentPage = nPage;
+ }
+ }
+ }
+ }
+
+ return nResult;
+}
+
+static int tas2559_dev_read(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned int *pValue)
+{
+ int nResult = 0;
+ unsigned char Value = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559, chn,
+ TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ if (chn == DevA)
+ nResult = tas2559_i2c_read_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_PAGE_REG(nRegister), &Value);
+ else
+ if (chn == DevB)
+ nResult = tas2559_i2c_read_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_PAGE_REG(nRegister), &Value);
+ else {
+ dev_err(pTAS2559->dev, "%s read chn ERROR %d\n", __func__, chn);
+ nResult = -EINVAL;
+ }
+
+ if (nResult >= 0)
+ *pValue = Value;
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static int tas2559_dev_write(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned int nValue)
+{
+ int nResult = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559,
+ chn, TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ if (chn & DevA)
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_PAGE_REG(nRegister), nValue);
+
+ if (chn & DevB)
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_PAGE_REG(nRegister), nValue);
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static int tas2559_dev_bulk_write(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned char *pData,
+ unsigned int nLength)
+{
+ int nResult = 0;
+ unsigned char reg = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559, chn,
+ TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ reg = TAS2559_PAGE_REG(nRegister);
+
+ if (chn & DevA)
+ nResult = tas2559_i2c_bulkwrite_device(pTAS2559,
+ pTAS2559->mnDevAAddr, reg, pData, nLength);
+
+ if (chn & DevB)
+ nResult = tas2559_i2c_bulkwrite_device(pTAS2559,
+ pTAS2559->mnDevBAddr, reg, pData, nLength);
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static int tas2559_dev_update_bits(
+ struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned int nMask,
+ unsigned int nValue)
+{
+ int nResult = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559,
+ chn, TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ if (chn & DevA)
+ nResult = tas2559_i2c_update_bits(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_PAGE_REG(nRegister), nMask, nValue);
+
+ if (chn & DevB)
+ nResult = tas2559_i2c_update_bits(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_PAGE_REG(nRegister), nMask, nValue);
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static void tas2559_hw_reset(struct tas2559_priv *pTAS2559)
+{
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+
+ gpiod_set_value_cansleep(pTAS2559->mnDevAGPIORST, 0);
+ msleep(5);
+ gpiod_set_value_cansleep(pTAS2559->mnDevAGPIORST, 1);
+ msleep(2);
+
+ gpiod_set_value_cansleep(pTAS2559->mnDevBGPIORST, 0);
+ msleep(5);
+ gpiod_set_value_cansleep(pTAS2559->mnDevBGPIORST, 1);
+ msleep(2);
+
+ pTAS2559->mnDevACurrentBook = -1;
+ pTAS2559->mnDevACurrentPage = -1;
+ pTAS2559->mnDevBCurrentBook = -1;
+ pTAS2559->mnDevBCurrentPage = -1;
+
+ if (pTAS2559->mnErrCode)
+ dev_info(pTAS2559->dev, "%s, ErrCode=0x%x\n", __func__, pTAS2559->mnErrCode);
+
+ pTAS2559->mnErrCode = 0;
+}
+
+static int tas2559_dev_load_data(struct tas2559_priv *pTAS2559,
+ enum channel dev, unsigned int *pData)
+{
+ int nResult = 0;
+ unsigned int n = 0;
+ unsigned int nRegister;
+ unsigned int nData;
+ enum channel chl;
+
+ do {
+ chl = pData[n * 3];
+
+ if (chl == 0xffffffff)
+ break;
+
+ if (dev & chl) {
+ nRegister = pData[n * 3 + 1];
+ nData = pData[n * 3 + 2];
+
+ if (nRegister == TAS2559_UDELAY) {
+ udelay(nData);
+ } else if (nRegister == TAS2559_MDELAY) {
+ mdelay(nData);
+ } else if (nRegister != 0xFFFFFFFF) {
+ nResult = tas2559_dev_write(pTAS2559, chl, nRegister, nData);
+ if (nResult < 0)
+ break;
+ }
+ }
+
+ n++;
+ } while (nRegister != 0xFFFFFFFF);
+
+ return nResult;
+}
+
+static int tas2559_DevStartup(struct tas2559_priv *pTAS2559,
+ unsigned int dev)
+{
+ int nResult = 0;
+ enum channel chl = dev;
+
+ if (dev == DevB)
+ chl = DevBoth;
+
+ dev_dbg(pTAS2559->dev, "%s, chl=%d\n", __func__, chl);
+ nResult = tas2559_dev_load_data(pTAS2559, chl, p_tas2559_startup_data);
+
+ return nResult;
+}
+
+static int tas2559_DevShutdown(struct tas2559_priv *pTAS2559,
+ unsigned int dev)
+{
+ int nResult = 0;
+
+ dev_dbg(pTAS2559->dev, "%s, dev=%d\n", __func__, dev);
+
+ if (dev == DevB)
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_shutdown_DevB_data);
+ else
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_shutdown_data);
+
+ return nResult;
+}
+
+int tas2559_set_DAC_gain(struct tas2559_priv *pTAS2559,
+ enum channel chl, unsigned int nGain)
+{
+ int nResult = 0;
+ int gain = (nGain & 0x0f);
+
+ dev_dbg(pTAS2559->dev, "%s, nGain: %d", __func__, nGain);
+
+ if (chl & DevA) {
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA,
+ TAS2559_SPK_CTRL_REG, 0x78, (gain << 3));
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (chl & DevB)
+ nResult = tas2559_dev_update_bits(pTAS2559, DevB,
+ TAS2560_SPK_CTRL_REG, 0x0f, gain);
+
+end:
+
+ return nResult;
+}
+
+int tas2559_get_DAC_gain(struct tas2559_priv *pTAS2559,
+ enum channel chl, unsigned char *pnGain)
+{
+ int nResult = 0;
+ int nGain;
+
+ if (chl == DevA) {
+ nResult = tas2559_dev_read(pTAS2559, DevA, TAS2559_SPK_CTRL_REG, &nGain);
+
+ if (nResult >= 0)
+ *pnGain = ((nGain >> 3) & 0x0f);
+ } else
+ if (chl == DevB) {
+ nResult = tas2559_dev_read(pTAS2559, DevB, TAS2560_SPK_CTRL_REG, &nGain);
+
+ if (nResult >= 0)
+ *pnGain = (nGain & 0x0f);
+ }
+
+ return nResult;
+}
+
+int tas2559_DevMute(struct tas2559_priv *pTAS2559, enum channel dev, bool mute)
+{
+ int nResult = 0;
+
+ dev_dbg(pTAS2559->dev, "%s, dev=%d, mute=%d\n", __func__, dev, mute);
+
+ if (mute)
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_mute_data);
+ else
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_unmute_data);
+
+ return nResult;
+}
+
+int tas2559_load_default(struct tas2559_priv *pTAS2559)
+{
+ int nResult = 0;
+
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+
+ nResult = tas2559_dev_load_data(pTAS2559, DevBoth, p_tas2559_default_data);
+ if (nResult < 0)
+ goto end;
+
+ // Set default bit rate of 16 for DevA
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA, TAS2559_ASI1_DAC_FORMAT_REG, 0x18, 0);
+ if (nResult < 0)
+ goto end;
+
+ // Set default bit rate of 16 for DevB
+ nResult = tas2559_dev_update_bits(pTAS2559, DevB, TAS2560_DAI_FMT, 0x03, 0);
+ if (nResult < 0)
+ goto end;
+
+ /* enable DOUT tri-state for extra BCLKs */
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA, TAS2559_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
+ if (nResult < 0)
+ goto end;
+
+ nResult = tas2559_dev_update_bits(pTAS2559, DevB, TAS2560_ASI_CFG_1, 0x02, 0x02);
+ if (nResult < 0)
+ goto end;
+
+ /* Interrupt pin, low-highZ, high active driven */
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA, TAS2559_GPIO_HIZ_CTRL2_REG, 0x30, 0x30);
+
+end:
+ return nResult;
+}
+
+
+void tas2559_clear_firmware(struct TFirmware *pFirmware)
+{
+ unsigned int n, nn;
+
+ if (!pFirmware)
+ return;
+
+ kfree(pFirmware->mpDescription);
+
+ if (pFirmware->mpPLLs != NULL) {
+ for (n = 0; n < pFirmware->mnPLLs; n++) {
+ kfree(pFirmware->mpPLLs[n].mpDescription);
+ kfree(pFirmware->mpPLLs[n].mBlock.mpData);
+ }
+
+ kfree(pFirmware->mpPLLs);
+ }
+
+ if (pFirmware->mpPrograms != NULL) {
+ for (n = 0; n < pFirmware->mnPrograms; n++) {
+ kfree(pFirmware->mpPrograms[n].mpDescription);
+ kfree(pFirmware->mpPrograms[n].mData.mpDescription);
+
+ for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
+ kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
+
+ kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
+ }
+
+ kfree(pFirmware->mpPrograms);
+ }
+
+ if (pFirmware->mpConfigurations != NULL) {
+ for (n = 0; n < pFirmware->mnConfigurations; n++) {
+ kfree(pFirmware->mpConfigurations[n].mpDescription);
+ kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
+
+ for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
+ kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
+
+ kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
+ }
+
+ kfree(pFirmware->mpConfigurations);
+ }
+
+ if (pFirmware->mpCalibrations != NULL) {
+ for (n = 0; n < pFirmware->mnCalibrations; n++) {
+ kfree(pFirmware->mpCalibrations[n].mpDescription);
+ kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
+
+ for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
+ kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
+
+ kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
+ }
+
+ kfree(pFirmware->mpCalibrations);
+ }
+
+ memset(pFirmware, 0x00, sizeof(struct TFirmware));
+}
+
+static int tas2559_load_block(struct tas2559_priv *pTAS2559, struct TBlock *pBlock)
+{
+ int nResult = 0;
+ unsigned int nCommand = 0;
+ unsigned char nBook;
+ unsigned char nPage;
+ unsigned char nOffset;
+ unsigned char nData;
+ unsigned int nValue1;
+ unsigned int nLength;
+ unsigned int nSleep;
+ enum channel chl;
+ unsigned char *pData = pBlock->mpData;
+
+ dev_dbg(pTAS2559->dev, "%s: Type = %d, commands = %d\n", __func__,
+ pBlock->mnType, pBlock->mnCommands);
+
+ if (pBlock->mnType == TAS2559_BLOCK_PLL) {
+ chl = DevA;
+ } else if ((pBlock->mnType == TAS2559_BLOCK_PGM_DEV_A)
+ || (pBlock->mnType == TAS2559_BLOCK_CFG_COEFF_DEV_A)
+ || (pBlock->mnType == TAS2559_BLOCK_CFG_PRE_DEV_A)) {
+ chl = DevA;
+ } else if ((pBlock->mnType == TAS2559_BLOCK_PGM_DEV_B)
+ || (pBlock->mnType == TAS2559_BLOCK_PST_POWERUP_DEV_B)
+ || (pBlock->mnType == TAS2559_BLOCK_CFG_PRE_DEV_B)) {
+ chl = DevB;
+ } else {
+ dev_err(pTAS2559->dev, "block type error %d\n", pBlock->mnType);
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (pBlock->mbPChkSumPresent) {
+ if (chl == DevA) {
+ nResult = tas2559_dev_write(pTAS2559, DevA, TAS2559_CRC_RESET_REG, 1);
+ if (nResult < 0)
+ goto end;
+ } else {
+ nResult = tas2559_dev_write(pTAS2559, DevB, TAS2560_CRC_CHK_REG, 1);
+ if (nResult < 0)
+ goto end;
+ }
+ }
+
+ nCommand = 0;
+ while (nCommand < pBlock->mnCommands) {
+ pData = pBlock->mpData + nCommand * 4;
+ nBook = pData[0];
+ nPage = pData[1];
+ nOffset = pData[2];
+ nData = pData[3];
+ nCommand++;
+
+ if (nOffset <= 0x7F) {
+ nResult = tas2559_dev_write(pTAS2559,
+ chl, TAS2559_REG(nBook, nPage, nOffset), nData);
+ if (nResult < 0)
+ goto end;
+
+ } else if (nOffset == 0x81) {
+ nSleep = (nBook << 8) + nPage;
+ msleep(nSleep);
+ } else if (nOffset == 0x85) {
+ pData += 4;
+ nLength = (nBook << 8) + nPage;
+ nBook = pData[0];
+ nPage = pData[1];
+ nOffset = pData[2];
+
+ if (nLength > 1) {
+ nResult = tas2559_dev_bulk_write(pTAS2559,
+ chl, TAS2559_REG(nBook, nPage, nOffset), pData + 3, nLength);
+ if (nResult < 0)
+ goto end;
+
+ } else {
+ nResult = tas2559_dev_write(pTAS2559,
+ chl, TAS2559_REG(nBook, nPage, nOffset), pData[3]);
+ if (nResult < 0)
+ goto end;
+
+ }
+
+ nCommand++;
+ if (nLength >= 2)
+ nCommand += ((nLength - 2) / 4) + 1;
+ }
+ }
+
+ if (pBlock->mbPChkSumPresent) {
+ if (chl == DevA)
+ nResult = tas2559_dev_read(pTAS2559, DevA,
+ TAS2559_CRC_CHECKSUM_REG, &nValue1);
+ else
+ nResult = tas2559_dev_read(pTAS2559, DevB,
+ TAS2560_CRC_CHK_REG, &nValue1);
+
+ if (nResult < 0)
+ goto end;
+
+ if (nValue1 != pBlock->mnPChkSum) {
+ dev_err(pTAS2559->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
+ pBlock->mnPChkSum, (nValue1 & 0xff));
+ nResult = -EAGAIN;
+ pTAS2559->mnErrCode |= ERROR_PRAM_CRCCHK;
+ }
+ }
+
+end:
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "Block (%d) load error\n",
+ pBlock->mnType);
+
+ return nResult;
+}
+
+static int tas2559_load_data(struct tas2559_priv *pTAS2559, struct TData *pData, unsigned int nType)
+{
+ int nResult = 0;
+ unsigned int nBlock;
+ struct TBlock *pBlock;
+
+ dev_dbg(pTAS2559->dev,
+ "TAS2559 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
+
+ for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
+ pBlock = &(pData->mpBlocks[nBlock]);
+
+ if (pBlock->mnType == nType) {
+ nResult = tas2559_load_block(pTAS2559, pBlock);
+
+ if (nResult < 0)
+ break;
+ }
+ }
+
+ return nResult;
+}
+
+static void failsafe(struct tas2559_priv *pTAS2559)
+{
+ dev_err(pTAS2559->dev, "%s\n", __func__);
+ pTAS2559->mnErrCode |= ERROR_FAILSAFE;
+
+ tas2559_DevShutdown(pTAS2559, DevBoth);
+ pTAS2559->mbPowerUp = false;
+ tas2559_hw_reset(pTAS2559);
+ tas2559_dev_write(pTAS2559, DevBoth, TAS2559_SW_RESET_REG, 0x01);
+ msleep(1);
+ tas2559_dev_write(pTAS2559, DevA, TAS2559_SPK_CTRL_REG, 0x04);
+ tas2559_dev_write(pTAS2559, DevB, TAS2560_SPK_CTRL_REG, 0x50);
+
+ if (pTAS2559->mpFirmware != NULL)
+ tas2559_clear_firmware(pTAS2559->mpFirmware);
+}
+
+static int tas2559_load_coefficient(struct tas2559_priv *pTAS2559,
+ int nPrevConfig, int nNewConfig, bool bPowerOn)
+{
+ int nResult = 0;
+ struct TPLL *pPLL;
+ struct TProgram *pProgram = NULL;
+ struct TConfiguration *pPrevConfiguration;
+ struct TConfiguration *pNewConfiguration;
+ enum channel chl;
+ bool bRestorePower = false;
+
+ dev_dbg(pTAS2559->dev, "%s, Prev=%d, new=%d, Pow=%d\n",
+ __func__, nPrevConfig, nNewConfig, bPowerOn);
+
+ if (!pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "%s, firmware not loaded\n", __func__);
+ goto end;
+ }
+
+ if (nNewConfig >= pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "%s, invalid configuration New=%d, total=%d\n",
+ __func__, nNewConfig, pTAS2559->mpFirmware->mnConfigurations);
+ goto end;
+ }
+
+ if (nPrevConfig < 0) {
+ pPrevConfiguration = NULL;
+ chl = DevBoth;
+ } else
+ if (nPrevConfig == nNewConfig) {
+ dev_dbg(pTAS2559->dev, "%d configuration is already loaded\n", nNewConfig);
+ goto end;
+ } else {
+ pPrevConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[nPrevConfig]);
+ chl = pPrevConfiguration->mnDevices;
+ }
+
+ pNewConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[nNewConfig]);
+ pTAS2559->mnCurrentConfiguration = nNewConfig;
+
+ if (pPrevConfiguration) {
+ if ((pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL)
+ && (pPrevConfiguration->mnDevices == pNewConfiguration->mnDevices)) {
+ dev_dbg(pTAS2559->dev, "%s, PLL and device same\n", __func__);
+ goto prog_coefficient;
+ }
+ }
+
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[pTAS2559->mnCurrentProgram]);
+
+ if (bPowerOn) {
+
+ nResult = tas2559_DevShutdown(pTAS2559, chl);
+
+ if (nResult < 0)
+ goto end;
+
+ bRestorePower = true;
+ }
+
+ /* load PLL */
+ pPLL = &(pTAS2559->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
+ dev_dbg(pTAS2559->dev, "load PLL: %s block for Configuration %s\n",
+ pPLL->mpName, pNewConfiguration->mpName);
+ nResult = tas2559_load_block(pTAS2559, &(pPLL->mBlock));
+
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
+
+ dev_dbg(pTAS2559->dev, "load configuration %s conefficient pre block\n",
+ pNewConfiguration->mpName);
+
+ if (pNewConfiguration->mnDevices & DevA) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData), TAS2559_BLOCK_CFG_PRE_DEV_A);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (pNewConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData), TAS2559_BLOCK_CFG_PRE_DEV_B);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+prog_coefficient:
+ dev_dbg(pTAS2559->dev, "load new configuration: %s, coeff block data\n",
+ pNewConfiguration->mpName);
+
+ if (pNewConfiguration->mnDevices & DevA) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData),
+ TAS2559_BLOCK_CFG_COEFF_DEV_A);
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (pNewConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData),
+ TAS2559_BLOCK_CFG_COEFF_DEV_B);
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (bRestorePower) {
+ nResult = tas2559_DevStartup(pTAS2559, pNewConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ if (pNewConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData),
+ TAS2559_BLOCK_PST_POWERUP_DEV_B);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ dev_dbg(pTAS2559->dev,
+ "device powered up, load unmute\n");
+ nResult = tas2559_DevMute(pTAS2559, pNewConfiguration->mnDevices, false);
+ if (nResult < 0)
+ goto end;
+ }
+
+end:
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s, load new conf %s error\n", __func__, pNewConfiguration->mpName);
+
+ pTAS2559->mnNewConfiguration = pTAS2559->mnCurrentConfiguration;
+ return nResult;
+}
+
+static int tas2559_load_configuration(struct tas2559_priv *pTAS2559,
+ unsigned int nConfiguration, bool bLoadSame)
+{
+ int nResult = 0;
+ struct TConfiguration *pCurrentConfiguration = NULL;
+ struct TConfiguration *pNewConfiguration = NULL;
+
+ dev_dbg(pTAS2559->dev, "%s: %d\n", __func__, nConfiguration);
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = 0;
+ goto end;
+ }
+
+ if (nConfiguration >= pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "Configuration %d doesn't exist\n",
+ nConfiguration);
+ nResult = 0;
+ goto end;
+ }
+
+ if ((!pTAS2559->mbLoadConfigurationPrePowerUp)
+ && (nConfiguration == pTAS2559->mnCurrentConfiguration)
+ && (!bLoadSame)) {
+ dev_info(pTAS2559->dev, "Configuration %d is already loaded\n",
+ nConfiguration);
+ nResult = 0;
+ goto end;
+ }
+
+ pCurrentConfiguration =
+ &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+ pNewConfiguration =
+ &(pTAS2559->mpFirmware->mpConfigurations[nConfiguration]);
+
+ if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
+ dev_err(pTAS2559->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
+ nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
+ nResult = 0;
+ goto end;
+ }
+
+ if (pNewConfiguration->mnPLL >= pTAS2559->mpFirmware->mnPLLs) {
+ dev_err(pTAS2559->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
+ nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
+ nResult = 0;
+ goto end;
+ }
+
+ if (pTAS2559->mbPowerUp) {
+ dev_err(pTAS2559->dev, "%s, device power on, load new conf[%d] %s\n", __func__,
+ nConfiguration, pNewConfiguration->mpName);
+ nResult = tas2559_load_coefficient(pTAS2559, pTAS2559->mnCurrentConfiguration, nConfiguration, true);
+ pTAS2559->mbLoadConfigurationPrePowerUp = false;
+ } else {
+ dev_dbg(pTAS2559->dev,
+ "TAS2559 was powered down, will load coefficient when power up\n");
+ pTAS2559->mbLoadConfigurationPrePowerUp = true;
+ pTAS2559->mnNewConfiguration = nConfiguration;
+ }
+
+end:
+
+ if (nResult < 0) {
+ if (pTAS2559->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+ failsafe(pTAS2559);
+ }
+
+ return nResult;
+}
+
+int tas2559_set_program(struct tas2559_priv *pTAS2559,
+ unsigned int nProgram, int nConfig)
+{
+ struct TProgram *pProgram;
+ struct TConfiguration *pConfiguration;
+ unsigned int nConfiguration = 0;
+ unsigned int nSampleRate = 0;
+ bool bFound = false;
+ int nResult = 0;
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = 0;
+ goto end;
+ }
+
+ if (nProgram >= pTAS2559->mpFirmware->mnPrograms) {
+ dev_err(pTAS2559->dev, "TAS2559: Program %d doesn't exist\n",
+ nProgram);
+ nResult = 0;
+ goto end;
+ }
+
+ if(nProgram == 1)
+ pTAS2559->mnCurrentSampleRate = 96000;
+ else
+ pTAS2559->mnCurrentSampleRate = 48000;
+
+ if (nConfig < 0) {
+ nConfiguration = 0;
+ nSampleRate = pTAS2559->mnCurrentSampleRate;
+ dev_err(pTAS2559->dev, "nSampleRate: %d\n", nSampleRate);
+
+ while (!bFound && (nConfiguration < pTAS2559->mpFirmware->mnConfigurations)) {
+ dev_err(pTAS2559->dev, "mpConfigurations SampleRate: %d\n",
+ pTAS2559->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate);
+ if (pTAS2559->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
+ if (nSampleRate == 0) {
+ bFound = true;
+ dev_info(pTAS2559->dev, "find default configuration %d\n", nConfiguration);
+ } else if (nSampleRate == pTAS2559->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
+ bFound = true;
+ dev_info(pTAS2559->dev, "find matching configuration %d\n", nConfiguration);
+ } else {
+ nConfiguration++;
+ }
+ } else {
+ nConfiguration++;
+ }
+ }
+
+ if (!bFound) {
+ dev_err(pTAS2559->dev,
+ "Program %d, no valid configuration found for sample rate %d, ignore\n",
+ nProgram, nSampleRate);
+ nResult = 0;
+ goto end;
+ }
+ } else {
+ if (pTAS2559->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
+ dev_err(pTAS2559->dev, "%s, configuration program doesn't match\n", __func__);
+ nResult = 0;
+ goto end;
+ }
+
+ nConfiguration = nConfig;
+ }
+
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[nProgram]);
+
+ if (pTAS2559->mbPowerUp) {
+ dev_info(pTAS2559->dev,
+ "device powered up, power down to load program %d (%s)\n",
+ nProgram, pProgram->mpName);
+
+ nResult = tas2559_DevShutdown(pTAS2559, DevBoth);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ tas2559_hw_reset(pTAS2559);
+ nResult = tas2559_dev_write(pTAS2559, DevBoth, TAS2559_SW_RESET_REG, 0x01);
+ if (nResult < 0)
+ goto end;
+
+ msleep(1);
+ nResult = tas2559_load_default(pTAS2559);
+ if (nResult < 0)
+ goto end;
+
+ dev_info(pTAS2559->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
+ nResult = tas2559_load_data(pTAS2559, &(pProgram->mData), TAS2559_BLOCK_PGM_DEV_A);
+ if (nResult < 0)
+ goto end;
+
+ nResult = tas2559_load_data(pTAS2559, &(pProgram->mData), TAS2559_BLOCK_PGM_DEV_B);
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mnCurrentProgram = nProgram;
+
+ nResult = tas2559_load_coefficient(pTAS2559, -1, nConfiguration, false);
+ if (nResult < 0)
+ goto end;
+
+ if (pTAS2559->mbPowerUp) {
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+ nResult = tas2559_DevStartup(pTAS2559, pConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ if (pConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pConfiguration->mData),
+ TAS2559_BLOCK_PST_POWERUP_DEV_B);
+ if (nResult < 0)
+ goto end;
+ }
+
+ nResult = tas2559_DevMute(pTAS2559, pConfiguration->mnDevices, false);
+ if (nResult < 0)
+ goto end;
+ }
+
+end:
+
+ if (nResult < 0) {
+ if (pTAS2559->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+ failsafe(pTAS2559);
+ }
+
+ return nResult;
+}
+
+static void fw_print_header(struct tas2559_priv *pTAS2559, struct TFirmware *pFirmware)
+{
+ dev_info(pTAS2559->dev, "FW Size = %d", pFirmware->mnFWSize);
+ dev_info(pTAS2559->dev, "Checksum = 0x%04X", pFirmware->mnChecksum);
+ dev_info(pTAS2559->dev, "PPC Version = 0x%04X", pFirmware->mnPPCVersion);
+ dev_info(pTAS2559->dev, "FW Version = 0x%04X", pFirmware->mnFWVersion);
+ dev_info(pTAS2559->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
+ dev_info(pTAS2559->dev, "Timestamp = %d", pFirmware->mnTimeStamp);
+ dev_info(pTAS2559->dev, "DDC Name = %s", pFirmware->mpDDCName);
+ dev_info(pTAS2559->dev, "Description = %s", pFirmware->mpDescription);
+}
+
+static inline unsigned int fw_convert_number(unsigned char *pData)
+{
+ return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
+}
+
+static int fw_parse_header(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
+
+ if (nSize < 104) {
+ dev_err(pTAS2559->dev, "Firmware: Header too short");
+ return -EINVAL;
+ }
+
+ if (memcmp(pData, pMagicNumber, 4)) {
+ dev_err(pTAS2559->dev, "Firmware: Magic number doesn't match");
+ return -EINVAL;
+ }
+
+ pData += 4;
+
+ pFirmware->mnFWSize = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnChecksum = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnPPCVersion = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnFWVersion = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnDriverVersion = fw_convert_number(pData);
+ dev_err(pTAS2559->dev, "Firmware driver: 0x%x", pFirmware->mnDriverVersion);
+ pData += 4;
+
+ pFirmware->mnTimeStamp = fw_convert_number(pData);
+ pData += 4;
+
+ memcpy(pFirmware->mpDDCName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ if ((pData - pDataStart) >= nSize) {
+ dev_err(pTAS2559->dev, "Firmware: Header too short after DDC description");
+ return -EINVAL;
+ }
+
+ pFirmware->mnDeviceFamily = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDeviceFamily != 0) {
+ dev_err(pTAS2559->dev,
+ "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
+ return -EINVAL;
+ }
+
+ pFirmware->mnDevice = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDevice != 4) {
+ dev_err(pTAS2559->dev,
+ "device %d, not TAS2559", pFirmware->mnDevice);
+ return -EINVAL;
+ }
+
+ fw_print_header(pTAS2559, pFirmware);
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_block_data(struct tas2559_priv *pTAS2559, struct TFirmware *pFirmware,
+ struct TBlock *pBlock, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+
+ pBlock->mnType = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
+ pBlock->mbPChkSumPresent = pData[0];
+ pData++;
+
+ pBlock->mnPChkSum = pData[0];
+ pData++;
+
+ // skip YRAM checksum data for simplicity
+ pData += 2;
+ } else {
+ pBlock->mbPChkSumPresent = 0;
+ }
+
+ pBlock->mnCommands = fw_convert_number(pData);
+ pData += 4;
+
+ n = pBlock->mnCommands * 4;
+ pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
+ pData += n;
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_data(struct tas2559_priv *pTAS2559, struct TFirmware *pFirmware,
+ struct TData *pImageData, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int nBlock;
+ unsigned int n;
+
+ memcpy(pImageData->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ pImageData->mnBlocks = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ pImageData->mpBlocks =
+ kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
+
+ for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
+ n = fw_parse_block_data(pTAS2559, pFirmware,
+ &(pImageData->mpBlocks[nBlock]), pData);
+ pData += n;
+ }
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_pll_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nPLL;
+ struct TPLL *pPLL;
+
+ pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnPLLs == 0)
+ goto end;
+
+ pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
+
+ for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
+ pPLL = &(pFirmware->mpPLLs[nPLL]);
+
+ memcpy(pPLL->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ n = fw_parse_block_data(pTAS2559, pFirmware, &(pPLL->mBlock), pData);
+ pData += n;
+ }
+
+end:
+ return pData - pDataStart;
+}
+
+static int fw_parse_program_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nProgram;
+ struct TProgram *pProgram;
+
+ pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnPrograms == 0)
+ goto end;
+
+ pFirmware->mpPrograms =
+ kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
+
+ for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
+ pProgram = &(pFirmware->mpPrograms[nProgram]);
+ memcpy(pProgram->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ pProgram->mnAppMode = pData[0];
+ pData++;
+
+ pProgram->mnBoost = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ n = fw_parse_data(pTAS2559, pFirmware, &(pProgram->mData), pData);
+ pData += n;
+ }
+
+end:
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_configuration_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nConfiguration;
+ struct TConfiguration *pConfiguration;
+
+ pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnConfigurations == 0)
+ goto end;
+
+ pFirmware->mpConfigurations =
+ kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
+ GFP_KERNEL);
+
+ for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
+ nConfiguration++) {
+ pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
+ memcpy(pConfiguration->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
+ || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
+ && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
+ pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
+ pData += 2;
+ } else
+ pConfiguration->mnDevices = DevBoth;
+
+ pConfiguration->mnProgram = pData[0];
+ pData++;
+
+ pConfiguration->mnPLL = pData[0];
+ pData++;
+
+ pConfiguration->mnSamplingRate = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
+ pConfiguration->mnPLLSrc = pData[0];
+ pData++;
+
+ pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
+ pData += 4;
+ dev_err(pTAS2559->dev, "line:%d, pData: 0x%x, 0x%x, 0x%x, 0x%x", __LINE__, pData[0], pData[1], pData[2], pData[3]);
+ }
+
+ n = fw_parse_data(pTAS2559, pFirmware, &(pConfiguration->mData), pData);
+ pData += n;
+ }
+
+end:
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_calibration_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nCalibration;
+ struct TCalibration *pCalibration;
+
+ pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnCalibrations == 0)
+ goto end;
+
+ pFirmware->mpCalibrations =
+ kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
+
+ for (nCalibration = 0;
+ nCalibration < pFirmware->mnCalibrations;
+ nCalibration++) {
+ pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
+ memcpy(pCalibration->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ pCalibration->mnProgram = pData[0];
+ pData++;
+
+ pCalibration->mnConfiguration = pData[0];
+ pData++;
+
+ n = fw_parse_data(pTAS2559, pFirmware, &(pCalibration->mData), pData);
+ pData += n;
+ }
+
+end:
+
+ return pData - pDataStart;
+}
+
+static int fw_parse(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
+{
+ int nPosition = 0;
+
+ nPosition = fw_parse_header(pTAS2559, pFirmware, pData, nSize);
+
+ if (nPosition < 0) {
+ dev_err(pTAS2559->dev, "Firmware: Wrong Header");
+ return -EINVAL;
+ }
+
+ if (nPosition >= nSize) {
+ dev_err(pTAS2559->dev, "Firmware: Too short");
+ return -EINVAL;
+ }
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ nPosition = fw_parse_pll_data(pTAS2559, pFirmware, pData);
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ nPosition = fw_parse_program_data(pTAS2559, pFirmware, pData);
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ nPosition = fw_parse_configuration_data(pTAS2559, pFirmware, pData);
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ if (nSize > 64)
+ nPosition = fw_parse_calibration_data(pTAS2559, pFirmware, pData);
+
+ return 0;
+}
+
+void tas2559_fw_ready(const struct firmware *pFW, void *pContext)
+{
+ struct tas2559_priv *pTAS2559 = (struct tas2559_priv *) pContext;
+ int nResult;
+ unsigned int nProgram = 0;
+ unsigned int nSampleRate = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_info(pTAS2559->dev, "%s:\n", __func__);
+
+ if (unlikely(!pFW) || unlikely(!pFW->data)) {
+ dev_err(pTAS2559->dev, "%s firmware is not loaded.\n",
+ TAS2559_FW_NAME);
+ goto end;
+ }
+
+ if (pTAS2559->mpFirmware->mpConfigurations) {
+ nProgram = pTAS2559->mnCurrentProgram;
+ nSampleRate = pTAS2559->mnCurrentSampleRate;
+ dev_dbg(pTAS2559->dev, "clear current firmware\n");
+ tas2559_clear_firmware(pTAS2559->mpFirmware);
+ }
+
+ nResult = fw_parse(pTAS2559, pTAS2559->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
+ release_firmware(pFW);
+
+ if (nResult < 0) {
+ dev_err(pTAS2559->dev, "firmware is corrupt\n");
+ goto end;
+ }
+
+ if (!pTAS2559->mpFirmware->mnPrograms) {
+ dev_err(pTAS2559->dev, "firmware contains no programs\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (!pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "firmware contains no configurations\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (nProgram >= pTAS2559->mpFirmware->mnPrograms) {
+ dev_info(pTAS2559->dev,
+ "no previous program, set to default\n");
+ nProgram = 0;
+ }
+
+ pTAS2559->mnCurrentSampleRate = nSampleRate;
+ nResult = tas2559_set_program(pTAS2559, nProgram, -1);
+
+end:
+ mutex_unlock(&pTAS2559->codec_lock);
+}
+
+int tas2559_enable(struct tas2559_priv *pTAS2559, bool bEnable)
+{
+ int nResult = 0;
+ struct TProgram *pProgram;
+ struct TConfiguration *pConfiguration;
+ unsigned int nValue;
+
+ dev_dbg(pTAS2559->dev, "%s: %s\n", __func__, bEnable ? "On" : "Off");
+
+ if ((pTAS2559->mpFirmware->mnPrograms == 0)
+ || (pTAS2559->mpFirmware->mnConfigurations == 0)) {
+ dev_err(pTAS2559->dev, "%s, firmware not loaded\n", __func__);
+ /*Load firmware*/
+ nResult = request_firmware_nowait(THIS_MODULE, 1, TAS2559_FW_NAME,
+ pTAS2559->dev, GFP_KERNEL, pTAS2559, tas2559_fw_ready);
+ if(nResult < 0) {
+ dev_err(pTAS2559->dev, "%s, firmware is loaded\n", __func__);
+ goto end;
+ }
+ }
+
+ /* check safe guard*/
+ nResult = tas2559_dev_read(pTAS2559, DevA, TAS2559_SAFE_GUARD_REG, &nValue);
+ if (nResult < 0)
+ goto end;
+ if ((nValue & 0xff) != TAS2559_SAFE_GUARD_PATTERN) {
+ dev_err(pTAS2559->dev, "ERROR DevA safe guard (0x%x) failure!\n", nValue);
+ nResult = -EPIPE;
+ pTAS2559->mnErrCode = ERROR_SAFE_GUARD;
+ pTAS2559->mbPowerUp = true;
+ goto end;
+ }
+
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[pTAS2559->mnCurrentProgram]);
+ if (bEnable) {
+ if (!pTAS2559->mbPowerUp) {
+ if (pTAS2559->mbLoadConfigurationPrePowerUp) {
+ pTAS2559->mbLoadConfigurationPrePowerUp = false;
+ nResult = tas2559_load_coefficient(pTAS2559,
+ pTAS2559->mnCurrentConfiguration, pTAS2559->mnNewConfiguration, false);
+ if (nResult < 0)
+ goto end;
+ }
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+ nResult = tas2559_DevStartup(pTAS2559, pConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ if (pConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pConfiguration->mData),
+ TAS2559_BLOCK_PST_POWERUP_DEV_B);
+ if (nResult < 0)
+ goto end;
+ }
+
+ nResult = tas2559_DevMute(pTAS2559, pConfiguration->mnDevices, false);
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mbPowerUp = true;
+ pTAS2559->mnRestart = 0;
+ }
+ } else {
+ if (pTAS2559->mbPowerUp) {
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+
+ nResult = tas2559_DevShutdown(pTAS2559, pConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mbPowerUp = false;
+ pTAS2559->mnRestart = 0;
+ }
+ }
+
+ nResult = 0;
+
+end:
+
+ if (nResult < 0) {
+ if (pTAS2559->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK | ERROR_SAFE_GUARD))
+ failsafe(pTAS2559);
+ }
+
+ dev_dbg(pTAS2559->dev, "%s: exit\n", __func__);
+ return nResult;
+}
+
+int tas2559_set_sampling_rate(struct tas2559_priv *pTAS2559, unsigned int nSamplingRate)
+{
+ int nResult = 0;
+ struct TConfiguration *pConfiguration;
+ unsigned int nConfiguration;
+
+ dev_dbg(pTAS2559->dev, "%s: nSamplingRate = %d [Hz]\n", __func__,
+ nSamplingRate);
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+
+ if (pConfiguration->mnSamplingRate == nSamplingRate) {
+ dev_info(pTAS2559->dev, "Sampling rate for current configuration matches: %d\n",
+ nSamplingRate);
+ nResult = 0;
+ goto end;
+ }
+
+ for (nConfiguration = 0;
+ nConfiguration < pTAS2559->mpFirmware->mnConfigurations;
+ nConfiguration++) {
+ pConfiguration =
+ &(pTAS2559->mpFirmware->mpConfigurations[nConfiguration]);
+
+ if ((pConfiguration->mnSamplingRate == nSamplingRate)
+ && (pConfiguration->mnProgram == pTAS2559->mnCurrentProgram)) {
+ dev_info(pTAS2559->dev,
+ "Found configuration: %s, with compatible sampling rate %d\n",
+ pConfiguration->mpName, nSamplingRate);
+ nResult = tas2559_load_configuration(pTAS2559, nConfiguration, false);
+ goto end;
+ }
+ }
+
+ dev_err(pTAS2559->dev, "Cannot find a configuration that supports sampling rate: %d\n",
+ nSamplingRate);
+
+end:
+
+ return nResult;
+}
+
+int tas2559_set_config(struct tas2559_priv *pTAS2559, int config)
+{
+ struct TConfiguration *pConfiguration;
+ struct TProgram *pProgram;
+ unsigned int nProgram = pTAS2559->mnCurrentProgram;
+ unsigned int nConfiguration = config;
+ int nResult = 0;
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (nConfiguration >= pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "Configuration %d doesn't exist\n",
+ nConfiguration);
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[nConfiguration]);
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[nProgram]);
+
+ if (nProgram != pConfiguration->mnProgram) {
+ dev_err(pTAS2559->dev,
+ "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
+ nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
+ nProgram, pProgram->mpName);
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ dev_dbg(pTAS2559->dev, "%s, load new conf %s\n", __func__, pConfiguration->mpName);
+ nResult = tas2559_load_configuration(pTAS2559, nConfiguration, false);
+
+end:
+
+ return nResult;
+}
+
+int tas2559_parse_dt(struct device *dev, struct tas2559_priv *pTAS2559)
+{
+ struct device_node *np = dev->of_node;
+ int rc = 0, ret = 0;
+ unsigned int value;
+
+ pTAS2559->mnDevAGPIORST = devm_gpiod_get(dev, "ti,tas2559-reset", GPIOD_OUT_LOW);
+ if (IS_ERR(pTAS2559->mnDevAGPIORST)) {
+ ret = PTR_ERR(pTAS2559->mnDevAGPIORST);
+ dev_err(dev, "Failed to request reset gpio, error %d\n", ret);
+ return ret;
+ }
+ else
+ dev_dbg(pTAS2559->dev, "%s, tas2559 reset gpio\n", __func__);
+
+ pTAS2559->mnDevBGPIORST = devm_gpiod_get(dev, "ti,tas2560-reset", GPIOD_OUT_LOW);
+ if (IS_ERR(pTAS2559->mnDevBGPIORST)) {
+ ret = PTR_ERR(pTAS2559->mnDevBGPIORST);
+ dev_err(dev, "Failed to request reset gpio, error %d\n", ret);
+ return ret;
+ }
+ else
+ dev_dbg(pTAS2559->dev, "%s, tas2560 reset gpio\n", __func__);
+
+ rc = of_property_read_u32(np, "ti,tas2559-addr", &value);
+ if (rc) {
+ dev_err(pTAS2559->dev, "Looking up %s property in node %s failed %d\n",
+ "ti,tas2559-addr", np->full_name, rc);
+ ret = -EINVAL;
+ goto end;
+ } else {
+ pTAS2559->mnDevAAddr = value;
+ dev_dbg(pTAS2559->dev, "ti,tas2559 addr=0x%x\n", pTAS2559->mnDevAAddr);
+ }
+
+ rc = of_property_read_u32(np, "ti,tas2560-addr", &value);
+ if (rc) {
+ dev_err(pTAS2559->dev, "Looking up %s property in node %s failed %d\n",
+ "ti,tas2560-addr", np->full_name, rc);
+ ret = -EINVAL;
+ goto end;
+ } else {
+ pTAS2559->mnDevBAddr = value;
+ dev_dbg(pTAS2559->dev, "ti,tas2560-addr=0x%x\n", pTAS2559->mnDevBAddr);
+ }
+
+end:
+
+ return ret;
+}
+
+// Codec related
+
+static const struct snd_soc_dapm_widget tas2559_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("ASI2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("ASIM", "ASIM Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_OUT_DRV("ClassD", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("NDivider", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("OUT")
+};
+
+static const struct snd_soc_dapm_route tas2559_audio_map[] = {
+ {"DAC", NULL, "ASI1"},
+ {"DAC", NULL, "ASI2"},
+ {"DAC", NULL, "ASIM"},
+ {"ClassD", NULL, "DAC"},
+ {"OUT", NULL, "ClassD"},
+ {"DAC", NULL, "PLL"},
+ {"DAC", NULL, "NDivider"},
+};
+
+static int tas2559_mute(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *codec = dai->component;
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+ tas2559_enable(pTAS2559, !mute);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return 0;
+}
+
+static int tas2559_hw_params(struct snd_pcm_substream *pSubstream,
+ struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
+{
+ struct snd_soc_component *pCodec = pDAI->component;
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(pCodec);
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+ tas2559_set_sampling_rate(pTAS2559, params_rate(pParams));
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return 0;
+}
+
+static int tas2559_configuration_get(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ pValue->value.integer.value[0] = pTAS2559->mnCurrentConfiguration;
+ dev_dbg(pTAS2559->dev, "%s = %d\n", __func__,
+ pTAS2559->mnCurrentConfiguration);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return 0;
+}
+
+static int tas2559_configuration_put(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned int nConfiguration = pValue->value.integer.value[0];
+ int ret = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_info(pTAS2559->dev, "%s = %d\n", __func__, nConfiguration);
+ ret = tas2559_set_config(pTAS2559, nConfiguration);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static int tas2559_ldac_gain_get(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned char nGain = 0;
+ int ret = -1;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_get_DAC_gain(pTAS2559, DevA, &nGain);
+
+ if (ret >= 0)
+ pValue->value.integer.value[0] = nGain;
+
+ dev_dbg(pTAS2559->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static int tas2559_ldac_gain_put(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned int nGain = pValue->value.integer.value[0];
+ int ret = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_set_DAC_gain(pTAS2559, DevA, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static int tas2559_rdac_gain_get(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned char nGain = 0;
+ int ret = -1;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_get_DAC_gain(pTAS2559, DevB, &nGain);
+
+ if (ret >= 0)
+ pValue->value.integer.value[0] = nGain;
+
+ dev_dbg(pTAS2559->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+
+ return ret;
+}
+
+static int tas2559_rdac_gain_put(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned int nGain = pValue->value.integer.value[0];
+ int ret = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_set_DAC_gain(pTAS2559, DevB, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static const struct snd_kcontrol_new tas2559_snd_controls[] = {
+ SOC_SINGLE_EXT("TAS2559 DAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0,
+ tas2559_ldac_gain_get, tas2559_ldac_gain_put),
+ SOC_SINGLE_EXT("TAS2560 DAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0,
+ tas2559_rdac_gain_get, tas2559_rdac_gain_put),
+ SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
+ tas2559_configuration_get, tas2559_configuration_put),
+};
+
+static const struct snd_soc_component_driver soc_codec_driver_tas2559 = {
+ .idle_bias_on = false,
+ .controls = tas2559_snd_controls,
+ .num_controls = ARRAY_SIZE(tas2559_snd_controls),
+ .dapm_widgets = tas2559_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tas2559_dapm_widgets),
+ .dapm_routes = tas2559_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(tas2559_audio_map),
+ .legacy_dai_naming = 1,
+};
+
+static struct snd_soc_dai_ops tas2559_dai_ops = {
+ .mute_stream = tas2559_mute,
+ .hw_params = tas2559_hw_params,
+};
+
+#define TAS2559_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+static struct snd_soc_dai_driver tas2559_dai_driver[] = {
+ {
+ .name = "tas2559 ASI1",
+ .id = 0,
+ .playback = {
+ .stream_name = "ASI1 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2559_FORMATS,
+ },
+ .ops = &tas2559_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tas2559 ASI2",
+ .id = 1,
+ .playback = {
+ .stream_name = "ASI2 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2559_FORMATS,
+ },
+ .ops = &tas2559_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tas2559 ASIM",
+ .id = 2,
+ .playback = {
+ .stream_name = "ASIM Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2559_FORMATS,
+ },
+ .ops = &tas2559_dai_ops,
+ .symmetric_rate = 1,
+ },
+};
+
+int tas2559_register_codec(struct tas2559_priv *pTAS2559)
+{
+ int nResult = 0;
+
+ dev_info(pTAS2559->dev, "%s, enter\n", __func__);
+ nResult = devm_snd_soc_register_component(pTAS2559->dev,
+ &soc_codec_driver_tas2559,
+ tas2559_dai_driver, ARRAY_SIZE(tas2559_dai_driver));
+ return nResult;
+}
+
+int tas2559_deregister_codec(struct tas2559_priv *pTAS2559)
+{
+ snd_soc_unregister_component(pTAS2559->dev);
+ return 0;
+}
+
+//I2C Driver
+
+static bool tas2559_volatile(struct device *pDev, unsigned int nRegister)
+{
+ return true;
+}
+
+static bool tas2559_writeable(struct device *pDev, unsigned int nRegister)
+{
+ return true;
+}
+
+static const struct regmap_config tas2559_i2c_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = tas2559_writeable,
+ .volatile_reg = tas2559_volatile,
+ .cache_type = REGCACHE_NONE,
+ .max_register = 128,
+};
+
+static int tas2559_i2c_probe(struct i2c_client *pClient)
+{
+ struct tas2559_priv *pTAS2559;
+ int nResult;
+
+ dev_info(&pClient->dev, "%s enter\n", __func__);
+ pTAS2559 = devm_kzalloc(&pClient->dev, sizeof(struct tas2559_priv), GFP_KERNEL);
+
+ if (!pTAS2559) {
+ dev_err(&pClient->dev, " -ENOMEM\n");
+ nResult = -ENOMEM;
+ goto err;
+ }
+
+ pTAS2559->client = pClient;
+ pTAS2559->dev = &pClient->dev;
+ i2c_set_clientdata(pClient, pTAS2559);
+ dev_set_drvdata(&pClient->dev, pTAS2559);
+
+ pTAS2559->mpRegmap = devm_regmap_init_i2c(pClient, &tas2559_i2c_regmap);
+
+ if (IS_ERR(pTAS2559->mpRegmap)) {
+ nResult = PTR_ERR(pTAS2559->mpRegmap);
+ dev_err(&pClient->dev, "Failed to allocate register map: %d\n",
+ nResult);
+ goto err;
+ }
+
+ if (pClient->dev.of_node)
+ tas2559_parse_dt(&pClient->dev, pTAS2559);
+
+ tas2559_hw_reset(pTAS2559);
+
+ pTAS2559->mnRestart = 0;
+
+ mutex_init(&pTAS2559->dev_lock);
+
+ /* Reset the chip */
+ nResult = tas2559_dev_write(pTAS2559, DevBoth, TAS2559_SW_RESET_REG, 1);
+ if (nResult < 0) {
+ dev_err(&pClient->dev, "I2c fail, %d\n", nResult);
+ goto err;
+ }
+ msleep(1);
+
+ pTAS2559->mpFirmware = devm_kzalloc(&pClient->dev, sizeof(struct TFirmware), GFP_KERNEL);
+
+ if (!pTAS2559->mpFirmware) {
+ dev_err(&pClient->dev, "mpFirmware ENOMEM\n");
+ nResult = -ENOMEM;
+ goto err;
+ }
+
+ mutex_init(&pTAS2559->codec_lock);
+ tas2559_register_codec(pTAS2559);
+
+ nResult = request_firmware_nowait(THIS_MODULE, 1, TAS2559_FW_NAME,
+ pTAS2559->dev, GFP_KERNEL, pTAS2559, tas2559_fw_ready);
+
+err:
+
+ return nResult;
+}
+
+static void tas2559_i2c_remove(struct i2c_client *pClient)
+{
+ struct tas2559_priv *pTAS2559 = i2c_get_clientdata(pClient);
+
+ dev_info(pTAS2559->dev, "%s\n", __func__);
+
+ tas2559_deregister_codec(pTAS2559);
+ mutex_destroy(&pTAS2559->codec_lock);
+
+ mutex_destroy(&pTAS2559->dev_lock);
+ return;
+}
+
+static const struct i2c_device_id tas2559_i2c_id[] = {
+ {"tas2559", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tas2559_i2c_id);
+
+#if defined(CONFIG_OF)
+static const struct of_device_id tas2559_of_match[] = {
+ {.compatible = "ti,tas2559"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, tas2559_of_match);
+#endif
+
+static struct i2c_driver tas2559_i2c_driver = {
+ .driver = {
+ .name = "tas2559",
+ .owner = THIS_MODULE,
+#if defined(CONFIG_OF)
+ .of_match_table = of_match_ptr(tas2559_of_match),
+#endif
+ },
+ .probe = tas2559_i2c_probe,
+ .remove = tas2559_i2c_remove,
+ .id_table = tas2559_i2c_id,
+};
+
+module_i2c_driver(tas2559_i2c_driver);
+
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("TAS2559 ALSA SOC Smart Amplifier Stereo driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/tas2559.h b/sound/soc/codecs/tas2559.h
new file mode 100644
index 00000000000..bdd5f4e767a
--- /dev/null
+++ b/sound/soc/codecs/tas2559.h
@@ -0,0 +1,525 @@
+/*
+** =============================================================================
+** Copyright (c) 2016 Texas Instruments Inc.
+**
+** 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; version 2.
+**
+** This program is distributed in the hope that it will be useful, but WITHOUT
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+**
+** File:
+** tas2559.h
+**
+** Description:
+** definitions and data structures for TAS2559 Android Linux driver
+**
+** =============================================================================
+*/
+
+#ifndef _TAS2559_H
+#define _TAS2559_H
+
+#include <linux/regmap.h>
+
+/* Page Control Register */
+#define TAS2559_PAGECTL_REG 0
+
+/* Book Control Register (available in page0 of each book) */
+#define TAS2559_BOOKCTL_PAGE 0
+#define TAS2559_BOOKCTL_REG 127
+
+#define TAS2559_REG(book, page, reg) ((((unsigned int)book * 256 * 128) + \
+ ((unsigned int)page * 128)) + reg)
+
+#define TAS2559_BOOK_ID(reg) ((unsigned char)(reg / (256 * 128)))
+#define TAS2559_PAGE_ID(reg) ((unsigned char)((reg % (256 * 128)) / 128))
+#define TAS2559_BOOK_REG(reg) ((unsigned char)(reg % (256 * 128)))
+#define TAS2559_PAGE_REG(reg) ((unsigned char)((reg % (256 * 128)) % 128))
+
+/* Book0, Page0 registers */
+#define TAS2559_SW_RESET_REG TAS2559_REG(0, 0, 1)
+
+#define TAS2559_REV_PGID_REG TAS2559_REG(0, 0, 3)
+#define TAS2559_PG_VERSION_1P0 0x00
+#define TAS2559_PG_VERSION_2P0 0x10
+#define TAS2559_PG_VERSION_2P1 0x20
+
+#define TAS2559_POWER_CTRL1_REG TAS2559_REG(0, 0, 4)
+#define TAS2559_POWER_CTRL2_REG TAS2559_REG(0, 0, 5)
+
+#define TAS2559_SPK_CTRL_REG TAS2559_REG(0, 0, 6)
+/* B0P0R6 - TAS2559_SPK_CTRL_REG */
+#define TAS2559_DAC_GAIN_MASK (0xf << 3)
+#define TAS2559_DAC_GAIN_SHIFT 0x03
+
+#define TAS2559_MUTE_REG TAS2559_REG(0, 0, 7)
+#define TAS2559_SNS_CTRL_REG TAS2559_REG(0, 0, 8)
+#define TAS2559_ADC_INPUT_SEL_REG TAS2559_REG(0, 0, 9)
+#define TAS2559_DBOOST_CTL_REG TAS2559_REG(0, 0, 10)
+#define TAS2559_NONAME11_REG TAS2559_REG(0, 0, 11)
+#define TAS2559_NONAME12_REG TAS2559_REG(0, 0, 12)
+#define TAS2559_NONAME13_REG TAS2559_REG(0, 0, 13)
+#define TAS2559_NONAME14_REG TAS2559_REG(0, 0, 14)
+#define TAS2559_NONAME15_REG TAS2559_REG(0, 0, 15)
+#define TAS2559_NONAME16_REG TAS2559_REG(0, 0, 16)
+#define TAS2559_NONAME17_REG TAS2559_REG(0, 0, 17)
+#define TAS2559_NONAME18_REG TAS2559_REG(0, 0, 18)
+#define TAS2559_SAR_SAMPLING_TIME_REG TAS2559_REG(0, 0, 19)
+#define TAS2559_SAR_ADC1_REG TAS2559_REG(0, 0, 20)
+#define TAS2559_SAR_ADC2_REG TAS2559_REG(0, 0, 21) /* B0_P0_R0x15 */
+#define TAS2559_CRC_CHECKSUM_REG TAS2559_REG(0, 0, 32) /* B0_P0_R0x20 */
+#define TAS2559_CRC_RESET_REG TAS2559_REG(0, 0, 33) /* B0_P0_R0x21 */
+#define TAS2559_DSP_MODE_SELECT_REG TAS2559_REG(0, 0, 34)
+#define TAS2559_SAFE_GUARD_REG TAS2559_REG(0, 0, 37) /* B0_P0_R0x25 */
+#define TAS2559_ASI_CTRL_REG TAS2559_REG(0, 0, 42)
+#define TAS2559_CLK_ERR_CTRL TAS2559_REG(0, 0, 44) /* B0_P0_R0x2c */
+#define TAS2559_CLK_ERR_CTRL2 TAS2559_REG(0, 0, 45) /* B0_P0_R0x2d*/
+#define TAS2559_CLK_ERR_CTRL3 TAS2559_REG(0, 0, 46) /* B0_P0_R0x2e*/
+#define TAS2559_DBOOST_CFG_REG TAS2559_REG(0, 0, 52)
+#define TAS2559_POWER_UP_FLAG_REG TAS2559_REG(0, 0, 100) /* B0_P0_R0x64 */
+#define TAS2559_FLAGS_1 TAS2559_REG(0, 0, 104) /* B0_P0_R0x68 */
+#define TAS2559_FLAGS_2 TAS2559_REG(0, 0, 108) /* B0_P0_R0x6c */
+
+/* Book0, Page1 registers */
+#define TAS2559_ASI1_DAC_FORMAT_REG TAS2559_REG(0, 1, 1)
+#define TAS2559_ASI1_ADC_FORMAT_REG TAS2559_REG(0, 1, 2)
+#define TAS2559_ASI1_OFFSET1_REG TAS2559_REG(0, 1, 3)
+#define TAS2559_ASI1_ADC_PATH_REG TAS2559_REG(0, 1, 7)
+#define TAS2559_ASI1_DAC_BCLK_REG TAS2559_REG(0, 1, 8)
+#define TAS2559_ASI1_DAC_WCLK_REG TAS2559_REG(0, 1, 9)
+#define TAS2559_ASI1_ADC_BCLK_REG TAS2559_REG(0, 1, 10)
+#define TAS2559_ASI1_ADC_WCLK_REG TAS2559_REG(0, 1, 11)
+#define TAS2559_ASI1_DIN_DOUT_MUX_REG TAS2559_REG(0, 1, 12)
+#define TAS2559_ASI1_BDIV_CLK_SEL_REG TAS2559_REG(0, 1, 13)
+#define TAS2559_ASI1_BDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 14)
+#define TAS2559_ASI1_WDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 15)
+#define TAS2559_ASI1_DAC_CLKOUT_REG TAS2559_REG(0, 1, 16)
+#define TAS2559_ASI1_ADC_CLKOUT_REG TAS2559_REG(0, 1, 17)
+
+#define TAS2559_ASI2_DAC_FORMAT_REG TAS2559_REG(0, 1, 21)
+#define TAS2559_ASI2_ADC_FORMAT_REG TAS2559_REG(0, 1, 22)
+#define TAS2559_ASI2_OFFSET1_REG TAS2559_REG(0, 1, 23)
+#define TAS2559_ASI2_ADC_PATH_REG TAS2559_REG(0, 1, 27)
+#define TAS2559_ASI2_DAC_BCLK_REG TAS2559_REG(0, 1, 28)
+#define TAS2559_ASI2_DAC_WCLK_REG TAS2559_REG(0, 1, 29)
+#define TAS2559_ASI2_ADC_BCLK_REG TAS2559_REG(0, 1, 30)
+#define TAS2559_ASI2_ADC_WCLK_REG TAS2559_REG(0, 1, 31)
+#define TAS2559_ASI2_DIN_DOUT_MUX_REG TAS2559_REG(0, 1, 32)
+#define TAS2559_ASI2_BDIV_CLK_SEL_REG TAS2559_REG(0, 1, 33)
+#define TAS2559_ASI2_BDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 34)
+#define TAS2559_ASI2_WDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 35)
+#define TAS2559_ASI2_DAC_CLKOUT_REG TAS2559_REG(0, 1, 36)
+#define TAS2559_ASI2_ADC_CLKOUT_REG TAS2559_REG(0, 1, 37)
+
+#define TAS2559_GPIO1_PIN_REG TAS2559_REG(0, 1, 61) /* B0_P1_R0x3d */
+#define TAS2559_GPIO2_PIN_REG TAS2559_REG(0, 1, 62) /* B0_P1_R0x3e */
+#define TAS2559_GPIO3_PIN_REG TAS2559_REG(0, 1, 63)
+#define TAS2559_GPIO4_PIN_REG TAS2559_REG(0, 1, 64)
+#define TAS2559_GPIO5_PIN_REG TAS2559_REG(0, 1, 65)
+#define TAS2559_GPIO6_PIN_REG TAS2559_REG(0, 1, 66)
+#define TAS2559_GPIO7_PIN_REG TAS2559_REG(0, 1, 67)
+#define TAS2559_GPIO8_PIN_REG TAS2559_REG(0, 1, 68)
+#define TAS2559_GPIO9_PIN_REG TAS2559_REG(0, 1, 69)
+#define TAS2559_GPIO10_PIN_REG TAS2559_REG(0, 1, 70)
+
+#define TAS2559_GPI_PIN_REG TAS2559_REG(0, 1, 77) /* B0_P1_R0x4d */
+#define TAS2559_GPIO_HIZ_CTRL1_REG TAS2559_REG(0, 1, 79)
+#define TAS2559_GPIO_HIZ_CTRL2_REG TAS2559_REG(0, 1, 80) /* B0_P1_R0x50 */
+#define TAS2559_GPIO_HIZ_CTRL3_REG TAS2559_REG(0, 1, 81)
+#define TAS2559_GPIO_HIZ_CTRL4_REG TAS2559_REG(0, 1, 82)
+#define TAS2559_GPIO_HIZ_CTRL5_REG TAS2559_REG(0, 1, 83)
+
+#define TAS2559_BIT_BANG_CTRL_REG TAS2559_REG(0, 1, 87)
+#define TAS2559_BIT_BANG_OUT1_REG TAS2559_REG(0, 1, 88)
+#define TAS2559_BIT_BANG_OUT2_REG TAS2559_REG(0, 1, 89)
+#define TAS2559_BIT_BANG_IN1_REG TAS2559_REG(0, 1, 90)
+#define TAS2559_BIT_BANG_IN2_REG TAS2559_REG(0, 1, 91)
+#define TAS2559_BIT_BANG_IN3_REG TAS2559_REG(0, 1, 92)
+
+#define TAS2559_PDM_IN_CLK_REG TAS2559_REG(0, 1, 94)
+#define TAS2559_PDM_IN_PIN_REG TAS2559_REG(0, 1, 95)
+
+#define TAS2559_ASIM_IFACE1_REG TAS2559_REG(0, 1, 98)
+#define TAS2559_ASIM_FORMAT_REG TAS2559_REG(0, 1, 99)
+#define TAS2559_ASIM_IFACE3_REG TAS2559_REG(0, 1, 100)
+#define TAS2559_ASIM_IFACE4_REG TAS2559_REG(0, 1, 101)
+#define TAS2559_ASIM_IFACE5_REG TAS2559_REG(0, 1, 102)
+#define TAS2559_ASIM_IFACE6_REG TAS2559_REG(0, 1, 103)
+#define TAS2559_ASIM_IFACE7_REG TAS2559_REG(0, 1, 104)
+#define TAS2559_ASIM_IFACE8_REG TAS2559_REG(0, 1, 105)
+#define TAS2559_CLK_HALT_REG TAS2559_REG(0, 1, 106) /* B0_P1_R0x6a */
+#define TAS2559_INT_GEN1_REG TAS2559_REG(0, 1, 108) /* B0_P1_R0x6c */
+#define TAS2559_INT_GEN2_REG TAS2559_REG(0, 1, 109) /* B0_P1_R0x6d */
+#define TAS2559_INT_GEN3_REG TAS2559_REG(0, 1, 110) /* B0_P1_R0x6e */
+#define TAS2559_INT_GEN4_REG TAS2559_REG(0, 1, 111) /* B0_P1_R0x6f */
+#define TAS2559_INT_MODE_REG TAS2559_REG(0, 1, 114) /* B0_P1_R0x72 */
+#define TAS2559_MAIN_CLKIN_REG TAS2559_REG(0, 1, 115)
+#define TAS2559_PLL_CLKIN_REG TAS2559_REG(0, 1, 116)
+#define TAS2559_CLKOUT_MUX_REG TAS2559_REG(0, 1, 117)
+#define TAS2559_CLKOUT_CDIV_REG TAS2559_REG(0, 1, 118)
+#define TAS2559_HACK_GP01_REG TAS2559_REG(0, 1, 122)
+
+#define TAS2559_SLEEPMODE_CTL_REG TAS2559_REG(0, 2, 7)
+#define TAS2559_HACK01_REG TAS2559_REG(0, 2, 10)
+
+#define TAS2559_ISENSE_THRESHOLD TAS2559_REG(0, 50, 104)
+#define TAS2559_BOOSTON_EFFICIENCY TAS2559_REG(0, 51, 16)
+#define TAS2559_BOOSTOFF_EFFICIENCY TAS2559_REG(0, 51, 20)
+#define TAS2559_BOOST_HEADROOM TAS2559_REG(0, 51, 24)
+#define TAS2559_THERMAL_FOLDBACK_REG TAS2559_REG(0, 51, 100)
+
+#define TAS2559_SA_CHL_CTRL_REG TAS2559_REG(0, 53, 20) /* B0_P0x35_R0x14 */
+#define TAS2559_VPRED_COMP_REG TAS2559_REG(0, 53, 24)
+#define TAS2559_SA_COEFF_SWAP_REG TAS2559_REG(0, 53, 44) /* B0_P0x35_R0x2c */
+
+#define TAS2559_TEST_MODE_REG TAS2559_REG(0, 253, 13)
+#define TAS2559_BROADCAST_REG TAS2559_REG(0, 253, 54)
+#define TAS2559_VBST_VOLT_REG TAS2559_REG(0, 253, 58)/* B0_P0xfd_R0x3a */
+#define TAS2559_CRYPTIC_REG TAS2559_REG(0, 253, 71)
+
+#define TAS2559_DAC_INTERPOL_REG TAS2559_REG(100, 0, 1)
+#define TAS2559_SOFT_MUTE_REG TAS2559_REG(100, 0, 7)
+#define TAS2559_PLL_P_VAL_REG TAS2559_REG(100, 0, 27)
+#define TAS2559_PLL_J_VAL_REG TAS2559_REG(100, 0, 28)
+#define TAS2559_PLL_D_VAL_MSB_REG TAS2559_REG(100, 0, 29)
+#define TAS2559_PLL_D_VAL_LSB_REG TAS2559_REG(100, 0, 30)
+#define TAS2559_CLK_MISC_REG TAS2559_REG(100, 0, 31)
+#define TAS2559_PLL_N_VAL_REG TAS2559_REG(100, 0, 32)
+#define TAS2559_DAC_MADC_VAL_REG TAS2559_REG(100, 0, 33)
+#define TAS2559_ISENSE_DIV_REG TAS2559_REG(100, 0, 42)
+#define TAS2559_RAMP_CLK_DIV_MSB_REG TAS2559_REG(100, 0, 43)
+#define TAS2559_RAMP_CLK_DIV_LSB_REG TAS2559_REG(100, 0, 44)
+#define TAS2559_VBOOST_CTL_REG TAS2559_REG(100, 0, 64) /* B0x64_P0x00_R0x40 */
+
+#define TAS2559_DIE_TEMP_REG TAS2559_REG(130, 2, 124) /* B0x82_P0x02_R0x7C */
+#define TAS2559_DEVA_CALI_R0_REG TAS2559_REG(140, 47, 40) /* B0x8c_P0x2f_R0x28 */
+#define TAS2559_DEVB_CALI_R0_REG TAS2559_REG(140, 54, 12) /* B0x8c_P0x36_R0x0c */
+
+/* Bits */
+/* B0P0R4 - TAS2559_POWER_CTRL1_REG */
+#define TAS2559_SW_SHUTDOWN (0x1 << 0)
+#define TAS2559_MADC_POWER_UP (0x1 << 3)
+#define TAS2559_MDAC_POWER_UP (0x1 << 4)
+#define TAS2559_NDIV_POWER_UP (0x1 << 5)
+#define TAS2559_PLL_POWER_UP (0x1 << 6)
+#define TAS2559_DSP_POWER_UP (0x1 << 7)
+
+/* B0P0R5 - TAS2559_POWER_CTRL2_REG */
+#define TAS2559_VSENSE_ENABLE (0x1 << 0)
+#define TAS2559_ISENSE_ENABLE (0x1 << 1)
+#define TAS2559_BOOST_ENABLE (0x1 << 5)
+#define TAS2559_CLASSD_ENABLE (0x1 << 7)
+
+/* B0P0R7 - TAS2559_MUTE_REG */
+#define TAS2559_CLASSD_MUTE (0x1 << 0)
+#define TAS2559_ISENSE_MUTE (0x1 << 1)
+
+/* B0P253R13 - TAS2559_TEST_MODE_REG */
+#define TAS2559_TEST_MODE_ENABLE (13)
+#define TAS2559_TEST_MODE_MASK (0xf << 0)
+
+/* B0P253R71 - TAS2559_CRYPTIC_REG */
+#define TAS2559_OSC_TRIM_CAP(x) ((x & 0x3f) << 0)
+#define TAS2559_DISABLE_ENCRYPTION (0x1 << 6)
+#define TAS2559_SL_COMP (0x1 << 7)
+
+/* B0P1R115/6 - TAS2559_MAIN/PLL_CLKIN_REG */
+#define TAS2559_XXX_CLKIN_GPIO1 (0)
+#define TAS2559_XXX_CLKIN_GPIO2 (1)
+#define TAS2559_XXX_CLKIN_GPIO3 (2)
+#define TAS2559_XXX_CLKIN_GPIO4 (3)
+#define TAS2559_XXX_CLKIN_GPIO5 (4)
+#define TAS2559_XXX_CLKIN_GPIO6 (5)
+#define TAS2559_XXX_CLKIN_GPIO7 (6)
+#define TAS2559_XXX_CLKIN_GPIO8 (7)
+#define TAS2559_XXX_CLKIN_GPIO9 (8)
+#define TAS2559_XXX_CLKIN_GPIO10 (9)
+#define TAS2559_XXX_CLKIN_GPI1 (12)
+#define TAS2559_XXX_CLKIN_GPI2 (13)
+#define TAS2559_XXX_CLKIN_GPI3 (14)
+#define TAS2559_NDIV_CLKIN_PLL (15)
+#define TAS2559_PLL_CLKIN_INT_OSC (15)
+
+#define TAS2559_MCLK_CLKIN_SRC_GPIO1 (0)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO2 (1)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO3 (2)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO4 (3)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO5 (4)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO6 (5)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO7 (6)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO8 (7)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO9 (8)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO10 (9)
+#define TAS2559_MCLK_CLKIN_SRC_GPI1 (12)
+#define TAS2559_MCLK_CLKIN_SRC_GPI2 (13)
+#define TAS2559_MCLK_CLKIN_SRC_GPI3 (14)
+
+#define TAS2559_FORMAT_I2S (0x0 << 5)
+#define TAS2559_FORMAT_DSP (0x1 << 5)
+#define TAS2559_FORMAT_RIGHT_J (0x2 << 5)
+#define TAS2559_FORMAT_LEFT_J (0x3 << 5)
+#define TAS2559_FORMAT_MONO_PCM (0x4 << 5)
+#define TAS2559_FORMAT_MASK (0x7 << 5)
+
+#define TAS2559_WORDLENGTH_16BIT (0x0 << 3)
+#define TAS2559_WORDLENGTH_20BIT (0x1 << 3)
+#define TAS2559_WORDLENGTH_24BIT (0x2 << 3)
+#define TAS2559_WORDLENGTH_32BIT (0x3 << 3)
+#define TAS2559_WORDLENGTH_MASK TAS2559_WORDLENGTH_32BIT
+
+/* B100P0R7 - TAS2559_SOFT_MUTE_REG */
+#define TAS2559_PDM_SOFT_MUTE (0x1 << 0)
+#define TAS2559_VSENSE_SOFT_MUTE (0x1 << 1)
+#define TAS2559_ISENSE_SOFT_MUTE (0x1 << 2)
+#define TAS2559_CLASSD_SOFT_MUTE (0x1 << 3)
+
+/* B100P0R27 - TAS2559_PLL_P_VAL_REG */
+#define TAS2559_PLL_P_VAL_MASK (0x3f << 0)
+
+/* B100P0R28 - TAS2559_PLL_J_VAL_REG */
+#define TAS2559_PLL_J_VAL_MASK ((unsigned int) (0x7f << 0))
+#define TAS2559_PLL_J_VAL_MASKX 0x00
+
+/* B100P0R29-30 - TAS2559_PLL_D_VAL_MSB/LSB_REG */
+#define TAS2559_PLL_D_MSB_VAL(x) ((x >> 8) & 0x3f)
+#define TAS2559_PLL_D_LSB_VAL(x) (x & 0xff)
+
+/* B100P0R31 - TAS2559_CLK_MISC_REG */
+#define TAS2559_DSP_CLK_FROM_PLL (0x1 << 5)
+
+#define TAS2559_FW_NAME "tas2559_uCDSP.bin"
+
+#define CHANNEL_LEFT (0)
+#define CHANNEL_RIGHT (1)
+
+#define TAS2559_APP_ROM1MODE 0
+#define TAS2559_APP_ROM2MODE 1
+#define TAS2559_APP_TUNINGMODE 2
+#define TAS2559_APP_ROM1_96KHZ 3
+#define TAS2559_APP_ROM2_96KHZ 4
+#define TAS2559_APP_RAMMODE 5
+
+#define TAS2559_BOOST_OFF 0
+#define TAS2559_BOOST_DEVA 1
+#define TAS2559_BOOST_DEVB 2
+#define TAS2559_BOOST_BOTH 3
+
+#define TAS2559_AD_BD 0 /* DevA default, DevB default */
+#define TAS2559_AM_BM 1 /* DevA mute, DevB mute */
+#define TAS2559_AL_BR 2 /* DevA left channel, DevB right channel */
+#define TAS2559_AR_BL 3 /* DevA right channel, DevB left channel */
+#define TAS2559_AH_BH 4 /* DevA (L+R)/2, DevB (L+R)/2 */
+
+#define TAS2559_VBST_DEFAULT 0 /* firmware default */
+#define TAS2559_VBST_A_ON 1 /* DevA always 8.5V, DevB default */
+#define TAS2559_VBST_B_ON 2 /* DevA default, DevB always 8.5V */
+#define TAS2559_VBST_A_ON_B_ON (TAS2559_VBST_A_ON | TAS2559_VBST_B_ON) /* both DevA and DevB always 8.5V */
+#define TAS2559_VBST_NEED_DEFAULT 0xff /* need default value */
+
+#define TAS2559_VBST_8P5V 0 /* coresponding PPG 0dB */
+#define TAS2559_VBST_8P1V 1 /* coresponding PPG -1dB */
+#define TAS2559_VBST_7P6V 2 /* coresponding PPG -2dB */
+#define TAS2559_VBST_6P6V 3 /* coresponding PPG -3dB */
+#define TAS2559_VBST_5P6V 4 /* coresponding PPG -4dB */
+
+#define TAS2559_YRAM_BOOK1 140 /* 0x8c */
+
+#define TAS2559_YRAM1_PAGE 42 /* 0x2a */
+#define TAS2559_YRAM1_START_REG 88
+#define TAS2559_YRAM1_END_REG 127
+
+#define TAS2559_YRAM2_START_PAGE 43 /* 0x2b */
+#define TAS2559_YRAM2_END_PAGE 55
+#define TAS2559_YRAM2_START_REG 8
+#define TAS2559_YRAM2_END_REG 127
+
+#define TAS2559_YRAM3_PAGE 56 /* 0x38 */
+#define TAS2559_YRAM3_START_REG 8
+#define TAS2559_YRAM3_END_REG 47
+
+/* should not include B0_P53_R44-R47 */
+#define TAS2559_YRAM_BOOK2 0
+#define TAS2559_YRAM4_START_PAGE 50 /* 0x32 */
+#define TAS2559_YRAM4_END_PAGE 60 /* 0x3c */
+#define TAS2559_YRAM4_START_REG 8
+#define TAS2559_YRAM4_END_REG 127
+
+#define TAS2559_YRAM5_PAGE 61 /* 0x3d */
+#define TAS2559_YRAM5_START_REG 8
+#define TAS2559_YRAM5_END_REG 27
+
+#define TAS2559_YRAM_BOOK3 120 /* 0x78 */
+#define TAS2559_YRAM6_PAGE 12 /* 0x0c */
+#define TAS2559_YRAM6_START_REG 104 /* 0x68 */
+#define TAS2559_YRAM6_END_REG 107 /* 0x6b */
+
+#define TAS2559_SAFE_GUARD_PATTERN 0x5a
+#define LOW_TEMPERATURE_CHECK_PERIOD 5000 /* 5 second */
+
+/* Page Control Register */
+#define TAS2560_PAGECTL_REG 0
+
+/* Book Control Register (available in page0 of each book) */
+#define TAS2560_BOOKCTL_PAGE 0
+#define TAS2560_BOOKCTL_REG 127
+
+#define TAS2560_REG(book, page, reg) (((book * 256 * 128) + \
+ (page * 128)) + reg)
+
+#define TAS2560_BOOK_ID(reg) (reg / (256 * 128))
+#define TAS2560_PAGE_ID(reg) ((reg % (256 * 128)) / 128)
+#define TAS2560_BOOK_REG(reg) (reg % (256 * 128))
+#define TAS2560_PAGE_REG(reg) ((reg % (256 * 128)) % 128)
+
+/* Book0, Page0 registers */
+#define TAS2560_SW_RESET_REG TAS2560_REG(0, 0, 1)
+#define TAS2560_DEV_MODE_REG TAS2560_REG(0, 0, 2)
+#define TAS2560_SPK_CTRL_REG TAS2560_REG(0, 0, 4)
+#define TAS2560_MUTE_REG TAS2560_REG(0, 0, 7)
+#define TAS2560_PWR_REG TAS2560_REG(0, 0, 7)
+#define TAS2560_PWR_BIT_MASK (0x3 << 6)
+#define TAS2560_MUTE_MASK (0x7)
+
+#define TAS2560_SR_CTRL1 TAS2560_REG(0, 0, 8)
+#define TAS2560_LOAD TAS2560_REG(0, 0, 9)
+#define TAS2560_SR_CTRL2 TAS2560_REG(0, 0, 13) /*B0_P0_R0x0d*/
+#define TAS2560_SR_CTRL3 TAS2560_REG(0, 0, 14) /*B0_P0_R0x0e*/
+
+#define TAS2560_CLK_SEL TAS2560_REG(0, 0, 15)
+#define TAS2560_PLL_SRC_MASK (0xc0)
+#define TAS2560_PLL_CLKIN_BCLK (0)
+#define TAS2560_PLL_CLKIN_MCLK (1)
+#define TAS2560_PLL_CLKIN_PDMCLK (2)
+#define TAS2560_PLL_P_MASK (0x3f)
+
+#define TAS2560_SET_FREQ TAS2560_REG(0, 0, 16)
+#define TAS2560_PLL_J_MASK (0x7f)
+
+#define TAS2560_PLL_D_MSB TAS2560_REG(0, 0, 17) /*B0_P0_R0x11*/
+#define TAS2560_PLL_D_LSB TAS2560_REG(0, 0, 18) /*B0_P0_R0x12*/
+
+#define TAS2560_DAI_FMT TAS2560_REG(0, 0, 20) /* B0_P0_R0x14 */
+#define TAS2560_ASI_CTRL TAS2560_REG(0, 0, 21) /* B0_P0_R0x15 */
+#define TAS2560_ASI_OFFSET_1 TAS2560_REG(0, 0, 22) /*B0_P0_R0x16*/
+#define TAS2560_ASI_CFG_1 TAS2560_REG(0, 0, 24) /* B0_P0_R0x18 */
+#define TAS2560_DIRINV_MASK 0x3c
+#define TAS2560_BCLKINV (1 << 2)
+#define TAS2560_WCLKINV (1 << 3)
+#define TAS2560_BCLKDIR (1 << 4)
+#define TAS2560_WCLKDIR (1 << 5)
+
+#define TAS2560_CLK_ERR_CTRL TAS2560_REG(0, 0, 33) /* B0_P0_R0x21 */
+#define TAS2560_IRQ_PIN_REG TAS2560_REG(0, 0, 35) /* B0_P0_R0x23 */
+#define TAS2560_INT_MODE_REG TAS2560_REG(0, 0, 36) /* B0_P0_R0x24 */
+#define TAS2560_INT_GEN_REG TAS2560_REG(0, 0, 37) /* B0_P0_R0x25 */
+#define TAS2560_FLAGS_1 TAS2560_REG(0, 0, 38) /* B0_P0_R0x26 */
+#define TAS2560_FLAGS_2 TAS2560_REG(0, 0, 39) /* B0_P0_R0x27 */
+#define TAS2560_POWER_UP_FLAG_REG TAS2560_REG(0, 0, 42) /* B0_P0_R0x2a */
+
+#define TAS2560_DR_BOOST_REG_2 TAS2560_REG(0, 0, 60) /* B0_P0_R0x3c */
+#define TAS2560_DR_BOOST_REG_1 TAS2560_REG(0, 0, 73) /* B0_P0_R0x49 */
+#define TAS2560_VBOOST_CTL_REG TAS2560_REG(0, 0, 79) /* B0_P0_R0x4f */
+#define TAS2560_CLK_ERR_CTRL2 TAS2560_REG(0, 0, 80) /* B0_P0_R0x50 */
+#define TAS2560_SLEEPMODE_CTL_REG TAS2560_REG(0, 0, 84) /* B0_P0_R0x54 */
+#define TAS2560_ID_REG TAS2560_REG(0, 0, 125)
+#define TAS2560_CRC_CHK_REG TAS2560_REG(0, 0, 126) /* B0_P0_R0x7e */
+
+/* Book0, Page50 registers */
+#define TAS2560_HPF_CUTOFF_CTL1 TAS2560_REG(0, 50, 28) /* B0_P0x32_R0x1c */
+#define TAS2560_HPF_CUTOFF_CTL2 TAS2560_REG(0, 50, 32) /* B0_P0x32_R0x20 */
+#define TAS2560_HPF_CUTOFF_CTL3 TAS2560_REG(0, 50, 36) /* B0_P0x32_R0x24 */
+
+#define TAS2560_ISENSE_PATH_CTL1 TAS2560_REG(0, 50, 40) /* B0_P0x32_R0x28 */
+#define TAS2560_ISENSE_PATH_CTL2 TAS2560_REG(0, 50, 44) /* B0_P0x32_R0x2c */
+#define TAS2560_ISENSE_PATH_CTL3 TAS2560_REG(0, 50, 48) /* B0_P0x32_R0x30 */
+
+#define TAS2560_VLIMIT_THRESHOLD TAS2560_REG(0, 50, 60)
+#define TAS2560_IDLE_CHNL_DETECT TAS2560_REG(0, 50, 108) /* B0_P0x32_R0x6c */
+
+/* Book0, Page51 registers */
+#define TAS2560_BOOST_HEAD TAS2560_REG(0, 51, 24) /* B0_P0x33_R0x18 */
+#define TAS2560_BOOST_ON TAS2560_REG(0, 51, 16) /* B0_P0x33_R0x10 */
+#define TAS2560_BOOST_OFF TAS2560_REG(0, 51, 20) /* B0_P0x33_R0x14 */
+#define TAS2560_BOOST_TABLE_CTRL1 TAS2560_REG(0, 51, 32) /* B0_P0x33_R0x20 */
+#define TAS2560_BOOST_TABLE_CTRL2 TAS2560_REG(0, 51, 36) /* B0_P0x33_R0x24 */
+#define TAS2560_BOOST_TABLE_CTRL3 TAS2560_REG(0, 51, 40) /* B0_P0x33_R0x28 */
+#define TAS2560_BOOST_TABLE_CTRL4 TAS2560_REG(0, 51, 44) /* B0_P0x33_R0x2c */
+#define TAS2560_BOOST_TABLE_CTRL5 TAS2560_REG(0, 51, 48) /* B0_P0x33_R0x30 */
+#define TAS2560_BOOST_TABLE_CTRL6 TAS2560_REG(0, 51, 52) /* B0_P0x33_R0x34 */
+#define TAS2560_BOOST_TABLE_CTRL7 TAS2560_REG(0, 51, 56) /* B0_P0x33_R0x38 */
+#define TAS2560_BOOST_TABLE_CTRL8 TAS2560_REG(0, 51, 60) /* B0_P0x33_R0x3c */
+#define TAS2560_THERMAL_FOLDBACK TAS2560_REG(0, 51, 100) /* B0_P0x33_R0x64 */
+
+/* Book0, Page52 registers */
+#define TAS2560_VSENSE_DEL_CTL1 TAS2560_REG(0, 52, 52) /* B0_P0x34_R0x34 */
+#define TAS2560_VSENSE_DEL_CTL2 TAS2560_REG(0, 52, 56) /* B0_P0x34_R0x38 */
+#define TAS2560_VSENSE_DEL_CTL3 TAS2560_REG(0, 52, 60) /* B0_P0x34_R0x3c */
+#define TAS2560_VSENSE_DEL_CTL4 TAS2560_REG(0, 52, 64) /* B0_P0x34_R0x40 */
+#define TAS2560_VSENSE_DEL_CTL5 TAS2560_REG(0, 52, 68) /* B0_P0x34_R0x44 */
+
+#define TAS2560_VBST_VOLT_REG TAS2559_REG(0, 253, 54) /* B0_P0xfd_R0x36 */
+
+#define TAS2560_DATAFORMAT_I2S (0x0 << 2)
+#define TAS2560_DATAFORMAT_DSP (0x1 << 2)
+#define TAS2560_DATAFORMAT_RIGHT_J (0x2 << 2)
+#define TAS2560_DATAFORMAT_LEFT_J (0x3 << 2)
+
+#define TAS2560_DAI_FMT_MASK (0x7 << 2)
+#define LOAD_MASK 0x18
+
+#define TAS2560_YRAM_BOOK 0
+#define TAS2560_YRAM_START_PAGE 50
+#define TAS2560_YRAM_END_PAGE 52
+#define TAS2560_YRAM_START_REG 8
+#define TAS2560_YRAM_END_REG 127
+
+#define ERROR_NONE 0x00000000
+#define ERROR_PLL_ABSENT 0x00000001
+#define ERROR_DEVA_I2C_COMM 0x00000002
+#define ERROR_DEVB_I2C_COMM 0x00000004
+#define ERROR_PRAM_CRCCHK 0x00000008
+#define ERROR_YRAM_CRCCHK 0x00000010
+#define ERROR_CLK_DET2 0x00000020
+#define ERROR_CLK_DET1 0x00000040
+#define ERROR_CLK_LOST 0x00000080
+#define ERROR_BROWNOUT 0x00000100
+#define ERROR_DIE_OVERTEMP 0x00000200
+#define ERROR_CLK_HALT 0x00000400
+#define ERROR_UNDER_VOLTAGE 0x00000800
+#define ERROR_OVER_CURRENT 0x00001000
+#define ERROR_CLASSD_PWR 0x00002000
+#define ERROR_SAFE_GUARD 0x00004000
+#define ERROR_FAILSAFE 0x40000000
+
+#define LOW_TEMPERATURE_GAIN 6
+#define LOW_TEMPERATURE_COUNTER 12
+
+#define RESTART_MAX 3
+
+#define TAS2559_UDELAY 0xFFFFFFFE
+#define TAS2559_MDELAY 0xFFFFFFFD
+
+#define FW_ERR_HEADER -1
+#define FW_ERR_SIZE -2
+
+#define TAS2559_BLOCK_PLL 0x00
+#define TAS2559_BLOCK_PGM_ALL 0x0d
+#define TAS2559_BLOCK_PGM_DEV_A 0x01
+#define TAS2559_BLOCK_PGM_DEV_B 0x08
+#define TAS2559_BLOCK_CFG_COEFF_DEV_A 0x03
+#define TAS2559_BLOCK_CFG_COEFF_DEV_B 0x0a
+#define TAS2559_BLOCK_CFG_PRE_DEV_A 0x04
+#define TAS2559_BLOCK_CFG_PRE_DEV_B 0x0b
+#define TAS2559_BLOCK_CFG_POST 0x05
+#define TAS2559_BLOCK_CFG_POST_POWER 0x06
+#define TAS2559_BLOCK_PST_POWERUP_DEV_B 0x0e
+
+#define PPC_DRIVER_CRCCHK 0x00000200
+#define PPC_DRIVER_CONFDEV 0x00000300
+#define PPC_DRIVER_MTPLLSRC 0x00000400
+#define PPC_DRIVER_CFGDEV_NONCRC 0x00000101
+
+#endif /* _TAS2559_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/config.h b/sound/soc/codecs/tfa98xx-downstream/config.h
new file mode 100644
index 00000000000..847608f0c41
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/config.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+
+/*
+ Linux kernel specific definitions used by code shared with
+ Linux/Windows user space.
+*/
+
+#ifndef __CONFIG_LINUX_KERNEL_INC__
+#define __CONFIG_LINUX_KERNEL_INC__
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/crc32.h>
+#include <linux/ftrace.h>
+
+#define _ASSERT(e)
+#define PRINT_ASSERT(e)if ((e)) printk(KERN_ERR "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+
+#if defined(CONFIG_TRACING) && defined(DEBUG)
+ #define tfa98xx_trace_printk(...) trace_printk(__VA_ARGS__)
+#else
+ #define tfa98xx_trace_printk(...)
+#endif
+
+#endif /* __CONFIG_LINUX_KERNEL_INC__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/dbgprint.h b/sound/soc/codecs/tfa98xx-downstream/dbgprint.h
new file mode 100644
index 00000000000..c0886fb2ff6
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/dbgprint.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#ifndef _DBGPRINT_H
+# define _DBGPRINT_H
+
+/* Debugging macro's. */
+# ifndef DEBUG
+# define DEBUG
+# endif
+
+# ifndef ASSERT
+//#define ASSERT
+# endif
+ //TODO wwwim
+# ifndef _ASSERT
+ #define _ASSERT(e)
+# endif
+
+# ifndef PREFIX
+# define PREFIX "tfa98xx: "
+# define DRIVER_NAME "tfa98xx"
+# endif
+
+#ifdef __KERNEL__
+
+# ifdef DEBUG
+# define _DEBUG(level,fmt,va...) do {\
+ if (unlikely(debug >= (level))) \
+ printk(KERN_INFO PREFIX "%s:%d: "fmt,__func__,__LINE__,##va); \
+ } while (0)
+
+# else
+# define _DEBUG(level,fmt,va...) do {} while(0)
+# endif
+
+# define MSG(fmt,va...) printk(KERN_INFO PREFIX "%s:%d: "fmt,__func__,__LINE__,##va)
+# define _ERRORMSG(fmt,va...) printk(KERN_ERR PREFIX "ERROR %s:%d: "fmt,__func__,__LINE__, ##va)
+
+
+# define DEBUG0(x...) MSG(x)
+# define DEBUG1(x...) _DEBUG(1,x)
+# define DEBUG2(x...) _DEBUG(2,x)
+# define DEBUG3(x...) _DEBUG(3,x)
+# define ERRORMSG(x...) _ERRORMSG(x)
+# define PRINT(x...) printk(x)
+# define PRINT_ERROR(x...) printk(KERN_INFO PREFIX " **ERROR** " x)
+# define PRINT_ASSERT(e)if ((e)) printk(KERN_ERR "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+
+# define PRINT_ENTRY DEBUG2("+[%s]\n", __func__)
+# define PRINT_EXIT DEBUG2("-[%s]\n", __func__)
+
+# ifdef ASSERT
+# define assert(cond,action) do { if (unlikely(!(cond))) { DEBUG0("Assert: %s\n",#cond); action; }} while(0)
+# else
+# define assert(cond,action) do { } while (0)
+# endif
+
+#else /* __KERNEL__ */
+#if defined(WIN32) || defined(_X64)
+#include <stdio.h>
+/* user mode */
+# ifdef DEBUG
+# define _DEBUGMSG(level,fmt,...) printf(PREFIX "%s:%d: "fmt,__FUNCTION__,__LINE__,__VA_ARGS__);
+# else
+# define _DEBUGMSG(level,fmt,...) do {} while(0)
+# endif
+
+# define _ERRORMSG(fmt,...) printf(PREFIX "%s:%s:%d: "fmt,__FILE__,__FUNCTION__,__LINE__,__VA_ARGS__)
+
+# define DEBUG0(...) MSG(__VA_ARGS__)
+# define DEBUG1(...) _DEBUGMSG(1,__VA_ARGS__)
+# define DEBUG2(...) _DEBUGMSG(2,__VA_ARGS__)
+# define DEBUG3(...) _DEBUGMSG(3,__VA_ARGS__)
+# define ERRORMSG(fmt,...) _ERRORMSG(fmt,__VA_ARGS__)
+# define PRINT(...) printf(__VA_ARGS__)
+/*
+# define PRINT(...) { FILE *stream; \
+ if((stream = freopen("tfa_tfa.txt", "ab+", stdout)) == NULL) exit(-1); \
+ printf(__VA_ARGS__); \
+ freopen( "CON", "ab+", stdout ); \
+ }
+*/
+# define PRINT_ERROR(...) fprintf(stderr,__VA_ARGS__)
+# define PRINT_FILE(file,...) fprintf(file,__VA_ARGS__)
+# define PRINT_ASSERT(e)if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+//# define PRINT_ASSERT(e) if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) %s\n",__FUNCTION__,__FILE__,__LINE__, Tfa98xx_GetErrorString(e))
+
+#elif defined(__CODE_RED)
+#include "app_global.h"
+# ifdef DEBUG
+# define _DEBUG(level,fmt,va...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,va))
+//printf(PREFIX "%s:%d: "fmt,__func__,__LINE__,##va);
+# else
+# define _DEBUG(level,fmt,va...) do {} while(0)
+# endif
+
+# define MSG(fmt,...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,__VA_ARGS__))
+//printf(PREFIX "%s:%s:%d: "fmt,__FILE__,__func__,__LINE__,##va)
+//TB_TRACE_INF(TbTracePfx2(APP_PFX,TB_FUNC,"path=%s, chan=%u, muted=%s, vol=%d\n",
+// path->isRecording ? "recording" : "playback",
+// i,
+// channelVol.currentMuteValue ? "YES" : "NO",
+// channelVol.currentVolumeValue
+// ));
+//# define _ERRORMSG(fmt,va...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,va))
+# define ERRORMSG(...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,__VA_ARGS__))
+//fprintf(stderr, PREFIX "ERROR %s:%s:%d: "fmt,__FILE__,__func__,__LINE__, ##va)
+
+# define DEBUG0(x...) MSG(x)
+# define DEBUG1(x...) _DEBUG(1,x)
+# define DEBUG2(x...) _DEBUG(2,x)
+# define DEBUG3(x...) _DEBUG(3,x)
+//# define ERRORMSG(x...) _ERRORMSG(x)
+# define PRINT(x...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,x))
+//printf(x)
+# define PRINT_ERROR(x...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,x))
+//fprintf(stderr,__VA_ARGS__)
+# define PRINT_FILE(file,x...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,x))
+//fprintf(file,__VA_ARGS__)
+# define PRINT_ASSERT(e)
+//TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,Tfa98xx_GetErrorString(e)))
+//if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) %s\n",__FUNCTION__,__FILE__,__LINE__, Tfa98xx_GetErrorString(e))
+#else
+#include <stdio.h>
+/* user mode */
+# ifdef DEBUG
+# define _DEBUG(level,fmt,va...) printf(PREFIX "%s:%d: "fmt,__func__,__LINE__,##va);
+# else
+# define _DEBUG(level,fmt,va...) do {} while(0)
+# endif
+
+# define MSG(fmt,va...) printf(PREFIX "%s:%s:%d: "fmt,__FILE__,__func__,__LINE__,##va)
+# define _ERRORMSG(fmt,va...) fprintf(stderr, PREFIX "ERROR %s:%s:%d: "fmt,__FILE__,__func__,__LINE__, ##va)
+
+# define DEBUG0(x...) MSG(x)
+# define DEBUG1(x...) _DEBUG(1,x)
+# define DEBUG2(x...) _DEBUG(2,x)
+# define DEBUG3(x...) _DEBUG(3,x)
+# define ERRORMSG(x...) _ERRORMSG(x)
+# define PRINT(x...) printf(x)
+# define PRINT_ERROR(...) fprintf(stderr,__VA_ARGS__)
+# define PRINT_FILE(file,...) fprintf(file,__VA_ARGS__)
+# define PRINT_ASSERT(e)if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+//# define PRINT_ASSERT(e) if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) %s\n",__FUNCTION__,__FILE__,__LINE__, Tfa98xx_GetErrorString(e))
+
+
+#endif /* WIN32 */
+
+#endif /* user */
+
+#endif /* _DBGPRINT_H --------------- */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa.h b/sound/soc/codecs/tfa98xx-downstream/tfa.h
new file mode 100644
index 00000000000..71faf323562
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#ifndef TFA_H_
+#define TFA_H_
+
+/* set the limit for the container file length */
+#define TFA_MAX_CNT_LENGTH (256*1024)
+
+extern struct tfa_device **devs;
+
+/**
+ * tfa error return codes
+ */
+enum tfa_error {
+ tfa_error_ok, /**< no error */
+ tfa_error_device, /**< no response from device */
+ tfa_error_bad_param,/**< parameter no accepted */
+ tfa_error_noclock, /**< required clock not present */
+ tfa_error_timeout, /**< a timeout occurred */
+ tfa_error_dsp, /**< a DSP error was returned */
+ tfa_error_container,/**< no or wrong container file */
+ tfa_error_max /**< impossible value, max enum */
+};
+
+enum Tfa98xx_Error tfa_write_filters(struct tfa_device *tfa, int prof_idx);
+
+struct tfa_device ** tfa_devs_create(int count);
+void tfa_devs_destroy(int count);
+
+struct tfa_device ** tfa_get_device_struct(void);
+
+int tfa_plop_noise_interrupt(struct tfa_device *tfa, int profile, int vstep);
+void tfa_lp_mode_interrupt(struct tfa_device *tfa);
+void tfa_adapt_noisemode(struct tfa_device *tfa);
+
+#endif /* TFA_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa1_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa1_tfafieldnames.h
new file mode 100644
index 00000000000..400716de139
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa1_tfafieldnames.h
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa1_TfaFieldnames.h
+ * This file was generated automatically on 03/20/2015 at 01:55:46 PM.
+ * Source file: TFA9897N1B_I2C_list_URT_Source_v34.xls
+ */
+#define TFA9897_I2CVERSION 34
+typedef enum Tfa1BfEnumList {
+ TFA1_BF_VDDS = 0x0000, /*!< Power-on-reset flag */
+ TFA1_BF_PLLS = 0x0010, /*!< PLL lock */
+ TFA1_BF_OTDS = 0x0020, /*!< Over Temperature Protection alarm */
+ TFA1_BF_OVDS = 0x0030, /*!< Over Voltage Protection alarm */
+ TFA1_BF_UVDS = 0x0040, /*!< Under Voltage Protection alarm */
+ TFA1_BF_OCDS = 0x0050, /*!< Over Current Protection alarm */
+ TFA1_BF_CLKS = 0x0060, /*!< Clocks stable flag */
+ TFA1_BF_CLIPS = 0x0070, /*!< Amplifier clipping */
+ TFA1_BF_MTPB = 0x0080, /*!< MTP busy */
+ TFA1_BF_NOCLK = 0x0090, /*!< Flag lost clock from clock generation unit */
+ TFA1_BF_SPKS = 0x00a0, /*!< Speaker error flag */
+ TFA1_BF_ACS = 0x00b0, /*!< Cold Start flag */
+ TFA1_BF_SWS = 0x00c0, /*!< Flag Engage */
+ TFA1_BF_WDS = 0x00d0, /*!< Flag watchdog reset */
+ TFA1_BF_AMPS = 0x00e0, /*!< Amplifier is enabled by manager */
+ TFA1_BF_AREFS = 0x00f0, /*!< References are enabled by manager */
+ TFA1_BF_BATS = 0x0109, /*!< Battery voltage readout; 0 .. 5.5 [V] */
+ TFA1_BF_TEMPS = 0x0208, /*!< Temperature readout from the temperature sensor */
+ TFA1_BF_REV = 0x030b, /*!< Device type number is B97 */
+ TFA1_BF_RCV = 0x0420, /*!< Enable Receiver Mode */
+ TFA1_BF_CHS12 = 0x0431, /*!< Channel Selection TDM input for Coolflux */
+ TFA1_BF_INPLVL= 0x0450, /*!< Input level selection control */
+ TFA1_BF_CHSA = 0x0461, /*!< Input selection for amplifier */
+ TFA1_BF_I2SDOE= 0x04b0, /*!< Enable data output */
+ TFA1_BF_AUDFS = 0x04c3, /*!< Audio sample rate setting */
+ TFA1_BF_BSSCR = 0x0501, /*!< Protection Attack Time */
+ TFA1_BF_BSST = 0x0523, /*!< ProtectionThreshold */
+ TFA1_BF_BSSRL = 0x0561, /*!< Protection Maximum Reduction */
+ TFA1_BF_BSSRR = 0x0582, /*!< Battery Protection Release Time */
+ TFA1_BF_BSSHY = 0x05b1, /*!< Battery Protection Hysteresis */
+ TFA1_BF_BSSR = 0x05e0, /*!< battery voltage for I2C read out only */
+ TFA1_BF_BSSBY = 0x05f0, /*!< bypass clipper battery protection */
+ TFA1_BF_DPSA = 0x0600, /*!< Enable dynamic powerstage activation */
+ TFA1_BF_CFSM = 0x0650, /*!< Soft mute in CoolFlux */
+ TFA1_BF_BSSS = 0x0670, /*!< BatSenseSteepness */
+ TFA1_BF_VOL = 0x0687, /*!< volume control (in CoolFlux) */
+ TFA1_BF_DCVO = 0x0702, /*!< Boost Voltage */
+ TFA1_BF_DCMCC = 0x0733, /*!< Max boost coil current - step of 175 mA */
+ TFA1_BF_DCIE = 0x07a0, /*!< Adaptive boost mode */
+ TFA1_BF_DCSR = 0x07b0, /*!< Soft RampUp/Down mode for DCDC controller */
+ TFA1_BF_DCPAVG= 0x07c0, /*!< ctrl_peak2avg for analog part of DCDC */
+ TFA1_BF_TROS = 0x0800, /*!< Select external temperature also the ext_temp will be put on the temp read out */
+ TFA1_BF_EXTTS = 0x0818, /*!< external temperature setting to be given by host */
+ TFA1_BF_PWDN = 0x0900, /*!< Device Mode */
+ TFA1_BF_I2CR = 0x0910, /*!< I2C Reset */
+ TFA1_BF_CFE = 0x0920, /*!< Enable CoolFlux */
+ TFA1_BF_AMPE = 0x0930, /*!< Enable Amplifier */
+ TFA1_BF_DCA = 0x0940, /*!< EnableBoost */
+ TFA1_BF_SBSL = 0x0950, /*!< Coolflux configured */
+ TFA1_BF_AMPC = 0x0960, /*!< Selection on how Amplifier is enabled */
+ TFA1_BF_DCDIS = 0x0970, /*!< DCDC not connected */
+ TFA1_BF_PSDR = 0x0980, /*!< IDDQ test amplifier */
+ TFA1_BF_DCCV = 0x0991, /*!< Coil Value */
+ TFA1_BF_CCFD = 0x09b0, /*!< Selection CoolFlux Clock */
+ TFA1_BF_INTPAD= 0x09c1, /*!< INT pad configuration control */
+ TFA1_BF_IPLL = 0x09e0, /*!< PLL input reference clock selection */
+ TFA1_BF_MTPK = 0x0b07, /*!< 5Ah, 90d To access KEY1_Protected registers (Default for engineering) */
+ TFA1_BF_CVFDLY= 0x0c25, /*!< Fractional delay adjustment between current and voltage sense */
+ TFA1_BF_TDMPRF= 0x1011, /*!< TDM_usecase */
+ TFA1_BF_TDMEN = 0x1030, /*!< TDM interface control */
+ TFA1_BF_TDMCKINV= 0x1040, /*!< TDM clock inversion */
+ TFA1_BF_TDMFSLN= 0x1053, /*!< TDM FS length */
+ TFA1_BF_TDMFSPOL= 0x1090, /*!< TDM FS polarity */
+ TFA1_BF_TDMSAMSZ= 0x10a4, /*!< TDM Sample Size for all tdm sinks/sources */
+ TFA1_BF_TDMSLOTS= 0x1103, /*!< Number of slots */
+ TFA1_BF_TDMSLLN= 0x1144, /*!< Slot length */
+ TFA1_BF_TDMBRMG= 0x1194, /*!< Bits remaining */
+ TFA1_BF_TDMDDEL= 0x11e0, /*!< Data delay */
+ TFA1_BF_TDMDADJ= 0x11f0, /*!< Data adjustment */
+ TFA1_BF_TDMTXFRM= 0x1201, /*!< TXDATA format */
+ TFA1_BF_TDMUUS0= 0x1221, /*!< TXDATA format unused slot sd0 */
+ TFA1_BF_TDMUUS1= 0x1241, /*!< TXDATA format unused slot sd1 */
+ TFA1_BF_TDMSI0EN= 0x1270, /*!< TDM sink0 enable */
+ TFA1_BF_TDMSI1EN= 0x1280, /*!< TDM sink1 enable */
+ TFA1_BF_TDMSI2EN= 0x1290, /*!< TDM sink2 enable */
+ TFA1_BF_TDMSO0EN= 0x12a0, /*!< TDM source0 enable */
+ TFA1_BF_TDMSO1EN= 0x12b0, /*!< TDM source1 enable */
+ TFA1_BF_TDMSO2EN= 0x12c0, /*!< TDM source2 enable */
+ TFA1_BF_TDMSI0IO= 0x12d0, /*!< tdm_sink0_io */
+ TFA1_BF_TDMSI1IO= 0x12e0, /*!< tdm_sink1_io */
+ TFA1_BF_TDMSI2IO= 0x12f0, /*!< tdm_sink2_io */
+ TFA1_BF_TDMSO0IO= 0x1300, /*!< tdm_source0_io */
+ TFA1_BF_TDMSO1IO= 0x1310, /*!< tdm_source1_io */
+ TFA1_BF_TDMSO2IO= 0x1320, /*!< tdm_source2_io */
+ TFA1_BF_TDMSI0SL= 0x1333, /*!< sink0_slot [GAIN IN] */
+ TFA1_BF_TDMSI1SL= 0x1373, /*!< sink1_slot [CH1 IN] */
+ TFA1_BF_TDMSI2SL= 0x13b3, /*!< sink2_slot [CH2 IN] */
+ TFA1_BF_TDMSO0SL= 0x1403, /*!< source0_slot [GAIN OUT] */
+ TFA1_BF_TDMSO1SL= 0x1443, /*!< source1_slot [Voltage Sense] */
+ TFA1_BF_TDMSO2SL= 0x1483, /*!< source2_slot [Current Sense] */
+ TFA1_BF_NBCK = 0x14c3, /*!< NBCK */
+ TFA1_BF_INTOVDDS= 0x2000, /*!< flag_por_int_out */
+ TFA1_BF_INTOPLLS= 0x2010, /*!< flag_pll_lock_int_out */
+ TFA1_BF_INTOOTDS= 0x2020, /*!< flag_otpok_int_out */
+ TFA1_BF_INTOOVDS= 0x2030, /*!< flag_ovpok_int_out */
+ TFA1_BF_INTOUVDS= 0x2040, /*!< flag_uvpok_int_out */
+ TFA1_BF_INTOOCDS= 0x2050, /*!< flag_ocp_alarm_int_out */
+ TFA1_BF_INTOCLKS= 0x2060, /*!< flag_clocks_stable_int_out */
+ TFA1_BF_INTOCLIPS= 0x2070, /*!< flag_clip_int_out */
+ TFA1_BF_INTOMTPB= 0x2080, /*!< mtp_busy_int_out */
+ TFA1_BF_INTONOCLK= 0x2090, /*!< flag_lost_clk_int_out */
+ TFA1_BF_INTOSPKS= 0x20a0, /*!< flag_cf_speakererror_int_out */
+ TFA1_BF_INTOACS= 0x20b0, /*!< flag_cold_started_int_out */
+ TFA1_BF_INTOSWS= 0x20c0, /*!< flag_engage_int_out */
+ TFA1_BF_INTOWDS= 0x20d0, /*!< flag_watchdog_reset_int_out */
+ TFA1_BF_INTOAMPS= 0x20e0, /*!< flag_enbl_amp_int_out */
+ TFA1_BF_INTOAREFS= 0x20f0, /*!< flag_enbl_ref_int_out */
+ TFA1_BF_INTOACK= 0x2201, /*!< Interrupt status register output - Corresponding flag */
+ TFA1_BF_INTIVDDS= 0x2300, /*!< flag_por_int_in */
+ TFA1_BF_INTIPLLS= 0x2310, /*!< flag_pll_lock_int_in */
+ TFA1_BF_INTIOTDS= 0x2320, /*!< flag_otpok_int_in */
+ TFA1_BF_INTIOVDS= 0x2330, /*!< flag_ovpok_int_in */
+ TFA1_BF_INTIUVDS= 0x2340, /*!< flag_uvpok_int_in */
+ TFA1_BF_INTIOCDS= 0x2350, /*!< flag_ocp_alarm_int_in */
+ TFA1_BF_INTICLKS= 0x2360, /*!< flag_clocks_stable_int_in */
+ TFA1_BF_INTICLIPS= 0x2370, /*!< flag_clip_int_in */
+ TFA1_BF_INTIMTPB= 0x2380, /*!< mtp_busy_int_in */
+ TFA1_BF_INTINOCLK= 0x2390, /*!< flag_lost_clk_int_in */
+ TFA1_BF_INTISPKS= 0x23a0, /*!< flag_cf_speakererror_int_in */
+ TFA1_BF_INTIACS= 0x23b0, /*!< flag_cold_started_int_in */
+ TFA1_BF_INTISWS= 0x23c0, /*!< flag_engage_int_in */
+ TFA1_BF_INTIWDS= 0x23d0, /*!< flag_watchdog_reset_int_in */
+ TFA1_BF_INTIAMPS= 0x23e0, /*!< flag_enbl_amp_int_in */
+ TFA1_BF_INTIAREFS= 0x23f0, /*!< flag_enbl_ref_int_in */
+ TFA1_BF_INTIACK= 0x2501, /*!< Interrupt register input */
+ TFA1_BF_INTENVDDS= 0x2600, /*!< flag_por_int_enable */
+ TFA1_BF_INTENPLLS= 0x2610, /*!< flag_pll_lock_int_enable */
+ TFA1_BF_INTENOTDS= 0x2620, /*!< flag_otpok_int_enable */
+ TFA1_BF_INTENOVDS= 0x2630, /*!< flag_ovpok_int_enable */
+ TFA1_BF_INTENUVDS= 0x2640, /*!< flag_uvpok_int_enable */
+ TFA1_BF_INTENOCDS= 0x2650, /*!< flag_ocp_alarm_int_enable */
+ TFA1_BF_INTENCLKS= 0x2660, /*!< flag_clocks_stable_int_enable */
+ TFA1_BF_INTENCLIPS= 0x2670, /*!< flag_clip_int_enable */
+ TFA1_BF_INTENMTPB= 0x2680, /*!< mtp_busy_int_enable */
+ TFA1_BF_INTENNOCLK= 0x2690, /*!< flag_lost_clk_int_enable */
+ TFA1_BF_INTENSPKS= 0x26a0, /*!< flag_cf_speakererror_int_enable */
+ TFA1_BF_INTENACS= 0x26b0, /*!< flag_cold_started_int_enable */
+ TFA1_BF_INTENSWS= 0x26c0, /*!< flag_engage_int_enable */
+ TFA1_BF_INTENWDS= 0x26d0, /*!< flag_watchdog_reset_int_enable */
+ TFA1_BF_INTENAMPS= 0x26e0, /*!< flag_enbl_amp_int_enable */
+ TFA1_BF_INTENAREFS= 0x26f0, /*!< flag_enbl_ref_int_enable */
+ TFA1_BF_INTENACK= 0x2801, /*!< Interrupt enable register */
+ TFA1_BF_INTPOLVDDS= 0x2900, /*!< flag_por_int_pol */
+ TFA1_BF_INTPOLPLLS= 0x2910, /*!< flag_pll_lock_int_pol */
+ TFA1_BF_INTPOLOTDS= 0x2920, /*!< flag_otpok_int_pol */
+ TFA1_BF_INTPOLOVDS= 0x2930, /*!< flag_ovpok_int_pol */
+ TFA1_BF_INTPOLUVDS= 0x2940, /*!< flag_uvpok_int_pol */
+ TFA1_BF_INTPOLOCDS= 0x2950, /*!< flag_ocp_alarm_int_pol */
+ TFA1_BF_INTPOLCLKS= 0x2960, /*!< flag_clocks_stable_int_pol */
+ TFA1_BF_INTPOLCLIPS= 0x2970, /*!< flag_clip_int_pol */
+ TFA1_BF_INTPOLMTPB= 0x2980, /*!< mtp_busy_int_pol */
+ TFA1_BF_INTPOLNOCLK= 0x2990, /*!< flag_lost_clk_int_pol */
+ TFA1_BF_INTPOLSPKS= 0x29a0, /*!< flag_cf_speakererror_int_pol */
+ TFA1_BF_INTPOLACS= 0x29b0, /*!< flag_cold_started_int_pol */
+ TFA1_BF_INTPOLSWS= 0x29c0, /*!< flag_engage_int_pol */
+ TFA1_BF_INTPOLWDS= 0x29d0, /*!< flag_watchdog_reset_int_pol */
+ TFA1_BF_INTPOLAMPS= 0x29e0, /*!< flag_enbl_amp_int_pol */
+ TFA1_BF_INTPOLAREFS= 0x29f0, /*!< flag_enbl_ref_int_pol */
+ TFA1_BF_INTPOLACK= 0x2b01, /*!< Interrupt status flags polarity register */
+ TFA1_BF_CLIP = 0x4900, /*!< Bypass clip control */
+ TFA1_BF_CIMTP = 0x62b0, /*!< start copying all the data from i2cregs_mtp to mtp [Key 2 protected] */
+ TFA1_BF_RST = 0x7000, /*!< Reset CoolFlux DSP */
+ TFA1_BF_DMEM = 0x7011, /*!< Target memory for access */
+ TFA1_BF_AIF = 0x7030, /*!< Autoincrement-flag for memory-address */
+ TFA1_BF_CFINT = 0x7040, /*!< Interrupt CoolFlux DSP */
+ TFA1_BF_REQ = 0x7087, /*!< request for access (8 channels) */
+ TFA1_BF_REQCMD= 0x7080, /*!< Firmware event request rpc command */
+ TFA1_BF_REQRST= 0x7090, /*!< Firmware event request reset restart */
+ TFA1_BF_REQMIPS= 0x70a0, /*!< Firmware event request short on mips */
+ TFA1_BF_REQMUTED= 0x70b0, /*!< Firmware event request mute sequence ready */
+ TFA1_BF_REQVOL= 0x70c0, /*!< Firmware event request volume ready */
+ TFA1_BF_REQDMG= 0x70d0, /*!< Firmware event request speaker damage detected */
+ TFA1_BF_REQCAL= 0x70e0, /*!< Firmware event request calibration completed */
+ TFA1_BF_REQRSV= 0x70f0, /*!< Firmware event request reserved */
+ TFA1_BF_MADD = 0x710f, /*!< memory-address to be accessed */
+ TFA1_BF_MEMA = 0x720f, /*!< activate memory access (24- or 32-bits data is written/read to/from memory */
+ TFA1_BF_ERR = 0x7307, /*!< Coolflux error flags */
+ TFA1_BF_ACK = 0x7387, /*!< acknowledge of requests (8 channels) */
+ TFA1_BF_MTPOTC= 0x8000, /*!< Calibration schedule (key2 protected) */
+ TFA1_BF_MTPEX = 0x8010, /*!< (key2 protected) */
+} Tfa1BfEnumList_t;
+#define TFA1_NAMETABLE static tfaBfName_t Tfa1DatasheetNames[]= {\
+ { 0x0, "VDDS"}, /* Power-on-reset flag , */\
+ { 0x10, "PLLS"}, /* PLL lock , */\
+ { 0x20, "OTDS"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "OVDS"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "UVDS"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "OCDS"}, /* Over Current Protection alarm , */\
+ { 0x60, "CLKS"}, /* Clocks stable flag , */\
+ { 0x70, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x80, "MTPB"}, /* MTP busy , */\
+ { 0x90, "NOCLK"}, /* Flag lost clock from clock generation unit , */\
+ { 0xa0, "SPKS"}, /* Speaker error flag , */\
+ { 0xb0, "ACS"}, /* Cold Start flag , */\
+ { 0xc0, "SWS"}, /* Flag Engage , */\
+ { 0xd0, "WDS"}, /* Flag watchdog reset , */\
+ { 0xe0, "AMPS"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "AREFS"}, /* References are enabled by manager , */\
+ { 0x109, "BATS"}, /* Battery voltage readout; 0 .. 5.5 [V] , */\
+ { 0x208, "TEMPS"}, /* Temperature readout from the temperature sensor , */\
+ { 0x30b, "REV"}, /* Device type number is B97 , */\
+ { 0x420, "RCV"}, /* Enable Receiver Mode , */\
+ { 0x431, "CHS12"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "INPLVL"}, /* Input level selection control , */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "AUDFS"}, /* Audio sample rate setting , */\
+ { 0x501, "SSCR"}, /* Protection Attack Time , */\
+ { 0x523, "SST"}, /* ProtectionThreshold , */\
+ { 0x561, "SSRL"}, /* Protection Maximum Reduction , */\
+ { 0x582, "SSRR"}, /* Battery Protection Release Time , */\
+ { 0x5b1, "SSHY"}, /* Battery Protection Hysteresis , */\
+ { 0x5e0, "SSR"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "SSBY"}, /* bypass clipper battery protection , */\
+ { 0x600, "DPSA"}, /* Enable dynamic powerstage activation , */\
+ { 0x650, "CFSM"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "SSS"}, /* BatSenseSteepness , */\
+ { 0x687, "VOL"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "DCVO"}, /* Boost Voltage , */\
+ { 0x733, "DCMCC"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x7a0, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7b0, "DCSR"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x7c0, "DCPAVG"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x800, "TROS"}, /* Select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "EXTTS"}, /* external temperature setting to be given by host , */\
+ { 0x900, "PWDN"}, /* Device Mode , */\
+ { 0x910, "I2CR"}, /* I2C Reset , */\
+ { 0x920, "CFE"}, /* Enable CoolFlux , */\
+ { 0x930, "AMPE"}, /* Enable Amplifier , */\
+ { 0x940, "DCA"}, /* EnableBoost , */\
+ { 0x950, "SBSL"}, /* Coolflux configured , */\
+ { 0x960, "AMPC"}, /* Selection on how Amplifier is enabled , */\
+ { 0x970, "DCDIS"}, /* DCDC not connected , */\
+ { 0x980, "PSDR"}, /* IDDQ test amplifier , */\
+ { 0x991, "DCCV"}, /* Coil Value , */\
+ { 0x9b0, "CCFD"}, /* Selection CoolFlux Clock , */\
+ { 0x9c1, "INTPAD"}, /* INT pad configuration control , */\
+ { 0x9e0, "IPLL"}, /* PLL input reference clock selection , */\
+ { 0xb07, "MTPK"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xc25, "CVFDLY"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0x1011, "TDMPRF"}, /* TDM_usecase , */\
+ { 0x1030, "TDMEN"}, /* TDM interface control , */\
+ { 0x1040, "TDMCKINV"}, /* TDM clock inversion , */\
+ { 0x1053, "TDMFSLN"}, /* TDM FS length , */\
+ { 0x1090, "TDMFSPOL"}, /* TDM FS polarity , */\
+ { 0x10a4, "TDMSAMSZ"}, /* TDM Sample Size for all tdm sinks/sources , */\
+ { 0x1103, "TDMSLOTS"}, /* Number of slots , */\
+ { 0x1144, "TDMSLLN"}, /* Slot length , */\
+ { 0x1194, "TDMBRMG"}, /* Bits remaining , */\
+ { 0x11e0, "TDMDDEL"}, /* Data delay , */\
+ { 0x11f0, "TDMDADJ"}, /* Data adjustment , */\
+ { 0x1201, "TDMTXFRM"}, /* TXDATA format , */\
+ { 0x1221, "TDMUUS0"}, /* TXDATA format unused slot sd0 , */\
+ { 0x1241, "TDMUUS1"}, /* TXDATA format unused slot sd1 , */\
+ { 0x1270, "TDMSI0EN"}, /* TDM sink0 enable , */\
+ { 0x1280, "TDMSI1EN"}, /* TDM sink1 enable , */\
+ { 0x1290, "TDMSI2EN"}, /* TDM sink2 enable , */\
+ { 0x12a0, "TDMSO0EN"}, /* TDM source0 enable , */\
+ { 0x12b0, "TDMSO1EN"}, /* TDM source1 enable , */\
+ { 0x12c0, "TDMSO2EN"}, /* TDM source2 enable , */\
+ { 0x12d0, "TDMSI0IO"}, /* tdm_sink0_io , */\
+ { 0x12e0, "TDMSI1IO"}, /* tdm_sink1_io , */\
+ { 0x12f0, "TDMSI2IO"}, /* tdm_sink2_io , */\
+ { 0x1300, "TDMSO0IO"}, /* tdm_source0_io , */\
+ { 0x1310, "TDMSO1IO"}, /* tdm_source1_io , */\
+ { 0x1320, "TDMSO2IO"}, /* tdm_source2_io , */\
+ { 0x1333, "TDMSI0SL"}, /* sink0_slot [GAIN IN] , */\
+ { 0x1373, "TDMSI1SL"}, /* sink1_slot [CH1 IN] , */\
+ { 0x13b3, "TDMSI2SL"}, /* sink2_slot [CH2 IN] , */\
+ { 0x1403, "TDMSO0SL"}, /* source0_slot [GAIN OUT] , */\
+ { 0x1443, "TDMSO1SL"}, /* source1_slot [Voltage Sense] , */\
+ { 0x1483, "TDMSO2SL"}, /* source2_slot [Current Sense] , */\
+ { 0x14c3, "NBCK"}, /* NBCK , */\
+ { 0x2000, "INTOVDDS"}, /* flag_por_int_out , */\
+ { 0x2010, "INTOPLLS"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "INTOOTDS"}, /* flag_otpok_int_out , */\
+ { 0x2030, "INTOOVDS"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "INTOUVDS"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "INTOOCDS"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "INTOCLKS"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "INTOCLIPS"}, /* flag_clip_int_out , */\
+ { 0x2080, "INTOMTPB"}, /* mtp_busy_int_out , */\
+ { 0x2090, "INTONOCLK"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "INTOSPKS"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "INTOACS"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "INTOSWS"}, /* flag_engage_int_out , */\
+ { 0x20d0, "INTOWDS"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "INTOAMPS"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "INTOAREFS"}, /* flag_enbl_ref_int_out , */\
+ { 0x2201, "INTOACK"}, /* Interrupt status register output - Corresponding flag, */\
+ { 0x2300, "INTIVDDS"}, /* flag_por_int_in , */\
+ { 0x2310, "INTIPLLS"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "INTIOTDS"}, /* flag_otpok_int_in , */\
+ { 0x2330, "INTIOVDS"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "INTIUVDS"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "INTIOCDS"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "INTICLKS"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "INTICLIPS"}, /* flag_clip_int_in , */\
+ { 0x2380, "INTIMTPB"}, /* mtp_busy_int_in , */\
+ { 0x2390, "INTINOCLK"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "INTISPKS"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "INTIACS"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "INTISWS"}, /* flag_engage_int_in , */\
+ { 0x23d0, "INTIWDS"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "INTIAMPS"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "INTIAREFS"}, /* flag_enbl_ref_int_in , */\
+ { 0x2501, "INTIACK"}, /* Interrupt register input , */\
+ { 0x2600, "INTENVDDS"}, /* flag_por_int_enable , */\
+ { 0x2610, "INTENPLLS"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "INTENOTDS"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "INTENOVDS"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "INTENUVDS"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "INTENOCDS"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "INTENCLKS"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "INTENCLIPS"}, /* flag_clip_int_enable , */\
+ { 0x2680, "INTENMTPB"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "INTENNOCLK"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "INTENSPKS"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "INTENACS"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "INTENSWS"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "INTENWDS"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "INTENAMPS"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "INTENAREFS"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2801, "INTENACK"}, /* Interrupt enable register , */\
+ { 0x2900, "INTPOLVDDS"}, /* flag_por_int_pol , */\
+ { 0x2910, "INTPOLPLLS"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "INTPOLOTDS"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "INTPOLOVDS"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "INTPOLUVDS"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "INTPOLOCDS"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "INTPOLCLKS"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "INTPOLCLIPS"}, /* flag_clip_int_pol , */\
+ { 0x2980, "INTPOLMTPB"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "INTPOLNOCLK"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "INTPOLSPKS"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "INTPOLACS"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "INTPOLSWS"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "INTPOLWDS"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "INTPOLAMPS"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "INTPOLAREFS"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2b01, "INTPOLACK"}, /* Interrupt status flags polarity register , */\
+ { 0x4900, "CLIP"}, /* Bypass clip control , */\
+ { 0x62b0, "CIMTP"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x7000, "RST"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "DMEM"}, /* Target memory for access , */\
+ { 0x7030, "AIF"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "CFINT"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "REQ"}, /* request for access (8 channels) , */\
+ { 0x7080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x7090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x70a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x70b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x70c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x70d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x70e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x70f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x710f, "MADD"}, /* memory-address to be accessed , */\
+ { 0x720f, "MEMA"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "ERR"}, /* Coolflux error flags , */\
+ { 0x7387, "ACK"}, /* acknowledge of requests (8 channels) , */\
+ { 0x7380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x7390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x73a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x73b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x73c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x73d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x73e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x73f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0x8000, "MTPOTC"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "MTPEX"}, /* (key2 protected) , */\
+ { 0x8045, "SWPROFIL" },\
+ { 0x80a5, "SWVSTEP" },\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA1_BITNAMETABLE static tfaBfName_t Tfa1BitNames[]= {\
+ { 0x0, "flag_por"}, /* Power-on-reset flag , */\
+ { 0x10, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x20, "flag_otpok"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "flag_ovpok"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "flag_uvpok"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "flag_ocp_alarm"}, /* Over Current Protection alarm , */\
+ { 0x60, "flag_clocks_stable"}, /* Clocks stable flag , */\
+ { 0x70, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x80, "mtp_busy"}, /* MTP busy , */\
+ { 0x90, "flag_lost_clk"}, /* Flag lost clock from clock generation unit , */\
+ { 0xa0, "flag_cf_speakererror"}, /* Speaker error flag , */\
+ { 0xb0, "flag_cold_started"}, /* Cold Start flag , */\
+ { 0xc0, "flag_engage"}, /* Flag Engage , */\
+ { 0xd0, "flag_watchdog_reset"}, /* Flag watchdog reset , */\
+ { 0xe0, "flag_enbl_amp"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "flag_enbl_ref"}, /* References are enabled by manager , */\
+ { 0x109, "bat_adc"}, /* Battery voltage readout; 0 .. 5.5 [V] , */\
+ { 0x208, "temp_adc"}, /* Temperature readout from the temperature sensor , */\
+ { 0x30b, "rev_reg"}, /* Device type number is B97 , */\
+ { 0x420, "ctrl_rcv"}, /* Enable Receiver Mode , */\
+ { 0x431, "chan_sel"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "input_level"}, /* Input level selection control , */\
+ { 0x461, "vamp_sel"}, /* Input selection for amplifier , */\
+ { 0x4c3, "audio_fs"}, /* Audio sample rate setting , */\
+ { 0x501, "vbat_prot_attacktime"}, /* Protection Attack Time , */\
+ { 0x523, "vbat_prot_thlevel"}, /* ProtectionThreshold , */\
+ { 0x561, "vbat_prot_max_reduct"}, /* Protection Maximum Reduction , */\
+ { 0x582, "vbat_prot_release_t"}, /* Battery Protection Release Time , */\
+ { 0x5b1, "vbat_prot_hysterese"}, /* Battery Protection Hysteresis , */\
+ { 0x5d0, "reset_min_vbat"}, /* reset clipper , */\
+ { 0x5e0, "sel_vbat"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "bypass_clipper"}, /* bypass clipper battery protection , */\
+ { 0x600, "dpsa"}, /* Enable dynamic powerstage activation , */\
+ { 0x650, "cf_mute"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "batsense_steepness"}, /* BatSenseSteepness , */\
+ { 0x687, "vol"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "boost_volt"}, /* Boost Voltage , */\
+ { 0x733, "boost_cur"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x7a0, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7b0, "boost_speed"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x7c0, "boost_peak2avg"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x800, "ext_temp_sel"}, /* Select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "ext_temp"}, /* external temperature setting to be given by host , */\
+ { 0x8b2, "dcdc_synchronisation"}, /* DCDC synchronisation off + 7 positions , */\
+ { 0x900, "powerdown"}, /* Device Mode , */\
+ { 0x910, "reset"}, /* I2C Reset , */\
+ { 0x920, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x930, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x940, "enbl_boost"}, /* EnableBoost , */\
+ { 0x950, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x960, "sel_enbl_amplifier"}, /* Selection on how Amplifier is enabled , */\
+ { 0x970, "dcdcoff_mode"}, /* DCDC not connected , */\
+ { 0x980, "iddqtest"}, /* IDDQ test amplifier , */\
+ { 0x991, "coil_value"}, /* Coil Value , */\
+ { 0x9b0, "sel_cf_clock"}, /* Selection CoolFlux Clock , */\
+ { 0x9c1, "int_pad_io"}, /* INT pad configuration control , */\
+ { 0x9e0, "sel_fs_bck"}, /* PLL input reference clock selection , */\
+ { 0x9f0, "sel_scl_cf_clock"}, /* Coolflux sub-system clock , */\
+ { 0xb07, "mtpkey2"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xc00, "enbl_volt_sense"}, /* Voltage sense enabling control bit , */\
+ { 0xc10, "vsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0xc25, "vi_frac_delay"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0xc80, "sel_voltsense_out"}, /* TDM output data selection control , */\
+ { 0xc90, "vsense_bypass_avg"}, /* Voltage Sense Average Block Bypass , */\
+ { 0xd05, "cf_frac_delay"}, /* Fractional delay adjustment between current and voltage sense by firmware, */\
+ { 0xe00, "bypass_dcdc_curr_prot"}, /* Control to switch off dcdc current reduction with bat protection, */\
+ { 0xe80, "disable_clock_sh_prot"}, /* disable clock_sh protection , */\
+ { 0xe96, "reserve_reg_1_15_9"}, /* , */\
+ { 0x1011, "tdm_usecase"}, /* TDM_usecase , */\
+ { 0x1030, "tdm_enable"}, /* TDM interface control , */\
+ { 0x1040, "tdm_clk_inversion"}, /* TDM clock inversion , */\
+ { 0x1053, "tdm_fs_ws_length"}, /* TDM FS length , */\
+ { 0x1090, "tdm_fs_ws_polarity"}, /* TDM FS polarity , */\
+ { 0x10a4, "tdm_sample_size"}, /* TDM Sample Size for all tdm sinks/sources , */\
+ { 0x1103, "tdm_nb_of_slots"}, /* Number of slots , */\
+ { 0x1144, "tdm_slot_length"}, /* Slot length , */\
+ { 0x1194, "tdm_bits_remaining"}, /* Bits remaining , */\
+ { 0x11e0, "tdm_data_delay"}, /* Data delay , */\
+ { 0x11f0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x1201, "tdm_txdata_format"}, /* TXDATA format , */\
+ { 0x1221, "tdm_txdata_format_unused_slot_sd0"}, /* TXDATA format unused slot sd0 , */\
+ { 0x1241, "tdm_txdata_format_unused_slot_sd1"}, /* TXDATA format unused slot sd1 , */\
+ { 0x1270, "tdm_sink0_enable"}, /* TDM sink0 enable , */\
+ { 0x1280, "tdm_sink1_enable"}, /* TDM sink1 enable , */\
+ { 0x1290, "tdm_sink2_enable"}, /* TDM sink2 enable , */\
+ { 0x12a0, "tdm_source0_enable"}, /* TDM source0 enable , */\
+ { 0x12b0, "tdm_source1_enable"}, /* TDM source1 enable , */\
+ { 0x12c0, "tdm_source2_enable"}, /* TDM source2 enable , */\
+ { 0x12d0, "tdm_sink0_io"}, /* tdm_sink0_io , */\
+ { 0x12e0, "tdm_sink1_io"}, /* tdm_sink1_io , */\
+ { 0x12f0, "tdm_sink2_io"}, /* tdm_sink2_io , */\
+ { 0x1300, "tdm_source0_io"}, /* tdm_source0_io , */\
+ { 0x1310, "tdm_source1_io"}, /* tdm_source1_io , */\
+ { 0x1320, "tdm_source2_io"}, /* tdm_source2_io , */\
+ { 0x1333, "tdm_sink0_slot"}, /* sink0_slot [GAIN IN] , */\
+ { 0x1373, "tdm_sink1_slot"}, /* sink1_slot [CH1 IN] , */\
+ { 0x13b3, "tdm_sink2_slot"}, /* sink2_slot [CH2 IN] , */\
+ { 0x1403, "tdm_source0_slot"}, /* source0_slot [GAIN OUT] , */\
+ { 0x1443, "tdm_source1_slot"}, /* source1_slot [Voltage Sense] , */\
+ { 0x1483, "tdm_source2_slot"}, /* source2_slot [Current Sense] , */\
+ { 0x14c3, "tdm_nbck"}, /* NBCK , */\
+ { 0x1500, "flag_tdm_lut_error"}, /* TDM LUT error flag , */\
+ { 0x1512, "flag_tdm_status"}, /* TDM interface status bits , */\
+ { 0x1540, "flag_tdm_error"}, /* TDM interface error indicator , */\
+ { 0x2000, "flag_por_int_out"}, /* flag_por_int_out , */\
+ { 0x2010, "flag_pll_lock_int_out"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "flag_otpok_int_out"}, /* flag_otpok_int_out , */\
+ { 0x2030, "flag_ovpok_int_out"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "flag_uvpok_int_out"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "flag_ocp_alarm_int_out"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "flag_clocks_stable_int_out"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "flag_clip_int_out"}, /* flag_clip_int_out , */\
+ { 0x2080, "mtp_busy_int_out"}, /* mtp_busy_int_out , */\
+ { 0x2090, "flag_lost_clk_int_out"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "flag_cf_speakererror_int_out"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "flag_cold_started_int_out"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "flag_engage_int_out"}, /* flag_engage_int_out , */\
+ { 0x20d0, "flag_watchdog_reset_int_out"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "flag_enbl_amp_int_out"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "flag_enbl_ref_int_out"}, /* flag_enbl_ref_int_out , */\
+ { 0x2100, "flag_voutcomp_int_out"}, /* flag_voutcomp_int_out , */\
+ { 0x2110, "flag_voutcomp93_int_out"}, /* flag_voutcomp93_int_out , */\
+ { 0x2120, "flag_voutcomp86_int_out"}, /* flag_voutcomp86_int_out , */\
+ { 0x2130, "flag_hiz_int_out"}, /* flag_hiz_int_out , */\
+ { 0x2140, "flag_ocpokbst_int_out"}, /* flag_ocpokbst_int_out , */\
+ { 0x2150, "flag_peakcur_int_out"}, /* flag_peakcur_int_out , */\
+ { 0x2160, "flag_ocpokap_int_out"}, /* flag_ocpokap_int_out , */\
+ { 0x2170, "flag_ocpokan_int_out"}, /* flag_ocpokan_int_out , */\
+ { 0x2180, "flag_ocpokbp_int_out"}, /* flag_ocpokbp_int_out , */\
+ { 0x2190, "flag_ocpokbn_int_out"}, /* flag_ocpokbn_int_out , */\
+ { 0x21a0, "flag_adc10_ready_int_out"}, /* flag_adc10_ready_int_out , */\
+ { 0x21b0, "flag_clipa_high_int_out"}, /* flag_clipa_high_int_out , */\
+ { 0x21c0, "flag_clipa_low_int_out"}, /* flag_clipa_low_int_out , */\
+ { 0x21d0, "flag_clipb_high_int_out"}, /* flag_clipb_high_int_out , */\
+ { 0x21e0, "flag_clipb_low_int_out"}, /* flag_clipb_low_int_out , */\
+ { 0x21f0, "flag_tdm_error_int_out"}, /* flag_tdm_error_int_out , */\
+ { 0x2201, "interrupt_out3"}, /* Interrupt status register output - Corresponding flag, */\
+ { 0x2300, "flag_por_int_in"}, /* flag_por_int_in , */\
+ { 0x2310, "flag_pll_lock_int_in"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "flag_otpok_int_in"}, /* flag_otpok_int_in , */\
+ { 0x2330, "flag_ovpok_int_in"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "flag_uvpok_int_in"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "flag_ocp_alarm_int_in"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "flag_clocks_stable_int_in"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "flag_clip_int_in"}, /* flag_clip_int_in , */\
+ { 0x2380, "mtp_busy_int_in"}, /* mtp_busy_int_in , */\
+ { 0x2390, "flag_lost_clk_int_in"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "flag_cf_speakererror_int_in"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "flag_cold_started_int_in"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "flag_engage_int_in"}, /* flag_engage_int_in , */\
+ { 0x23d0, "flag_watchdog_reset_int_in"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "flag_enbl_amp_int_in"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "flag_enbl_ref_int_in"}, /* flag_enbl_ref_int_in , */\
+ { 0x2400, "flag_voutcomp_int_in"}, /* flag_voutcomp_int_in , */\
+ { 0x2410, "flag_voutcomp93_int_in"}, /* flag_voutcomp93_int_in , */\
+ { 0x2420, "flag_voutcomp86_int_in"}, /* flag_voutcomp86_int_in , */\
+ { 0x2430, "flag_hiz_int_in"}, /* flag_hiz_int_in , */\
+ { 0x2440, "flag_ocpokbst_int_in"}, /* flag_ocpokbst_int_in , */\
+ { 0x2450, "flag_peakcur_int_in"}, /* flag_peakcur_int_in , */\
+ { 0x2460, "flag_ocpokap_int_in"}, /* flag_ocpokap_int_in , */\
+ { 0x2470, "flag_ocpokan_int_in"}, /* flag_ocpokan_int_in , */\
+ { 0x2480, "flag_ocpokbp_int_in"}, /* flag_ocpokbp_int_in , */\
+ { 0x2490, "flag_ocpokbn_int_in"}, /* flag_ocpokbn_int_in , */\
+ { 0x24a0, "flag_adc10_ready_int_in"}, /* flag_adc10_ready_int_in , */\
+ { 0x24b0, "flag_clipa_high_int_in"}, /* flag_clipa_high_int_in , */\
+ { 0x24c0, "flag_clipa_low_int_in"}, /* flag_clipa_low_int_in , */\
+ { 0x24d0, "flag_clipb_high_int_in"}, /* flag_clipb_high_int_in , */\
+ { 0x24e0, "flag_clipb_low_int_in"}, /* flag_clipb_low_int_in , */\
+ { 0x24f0, "flag_tdm_error_int_in"}, /* flag_tdm_error_int_in , */\
+ { 0x2501, "interrupt_in3"}, /* Interrupt register input , */\
+ { 0x2600, "flag_por_int_enable"}, /* flag_por_int_enable , */\
+ { 0x2610, "flag_pll_lock_int_enable"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "flag_otpok_int_enable"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "flag_ovpok_int_enable"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "flag_uvpok_int_enable"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "flag_ocp_alarm_int_enable"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "flag_clocks_stable_int_enable"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "flag_clip_int_enable"}, /* flag_clip_int_enable , */\
+ { 0x2680, "mtp_busy_int_enable"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "flag_lost_clk_int_enable"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "flag_cf_speakererror_int_enable"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "flag_cold_started_int_enable"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "flag_engage_int_enable"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "flag_watchdog_reset_int_enable"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "flag_enbl_amp_int_enable"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "flag_enbl_ref_int_enable"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2700, "flag_voutcomp_int_enable"}, /* flag_voutcomp_int_enable , */\
+ { 0x2710, "flag_voutcomp93_int_enable"}, /* flag_voutcomp93_int_enable , */\
+ { 0x2720, "flag_voutcomp86_int_enable"}, /* flag_voutcomp86_int_enable , */\
+ { 0x2730, "flag_hiz_int_enable"}, /* flag_hiz_int_enable , */\
+ { 0x2740, "flag_ocpokbst_int_enable"}, /* flag_ocpokbst_int_enable , */\
+ { 0x2750, "flag_peakcur_int_enable"}, /* flag_peakcur_int_enable , */\
+ { 0x2760, "flag_ocpokap_int_enable"}, /* flag_ocpokap_int_enable , */\
+ { 0x2770, "flag_ocpokan_int_enable"}, /* flag_ocpokan_int_enable , */\
+ { 0x2780, "flag_ocpokbp_int_enable"}, /* flag_ocpokbp_int_enable , */\
+ { 0x2790, "flag_ocpokbn_int_enable"}, /* flag_ocpokbn_int_enable , */\
+ { 0x27a0, "flag_adc10_ready_int_enable"}, /* flag_adc10_ready_int_enable , */\
+ { 0x27b0, "flag_clipa_high_int_enable"}, /* flag_clipa_high_int_enable , */\
+ { 0x27c0, "flag_clipa_low_int_enable"}, /* flag_clipa_low_int_enable , */\
+ { 0x27d0, "flag_clipb_high_int_enable"}, /* flag_clipb_high_int_enable , */\
+ { 0x27e0, "flag_clipb_low_int_enable"}, /* flag_clipb_low_int_enable , */\
+ { 0x27f0, "flag_tdm_error_int_enable"}, /* flag_tdm_error_int_enable , */\
+ { 0x2801, "interrupt_enable3"}, /* Interrupt enable register , */\
+ { 0x2900, "flag_por_int_pol"}, /* flag_por_int_pol , */\
+ { 0x2910, "flag_pll_lock_int_pol"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "flag_otpok_int_pol"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "flag_ovpok_int_pol"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "flag_uvpok_int_pol"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "flag_ocp_alarm_int_pol"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "flag_clocks_stable_int_pol"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "flag_clip_int_pol"}, /* flag_clip_int_pol , */\
+ { 0x2980, "mtp_busy_int_pol"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "flag_lost_clk_int_pol"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "flag_cf_speakererror_int_pol"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "flag_cold_started_int_pol"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "flag_engage_int_pol"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "flag_watchdog_reset_int_pol"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "flag_enbl_amp_int_pol"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "flag_enbl_ref_int_pol"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2a00, "flag_voutcomp_int_pol"}, /* flag_voutcomp_int_pol , */\
+ { 0x2a10, "flag_voutcomp93_int_pol"}, /* flag_voutcomp93_int_pol , */\
+ { 0x2a20, "flag_voutcomp86_int_pol"}, /* flag_voutcomp86_int_pol , */\
+ { 0x2a30, "flag_hiz_int_pol"}, /* flag_hiz_int_pol , */\
+ { 0x2a40, "flag_ocpokbst_int_pol"}, /* flag_ocpokbst_int_pol , */\
+ { 0x2a50, "flag_peakcur_int_pol"}, /* flag_peakcur_int_pol , */\
+ { 0x2a60, "flag_ocpokap_int_pol"}, /* flag_ocpokap_int_pol , */\
+ { 0x2a70, "flag_ocpokan_int_pol"}, /* flag_ocpokan_int_pol , */\
+ { 0x2a80, "flag_ocpokbp_int_pol"}, /* flag_ocpokbp_int_pol , */\
+ { 0x2a90, "flag_ocpokbn_int_pol"}, /* flag_ocpokbn_int_pol , */\
+ { 0x2aa0, "flag_adc10_ready_int_pol"}, /* flag_adc10_ready_int_pol , */\
+ { 0x2ab0, "flag_clipa_high_int_pol"}, /* flag_clipa_high_int_pol , */\
+ { 0x2ac0, "flag_clipa_low_int_pol"}, /* flag_clipa_low_int_pol , */\
+ { 0x2ad0, "flag_clipb_high_int_pol"}, /* flag_clipb_high_int_pol , */\
+ { 0x2ae0, "flag_clipb_low_int_pol"}, /* flag_clipb_low_int_pol , */\
+ { 0x2af0, "flag_tdm_error_int_pol"}, /* flag_tdm_error_int_pol , */\
+ { 0x2b01, "status_polarity3"}, /* Interrupt status flags polarity register , */\
+ { 0x3000, "flag_voutcomp"}, /* flag_voutcomp, indication Vset is larger than Vbat, */\
+ { 0x3010, "flag_voutcomp93"}, /* flag_voutcomp93, indication Vset is larger than 1.07* Vbat, */\
+ { 0x3020, "flag_voutcomp86"}, /* flag_voutcomp86, indication Vset is larger than 1.14* Vbat, */\
+ { 0x3030, "flag_hiz"}, /* flag_hiz, indication Vbst is larger than Vbat , */\
+ { 0x3040, "flag_ocpokbst"}, /* flag_ocpokbst, indication no over current in boost converter pmos switch, */\
+ { 0x3050, "flag_peakcur"}, /* flag_peakcur, indication current is max in dcdc converter, */\
+ { 0x3060, "flag_ocpokap"}, /* flag_ocpokap, indication no over current in amplifier "a" pmos output stage, */\
+ { 0x3070, "flag_ocpokan"}, /* flag_ocpokan, indication no over current in amplifier "a" nmos output stage, */\
+ { 0x3080, "flag_ocpokbp"}, /* flag_ocpokbp, indication no over current in amplifier "b" pmos output stage, */\
+ { 0x3090, "flag_ocpokbn"}, /* flag_ocpokbn, indication no over current in amplifier"b" nmos output stage, */\
+ { 0x30a0, "flag_adc10_ready"}, /* flag_adc10_ready, indication adc10 is ready , */\
+ { 0x30b0, "flag_clipa_high"}, /* flag_clipa_high, indication pmos amplifier "a" is clipping, */\
+ { 0x30c0, "flag_clipa_low"}, /* flag_clipa_low, indication nmos amplifier "a" is clipping, */\
+ { 0x30d0, "flag_clipb_high"}, /* flag_clipb_high, indication pmos amplifier "b" is clipping, */\
+ { 0x30e0, "flag_clipb_low"}, /* flag_clipb_low, indication nmos amplifier "b" is clipping, */\
+ { 0x310f, "mtp_man_data_out"}, /* single word read from MTP (manual copy) , */\
+ { 0x3200, "key01_locked"}, /* key01_locked, indication key 1 is locked , */\
+ { 0x3210, "key02_locked"}, /* key02_locked, indication key 2 is locked , */\
+ { 0x3225, "mtp_ecc_tcout"}, /* mtp_ecc_tcout , */\
+ { 0x3280, "mtpctrl_valid_test_rd"}, /* mtp test readout for read , */\
+ { 0x3290, "mtpctrl_valid_test_wr"}, /* mtp test readout for write , */\
+ { 0x32a0, "flag_in_alarm_state"}, /* Alarm state , */\
+ { 0x32b0, "mtp_ecc_err2"}, /* two or more bit errors detected in MTP, can not reconstruct value, */\
+ { 0x32c0, "mtp_ecc_err1"}, /* one bit error detected in MTP, reconstructed value, */\
+ { 0x32d0, "mtp_mtp_hvf"}, /* high voltage ready flag for MTP , */\
+ { 0x32f0, "mtp_zero_check_fail"}, /* zero check failed (tbd) for MTP , */\
+ { 0x3309, "data_adc10_tempbat"}, /* data_adc10_tempbat[9;0], adc 10 data output for testing, */\
+ { 0x400f, "hid_code"}, /* 5A6Bh, 23147d to access registers (Default for engineering), */\
+ { 0x4100, "bypass_hp"}, /* Bypass_High Pass Filter , */\
+ { 0x4110, "hard_mute"}, /* Hard Mute , */\
+ { 0x4120, "soft_mute"}, /* Soft Mute , */\
+ { 0x4134, "pwm_delay"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "pwm_shape"}, /* PWM Shape , */\
+ { 0x4190, "pwm_bitlength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4203, "drive"}, /* Drive bits to select amount of power stage amplifier, */\
+ { 0x4240, "reclock_pwm"}, /* , */\
+ { 0x4250, "reclock_voltsense"}, /* , */\
+ { 0x4281, "dpsalevel"}, /* DPSA Threshold level , */\
+ { 0x42a1, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x42c0, "coincidence"}, /* Prevent simultaneously switching of output stage , */\
+ { 0x42d0, "kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x4306, "drivebst"}, /* Drive bits to select the powertransistor sections boost converter, */\
+ { 0x43a0, "ocptestbst"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0);For new ocp (ctrl_reversebst is 1);, */\
+ { 0x43d0, "test_abistfft_enbl"}, /* FFT coolflux , */\
+ { 0x43f0, "test_bcontrol"}, /* test _bcontrol , */\
+ { 0x4400, "reversebst"}, /* OverCurrent Protection selection of power stage boost converter, */\
+ { 0x4410, "sensetest"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0x4420, "enbl_engagebst"}, /* Enable power stage dcdc controller , */\
+ { 0x4470, "enbl_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x4480, "enbl_voutcomp"}, /* Enable vout comparators , */\
+ { 0x4490, "enbl_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x44a0, "enbl_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x44b0, "enbl_hizcom"}, /* Enable hiz comparator , */\
+ { 0x44c0, "enbl_peakcur"}, /* Enable peak current , */\
+ { 0x44d0, "bypass_ovpglitch"}, /* Bypass OVP Glitch Filter , */\
+ { 0x44e0, "enbl_windac"}, /* Enable window dac , */\
+ { 0x44f0, "enbl_powerbst"}, /* Enable line of the powerstage , */\
+ { 0x4507, "ocp_thr"}, /* ocp_thr threshold level for OCP , */\
+ { 0x4580, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0x4590, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0x45a0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0x45b0, "bypass_otp"}, /* Bypass OTP , */\
+ { 0x45c0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0x45d0, "bypass_ocpcounter"}, /* BypassOCPCounter , */\
+ { 0x45e0, "bypass_lost_clk"}, /* Bypasslost_clk detector , */\
+ { 0x45f0, "vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0x4600, "bypass_gc"}, /* bypass_gc, bypasses the CS gain correction , */\
+ { 0x4610, "cs_gain_control"}, /* gain control by means of MTP or i2c; 0 is MTP , */\
+ { 0x4627, "cs_gain"}, /* + / - 128 steps in steps of 1/4 percent 2's compliment, */\
+ { 0x46a0, "bypass_lp"}, /* bypass Low-Pass filter in temperature sensor , */\
+ { 0x46b0, "bypass_pwmcounter"}, /* bypass_pwmcounter , */\
+ { 0x46c0, "cs_negfixed"}, /* does not switch to neg , */\
+ { 0x46d2, "cs_neghyst"}, /* switches to neg depending on level , */\
+ { 0x4700, "switch_fb"}, /* switch_fb , */\
+ { 0x4713, "se_hyst"}, /* se_hyst , */\
+ { 0x4754, "se_level"}, /* se_level , */\
+ { 0x47a5, "ktemp"}, /* temperature compensation trimming , */\
+ { 0x4800, "cs_negin"}, /* negin , */\
+ { 0x4810, "cs_sein"}, /* cs_sein , */\
+ { 0x4820, "cs_coincidence"}, /* Coincidence current sense , */\
+ { 0x4830, "iddqtestbst"}, /* for iddq testing in powerstage of boost convertor , */\
+ { 0x4840, "coincidencebst"}, /* Switch protection on to prevent simultaneously switching power stages bst and amp, */\
+ { 0x4876, "delay_se_neg"}, /* delay of se and neg , */\
+ { 0x48e1, "cs_ttrack"}, /* sample & hold track time , */\
+ { 0x4900, "bypass_clip"}, /* Bypass clip control , */\
+ { 0x4920, "cf_cgate_off"}, /* to disable clock gating in the coolflux , */\
+ { 0x4940, "clipfast"}, /* clock switch for battery protection clipper, it switches back to old frequency, */\
+ { 0x4950, "cs_8ohm"}, /* 8 ohm mode for current sense (gain mode) , */\
+ { 0x4974, "delay_clock_sh"}, /* delay_sh, tunes S7H delay , */\
+ { 0x49c0, "inv_clksh"}, /* Invert the sample/hold clock for current sense ADC, */\
+ { 0x49d0, "inv_neg"}, /* Invert neg signal , */\
+ { 0x49e0, "inv_se"}, /* Invert se signal , */\
+ { 0x49f0, "setse"}, /* switches between Single Ende and differential mode; 1 is single ended, */\
+ { 0x4a12, "adc10_sel"}, /* select the input to convert the 10b ADC , */\
+ { 0x4a60, "adc10_reset"}, /* Global asynchronous reset (active HIGH) 10 bit ADC, */\
+ { 0x4a81, "adc10_test"}, /* Test mode selection signal 10 bit ADC , */\
+ { 0x4aa0, "bypass_lp_vbat"}, /* lp filter in batt sensor , */\
+ { 0x4ae0, "dc_offset"}, /* switch offset control on/off, is decimator offset control, */\
+ { 0x4af0, "tsense_hibias"}, /* bit to set the biasing in temp sensor to high , */\
+ { 0x4b00, "adc13_iset"}, /* Micadc Setting of current consumption. Debug use only, */\
+ { 0x4b14, "adc13_gain"}, /* Micadc gain setting (2-compl) , */\
+ { 0x4b61, "adc13_slowdel"}, /* Micadc Delay setting for internal clock. Debug use only, */\
+ { 0x4b83, "adc13_offset"}, /* Micadc ADC offset setting , */\
+ { 0x4bc0, "adc13_bsoinv"}, /* Micadc bit stream output invert mode for test , */\
+ { 0x4bd0, "adc13_resonator_enable"}, /* Micadc Give extra SNR with less stability. Debug use only, */\
+ { 0x4be0, "testmicadc"}, /* Mux at input of MICADC for test purpose , */\
+ { 0x4c0f, "abist_offset"}, /* offset control for ABIST testing , */\
+ { 0x4d05, "windac"}, /* for testing direct control windac , */\
+ { 0x4dc3, "pwm_dcc_cnt"}, /* control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0x4e04, "slopecur"}, /* for testing direct control slopecur , */\
+ { 0x4e50, "ctrl_dem"}, /* dyn element matching control, rest of codes are optional, */\
+ { 0x4ed0, "enbl_pwm_dcc"}, /* to enable direct control of pwm duty cycle , */\
+ { 0x5007, "gain"}, /* Gain setting of the gain multiplier , */\
+ { 0x5081, "sourceb"}, /* Set OUTB to , */\
+ { 0x50a1, "sourcea"}, /* Set OUTA to , */\
+ { 0x50c1, "sourcebst"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0x50e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0x5104, "pulselengthbst"}, /* pulse length setting test input for boost converter, */\
+ { 0x5150, "bypasslatchbst"}, /* bypass_latch in boost converter , */\
+ { 0x5160, "invertbst"}, /* invert pwmbst test signal , */\
+ { 0x5174, "pulselength"}, /* pulse length setting test input for amplifier , */\
+ { 0x51c0, "bypasslatch"}, /* bypass_latch in PWM source selection module , */\
+ { 0x51d0, "invertb"}, /* invert pwmb test signal , */\
+ { 0x51e0, "inverta"}, /* invert pwma test signal , */\
+ { 0x51f0, "bypass_ctrlloop"}, /* bypass_ctrlloop bypasses the control loop of the amplifier, */\
+ { 0x5210, "test_rdsona"}, /* tbd for rdson testing , */\
+ { 0x5220, "test_rdsonb"}, /* tbd for rdson testing , */\
+ { 0x5230, "test_rdsonbst"}, /* tbd for rdson testing , */\
+ { 0x5240, "test_cvia"}, /* tbd for rdson testing , */\
+ { 0x5250, "test_cvib"}, /* tbd for rdson testing , */\
+ { 0x5260, "test_cvibst"}, /* tbd for rdson testing , */\
+ { 0x5306, "digimuxa_sel"}, /* DigimuxA input selection control (see Digimux list for details), */\
+ { 0x5376, "digimuxb_sel"}, /* DigimuxB input selection control (see Digimux list for details), */\
+ { 0x5400, "hs_mode"}, /* hs_mode, high speed mode I2C bus , */\
+ { 0x5412, "test_parametric_io"}, /* test_parametric_io for testing pads , */\
+ { 0x5440, "enbl_ringo"}, /* enbl_ringo, for test purpose to check with ringo , */\
+ { 0x5456, "digimuxc_sel"}, /* DigimuxC input selection control (see Digimux list for details), */\
+ { 0x54c0, "dio_ehs"}, /* Slew control for DIO in output mode , */\
+ { 0x54d0, "gainio_ehs"}, /* Slew control for GAINIO in output mode , */\
+ { 0x550d, "enbl_amp"}, /* enbl_amp for testing to enable all analoge blocks in amplifier, */\
+ { 0x5600, "use_direct_ctrls"}, /* use_direct_ctrls, to overrule several functions direct for testing, */\
+ { 0x5610, "rst_datapath"}, /* rst_datapath, datapath reset , */\
+ { 0x5620, "rst_cgu"}, /* rst_cgu, cgu reset , */\
+ { 0x5637, "enbl_ref"}, /* for testing to enable all analoge blocks in references, */\
+ { 0x56b0, "enbl_engage"}, /* Enable output stage amplifier , */\
+ { 0x56c0, "use_direct_clk_ctrl"}, /* use_direct_clk_ctrl, to overrule several functions direct for testing, */\
+ { 0x56d0, "use_direct_pll_ctrl"}, /* use_direct_pll_ctrl, to overrule several functions direct for testing, */\
+ { 0x56e0, "use_direct_ctrls_2"}, /* use_direct_sourseamp_ctrls, to overrule several functions direct for testing, */\
+ { 0x5707, "anamux"}, /* Anamux control , */\
+ { 0x57c0, "ocptest"}, /* ctrl_ocptest, deactivates the over current protection in the power stages of the amplifier. The ocp flag signals stay active., */\
+ { 0x57e0, "otptest"}, /* otptest, test mode otp amplifier , */\
+ { 0x57f0, "reverse"}, /* 1: Normal mode, slope is controlled , */\
+ { 0x5813, "pll_selr"}, /* pll_selr , */\
+ { 0x5854, "pll_selp"}, /* pll_selp , */\
+ { 0x58a5, "pll_seli"}, /* pll_seli , */\
+ { 0x5950, "pll_mdec_msb"}, /* most significant bits of pll_mdec[16] , */\
+ { 0x5960, "pll_ndec_msb"}, /* most significant bits of pll_ndec[9] , */\
+ { 0x5970, "pll_frm"}, /* pll_frm , */\
+ { 0x5980, "pll_directi"}, /* pll_directi , */\
+ { 0x5990, "pll_directo"}, /* pll_directo , */\
+ { 0x59a0, "enbl_pll"}, /* enbl_pll , */\
+ { 0x59f0, "pll_bypass"}, /* pll_bypass , */\
+ { 0x5a0f, "tsig_freq"}, /* tsig_freq, internal sinus test generator, frequency control, */\
+ { 0x5b02, "tsig_freq_msb"}, /* select internal sinus test generator, frequency control msb bits, */\
+ { 0x5b30, "inject_tsig"}, /* inject_tsig, control bit to switch to internal sinus test generator, */\
+ { 0x5b44, "adc10_prog_sample"}, /* control ADC10 , */\
+ { 0x5c0f, "pll_mdec"}, /* bits 15..0 of pll_mdec[16;0] , */\
+ { 0x5d06, "pll_pdec"}, /* pll_pdec , */\
+ { 0x5d78, "pll_ndec"}, /* bits 8..0 of pll_ndec[9;0] , */\
+ { 0x6007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0x6185, "mtp_ecc_tcin"}, /* Mtp_ecc_tcin , */\
+ { 0x6203, "mtp_man_address_in"}, /* address from I2C regs for writing one word single mtp, */\
+ { 0x6260, "mtp_ecc_eeb"}, /* enable code bit generation (active low!) , */\
+ { 0x6270, "mtp_ecc_ecb"}, /* enable correction signal (active low!) , */\
+ { 0x6280, "man_copy_mtp_to_iic"}, /* start copying single word from mtp to i2cregs_mtp , */\
+ { 0x6290, "man_copy_iic_to_mtp"}, /* start copying single word from i2cregs_mtp to mtp [Key 1 protected], */\
+ { 0x62a0, "auto_copy_mtp_to_iic"}, /* start copying all the data from mtp to i2cregs_mtp, */\
+ { 0x62b0, "auto_copy_iic_to_mtp"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x62d2, "mtp_speed_mode"}, /* Speed mode , */\
+ { 0x6340, "mtp_direct_enable"}, /* mtp_direct_enable (key1 protected) , */\
+ { 0x6350, "mtp_direct_wr"}, /* mtp_direct_wr (key1 protected) , */\
+ { 0x6360, "mtp_direct_rd"}, /* mtp_direct_rd (key1 protected) , */\
+ { 0x6370, "mtp_direct_rst"}, /* mtp_direct_rst (key1 protected) , */\
+ { 0x6380, "mtp_direct_ers"}, /* mtp_direct_ers (key1 protected) , */\
+ { 0x6390, "mtp_direct_prg"}, /* mtp_direct_prg (key1 protected) , */\
+ { 0x63a0, "mtp_direct_epp"}, /* mtp_direct_epp (key1 protected) , */\
+ { 0x63b4, "mtp_direct_test"}, /* mtp_direct_test (key1 protected) , */\
+ { 0x640f, "mtp_man_data_in"}, /* single word to be written to MTP (manual copy) , */\
+ { 0x7000, "cf_rst_dsp"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "cf_dmem"}, /* Target memory for access , */\
+ { 0x7030, "cf_aif"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "cf_int"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "cf_req"}, /* request for access (8 channels) , */\
+ { 0x710f, "cf_madd"}, /* memory-address to be accessed , */\
+ { 0x720f, "cf_mema"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "cf_err"}, /* Coolflux error flags , */\
+ { 0x7387, "cf_ack"}, /* acknowledge of requests (8 channels) , */\
+ { 0x8000, "calibration_onetime"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "calibr_ron_done"}, /* (key2 protected) , */\
+ { 0x8105, "calibr_vout_offset"}, /* calibr_vout_offset (DCDCoffset) 2's compliment (key1 protected), */\
+ { 0x8163, "calibr_delta_gain"}, /* delta gain for vamp (alpha) 2's compliment (key1 protected), */\
+ { 0x81a5, "calibr_offs_amp"}, /* offset for vamp (Ampoffset) 2's compliment (key1 protected), */\
+ { 0x8207, "calibr_gain_cs"}, /* gain current sense (Imeasalpha) 2's compliment (key1 protected), */\
+ { 0x8284, "calibr_temp_offset"}, /* temperature offset 2's compliment (key1 protected), */\
+ { 0x82d2, "calibr_temp_gain"}, /* temperature gain 2's compliment (key1 protected) , */\
+ { 0x830f, "calibr_ron"}, /* Ron resistance of coil (key1 protected) , */\
+ { 0x8505, "type_bits_HW"}, /* Key1_Protected_MTP5 , */\
+ { 0x8601, "type_bits_1_0_SW"}, /* MTP-control SW , */\
+ { 0x8681, "type_bits_8_9_SW"}, /* MTP-control SW , */\
+ { 0x870f, "type_bits2_SW"}, /* MTP-control SW2 , */\
+ { 0x8806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0x8870, "htol_iic_addr_en"}, /* HTOL_I2C_Address_Enable , */\
+ { 0x8881, "ctrl_ovp_response"}, /* OVP response control , */\
+ { 0x88a0, "disable_ovp_alarm_state"}, /* OVP alarm state control , */\
+ { 0x88b0, "enbl_stretch_ovp"}, /* OVP alram strech control , */\
+ { 0x88c0, "cf_debug_mode"}, /* Coolflux debug mode , */\
+ { 0x8a0f, "production_data1"}, /* (key1 protected) , */\
+ { 0x8b0f, "production_data2"}, /* (key1 protected) , */\
+ { 0x8c0f, "production_data3"}, /* (key1 protected) , */\
+ { 0x8d0f, "production_data4"}, /* (key1 protected) , */\
+ { 0x8e0f, "production_data5"}, /* (key1 protected) , */\
+ { 0x8f0f, "production_data6"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa1_irq {
+ tfa1_irq_vdds = 0,
+ tfa1_irq_plls = 1,
+ tfa1_irq_ds = 2,
+ tfa1_irq_vds = 3,
+ tfa1_irq_uvds = 4,
+ tfa1_irq_cds = 5,
+ tfa1_irq_clks = 6,
+ tfa1_irq_clips = 7,
+ tfa1_irq_mtpb = 8,
+ tfa1_irq_clk = 9,
+ tfa1_irq_spks = 10,
+ tfa1_irq_acs = 11,
+ tfa1_irq_sws = 12,
+ tfa1_irq_wds = 13,
+ tfa1_irq_amps = 14,
+ tfa1_irq_arefs = 15,
+ tfa1_irq_ack = 32,
+ tfa1_irq_max = 33,
+ tfa1_irq_all = -1 /* all irqs */};
+
+#define TFA1_IRQ_NAMETABLE static tfaIrqName_t Tfa1IrqNames[]= {\
+ { 0, "VDDS"},\
+ { 1, "PLLS"},\
+ { 2, "DS"},\
+ { 3, "VDS"},\
+ { 4, "UVDS"},\
+ { 5, "CDS"},\
+ { 6, "CLKS"},\
+ { 7, "CLIPS"},\
+ { 8, "MTPB"},\
+ { 9, "CLK"},\
+ { 10, "SPKS"},\
+ { 11, "ACS"},\
+ { 12, "SWS"},\
+ { 13, "WDS"},\
+ { 14, "AMPS"},\
+ { 15, "AREFS"},\
+ { 16, "16"},\
+ { 17, "17"},\
+ { 18, "18"},\
+ { 19, "19"},\
+ { 20, "20"},\
+ { 21, "21"},\
+ { 22, "22"},\
+ { 23, "23"},\
+ { 24, "24"},\
+ { 25, "25"},\
+ { 26, "26"},\
+ { 27, "27"},\
+ { 28, "28"},\
+ { 29, "29"},\
+ { 30, "30"},\
+ { 31, "31"},\
+ { 32, "ACK"},\
+ { 33, "33"},\
+};
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa2_tfafieldnames_N1C.h b/sound/soc/codecs/tfa98xx-downstream/tfa2_tfafieldnames_N1C.h
new file mode 100644
index 00000000000..ac0bb040356
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa2_tfafieldnames_N1C.h
@@ -0,0 +1,1533 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa98xx_TfaFieldnames.h
+ * This file was generated automatically on 09/01/15 at 09:40:28.
+ * Source file: TFA9888_N1C_I2C_regmap_V1.xlsx
+ */
+#define TFA9888_I2CVERSION 18
+typedef enum Tfa2BfEnumList {
+ TFA2_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA2_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA2_BF_CFE = 0x0020, /*!< Enable CoolFlux */
+ TFA2_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA2_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA2_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA2_BF_AMPC = 0x0060, /*!< CoolFlux controls amplifier */
+ TFA2_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA2_BF_FSSSEL= 0x0091, /*!< Audio sample reference */
+ TFA2_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA2_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA2_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA2_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA2_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA2_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA2_BF_MANROBOD= 0x0150, /*!< Reaction on BOD */
+ TFA2_BF_BODE = 0x0160, /*!< BOD Enable */
+ TFA2_BF_BODHYS= 0x0170, /*!< BOD Hysteresis */
+ TFA2_BF_BODFILT= 0x0181, /*!< BOD filter */
+ TFA2_BF_BODTHLVL= 0x01a1, /*!< BOD threshold */
+ TFA2_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA2_BF_RCVNS = 0x01e0, /*!< Noise shaper selection */
+ TFA2_BF_MANWDE= 0x01f0, /*!< Watchdog manager reaction */
+ TFA2_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA2_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA2_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA2_BF_BYPHVBF= 0x02b0, /*!< Bypass HVBAT filter */
+ TFA2_BF_LDOBYP= 0x02c0, /*!< Receiver LDO bypass */
+ TFA2_BF_REV = 0x030f, /*!< Revision info */
+ TFA2_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA2_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA2_BF_SSLEFTE= 0x0500, /*!< Enable left channel */
+ TFA2_BF_SSRIGHTE= 0x0510, /*!< Enable right channel */
+ TFA2_BF_VSLEFTE= 0x0520, /*!< Voltage sense left */
+ TFA2_BF_VSRIGHTE= 0x0530, /*!< Voltage sense right */
+ TFA2_BF_CSLEFTE= 0x0540, /*!< Current sense left */
+ TFA2_BF_CSRIGHTE= 0x0550, /*!< Current sense right */
+ TFA2_BF_SSPDME= 0x0560, /*!< Sub-system PDM */
+ TFA2_BF_STGAIN= 0x0d18, /*!< Side tone gain */
+ TFA2_BF_PDMSMUTE= 0x0da0, /*!< Side tone soft mute */
+ TFA2_BF_SWVSTEP= 0x0e06, /*!< Register for the host SW to record the current active vstep */
+ TFA2_BF_VDDS = 0x1000, /*!< POR */
+ TFA2_BF_PLLS = 0x1010, /*!< PLL lock */
+ TFA2_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA2_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA2_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA2_BF_CLKS = 0x1050, /*!< Clocks stable */
+ TFA2_BF_MTPB = 0x1060, /*!< MTP busy */
+ TFA2_BF_NOCLK = 0x1070, /*!< Lost clock */
+ TFA2_BF_SPKS = 0x1080, /*!< Speaker error */
+ TFA2_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA2_BF_SWS = 0x10a0, /*!< Amplifier engage */
+ TFA2_BF_WDS = 0x10b0, /*!< Watchdog */
+ TFA2_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA2_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA2_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA2_BF_BODNOK= 0x10f0, /*!< BOD */
+ TFA2_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA2_BF_DCDCA = 0x1110, /*!< DCDC active */
+ TFA2_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos */
+ TFA2_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA2_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA2_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA2_BF_STMUTEB= 0x1170, /*!< side tone (un)mute busy */
+ TFA2_BF_STMUTE= 0x1180, /*!< side tone mute state */
+ TFA2_BF_TDMLUTER= 0x1190, /*!< TDM LUT error */
+ TFA2_BF_TDMSTAT= 0x11a2, /*!< TDM status bits */
+ TFA2_BF_TDMERR= 0x11d0, /*!< TDM error */
+ TFA2_BF_HAPTIC= 0x11e0, /*!< Status haptic driver */
+ TFA2_BF_OCPOAPL= 0x1200, /*!< OCPOK pmos A left */
+ TFA2_BF_OCPOANL= 0x1210, /*!< OCPOK nmos A left */
+ TFA2_BF_OCPOBPL= 0x1220, /*!< OCPOK pmos B left */
+ TFA2_BF_OCPOBNL= 0x1230, /*!< OCPOK nmos B left */
+ TFA2_BF_CLIPAHL= 0x1240, /*!< Clipping A left to Vddp */
+ TFA2_BF_CLIPALL= 0x1250, /*!< Clipping A left to gnd */
+ TFA2_BF_CLIPBHL= 0x1260, /*!< Clipping B left to Vddp */
+ TFA2_BF_CLIPBLL= 0x1270, /*!< Clipping B left to gnd */
+ TFA2_BF_OCPOAPRC= 0x1280, /*!< OCPOK pmos A RCV */
+ TFA2_BF_OCPOANRC= 0x1290, /*!< OCPOK nmos A RCV */
+ TFA2_BF_OCPOBPRC= 0x12a0, /*!< OCPOK pmos B RCV */
+ TFA2_BF_OCPOBNRC= 0x12b0, /*!< OCPOK nmos B RCV */
+ TFA2_BF_RCVLDOR= 0x12c0, /*!< RCV LDO regulates */
+ TFA2_BF_RCVLDOBR= 0x12d0, /*!< Receiver LDO ready */
+ TFA2_BF_OCDSL = 0x12e0, /*!< OCP left amplifier */
+ TFA2_BF_CLIPSL= 0x12f0, /*!< Amplifier left clipping */
+ TFA2_BF_OCPOAPR= 0x1300, /*!< OCPOK pmos A right */
+ TFA2_BF_OCPOANR= 0x1310, /*!< OCPOK nmos A right */
+ TFA2_BF_OCPOBPR= 0x1320, /*!< OCPOK pmos B right */
+ TFA2_BF_OCPOBNR= 0x1330, /*!< OCPOK nmos B right */
+ TFA2_BF_CLIPAHR= 0x1340, /*!< Clipping A right to Vddp */
+ TFA2_BF_CLIPALR= 0x1350, /*!< Clipping A right to gnd */
+ TFA2_BF_CLIPBHR= 0x1360, /*!< Clipping B left to Vddp */
+ TFA2_BF_CLIPBLR= 0x1370, /*!< Clipping B right to gnd */
+ TFA2_BF_OCDSR = 0x1380, /*!< OCP right amplifier */
+ TFA2_BF_CLIPSR= 0x1390, /*!< Amplifier right clipping */
+ TFA2_BF_OCPOKMC= 0x13a0, /*!< OCPOK MICVDD */
+ TFA2_BF_MANALARM= 0x13b0, /*!< Alarm state */
+ TFA2_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA2_BF_MANWAIT2= 0x13d0, /*!< Wait CF config */
+ TFA2_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA2_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA2_BF_SPKSL = 0x1400, /*!< Left speaker status */
+ TFA2_BF_SPKSR = 0x1410, /*!< Right speaker status */
+ TFA2_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA2_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA2_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA2_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA2_BF_TDMUC = 0x2003, /*!< Usecase setting */
+ TFA2_BF_TDME = 0x2040, /*!< Enable interface */
+ TFA2_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA2_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA2_BF_TDMFSLN= 0x2073, /*!< FS length (master mode only) */
+ TFA2_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA2_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA2_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA2_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA2_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA2_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA2_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA2_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA2_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA2_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA2_BF_TDMTXUS0= 0x2291, /*!< Format unused slots GAINIO */
+ TFA2_BF_TDMTXUS1= 0x22b1, /*!< Format unused slots DIO1 */
+ TFA2_BF_TDMTXUS2= 0x22d1, /*!< Format unused slots DIO2 */
+ TFA2_BF_TDMLE = 0x2310, /*!< Control audio left */
+ TFA2_BF_TDMRE = 0x2320, /*!< Control audio right */
+ TFA2_BF_TDMVSRE= 0x2340, /*!< Control voltage sense right */
+ TFA2_BF_TDMCSRE= 0x2350, /*!< Control current sense right */
+ TFA2_BF_TDMVSLE= 0x2360, /*!< Voltage sense left control */
+ TFA2_BF_TDMCSLE= 0x2370, /*!< Current sense left control */
+ TFA2_BF_TDMCFRE= 0x2380, /*!< DSP out right control */
+ TFA2_BF_TDMCFLE= 0x2390, /*!< DSP out left control */
+ TFA2_BF_TDMCF3E= 0x23a0, /*!< AEC ref left control */
+ TFA2_BF_TDMCF4E= 0x23b0, /*!< AEC ref right control */
+ TFA2_BF_TDMPD1E= 0x23c0, /*!< PDM 1 control */
+ TFA2_BF_TDMPD2E= 0x23d0, /*!< PDM 2 control */
+ TFA2_BF_TDMLIO= 0x2421, /*!< IO audio left */
+ TFA2_BF_TDMRIO= 0x2441, /*!< IO audio right */
+ TFA2_BF_TDMVSRIO= 0x2481, /*!< IO voltage sense right */
+ TFA2_BF_TDMCSRIO= 0x24a1, /*!< IO current sense right */
+ TFA2_BF_TDMVSLIO= 0x24c1, /*!< IO voltage sense left */
+ TFA2_BF_TDMCSLIO= 0x24e1, /*!< IO current sense left */
+ TFA2_BF_TDMCFRIO= 0x2501, /*!< IO dspout right */
+ TFA2_BF_TDMCFLIO= 0x2521, /*!< IO dspout left */
+ TFA2_BF_TDMCF3IO= 0x2541, /*!< IO AEC ref left control */
+ TFA2_BF_TDMCF4IO= 0x2561, /*!< IO AEC ref right control */
+ TFA2_BF_TDMPD1IO= 0x2581, /*!< IO pdm1 */
+ TFA2_BF_TDMPD2IO= 0x25a1, /*!< IO pdm2 */
+ TFA2_BF_TDMLS = 0x2643, /*!< Position audio left */
+ TFA2_BF_TDMRS = 0x2683, /*!< Position audio right */
+ TFA2_BF_TDMVSRS= 0x2703, /*!< Position voltage sense right */
+ TFA2_BF_TDMCSRS= 0x2743, /*!< Position current sense right */
+ TFA2_BF_TDMVSLS= 0x2783, /*!< Position voltage sense left */
+ TFA2_BF_TDMCSLS= 0x27c3, /*!< Position current sense left */
+ TFA2_BF_TDMCFRS= 0x2803, /*!< Position dspout right */
+ TFA2_BF_TDMCFLS= 0x2843, /*!< Position dspout left */
+ TFA2_BF_TDMCF3S= 0x2883, /*!< Position AEC ref left control */
+ TFA2_BF_TDMCF4S= 0x28c3, /*!< Position AEC ref right control */
+ TFA2_BF_TDMPD1S= 0x2903, /*!< Position pdm1 */
+ TFA2_BF_TDMPD2S= 0x2943, /*!< Position pdm2 */
+ TFA2_BF_PDMSM = 0x3100, /*!< PDM control */
+ TFA2_BF_PDMSTSEL= 0x3111, /*!< Side tone input */
+ TFA2_BF_PDMLSEL= 0x3130, /*!< PDM data selection for left channel during PDM direct mode */
+ TFA2_BF_PDMRSEL= 0x3140, /*!< PDM data selection for right channel during PDM direct mode */
+ TFA2_BF_MICVDDE= 0x3150, /*!< Enable MICVDD */
+ TFA2_BF_PDMCLRAT= 0x3201, /*!< PDM BCK/Fs ratio */
+ TFA2_BF_PDMGAIN= 0x3223, /*!< PDM gain */
+ TFA2_BF_PDMOSEL= 0x3263, /*!< PDM output selection - RE/FE data combination */
+ TFA2_BF_SELCFHAPD= 0x32a0, /*!< Select the source for haptic data output (not for customer) */
+ TFA2_BF_HAPTIME= 0x3307, /*!< Duration (ms) */
+ TFA2_BF_HAPLEVEL= 0x3387, /*!< DC value (FFS) */
+ TFA2_BF_GPIODIN= 0x3403, /*!< Receiving value */
+ TFA2_BF_GPIOCTRL= 0x3500, /*!< GPIO master control over GPIO1/2 ports (not for customer) */
+ TFA2_BF_GPIOCONF= 0x3513, /*!< Configuration */
+ TFA2_BF_GPIODOUT= 0x3553, /*!< Transmitting value */
+ TFA2_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA2_BF_ISTPLLS= 0x4010, /*!< Status PLL lock */
+ TFA2_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA2_BF_ISTOVDS= 0x4030, /*!< Status OVP alarm */
+ TFA2_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA2_BF_ISTCLKS= 0x4050, /*!< Status clocks stable */
+ TFA2_BF_ISTMTPB= 0x4060, /*!< Status MTP busy */
+ TFA2_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA2_BF_ISTSPKS= 0x4080, /*!< Status speaker error */
+ TFA2_BF_ISTACS= 0x4090, /*!< Status cold start */
+ TFA2_BF_ISTSWS= 0x40a0, /*!< Status amplifier engage */
+ TFA2_BF_ISTWDS= 0x40b0, /*!< Status watchdog */
+ TFA2_BF_ISTAMPS= 0x40c0, /*!< Status amplifier enable */
+ TFA2_BF_ISTAREFS= 0x40d0, /*!< Status Ref enable */
+ TFA2_BF_ISTADCCR= 0x40e0, /*!< Status Control ADC */
+ TFA2_BF_ISTBODNOK= 0x40f0, /*!< Status BOD */
+ TFA2_BF_ISTBSTCU= 0x4100, /*!< Status DCDC current limiting */
+ TFA2_BF_ISTBSTHI= 0x4110, /*!< Status DCDC active */
+ TFA2_BF_ISTBSTOC= 0x4120, /*!< Status DCDC OCP */
+ TFA2_BF_ISTBSTPKCUR= 0x4130, /*!< Status bst peakcur */
+ TFA2_BF_ISTBSTVC= 0x4140, /*!< Status DCDC level 1x */
+ TFA2_BF_ISTBST86= 0x4150, /*!< Status DCDC level 1.14x */
+ TFA2_BF_ISTBST93= 0x4160, /*!< Status DCDC level 1.07x */
+ TFA2_BF_ISTRCVLD= 0x4170, /*!< Status rcvldop ready */
+ TFA2_BF_ISTOCPL= 0x4180, /*!< Status ocp alarm left */
+ TFA2_BF_ISTOCPR= 0x4190, /*!< Status ocp alarm right */
+ TFA2_BF_ISTMWSRC= 0x41a0, /*!< Status Waits HW I2C settings */
+ TFA2_BF_ISTMWCFC= 0x41b0, /*!< Status waits CF config */
+ TFA2_BF_ISTMWSMU= 0x41c0, /*!< Status Audio mute sequence */
+ TFA2_BF_ISTCFMER= 0x41d0, /*!< Status cfma error */
+ TFA2_BF_ISTCFMAC= 0x41e0, /*!< Status cfma ack */
+ TFA2_BF_ISTCLKOOR= 0x41f0, /*!< Status flag_clk_out_of_range */
+ TFA2_BF_ISTTDMER= 0x4200, /*!< Status tdm error */
+ TFA2_BF_ISTCLPL= 0x4210, /*!< Status clip left */
+ TFA2_BF_ISTCLPR= 0x4220, /*!< Status clip right */
+ TFA2_BF_ISTOCPM= 0x4230, /*!< Status mic ocpok */
+ TFA2_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA2_BF_ICLPLLS= 0x4410, /*!< Clear PLL lock */
+ TFA2_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA2_BF_ICLOVDS= 0x4430, /*!< Clear OVP alarm */
+ TFA2_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA2_BF_ICLCLKS= 0x4450, /*!< Clear clocks stable */
+ TFA2_BF_ICLMTPB= 0x4460, /*!< Clear mtp busy */
+ TFA2_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA2_BF_ICLSPKS= 0x4480, /*!< Clear speaker error */
+ TFA2_BF_ICLACS= 0x4490, /*!< Clear cold started */
+ TFA2_BF_ICLSWS= 0x44a0, /*!< Clear amplifier engage */
+ TFA2_BF_ICLWDS= 0x44b0, /*!< Clear watchdog */
+ TFA2_BF_ICLAMPS= 0x44c0, /*!< Clear enbl amp */
+ TFA2_BF_ICLAREFS= 0x44d0, /*!< Clear ref enable */
+ TFA2_BF_ICLADCCR= 0x44e0, /*!< Clear control ADC */
+ TFA2_BF_ICLBODNOK= 0x44f0, /*!< Clear BOD */
+ TFA2_BF_ICLBSTCU= 0x4500, /*!< Clear DCDC current limiting */
+ TFA2_BF_ICLBSTHI= 0x4510, /*!< Clear DCDC active */
+ TFA2_BF_ICLBSTOC= 0x4520, /*!< Clear DCDC OCP */
+ TFA2_BF_ICLBSTPC= 0x4530, /*!< Clear bst peakcur */
+ TFA2_BF_ICLBSTVC= 0x4540, /*!< Clear DCDC level 1x */
+ TFA2_BF_ICLBST86= 0x4550, /*!< Clear DCDC level 1.14x */
+ TFA2_BF_ICLBST93= 0x4560, /*!< Clear DCDC level 1.07x */
+ TFA2_BF_ICLRCVLD= 0x4570, /*!< Clear rcvldop ready */
+ TFA2_BF_ICLOCPL= 0x4580, /*!< Clear ocp alarm left */
+ TFA2_BF_ICLOCPR= 0x4590, /*!< Clear ocp alarm right */
+ TFA2_BF_ICLMWSRC= 0x45a0, /*!< Clear wait HW I2C settings */
+ TFA2_BF_ICLMWCFC= 0x45b0, /*!< Clear wait cf config */
+ TFA2_BF_ICLMWSMU= 0x45c0, /*!< Clear audio mute sequence */
+ TFA2_BF_ICLCFMER= 0x45d0, /*!< Clear cfma err */
+ TFA2_BF_ICLCFMAC= 0x45e0, /*!< Clear cfma ack */
+ TFA2_BF_ICLCLKOOR= 0x45f0, /*!< Clear flag_clk_out_of_range */
+ TFA2_BF_ICLTDMER= 0x4600, /*!< Clear tdm error */
+ TFA2_BF_ICLCLPL= 0x4610, /*!< Clear clip left */
+ TFA2_BF_ICLCLPR= 0x4620, /*!< Clear clip right */
+ TFA2_BF_ICLOCPM= 0x4630, /*!< Clear mic ocpok */
+ TFA2_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA2_BF_IEPLLS= 0x4810, /*!< Enable pll lock */
+ TFA2_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA2_BF_IEOVDS= 0x4830, /*!< Enable OVP alarm */
+ TFA2_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA2_BF_IECLKS= 0x4850, /*!< Enable clocks stable */
+ TFA2_BF_IEMTPB= 0x4860, /*!< Enable mtp busy */
+ TFA2_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA2_BF_IESPKS= 0x4880, /*!< Enable speaker error */
+ TFA2_BF_IEACS = 0x4890, /*!< Enable cold started */
+ TFA2_BF_IESWS = 0x48a0, /*!< Enable amplifier engage */
+ TFA2_BF_IEWDS = 0x48b0, /*!< Enable watchdog */
+ TFA2_BF_IEAMPS= 0x48c0, /*!< Enable enbl amp */
+ TFA2_BF_IEAREFS= 0x48d0, /*!< Enable ref enable */
+ TFA2_BF_IEADCCR= 0x48e0, /*!< Enable Control ADC */
+ TFA2_BF_IEBODNOK= 0x48f0, /*!< Enable BOD */
+ TFA2_BF_IEBSTCU= 0x4900, /*!< Enable DCDC current limiting */
+ TFA2_BF_IEBSTHI= 0x4910, /*!< Enable DCDC active */
+ TFA2_BF_IEBSTOC= 0x4920, /*!< Enable DCDC OCP */
+ TFA2_BF_IEBSTPC= 0x4930, /*!< Enable bst peakcur */
+ TFA2_BF_IEBSTVC= 0x4940, /*!< Enable DCDC level 1x */
+ TFA2_BF_IEBST86= 0x4950, /*!< Enable DCDC level 1.14x */
+ TFA2_BF_IEBST93= 0x4960, /*!< Enable DCDC level 1.07x */
+ TFA2_BF_IERCVLD= 0x4970, /*!< Enable rcvldop ready */
+ TFA2_BF_IEOCPL= 0x4980, /*!< Enable ocp alarm left */
+ TFA2_BF_IEOCPR= 0x4990, /*!< Enable ocp alarm right */
+ TFA2_BF_IEMWSRC= 0x49a0, /*!< Enable waits HW I2C settings */
+ TFA2_BF_IEMWCFC= 0x49b0, /*!< Enable man wait cf config */
+ TFA2_BF_IEMWSMU= 0x49c0, /*!< Enable man Audio mute sequence */
+ TFA2_BF_IECFMER= 0x49d0, /*!< Enable cfma err */
+ TFA2_BF_IECFMAC= 0x49e0, /*!< Enable cfma ack */
+ TFA2_BF_IECLKOOR= 0x49f0, /*!< Enable flag_clk_out_of_range */
+ TFA2_BF_IETDMER= 0x4a00, /*!< Enable tdm error */
+ TFA2_BF_IECLPL= 0x4a10, /*!< Enable clip left */
+ TFA2_BF_IECLPR= 0x4a20, /*!< Enable clip right */
+ TFA2_BF_IEOCPM1= 0x4a30, /*!< Enable mic ocpok */
+ TFA2_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA2_BF_IPOPLLS= 0x4c10, /*!< Polarity pll lock */
+ TFA2_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA2_BF_IPOOVDS= 0x4c30, /*!< Polarity OVP alarm */
+ TFA2_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA2_BF_IPOCLKS= 0x4c50, /*!< Polarity clocks stable */
+ TFA2_BF_IPOMTPB= 0x4c60, /*!< Polarity mtp busy */
+ TFA2_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA2_BF_IPOSPKS= 0x4c80, /*!< Polarity speaker error */
+ TFA2_BF_IPOACS= 0x4c90, /*!< Polarity cold started */
+ TFA2_BF_IPOSWS= 0x4ca0, /*!< Polarity amplifier engage */
+ TFA2_BF_IPOWDS= 0x4cb0, /*!< Polarity watchdog */
+ TFA2_BF_IPOAMPS= 0x4cc0, /*!< Polarity enbl amp */
+ TFA2_BF_IPOAREFS= 0x4cd0, /*!< Polarity ref enable */
+ TFA2_BF_IPOADCCR= 0x4ce0, /*!< Polarity Control ADC */
+ TFA2_BF_IPOBODNOK= 0x4cf0, /*!< Polarity BOD */
+ TFA2_BF_IPOBSTCU= 0x4d00, /*!< Polarity DCDC current limiting */
+ TFA2_BF_IPOBSTHI= 0x4d10, /*!< Polarity DCDC active */
+ TFA2_BF_IPOBSTOC= 0x4d20, /*!< Polarity DCDC OCP */
+ TFA2_BF_IPOBSTPC= 0x4d30, /*!< Polarity bst peakcur */
+ TFA2_BF_IPOBSTVC= 0x4d40, /*!< Polarity DCDC level 1x */
+ TFA2_BF_IPOBST86= 0x4d50, /*!< Polarity DCDC level 1.14x */
+ TFA2_BF_IPOBST93= 0x4d60, /*!< Polarity DCDC level 1.07x */
+ TFA2_BF_IPORCVLD= 0x4d70, /*!< Polarity rcvldop ready */
+ TFA2_BF_IPOOCPL= 0x4d80, /*!< Polarity ocp alarm left */
+ TFA2_BF_IPOOCPR= 0x4d90, /*!< Polarity ocp alarm right */
+ TFA2_BF_IPOMWSRC= 0x4da0, /*!< Polarity waits HW I2C settings */
+ TFA2_BF_IPOMWCFC= 0x4db0, /*!< Polarity man wait cf config */
+ TFA2_BF_IPOMWSMU= 0x4dc0, /*!< Polarity man audio mute sequence */
+ TFA2_BF_IPOCFMER= 0x4dd0, /*!< Polarity cfma err */
+ TFA2_BF_IPOCFMAC= 0x4de0, /*!< Polarity cfma ack */
+ TFA2_BF_IPCLKOOR= 0x4df0, /*!< Polarity flag_clk_out_of_range */
+ TFA2_BF_IPOTDMER= 0x4e00, /*!< Polarity tdm error */
+ TFA2_BF_IPOCLPL= 0x4e10, /*!< Polarity clip left */
+ TFA2_BF_IPOCLPR= 0x4e20, /*!< Polarity clip right */
+ TFA2_BF_IPOOCPM= 0x4e30, /*!< Polarity mic ocpok */
+ TFA2_BF_BSSCR = 0x5001, /*!< Battery protection attack Time */
+ TFA2_BF_BSST = 0x5023, /*!< Battery protection threshold voltage level */
+ TFA2_BF_BSSRL = 0x5061, /*!< Battery protection maximum reduction */
+ TFA2_BF_BSSRR = 0x5082, /*!< Battery protection release time */
+ TFA2_BF_BSSHY = 0x50b1, /*!< Battery protection hysteresis */
+ TFA2_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA2_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA2_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA2_BF_INTSMUTE= 0x5110, /*!< Soft mute HW */
+ TFA2_BF_CFSML = 0x5120, /*!< Soft mute FW left */
+ TFA2_BF_CFSMR = 0x5130, /*!< Soft mute FW right */
+ TFA2_BF_HPFBYPL= 0x5140, /*!< Bypass HPF left */
+ TFA2_BF_HPFBYPR= 0x5150, /*!< Bypass HPF right */
+ TFA2_BF_DPSAL = 0x5160, /*!< Enable DPSA left */
+ TFA2_BF_DPSAR = 0x5170, /*!< Enable DPSA right */
+ TFA2_BF_VOL = 0x5187, /*!< FW volume control for primary audio channel */
+ TFA2_BF_HNDSFRCV= 0x5200, /*!< Selection receiver */
+ TFA2_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA2_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA2_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA2_BF_SLOPESET= 0x52e1, /*!< Set slope */
+ TFA2_BF_VOLSEC= 0x5a07, /*!< FW volume control for secondary audio channel */
+ TFA2_BF_SWPROFIL= 0x5a87, /*!< Software profile data */
+ TFA2_BF_DCVO = 0x7002, /*!< Boost voltage */
+ TFA2_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA2_BF_DCCV = 0x7071, /*!< Coil Value */
+ TFA2_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA2_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA2_BF_DCSYNCP= 0x70b2, /*!< DCDC synchronization off + 7 positions */
+ TFA2_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA2_BF_RST = 0x9000, /*!< Reset */
+ TFA2_BF_DMEM = 0x9011, /*!< Target memory */
+ TFA2_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA2_BF_CFINT = 0x9040, /*!< Interrupt - auto clear */
+ TFA2_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA2_BF_REQ = 0x9087, /*!< request for access (8 channels) */
+ TFA2_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA2_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA2_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA2_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA2_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA2_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA2_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA2_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA2_BF_MADD = 0x910f, /*!< Memory address */
+ TFA2_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA2_BF_ERR = 0x9307, /*!< Error flags */
+ TFA2_BF_ACK = 0x9387, /*!< Acknowledge of requests */
+ TFA2_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA2_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA2_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA2_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA2_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA2_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA2_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA2_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA2_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA2_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA2_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA2_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA2_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA2_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA2_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA2_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA2_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA2_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA2_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA2_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA2_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA2_BF_R25CL = 0xf40f, /*!< Ron resistance of left channel speaker coil */
+ TFA2_BF_R25CR = 0xf50f, /*!< Ron resistance of right channel speaker coil */
+} Tfa2BfEnumList_t;
+#define TFA2_NAMETABLE static tfaBfName_t Tfa2DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x91, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x150, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x160, "BODE"}, /* BOD Enable , */\
+ { 0x170, "BODHYS"}, /* BOD Hysteresis , */\
+ { 0x181, "BODFILT"}, /* BOD filter , */\
+ { 0x1a1, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "RCVNS"}, /* Noise shaper selection , */\
+ { 0x1f0, "MANWDE"}, /* Watchdog manager reaction , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b0, "BYPHVBF"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "LDOBYP"}, /* Receiver LDO bypass , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x500, "SSLEFTE"}, /* Enable left channel , */\
+ { 0x510, "SSRIGHTE"}, /* Enable right channel , */\
+ { 0x520, "VSLEFTE"}, /* Voltage sense left , */\
+ { 0x530, "VSRIGHTE"}, /* Voltage sense right , */\
+ { 0x540, "CSLEFTE"}, /* Current sense left , */\
+ { 0x550, "CSRIGHTE"}, /* Current sense right , */\
+ { 0x560, "SSPDME"}, /* Sub-system PDM , */\
+ { 0xd18, "STGAIN"}, /* Side tone gain , */\
+ { 0xda0, "PDMSMUTE"}, /* Side tone soft mute , */\
+ { 0xe06, "SWVSTEP"}, /* Register for the host SW to record the current active vstep, */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "CLKS"}, /* Clocks stable , */\
+ { 0x1060, "MTPB"}, /* MTP busy , */\
+ { 0x1070, "NOCLK"}, /* Lost clock , */\
+ { 0x1080, "SPKS"}, /* Speaker error , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "SWS"}, /* Amplifier engage , */\
+ { 0x10b0, "WDS"}, /* Watchdog , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "STMUTEB"}, /* side tone (un)mute busy , */\
+ { 0x1180, "STMUTE"}, /* side tone mute state , */\
+ { 0x1190, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11a2, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11d0, "TDMERR"}, /* TDM error , */\
+ { 0x11e0, "HAPTIC"}, /* Status haptic driver , */\
+ { 0x1200, "OCPOAPL"}, /* OCPOK pmos A left , */\
+ { 0x1210, "OCPOANL"}, /* OCPOK nmos A left , */\
+ { 0x1220, "OCPOBPL"}, /* OCPOK pmos B left , */\
+ { 0x1230, "OCPOBNL"}, /* OCPOK nmos B left , */\
+ { 0x1240, "CLIPAHL"}, /* Clipping A left to Vddp , */\
+ { 0x1250, "CLIPALL"}, /* Clipping A left to gnd , */\
+ { 0x1260, "CLIPBHL"}, /* Clipping B left to Vddp , */\
+ { 0x1270, "CLIPBLL"}, /* Clipping B left to gnd , */\
+ { 0x1280, "OCPOAPRC"}, /* OCPOK pmos A RCV , */\
+ { 0x1290, "OCPOANRC"}, /* OCPOK nmos A RCV , */\
+ { 0x12a0, "OCPOBPRC"}, /* OCPOK pmos B RCV , */\
+ { 0x12b0, "OCPOBNRC"}, /* OCPOK nmos B RCV , */\
+ { 0x12c0, "RCVLDOR"}, /* RCV LDO regulates , */\
+ { 0x12d0, "RCVLDOBR"}, /* Receiver LDO ready , */\
+ { 0x12e0, "OCDSL"}, /* OCP left amplifier , */\
+ { 0x12f0, "CLIPSL"}, /* Amplifier left clipping , */\
+ { 0x1300, "OCPOAPR"}, /* OCPOK pmos A right , */\
+ { 0x1310, "OCPOANR"}, /* OCPOK nmos A right , */\
+ { 0x1320, "OCPOBPR"}, /* OCPOK pmos B right , */\
+ { 0x1330, "OCPOBNR"}, /* OCPOK nmos B right , */\
+ { 0x1340, "CLIPAHR"}, /* Clipping A right to Vddp , */\
+ { 0x1350, "CLIPALR"}, /* Clipping A right to gnd , */\
+ { 0x1360, "CLIPBHR"}, /* Clipping B left to Vddp , */\
+ { 0x1370, "CLIPBLR"}, /* Clipping B right to gnd , */\
+ { 0x1380, "OCDSR"}, /* OCP right amplifier , */\
+ { 0x1390, "CLIPSR"}, /* Amplifier right clipping , */\
+ { 0x13a0, "OCPOKMC"}, /* OCPOK MICVDD , */\
+ { 0x13b0, "MANALARM"}, /* Alarm state , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "MANWAIT2"}, /* Wait CF config , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1400, "SPKSL"}, /* Left speaker status , */\
+ { 0x1410, "SPKSR"}, /* Right speaker status , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x2003, "TDMUC"}, /* Usecase setting , */\
+ { 0x2040, "TDME"}, /* Enable interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "TDMTXUS1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "TDMTXUS2"}, /* Format unused slots DIO2 , */\
+ { 0x2310, "TDMLE"}, /* Control audio left , */\
+ { 0x2320, "TDMRE"}, /* Control audio right , */\
+ { 0x2340, "TDMVSRE"}, /* Control voltage sense right , */\
+ { 0x2350, "TDMCSRE"}, /* Control current sense right , */\
+ { 0x2360, "TDMVSLE"}, /* Voltage sense left control , */\
+ { 0x2370, "TDMCSLE"}, /* Current sense left control , */\
+ { 0x2380, "TDMCFRE"}, /* DSP out right control , */\
+ { 0x2390, "TDMCFLE"}, /* DSP out left control , */\
+ { 0x23a0, "TDMCF3E"}, /* AEC ref left control , */\
+ { 0x23b0, "TDMCF4E"}, /* AEC ref right control , */\
+ { 0x23c0, "TDMPD1E"}, /* PDM 1 control , */\
+ { 0x23d0, "TDMPD2E"}, /* PDM 2 control , */\
+ { 0x2421, "TDMLIO"}, /* IO audio left , */\
+ { 0x2441, "TDMRIO"}, /* IO audio right , */\
+ { 0x2481, "TDMVSRIO"}, /* IO voltage sense right , */\
+ { 0x24a1, "TDMCSRIO"}, /* IO current sense right , */\
+ { 0x24c1, "TDMVSLIO"}, /* IO voltage sense left , */\
+ { 0x24e1, "TDMCSLIO"}, /* IO current sense left , */\
+ { 0x2501, "TDMCFRIO"}, /* IO dspout right , */\
+ { 0x2521, "TDMCFLIO"}, /* IO dspout left , */\
+ { 0x2541, "TDMCF3IO"}, /* IO AEC ref left control , */\
+ { 0x2561, "TDMCF4IO"}, /* IO AEC ref right control , */\
+ { 0x2581, "TDMPD1IO"}, /* IO pdm1 , */\
+ { 0x25a1, "TDMPD2IO"}, /* IO pdm2 , */\
+ { 0x2643, "TDMLS"}, /* Position audio left , */\
+ { 0x2683, "TDMRS"}, /* Position audio right , */\
+ { 0x2703, "TDMVSRS"}, /* Position voltage sense right , */\
+ { 0x2743, "TDMCSRS"}, /* Position current sense right , */\
+ { 0x2783, "TDMVSLS"}, /* Position voltage sense left , */\
+ { 0x27c3, "TDMCSLS"}, /* Position current sense left , */\
+ { 0x2803, "TDMCFRS"}, /* Position dspout right , */\
+ { 0x2843, "TDMCFLS"}, /* Position dspout left , */\
+ { 0x2883, "TDMCF3S"}, /* Position AEC ref left control , */\
+ { 0x28c3, "TDMCF4S"}, /* Position AEC ref right control , */\
+ { 0x2903, "TDMPD1S"}, /* Position pdm1 , */\
+ { 0x2943, "TDMPD2S"}, /* Position pdm2 , */\
+ { 0x3100, "PDMSM"}, /* PDM control , */\
+ { 0x3111, "PDMSTSEL"}, /* Side tone input , */\
+ { 0x3130, "PDMLSEL"}, /* PDM data selection for left channel during PDM direct mode, */\
+ { 0x3140, "PDMRSEL"}, /* PDM data selection for right channel during PDM direct mode, */\
+ { 0x3150, "MICVDDE"}, /* Enable MICVDD , */\
+ { 0x3201, "PDMCLRAT"}, /* PDM BCK/Fs ratio , */\
+ { 0x3223, "PDMGAIN"}, /* PDM gain , */\
+ { 0x3263, "PDMOSEL"}, /* PDM output selection - RE/FE data combination , */\
+ { 0x32a0, "SELCFHAPD"}, /* Select the source for haptic data output (not for customer), */\
+ { 0x3307, "HAPTIME"}, /* Duration (ms) , */\
+ { 0x3387, "HAPLEVEL"}, /* DC value (FFS) , */\
+ { 0x3403, "GPIODIN"}, /* Receiving value , */\
+ { 0x3500, "GPIOCTRL"}, /* GPIO master control over GPIO1/2 ports (not for customer), */\
+ { 0x3513, "GPIOCONF"}, /* Configuration , */\
+ { 0x3553, "GPIODOUT"}, /* Transmitting value , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTPLLS"}, /* Status PLL lock , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOVDS"}, /* Status OVP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTCLKS"}, /* Status clocks stable , */\
+ { 0x4060, "ISTMTPB"}, /* Status MTP busy , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTSPKS"}, /* Status speaker error , */\
+ { 0x4090, "ISTACS"}, /* Status cold start , */\
+ { 0x40a0, "ISTSWS"}, /* Status amplifier engage , */\
+ { 0x40b0, "ISTWDS"}, /* Status watchdog , */\
+ { 0x40c0, "ISTAMPS"}, /* Status amplifier enable , */\
+ { 0x40d0, "ISTAREFS"}, /* Status Ref enable , */\
+ { 0x40e0, "ISTADCCR"}, /* Status Control ADC , */\
+ { 0x40f0, "ISTBODNOK"}, /* Status BOD , */\
+ { 0x4100, "ISTBSTCU"}, /* Status DCDC current limiting , */\
+ { 0x4110, "ISTBSTHI"}, /* Status DCDC active , */\
+ { 0x4120, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4130, "ISTBSTPKCUR"}, /* Status bst peakcur , */\
+ { 0x4140, "ISTBSTVC"}, /* Status DCDC level 1x , */\
+ { 0x4150, "ISTBST86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "ISTBST93"}, /* Status DCDC level 1.07x , */\
+ { 0x4170, "ISTRCVLD"}, /* Status rcvldop ready , */\
+ { 0x4180, "ISTOCPL"}, /* Status ocp alarm left , */\
+ { 0x4190, "ISTOCPR"}, /* Status ocp alarm right , */\
+ { 0x41a0, "ISTMWSRC"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "ISTMWCFC"}, /* Status waits CF config , */\
+ { 0x41c0, "ISTMWSMU"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x41e0, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x41f0, "ISTCLKOOR"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4210, "ISTCLPL"}, /* Status clip left , */\
+ { 0x4220, "ISTCLPR"}, /* Status clip right , */\
+ { 0x4230, "ISTOCPM"}, /* Status mic ocpok , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLPLLS"}, /* Clear PLL lock , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOVDS"}, /* Clear OVP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLCLKS"}, /* Clear clocks stable , */\
+ { 0x4460, "ICLMTPB"}, /* Clear mtp busy , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLSPKS"}, /* Clear speaker error , */\
+ { 0x4490, "ICLACS"}, /* Clear cold started , */\
+ { 0x44a0, "ICLSWS"}, /* Clear amplifier engage , */\
+ { 0x44b0, "ICLWDS"}, /* Clear watchdog , */\
+ { 0x44c0, "ICLAMPS"}, /* Clear enbl amp , */\
+ { 0x44d0, "ICLAREFS"}, /* Clear ref enable , */\
+ { 0x44e0, "ICLADCCR"}, /* Clear control ADC , */\
+ { 0x44f0, "ICLBODNOK"}, /* Clear BOD , */\
+ { 0x4500, "ICLBSTCU"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "ICLBSTHI"}, /* Clear DCDC active , */\
+ { 0x4520, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4530, "ICLBSTPC"}, /* Clear bst peakcur , */\
+ { 0x4540, "ICLBSTVC"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "ICLBST86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "ICLBST93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4570, "ICLRCVLD"}, /* Clear rcvldop ready , */\
+ { 0x4580, "ICLOCPL"}, /* Clear ocp alarm left , */\
+ { 0x4590, "ICLOCPR"}, /* Clear ocp alarm right , */\
+ { 0x45a0, "ICLMWSRC"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "ICLMWCFC"}, /* Clear wait cf config , */\
+ { 0x45c0, "ICLMWSMU"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x45e0, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x45f0, "ICLCLKOOR"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4610, "ICLCLPL"}, /* Clear clip left , */\
+ { 0x4620, "ICLCLPR"}, /* Clear clip right , */\
+ { 0x4630, "ICLOCPM"}, /* Clear mic ocpok , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEPLLS"}, /* Enable pll lock , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOVDS"}, /* Enable OVP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IECLKS"}, /* Enable clocks stable , */\
+ { 0x4860, "IEMTPB"}, /* Enable mtp busy , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IESPKS"}, /* Enable speaker error , */\
+ { 0x4890, "IEACS"}, /* Enable cold started , */\
+ { 0x48a0, "IESWS"}, /* Enable amplifier engage , */\
+ { 0x48b0, "IEWDS"}, /* Enable watchdog , */\
+ { 0x48c0, "IEAMPS"}, /* Enable enbl amp , */\
+ { 0x48d0, "IEAREFS"}, /* Enable ref enable , */\
+ { 0x48e0, "IEADCCR"}, /* Enable Control ADC , */\
+ { 0x48f0, "IEBODNOK"}, /* Enable BOD , */\
+ { 0x4900, "IEBSTCU"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "IEBSTHI"}, /* Enable DCDC active , */\
+ { 0x4920, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4930, "IEBSTPC"}, /* Enable bst peakcur , */\
+ { 0x4940, "IEBSTVC"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "IEBST86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "IEBST93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4970, "IERCVLD"}, /* Enable rcvldop ready , */\
+ { 0x4980, "IEOCPL"}, /* Enable ocp alarm left , */\
+ { 0x4990, "IEOCPR"}, /* Enable ocp alarm right , */\
+ { 0x49a0, "IEMWSRC"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "IEMWCFC"}, /* Enable man wait cf config , */\
+ { 0x49c0, "IEMWSMU"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "IECFMER"}, /* Enable cfma err , */\
+ { 0x49e0, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x49f0, "IECLKOOR"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4a10, "IECLPL"}, /* Enable clip left , */\
+ { 0x4a20, "IECLPR"}, /* Enable clip right , */\
+ { 0x4a30, "IEOCPM1"}, /* Enable mic ocpok , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOPLLS"}, /* Polarity pll lock , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOVDS"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOCLKS"}, /* Polarity clocks stable , */\
+ { 0x4c60, "IPOMTPB"}, /* Polarity mtp busy , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOSPKS"}, /* Polarity speaker error , */\
+ { 0x4c90, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4ca0, "IPOSWS"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "IPOWDS"}, /* Polarity watchdog , */\
+ { 0x4cc0, "IPOAMPS"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "IPOAREFS"}, /* Polarity ref enable , */\
+ { 0x4ce0, "IPOADCCR"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "IPOBODNOK"}, /* Polarity BOD , */\
+ { 0x4d00, "IPOBSTCU"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "IPOBSTHI"}, /* Polarity DCDC active , */\
+ { 0x4d20, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "IPOBSTPC"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "IPOBSTVC"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "IPOBST86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "IPOBST93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d70, "IPORCVLD"}, /* Polarity rcvldop ready , */\
+ { 0x4d80, "IPOOCPL"}, /* Polarity ocp alarm left , */\
+ { 0x4d90, "IPOOCPR"}, /* Polarity ocp alarm right , */\
+ { 0x4da0, "IPOMWSRC"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "IPOMWCFC"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "IPOMWSMU"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4de0, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4df0, "IPCLKOOR"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4e10, "IPOCLPL"}, /* Polarity clip left , */\
+ { 0x4e20, "IPOCLPR"}, /* Polarity clip right , */\
+ { 0x4e30, "IPOOCPM"}, /* Polarity mic ocpok , */\
+ { 0x5001, "BSSCR"}, /* Battery protection attack Time , */\
+ { 0x5023, "BSST"}, /* Battery protection threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery protection maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery protection release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery protection hysteresis , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5110, "INTSMUTE"}, /* Soft mute HW , */\
+ { 0x5120, "CFSML"}, /* Soft mute FW left , */\
+ { 0x5130, "CFSMR"}, /* Soft mute FW right , */\
+ { 0x5140, "HPFBYPL"}, /* Bypass HPF left , */\
+ { 0x5150, "HPFBYPR"}, /* Bypass HPF right , */\
+ { 0x5160, "DPSAL"}, /* Enable DPSA left , */\
+ { 0x5170, "DPSAR"}, /* Enable DPSA right , */\
+ { 0x5187, "VOL"}, /* FW volume control for primary audio channel , */\
+ { 0x5200, "HNDSFRCV"}, /* Selection receiver , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e1, "SLOPESET"}, /* Set slope , */\
+ { 0x5a07, "VOLSEC"}, /* FW volume control for secondary audio channel , */\
+ { 0x5a87, "SWPROFIL"}, /* Software profile data , */\
+ { 0x7002, "DCVO"}, /* Boost voltage , */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Coil Value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70b2, "DCSYNCP"}, /* DCDC synchronization off + 7 positions , */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x9000, "RST"}, /* Reset , */\
+ { 0x9011, "DMEM"}, /* Target memory , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* Memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* Error flags , */\
+ { 0x9387, "ACK"}, /* Acknowledge of requests , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf40f, "R25CL"}, /* Ron resistance of left channel speaker coil , */\
+ { 0xf50f, "R25CR"}, /* Ron resistance of right channel speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA2_BITNAMETABLE static tfaBfName_t Tfa2BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x91, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x101, "vamp_sel"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "enbl_osc1m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x150, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x160, "enbl_bod"}, /* BOD Enable , */\
+ { 0x170, "enbl_bod_hyst"}, /* BOD Hysteresis , */\
+ { 0x181, "bod_delay"}, /* BOD filter , */\
+ { 0x1a1, "bod_lvlsel"}, /* BOD threshold , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "pwm_sel_rcv_ns"}, /* Noise shaper selection , */\
+ { 0x1f0, "man_enbl_watchdog"}, /* Watchdog manager reaction , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b0, "bypass_hvbat_filter"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "ctrl_rcvldop_bypass"}, /* Receiver LDO bypass , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x500, "enbl_spkr_ss_left"}, /* Enable left channel , */\
+ { 0x510, "enbl_spkr_ss_right"}, /* Enable right channel , */\
+ { 0x520, "enbl_volsense_left"}, /* Voltage sense left , */\
+ { 0x530, "enbl_volsense_right"}, /* Voltage sense right , */\
+ { 0x540, "enbl_cursense_left"}, /* Current sense left , */\
+ { 0x550, "enbl_cursense_right"}, /* Current sense right , */\
+ { 0x560, "enbl_pdm_ss"}, /* Sub-system PDM , */\
+ { 0xd00, "side_tone_gain_sel"}, /* PDM side tone gain selector , */\
+ { 0xd18, "side_tone_gain"}, /* Side tone gain , */\
+ { 0xda0, "mute_side_tone"}, /* Side tone soft mute , */\
+ { 0xe06, "ctrl_digtoana"}, /* Register for the host SW to record the current active vstep, */\
+ { 0xe70, "enbl_cmfb_left"}, /* Current sense common mode feedback control for left channel, */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1060, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1080, "flag_cf_speakererror"}, /* Speaker error , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10b0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_soft_mute_busy"}, /* side tone (un)mute busy , */\
+ { 0x1180, "flag_soft_mute_state"}, /* side tone mute state , */\
+ { 0x1190, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11a2, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11d0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x11e0, "flag_haptic_busy"}, /* Status haptic driver , */\
+ { 0x1200, "flag_ocpokap_left"}, /* OCPOK pmos A left , */\
+ { 0x1210, "flag_ocpokan_left"}, /* OCPOK nmos A left , */\
+ { 0x1220, "flag_ocpokbp_left"}, /* OCPOK pmos B left , */\
+ { 0x1230, "flag_ocpokbn_left"}, /* OCPOK nmos B left , */\
+ { 0x1240, "flag_clipa_high_left"}, /* Clipping A left to Vddp , */\
+ { 0x1250, "flag_clipa_low_left"}, /* Clipping A left to gnd , */\
+ { 0x1260, "flag_clipb_high_left"}, /* Clipping B left to Vddp , */\
+ { 0x1270, "flag_clipb_low_left"}, /* Clipping B left to gnd , */\
+ { 0x1280, "flag_ocpokap_rcv"}, /* OCPOK pmos A RCV , */\
+ { 0x1290, "flag_ocpokan_rcv"}, /* OCPOK nmos A RCV , */\
+ { 0x12a0, "flag_ocpokbp_rcv"}, /* OCPOK pmos B RCV , */\
+ { 0x12b0, "flag_ocpokbn_rcv"}, /* OCPOK nmos B RCV , */\
+ { 0x12c0, "flag_rcvldop_ready"}, /* RCV LDO regulates , */\
+ { 0x12d0, "flag_rcvldop_bypassready"}, /* Receiver LDO ready , */\
+ { 0x12e0, "flag_ocp_alarm_left"}, /* OCP left amplifier , */\
+ { 0x12f0, "flag_clip_left"}, /* Amplifier left clipping , */\
+ { 0x1300, "flag_ocpokap_right"}, /* OCPOK pmos A right , */\
+ { 0x1310, "flag_ocpokan_right"}, /* OCPOK nmos A right , */\
+ { 0x1320, "flag_ocpokbp_right"}, /* OCPOK pmos B right , */\
+ { 0x1330, "flag_ocpokbn_right"}, /* OCPOK nmos B right , */\
+ { 0x1340, "flag_clipa_high_right"}, /* Clipping A right to Vddp , */\
+ { 0x1350, "flag_clipa_low_right"}, /* Clipping A right to gnd , */\
+ { 0x1360, "flag_clipb_high_right"}, /* Clipping B left to Vddp , */\
+ { 0x1370, "flag_clipb_low_right"}, /* Clipping B right to gnd , */\
+ { 0x1380, "flag_ocp_alarm_right"}, /* OCP right amplifier , */\
+ { 0x1390, "flag_clip_right"}, /* Amplifier right clipping , */\
+ { 0x13a0, "flag_mic_ocpok"}, /* OCPOK MICVDD , */\
+ { 0x13b0, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "flag_man_wait_cf_config"}, /* Wait CF config , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1400, "flag_cf_speakererror_left"}, /* Left speaker status , */\
+ { 0x1410, "flag_cf_speakererror_right"}, /* Right speaker status , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x2003, "tdm_usecase"}, /* Usecase setting , */\
+ { 0x2040, "tdm_enable"}, /* Enable interface , */\
+ { 0x2050, "tdm_mode"}, /* Slave/master , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "tdm_txdata_format_unused_slot_sd1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "tdm_txdata_format_unused_slot_sd2"}, /* Format unused slots DIO2 , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control gainin (not used in DSP) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio left , */\
+ { 0x2320, "tdm_sink2_enable"}, /* Control audio right , */\
+ { 0x2330, "tdm_source0_enable"}, /* Control gainout (not used in DSP) , */\
+ { 0x2340, "tdm_source1_enable"}, /* Control voltage sense right , */\
+ { 0x2350, "tdm_source2_enable"}, /* Control current sense right , */\
+ { 0x2360, "tdm_source3_enable"}, /* Voltage sense left control , */\
+ { 0x2370, "tdm_source4_enable"}, /* Current sense left control , */\
+ { 0x2380, "tdm_source5_enable"}, /* DSP out right control , */\
+ { 0x2390, "tdm_source6_enable"}, /* DSP out left control , */\
+ { 0x23a0, "tdm_source7_enable"}, /* AEC ref left control , */\
+ { 0x23b0, "tdm_source8_enable"}, /* AEC ref right control , */\
+ { 0x23c0, "tdm_source9_enable"}, /* PDM 1 control , */\
+ { 0x23d0, "tdm_source10_enable"}, /* PDM 2 control , */\
+ { 0x2401, "tdm_sink0_io"}, /* IO gainin (not used in DSP) , */\
+ { 0x2421, "tdm_sink1_io"}, /* IO audio left , */\
+ { 0x2441, "tdm_sink2_io"}, /* IO audio right , */\
+ { 0x2461, "tdm_source0_io"}, /* IO gainout (not used in DSP) , */\
+ { 0x2481, "tdm_source1_io"}, /* IO voltage sense right , */\
+ { 0x24a1, "tdm_source2_io"}, /* IO current sense right , */\
+ { 0x24c1, "tdm_source3_io"}, /* IO voltage sense left , */\
+ { 0x24e1, "tdm_source4_io"}, /* IO current sense left , */\
+ { 0x2501, "tdm_source5_io"}, /* IO dspout right , */\
+ { 0x2521, "tdm_source6_io"}, /* IO dspout left , */\
+ { 0x2541, "tdm_source7_io"}, /* IO AEC ref left control , */\
+ { 0x2561, "tdm_source8_io"}, /* IO AEC ref right control , */\
+ { 0x2581, "tdm_source9_io"}, /* IO pdm1 , */\
+ { 0x25a1, "tdm_source10_io"}, /* IO pdm2 , */\
+ { 0x2603, "tdm_sink0_slot"}, /* Position gainin (not used in DSP) , */\
+ { 0x2643, "tdm_sink1_slot"}, /* Position audio left , */\
+ { 0x2683, "tdm_sink2_slot"}, /* Position audio right , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Position gainout (not used in DSP) , */\
+ { 0x2703, "tdm_source1_slot"}, /* Position voltage sense right , */\
+ { 0x2743, "tdm_source2_slot"}, /* Position current sense right , */\
+ { 0x2783, "tdm_source3_slot"}, /* Position voltage sense left , */\
+ { 0x27c3, "tdm_source4_slot"}, /* Position current sense left , */\
+ { 0x2803, "tdm_source5_slot"}, /* Position dspout right , */\
+ { 0x2843, "tdm_source6_slot"}, /* Position dspout left , */\
+ { 0x2883, "tdm_source7_slot"}, /* Position AEC ref left control , */\
+ { 0x28c3, "tdm_source8_slot"}, /* Position AEC ref right control , */\
+ { 0x2903, "tdm_source9_slot"}, /* Position pdm1 , */\
+ { 0x2943, "tdm_source10_slot"}, /* Position pdm2 , */\
+ { 0x3100, "pdm_mode"}, /* PDM control , */\
+ { 0x3111, "pdm_side_tone_sel"}, /* Side tone input , */\
+ { 0x3130, "pdm_left_sel"}, /* PDM data selection for left channel during PDM direct mode, */\
+ { 0x3140, "pdm_right_sel"}, /* PDM data selection for right channel during PDM direct mode, */\
+ { 0x3150, "enbl_micvdd"}, /* Enable MICVDD , */\
+ { 0x3160, "bypass_micvdd_ocp"}, /* Bypass control for the MICVDD OCP flag processing , */\
+ { 0x3201, "pdm_nbck"}, /* PDM BCK/Fs ratio , */\
+ { 0x3223, "pdm_gain"}, /* PDM gain , */\
+ { 0x3263, "sel_pdm_out_data"}, /* PDM output selection - RE/FE data combination , */\
+ { 0x32a0, "sel_cf_haptic_data"}, /* Select the source for haptic data output (not for customer), */\
+ { 0x3307, "haptic_duration"}, /* Duration (ms) , */\
+ { 0x3387, "haptic_data"}, /* DC value (FFS) , */\
+ { 0x3403, "gpio_datain"}, /* Receiving value , */\
+ { 0x3500, "gpio_ctrl"}, /* GPIO master control over GPIO1/2 ports (not for customer), */\
+ { 0x3513, "gpio_dir"}, /* Configuration , */\
+ { 0x3553, "gpio_dataout"}, /* Transmitting value , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_pll_lock"}, /* Status PLL lock , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ovpok"}, /* Status OVP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_clocks_stable"}, /* Status clocks stable , */\
+ { 0x4060, "int_out_flag_mtp_busy"}, /* Status MTP busy , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cf_speakererror"}, /* Status speaker error , */\
+ { 0x4090, "int_out_flag_cold_started"}, /* Status cold start , */\
+ { 0x40a0, "int_out_flag_engage"}, /* Status amplifier engage , */\
+ { 0x40b0, "int_out_flag_watchdog_reset"}, /* Status watchdog , */\
+ { 0x40c0, "int_out_flag_enbl_amp"}, /* Status amplifier enable , */\
+ { 0x40d0, "int_out_flag_enbl_ref"}, /* Status Ref enable , */\
+ { 0x40e0, "int_out_flag_adc10_ready"}, /* Status Control ADC , */\
+ { 0x40f0, "int_out_flag_bod_vddd_nok"}, /* Status BOD , */\
+ { 0x4100, "int_out_flag_bst_bstcur"}, /* Status DCDC current limiting , */\
+ { 0x4110, "int_out_flag_bst_hiz"}, /* Status DCDC active , */\
+ { 0x4120, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4130, "int_out_flag_bst_peakcur"}, /* Status bst peakcur , */\
+ { 0x4140, "int_out_flag_bst_voutcomp"}, /* Status DCDC level 1x , */\
+ { 0x4150, "int_out_flag_bst_voutcomp86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "int_out_flag_bst_voutcomp93"}, /* Status DCDC level 1.07x , */\
+ { 0x4170, "int_out_flag_rcvldop_ready"}, /* Status rcvldop ready , */\
+ { 0x4180, "int_out_flag_ocp_alarm_left"}, /* Status ocp alarm left , */\
+ { 0x4190, "int_out_flag_ocp_alarm_right"}, /* Status ocp alarm right , */\
+ { 0x41a0, "int_out_flag_man_wait_src_settings"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "int_out_flag_man_wait_cf_config"}, /* Status waits CF config , */\
+ { 0x41c0, "int_out_flag_man_start_mute_audio"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x41e0, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x41f0, "int_out_flag_clk_out_of_range"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4210, "int_out_flag_clip_left"}, /* Status clip left , */\
+ { 0x4220, "int_out_flag_clip_right"}, /* Status clip right , */\
+ { 0x4230, "int_out_flag_mic_ocpok"}, /* Status mic ocpok , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_pll_lock"}, /* Clear PLL lock , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ovpok"}, /* Clear OVP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_clocks_stable"}, /* Clear clocks stable , */\
+ { 0x4460, "int_in_flag_mtp_busy"}, /* Clear mtp busy , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cf_speakererror"}, /* Clear speaker error , */\
+ { 0x4490, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44a0, "int_in_flag_engage"}, /* Clear amplifier engage , */\
+ { 0x44b0, "int_in_flag_watchdog_reset"}, /* Clear watchdog , */\
+ { 0x44c0, "int_in_flag_enbl_amp"}, /* Clear enbl amp , */\
+ { 0x44d0, "int_in_flag_enbl_ref"}, /* Clear ref enable , */\
+ { 0x44e0, "int_in_flag_adc10_ready"}, /* Clear control ADC , */\
+ { 0x44f0, "int_in_flag_bod_vddd_nok"}, /* Clear BOD , */\
+ { 0x4500, "int_in_flag_bst_bstcur"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "int_in_flag_bst_hiz"}, /* Clear DCDC active , */\
+ { 0x4520, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4530, "int_in_flag_bst_peakcur"}, /* Clear bst peakcur , */\
+ { 0x4540, "int_in_flag_bst_voutcomp"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "int_in_flag_bst_voutcomp86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "int_in_flag_bst_voutcomp93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4570, "int_in_flag_rcvldop_ready"}, /* Clear rcvldop ready , */\
+ { 0x4580, "int_in_flag_ocp_alarm_left"}, /* Clear ocp alarm left , */\
+ { 0x4590, "int_in_flag_ocp_alarm_right"}, /* Clear ocp alarm right , */\
+ { 0x45a0, "int_in_flag_man_wait_src_settings"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "int_in_flag_man_wait_cf_config"}, /* Clear wait cf config , */\
+ { 0x45c0, "int_in_flag_man_start_mute_audio"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x45e0, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x45f0, "int_in_flag_clk_out_of_range"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4610, "int_in_flag_clip_left"}, /* Clear clip left , */\
+ { 0x4620, "int_in_flag_clip_right"}, /* Clear clip right , */\
+ { 0x4630, "int_in_flag_mic_ocpok"}, /* Clear mic ocpok , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_pll_lock"}, /* Enable pll lock , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ovpok"}, /* Enable OVP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_clocks_stable"}, /* Enable clocks stable , */\
+ { 0x4860, "int_enable_flag_mtp_busy"}, /* Enable mtp busy , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cf_speakererror"}, /* Enable speaker error , */\
+ { 0x4890, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48a0, "int_enable_flag_engage"}, /* Enable amplifier engage , */\
+ { 0x48b0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog , */\
+ { 0x48c0, "int_enable_flag_enbl_amp"}, /* Enable enbl amp , */\
+ { 0x48d0, "int_enable_flag_enbl_ref"}, /* Enable ref enable , */\
+ { 0x48e0, "int_enable_flag_adc10_ready"}, /* Enable Control ADC , */\
+ { 0x48f0, "int_enable_flag_bod_vddd_nok"}, /* Enable BOD , */\
+ { 0x4900, "int_enable_flag_bst_bstcur"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "int_enable_flag_bst_hiz"}, /* Enable DCDC active , */\
+ { 0x4920, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4930, "int_enable_flag_bst_peakcur"}, /* Enable bst peakcur , */\
+ { 0x4940, "int_enable_flag_bst_voutcomp"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "int_enable_flag_bst_voutcomp86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "int_enable_flag_bst_voutcomp93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4970, "int_enable_flag_rcvldop_ready"}, /* Enable rcvldop ready , */\
+ { 0x4980, "int_enable_flag_ocp_alarm_left"}, /* Enable ocp alarm left , */\
+ { 0x4990, "int_enable_flag_ocp_alarm_right"}, /* Enable ocp alarm right , */\
+ { 0x49a0, "int_enable_flag_man_wait_src_settings"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "int_enable_flag_man_wait_cf_config"}, /* Enable man wait cf config , */\
+ { 0x49c0, "int_enable_flag_man_start_mute_audio"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x49e0, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x49f0, "int_enable_flag_clk_out_of_range"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4a10, "int_enable_flag_clip_left"}, /* Enable clip left , */\
+ { 0x4a20, "int_enable_flag_clip_right"}, /* Enable clip right , */\
+ { 0x4a30, "int_enable_flag_mic_ocpok"}, /* Enable mic ocpok , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_pll_lock"}, /* Polarity pll lock , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ovpok"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_clocks_stable"}, /* Polarity clocks stable , */\
+ { 0x4c60, "int_polarity_flag_mtp_busy"}, /* Polarity mtp busy , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cf_speakererror"}, /* Polarity speaker error , */\
+ { 0x4c90, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4ca0, "int_polarity_flag_engage"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog , */\
+ { 0x4cc0, "int_polarity_flag_enbl_amp"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "int_polarity_flag_enbl_ref"}, /* Polarity ref enable , */\
+ { 0x4ce0, "int_polarity_flag_adc10_ready"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity BOD , */\
+ { 0x4d00, "int_polarity_flag_bst_bstcur"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "int_polarity_flag_bst_hiz"}, /* Polarity DCDC active , */\
+ { 0x4d20, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "int_polarity_flag_bst_peakcur"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "int_polarity_flag_bst_voutcomp"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "int_polarity_flag_bst_voutcomp86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "int_polarity_flag_bst_voutcomp93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d70, "int_polarity_flag_rcvldop_ready"}, /* Polarity rcvldop ready , */\
+ { 0x4d80, "int_polarity_flag_ocp_alarm_left"}, /* Polarity ocp alarm left , */\
+ { 0x4d90, "int_polarity_flag_ocp_alarm_right"}, /* Polarity ocp alarm right , */\
+ { 0x4da0, "int_polarity_flag_man_wait_src_settings"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "int_polarity_flag_man_wait_cf_config"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "int_polarity_flag_man_start_mute_audio"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4de0, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4df0, "int_polarity_flag_clk_out_of_range"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4e10, "int_polarity_flag_clip_left"}, /* Polarity clip left , */\
+ { 0x4e20, "int_polarity_flag_clip_right"}, /* Polarity clip right , */\
+ { 0x4e30, "int_polarity_flag_mic_ocpok"}, /* Polarity mic ocpok , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery protection attack Time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery protection threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery protection maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery protection release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery protection hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5110, "soft_mute"}, /* Soft mute HW , */\
+ { 0x5120, "cf_mute_left"}, /* Soft mute FW left , */\
+ { 0x5130, "cf_mute_right"}, /* Soft mute FW right , */\
+ { 0x5140, "bypass_hp_left"}, /* Bypass HPF left , */\
+ { 0x5150, "bypass_hp_right"}, /* Bypass HPF right , */\
+ { 0x5160, "enbl_dpsa_left"}, /* Enable DPSA left , */\
+ { 0x5170, "enbl_dpsa_right"}, /* Enable DPSA right , */\
+ { 0x5187, "cf_volume"}, /* FW volume control for primary audio channel , */\
+ { 0x5200, "ctrl_rcv"}, /* Selection receiver , */\
+ { 0x5210, "ctrl_rcv_fb_100k"}, /* Selection of feedback resistor for receiver mode (not for customer), */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e1, "ctrl_slope"}, /* Set slope , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for battery protection, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "enbl_low_latency"}, /* CF low latency outputs for add module , */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5420, "fb_hz"}, /* Feedback resistor set to high ohmic , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5581, "dpsa_drive"}, /* Control of the number of power stage sections, total of 4 sections. Each section is 1/4 of the total power stages., */\
+ { 0x560a, "enbl_amp_left"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually - Left channel, */\
+ { 0x56b0, "enbl_engage_left"}, /* Enables/engage power stage and control loop - left channel, */\
+ { 0x570a, "enbl_amp_right"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually - Right channel, */\
+ { 0x57b0, "enbl_engage_right"}, /* Enables/engage power stage and control loop - right channel, */\
+ { 0x5800, "hard_mute_left"}, /* Hard mute - PWM module left , */\
+ { 0x5810, "hard_mute_right"}, /* Hard mute - PWM module right , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5830, "pwm_bitlength"}, /* PWM bit length in noise shaper , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58b0, "enbl_pwm_phase_shift_left"}, /* Control for pwm phase shift, inverted function - left channel, */\
+ { 0x58c0, "enbl_pwm_phase_shift_right"}, /* Control for pwm phase shift - right channel , */\
+ { 0x5900, "ctrl_rcvldop_pulldown"}, /* Pulldown of LDO (2.7V) , */\
+ { 0x5910, "ctrl_rcvldop_test_comp"}, /* Enable testing of LDO comparator , */\
+ { 0x5920, "ctrl_rcvldop_test_loadedldo"}, /* Load connected to rcvldo , */\
+ { 0x5930, "enbl_rcvldop"}, /* Enables the LDO (2.7) , */\
+ { 0x5a07, "cf_volume_sec"}, /* FW volume control for secondary audio channel , */\
+ { 0x5a87, "sw_profile"}, /* Software profile data , */\
+ { 0x7002, "boost_volt"}, /* Boost voltage , */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_coil_value"}, /* Coil Value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70b2, "dcdc_synchronisation"}, /* DCDC synchronization off + 7 positions , */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7332, "bst_freq"}, /* DCDC bost frequency control , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8040, "cs_dc_offset"}, /* Current sense decimator offset control , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8110, "invertpwm_left"}, /* Current sense common mode feedback pwm invert control for left channel, */\
+ { 0x8122, "cmfb_gain_left"}, /* Current sense common mode feedback control gain for left channel, */\
+ { 0x8154, "cmfb_offset_left"}, /* Current sense common mode feedback control offset for left channel, */\
+ { 0x8200, "enbl_cmfb_right"}, /* Current sense common mode feedback control for right channel, */\
+ { 0x8210, "invertpwm_right"}, /* Current sense common mode feedback pwm invert control for right channel, */\
+ { 0x8222, "cmfb_gain_right"}, /* Current sense common mode feedback control gain for right channel, */\
+ { 0x8254, "cmfb_offset_right"}, /* Current sense common mode feedback control offset for right channel, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8600, "enbl_cs_adc_left"}, /* Enable current sense ADC , */\
+ { 0x8610, "enbl_cs_inn1_left"}, /* Enable connection of current sense negative1 , */\
+ { 0x8630, "enbl_cs_inp1_left"}, /* Enable connection of current sense positive1 , */\
+ { 0x8650, "enbl_cs_ldo_left"}, /* Enable current sense LDO , */\
+ { 0x8660, "enbl_cs_nofloating_n_left"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8670, "enbl_cs_nofloating_p_left"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8680, "enbl_cs_vbatldo_left"}, /* Enable of current sense LDO , */\
+ { 0x8700, "enbl_cs_adc_right"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1_right"}, /* Enable connection of current sense negative1 , */\
+ { 0x8730, "enbl_cs_inp1_right"}, /* Enable connection of current sense positive1 , */\
+ { 0x8750, "enbl_cs_ldo_right"}, /* Enable current sense LDO , */\
+ { 0x8760, "enbl_cs_nofloating_n_right"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8770, "enbl_cs_nofloating_p_right"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8780, "enbl_cs_vbatldo_right"}, /* Enable of current sense LDO , */\
+ { 0x8800, "volsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0x8810, "volsense_dc_offset"}, /* Voltage sense decimator offset control , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset , */\
+ { 0x9011, "cf_dmem"}, /* Target memory , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* Memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* Error flags , */\
+ { 0x9387, "cf_ack"}, /* Acknowledge of requests , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0x980f, "ivt_addr0_msb"}, /* Coolflux interrupt vector table address0 MSB , */\
+ { 0x990f, "ivt_addr0_lsb"}, /* Coolflux interrupt vector table address0 LSB , */\
+ { 0x9a0f, "ivt_addr1_msb"}, /* Coolflux interrupt vector table address1 MSB , */\
+ { 0x9b0f, "ivt_addr1_lsb"}, /* Coolflux interrupt vector table address1 LSB , */\
+ { 0x9c0f, "ivt_addr2_msb"}, /* Coolflux interrupt vector table address2 MSB , */\
+ { 0x9d0f, "ivt_addr2_lsb"}, /* Coolflux interrupt vector table address2 LSB , */\
+ { 0x9e0f, "ivt_addr3_msb"}, /* Coolflux interrupt vector table address3 MSB , */\
+ { 0x9f0f, "ivt_addr3_lsb"}, /* Coolflux interrupt vector table address3 LSB , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* FFT Coolflux , */\
+ { 0xc3e0, "test_pwr_switch"}, /* Test mode for digital power switches core sw/mem sw/micvdd sw, */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc660, "bypass_diosw_ovp"}, /* Bypass ovp for memory switch diosw , */\
+ { 0xc670, "enbl_powerswitch"}, /* Vddd core power switch control - overrules the manager control, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to GPIO1 (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to GPIO2 (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to GPIO3 (see Digimux list for details), */\
+ { 0xc887, "digimuxd_sel"}, /* DigimuxD input selection control routed to GPIO4 (see Digimux list for details), */\
+ { 0xc901, "dio1_ehs"}, /* Speed/load setting for DIO1 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc921, "dio2_ehs"}, /* Speed/load setting for DIO2 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc941, "gainio_ehs"}, /* Speed/load setting for GAINIO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc961, "pdmo_ehs"}, /* Speed/load setting for PDMO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9a1, "tdo_ehs"}, /* Speed/load setting for TDO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca40, "enbl_anamux5"}, /* Enable anamux5 , */\
+ { 0xca50, "enbl_anamux6"}, /* Enable anamux6 , */\
+ { 0xca60, "enbl_anamux7"}, /* Enable anamux7 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb54, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba4, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcc04, "anamux5"}, /* Anamux selection control - anamux on TEST5 , */\
+ { 0xcc54, "anamux6"}, /* Anamux selection control - anamux on TEST6 , */\
+ { 0xcca4, "anamux7"}, /* Anamux selection control - anamux on TEST7 , */\
+ { 0xcd05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xcd64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcdb3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd243, "tsig_gain_left"}, /* Test signal gain for left channel , */\
+ { 0xd283, "tsig_gain_right"}, /* Test signal gain for right channel , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd506, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd570, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "calibr_gain_left"}, /* HW gain module - left channel (2's complement) , */\
+ { 0xf1a5, "calibr_offset_left"}, /* Offset for amplifier, HW gain module - left channel (2's complement), */\
+ { 0xf203, "calibr_gain_right"}, /* HW gain module - right channel (2's complement) , */\
+ { 0xf245, "calibr_offset_right"}, /* Offset for amplifier, HW gain module - right channel (2's complement), */\
+ { 0xf2a3, "calibr_rcvldop_trim"}, /* Trimming of LDO (2.7V) , */\
+ { 0xf307, "calibr_gain_cs_left"}, /* Current sense gain - left channel (signed two's complement format), */\
+ { 0xf387, "calibr_gain_cs_right"}, /* Current sense gain - right channel (signed two's complement format), */\
+ { 0xf40f, "calibr_R25C_L"}, /* Ron resistance of left channel speaker coil , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of right channel speaker coil , */\
+ { 0xf606, "ctrl_offset_a_left"}, /* Offset of left amplifier level shifter A , */\
+ { 0xf686, "ctrl_offset_b_left"}, /* Offset of left amplifier level shifter B , */\
+ { 0xf706, "ctrl_offset_a_right"}, /* Offset of right amplifier level shifter A , */\
+ { 0xf786, "ctrl_offset_b_right"}, /* Offset of right amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "mtp_lock_enbl_coolflux"}, /* Disable function enbl_coolflux , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Disable programming of max dcdc boost voltage , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf987, "type_bits_fw"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa2_irq {
+ tfa2_irq_stvdds = 0,
+ tfa2_irq_stplls = 1,
+ tfa2_irq_stotds = 2,
+ tfa2_irq_stovds = 3,
+ tfa2_irq_stuvds = 4,
+ tfa2_irq_stclks = 5,
+ tfa2_irq_stmtpb = 6,
+ tfa2_irq_stnoclk = 7,
+ tfa2_irq_stspks = 8,
+ tfa2_irq_stacs = 9,
+ tfa2_irq_stsws = 10,
+ tfa2_irq_stwds = 11,
+ tfa2_irq_stamps = 12,
+ tfa2_irq_starefs = 13,
+ tfa2_irq_stadccr = 14,
+ tfa2_irq_stbodnok = 15,
+ tfa2_irq_stbstcu = 16,
+ tfa2_irq_stbsthi = 17,
+ tfa2_irq_stbstoc = 18,
+ tfa2_irq_stbstpkcur = 19,
+ tfa2_irq_stbstvc = 20,
+ tfa2_irq_stbst86 = 21,
+ tfa2_irq_stbst93 = 22,
+ tfa2_irq_strcvld = 23,
+ tfa2_irq_stocpl = 24,
+ tfa2_irq_stocpr = 25,
+ tfa2_irq_stmwsrc = 26,
+ tfa2_irq_stmwcfc = 27,
+ tfa2_irq_stmwsmu = 28,
+ tfa2_irq_stcfmer = 29,
+ tfa2_irq_stcfmac = 30,
+ tfa2_irq_stclkoor = 31,
+ tfa2_irq_sttdmer = 32,
+ tfa2_irq_stclpl = 33,
+ tfa2_irq_stclpr = 34,
+ tfa2_irq_stocpm = 35,
+ tfa2_irq_max = 36,
+ tfa2_irq_all = -1 /* all irqs */};
+
+#define TFA2_IRQ_NAMETABLE static tfaIrqName_t Tfa2IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STPLLS"},\
+ { 2, "STOTDS"},\
+ { 3, "STOVDS"},\
+ { 4, "STUVDS"},\
+ { 5, "STCLKS"},\
+ { 6, "STMTPB"},\
+ { 7, "STNOCLK"},\
+ { 8, "STSPKS"},\
+ { 9, "STACS"},\
+ { 10, "STSWS"},\
+ { 11, "STWDS"},\
+ { 12, "STAMPS"},\
+ { 13, "STAREFS"},\
+ { 14, "STADCCR"},\
+ { 15, "STBODNOK"},\
+ { 16, "STBSTCU"},\
+ { 17, "STBSTHI"},\
+ { 18, "STBSTOC"},\
+ { 19, "STBSTPKCUR"},\
+ { 20, "STBSTVC"},\
+ { 21, "STBST86"},\
+ { 22, "STBST93"},\
+ { 23, "STRCVLD"},\
+ { 24, "STOCPL"},\
+ { 25, "STOCPR"},\
+ { 26, "STMWSRC"},\
+ { 27, "STMWCFC"},\
+ { 28, "STMWSMU"},\
+ { 29, "STCFMER"},\
+ { 30, "STCFMAC"},\
+ { 31, "STCLKOOR"},\
+ { 32, "STTDMER"},\
+ { 33, "STCLPL"},\
+ { 34, "STCLPR"},\
+ { 35, "STOCPM"},\
+ { 36, "36"},\
+};
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9872_device_genregs_POR.h b/sound/soc/codecs/tfa98xx-downstream/tfa9872_device_genregs_POR.h
new file mode 100644
index 00000000000..9dee345d8d7
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9872_device_genregs_POR.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/** Filename: Tfa98xx_device_genregs.h
+ * This file was generated automatically on 08/11/16 at 07:44:41.
+ * Source file: TFA9872N1B2_DefaultI2CSettings - V1.xlsx
+ */
+
+#ifndef _TFA9872_DEVICE_GENREGS_H
+#define _TFA9872_DEVICE_GENREGS_H
+
+
+#define TFA9872_SYS_CONTROL0 0x00
+#define TFA9872_SYS_CONTROL1 0x01
+#define TFA9872_SYS_CONTROL2 0x02
+#define TFA9872_DEVICE_REVISION 0x03
+#define TFA9872_CLOCK_CONTROL 0x04
+#define TFA9872_CLOCK_GATING_CONTROL 0x05
+#define TFA9872_SIDE_TONE_CONFIG 0x0d
+#define TFA9872_STATUS_FLAGS0 0x10
+#define TFA9872_STATUS_FLAGS1 0x11
+#define TFA9872_STATUS_FLAGS3 0x13
+#define TFA9872_STATUS_FLAGS4 0x14
+#define TFA9872_BATTERY_VOLTAGE 0x15
+#define TFA9872_TEMPERATURE 0x16
+#define TFA9872_VDDP_VOLTAGE 0x17
+#define TFA9872_TDM_CONFIG0 0x20
+#define TFA9872_TDM_CONFIG1 0x21
+#define TFA9872_TDM_CONFIG2 0x22
+#define TFA9872_TDM_CONFIG3 0x23
+#define TFA9872_TDM_CONFIG6 0x26
+#define TFA9872_TDM_CONFIG7 0x27
+#define TFA9872_PDM_CONFIG0 0x31
+#define TFA9872_INTERRUPT_OUT_REG1 0x40
+#define TFA9872_INTERRUPT_OUT_REG2 0x41
+#define TFA9872_INTERRUPT_OUT_REG3 0x42
+#define TFA9872_INTERRUPT_IN_REG1 0x44
+#define TFA9872_INTERRUPT_IN_REG2 0x45
+#define TFA9872_INTERRUPT_IN_REG3 0x46
+#define TFA9872_INTERRUPT_ENABLE_REG1 0x48
+#define TFA9872_INTERRUPT_ENABLE_REG2 0x49
+#define TFA9872_INTERRUPT_ENABLE_REG3 0x4a
+#define TFA9872_STATUS_POLARITY_REG1 0x4c
+#define TFA9872_STATUS_POLARITY_REG2 0x4d
+#define TFA9872_STATUS_POLARITY_REG3 0x4e
+#define TFA9872_BAT_PROT_CONFIG 0x50
+#define TFA9872_AUDIO_CONTROL 0x51
+#define TFA9872_AMPLIFIER_CONFIG 0x52
+#define TFA9872_PGA_CONTROL0 0x60
+#define TFA9872_GAIN_ATT 0x61
+#define TFA9872_TDM_SOURCE_CTRL 0x68
+#define TFA9872_SAM_CTRL 0x69
+#define TFA9872_STATUS_FLAGS5 0x6e
+#define TFA9872_CURSENSE_COMP 0x6f
+#define TFA9872_DCDC_CONTROL0 0x70
+#define TFA9872_DCDC_CONTROL4 0x74
+#define TFA9872_DCDC_CONTROL5 0x75
+#define TFA9872_MTPKEY2_REG 0xa1
+#define TFA9872_MTP_STATUS 0xa2
+#define TFA9872_KEY_PROTECTED_MTP_CONTROL 0xa3
+#define TFA9872_MTP_DATA_OUT_MSB 0xa5
+#define TFA9872_MTP_DATA_OUT_LSB 0xa6
+#define TFA9872_TEMP_SENSOR_CONFIG 0xb1
+#define TFA9872_SOFTWARE_PROFILE 0xee
+#define TFA9872_SOFTWARE_VSTEP 0xef
+#define TFA9872_KEY2_PROTECTED_MTP0 0xf0
+#define TFA9872_KEY2_PROTECTED_MTP5 0xf5
+#define TFA9872_SYS_CONTROL0_POR 0x0001
+#define TFA9872_SYS_CONTROL1_POR 0x0000
+#define TFA9872_SYS_CONTROL2_POR 0x2828
+#define TFA9872_DEVICE_REVISION_POR 0x3b72
+#define TFA9872_CLOCK_CONTROL_POR 0x0000
+#define TFA9872_CLOCK_GATING_CONTROL_POR 0x1f6a
+#define TFA9872_SIDE_TONE_CONFIG_POR 0x0ebe
+#define TFA9872_STATUS_FLAGS0_POR 0x001d
+#define TFA9872_STATUS_FLAGS1_POR 0x0004
+#define TFA9872_STATUS_FLAGS3_POR 0x000f
+#define TFA9872_STATUS_FLAGS4_POR 0x0000
+#define TFA9872_BATTERY_VOLTAGE_POR 0x03ff
+#define TFA9872_TEMPERATURE_POR 0x0100
+#define TFA9872_VDDP_VOLTAGE_POR 0x0000
+#define TFA9872_TDM_CONFIG0_POR 0x2890
+#define TFA9872_TDM_CONFIG1_POR 0xc1f1
+#define TFA9872_TDM_CONFIG2_POR 0x045c
+#define TFA9872_TDM_CONFIG3_POR 0x0003
+#define TFA9872_TDM_CONFIG6_POR 0x0010
+#define TFA9872_TDM_CONFIG7_POR 0x0001
+#define TFA9872_PDM_CONFIG0_POR 0x0000
+#define TFA9872_INTERRUPT_OUT_REG1_POR 0x0081
+#define TFA9872_INTERRUPT_OUT_REG2_POR 0x0000
+#define TFA9872_INTERRUPT_OUT_REG3_POR 0x0000
+#define TFA9872_INTERRUPT_IN_REG1_POR 0x0000
+#define TFA9872_INTERRUPT_IN_REG2_POR 0x0000
+#define TFA9872_INTERRUPT_IN_REG3_POR 0x0000
+#define TFA9872_INTERRUPT_ENABLE_REG1_POR 0x0001
+#define TFA9872_INTERRUPT_ENABLE_REG2_POR 0x0000
+#define TFA9872_INTERRUPT_ENABLE_REG3_POR 0x0000
+#define TFA9872_STATUS_POLARITY_REG1_POR 0x74e3
+#define TFA9872_STATUS_POLARITY_REG2_POR 0x967b
+#define TFA9872_STATUS_POLARITY_REG3_POR 0x0085
+#define TFA9872_BAT_PROT_CONFIG_POR 0x8091
+#define TFA9872_AUDIO_CONTROL_POR 0x0080
+#define TFA9872_AMPLIFIER_CONFIG_POR 0x7a08
+#define TFA9872_PGA_CONTROL0_POR 0x0000
+#define TFA9872_GAIN_ATT_POR 0x0000
+#define TFA9872_TDM_SOURCE_CTRL_POR 0x0400
+#define TFA9872_SAM_CTRL_POR 0x0000
+#define TFA9872_STATUS_FLAGS5_POR 0x0007
+#define TFA9872_CURSENSE_COMP_POR 0x02e4
+#define TFA9872_DCDC_CONTROL0_POR 0x06e6
+#define TFA9872_DCDC_CONTROL4_POR 0xd913
+#define TFA9872_DCDC_CONTROL5_POR 0x118a
+#define TFA9872_MTPKEY2_REG_POR 0x0000
+#define TFA9872_MTP_STATUS_POR 0x0003
+#define TFA9872_KEY_PROTECTED_MTP_CONTROL_POR 0x0000
+#define TFA9872_MTP_DATA_OUT_MSB_POR 0x0000
+#define TFA9872_MTP_DATA_OUT_LSB_POR 0x0000
+#define TFA9872_TEMP_SENSOR_CONFIG_POR 0x0000
+#define TFA9872_SOFTWARE_PROFILE_POR 0x0000
+#define TFA9872_SOFTWARE_VSTEP_POR 0x0000
+#define TFA9872_KEY2_PROTECTED_MTP0_POR 0x0000
+#define TFA9872_KEY2_PROTECTED_MTP5_POR 0x0000
+
+#endif /* _TFA9872_DEVICE_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9872_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9872_tfafieldnames.h
new file mode 100644
index 00000000000..db9929d24c5
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9872_tfafieldnames.h
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9872_tfaFieldnames.h
+ * This file was generated automatically on 09/28/18 at 11:21:43.
+ * Source file: TFA9872N1B2_DefaultI2CSettings -v25.xlsx
+ */
+
+#ifndef _TFA9872_TFAFIELDNAMES_H
+#define _TFA9872_TFAFIELDNAMES_H
+
+#define TFA9872_I2CVERSION_N1A 26
+#define TFA9872_I2CVERSION_N1B 29
+#define TFA9872_I2CVERSION_N1B2 25
+
+typedef enum Tfa9872BfEnumList {
+ TFA9872_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9872_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9872_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA9872_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9872_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9872_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9872_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9872_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9872_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA9872_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA9872_BF_RCVNS = 0x01e0, /*!< Noise shaper selection */
+ TFA9872_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9872_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9872_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9872_BF_BYPHVBF= 0x02b0, /*!< Bypass HVBAT filter */
+ TFA9872_BF_REV = 0x030f, /*!< Revision info */
+ TFA9872_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9872_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9872_BF_SSE = 0x0510, /*!< Enable speaker path */
+ TFA9872_BF_VSE = 0x0530, /*!< Voltage sense */
+ TFA9872_BF_CSE = 0x0550, /*!< Current sense */
+ TFA9872_BF_SSPDME= 0x0560, /*!< Sub-system PDM */
+ TFA9872_BF_PGAE = 0x0580, /*!< Enable PGA chop clock */
+ TFA9872_BF_SSTDME= 0x0590, /*!< Sub-system TDM */
+ TFA9872_BF_SSPBSTE= 0x05a0, /*!< Sub-system boost */
+ TFA9872_BF_SSADCE= 0x05b0, /*!< Sub-system ADC */
+ TFA9872_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9872_BF_STGAIN= 0x0d18, /*!< Side tone gain */
+ TFA9872_BF_STSMUTE= 0x0da0, /*!< Side tone soft mute */
+ TFA9872_BF_ST1C = 0x0db0, /*!< side tone one s complement */
+ TFA9872_BF_VDDS = 0x1000, /*!< POR */
+ TFA9872_BF_PLLS = 0x1010, /*!< PLL lock */
+ TFA9872_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9872_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9872_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9872_BF_CLKS = 0x1050, /*!< Clocks stable */
+ TFA9872_BF_MTPB = 0x1060, /*!< MTP busy */
+ TFA9872_BF_NOCLK = 0x1070, /*!< Lost clock */
+ TFA9872_BF_SWS = 0x10a0, /*!< Amplifier engage */
+ TFA9872_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9872_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9872_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9872_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9872_BF_DCDCA = 0x1110, /*!< DCDC active */
+ TFA9872_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos */
+ TFA9872_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9872_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9872_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9872_BF_STMUTEB= 0x1170, /*!< side tone (un)mute busy */
+ TFA9872_BF_STMUTE= 0x1180, /*!< side tone mute state */
+ TFA9872_BF_TDMLUTER= 0x1190, /*!< TDM LUT error */
+ TFA9872_BF_TDMSTAT= 0x11a2, /*!< TDM status bits */
+ TFA9872_BF_TDMERR= 0x11d0, /*!< TDM error */
+ TFA9872_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9872_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9872_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9872_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9872_BF_CLIPAH= 0x1340, /*!< Clipping A to Vddp */
+ TFA9872_BF_CLIPAL= 0x1350, /*!< Clipping A to gnd */
+ TFA9872_BF_CLIPBH= 0x1360, /*!< Clipping B to Vddp */
+ TFA9872_BF_CLIPBL= 0x1370, /*!< Clipping B to gnd */
+ TFA9872_BF_OCDS = 0x1380, /*!< OCP amplifier */
+ TFA9872_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9872_BF_OCPOKMC= 0x13a0, /*!< OCPOK MICVDD */
+ TFA9872_BF_MANALARM= 0x13b0, /*!< Alarm state */
+ TFA9872_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9872_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9872_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9872_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA9872_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9872_BF_DCMODE= 0x1471, /*!< DCDC mode status bits */
+ TFA9872_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9872_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9872_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/9.5 V) */
+ TFA9872_BF_TDME = 0x2040, /*!< Enable interface */
+ TFA9872_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA9872_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9872_BF_TDMFSLN= 0x2073, /*!< FS length (master mode only) */
+ TFA9872_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9872_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9872_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA9872_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9872_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9872_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9872_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9872_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9872_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9872_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9872_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9872_BF_TDMSPKE= 0x2300, /*!< Control audio tdm channel in 0 (spkr + dcdc) */
+ TFA9872_BF_TDMDCE= 0x2310, /*!< Control audio tdm channel in 1 (dcdc) */
+ TFA9872_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9872_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9872_BF_TDMSPKS= 0x2603, /*!< tdm slot for sink 0 (speaker + dcdc) */
+ TFA9872_BF_TDMDCS= 0x2643, /*!< tdm slot for sink 1 (dcdc) */
+ TFA9872_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9872_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9872_BF_PDMSTSEL= 0x3111, /*!< Side tone input */
+ TFA9872_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9872_BF_ISTPLLS= 0x4010, /*!< Status PLL lock */
+ TFA9872_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9872_BF_ISTOVDS= 0x4030, /*!< Status OVP alarm */
+ TFA9872_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9872_BF_ISTCLKS= 0x4050, /*!< Status clocks stable */
+ TFA9872_BF_ISTMTPB= 0x4060, /*!< Status MTP busy */
+ TFA9872_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9872_BF_ISTSWS= 0x40a0, /*!< Status amplifier engage */
+ TFA9872_BF_ISTAMPS= 0x40c0, /*!< Status amplifier enable */
+ TFA9872_BF_ISTAREFS= 0x40d0, /*!< Status Ref enable */
+ TFA9872_BF_ISTADCCR= 0x40e0, /*!< Status Control ADC */
+ TFA9872_BF_ISTBSTCU= 0x4100, /*!< Status DCDC current limiting */
+ TFA9872_BF_ISTBSTHI= 0x4110, /*!< Status DCDC active */
+ TFA9872_BF_ISTBSTOC= 0x4120, /*!< Status DCDC OCP */
+ TFA9872_BF_ISTBSTPKCUR= 0x4130, /*!< Status bst peakcur */
+ TFA9872_BF_ISTBSTVC= 0x4140, /*!< Status DCDC level 1x */
+ TFA9872_BF_ISTBST86= 0x4150, /*!< Status DCDC level 1.14x */
+ TFA9872_BF_ISTBST93= 0x4160, /*!< Status DCDC level 1.07x */
+ TFA9872_BF_ISTOCPR= 0x4190, /*!< Status ocp alarm */
+ TFA9872_BF_ISTMWSRC= 0x41a0, /*!< Status Waits HW I2C settings */
+ TFA9872_BF_ISTMWSMU= 0x41c0, /*!< Status Audio mute sequence */
+ TFA9872_BF_ISTCLKOOR= 0x41f0, /*!< Status flag_clk_out_of_range */
+ TFA9872_BF_ISTTDMER= 0x4200, /*!< Status tdm error */
+ TFA9872_BF_ISTCLPR= 0x4220, /*!< Status clip */
+ TFA9872_BF_ISTLP0= 0x4240, /*!< Status low power mode0 */
+ TFA9872_BF_ISTLP1= 0x4250, /*!< Status low power mode1 */
+ TFA9872_BF_ISTLA = 0x4260, /*!< Status low noise detection */
+ TFA9872_BF_ISTVDDPH= 0x4270, /*!< Status VDDP greater than VBAT */
+ TFA9872_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9872_BF_ICLPLLS= 0x4410, /*!< Clear PLL lock */
+ TFA9872_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9872_BF_ICLOVDS= 0x4430, /*!< Clear OVP alarm */
+ TFA9872_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9872_BF_ICLCLKS= 0x4450, /*!< Clear clocks stable */
+ TFA9872_BF_ICLMTPB= 0x4460, /*!< Clear mtp busy */
+ TFA9872_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9872_BF_ICLSWS= 0x44a0, /*!< Clear amplifier engage */
+ TFA9872_BF_ICLAMPS= 0x44c0, /*!< Clear enbl amp */
+ TFA9872_BF_ICLAREFS= 0x44d0, /*!< Clear ref enable */
+ TFA9872_BF_ICLADCCR= 0x44e0, /*!< Clear control ADC */
+ TFA9872_BF_ICLBSTCU= 0x4500, /*!< Clear DCDC current limiting */
+ TFA9872_BF_ICLBSTHI= 0x4510, /*!< Clear DCDC active */
+ TFA9872_BF_ICLBSTOC= 0x4520, /*!< Clear DCDC OCP */
+ TFA9872_BF_ICLBSTPC= 0x4530, /*!< Clear bst peakcur */
+ TFA9872_BF_ICLBSTVC= 0x4540, /*!< Clear DCDC level 1x */
+ TFA9872_BF_ICLBST86= 0x4550, /*!< Clear DCDC level 1.14x */
+ TFA9872_BF_ICLBST93= 0x4560, /*!< Clear DCDC level 1.07x */
+ TFA9872_BF_ICLOCPR= 0x4590, /*!< Clear ocp alarm */
+ TFA9872_BF_ICLMWSRC= 0x45a0, /*!< Clear wait HW I2C settings */
+ TFA9872_BF_ICLMWSMU= 0x45c0, /*!< Clear audio mute sequence */
+ TFA9872_BF_ICLCLKOOR= 0x45f0, /*!< Clear flag_clk_out_of_range */
+ TFA9872_BF_ICLTDMER= 0x4600, /*!< Clear tdm error */
+ TFA9872_BF_ICLCLPR= 0x4620, /*!< Clear clip */
+ TFA9872_BF_ICLLP0= 0x4640, /*!< Clear low power mode0 */
+ TFA9872_BF_ICLLP1= 0x4650, /*!< Clear low power mode1 */
+ TFA9872_BF_ICLLA = 0x4660, /*!< Clear low noise detection */
+ TFA9872_BF_ICLVDDPH= 0x4670, /*!< Clear VDDP greater then VBAT */
+ TFA9872_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9872_BF_IEPLLS= 0x4810, /*!< Enable pll lock */
+ TFA9872_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9872_BF_IEOVDS= 0x4830, /*!< Enable OVP alarm */
+ TFA9872_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9872_BF_IECLKS= 0x4850, /*!< Enable clocks stable */
+ TFA9872_BF_IEMTPB= 0x4860, /*!< Enable mtp busy */
+ TFA9872_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9872_BF_IESWS = 0x48a0, /*!< Enable amplifier engage */
+ TFA9872_BF_IEAMPS= 0x48c0, /*!< Enable enbl amp */
+ TFA9872_BF_IEAREFS= 0x48d0, /*!< Enable ref enable */
+ TFA9872_BF_IEADCCR= 0x48e0, /*!< Enable Control ADC */
+ TFA9872_BF_IEBSTCU= 0x4900, /*!< Enable DCDC current limiting */
+ TFA9872_BF_IEBSTHI= 0x4910, /*!< Enable DCDC active */
+ TFA9872_BF_IEBSTOC= 0x4920, /*!< Enable DCDC OCP */
+ TFA9872_BF_IEBSTPC= 0x4930, /*!< Enable bst peakcur */
+ TFA9872_BF_IEBSTVC= 0x4940, /*!< Enable DCDC level 1x */
+ TFA9872_BF_IEBST86= 0x4950, /*!< Enable DCDC level 1.14x */
+ TFA9872_BF_IEBST93= 0x4960, /*!< Enable DCDC level 1.07x */
+ TFA9872_BF_IEOCPR= 0x4990, /*!< Enable ocp alarm */
+ TFA9872_BF_IEMWSRC= 0x49a0, /*!< Enable waits HW I2C settings */
+ TFA9872_BF_IEMWSMU= 0x49c0, /*!< Enable man Audio mute sequence */
+ TFA9872_BF_IECLKOOR= 0x49f0, /*!< Enable flag_clk_out_of_range */
+ TFA9872_BF_IETDMER= 0x4a00, /*!< Enable tdm error */
+ TFA9872_BF_IECLPR= 0x4a20, /*!< Enable clip */
+ TFA9872_BF_IELP0 = 0x4a40, /*!< Enable low power mode0 */
+ TFA9872_BF_IELP1 = 0x4a50, /*!< Enable low power mode1 */
+ TFA9872_BF_IELA = 0x4a60, /*!< Enable low noise detection */
+ TFA9872_BF_IEVDDPH= 0x4a70, /*!< Enable VDDP greater tehn VBAT */
+ TFA9872_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9872_BF_IPOPLLS= 0x4c10, /*!< Polarity pll lock */
+ TFA9872_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9872_BF_IPOOVDS= 0x4c30, /*!< Polarity OVP alarm */
+ TFA9872_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9872_BF_IPOCLKS= 0x4c50, /*!< Polarity clocks stable */
+ TFA9872_BF_IPOMTPB= 0x4c60, /*!< Polarity mtp busy */
+ TFA9872_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9872_BF_IPOSWS= 0x4ca0, /*!< Polarity amplifier engage */
+ TFA9872_BF_IPOAMPS= 0x4cc0, /*!< Polarity enbl amp */
+ TFA9872_BF_IPOAREFS= 0x4cd0, /*!< Polarity ref enable */
+ TFA9872_BF_IPOADCCR= 0x4ce0, /*!< Polarity Control ADC */
+ TFA9872_BF_IPOBSTCU= 0x4d00, /*!< Polarity DCDC current limiting */
+ TFA9872_BF_IPOBSTHI= 0x4d10, /*!< Polarity DCDC active */
+ TFA9872_BF_IPOBSTOC= 0x4d20, /*!< Polarity DCDC OCP */
+ TFA9872_BF_IPOBSTPC= 0x4d30, /*!< Polarity bst peakcur */
+ TFA9872_BF_IPOBSTVC= 0x4d40, /*!< Polarity DCDC level 1x */
+ TFA9872_BF_IPOBST86= 0x4d50, /*!< Polarity DCDC level 1.14x */
+ TFA9872_BF_IPOBST93= 0x4d60, /*!< Polarity DCDC level 1.07x */
+ TFA9872_BF_IPOOCPR= 0x4d90, /*!< Polarity ocp alarm */
+ TFA9872_BF_IPOMWSRC= 0x4da0, /*!< Polarity waits HW I2C settings */
+ TFA9872_BF_IPOMWSMU= 0x4dc0, /*!< Polarity man audio mute sequence */
+ TFA9872_BF_IPCLKOOR= 0x4df0, /*!< Polarity flag_clk_out_of_range */
+ TFA9872_BF_IPOTDMER= 0x4e00, /*!< Polarity tdm error */
+ TFA9872_BF_IPOCLPR= 0x4e20, /*!< Polarity clip right */
+ TFA9872_BF_IPOLP0= 0x4e40, /*!< Polarity low power mode0 */
+ TFA9872_BF_IPOLP1= 0x4e50, /*!< Polarity low power mode1 */
+ TFA9872_BF_IPOLA = 0x4e60, /*!< Polarity low noise mode */
+ TFA9872_BF_IPOVDDPH= 0x4e70, /*!< Polarity VDDP greater than VBAT */
+ TFA9872_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time */
+ TFA9872_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9872_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9872_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9872_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9872_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9872_BF_INTSMUTE= 0x5110, /*!< Soft mute HW */
+ TFA9872_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9872_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9872_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9872_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9872_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9872_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9872_BF_PGAGAIN= 0x6081, /*!< PGA gain selection */
+ TFA9872_BF_PGALPE= 0x60b0, /*!< Lowpass enable */
+ TFA9872_BF_LPM0BYP= 0x6110, /*!< bypass low power idle mode */
+ TFA9872_BF_TDMDCG= 0x6123, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9872_BF_TDMSPKG= 0x6163, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9872_BF_STIDLEEN= 0x61b0, /*!< enable idle feature for channel 1 */
+ TFA9872_BF_LNMODE= 0x62e1, /*!< ctrl select mode */
+ TFA9872_BF_LPM1MODE= 0x64e1, /*!< low power mode control */
+ TFA9872_BF_LPM1DIS= 0x65c0, /*!< low power mode1 detector control */
+ TFA9872_BF_TDMSRCMAP= 0x6801, /*!< tdm source mapping */
+ TFA9872_BF_TDMSRCAS= 0x6821, /*!< Sensed value A */
+ TFA9872_BF_TDMSRCBS= 0x6841, /*!< Sensed value B */
+ TFA9872_BF_ANCSEL= 0x6881, /*!< anc input */
+ TFA9872_BF_ANC1C = 0x68a0, /*!< ANC one s complement */
+ TFA9872_BF_SAMMODE= 0x6901, /*!< sam enable */
+ TFA9872_BF_SAMSEL= 0x6920, /*!< sam source */
+ TFA9872_BF_PDMOSELH= 0x6931, /*!< pdm out value when pdm_clk is higth */
+ TFA9872_BF_PDMOSELL= 0x6951, /*!< pdm out value when pdm_clk is low */
+ TFA9872_BF_SAMOSEL= 0x6970, /*!< ram output on mode sam and audio */
+ TFA9872_BF_LP0 = 0x6e00, /*!< low power mode 0 detection */
+ TFA9872_BF_LP1 = 0x6e10, /*!< low power mode 1 detection */
+ TFA9872_BF_LA = 0x6e20, /*!< low amplitude detection */
+ TFA9872_BF_VDDPH = 0x6e30, /*!< vddp greater than vbat */
+ TFA9872_BF_DELCURCOMP= 0x6f02, /*!< delay to allign compensation signal with current sense signal */
+ TFA9872_BF_SIGCURCOMP= 0x6f40, /*!< polarity of compensation for current sense */
+ TFA9872_BF_ENCURCOMP= 0x6f50, /*!< enable current sense compensation */
+ TFA9872_BF_SELCLPPWM= 0x6f60, /*!< Select pwm clip flag */
+ TFA9872_BF_LVLCLPPWM= 0x6f72, /*!< set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9872_BF_DCVOS = 0x7002, /*!< Second boost voltage level */
+ TFA9872_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA9872_BF_DCCV = 0x7071, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9872_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA9872_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA9872_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9872_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9872_BF_DCVOF = 0x7402, /*!< 1st boost voltage level */
+ TFA9872_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9872_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9872_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9872_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9872_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9872_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9872_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9872_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9872_BF_CMTPI = 0xa350, /*!< Start copying all the data from mtp to I2C mtp registers */
+ TFA9872_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9872_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9872_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9872_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9872_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9872_BF_SWPROFIL= 0xee0f, /*!< Software profile data */
+ TFA9872_BF_SWVSTEP= 0xef0f, /*!< Software vstep information */
+ TFA9872_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9872_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9872_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9872_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9872_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9872_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9872_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9872BfEnumList_t;
+#define TFA9872_NAMETABLE static tfaBfName_t Tfa9872DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "RCVNS"}, /* Noise shaper selection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b0, "BYPHVBF"}, /* Bypass HVBAT filter , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x510, "SSE"}, /* Enable speaker path , */\
+ { 0x530, "VSE"}, /* Voltage sense , */\
+ { 0x550, "CSE"}, /* Current sense , */\
+ { 0x560, "SSPDME"}, /* Sub-system PDM , */\
+ { 0x580, "PGAE"}, /* Enable PGA chop clock , */\
+ { 0x590, "SSTDME"}, /* Sub-system TDM , */\
+ { 0x5a0, "SSPBSTE"}, /* Sub-system boost , */\
+ { 0x5b0, "SSADCE"}, /* Sub-system ADC , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0xd18, "STGAIN"}, /* Side tone gain , */\
+ { 0xda0, "STSMUTE"}, /* Side tone soft mute , */\
+ { 0xdb0, "ST1C"}, /* side tone one s complement , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "CLKS"}, /* Clocks stable , */\
+ { 0x1060, "MTPB"}, /* MTP busy , */\
+ { 0x1070, "NOCLK"}, /* Lost clock , */\
+ { 0x10a0, "SWS"}, /* Amplifier engage , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "STMUTEB"}, /* side tone (un)mute busy , */\
+ { 0x1180, "STMUTE"}, /* side tone mute state , */\
+ { 0x1190, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11a2, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11d0, "TDMERR"}, /* TDM error , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1340, "CLIPAH"}, /* Clipping A to Vddp , */\
+ { 0x1350, "CLIPAL"}, /* Clipping A to gnd , */\
+ { 0x1360, "CLIPBH"}, /* Clipping B to Vddp , */\
+ { 0x1370, "CLIPBL"}, /* Clipping B to gnd , */\
+ { 0x1380, "OCDS"}, /* OCP amplifier , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "OCPOKMC"}, /* OCPOK MICVDD , */\
+ { 0x13b0, "MANALARM"}, /* Alarm state , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1471, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/9.5 V) , */\
+ { 0x2040, "TDME"}, /* Enable interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "TDMDCE"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x3111, "PDMSTSEL"}, /* Side tone input , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTPLLS"}, /* Status PLL lock , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOVDS"}, /* Status OVP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTCLKS"}, /* Status clocks stable , */\
+ { 0x4060, "ISTMTPB"}, /* Status MTP busy , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x40a0, "ISTSWS"}, /* Status amplifier engage , */\
+ { 0x40c0, "ISTAMPS"}, /* Status amplifier enable , */\
+ { 0x40d0, "ISTAREFS"}, /* Status Ref enable , */\
+ { 0x40e0, "ISTADCCR"}, /* Status Control ADC , */\
+ { 0x4100, "ISTBSTCU"}, /* Status DCDC current limiting , */\
+ { 0x4110, "ISTBSTHI"}, /* Status DCDC active , */\
+ { 0x4120, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4130, "ISTBSTPKCUR"}, /* Status bst peakcur , */\
+ { 0x4140, "ISTBSTVC"}, /* Status DCDC level 1x , */\
+ { 0x4150, "ISTBST86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "ISTBST93"}, /* Status DCDC level 1.07x , */\
+ { 0x4190, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x41a0, "ISTMWSRC"}, /* Status Waits HW I2C settings , */\
+ { 0x41c0, "ISTMWSMU"}, /* Status Audio mute sequence , */\
+ { 0x41f0, "ISTCLKOOR"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4220, "ISTCLPR"}, /* Status clip , */\
+ { 0x4240, "ISTLP0"}, /* Status low power mode0 , */\
+ { 0x4250, "ISTLP1"}, /* Status low power mode1 , */\
+ { 0x4260, "ISTLA"}, /* Status low noise detection , */\
+ { 0x4270, "ISTVDDPH"}, /* Status VDDP greater than VBAT , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLPLLS"}, /* Clear PLL lock , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOVDS"}, /* Clear OVP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLCLKS"}, /* Clear clocks stable , */\
+ { 0x4460, "ICLMTPB"}, /* Clear mtp busy , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x44a0, "ICLSWS"}, /* Clear amplifier engage , */\
+ { 0x44c0, "ICLAMPS"}, /* Clear enbl amp , */\
+ { 0x44d0, "ICLAREFS"}, /* Clear ref enable , */\
+ { 0x44e0, "ICLADCCR"}, /* Clear control ADC , */\
+ { 0x4500, "ICLBSTCU"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "ICLBSTHI"}, /* Clear DCDC active , */\
+ { 0x4520, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4530, "ICLBSTPC"}, /* Clear bst peakcur , */\
+ { 0x4540, "ICLBSTVC"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "ICLBST86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "ICLBST93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4590, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x45a0, "ICLMWSRC"}, /* Clear wait HW I2C settings , */\
+ { 0x45c0, "ICLMWSMU"}, /* Clear audio mute sequence , */\
+ { 0x45f0, "ICLCLKOOR"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4620, "ICLCLPR"}, /* Clear clip , */\
+ { 0x4640, "ICLLP0"}, /* Clear low power mode0 , */\
+ { 0x4650, "ICLLP1"}, /* Clear low power mode1 , */\
+ { 0x4660, "ICLLA"}, /* Clear low noise detection , */\
+ { 0x4670, "ICLVDDPH"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEPLLS"}, /* Enable pll lock , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOVDS"}, /* Enable OVP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IECLKS"}, /* Enable clocks stable , */\
+ { 0x4860, "IEMTPB"}, /* Enable mtp busy , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x48a0, "IESWS"}, /* Enable amplifier engage , */\
+ { 0x48c0, "IEAMPS"}, /* Enable enbl amp , */\
+ { 0x48d0, "IEAREFS"}, /* Enable ref enable , */\
+ { 0x48e0, "IEADCCR"}, /* Enable Control ADC , */\
+ { 0x4900, "IEBSTCU"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "IEBSTHI"}, /* Enable DCDC active , */\
+ { 0x4920, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4930, "IEBSTPC"}, /* Enable bst peakcur , */\
+ { 0x4940, "IEBSTVC"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "IEBST86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "IEBST93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4990, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x49a0, "IEMWSRC"}, /* Enable waits HW I2C settings , */\
+ { 0x49c0, "IEMWSMU"}, /* Enable man Audio mute sequence , */\
+ { 0x49f0, "IECLKOOR"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4a20, "IECLPR"}, /* Enable clip , */\
+ { 0x4a40, "IELP0"}, /* Enable low power mode0 , */\
+ { 0x4a50, "IELP1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "IELA"}, /* Enable low noise detection , */\
+ { 0x4a70, "IEVDDPH"}, /* Enable VDDP greater tehn VBAT , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOPLLS"}, /* Polarity pll lock , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOVDS"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOCLKS"}, /* Polarity clocks stable , */\
+ { 0x4c60, "IPOMTPB"}, /* Polarity mtp busy , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4ca0, "IPOSWS"}, /* Polarity amplifier engage , */\
+ { 0x4cc0, "IPOAMPS"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "IPOAREFS"}, /* Polarity ref enable , */\
+ { 0x4ce0, "IPOADCCR"}, /* Polarity Control ADC , */\
+ { 0x4d00, "IPOBSTCU"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "IPOBSTHI"}, /* Polarity DCDC active , */\
+ { 0x4d20, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "IPOBSTPC"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "IPOBSTVC"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "IPOBST86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "IPOBST93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d90, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "IPOMWSRC"}, /* Polarity waits HW I2C settings , */\
+ { 0x4dc0, "IPOMWSMU"}, /* Polarity man audio mute sequence , */\
+ { 0x4df0, "IPCLKOOR"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4e20, "IPOCLPR"}, /* Polarity clip right , */\
+ { 0x4e40, "IPOLP0"}, /* Polarity low power mode0 , */\
+ { 0x4e50, "IPOLP1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "IPOLA"}, /* Polarity low noise mode , */\
+ { 0x4e70, "IPOVDDPH"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5110, "INTSMUTE"}, /* Soft mute HW , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x6081, "PGAGAIN"}, /* PGA gain selection , */\
+ { 0x60b0, "PGALPE"}, /* Lowpass enable , */\
+ { 0x6110, "LPM0BYP"}, /* bypass low power idle mode , */\
+ { 0x6123, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x61b0, "STIDLEEN"}, /* enable idle feature for channel 1 , */\
+ { 0x62e1, "LNMODE"}, /* ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* low power mode control , */\
+ { 0x65c0, "LPM1DIS"}, /* low power mode1 detector control , */\
+ { 0x6801, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6821, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6841, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6881, "ANCSEL"}, /* anc input , */\
+ { 0x68a0, "ANC1C"}, /* ANC one s complement , */\
+ { 0x6901, "SAMMODE"}, /* sam enable , */\
+ { 0x6920, "SAMSEL"}, /* sam source , */\
+ { 0x6931, "PDMOSELH"}, /* pdm out value when pdm_clk is higth , */\
+ { 0x6951, "PDMOSELL"}, /* pdm out value when pdm_clk is low , */\
+ { 0x6970, "SAMOSEL"}, /* ram output on mode sam and audio , */\
+ { 0x6e00, "LP0"}, /* low power mode 0 detection , */\
+ { 0x6e10, "LP1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* vddp greater than vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* enable current sense compensation , */\
+ { 0x6f60, "SELCLPPWM"}, /* Select pwm clip flag , */\
+ { 0x6f72, "LVLCLPPWM"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7002, "DCVOS"}, /* Second boost voltage level , */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7402, "DCVOF"}, /* 1st boost voltage level , */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa350, "CMTPI"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xee0f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xef0f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9872_BITNAMETABLE static tfaBfName_t Tfa9872BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x140, "enbl_osc1m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b0, "bypass_hvbat_filter"}, /* Bypass HVBAT filter , */\
+ { 0x2d0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker path , */\
+ { 0x530, "enbl_volsense"}, /* Voltage sense , */\
+ { 0x550, "enbl_cursense"}, /* Current sense , */\
+ { 0x560, "enbl_pdm_ss"}, /* Sub-system PDM , */\
+ { 0x580, "enbl_pga_chop"}, /* Enable PGA chop clock , */\
+ { 0x590, "enbl_tdm_ss"}, /* Sub-system TDM , */\
+ { 0x5a0, "enbl_bst_ss"}, /* Sub-system boost , */\
+ { 0x5b0, "enbl_adc_ss"}, /* Sub-system ADC , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0xd18, "side_tone_gain"}, /* Side tone gain , */\
+ { 0xda0, "mute_side_tone"}, /* Side tone soft mute , */\
+ { 0xdb0, "side_tone_1scomplement"}, /* side tone one s complement , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1060, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x10a0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_soft_mute_busy"}, /* side tone (un)mute busy , */\
+ { 0x1180, "flag_soft_mute_state"}, /* side tone mute state , */\
+ { 0x1190, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11a2, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11d0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1340, "flag_clipa_high"}, /* Clipping A to Vddp , */\
+ { 0x1350, "flag_clipa_low"}, /* Clipping A to gnd , */\
+ { 0x1360, "flag_clipb_high"}, /* Clipping B to Vddp , */\
+ { 0x1370, "flag_clipb_low"}, /* Clipping B to gnd , */\
+ { 0x1380, "flag_ocp_alarm"}, /* OCP amplifier , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13b0, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1471, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/9.5 V) , */\
+ { 0x2040, "tdm_enable"}, /* Enable interface , */\
+ { 0x2050, "tdm_mode"}, /* Slave/master , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x3111, "pdm_side_tone_sel"}, /* Side tone input , */\
+ { 0x3201, "pdm_nbck"}, /* PDM BCK/Fs ratio , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_pll_lock"}, /* Status PLL lock , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ovpok"}, /* Status OVP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_clocks_stable"}, /* Status clocks stable , */\
+ { 0x4060, "int_out_flag_mtp_busy"}, /* Status MTP busy , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x40a0, "int_out_flag_engage"}, /* Status amplifier engage , */\
+ { 0x40c0, "int_out_flag_enbl_amp"}, /* Status amplifier enable , */\
+ { 0x40d0, "int_out_flag_enbl_ref"}, /* Status Ref enable , */\
+ { 0x40e0, "int_out_flag_adc10_ready"}, /* Status Control ADC , */\
+ { 0x4100, "int_out_flag_bst_bstcur"}, /* Status DCDC current limiting , */\
+ { 0x4110, "int_out_flag_bst_hiz"}, /* Status DCDC active , */\
+ { 0x4120, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4130, "int_out_flag_bst_peakcur"}, /* Status bst peakcur , */\
+ { 0x4140, "int_out_flag_bst_voutcomp"}, /* Status DCDC level 1x , */\
+ { 0x4150, "int_out_flag_bst_voutcomp86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "int_out_flag_bst_voutcomp93"}, /* Status DCDC level 1.07x , */\
+ { 0x4190, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x41a0, "int_out_flag_man_wait_src_settings"}, /* Status Waits HW I2C settings , */\
+ { 0x41c0, "int_out_flag_man_start_mute_audio"}, /* Status Audio mute sequence , */\
+ { 0x41f0, "int_out_flag_clk_out_of_range"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4220, "int_out_flag_clip"}, /* Status clip , */\
+ { 0x4240, "int_out_flag_lp_detect_mode0"}, /* Status low power mode0 , */\
+ { 0x4250, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 , */\
+ { 0x4260, "int_out_flag_low_amplitude"}, /* Status low noise detection , */\
+ { 0x4270, "int_out_flag_vddp_gt_vbat"}, /* Status VDDP greater than VBAT , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_pll_lock"}, /* Clear PLL lock , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ovpok"}, /* Clear OVP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_clocks_stable"}, /* Clear clocks stable , */\
+ { 0x4460, "int_in_flag_mtp_busy"}, /* Clear mtp busy , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x44a0, "int_in_flag_engage"}, /* Clear amplifier engage , */\
+ { 0x44c0, "int_in_flag_enbl_amp"}, /* Clear enbl amp , */\
+ { 0x44d0, "int_in_flag_enbl_ref"}, /* Clear ref enable , */\
+ { 0x44e0, "int_in_flag_adc10_ready"}, /* Clear control ADC , */\
+ { 0x4500, "int_in_flag_bst_bstcur"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "int_in_flag_bst_hiz"}, /* Clear DCDC active , */\
+ { 0x4520, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4530, "int_in_flag_bst_peakcur"}, /* Clear bst peakcur , */\
+ { 0x4540, "int_in_flag_bst_voutcomp"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "int_in_flag_bst_voutcomp86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "int_in_flag_bst_voutcomp93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4590, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x45a0, "int_in_flag_man_wait_src_settings"}, /* Clear wait HW I2C settings , */\
+ { 0x45c0, "int_in_flag_man_start_mute_audio"}, /* Clear audio mute sequence , */\
+ { 0x45f0, "int_in_flag_clk_out_of_range"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4620, "int_in_flag_clip"}, /* Clear clip , */\
+ { 0x4640, "int_in_flag_lp_detect_mode0"}, /* Clear low power mode0 , */\
+ { 0x4650, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 , */\
+ { 0x4660, "int_in_flag_low_amplitude"}, /* Clear low noise detection , */\
+ { 0x4670, "int_in_flag_vddp_gt_vbat"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_pll_lock"}, /* Enable pll lock , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ovpok"}, /* Enable OVP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_clocks_stable"}, /* Enable clocks stable , */\
+ { 0x4860, "int_enable_flag_mtp_busy"}, /* Enable mtp busy , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x48a0, "int_enable_flag_engage"}, /* Enable amplifier engage , */\
+ { 0x48c0, "int_enable_flag_enbl_amp"}, /* Enable enbl amp , */\
+ { 0x48d0, "int_enable_flag_enbl_ref"}, /* Enable ref enable , */\
+ { 0x48e0, "int_enable_flag_adc10_ready"}, /* Enable Control ADC , */\
+ { 0x4900, "int_enable_flag_bst_bstcur"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "int_enable_flag_bst_hiz"}, /* Enable DCDC active , */\
+ { 0x4920, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4930, "int_enable_flag_bst_peakcur"}, /* Enable bst peakcur , */\
+ { 0x4940, "int_enable_flag_bst_voutcomp"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "int_enable_flag_bst_voutcomp86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "int_enable_flag_bst_voutcomp93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4990, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x49a0, "int_enable_flag_man_wait_src_settings"}, /* Enable waits HW I2C settings , */\
+ { 0x49c0, "int_enable_flag_man_start_mute_audio"}, /* Enable man Audio mute sequence , */\
+ { 0x49f0, "int_enable_flag_clk_out_of_range"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4a20, "int_enable_flag_clip"}, /* Enable clip , */\
+ { 0x4a40, "int_enable_flag_lp_detect_mode0"}, /* Enable low power mode0 , */\
+ { 0x4a50, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "int_enable_flag_low_amplitude"}, /* Enable low noise detection , */\
+ { 0x4a70, "int_enable_flag_vddp_gt_vbat"}, /* Enable VDDP greater tehn VBAT , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_pll_lock"}, /* Polarity pll lock , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ovpok"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_clocks_stable"}, /* Polarity clocks stable , */\
+ { 0x4c60, "int_polarity_flag_mtp_busy"}, /* Polarity mtp busy , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4ca0, "int_polarity_flag_engage"}, /* Polarity amplifier engage , */\
+ { 0x4cc0, "int_polarity_flag_enbl_amp"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "int_polarity_flag_enbl_ref"}, /* Polarity ref enable , */\
+ { 0x4ce0, "int_polarity_flag_adc10_ready"}, /* Polarity Control ADC , */\
+ { 0x4d00, "int_polarity_flag_bst_bstcur"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "int_polarity_flag_bst_hiz"}, /* Polarity DCDC active , */\
+ { 0x4d20, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "int_polarity_flag_bst_peakcur"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "int_polarity_flag_bst_voutcomp"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "int_polarity_flag_bst_voutcomp86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "int_polarity_flag_bst_voutcomp93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d90, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "int_polarity_flag_man_wait_src_settings"}, /* Polarity waits HW I2C settings , */\
+ { 0x4dc0, "int_polarity_flag_man_start_mute_audio"}, /* Polarity man audio mute sequence , */\
+ { 0x4df0, "int_polarity_flag_clk_out_of_range"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4e20, "int_polarity_flag_clip"}, /* Polarity clip right , */\
+ { 0x4e40, "int_polarity_flag_lp_detect_mode0"}, /* Polarity low power mode0 , */\
+ { 0x4e50, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "int_polarity_flag_low_amplitude"}, /* Polarity low noise mode , */\
+ { 0x4e70, "int_polarity_flag_vddp_gt_vbat"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5110, "soft_mute"}, /* Soft mute HW , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for Battery Safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5420, "fb_hz"}, /* Feedback resistor set to high ohmic , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5582, "dpsa_drive"}, /* Drive setting (bin. coded) , */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x6081, "pga_gain_set"}, /* PGA gain selection , */\
+ { 0x60b0, "pga_lowpass_enable"}, /* Lowpass enable , */\
+ { 0x60c0, "pga_pwr_enable"}, /* Power enable, directcontrol mode only , */\
+ { 0x60d0, "pga_switch_enable"}, /* Switch enable, directcontrol mode only , */\
+ { 0x60e0, "pga_switch_aux_enable"}, /* Switch enable aux, directcontrol mode only , */\
+ { 0x6100, "force_idle"}, /* force low power in idle mode , */\
+ { 0x6110, "bypass_idle"}, /* bypass low power idle mode , */\
+ { 0x6123, "ctrl_attl"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x61a0, "idle_cnt"}, /* idle counter , */\
+ { 0x61b0, "enbl_idle_ch1"}, /* enable idle feature for channel 1 , */\
+ { 0x6265, "zero_lvl"}, /* low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_classd"}, /* class D gain ctrl_fb_50k ctrl_fb_100k , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6801, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6821, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6841, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6881, "pdm_anc_sel"}, /* anc input , */\
+ { 0x68a0, "anc_1scomplement"}, /* ANC one s complement , */\
+ { 0x6901, "sam_mode"}, /* sam enable , */\
+ { 0x6920, "sam_src"}, /* sam source , */\
+ { 0x6931, "pdmdat_h_sel"}, /* pdm out value when pdm_clk is higth , */\
+ { 0x6951, "pdmdat_l_sel"}, /* pdm out value when pdm_clk is low , */\
+ { 0x6970, "sam_spkr_sel"}, /* ram output on mode sam and audio , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* disable auto engange , */\
+ { 0x6b10, "sel_tdm_data_valid"}, /* select tdm valid for speaker subsystem , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_lp_detect_mode0"}, /* low power mode 0 detection , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* enable current sense compensation , */\
+ { 0x6f60, "sel_clip_pwms"}, /* Select pwm clip flag , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7002, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7402, "frst_boost_voltage"}, /* 1st boost voltage level , */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Ignore flag_voutcomp86 , */\
+ { 0x7502, "track_decay"}, /* DCDC Boost decay speed after a peak value, effective only when boost_track is set to 1, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x7620, "pga_test_ldo_bypass"}, /* bypass internal PGA LDO , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8200, "enbl_cmfb"}, /* Current sense common mode feedback control , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8222, "cmfb_gain"}, /* Current sense common mode feedback control gain , */\
+ { 0x8254, "cmfb_offset"}, /* Current sense common mode feedback control offset , */\
+ { 0x82a0, "cs_sam_set"}, /* Enable SAM input for current sense , */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8760, "enbl_cs_nofloating_n"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8770, "enbl_cs_nofloating_p"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8800, "volsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0x8810, "vol_cur_sense_dc_offset"}, /* voltage and current sense decimator offset control, */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc5b0, "pga_test_enable"}, /* Enable PGA test mode , */\
+ { 0xc5c0, "pga_test_offset_enable"}, /* Enable PGA test offset , */\
+ { 0xc5d0, "pga_test_shortinput_enable"}, /* Enable PGA test shortinput , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to PDMDAT (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb54, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba4, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xcd64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcdb3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd621, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd641, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd661, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd701, "pdmdat_ehs"}, /* Speed/load setting for PDMDAT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd760, "pdmclk_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* tdm source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_feedback"}, /* gainatt feedback to tdm , */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost , */\
+ { 0xd890, "pdm_loopback"}, /* pdm loop back to tdm , */\
+ { 0xd8a1, "force_pga_clock"}, /* force pga clock , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xee0f, "sw_profile"}, /* Software profile data , */\
+ { 0xef0f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "spare_mpt1_9_6"}, /* HW gain module - left channel (2's complement) , */\
+ { 0xf1a5, "spare_mpt1_15_10"}, /* Offset for amplifier, HW gain module - left channel (2's complement), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a3, "spare_mpt2_13_10"}, /* Trimming of LDO (2.7V) , */\
+ { 0xf307, "spare_mpt3_7_0"}, /* SPARE , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "spare_mtp4_15_0"}, /* SPARE , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf606, "spare_mpt6_6_0"}, /* SPARE , */\
+ { 0xf686, "spare_mpt6_14_8"}, /* Offset of left amplifier level shifter B , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "disable_sam_mode"}, /* Disable same mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Disable programming of max dcdc boost voltage , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf980, "mtp_enbl_amp_in_state_alarm"}, /* Enbl_amp in alarm state , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* pwm delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* ocpclock auto gating , */\
+ { 0xf9b0, "mtp_gate_cgu_clock_for_test"}, /* cgu test clock control , */\
+ { 0xf9c3, "spare_mtp9_15_12"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9872_irq {
+ tfa9872_irq_stvdds = 0,
+ tfa9872_irq_stplls = 1,
+ tfa9872_irq_stotds = 2,
+ tfa9872_irq_stovds = 3,
+ tfa9872_irq_stuvds = 4,
+ tfa9872_irq_stclks = 5,
+ tfa9872_irq_stmtpb = 6,
+ tfa9872_irq_stnoclk = 7,
+ tfa9872_irq_stsws = 10,
+ tfa9872_irq_stamps = 12,
+ tfa9872_irq_starefs = 13,
+ tfa9872_irq_stadccr = 14,
+ tfa9872_irq_stbstcu = 16,
+ tfa9872_irq_stbsthi = 17,
+ tfa9872_irq_stbstoc = 18,
+ tfa9872_irq_stbstpkcur = 19,
+ tfa9872_irq_stbstvc = 20,
+ tfa9872_irq_stbst86 = 21,
+ tfa9872_irq_stbst93 = 22,
+ tfa9872_irq_stocpr = 25,
+ tfa9872_irq_stmwsrc = 26,
+ tfa9872_irq_stmwsmu = 28,
+ tfa9872_irq_stclkoor = 31,
+ tfa9872_irq_sttdmer = 32,
+ tfa9872_irq_stclpr = 34,
+ tfa9872_irq_stlp0 = 36,
+ tfa9872_irq_stlp1 = 37,
+ tfa9872_irq_stla = 38,
+ tfa9872_irq_stvddph = 39,
+ tfa9872_irq_max = 40,
+ tfa9872_irq_all = -1 /* all irqs */};
+
+#define TFA9872_IRQ_NAMETABLE static tfaIrqName_t Tfa9872IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STPLLS"},\
+ { 2, "STOTDS"},\
+ { 3, "STOVDS"},\
+ { 4, "STUVDS"},\
+ { 5, "STCLKS"},\
+ { 6, "STMTPB"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+ { 9, "9"},\
+ { 10, "STSWS"},\
+ { 11, "11"},\
+ { 12, "STAMPS"},\
+ { 13, "STAREFS"},\
+ { 14, "STADCCR"},\
+ { 15, "15"},\
+ { 16, "STBSTCU"},\
+ { 17, "STBSTHI"},\
+ { 18, "STBSTOC"},\
+ { 19, "STBSTPKCUR"},\
+ { 20, "STBSTVC"},\
+ { 21, "STBST86"},\
+ { 22, "STBST93"},\
+ { 23, "23"},\
+ { 24, "24"},\
+ { 25, "STOCPR"},\
+ { 26, "STMWSRC"},\
+ { 27, "27"},\
+ { 28, "STMWSMU"},\
+ { 29, "29"},\
+ { 30, "30"},\
+ { 31, "STCLKOOR"},\
+ { 32, "STTDMER"},\
+ { 33, "33"},\
+ { 34, "STCLPR"},\
+ { 35, "35"},\
+ { 36, "STLP0"},\
+ { 37, "STLP1"},\
+ { 38, "STLA"},\
+ { 39, "STVDDPH"},\
+ { 40, "40"},\
+};
+#endif /* _TFA9872_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames.h
new file mode 100644
index 00000000000..726ffe066a8
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames.h
@@ -0,0 +1,934 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9873_tfaFieldnames.h
+ * This file was generated automatically on 10/21/19 at 17:03:34.
+ * Source file: TFA9873_PRB4_N1A0_I2C_RegisterMap.xlsx
+ */
+
+#ifndef _TFA9873_TFAFIELDNAMES_H
+#define _TFA9873_TFAFIELDNAMES_H
+
+
+#define TFA9873_I2CVERSION 28
+
+typedef enum Tfa9873BfEnumList {
+ TFA9873_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9873_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9873_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9873_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9873_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9873_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9873_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9873_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9873_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9873_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9873_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9873_BF_MUTETO= 0x0160, /*!< Time out SB mute sequence */
+ TFA9873_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9873_BF_DISFCRBST= 0x01f0, /*!< Disable boost control with FRCBST */
+ TFA9873_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9873_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9873_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9873_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9873_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9873_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9873_BF_MANAOOSC= 0x0460, /*!< Internal osc off in power down mode */
+ TFA9873_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9873_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9873_BF_AUTOFROSEL= 0x04a0, /*!< Override automatic OSC selection mechanism */
+ TFA9873_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9873_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9873_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9873_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9873_BF_CLKCHKLO= 0x0707, /*!< Clock check low threshold */
+ TFA9873_BF_CLKCHKHI= 0x0787, /*!< Clock check higher threshold */
+ TFA9873_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9873_BF_VDDS = 0x1000, /*!< POR */
+ TFA9873_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9873_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register, clear on read) */
+ TFA9873_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9873_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register, clear on read) */
+ TFA9873_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9873_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9873_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9873_BF_NOCLK = 0x1080, /*!< Lost clock (sticky register, clear on read) */
+ TFA9873_BF_TDMERR= 0x10a0, /*!< TDM error */
+ TFA9873_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9873_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9873_BF_DCDCPC= 0x1120, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9873_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9873_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9873_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9873_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9873_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9873_BF_CLKOOR= 0x11c0, /*!< External clock status */
+ TFA9873_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9873_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9873_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9873_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9873_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9873_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9873_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9873_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9873_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9873_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9873_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9873_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9873_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9873_BF_TDMSTAT= 0x1402, /*!< TDM status bits */
+ TFA9873_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9873_BF_AMPSTE= 0x1473, /*!< Amplifier control status */
+ TFA9873_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9873_BF_WAITSYNC= 0x14d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9873_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9873_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9873_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9873_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9873_BF_TDMSLOTS= 0x2013, /*!< N-slots in Frame */
+ TFA9873_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9873_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9873_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9873_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9873_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9873_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9873_BF_TDMDEL= 0x21e0, /*!< Data delay to FS */
+ TFA9873_BF_TDMADJ= 0x21f0, /*!< Data adjustment */
+ TFA9873_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9873_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9873_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9873_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9873_BF_TDMSPKE= 0x2300, /*!< Control audio TDM channel in 0 */
+ TFA9873_BF_TDMDCE= 0x2310, /*!< Control audio TDM channel in 1 */
+ TFA9873_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9873_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9873_BF_TDMSPKS= 0x2603, /*!< TDM slot for sink 0 */
+ TFA9873_BF_TDMDCS= 0x2643, /*!< TDM slot for sink 1 */
+ TFA9873_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9873_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9873_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9873_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9873_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9873_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9873_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9873_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9873_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9873_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9873_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9873_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9873_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9873_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9873_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9873_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9873_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9873_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9873_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9873_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9873_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9873_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9873_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9873_BF_IEMANALARM= 0x4850, /*!< Enable manager alarm state */
+ TFA9873_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9873_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9873_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9873_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9873_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9873_BF_IPOOCPR= 0x4c30, /*!< Polarity OCP alarm */
+ TFA9873_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9873_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9873_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9873_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9873_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9873_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9873_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9873_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9873_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9873_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9873_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9873_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9873_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9873_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9873_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9873_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9873_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9873_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9873_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9873_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9873_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9873_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9873_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9873_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9873_BF_TDMSRCACLIP= 0x6871, /*!< Clip information (analog /digital) for source0 */
+ TFA9873_BF_TDMSRCBCLIP= 0x6891, /*!< Clip information (analog /digital) for source1 */
+ TFA9873_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9873_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9873_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9873_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9873_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9873_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9873_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9873_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9873_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9873_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9873_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9873_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9873_BF_DCOVL = 0x7085, /*!< Threshold level to activate active overshoot control */
+ TFA9873_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9873_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9873_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9873_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9873_BF_ENBSTFLT= 0x7620, /*!< Enable the boost filter */
+ TFA9873_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9873_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9873_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9873_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9873_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9873_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9873_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9873_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9873_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9873_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9873_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9873_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9873_BF_PLLINSI= 0xcd05, /*!< PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1 */
+ TFA9873_BF_PLLINSP= 0xcd64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873_BF_PLLINSR= 0xcdb3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection control, USE WITH CAUTION */
+ TFA9873_BF_PLLNDEC= 0xce09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLMDECM= 0xcea0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLBP = 0xceb0, /*!< PLL bypass control during functional mode */
+ TFA9873_BF_PLLDI = 0xcec0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLDO = 0xced0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLCLKSTB= 0xcee0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLFRM= 0xcef0, /*!< PLL free running mode control in functional mode */
+ TFA9873_BF_PLLMDECL= 0xcf0f, /*!< Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLPDEC= 0xd006, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLDCTRL= 0xd070, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9873_BF_PLLLIMOFF= 0xd090, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9873_BF_PLLSTRTM= 0xd0a2, /*!< PLL startup time selection control */
+ TFA9873_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9873_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9873_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9873_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9873_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9873_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9873_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9873_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9873_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9873BfEnumList_t;
+#define TFA9873_NAMETABLE static tfaBfName_t Tfa9873DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x160, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "DISFCRBST"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal osc off in power down mode , */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "AUTOFROSEL"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x707, "CLKCHKLO"}, /* Clock check low threshold , */\
+ { 0x787, "CLKCHKHI"}, /* Clock check higher threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "TDMERR"}, /* TDM error , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11c0, "CLKOOR"}, /* External clock status , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1402, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1473, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x14d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2013, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable manager alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7085, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLINSI"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "PLLINSP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "PLLINSR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "PLLMDECM"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "PLLBP"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "PLLDI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "PLLDO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "PLLCLKSTB"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "PLLMDECL"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "PLLDCTRL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9873_BITNAMETABLE static tfaBfName_t Tfa9873BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x160, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "disable_frcbst"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal osc off in power down mode , */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "override_auto_sel_osc"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x707, "clkchk_th_lo"}, /* Clock check low threshold , */\
+ { 0x787, "clkchk_th_hi"}, /* Clock check higher threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11c0, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1402, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x14d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2013, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable manager alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA release time , */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5463, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x5500, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5513, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5552, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x5581, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5631, "ref_irefdist_set_ctrl"}, /* Scaling of reference current for OCP , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5900, "sel_pwm_freq"}, /* Control for selection for PWM switching frequency , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6631, "pfm2pwm_cnt_max"}, /* Number of pulses in PFM mode before going to PWM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* Disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7085, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC , */\
+ { 0x72a5, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8887, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xb200, "bypass_ovpglitchfilter"}, /* Bypass glitch filter on over voltage protection signal from analog, */\
+ { 0xb210, "enbl_ovp_alarm_state"}, /* Allow manager to go into alarm state when OVP (only when ctrl_vpalarm is 0), */\
+ { 0xb220, "amp_in_tristate_when_ovp"}, /* Brings amplifier in tristate when OVP (only when ctrl_enbl_ovp_alarm_state is 0) , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_tdm_feedback"}, /* GainAtt feedback to TDM , */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd890, "railclamp_disable"}, /* ESD rail clamp control, controls amp and boost rail clamp for ESD, */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xd920, "enbl_irefcal"}, /* Enable IREF calibration , */\
+ { 0xd930, "start_iref_calibration"}, /* Start IREF Calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xda80, "iref_calibration_done"}, /* IREF Calibration done - Read Only , */\
+ { 0xda94, "iref_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xdae0, "iref_calibration_error"}, /* IREF Calibration done - Read Only , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs1"}, /* Voltage sense gain when external voltage sensing input is selected, */\
+ { 0xf387, "calibr_gain_vs2"}, /* Voltage sense gain when internal voltage sensing input is selected, */\
+ { 0xf407, "vs_trim1"}, /* VS Trimming when external voltage sensing input is selected, */\
+ { 0xf487, "vs_trim2"}, /* VS Trimming when internal voltage sensing input is selected, */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9873_irq {
+ tfa9873_irq_stvdds = 0,
+ tfa9873_irq_stbstoc = 1,
+ tfa9873_irq_stotds = 2,
+ tfa9873_irq_stocpr = 3,
+ tfa9873_irq_stuvds = 4,
+ tfa9873_irq_stmanalarm = 5,
+ tfa9873_irq_sttdmer = 6,
+ tfa9873_irq_stnoclk = 7,
+ tfa9873_irq_max = 8,
+ tfa9873_irq_all = -1 /* all irqs */};
+
+#define TFA9873_IRQ_NAMETABLE static tfaIrqName_t Tfa9873IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+};
+#endif /* _TFA9873_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames_B0.h b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames_B0.h
new file mode 100644
index 00000000000..7bd0a99256d
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames_B0.h
@@ -0,0 +1,933 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+
+#ifndef _TFA9873_TFAFIELDNAMES_B0_H
+#define _TFA9873_TFAFIELDNAMES_B0_H
+
+
+#define TFA9873B0_I2CVERSION 20
+
+typedef enum Tfa9873B0BfEnumList {
+ TFA9873B0_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9873B0_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9873B0_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9873B0_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9873B0_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9873B0_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9873B0_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9873B0_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9873B0_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9873B0_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9873B0_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9873B0_BF_MUTETO= 0x0160, /*!< Time out SB mute sequence */
+ TFA9873B0_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9873B0_BF_DISFCRBST= 0x01f0, /*!< Disable boost control with FRCBST */
+ TFA9873B0_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9873B0_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9873B0_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9873B0_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9873B0_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9873B0_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9873B0_BF_MANAOOSC= 0x0460, /*!< Internal osc off in power down mode */
+ TFA9873B0_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9873B0_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9873B0_BF_AUTOFROSEL= 0x04a0, /*!< Override automatic OSC selection mechanism */
+ TFA9873B0_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9873B0_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9873B0_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9873B0_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9873B0_BF_CLKCHKLO= 0x0707, /*!< Clock check low threshold */
+ TFA9873B0_BF_CLKCHKHI= 0x0787, /*!< Clock check higher threshold */
+ TFA9873B0_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9873B0_BF_VDDS = 0x1000, /*!< POR */
+ TFA9873B0_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9873B0_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register, clear on read) */
+ TFA9873B0_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9873B0_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register, clear on read) */
+ TFA9873B0_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9873B0_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9873B0_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9873B0_BF_NOCLK = 0x1080, /*!< Lost clock (sticky register, clear on read) */
+ TFA9873B0_BF_TDMERR= 0x10a0, /*!< TDM error */
+ TFA9873B0_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9873B0_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9873B0_BF_DCDCPC= 0x1120, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9873B0_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9873B0_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9873B0_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9873B0_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9873B0_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9873B0_BF_CLKOOR= 0x11c0, /*!< External clock status */
+ TFA9873B0_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9873B0_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9873B0_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9873B0_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9873B0_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9873B0_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9873B0_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9873B0_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9873B0_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9873B0_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9873B0_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9873B0_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9873B0_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9873B0_BF_TDMSTAT= 0x1402, /*!< TDM status bits */
+ TFA9873B0_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9873B0_BF_AMPSTE= 0x1473, /*!< Amplifier control status */
+ TFA9873B0_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9873B0_BF_WAITSYNC= 0x14d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9873B0_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9873B0_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9873B0_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9873B0_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9873B0_BF_TDMSLOTS= 0x2013, /*!< N-slots in Frame */
+ TFA9873B0_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9873B0_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9873B0_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9873B0_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9873B0_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9873B0_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9873B0_BF_TDMDEL= 0x21e0, /*!< Data delay to FS */
+ TFA9873B0_BF_TDMADJ= 0x21f0, /*!< Data adjustment */
+ TFA9873B0_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9873B0_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9873B0_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9873B0_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9873B0_BF_TDMSPKE= 0x2300, /*!< Control audio TDM channel in 0 */
+ TFA9873B0_BF_TDMDCE= 0x2310, /*!< Control audio TDM channel in 1 */
+ TFA9873B0_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_TDMSPKS= 0x2603, /*!< TDM slot for sink 0 */
+ TFA9873B0_BF_TDMDCS= 0x2643, /*!< TDM slot for sink 1 */
+ TFA9873B0_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9873B0_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9873B0_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9873B0_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9873B0_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9873B0_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9873B0_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9873B0_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9873B0_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9873B0_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9873B0_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9873B0_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9873B0_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9873B0_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9873B0_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9873B0_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9873B0_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9873B0_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9873B0_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9873B0_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9873B0_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9873B0_BF_IEMANALARM= 0x4850, /*!< Enable manager alarm state */
+ TFA9873B0_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9873B0_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9873B0_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9873B0_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9873B0_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9873B0_BF_IPOOCPR= 0x4c30, /*!< Polarity OCP alarm */
+ TFA9873B0_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9873B0_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9873B0_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9873B0_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9873B0_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9873B0_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9873B0_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9873B0_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9873B0_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9873B0_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9873B0_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9873B0_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9873B0_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9873B0_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9873B0_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9873B0_BF_SLOPEE= 0x55a0, /*!< Enables slope control */
+ TFA9873B0_BF_SLOPESET= 0x55b0, /*!< Slope speed setting */
+ TFA9873B0_BF_PWMFREQ= 0x5900, /*!< Control for selection for PWM switching frequency */
+ TFA9873B0_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9873B0_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9873B0_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9873B0_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9873B0_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9873B0_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9873B0_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9873B0_BF_TDMSRCACLIP= 0x6871, /*!< Clip information (analog /digital) for source0 */
+ TFA9873B0_BF_TDMSRCBCLIP= 0x6891, /*!< Clip information (analog /digital) for source1 */
+ TFA9873B0_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9873B0_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9873B0_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9873B0_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9873B0_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9873B0_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9873B0_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9873B0_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9873B0_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9873B0_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9873B0_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9873B0_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9873B0_BF_DCOVL = 0x7085, /*!< Threshold level to activate active overshoot control */
+ TFA9873B0_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9873B0_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9873B0_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9873B0_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873B0_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873B0_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9873B0_BF_ENBSTFLT= 0x7620, /*!< Enable the boost filter */
+ TFA9873B0_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9873B0_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9873B0_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9873B0_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9873B0_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9873B0_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9873B0_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9873B0_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9873B0_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9873B0_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9873B0_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9873B0_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9873B0_BF_PLLINSI= 0xcd05, /*!< PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLINSP= 0xcd64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLINSR= 0xcdb3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection control, USE WITH CAUTION */
+ TFA9873B0_BF_PLLNDEC= 0xce09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLMDECM= 0xcea0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLBP = 0xceb0, /*!< PLL bypass control during functional mode */
+ TFA9873B0_BF_PLLDI = 0xcec0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLDO = 0xced0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLCLKSTB= 0xcee0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLFRM= 0xcef0, /*!< PLL free running mode control in functional mode */
+ TFA9873B0_BF_PLLMDECL= 0xcf0f, /*!< Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLPDEC= 0xd006, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLDCTRL= 0xd070, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9873B0_BF_PLLLIMOFF= 0xd090, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLSTRTM= 0xd0a2, /*!< PLL startup time selection control */
+ TFA9873B0_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9873B0_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9873B0_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9873B0_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9873B0_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9873B0_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9873B0_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9873B0_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9873B0_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9873B0BfEnumList_t;
+#define TFA9873B0_NAMETABLE static tfaBfName_t Tfa9873B0DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x160, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "DISFCRBST"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal osc off in power down mode , */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "AUTOFROSEL"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x707, "CLKCHKLO"}, /* Clock check low threshold , */\
+ { 0x787, "CLKCHKHI"}, /* Clock check higher threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "TDMERR"}, /* TDM error , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11c0, "CLKOOR"}, /* External clock status , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1402, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1473, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x14d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2013, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable manager alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x55a0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x55b0, "SLOPESET"}, /* Slope speed setting , */\
+ { 0x5900, "PWMFREQ"}, /* Control for selection for PWM switching frequency , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7085, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLINSI"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "PLLINSP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "PLLINSR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "PLLMDECM"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "PLLBP"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "PLLDI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "PLLDO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "PLLCLKSTB"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "PLLMDECL"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "PLLDCTRL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9873B0_BITNAMETABLE static tfaBfName_t Tfa9873B0BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x160, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "disable_frcbst"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal osc off in power down mode , */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "override_auto_sel_osc"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x707, "clkchk_th_lo"}, /* Clock check low threshold , */\
+ { 0x787, "clkchk_th_hi"}, /* Clock check higher threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11c0, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1402, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x14d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2013, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable manager alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA release time , */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5463, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x54a1, "ref_amp_irefdist_set_ctrl"}, /* Scaling of reference current for amplifier OCP , */\
+ { 0x5500, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5513, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5552, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x5581, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x55a0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x55b0, "ctrl_slope"}, /* Slope speed setting , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5900, "sel_pwm_freq"}, /* Control for selection for PWM switching frequency , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* Disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7085, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC , */\
+ { 0x72a5, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7360, "disable_artf676996_fix"}, /* Disables the fix for artf676996 (OCP booster triggered when Vtrgt is just above Vbat), */\
+ { 0x7371, "ref_bst_irefdist_set_ctrl"}, /* Scaling of reference current for booster OCP , */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8887, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xb200, "bypass_ovpglitchfilter"}, /* Bypass glitch filter on over voltage protection signal from analog, */\
+ { 0xb210, "enbl_ovp_alarm_state"}, /* Allow manager to go into alarm state when OVP (only when ctrl_vpalarm is 0), */\
+ { 0xb220, "amp_in_tristate_when_ovp"}, /* Brings amplifier in tristate when OVP (only when ctrl_enbl_ovp_alarm_state is 0) , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_tdm_feedback"}, /* GainAtt feedback to TDM , */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xd920, "enbl_irefcal"}, /* Enable IREF calibration , */\
+ { 0xd930, "start_iref_calibration"}, /* Start IREF Calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xda80, "iref_calibration_done"}, /* IREF Calibration done - Read Only , */\
+ { 0xda94, "iref_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xdae0, "iref_calibration_error"}, /* IREF Calibration done - Read Only , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs1"}, /* Voltage sense gain when external voltage sensing input is selected, */\
+ { 0xf387, "calibr_gain_vs2"}, /* Voltage sense gain when internal voltage sensing input is selected, */\
+ { 0xf407, "vs_trim1"}, /* VS Trimming when external voltage sensing input is selected, */\
+ { 0xf487, "vs_trim2"}, /* VS Trimming when internal voltage sensing input is selected, */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "mtp_pll_lut_sel"}, /* PLL lookup table selection control , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+#if 0
+enum tfa9873_irq {
+ tfa9873_irq_stvdds = 0,
+ tfa9873_irq_stbstoc = 1,
+ tfa9873_irq_stotds = 2,
+ tfa9873_irq_stocpr = 3,
+ tfa9873_irq_stuvds = 4,
+ tfa9873_irq_stmanalarm = 5,
+ tfa9873_irq_sttdmer = 6,
+ tfa9873_irq_stnoclk = 7,
+ tfa9873_irq_max = 8,
+ tfa9873_irq_all = -1 /* all irqs */};
+#endif//
+#define TFA9873_IRQ_NAMETABLE static tfaIrqName_t Tfa9873IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+};
+#endif /* _TFA9873_TFAFIELDNAMES_B0_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9874_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9874_tfafieldnames.h
new file mode 100644
index 00000000000..7fba0d68960
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9874_tfafieldnames.h
@@ -0,0 +1,843 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9874_tfaFieldnames_last.h
+ * This file was generated automatically on 09/28/18 at 11:20:52.
+ * Source file: TFA9874N1C0_DefaultI2CSettings.xlsx
+ */
+
+#ifndef _TFA9874_TFAFIELDNAMES_H
+#define _TFA9874_TFAFIELDNAMES_H
+
+
+#define TFA9874_I2CVERSION 1.16
+
+typedef enum Tfa9874BfEnumList {
+ TFA9874_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9874_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9874_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA9874_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9874_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9874_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9874_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9874_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9874_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA9874_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA9874_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9874_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9874_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9874_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9874_BF_REV = 0x030f, /*!< Revision info */
+ TFA9874_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9874_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9874_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9874_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9874_BF_VDDS = 0x1000, /*!< POR */
+ TFA9874_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register , clear on read) */
+ TFA9874_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register , clear on read) */
+ TFA9874_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register , clear on read) */
+ TFA9874_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register , clear on read) */
+ TFA9874_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9874_BF_TDMERR= 0x1060, /*!< TDM error */
+ TFA9874_BF_NOCLK = 0x1070, /*!< Lost clock (sticky register , clear on read) */
+ TFA9874_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9874_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register , clear on read) */
+ TFA9874_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9874_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9874_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9874_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9874_BF_CLKS = 0x1170, /*!< Clocks stable */
+ TFA9874_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9874_BF_TDMSTAT= 0x1192, /*!< TDM status bits */
+ TFA9874_BF_MTPB = 0x11c0, /*!< MTP busy */
+ TFA9874_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9874_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9874_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9874_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9874_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9874_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9874_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9874_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9874_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9874_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9874_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9874_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9874_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9874_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA9874_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9874_BF_DCMODE= 0x1471, /*!< DCDC mode status bits */
+ TFA9874_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9874_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9874_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9874_BF_TDME = 0x2040, /*!< Enable interface */
+ TFA9874_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA9874_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9874_BF_TDMFSLN= 0x2073, /*!< FS length (master mode only) */
+ TFA9874_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9874_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9874_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA9874_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9874_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9874_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9874_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9874_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9874_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9874_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9874_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9874_BF_TDMSPKE= 0x2300, /*!< Control audio tdm channel in 0 (spkr + dcdc) */
+ TFA9874_BF_TDMDCE= 0x2310, /*!< Control audio tdm channel in 1 (dcdc) */
+ TFA9874_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9874_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9874_BF_TDMSPKS= 0x2603, /*!< tdm slot for sink 0 (speaker + dcdc) */
+ TFA9874_BF_TDMDCS= 0x2643, /*!< tdm slot for sink 1 (dcdc) */
+ TFA9874_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9874_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9874_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9874_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9874_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9874_BF_ISTOCPR= 0x4030, /*!< Status ocp alarm */
+ TFA9874_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9874_BF_ISTMANALARM= 0x4050, /*!< Status nanager Alarm state */
+ TFA9874_BF_ISTTDMER= 0x4060, /*!< Status tdm error */
+ TFA9874_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9874_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9874_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9874_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9874_BF_ICLOCPR= 0x4430, /*!< Clear ocp alarm */
+ TFA9874_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9874_BF_ICLMANALARM= 0x4450, /*!< clear nanager Alarm state */
+ TFA9874_BF_ICLTDMER= 0x4460, /*!< Clear tdm error */
+ TFA9874_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9874_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9874_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9874_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9874_BF_IEOCPR= 0x4830, /*!< Enable ocp alarm */
+ TFA9874_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9874_BF_IEMANALARM= 0x4850, /*!< Enable nanager Alarm state */
+ TFA9874_BF_IETDMER= 0x4860, /*!< Enable tdm error */
+ TFA9874_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9874_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9874_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9874_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9874_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9874_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9874_BF_IPOMANALARM= 0x4c50, /*!< Polarity nanager Alarm state */
+ TFA9874_BF_IPOTDMER= 0x4c60, /*!< Polarity tdm error */
+ TFA9874_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9874_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time */
+ TFA9874_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9874_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9874_BF_VBATFLTL= 0x5080, /*!< vbat filter limit */
+ TFA9874_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9874_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9874_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9874_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9874_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9874_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9874_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9874_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9874_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9874_BF_TDMDCG= 0x6123, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9874_BF_TDMSPKG= 0x6163, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9874_BF_LNMODE= 0x62e1, /*!< ctrl select mode */
+ TFA9874_BF_LPM1MODE= 0x64e1, /*!< low power mode control */
+ TFA9874_BF_TDMSRCMAP= 0x6802, /*!< tdm source mapping */
+ TFA9874_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9874_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9874_BF_TDMSRCACLIP= 0x6871, /*!< clip information (analog /digital) for source0 */
+ TFA9874_BF_TDMSRCBCLIP= 0x6891, /*!< clip information (analog /digital) for source1 */
+ TFA9874_BF_LP1 = 0x6e10, /*!< low power mode 1 detection */
+ TFA9874_BF_LA = 0x6e20, /*!< low amplitude detection */
+ TFA9874_BF_VDDPH = 0x6e30, /*!< vddp greater than vbat */
+ TFA9874_BF_DELCURCOMP= 0x6f02, /*!< delay to allign compensation signal with current sense signal */
+ TFA9874_BF_SIGCURCOMP= 0x6f40, /*!< polarity of compensation for current sense */
+ TFA9874_BF_ENCURCOMP= 0x6f50, /*!< enable current sense compensation */
+ TFA9874_BF_LVLCLPPWM= 0x6f72, /*!< set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9874_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA9874_BF_DCCV = 0x7071, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9874_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA9874_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA9874_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9874_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9874_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9874_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9874_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9874_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9874_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9874_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9874_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9874_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9874_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9874_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9874_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9874_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9874_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9874_BF_SWPROFIL= 0xee0f, /*!< Software profile data */
+ TFA9874_BF_SWVSTEP= 0xef0f, /*!< Software vstep information */
+ TFA9874_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9874_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9874_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9874_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9874_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9874_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9874_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9874BfEnumList_t;
+#define TFA9874_NAMETABLE static tfaBfName_t Tfa9874DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "TDMERR"}, /* TDM error , */\
+ { 0x1070, "NOCLK"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1170, "CLKS"}, /* Clocks stable , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x1192, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11c0, "MTPB"}, /* MTP busy , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1471, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2040, "TDME"}, /* Enable interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "TDMDCE"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status nanager Alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* clear nanager Alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5080, "VBATFLTL"}, /* vbat filter limit , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x6123, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x62e1, "LNMODE"}, /* ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6e10, "LP1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* vddp greater than vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xee0f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xef0f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9874_BITNAMETABLE static tfaBfName_t Tfa9874BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x140, "enbl_osc1m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2d0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1170, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x1192, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11c0, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1471, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2040, "tdm_enable"}, /* Enable interface , */\
+ { 0x2050, "tdm_mode"}, /* Slave/master , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status nanager Alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* clear nanager Alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5080, "vbat_flt_limit"}, /* vbat filter limit , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for Battery Safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5582, "dpsa_drive"}, /* Drive setting (bin. coded) , */\
+ { 0x5690, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x56a1, "enbl_odd_up_even_down"}, /* Control for PWM reference sawtooth generartion , */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x6123, "ctrl_attl"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6265, "zero_lvl"}, /* low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7360, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8801, "volsense_pwm_sel"}, /* Voltage sense source selection control , */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8870, "vs_igen_supply"}, /* Switch internal supply of current generator , */\
+ { 0x8887, "vs_gain"}, /* voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d10, "vs_classd_tran_skip"}, /* Skip voltage sense connection during a classD amplifier transition, */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* voltage sense Direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to PDMDAT (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xcd64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcdb3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd621, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd641, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd661, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* tdm source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_feedback"}, /* gainatt feedback to tdm , */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xee0f, "sw_profile"}, /* Software profile data , */\
+ { 0xef0f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf169, "spare_mpt1_15_6"}, /* SPARE , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a5, "spare_mtp2_15_10"}, /* SPARE , */\
+ { 0xf307, "calibr_gain_vs"}, /* Voltage sense gain , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf407, "spare_mtp4_15_0"}, /* SPARE , */\
+ { 0xf487, "vs_trim"}, /* VS Trimming , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf60f, "spare_mpt6_6_0"}, /* SPARE , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf770, "spare_mtp7_07"}, /* SPARE , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf7f0, "spare_mtp7_15"}, /* SPARE , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "spare_mtp9_1"}, /* SPARE , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf980, "spare_mtp9_8"}, /* SPARE , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* pwm delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* ocpclock auto gating , */\
+ { 0xf9b0, "mtp_gate_cgu_clock_for_test"}, /* cgu test clock control , */\
+ { 0xf9c0, "mtp_tdm_pad_sel"}, /* tdm pad selection , */\
+ { 0xf9d2, "spare_mtp9_15_12"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xff87, "spare_mtp7_15_08"}, /* SPARE , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9874_irq {
+ tfa9874_irq_stvdds = 0,
+ tfa9874_irq_stbstoc = 1,
+ tfa9874_irq_stotds = 2,
+ tfa9874_irq_stocpr = 3,
+ tfa9874_irq_stuvds = 4,
+ tfa9874_irq_stmanalarm = 5,
+ tfa9874_irq_sttdmer = 6,
+ tfa9874_irq_stnoclk = 7,
+ tfa9874_irq_max = 8,
+ tfa9874_irq_all = -1 /* all irqs */};
+
+#define TFA9874_IRQ_NAMETABLE static tfaIrqName_t Tfa9874IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+};
+#endif /* _TFA9874_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames.h
new file mode 100644
index 00000000000..6f053bf48e6
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames.h
@@ -0,0 +1,936 @@
+/*
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _TFA9875_TFAFIELDNAMES_H
+#define _TFA9875_TFAFIELDNAMES_H
+
+
+#define TFA9875_I2CVERSION 26
+
+typedef enum Tfa9875BfEnumList {
+ TFA9875_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9875_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9875_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9875_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9875_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9875_BF_BYPUVP= 0x00a0, /*!< Bypass UVP */
+ TFA9875_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9875_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9875_BF_MANWTIME= 0x00d0, /*!< Manager wait time selection control */
+ TFA9875_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9875_BF_COORHYS= 0x00f0, /*!< Select hysteresis for clock range detector */
+ TFA9875_BF_MANSCONF= 0x0120, /*!< Configuration setting if I2C settings are uploaded by the host */
+ TFA9875_BF_MUTETO= 0x0160, /*!< Time out mute sequence */
+ TFA9875_BF_MANROBOD= 0x0170, /*!< Controls the reaction of the device on BOD */
+ TFA9875_BF_BODHYS= 0x0180, /*!< Enable Hysteresis of BOD */
+ TFA9875_BF_BODFILT= 0x0191, /*!< BOD filter */
+ TFA9875_BF_BODTHLVL= 0x01b1, /*!< BOD threshold level */
+ TFA9875_BF_MANEDCTH= 0x01d0, /*!< Device response to too high DC level flag (DCTH = 1) */
+ TFA9875_BF_OPENMTP= 0x01e0, /*!< Control for MTP protection */
+ TFA9875_BF_AUDFS = 0x0203, /*!< Sample rate (Fs) */
+ TFA9875_BF_ENLBW = 0x0240, /*!< CS/VS decimator low bandwidth mode control */
+ TFA9875_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9875_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9875_BF_REFCKEXT= 0x0400, /*!< PLL external ref clock */
+ TFA9875_BF_MANAOOSC= 0x0460, /*!< Internal oscillator control during power down mode */
+ TFA9875_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9875_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9875_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9875_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9875_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9875_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM (MTP) */
+ TFA9875_BF_VDDS = 0x1000, /*!< POR (sticky flag, clear on write a '1') */
+ TFA9875_BF_OTDS = 0x1010, /*!< OTP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_UVDS = 0x1020, /*!< UVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OVDS = 0x1030, /*!< OVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCDS = 0x1040, /*!< OCP amplifier (sticky flag, clear on write a '1') */
+ TFA9875_BF_NOCLK = 0x1050, /*!< Lost clock (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKOOR= 0x1060, /*!< External clock status (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCOCPOK= 0x1070, /*!< DCDC OCP nmos (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCIL = 0x1080, /*!< DCDC current limiting (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCDCA = 0x1090, /*!< DCDC active (sticky flag, clear on write a '1') */
+ TFA9875_BF_ADCCR = 0x10a0, /*!< ADC ready flag (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAP= 0x10b0, /*!< OCPOK pmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAN= 0x10c0, /*!< OCPOK nmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBP= 0x10d0, /*!< OCPOK pmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBN= 0x10e0, /*!< OCPOK nmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCTH = 0x10f0, /*!< DC level on audio input stream too high (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKS = 0x1100, /*!< Clocks stable */
+ TFA9875_BF_MTPB = 0x1110, /*!< MTP busy */
+ TFA9875_BF_TDMERR= 0x1120, /*!< TDM error */
+ TFA9875_BF_DCDCPC= 0x1130, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9875_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9875_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9875_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9875_BF_PLLS = 0x1170, /*!< PLL lock */
+ TFA9875_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9875_BF_SWS = 0x1190, /*!< Amplifier engage */
+ TFA9875_BF_AMPS = 0x11a0, /*!< Amplifier enable */
+ TFA9875_BF_AREFS = 0x11b0, /*!< References enable */
+ TFA9875_BF_CLIPS = 0x11c0, /*!< Amplifier clipping */
+ TFA9875_BF_MANSTATE= 0x1203, /*!< Device manager status */
+ TFA9875_BF_AMPSTE= 0x1243, /*!< Amplifier control status */
+ TFA9875_BF_TDMSTAT= 0x1282, /*!< TDM status bits */
+ TFA9875_BF_DCMODE= 0x12b1, /*!< DCDC mode status bits */
+ TFA9875_BF_WAITSYNC= 0x12d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9875_BF_BODNOK= 0x1300, /*!< BOD Flag VDD NOT OK (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCLD = 0x140c, /*!< DC level detected by DC protection module (2s complement) */
+ TFA9875_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9875_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9875_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9875_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9875_BF_AMPINSEL= 0x2011, /*!< Amplifier input selection */
+ TFA9875_BF_INPLEV= 0x2030, /*!< TDM output attenuation */
+ TFA9875_BF_TDMCLINV= 0x2040, /*!< Reception data to BCK clock */
+ TFA9875_BF_TDMFSPOL= 0x2050, /*!< FS polarity */
+ TFA9875_BF_TDMSLOTS= 0x2061, /*!< N-slots in Frame */
+ TFA9875_BF_TDMSLLN= 0x2081, /*!< N-bits in slot */
+ TFA9875_BF_TDMSSIZE= 0x20a1, /*!< Sample size per slot */
+ TFA9875_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9875_BF_TDMDEL= 0x2100, /*!< Data delay to FS */
+ TFA9875_BF_TDMADJ= 0x2110, /*!< Data adjustment */
+ TFA9875_BF_TDMSPKE= 0x2120, /*!< Control audio TDM channel in 0 */
+ TFA9875_BF_TDMDCE= 0x2130, /*!< Control audio TDM channel in 1 */
+ TFA9875_BF_TDMSRC0E= 0x2140, /*!< Enable TDM source0 data channel */
+ TFA9875_BF_TDMSRC1E= 0x2150, /*!< Enable TDM source1 data channel */
+ TFA9875_BF_TDMSRC2E= 0x2160, /*!< Enable TDM source2 data channel */
+ TFA9875_BF_TDMSRC3E= 0x2170, /*!< Enable TDM source3 data channel */
+ TFA9875_BF_TDMSPKS= 0x2183, /*!< TDM slot for sink 0 */
+ TFA9875_BF_TDMDCS= 0x21c3, /*!< TDM slot for sink 1 */
+ TFA9875_BF_TDMSRC0S= 0x2203, /*!< Slot Position of TDM source0 channel data */
+ TFA9875_BF_TDMSRC1S= 0x2243, /*!< Slot Position of TDM source1 channel data */
+ TFA9875_BF_TDMSRC2S= 0x2283, /*!< Slot Position of TDM source2 channel data */
+ TFA9875_BF_TDMSRC3S= 0x22c3, /*!< Slot Position of TDM source3 channel data */
+ TFA9875_BF_ISTVDDS= 0x4000, /*!< Interrupt status POR */
+ TFA9875_BF_ISTBSTOC= 0x4010, /*!< Interrupt status DCDC OCP alarm */
+ TFA9875_BF_ISTOTDS= 0x4020, /*!< Interrupt status OTP alarm */
+ TFA9875_BF_ISTOCPR= 0x4030, /*!< Interrupt status OCP alarm */
+ TFA9875_BF_ISTUVDS= 0x4040, /*!< Interrupt status UVP alarm */
+ TFA9875_BF_ISTTDMER= 0x4050, /*!< Interrupt status TDM error */
+ TFA9875_BF_ISTNOCLK= 0x4060, /*!< Interrupt status lost clock */
+ TFA9875_BF_ISTDCTH= 0x4070, /*!< Interrupt status dc too high */
+ TFA9875_BF_ISTBODNOK= 0x4080, /*!< Interrupt status brown out detected */
+ TFA9875_BF_ISTCOOR= 0x4090, /*!< Interrupt status clock out of range */
+ TFA9875_BF_ICLVDDS= 0x4400, /*!< Clear interrupt status POR */
+ TFA9875_BF_ICLBSTOC= 0x4410, /*!< Clear interrupt status DCDC OCP */
+ TFA9875_BF_ICLOTDS= 0x4420, /*!< Clear interrupt status OTP alarm */
+ TFA9875_BF_ICLOCPR= 0x4430, /*!< Clear interrupt status OCP alarm */
+ TFA9875_BF_ICLUVDS= 0x4440, /*!< Clear interrupt status UVP alarm */
+ TFA9875_BF_ICLTDMER= 0x4450, /*!< Clear interrupt status TDM error */
+ TFA9875_BF_ICLNOCLK= 0x4460, /*!< Clear interrupt status lost clk */
+ TFA9875_BF_ICLDCTH= 0x4470, /*!< Clear interrupt status dc too high */
+ TFA9875_BF_ICLBODNOK= 0x4480, /*!< Clear interrupt status brown out detected */
+ TFA9875_BF_ICLCOOR= 0x4490, /*!< Clear interrupt status clock out of range */
+ TFA9875_BF_IEVDDS= 0x4800, /*!< Enable interrupt POR */
+ TFA9875_BF_IEBSTOC= 0x4810, /*!< Enable interrupt DCDC OCP */
+ TFA9875_BF_IEOTDS= 0x4820, /*!< Enable interrupt OTP alarm */
+ TFA9875_BF_IEOCPR= 0x4830, /*!< Enable interrupt OCP alarm */
+ TFA9875_BF_IEUVDS= 0x4840, /*!< Enable interrupt UVP alarm */
+ TFA9875_BF_IETDMER= 0x4850, /*!< Enable interrupt TDM error */
+ TFA9875_BF_IENOCLK= 0x4860, /*!< Enable interrupt lost clk */
+ TFA9875_BF_IEDCTH= 0x4870, /*!< Enable interrupt dc too high */
+ TFA9875_BF_IEBODNOK= 0x4880, /*!< Enable interrupt brown out detect */
+ TFA9875_BF_IECOOR= 0x4890, /*!< Enable interrupt clock out of range */
+ TFA9875_BF_IPOVDDS= 0x4c00, /*!< Interrupt polarity POR */
+ TFA9875_BF_IPOBSTOC= 0x4c10, /*!< Interrupt polarity DCDC OCP */
+ TFA9875_BF_IPOOTDS= 0x4c20, /*!< Interrupt polarity OTP alarm */
+ TFA9875_BF_IPOOCPR= 0x4c30, /*!< Interrupt polarity OCP alarm */
+ TFA9875_BF_IPOUVDS= 0x4c40, /*!< Interrupt polarity UVP alarm */
+ TFA9875_BF_IPOTDMER= 0x4c50, /*!< Interrupt polarity TDM error */
+ TFA9875_BF_IPONOCLK= 0x4c60, /*!< Interrupt polarity lost clk */
+ TFA9875_BF_IPODCTH= 0x4c70, /*!< Interrupt polarity dc too high */
+ TFA9875_BF_IPOBODNOK= 0x4c80, /*!< Interrupt polarity brown out detect */
+ TFA9875_BF_IPOCOOR= 0x4c90, /*!< Interrupt polarity clock out of range */
+ TFA9875_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9875_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9875_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9875_BF_BSSCLRST= 0x50d0, /*!< Reset clipper - auto clear */
+ TFA9875_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9875_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9875_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9875_BF_DCPTC = 0x5111, /*!< Duration of DC level detection */
+ TFA9875_BF_DCPL = 0x5131, /*!< DC-level detection */
+ TFA9875_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9875_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9875_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9875_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9875_BF_SLOPEE= 0x54a0, /*!< Enables slope control */
+ TFA9875_BF_SLOPESET= 0x54b0, /*!< Slope speed setting */
+ TFA9875_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9875_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9875_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9875_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9875_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9875_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9875_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9875_BF_TDMSRCACLIP= 0x6871, /*!< Clip flag information for TDM Compressed2a/b/c modes */
+ TFA9875_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9875_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9875_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9875_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9875_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9875_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9875_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9875_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9875_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9875_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9875_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9875_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9875_BF_DCOVL = 0x7087, /*!< Threshold level to activate active overshoot control */
+ TFA9875_BF_DCNS = 0x7400, /*!< Disable control of noise shaper in DCDC control */
+ TFA9875_BF_DCNSRST= 0x7410, /*!< Disable control of reset of noise shaper when 8 bit value for dcdc control occurs */
+ TFA9875_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9875_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCTRIP= 0x7444, /*!< Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0 */
+ TFA9875_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCDIS = 0x7500, /*!< DCDC on/off */
+ TFA9875_BF_DCPWM = 0x7510, /*!< DCDC PWM only mode */
+ TFA9875_BF_DCTRIP2= 0x7534, /*!< Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0 */
+ TFA9875_BF_DCTRIPT= 0x7584, /*!< Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1 */
+ TFA9875_BF_BYPDCLPF= 0x75d0, /*!< Bypass control of DCDC control low pass filter for quantization noise suppression */
+ TFA9875_BF_ENBSTFLT= 0x75e0, /*!< Enable the boost filter */
+ TFA9875_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9875_BF_DCVOF = 0x7607, /*!< First boost voltage level */
+ TFA9875_BF_DCVOS = 0x7687, /*!< Second boost voltage level */
+ TFA9875_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9875_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9875_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9875_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9875_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9875_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9875_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9875_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9875_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9875_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9875_BF_PLLSELI= 0xcd05, /*!< PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELP= 0xcd64, /*!< PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELR= 0xcdb3, /*!< PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection direct control, USE WITH CAUTION */
+ TFA9875_BF_PLLFRM= 0xce00, /*!< PLL free running mode control in functional mode */
+ TFA9875_BF_PLLDI = 0xce10, /*!< PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDO = 0xce20, /*!< PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLPDIV= 0xce34, /*!< PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLNDIV= 0xce87, /*!< PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLMDIV= 0xcf0f, /*!< PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDCTRL= 0xd000, /*!< Enable PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9875_BF_PLLENBL= 0xd010, /*!< Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLLIMOFF= 0xd020, /*!< PLL up limiter control in PLL direct bandwidth control mode */
+ TFA9875_BF_PLLCLKSTB= 0xd030, /*!< PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSTRTM= 0xd042, /*!< PLL startup time selection control */
+ TFA9875_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9875_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9875_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9875_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9875_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9875_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9875_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9875_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9875_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9875BfEnumList_t;
+#define TFA9875_NAMETABLE static tfaBfName_t Tfa9875DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xa0, "BYPUVP"}, /* Bypass UVP , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xd0, "MANWTIME"}, /* Manager wait time selection control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "COORHYS"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "MANSCONF"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "MUTETO"}, /* Time out mute sequence , */\
+ { 0x170, "MANROBOD"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "BODFILT"}, /* BOD filter , */\
+ { 0x1b1, "BODTHLVL"}, /* BOD threshold level , */\
+ { 0x1d0, "MANEDCTH"}, /* Device response to too high DC level flag (DCTH = 1) , */\
+ { 0x1e0, "OPENMTP"}, /* Control for MTP protection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (Fs) , */\
+ { 0x240, "ENLBW"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x400, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM (MTP) , */\
+ { 0x1000, "VDDS"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "OTDS"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "UVDS"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "OVDS"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "OCDS"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "NOCLK"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "CLKOOR"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "DCOCPOK"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "DCIL"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "DCDCA"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "ADCCR"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "OCPOAP"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "OCPOAN"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "OCPOBP"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "OCPOBN"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "DCTH"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "CLKS"}, /* Clocks stable , */\
+ { 0x1110, "MTPB"}, /* MTP busy , */\
+ { 0x1120, "TDMERR"}, /* TDM error , */\
+ { 0x1130, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x1190, "SWS"}, /* Amplifier engage , */\
+ { 0x11a0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11b0, "AREFS"}, /* References enable , */\
+ { 0x11c0, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1203, "MANSTATE"}, /* Device manager status , */\
+ { 0x1243, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x1282, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x12b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x12d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "BODNOK"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "DCLD"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2011, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x2030, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x2040, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2050, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2061, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2081, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x20a1, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2100, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x2110, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2120, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "TDMSRC0E"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "TDMSRC1E"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "TDMSRC2E"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "TDMSRC3E"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "TDMSRC0S"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "TDMSRC1S"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "TDMSRC2S"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "TDMSRC3S"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "ISTVDDS"}, /* Interrupt status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "ISTOTDS"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "ISTTDMER"}, /* Interrupt status TDM error , */\
+ { 0x4060, "ISTNOCLK"}, /* Interrupt status lost clock , */\
+ { 0x4070, "ISTDCTH"}, /* Interrupt status dc too high , */\
+ { 0x4080, "ISTBODNOK"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "ISTCOOR"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear interrupt status POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "ICLTDMER"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "ICLNOCLK"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "ICLDCTH"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "ICLBODNOK"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "ICLCOOR"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable interrupt POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "IETDMER"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "IENOCLK"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "IEDCTH"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "IEBODNOK"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "IECOOR"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "IPOTDMER"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "IPONOCLK"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "IPODCTH"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "IPOBODNOK"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "IPOCOOR"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "BSSCLRST"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5111, "DCPTC"}, /* Duration of DC level detection , */\
+ { 0x5131, "DCPL"}, /* DC-level detection , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x54a0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x54b0, "SLOPESET"}, /* Slope speed setting , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7087, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7400, "DCNS"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "DCNSRST"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x7500, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7510, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7534, "DCTRIP2"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "DCTRIPT"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "BYPDCLPF"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7687, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLSELI"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "PLLSELP"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "PLLSELR"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "PLLDI"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "PLLDO"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "PLLPDIV"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "PLLNDIV"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "PLLMDIV"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "PLLDCTRL"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "PLLENBL"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "PLLCLKSTB"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9875_BITNAMETABLE static tfaBfName_t Tfa9875BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xa0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "src_set_configured"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "disable_mute_time_out"}, /* Time out mute sequence , */\
+ { 0x170, "man_enbl_brown"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "bod_delay_set"}, /* BOD filter , */\
+ { 0x1b1, "bod_lvl_set"}, /* BOD threshold level , */\
+ { 0x1d0, "man_enbl_dc_too_high"}, /* Device response to too high DC level flag (DCTH = 1) , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for MTP protection , */\
+ { 0x203, "audio_fs"}, /* Sample rate (Fs) , */\
+ { 0x240, "enbl_low_bandwidth"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x400, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM (MTP) , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to key registers , */\
+ { 0x1000, "flag_por"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "flag_otpok"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "flag_uvpok"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "flag_ocp_alarm"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "flag_lost_clk"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "flag_clk_out_of_range"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "flag_bst_bstcur"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "flag_bst_hiz"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "flag_adc10_ready"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "flag_ocpokap"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "flag_ocpokan"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "flag_ocpokbp"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "flag_ocpokbn"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "flag_dc_too_high"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1110, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1120, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x1190, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11a0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11b0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x11c0, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1203, "man_state"}, /* Device manager status , */\
+ { 0x1243, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x1282, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x12b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x12d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "flag_bod_vddd_nok"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "dc_level_detect"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2011, "tdm_vamp_sel"}, /* Amplifier input selection , */\
+ { 0x2030, "tdm_input_level"}, /* TDM output attenuation , */\
+ { 0x2040, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2050, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2061, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2081, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x20a1, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2100, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x2110, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2120, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "tdm_source0_enable"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "tdm_source1_enable"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "tdm_source2_enable"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "tdm_source3_enable"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "tdm_source0_slot"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "tdm_source1_slot"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "tdm_source2_slot"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "tdm_source3_slot"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "int_out_flag_por"}, /* Interrupt status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "int_out_flag_tdm_error"}, /* Interrupt status TDM error , */\
+ { 0x4060, "int_out_flag_lost_clk"}, /* Interrupt status lost clock , */\
+ { 0x4070, "int_out_flag_dc_too_high"}, /* Interrupt status dc too high , */\
+ { 0x4080, "int_out_flag_bod_vddd_nok"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "int_out_flag_clk_out_of_range"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear interrupt status POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "int_in_flag_tdm_error"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "int_in_flag_lost_clk"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "int_in_flag_dc_too_high"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "int_in_flag_bod_vddd_nok"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "int_in_flag_clk_out_of_range"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable interrupt POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "int_enable_flag_tdm_error"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "int_enable_flag_lost_clk"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "int_enable_flag_dc_too_high"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "int_enable_flag_bod_vddd_nok"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "int_enable_flag_clk_out_of_range"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_tdm_error"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "int_polarity_flag_lost_clk"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "int_polarity_flag_dc_too_high"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "int_polarity_flag_bod_vddd_nok"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "int_polarity_flag_clk_out_of_range"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5111, "dc_prot_time_constant"}, /* Duration of DC level detection , */\
+ { 0x5131, "dc_prot_level"}, /* DC-level detection , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5300, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5310, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5320, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5330, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5343, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x5381, "ref_amp_irefdist_set_ctrl"}, /* Scaling of reference current for amplifier OCP , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5452, "amp_pst_drive_ctrl"}, /* Amplifier powerstage drive control in direct control mode only, */\
+ { 0x5481, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x54a0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x54b0, "ctrl_slope"}, /* Slope speed setting , */\
+ { 0x54c0, "sel_icomp_dem_clk"}, /* Clock selection for icomp_dem , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5610, "ref_iref_test_enbl"}, /* Enable of test function of reference current , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x5705, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually in I2C direct control mode, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage in I2C direct control mode, */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage in I2C direct control mode, */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*4096*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage in I2C direct control mode, */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engage , */\
+ { 0x6b10, "disable_engage"}, /* Disable engage , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* Spare control bits for future use , */\
+ { 0x6d09, "spare_in"}, /* Spare control bit - read only , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7087, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* Scale factor for peak current measurement - ratio between reference current and power transistor current, */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller in I2C direct control mode, */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator in I2C direct control mode , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current in I2C direct control mode , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage in I2C direct control mode, */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC in I2C direct control mode, */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators in I2C direct control mode, */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators in I2C direct control mode, */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators in I2C direct control mode, */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC in I2C direct control mode , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7360, "disable_artf676996_fix"}, /* Disables the fix for artf676996 (OCP booster triggered when Vtrgt is just above Vbat), */\
+ { 0x7371, "ref_bst_irefdist_set_ctrl"}, /* Scaling of reference current for booster OCP , */\
+ { 0x7400, "dcdc_disable_ns"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "dcdc_disable_mod8bit"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7500, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7510, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "bypass_dcdc_lpf"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7687, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7707, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x87a0, "enbl_ana_pre"}, /* Control for enabling the pre-empasis filter for voltage and current sense decimator, */\
+ { 0x8800, "vs1_adc_enbl"}, /* Enable voltage sense VS1 ADC (direct control mode only), */\
+ { 0x8810, "vs1_inn_short_ctrl"}, /* Short voltage sense VS1 negative to common mode , */\
+ { 0x8820, "vs1_inp_short_ctrl"}, /* Short voltage sense VS1 positive to common mode , */\
+ { 0x8830, "vs1_ldo_enbl"}, /* Enable voltage sense VS1 LDO (direct control mode only), */\
+ { 0x8840, "vs1_vbatldo_enbl"}, /* Enable voltage sense VS1 VBAT LDO (direct control mode only), */\
+ { 0x8850, "vs1_gain_control"}, /* Voltage sense VS1 gain control , */\
+ { 0x8860, "vs1_bypass_gc"}, /* Bypasses the VS1 gain correction , */\
+ { 0x8870, "vs1_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8887, "vs1_gain"}, /* Voltage sense VS1 gain , */\
+ { 0x8900, "vs2_adc_enbl"}, /* Enable voltage sense VS2 ADC (direct control mode only), */\
+ { 0x8910, "vs2_inn_short_ctrl"}, /* Short voltage sense VS2 negative to common mode , */\
+ { 0x8920, "vs2_inp_short_ctrl"}, /* Short voltage sense VS2 positive to common mode , */\
+ { 0x8930, "vs2_ldo_enbl"}, /* Enable voltage sense VS2 LDO (direct control mode only), */\
+ { 0x8940, "vs2_vbatldo_enbl"}, /* Enable voltage sense VS2 VBAT LDO (direct control mode only), */\
+ { 0x8950, "vs2_gain_control"}, /* Voltage sense VS2 gain control , */\
+ { 0x8960, "vs2_bypass_gc"}, /* Bypasses the VS2 gain correction , */\
+ { 0x8970, "vs2_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8987, "vs2_gain"}, /* Voltage sense VS2 gain , */\
+ { 0x8a00, "vs_adc_delay_ctrl"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8a10, "vs_adc_nortz_ctrl"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8a20, "vs_ldo_bypass_ctrl"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown_ctrl"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset_ctrl"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "vs_anamux_overrule"}, /* Overrule the disconnection of VS pins , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc0f0, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "cs_test_enbl"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "vs1_test_enbl"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc590, "vs2_test_enbl"}, /* Enable for digimux mode of dual sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "pll_selp"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "pll_selr"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "pll_band_direct"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "pll_directi"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "pll_directo"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "pll_pdiv"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "pll_ndiv"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "pll_mdiv"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "use_direct_pll_ctrl"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "enbl_pll"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "pll_frm_clockstable"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range checker , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf107, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_vs1_gain"}, /* Voltage sense VS1 gain calibration , */\
+ { 0xf387, "calibr_vs2_gain"}, /* Voltage sense VS2 gain calibration , */\
+ { 0xf407, "calibr_vs1_trim"}, /* VS1 ADC trimming , */\
+ { 0xf487, "calibr_vs2_trim"}, /* VS2 ADC Trimming , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9875_irq {
+ tfa9875_irq_max = -1,
+ tfa9875_irq_all = -1 /* all irqs */};
+
+#define TFA9875_IRQ_NAMETABLE static tfaIrqName_t Tfa9875IrqNames[]= {\
+};
+#endif /* _TFA9875_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames_A1.h b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames_A1.h
new file mode 100644
index 00000000000..df919afd30b
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames_A1.h
@@ -0,0 +1,939 @@
+/*
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _TFA9875_TFAFIELDNAMES_A1_H
+#define _TFA9875_TFAFIELDNAMES_A1_H
+
+
+#define TFA9875N1A1_I2CVERSION 26
+#ifndef TFA9875_I2CVERSION
+typedef enum Tfa9875A1BfEnumList {
+ TFA9875_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9875_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9875_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9875_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9875_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9875_BF_BYPUVP= 0x00a0, /*!< Bypass UVP */
+ TFA9875_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9875_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9875_BF_MANWTIME= 0x00d0, /*!< Manager wait time selection control */
+ TFA9875_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9875_BF_COORHYS= 0x00f0, /*!< Select hysteresis for clock range detector */
+ TFA9875_BF_MANSCONF= 0x0120, /*!< Configuration setting if I2C settings are uploaded by the host */
+ TFA9875_BF_MUTETO= 0x0160, /*!< Time out mute sequence */
+ TFA9875_BF_MANROBOD= 0x0170, /*!< Controls the reaction of the device on BOD */
+ TFA9875_BF_BODHYS= 0x0180, /*!< Enable Hysteresis of BOD */
+ TFA9875_BF_BODFILT= 0x0191, /*!< BOD filter */
+ TFA9875_BF_BODTHLVL= 0x01b1, /*!< BOD threshold level */
+ TFA9875_BF_MANEDCTH= 0x01d0, /*!< Device response to too high DC level flag (when DCTH asserts to 1) */
+ TFA9875_BF_OPENMTP= 0x01e0, /*!< Control for MTP protection */
+ TFA9875_BF_AUDFS = 0x0203, /*!< Sample rate (Fs) */
+ TFA9875_BF_ENLBW = 0x0240, /*!< CS/VS decimator low bandwidth mode control */
+ TFA9875_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9875_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9875_BF_REFCKEXT= 0x0400, /*!< PLL external ref clock */
+ TFA9875_BF_MANAOOSC= 0x0460, /*!< Internal oscillator control during power down mode */
+ TFA9875_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9875_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9875_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9875_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9875_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9875_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM (MTP) */
+ TFA9875_BF_VDDS = 0x1000, /*!< POR (sticky flag, clear on write a '1') */
+ TFA9875_BF_OTDS = 0x1010, /*!< OTP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_UVDS = 0x1020, /*!< UVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OVDS = 0x1030, /*!< OVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCDS = 0x1040, /*!< OCP amplifier (sticky flag, clear on write a '1') */
+ TFA9875_BF_NOCLK = 0x1050, /*!< Lost clock (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKOOR= 0x1060, /*!< External clock status (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCOCPOK= 0x1070, /*!< DCDC OCP nmos (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCIL = 0x1080, /*!< DCDC current limiting (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCDCA = 0x1090, /*!< DCDC active (sticky flag, clear on write a '1') */
+ TFA9875_BF_ADCCR = 0x10a0, /*!< ADC ready flag (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAP= 0x10b0, /*!< OCPOK pmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAN= 0x10c0, /*!< OCPOK nmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBP= 0x10d0, /*!< OCPOK pmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBN= 0x10e0, /*!< OCPOK nmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCTH = 0x10f0, /*!< DC level on audio input stream too high (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKS = 0x1100, /*!< Clocks stable */
+ TFA9875_BF_MTPB = 0x1110, /*!< MTP busy */
+ TFA9875_BF_TDMERR= 0x1120, /*!< TDM error */
+ TFA9875_BF_DCDCPC= 0x1130, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9875_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9875_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9875_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9875_BF_PLLS = 0x1170, /*!< PLL lock */
+ TFA9875_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9875_BF_SWS = 0x1190, /*!< Amplifier engage */
+ TFA9875_BF_AMPS = 0x11a0, /*!< Amplifier enable */
+ TFA9875_BF_AREFS = 0x11b0, /*!< References enable */
+ TFA9875_BF_CLIPS = 0x11c0, /*!< Amplifier clipping */
+ TFA9875_BF_MANSTATE= 0x1203, /*!< Device manager status */
+ TFA9875_BF_AMPSTE= 0x1243, /*!< Amplifier control status */
+ TFA9875_BF_TDMSTAT= 0x1282, /*!< TDM status bits */
+ TFA9875_BF_DCMODE= 0x12b1, /*!< DCDC mode status bits */
+ TFA9875_BF_WAITSYNC= 0x12d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9875_BF_BODNOK= 0x1300, /*!< BOD Flag VDD NOT OK (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCLD = 0x140c, /*!< DC level detected by DC protection module (2s complement) */
+ TFA9875_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9875_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9875_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9875_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9875_BF_AMPINSEL= 0x2011, /*!< Amplifier input selection */
+ TFA9875_BF_INPLEV= 0x2030, /*!< TDM output attenuation */
+ TFA9875_BF_TDMCLINV= 0x2040, /*!< Reception data to BCK clock */
+ TFA9875_BF_TDMFSPOL= 0x2050, /*!< FS polarity */
+ TFA9875_BF_TDMSLOTS= 0x2061, /*!< N-slots in Frame */
+ TFA9875_BF_TDMSLLN= 0x2081, /*!< N-bits in slot */
+ TFA9875_BF_TDMSSIZE= 0x20a1, /*!< Sample size per slot */
+ TFA9875_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9875_BF_TDMDEL= 0x2100, /*!< Data delay to FS */
+ TFA9875_BF_TDMADJ= 0x2110, /*!< Data adjustment */
+ TFA9875_BF_TDMSPKE= 0x2120, /*!< Control audio TDM channel in 0 */
+ TFA9875_BF_TDMDCE= 0x2130, /*!< Control audio TDM channel in 1 */
+ TFA9875_BF_TDMSRC0E= 0x2140, /*!< Enable TDM source0 data channel */
+ TFA9875_BF_TDMSRC1E= 0x2150, /*!< Enable TDM source1 data channel */
+ TFA9875_BF_TDMSRC2E= 0x2160, /*!< Enable TDM source2 data channel */
+ TFA9875_BF_TDMSRC3E= 0x2170, /*!< Enable TDM source3 data channel */
+ TFA9875_BF_TDMSPKS= 0x2183, /*!< TDM slot for sink 0 */
+ TFA9875_BF_TDMDCS= 0x21c3, /*!< TDM slot for sink 1 */
+ TFA9875_BF_TDMSRC0S= 0x2203, /*!< Slot Position of TDM source0 channel data */
+ TFA9875_BF_TDMSRC1S= 0x2243, /*!< Slot Position of TDM source1 channel data */
+ TFA9875_BF_TDMSRC2S= 0x2283, /*!< Slot Position of TDM source2 channel data */
+ TFA9875_BF_TDMSRC3S= 0x22c3, /*!< Slot Position of TDM source3 channel data */
+ TFA9875_BF_ISTVDDS= 0x4000, /*!< Interrupt status POR */
+ TFA9875_BF_ISTBSTOC= 0x4010, /*!< Interrupt status DCDC OCP alarm */
+ TFA9875_BF_ISTOTDS= 0x4020, /*!< Interrupt status OTP alarm */
+ TFA9875_BF_ISTOCPR= 0x4030, /*!< Interrupt status OCP alarm */
+ TFA9875_BF_ISTUVDS= 0x4040, /*!< Interrupt status UVP alarm */
+ TFA9875_BF_ISTTDMER= 0x4050, /*!< Interrupt status TDM error */
+ TFA9875_BF_ISTNOCLK= 0x4060, /*!< Interrupt status lost clock */
+ TFA9875_BF_ISTDCTH= 0x4070, /*!< Interrupt status dc too high */
+ TFA9875_BF_ISTBODNOK= 0x4080, /*!< Interrupt status brown out detected */
+ TFA9875_BF_ISTCOOR= 0x4090, /*!< Interrupt status clock out of range */
+ TFA9875_BF_ICLVDDS= 0x4400, /*!< Clear interrupt status POR */
+ TFA9875_BF_ICLBSTOC= 0x4410, /*!< Clear interrupt status DCDC OCP */
+ TFA9875_BF_ICLOTDS= 0x4420, /*!< Clear interrupt status OTP alarm */
+ TFA9875_BF_ICLOCPR= 0x4430, /*!< Clear interrupt status OCP alarm */
+ TFA9875_BF_ICLUVDS= 0x4440, /*!< Clear interrupt status UVP alarm */
+ TFA9875_BF_ICLTDMER= 0x4450, /*!< Clear interrupt status TDM error */
+ TFA9875_BF_ICLNOCLK= 0x4460, /*!< Clear interrupt status lost clk */
+ TFA9875_BF_ICLDCTH= 0x4470, /*!< Clear interrupt status dc too high */
+ TFA9875_BF_ICLBODNOK= 0x4480, /*!< Clear interrupt status brown out detected */
+ TFA9875_BF_ICLCOOR= 0x4490, /*!< Clear interrupt status clock out of range */
+ TFA9875_BF_IEVDDS= 0x4800, /*!< Enable interrupt POR */
+ TFA9875_BF_IEBSTOC= 0x4810, /*!< Enable interrupt DCDC OCP */
+ TFA9875_BF_IEOTDS= 0x4820, /*!< Enable interrupt OTP alarm */
+ TFA9875_BF_IEOCPR= 0x4830, /*!< Enable interrupt OCP alarm */
+ TFA9875_BF_IEUVDS= 0x4840, /*!< Enable interrupt UVP alarm */
+ TFA9875_BF_IETDMER= 0x4850, /*!< Enable interrupt TDM error */
+ TFA9875_BF_IENOCLK= 0x4860, /*!< Enable interrupt lost clk */
+ TFA9875_BF_IEDCTH= 0x4870, /*!< Enable interrupt dc too high */
+ TFA9875_BF_IEBODNOK= 0x4880, /*!< Enable interrupt brown out detect */
+ TFA9875_BF_IECOOR= 0x4890, /*!< Enable interrupt clock out of range */
+ TFA9875_BF_IPOVDDS= 0x4c00, /*!< Interrupt polarity POR */
+ TFA9875_BF_IPOBSTOC= 0x4c10, /*!< Interrupt polarity DCDC OCP */
+ TFA9875_BF_IPOOTDS= 0x4c20, /*!< Interrupt polarity OTP alarm */
+ TFA9875_BF_IPOOCPR= 0x4c30, /*!< Interrupt polarity OCP alarm */
+ TFA9875_BF_IPOUVDS= 0x4c40, /*!< Interrupt polarity UVP alarm */
+ TFA9875_BF_IPOTDMER= 0x4c50, /*!< Interrupt polarity TDM error */
+ TFA9875_BF_IPONOCLK= 0x4c60, /*!< Interrupt polarity lost clk */
+ TFA9875_BF_IPODCTH= 0x4c70, /*!< Interrupt polarity dc too high */
+ TFA9875_BF_IPOBODNOK= 0x4c80, /*!< Interrupt polarity brown out detect */
+ TFA9875_BF_IPOCOOR= 0x4c90, /*!< Interrupt polarity clock out of range */
+ TFA9875_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9875_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9875_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9875_BF_BSSCLRST= 0x50d0, /*!< Reset clipper - auto clear */
+ TFA9875_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9875_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9875_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9875_BF_DCPTC = 0x5111, /*!< Duration of DC level detection */
+ TFA9875_BF_DCPL = 0x5131, /*!< DC-level detection */
+ TFA9875_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9875_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9875_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9875_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9875_BF_SLOPEE= 0x54a0, /*!< Enables slope control */
+ TFA9875_BF_SLOPESET= 0x54b0, /*!< Slope speed setting */
+ TFA9875_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9875_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9875_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9875_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9875_BF_PFMFREQLIM= 0x66d2, /*!< Lowest PFM frequency limit */
+ TFA9875_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9875_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9875_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9875_BF_TDMSRCACLIP= 0x6871, /*!< Clip flag information for TDM Compressed2a/b/c modes */
+ TFA9875_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9875_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9875_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9875_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9875_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9875_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9875_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9875_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9875_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9875_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9875_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9875_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9875_BF_DCOVL = 0x7087, /*!< Threshold level to activate active overshoot control */
+ TFA9875_BF_DCNS = 0x7400, /*!< Disable control of noise shaper in DCDC control */
+ TFA9875_BF_DCNSRST= 0x7410, /*!< Disable control of reset of noise shaper when 8 bit value for dcdc control occurs */
+ TFA9875_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9875_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCTRIP= 0x7444, /*!< Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0 */
+ TFA9875_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCDIS = 0x7500, /*!< DCDC on/off */
+ TFA9875_BF_DCPWM = 0x7510, /*!< DCDC PWM only mode */
+ TFA9875_BF_DCTRIP2= 0x7534, /*!< Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0 */
+ TFA9875_BF_DCTRIPT= 0x7584, /*!< Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1 */
+ TFA9875_BF_BYPDCLPF= 0x75d0, /*!< Bypass control of DCDC control low pass filter for quantization noise suppression */
+ TFA9875_BF_ENBSTFLT= 0x75e0, /*!< Enable the boost filter */
+ TFA9875_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9875_BF_DCVOF = 0x7607, /*!< First boost voltage level */
+ TFA9875_BF_DCVOS = 0x7687, /*!< Second boost voltage level */
+ TFA9875_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9875_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9875_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9875_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9875_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9875_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9875_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9875_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9875_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9875_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9875_BF_PLLSELI= 0xcd05, /*!< PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELP= 0xcd64, /*!< PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELR= 0xcdb3, /*!< PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection direct control, USE WITH CAUTION */
+ TFA9875_BF_PLLFRM= 0xce00, /*!< PLL free running mode control in functional mode */
+ TFA9875_BF_PLLDI = 0xce10, /*!< PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDO = 0xce20, /*!< PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLPDIV= 0xce34, /*!< PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLNDIV= 0xce87, /*!< PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLMDIV= 0xcf0f, /*!< PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDCTRL= 0xd000, /*!< Enable PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9875_BF_PLLENBL= 0xd010, /*!< Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLLIMOFF= 0xd020, /*!< PLL up limiter control in PLL direct bandwidth control mode */
+ TFA9875_BF_PLLCLKSTB= 0xd030, /*!< PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSTRTM= 0xd042, /*!< PLL startup time selection control */
+ TFA9875_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9875_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9875_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9875_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9875_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9875_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9875_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9875_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9875_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+}Tfa9875A1BfEnumList_t;
+#endif
+#define TFA9875A1_NAMETABLE static tfaBfName_t Tfa9875A1DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xa0, "BYPUVP"}, /* Bypass UVP , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xd0, "MANWTIME"}, /* Manager wait time selection control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "COORHYS"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "MANSCONF"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "MUTETO"}, /* Time out mute sequence , */\
+ { 0x170, "MANROBOD"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "BODFILT"}, /* BOD filter , */\
+ { 0x1b1, "BODTHLVL"}, /* BOD threshold level , */\
+ { 0x1d0, "MANEDCTH"}, /* Device response to too high DC level flag (when DCTH asserts to 1) , */\
+ { 0x1e0, "OPENMTP"}, /* Control for MTP protection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (Fs) , */\
+ { 0x240, "ENLBW"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x400, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM (MTP) , */\
+ { 0x1000, "VDDS"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "OTDS"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "UVDS"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "OVDS"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "OCDS"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "NOCLK"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "CLKOOR"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "DCOCPOK"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "DCIL"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "DCDCA"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "ADCCR"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "OCPOAP"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "OCPOAN"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "OCPOBP"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "OCPOBN"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "DCTH"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "CLKS"}, /* Clocks stable , */\
+ { 0x1110, "MTPB"}, /* MTP busy , */\
+ { 0x1120, "TDMERR"}, /* TDM error , */\
+ { 0x1130, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x1190, "SWS"}, /* Amplifier engage , */\
+ { 0x11a0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11b0, "AREFS"}, /* References enable , */\
+ { 0x11c0, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1203, "MANSTATE"}, /* Device manager status , */\
+ { 0x1243, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x1282, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x12b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x12d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "BODNOK"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "DCLD"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2011, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x2030, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x2040, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2050, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2061, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2081, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x20a1, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2100, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x2110, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2120, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "TDMSRC0E"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "TDMSRC1E"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "TDMSRC2E"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "TDMSRC3E"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "TDMSRC0S"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "TDMSRC1S"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "TDMSRC2S"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "TDMSRC3S"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "ISTVDDS"}, /* Interrupt status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "ISTOTDS"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "ISTTDMER"}, /* Interrupt status TDM error , */\
+ { 0x4060, "ISTNOCLK"}, /* Interrupt status lost clock , */\
+ { 0x4070, "ISTDCTH"}, /* Interrupt status dc too high , */\
+ { 0x4080, "ISTBODNOK"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "ISTCOOR"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear interrupt status POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "ICLTDMER"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "ICLNOCLK"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "ICLDCTH"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "ICLBODNOK"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "ICLCOOR"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable interrupt POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "IETDMER"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "IENOCLK"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "IEDCTH"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "IEBODNOK"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "IECOOR"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "IPOTDMER"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "IPONOCLK"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "IPODCTH"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "IPOBODNOK"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "IPOCOOR"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "BSSCLRST"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5111, "DCPTC"}, /* Duration of DC level detection , */\
+ { 0x5131, "DCPL"}, /* DC-level detection , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x54a0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x54b0, "SLOPESET"}, /* Slope speed setting , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x66d2, "PFMFREQLIM"}, /* Lowest PFM frequency limit , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7087, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7400, "DCNS"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "DCNSRST"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x7500, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7510, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7534, "DCTRIP2"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "DCTRIPT"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "BYPDCLPF"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7687, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLSELI"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "PLLSELP"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "PLLSELR"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "PLLDI"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "PLLDO"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "PLLPDIV"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "PLLNDIV"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "PLLMDIV"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "PLLDCTRL"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "PLLENBL"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "PLLCLKSTB"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9875A1_BITNAMETABLE static tfaBfName_t Tfa9875A1BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xa0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "src_set_configured"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "disable_mute_time_out"}, /* Time out mute sequence , */\
+ { 0x170, "man_enbl_brown"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "bod_delay_set"}, /* BOD filter , */\
+ { 0x1b1, "bod_lvl_set"}, /* BOD threshold level , */\
+ { 0x1d0, "man_enbl_dc_too_high"}, /* Device response to too high DC level flag (when DCTH asserts to 1) , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for MTP protection , */\
+ { 0x203, "audio_fs"}, /* Sample rate (Fs) , */\
+ { 0x240, "enbl_low_bandwidth"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x400, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM (MTP) , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to key registers , */\
+ { 0x1000, "flag_por"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "flag_otpok"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "flag_uvpok"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "flag_ocp_alarm"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "flag_lost_clk"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "flag_clk_out_of_range"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "flag_bst_bstcur"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "flag_bst_hiz"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "flag_adc10_ready"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "flag_ocpokap"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "flag_ocpokan"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "flag_ocpokbp"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "flag_ocpokbn"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "flag_dc_too_high"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1110, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1120, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x1190, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11a0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11b0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x11c0, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1203, "man_state"}, /* Device manager status , */\
+ { 0x1243, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x1282, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x12b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x12d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "flag_bod_vddd_nok"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "dc_level_detect"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2011, "tdm_vamp_sel"}, /* Amplifier input selection , */\
+ { 0x2030, "tdm_input_level"}, /* TDM output attenuation , */\
+ { 0x2040, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2050, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2061, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2081, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x20a1, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2100, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x2110, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2120, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "tdm_source0_enable"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "tdm_source1_enable"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "tdm_source2_enable"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "tdm_source3_enable"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "tdm_source0_slot"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "tdm_source1_slot"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "tdm_source2_slot"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "tdm_source3_slot"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "int_out_flag_por"}, /* Interrupt status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "int_out_flag_tdm_error"}, /* Interrupt status TDM error , */\
+ { 0x4060, "int_out_flag_lost_clk"}, /* Interrupt status lost clock , */\
+ { 0x4070, "int_out_flag_dc_too_high"}, /* Interrupt status dc too high , */\
+ { 0x4080, "int_out_flag_bod_vddd_nok"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "int_out_flag_clk_out_of_range"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear interrupt status POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "int_in_flag_tdm_error"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "int_in_flag_lost_clk"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "int_in_flag_dc_too_high"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "int_in_flag_bod_vddd_nok"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "int_in_flag_clk_out_of_range"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable interrupt POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "int_enable_flag_tdm_error"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "int_enable_flag_lost_clk"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "int_enable_flag_dc_too_high"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "int_enable_flag_bod_vddd_nok"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "int_enable_flag_clk_out_of_range"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_tdm_error"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "int_polarity_flag_lost_clk"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "int_polarity_flag_dc_too_high"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "int_polarity_flag_bod_vddd_nok"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "int_polarity_flag_clk_out_of_range"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5111, "dc_prot_time_constant"}, /* Duration of DC level detection , */\
+ { 0x5131, "dc_prot_level"}, /* DC-level detection , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5300, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5310, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5320, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5330, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5343, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x5381, "ref_amp_irefdist_set_ctrl"}, /* Scaling of reference current for amplifier OCP , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5481, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x54a0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x54b0, "ctrl_slope"}, /* Slope speed setting , */\
+ { 0x54c0, "sel_icomp_dem_clk"}, /* Clock selection for icomp_dem , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5610, "ref_iref_test_enbl"}, /* Enable of test function of reference current , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x5705, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually in I2C direct control mode, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage in I2C direct control mode, */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage in I2C direct control mode, */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*4096*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage in I2C direct control mode, */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engage , */\
+ { 0x6b10, "disable_engage"}, /* Disable engage , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* Spare control bits for future use , */\
+ { 0x6d09, "spare_in"}, /* Spare control bit - read only , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7087, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* Scale factor for peak current measurement - ratio between reference current and power transistor current, */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller in I2C direct control mode, */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator in I2C direct control mode , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current in I2C direct control mode , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage in I2C direct control mode, */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC in I2C direct control mode, */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators in I2C direct control mode, */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators in I2C direct control mode, */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators in I2C direct control mode, */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC in I2C direct control mode , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7360, "disable_artf676996_fix"}, /* Disables the fix for artf676996 (OCP booster triggered when Vtrgt is just above Vbat), */\
+ { 0x7371, "ref_bst_irefdist_set_ctrl"}, /* Scaling of reference current for booster OCP , */\
+ { 0x7400, "dcdc_disable_ns"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "dcdc_disable_mod8bit"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7500, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7510, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "bypass_dcdc_lpf"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7687, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7707, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x87a0, "enbl_ana_pre"}, /* Control for enabling the pre-empasis filter for voltage and current sense decimator, */\
+ { 0x8800, "vs1_adc_enbl"}, /* Enable voltage sense VS1 ADC (direct control mode only), */\
+ { 0x8810, "vs1_inn_short_ctrl"}, /* Short voltage sense VS1 negative to common mode , */\
+ { 0x8820, "vs1_inp_short_ctrl"}, /* Short voltage sense VS1 positive to common mode , */\
+ { 0x8830, "vs1_ldo_enbl"}, /* Enable voltage sense VS1 LDO (direct control mode only), */\
+ { 0x8840, "vs1_vbatldo_enbl"}, /* Enable voltage sense VS1 VBAT LDO (direct control mode only), */\
+ { 0x8850, "vs1_gain_control"}, /* Voltage sense VS1 gain control , */\
+ { 0x8860, "vs1_bypass_gc"}, /* Bypasses the VS1 gain correction , */\
+ { 0x8870, "vs1_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8887, "vs1_gain"}, /* Voltage sense VS1 gain , */\
+ { 0x8900, "vs2_adc_enbl"}, /* Enable voltage sense VS2 ADC (direct control mode only), */\
+ { 0x8910, "vs2_inn_short_ctrl"}, /* Short voltage sense VS2 negative to common mode , */\
+ { 0x8920, "vs2_inp_short_ctrl"}, /* Short voltage sense VS2 positive to common mode , */\
+ { 0x8930, "vs2_ldo_enbl"}, /* Enable voltage sense VS2 LDO (direct control mode only), */\
+ { 0x8940, "vs2_vbatldo_enbl"}, /* Enable voltage sense VS2 VBAT LDO (direct control mode only), */\
+ { 0x8950, "vs2_gain_control"}, /* Voltage sense VS2 gain control , */\
+ { 0x8960, "vs2_bypass_gc"}, /* Bypasses the VS2 gain correction , */\
+ { 0x8970, "vs2_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8987, "vs2_gain"}, /* Voltage sense VS2 gain , */\
+ { 0x8a00, "vs_adc_delay_ctrl"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8a10, "vs_adc_nortz_ctrl"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8a20, "vs_ldo_bypass_ctrl"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown_ctrl"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset_ctrl"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "vs_anamux_overrule"}, /* Overrule the disconnection of VS pins , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc0f0, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "cs_test_enbl"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "vs1_test_enbl"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc590, "vs2_test_enbl"}, /* Enable for digimux mode of dual sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "pll_selp"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "pll_selr"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "pll_band_direct"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "pll_directi"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "pll_directo"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "pll_pdiv"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "pll_ndiv"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "pll_mdiv"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "use_direct_pll_ctrl"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "enbl_pll"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "pll_frm_clockstable"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd502, "amp_pst_drive_ctrl"}, /* Amplifier powerstage drive control , */\
+ { 0xd534, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range checker , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf107, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_vs1_gain"}, /* Voltage sense VS1 gain calibration , */\
+ { 0xf387, "calibr_vs2_gain"}, /* Voltage sense VS2 gain calibration , */\
+ { 0xf407, "calibr_vs1_trim"}, /* VS1 ADC trimming , */\
+ { 0xf487, "calibr_vs2_trim"}, /* VS2 ADC Trimming , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+#if 0
+enum tfa9875_irq {
+ tfa9875_irq_max = -1,
+ tfa9875_irq_all = -1 /* all irqs */};
+#endif
+#define TFA9875_IRQ_NAMETABLE static tfaIrqName_t Tfa9875IrqNames[]= {\
+};
+#endif /* _TFA9875_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9878_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9878_tfafieldnames.h
new file mode 100644
index 00000000000..f015fe7ca6f
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9878_tfafieldnames.h
@@ -0,0 +1,980 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9878_tfaFieldnames.h
+ * This file was generated automatically on 06/28/19 at 10:22:32.
+ * Source file: TFA9878_PRB3_N1A1_DefaultI2CSettings.xlsx
+ */
+
+#ifndef _TFA9878_TFAFIELDNAMES_H
+#define _TFA9878_TFAFIELDNAMES_H
+
+
+#define TFA9878_I2CVERSION 12
+
+typedef enum Tfa9878BfEnumList {
+ TFA9878_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9878_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9878_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA9878_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9878_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9878_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9878_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9878_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9878_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9878_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9878_BF_DCINSEL= 0x0131, /*!< VAMP_OUT2 input selection */
+ TFA9878_BF_MUTETO= 0x0160, /*!< Time out SB mute sequence */
+ TFA9878_BF_MANROBOD= 0x0170, /*!< Reaction on BOD */
+ TFA9878_BF_BODE = 0x0180, /*!< Enable BOD (only in direct control mode) */
+ TFA9878_BF_BODHYS= 0x0190, /*!< Enable Hysteresis of BOD */
+ TFA9878_BF_BODFILT= 0x01a1, /*!< BOD filter */
+ TFA9878_BF_BODTHLVL= 0x01c1, /*!< BOD threshold */
+ TFA9878_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9878_BF_DISFCRBST= 0x01f0, /*!< disable boost control with FRCBST */
+ TFA9878_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9878_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9878_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9878_BF_AMPINPSEL= 0x02b1, /*!< amp input selection */
+ TFA9878_BF_PDMRATE= 0x02d0, /*!< Pdm rate */
+ TFA9878_BF_REV = 0x030f, /*!< Revision info */
+ TFA9878_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9878_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9878_BF_SWCLKSEL= 0x0432, /*!< Sound Wire clock frequnecy */
+ TFA9878_BF_MANAOOSC= 0x0460, /*!< Internal osc off at PWDN */
+ TFA9878_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9878_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9878_BF_AUTOFROSEL= 0x04a0, /*!< override automatic OSC selection mechanism */
+ TFA9878_BF_SWFRSYNC= 0x04b0, /*!< Selection SW signal reference for Stream Synchronization */
+ TFA9878_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9878_BF_FRCCLKSPKR= 0x0510, /*!< force active the speaker sub-system clock when in idle power */
+ TFA9878_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9878_BF_CLKCHKLO= 0x0707, /*!< Clock check Low Threshold */
+ TFA9878_BF_CLKCHKHI= 0x0787, /*!< Clock check Higher Threshold */
+ TFA9878_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9878_BF_VDDS = 0x1000, /*!< POR */
+ TFA9878_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register , clear on read) */
+ TFA9878_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register , clear on read) */
+ TFA9878_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register , clear on read) */
+ TFA9878_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register , clear on read) */
+ TFA9878_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9878_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9878_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9878_BF_NOCLK = 0x1080, /*!< Lost clock (sticky register , clear on read) */
+ TFA9878_BF_BODNOK= 0x1090, /*!< BOD Flag - VDD NOT OK */
+ TFA9878_BF_TDMERR= 0x10a0, /*!< TDM error */
+ TFA9878_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9878_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register , clear on read) */
+ TFA9878_BF_DCDCPC= 0x1120, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9878_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9878_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9878_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9878_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9878_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9878_BF_CLKOOR= 0x11c0, /*!< External clock status */
+ TFA9878_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9878_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9878_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9878_BF_OCPOAP= 0x1300, /*!< OCPOK pmos B */
+ TFA9878_BF_OCPOAN= 0x1310, /*!< OCPOK pmos A */
+ TFA9878_BF_OCPOBP= 0x1320, /*!< OCPOK nmos B */
+ TFA9878_BF_OCPOBN= 0x1330, /*!< OCPOK nmos A */
+ TFA9878_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9878_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9878_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9878_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9878_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9878_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9878_BF_TDMSTAT= 0x1402, /*!< TDM status bits */
+ TFA9878_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9878_BF_AMPSTE= 0x1473, /*!< Amplifier control status */
+ TFA9878_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9878_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9878_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9878_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9878_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9878_BF_TDMSLOTS= 0x2013, /*!< N-slots in Frame */
+ TFA9878_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9878_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9878_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9878_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9878_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9878_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9878_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9878_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9878_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9878_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9878_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9878_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9878_BF_TDMSPKE= 0x2300, /*!< Control audio tdm channel in 0 */
+ TFA9878_BF_TDMDCE= 0x2310, /*!< Control audio tdm channel in 1 */
+ TFA9878_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9878_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9878_BF_TDMSPKS= 0x2603, /*!< tdm slot for sink 0 */
+ TFA9878_BF_TDMDCS= 0x2643, /*!< tdm slot for sink 1 */
+ TFA9878_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9878_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9878_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9878_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9878_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9878_BF_ISTOCPR= 0x4030, /*!< Status ocp alarm */
+ TFA9878_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9878_BF_ISTMANALARM= 0x4050, /*!< Status nanager Alarm state */
+ TFA9878_BF_ISTTDMER= 0x4060, /*!< Status tdm error */
+ TFA9878_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9878_BF_ISTBODNOK= 0x4080, /*!< Status BOD event */
+ TFA9878_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9878_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9878_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9878_BF_ICLOCPR= 0x4430, /*!< Clear ocp alarm */
+ TFA9878_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9878_BF_ICLMANALARM= 0x4450, /*!< Clear manager Alarm state */
+ TFA9878_BF_ICLTDMER= 0x4460, /*!< Clear tdm error */
+ TFA9878_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9878_BF_ICLBODNOK= 0x4480, /*!< Clear BOD event */
+ TFA9878_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9878_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9878_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9878_BF_IEOCPR= 0x4830, /*!< Enable ocp alarm */
+ TFA9878_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9878_BF_IEMANALARM= 0x4850, /*!< Enable nanager Alarm state */
+ TFA9878_BF_IETDMER= 0x4860, /*!< Enable tdm error */
+ TFA9878_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9878_BF_IEBODNOK= 0x4880, /*!< Enable BOD trigger */
+ TFA9878_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9878_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9878_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9878_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9878_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9878_BF_IPOMANALARM= 0x4c50, /*!< Polarity nanager Alarm state */
+ TFA9878_BF_IPOTDMER= 0x4c60, /*!< Polarity tdm error */
+ TFA9878_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9878_BF_IPOBODNOK= 0x4c80, /*!< Polarity BOD trigger */
+ TFA9878_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time (with K = 1 at sample rate fs of 32kHz, 44,1 kHz or 48kHz ; with K = 2 at sample rate fs 16 kHz . With K =0.5 at sample rate of 96 kHz) */
+ TFA9878_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9878_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9878_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9878_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9878_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9878_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9878_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9878_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9878_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9878_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9878_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9878_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9878_BF_TDMDCG= 0x5f23, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9878_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9878_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9878_BF_LNMODE= 0x62e1, /*!< ctrl select mode */
+ TFA9878_BF_LPM1MODE= 0x64e1, /*!< low power mode control */
+ TFA9878_BF_TDMSRCMAP= 0x6802, /*!< tdm source mapping */
+ TFA9878_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9878_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9878_BF_TDMSRCACLIP= 0x6871, /*!< clip information (analog /digital) for source0 */
+ TFA9878_BF_TDMSRCBCLIP= 0x6891, /*!< clip information (analog /digital) for source1 */
+ TFA9878_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9878_BF_LP1 = 0x6e10, /*!< low power mode 1 detection */
+ TFA9878_BF_LA = 0x6e20, /*!< low amplitude detection */
+ TFA9878_BF_VDDPH = 0x6e30, /*!< vddp greater than vbat */
+ TFA9878_BF_DELCURCOMP= 0x6f02, /*!< delay to allign compensation signal with current sense signal */
+ TFA9878_BF_SIGCURCOMP= 0x6f40, /*!< polarity of compensation for current sense */
+ TFA9878_BF_ENCURCOMP= 0x6f50, /*!< enable current sense compensation */
+ TFA9878_BF_LVLCLPPWM= 0x6f72, /*!< set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9878_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9878_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9878_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9878_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9878_BF_DCOVL = 0x7085, /*!< Threshold level to activate active overshoot control */
+ TFA9878_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9878_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9878_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9878_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9878_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9878_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9878_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9878_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9878_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9878_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9878_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9878_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9878_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9878_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9878_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9878_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9878_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9878_BF_PLLINSI= 0xcd05, /*!< PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9878_BF_PLLINSP= 0xcd64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9878_BF_PLLINSR= 0xcdb3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9878_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection control, USE WITH CAUTION */
+ TFA9878_BF_PLLNDEC= 0xce09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLMDECM= 0xcea0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLBP = 0xceb0, /*!< PLL bypass control during functional mode */
+ TFA9878_BF_PLLDI = 0xcec0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLDO = 0xced0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLCLKSTB= 0xcee0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLFRM= 0xcef0, /*!< PLL free running mode control in functional mode */
+ TFA9878_BF_PLLMDECL= 0xcf0f, /*!< Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLPDEC= 0xd006, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLDCTRL= 0xd070, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9878_BF_PLLLIMOFF= 0xd090, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9878_BF_PLLSTRTM= 0xd0a2, /*!< PLL startup time selection control */
+ TFA9878_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9878_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9878_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9878_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9878_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9878_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9878_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9878_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9878_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9878BfEnumList_t;
+#define TFA9878_NAMETABLE static tfaBfName_t Tfa9878DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x131, "DCINSEL"}, /* VAMP_OUT2 input selection , */\
+ { 0x160, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x170, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x180, "BODE"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x190, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x1a1, "BODFILT"}, /* BOD filter , */\
+ { 0x1c1, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "DISFCRBST"}, /* disable boost control with FRCBST , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b1, "AMPINPSEL"}, /* amp input selection , */\
+ { 0x2d0, "PDMRATE"}, /* Pdm rate , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x432, "SWCLKSEL"}, /* Sound Wire clock frequnecy , */\
+ { 0x460, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "AUTOFROSEL"}, /* override automatic OSC selection mechanism , */\
+ { 0x4b0, "SWFRSYNC"}, /* Selection SW signal reference for Stream Synchronization , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* force active the speaker sub-system clock when in idle power, */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x707, "CLKCHKLO"}, /* Clock check Low Threshold , */\
+ { 0x787, "CLKCHKHI"}, /* Clock check Higher Threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1090, "BODNOK"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x10a0, "TDMERR"}, /* TDM error , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1120, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11c0, "CLKOOR"}, /* External clock status , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos B , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK pmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK nmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos A , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1402, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1473, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2013, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio tdm channel in 0 , */\
+ { 0x2310, "TDMDCE"}, /* Control audio tdm channel in 1 , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* tdm slot for sink 0 , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for sink 1 , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status nanager Alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTBODNOK"}, /* Status BOD event , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager Alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLBODNOK"}, /* Clear BOD event , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IEBODNOK"}, /* Enable BOD trigger , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOBODNOK"}, /* Polarity BOD trigger , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time (with K = 1 at sample rate fs of 32kHz, 44,1 kHz or 48kHz ; with K = 2 at sample rate fs 16 kHz . With K =0.5 at sample rate of 96 kHz), */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x5f23, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* vddp greater than vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7085, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLINSI"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcd64, "PLLINSP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "PLLINSR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "PLLMDECM"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "PLLBP"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "PLLDI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "PLLDO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "PLLCLKSTB"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "PLLMDECL"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "PLLDCTRL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9878_BITNAMETABLE static tfaBfName_t Tfa9878BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x131, "vamp_sel2"}, /* VAMP_OUT2 input selection , */\
+ { 0x160, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x170, "man_enbl_brown"}, /* Reaction on BOD , */\
+ { 0x180, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x190, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x1a1, "bod_delay_set"}, /* BOD filter , */\
+ { 0x1c1, "bod_lvl_set"}, /* BOD threshold , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "disable_frcbst"}, /* disable boost control with FRCBST , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b1, "amp_input_sel"}, /* amp input selection , */\
+ { 0x2d0, "pdm_rate"}, /* Pdm rate , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x432, "sw_clk_sel"}, /* Sound Wire clock frequnecy , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "override_auto_sel_osc"}, /* override automatic OSC selection mechanism , */\
+ { 0x4b0, "sw_sync_sel"}, /* Selection SW signal reference for Stream Synchronization , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* force active the speaker sub-system clock when in idle power, */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x707, "clkchk_th_lo"}, /* Clock check Low Threshold , */\
+ { 0x787, "clkchk_th_hi"}, /* Clock check Higher Threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1090, "flag_bod_vddd_nok"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x10a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11c0, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1310, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1320, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1330, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1402, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2013, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio tdm channel in 0 , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio tdm channel in 1 , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* tdm slot for sink 0 , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for sink 1 , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status nanager Alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_bod_vddd_nok"}, /* Status BOD event , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager Alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_bod_vddd_nok"}, /* Clear BOD event , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_bod_vddd_nok"}, /* Enable BOD trigger , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_bod_vddd_nok"}, /* Polarity BOD trigger , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time (with K = 1 at sample rate fs of 32kHz, 44,1 kHz or 48kHz ; with K = 2 at sample rate fs 16 kHz . With K =0.5 at sample rate of 96 kHz), */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5463, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5500, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5513, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5552, "dpsa_drive"}, /* Drive setting (bin. coded) , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5631, "ref_irefdist_set_ctrl"}, /* Scaling of reference current for OCP , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x5900, "pwm_clk_sel"}, /* Control for selection for PWM delay line source , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f23, "ctrl_attl"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7085, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7360, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8887, "vs_gain"}, /* voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* voltage sense Direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs ), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xc9d1, "sw_hs_mode"}, /* Speed/load setting for SW IO cell, clk or data mode range (see SWMF IO cell datasheet), */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcac0, "open_frcbst_ensw_switch"}, /* Save test2 configuration before enable anamux2 (open test2 switch and save test2 setting) , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on FRCBST/TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcd64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* tdm source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_tdm_feedback"}, /* gainatt feedback to tdm , */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost , */\
+ { 0xd890, "gainatt_sw_feedback"}, /* gainatt feedback to sw , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xd920, "enbl_irefcal"}, /* Enable IREF calibration , */\
+ { 0xd930, "start_iref_calibration"}, /* Start IREF Calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from Auto Calibration block, to be written into MTP - Read Only, */\
+ { 0xda80, "iref_calibration_done"}, /* IREF Calibration done - Read Only , */\
+ { 0xda94, "iref_auto_trim_val"}, /* Calibration value from Auto Calibration block, to be written into MTP - Read Only, */\
+ { 0xdae0, "iref_calibration_error"}, /* IREF Calibration done - Read Only , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf169, "spare_mtp1_15_6"}, /* SPARE , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a4, "optimal_pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0xf2f0, "enbl_optimal_pwm_delay"}, /* optimized pwm delay function enabled , */\
+ { 0xf307, "calibr_gain_vs1"}, /* Voltage sense gain when external voltage sensing input is selected, */\
+ { 0xf387, "calibr_gain_vs2"}, /* Voltage sense gain when internal voltage sensing input is selected, */\
+ { 0xf407, "vs_trim1"}, /* VS Trimming when external voltage sensing input is selected, */\
+ { 0xf487, "vs_trim2"}, /* VS Trimming when internal voltage sensing input is selected, */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf687, "spare_mpt6_15_06"}, /* SPARE , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf770, "spare_mtp7_07"}, /* SPARE , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf7f0, "spare_mtp7_15"}, /* SPARE , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "spare_mtp9_1"}, /* SPARE , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf980, "spare_mtp9_8"}, /* SPARE , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* pwm delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* ocpclock auto gating , */\
+ { 0xf9b0, "mtp_gate_cgu_clock_for_test"}, /* cgu test clock control , */\
+ { 0xf9c0, "mtp_tdm_pad_sel"}, /* tdm pad selection , */\
+ { 0xf9d2, "spare_mtp9_15_12"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9878_irq {
+ tfa9878_irq_stvdds = 0,
+ tfa9878_irq_stbstoc = 1,
+ tfa9878_irq_stotds = 2,
+ tfa9878_irq_stocpr = 3,
+ tfa9878_irq_stuvds = 4,
+ tfa9878_irq_stmanalarm = 5,
+ tfa9878_irq_sttdmer = 6,
+ tfa9878_irq_stnoclk = 7,
+ tfa9878_irq_stbodnok = 8,
+ tfa9878_irq_max = 9,
+ tfa9878_irq_all = -1 /* all irqs */};
+
+#define TFA9878_IRQ_NAMETABLE static tfaIrqName_t Tfa9878IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "STBODNOK"},\
+ { 9, "9"},\
+};
+#endif /* _TFA9878_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9887_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9887_tfafieldnames.h
new file mode 100644
index 00000000000..ace434854f3
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9887_tfafieldnames.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa9887_TfaFieldnames.h
+ * This file was generated automatically on 04/14/15 at 10:23:40.
+ * Source file: TFA9897N1B_I2C_list_URT_source_v34_87Only.xls
+ */
+#define TFA9887_I2CVERSION 34
+#define TFA9895_I2CVERSION 34
+#define TFA9887_NAMETABLE static tfaBfName_t Tfa9887DatasheetNames[]= {\
+ { 0x402, "I2SF"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "CHS12"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "CHS3"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "I2SSR"}, /* sample rate setting , */\
+ { 0x500, "BSSBY"}, /* , */\
+ { 0x511, "BSSCR"}, /* 00 = 0.56 dB/Sample , */\
+ { 0x532, "BSST"}, /* 000 = 2.92V , */\
+ { 0x5f0, "I2SDOC"}, /* selection data out , */\
+ { 0xa02, "DOLS"}, /* Output selection dataout left channel , */\
+ { 0xa32, "DORS"}, /* Output selection dataout right channel , */\
+ { 0xa62, "SPKL"}, /* Selection speaker induction , */\
+ { 0xa91, "SPKR"}, /* Selection speaker impedance , */\
+ { 0xab3, "DCFG"}, /* DCDC speaker current compensation gain , */\
+ { 0x4134, "PWMDEL"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "PWMSH"}, /* PWM Shape , */\
+ { 0x4190, "PWMRE"}, /* PWM Bitlength in noise shaper , */\
+ { 0x48e1, "TCC"}, /* sample & hold track time: , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9887_BITNAMETABLE static tfaBfName_t Tfa9887BitNames[]= {\
+ { 0x402, "i2s_seti"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "chan_sel1"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "lr_sw_i2si2"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "input_sel"}, /* Input selection for amplifier , */\
+ { 0x4b0, "enbl_datao"}, /* Enable data output , */\
+ { 0x4c3, "i2s_fs"}, /* sample rate setting , */\
+ { 0x500, "bypass_clipper"}, /* , */\
+ { 0x511, "vbat_prot_attacktime[1:0]"}, /* 00 = 0.56 dB/Sample , */\
+ { 0x532, "vbat_prot_thlevel[2:0]"}, /* 000 = 2.92V , */\
+ { 0x5d0, "reset_min_vbat"}, /* to reset the clipper via I2C in case the CF is bypassed, */\
+ { 0x5f0, "datao_sel"}, /* selection data out , */\
+ { 0xa02, "sel_i2so_l"}, /* Output selection dataout left channel , */\
+ { 0xa32, "sel_i2so_r"}, /* Output selection dataout right channel , */\
+ { 0xa62, "ctrl_spkr_coil"}, /* Selection speaker induction , */\
+ { 0xa91, "ctrl_spr_res"}, /* Selection speaker impedance , */\
+ { 0xab3, "ctrl_dcdc_spkr_i_comp_gain"}, /* DCDC speaker current compensation gain , */\
+ { 0xaf0, "ctrl_dcdc_spkr_i_comp_sign"}, /* DCDC speaker current compensation sign , */\
+ { 0x4100, "bypass_hp"}, /* bypass_hp, to bypass the hp filter byhind the CoolFlux, */\
+ { 0x4110, "hard_mute"}, /* hard mute setting in HW , */\
+ { 0x4120, "soft_mute"}, /* Soft mute setting in HW , */\
+ { 0x4134, "PWM_Delay[4:0]"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "PWM_Shape"}, /* PWM Shape , */\
+ { 0x4190, "PWM_BitLength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4800, "ctrl_negin"}, /* , */\
+ { 0x4810, "ctrl_cs_sein"}, /* , */\
+ { 0x4820, "ctrl_coincidencecs"}, /* HIGH => Prevent dcdc switching during clk_cs_clksh, */\
+ { 0x4876, "delay_se_neg[6:0]"}, /* delayshiftse2 , */\
+ { 0x48e1, "ctrl_cs_ttrack[1:0]"}, /* sample & hold track time: , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9890_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9890_tfafieldnames.h
new file mode 100644
index 00000000000..4bdeff6ac07
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9890_tfafieldnames.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa9890_TfaFieldnames.h
+ * This file was generated automatically on 04/07/15 at 14:46:37.
+ * Source file: TFA9897N1B_I2C_list_URT_source_v34_90Only.xls
+ */
+#define TFA9890_I2CVERSION 34
+#define TFA9890_NAMETABLE static tfaBfName_t Tfa9890DatasheetNames[]= {\
+ { 0x402, "I2SF"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "CHS12"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "CHS3"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x481, "I2SDOC"}, /* selection data out , */\
+ { 0x4a0, "DISP"}, /* idp protection , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "I2SSR"}, /* sample rate setting , */\
+ { 0x732, "DCMCC"}, /* Max boost coil current - step of 500 mA , */\
+ { 0x9c0, "CCFD"}, /* Selection CoolFlux Clock , */\
+ { 0x9d0, "ISEL"}, /* selection input 1 or 2 , */\
+ { 0xa02, "DOLS"}, /* Output selection dataout left channel , */\
+ { 0xa32, "DORS"}, /* Output selection dataout right channel , */\
+ { 0xa62, "SPKL"}, /* Selection speaker induction , */\
+ { 0xa91, "SPKR"}, /* Selection speaker impedance , */\
+ { 0xab3, "DCFG"}, /* DCDC speaker current compensation gain , */\
+ { 0xf00, "VDDD"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "OTDD"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "OVDD"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "UVDD"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "OCDD"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "CLKD"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "DCCD"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "SPKD"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "WDD"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xf90, "LCLK"}, /* mask flag_lost_clk for interupt generation , */\
+ { 0xfe0, "INT"}, /* enabling interrupt , */\
+ { 0xff0, "INTP"}, /* Setting polarity interupt , */\
+ { 0x8f0f, "VERSION"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9890_BITNAMETABLE static tfaBfName_t Tfa9890BitNames[]= {\
+ { 0x402, "i2s_seti"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "chan_sel1"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "lr_sw_i2si2"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "input_sel"}, /* Input selection for amplifier , */\
+ { 0x481, "datao_sel"}, /* selection data out , */\
+ { 0x4a0, "disable_idp"}, /* idp protection , */\
+ { 0x4b0, "enbl_datao"}, /* Enable data output , */\
+ { 0x4c3, "i2s_fs"}, /* sample rate setting , */\
+ { 0x732, "ctrl_bstcur"}, /* Max boost coil current - step of 500 mA , */\
+ { 0x9c0, "sel_cf_clk"}, /* Selection CoolFlux Clock , */\
+ { 0x9d0, "intf_sel"}, /* selection input 1 or 2 , */\
+ { 0xa02, "sel_i2so_l"}, /* Output selection dataout left channel , */\
+ { 0xa32, "sel_i2so_r"}, /* Output selection dataout right channel , */\
+ { 0xa62, "ctrl_spkr_coil"}, /* Selection speaker induction , */\
+ { 0xa91, "ctrl_spr_res"}, /* Selection speaker impedance , */\
+ { 0xab3, "ctrl_dcdc_spkr_i_comp_gain"}, /* DCDC speaker current compensation gain , */\
+ { 0xaf0, "ctrl_dcdc_spkr_i_comp_sign"}, /* DCDC speaker current compensation sign , */\
+ { 0xf00, "flag_por_mask"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "flag_otpok_mask"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "flag_ovpok_mask"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "flag_uvpok_mask"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "flag_ocp_alarm_mask"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "flag_clocks_stable_mask"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "flag_pwrokbst_mask"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "flag_cf_speakererror_mask"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "flag_watchdog_reset_mask"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xf90, "flag_lost_clk_mask"}, /* mask flag_lost_clk for interupt generation , */\
+ { 0xfe0, "enable_interrupt"}, /* enabling interrupt , */\
+ { 0xff0, "invert_int_polarity"}, /* Setting polarity interupt , */\
+ { 0x4700, "switch_fb"}, /* switch_fb , */\
+ { 0x4713, "se_hyst"}, /* se_hyst , */\
+ { 0x4754, "se_level"}, /* se_level , */\
+ { 0x47a5, "ktemp"}, /* temperature compensation trimming , */\
+ { 0x8f0f, "production_data6"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9891_genregs.h b/sound/soc/codecs/tfa98xx-downstream/tfa9891_genregs.h
new file mode 100644
index 00000000000..7e5de58d334
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9891_genregs.h
@@ -0,0 +1,1136 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa98xx_genregs.h
+ * This file was generated automatically on 07/01/15 at 10:25:08.
+ * Source file: TFA9891_I2C_list_V11.xls
+ */
+
+#ifndef TFA9891_GENREGS_H
+#define TFA9891_GENREGS_H
+
+
+#define TFA98XX_STATUSREG 0x00
+#define TFA98XX_BATTERYVOLTAGE 0x01
+#define TFA9891_TEMPERATURE 0x02
+#define TFA98XX_REVISIONNUMBER 0x03
+#define TFA98XX_I2SREG 0x04
+#define TFA98XX_BAT_PROT 0x05
+#define TFA98XX_AUDIO_CTR 0x06
+#define TFA98XX_DCDCBOOST 0x07
+#define TFA98XX_SPKR_CALIBRATION 0x08
+#define TFA98XX_SYS_CTRL 0x09
+#define TFA98XX_I2S_SEL_REG 0x0a
+#define TFA98XX_HIDDEN_MTP_KEY2 0x0b
+#define TFA98XX_INTERRUPT_REG 0x0f
+#define TFA98XX_PDM_CTRL 0x10
+#define TFA98XX_PDM_OUT_CTRL 0x11
+#define TFA98XX_PDM_DS4_R 0x12
+#define TFA98XX_PDM_DS4_L 0x13
+#define TFA98XX_CTRL_SAAM_PGA 0x22
+#define TFA98XX_MISC_CTRL 0x25
+#define TFA98XX_CURRENTSENSE1 0x46
+#define TFA98XX_CURRENTSENSE4 0x49
+#define TFA98XX_HIDDEN_MTP_CTRL_REG3 0x62
+#define TFA9891_CF_CONTROLS 0x70
+#define TFA9891_CF_MAD 0x71
+#define TFA9891_CF_MEM 0x72
+#define TFA9891_CF_STATUS 0x73
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP 0x80
+
+/*
+ * (0x00)-StatusReg
+ */
+
+/*
+ * POR
+ */
+#define TFA98XX_STATUSREG_VDDS (0x1<<0)
+#define TFA98XX_STATUSREG_VDDS_POS 0
+#define TFA98XX_STATUSREG_VDDS_LEN 1
+#define TFA98XX_STATUSREG_VDDS_MAX 1
+#define TFA98XX_STATUSREG_VDDS_MSK 0x1
+
+/*
+ * PLL_LOCK
+ */
+#define TFA98XX_STATUSREG_PLLS (0x1<<1)
+#define TFA98XX_STATUSREG_PLLS_POS 1
+#define TFA98XX_STATUSREG_PLLS_LEN 1
+#define TFA98XX_STATUSREG_PLLS_MAX 1
+#define TFA98XX_STATUSREG_PLLS_MSK 0x2
+
+/*
+ * flag_otpok
+ */
+#define TFA98XX_STATUSREG_OTDS (0x1<<2)
+#define TFA98XX_STATUSREG_OTDS_POS 2
+#define TFA98XX_STATUSREG_OTDS_LEN 1
+#define TFA98XX_STATUSREG_OTDS_MAX 1
+#define TFA98XX_STATUSREG_OTDS_MSK 0x4
+
+/*
+ * flag_ovpok
+ */
+#define TFA98XX_STATUSREG_OVDS (0x1<<3)
+#define TFA98XX_STATUSREG_OVDS_POS 3
+#define TFA98XX_STATUSREG_OVDS_LEN 1
+#define TFA98XX_STATUSREG_OVDS_MAX 1
+#define TFA98XX_STATUSREG_OVDS_MSK 0x8
+
+/*
+ * flag_uvpok
+ */
+#define TFA98XX_STATUSREG_UVDS (0x1<<4)
+#define TFA98XX_STATUSREG_UVDS_POS 4
+#define TFA98XX_STATUSREG_UVDS_LEN 1
+#define TFA98XX_STATUSREG_UVDS_MAX 1
+#define TFA98XX_STATUSREG_UVDS_MSK 0x10
+
+/*
+ * flag_OCP_alarm
+ */
+#define TFA98XX_STATUSREG_OCDS (0x1<<5)
+#define TFA98XX_STATUSREG_OCDS_POS 5
+#define TFA98XX_STATUSREG_OCDS_LEN 1
+#define TFA98XX_STATUSREG_OCDS_MAX 1
+#define TFA98XX_STATUSREG_OCDS_MSK 0x20
+
+/*
+ * flag_clocks_stable
+ */
+#define TFA98XX_STATUSREG_CLKS (0x1<<6)
+#define TFA98XX_STATUSREG_CLKS_POS 6
+#define TFA98XX_STATUSREG_CLKS_LEN 1
+#define TFA98XX_STATUSREG_CLKS_MAX 1
+#define TFA98XX_STATUSREG_CLKS_MSK 0x40
+
+/*
+ * CLIP
+ */
+#define TFA98XX_STATUSREG_CLIPS (0x1<<7)
+#define TFA98XX_STATUSREG_CLIPS_POS 7
+#define TFA98XX_STATUSREG_CLIPS_LEN 1
+#define TFA98XX_STATUSREG_CLIPS_MAX 1
+#define TFA98XX_STATUSREG_CLIPS_MSK 0x80
+
+/*
+ * mtp_busy
+ */
+#define TFA98XX_STATUSREG_MTPB (0x1<<8)
+#define TFA98XX_STATUSREG_MTPB_POS 8
+#define TFA98XX_STATUSREG_MTPB_LEN 1
+#define TFA98XX_STATUSREG_MTPB_MAX 1
+#define TFA98XX_STATUSREG_MTPB_MSK 0x100
+
+/*
+ * flag_pwrokbst
+ */
+#define TFA98XX_STATUSREG_DCCS (0x1<<9)
+#define TFA98XX_STATUSREG_DCCS_POS 9
+#define TFA98XX_STATUSREG_DCCS_LEN 1
+#define TFA98XX_STATUSREG_DCCS_MAX 1
+#define TFA98XX_STATUSREG_DCCS_MSK 0x200
+
+/*
+ * flag_cf_speakererror
+ */
+#define TFA98XX_STATUSREG_SPKS (0x1<<10)
+#define TFA98XX_STATUSREG_SPKS_POS 10
+#define TFA98XX_STATUSREG_SPKS_LEN 1
+#define TFA98XX_STATUSREG_SPKS_MAX 1
+#define TFA98XX_STATUSREG_SPKS_MSK 0x400
+
+/*
+ * flag_cold_started
+ */
+#define TFA98XX_STATUSREG_ACS (0x1<<11)
+#define TFA98XX_STATUSREG_ACS_POS 11
+#define TFA98XX_STATUSREG_ACS_LEN 1
+#define TFA98XX_STATUSREG_ACS_MAX 1
+#define TFA98XX_STATUSREG_ACS_MSK 0x800
+
+/*
+ * flag_engage
+ */
+#define TFA98XX_STATUSREG_SWS (0x1<<12)
+#define TFA98XX_STATUSREG_SWS_POS 12
+#define TFA98XX_STATUSREG_SWS_LEN 1
+#define TFA98XX_STATUSREG_SWS_MAX 1
+#define TFA98XX_STATUSREG_SWS_MSK 0x1000
+
+/*
+ * flag_watchdog_reset
+ */
+#define TFA98XX_STATUSREG_WDS (0x1<<13)
+#define TFA98XX_STATUSREG_WDS_POS 13
+#define TFA98XX_STATUSREG_WDS_LEN 1
+#define TFA98XX_STATUSREG_WDS_MAX 1
+#define TFA98XX_STATUSREG_WDS_MSK 0x2000
+
+/*
+ * flag_enbl_amp
+ */
+#define TFA98XX_STATUSREG_AMPS (0x1<<14)
+#define TFA98XX_STATUSREG_AMPS_POS 14
+#define TFA98XX_STATUSREG_AMPS_LEN 1
+#define TFA98XX_STATUSREG_AMPS_MAX 1
+#define TFA98XX_STATUSREG_AMPS_MSK 0x4000
+
+/*
+ * flag_enbl_ref
+ */
+#define TFA98XX_STATUSREG_AREFS (0x1<<15)
+#define TFA98XX_STATUSREG_AREFS_POS 15
+#define TFA98XX_STATUSREG_AREFS_LEN 1
+#define TFA98XX_STATUSREG_AREFS_MAX 1
+#define TFA98XX_STATUSREG_AREFS_MSK 0x8000
+
+/*
+ * (0x01)-BatteryVoltage
+ */
+
+/*
+ * bat_adc
+ */
+#define TFA98XX_BATTERYVOLTAGE_BATS (0x3ff<<0)
+#define TFA98XX_BATTERYVOLTAGE_BATS_POS 0
+#define TFA98XX_BATTERYVOLTAGE_BATS_LEN 10
+#define TFA98XX_BATTERYVOLTAGE_BATS_MAX 1023
+#define TFA98XX_BATTERYVOLTAGE_BATS_MSK 0x3ff
+
+
+/*
+ * (0x02)-Temperature
+ */
+
+/*
+ * temp_adc
+ */
+#define TFA9891_TEMPERATURE_TEMPS (0x1ff<<0)
+#define TFA9891_TEMPERATURE_TEMPS_POS 0
+#define TFA9891_TEMPERATURE_TEMPS_LEN 9
+#define TFA9891_TEMPERATURE_TEMPS_MAX 511
+#define TFA9891_TEMPERATURE_TEMPS_MSK 0x1ff
+
+
+/*
+ * (0x03)-RevisionNumber
+ */
+
+/*
+ * rev_reg
+ */
+#define TFA98XX_REVISIONNUMBER_REV (0xff<<0)
+#define TFA98XX_REVISIONNUMBER_REV_POS 0
+#define TFA98XX_REVISIONNUMBER_REV_LEN 8
+#define TFA98XX_REVISIONNUMBER_REV_MAX 255
+#define TFA98XX_REVISIONNUMBER_REV_MSK 0xff
+
+
+/*
+ * (0x04)-I2SReg
+ */
+
+/*
+ * i2s_seti
+ */
+#define TFA98XX_I2SREG_I2SF (0x7<<0)
+#define TFA98XX_I2SREG_I2SF_POS 0
+#define TFA98XX_I2SREG_I2SF_LEN 3
+#define TFA98XX_I2SREG_I2SF_MAX 7
+#define TFA98XX_I2SREG_I2SF_MSK 0x7
+
+/*
+ * chan_sel1
+ */
+#define TFA98XX_I2SREG_CHS12 (0x3<<3)
+#define TFA98XX_I2SREG_CHS12_POS 3
+#define TFA98XX_I2SREG_CHS12_LEN 2
+#define TFA98XX_I2SREG_CHS12_MAX 3
+#define TFA98XX_I2SREG_CHS12_MSK 0x18
+
+/*
+ * lr_sw_i2si2
+ */
+#define TFA98XX_I2SREG_CHS3 (0x1<<5)
+#define TFA98XX_I2SREG_CHS3_POS 5
+#define TFA98XX_I2SREG_CHS3_LEN 1
+#define TFA98XX_I2SREG_CHS3_MAX 1
+#define TFA98XX_I2SREG_CHS3_MSK 0x20
+
+/*
+ * input_sel
+ */
+#define TFA98XX_I2SREG_CHSA (0x3<<6)
+#define TFA98XX_I2SREG_CHSA_POS 6
+#define TFA98XX_I2SREG_CHSA_LEN 2
+#define TFA98XX_I2SREG_CHSA_MAX 3
+#define TFA98XX_I2SREG_CHSA_MSK 0xc0
+
+/*
+ * datao_sel
+ */
+#define TFA98XX_I2SREG_I2SDOC (0x3<<8)
+#define TFA98XX_I2SREG_I2SDOC_POS 8
+#define TFA98XX_I2SREG_I2SDOC_LEN 2
+#define TFA98XX_I2SREG_I2SDOC_MAX 3
+#define TFA98XX_I2SREG_I2SDOC_MSK 0x300
+
+/*
+ * disable_idp
+ */
+#define TFA98XX_I2SREG_DISP (0x1<<10)
+#define TFA98XX_I2SREG_DISP_POS 10
+#define TFA98XX_I2SREG_DISP_LEN 1
+#define TFA98XX_I2SREG_DISP_MAX 1
+#define TFA98XX_I2SREG_DISP_MSK 0x400
+
+/*
+ * enbl_datao
+ */
+#define TFA98XX_I2SREG_I2SDOE (0x1<<11)
+#define TFA98XX_I2SREG_I2SDOE_POS 11
+#define TFA98XX_I2SREG_I2SDOE_LEN 1
+#define TFA98XX_I2SREG_I2SDOE_MAX 1
+#define TFA98XX_I2SREG_I2SDOE_MSK 0x800
+
+/*
+ * i2s_fs
+ */
+#define TFA98XX_I2SREG_I2SSR (0xf<<12)
+#define TFA98XX_I2SREG_I2SSR_POS 12
+#define TFA98XX_I2SREG_I2SSR_LEN 4
+#define TFA98XX_I2SREG_I2SSR_MAX 15
+#define TFA98XX_I2SREG_I2SSR_MSK 0xf000
+
+
+/*
+ * (0x05)-bat_prot
+ */
+
+/*
+ * vbat_prot_attacktime
+ */
+#define TFA98XX_BAT_PROT_BSSCR (0x3<<0)
+#define TFA98XX_BAT_PROT_BSSCR_POS 0
+#define TFA98XX_BAT_PROT_BSSCR_LEN 2
+#define TFA98XX_BAT_PROT_BSSCR_MAX 3
+#define TFA98XX_BAT_PROT_BSSCR_MSK 0x3
+
+/*
+ * vbat_prot_thlevel
+ */
+#define TFA98XX_BAT_PROT_BSST (0xf<<2)
+#define TFA98XX_BAT_PROT_BSST_POS 2
+#define TFA98XX_BAT_PROT_BSST_LEN 4
+#define TFA98XX_BAT_PROT_BSST_MAX 15
+#define TFA98XX_BAT_PROT_BSST_MSK 0x3c
+
+/*
+ * vbat_prot_max_reduct
+ */
+#define TFA98XX_BAT_PROT_BSSRL (0x3<<6)
+#define TFA98XX_BAT_PROT_BSSRL_POS 6
+#define TFA98XX_BAT_PROT_BSSRL_LEN 2
+#define TFA98XX_BAT_PROT_BSSRL_MAX 3
+#define TFA98XX_BAT_PROT_BSSRL_MSK 0xc0
+
+/*
+ * vbat_prot_release_t
+ */
+#define TFA98XX_BAT_PROT_BSSRR (0x7<<8)
+#define TFA98XX_BAT_PROT_BSSRR_POS 8
+#define TFA98XX_BAT_PROT_BSSRR_LEN 3
+#define TFA98XX_BAT_PROT_BSSRR_MAX 7
+#define TFA98XX_BAT_PROT_BSSRR_MSK 0x700
+
+/*
+ * vbat_prot_hysterese
+ */
+#define TFA98XX_BAT_PROT_BSSHY (0x3<<11)
+#define TFA98XX_BAT_PROT_BSSHY_POS 11
+#define TFA98XX_BAT_PROT_BSSHY_LEN 2
+#define TFA98XX_BAT_PROT_BSSHY_MAX 3
+#define TFA98XX_BAT_PROT_BSSHY_MSK 0x1800
+
+/*
+ * sel_vbat
+ */
+#define TFA98XX_BAT_PROT_BSSR (0x1<<14)
+#define TFA98XX_BAT_PROT_BSSR_POS 14
+#define TFA98XX_BAT_PROT_BSSR_LEN 1
+#define TFA98XX_BAT_PROT_BSSR_MAX 1
+#define TFA98XX_BAT_PROT_BSSR_MSK 0x4000
+
+/*
+ * bypass_clipper
+ */
+#define TFA98XX_BAT_PROT_BSSBY (0x1<<15)
+#define TFA98XX_BAT_PROT_BSSBY_POS 15
+#define TFA98XX_BAT_PROT_BSSBY_LEN 1
+#define TFA98XX_BAT_PROT_BSSBY_MAX 1
+#define TFA98XX_BAT_PROT_BSSBY_MSK 0x8000
+
+
+/*
+ * (0x06)-audio_ctr
+ */
+
+/*
+ * dpsa
+ */
+#define TFA98XX_AUDIO_CTR_DPSA (0x1<<0)
+#define TFA98XX_AUDIO_CTR_DPSA_POS 0
+#define TFA98XX_AUDIO_CTR_DPSA_LEN 1
+#define TFA98XX_AUDIO_CTR_DPSA_MAX 1
+#define TFA98XX_AUDIO_CTR_DPSA_MSK 0x1
+
+/*
+ * ctrl_slope
+ */
+#define TFA98XX_AUDIO_CTR_AMPSL (0xf<<1)
+#define TFA98XX_AUDIO_CTR_AMPSL_POS 1
+#define TFA98XX_AUDIO_CTR_AMPSL_LEN 4
+#define TFA98XX_AUDIO_CTR_AMPSL_MAX 15
+#define TFA98XX_AUDIO_CTR_AMPSL_MSK 0x1e
+
+/*
+ * cf_mute
+ */
+#define TFA98XX_AUDIO_CTR_CFSM (0x1<<5)
+#define TFA98XX_AUDIO_CTR_CFSM_POS 5
+#define TFA98XX_AUDIO_CTR_CFSM_LEN 1
+#define TFA98XX_AUDIO_CTR_CFSM_MAX 1
+#define TFA98XX_AUDIO_CTR_CFSM_MSK 0x20
+
+/*
+ * ctrl_batsensesteepness
+ */
+#define TFA98XX_AUDIO_CTR_BSSS (0x1<<7)
+#define TFA98XX_AUDIO_CTR_BSSS_POS 7
+#define TFA98XX_AUDIO_CTR_BSSS_LEN 1
+#define TFA98XX_AUDIO_CTR_BSSS_MAX 1
+#define TFA98XX_AUDIO_CTR_BSSS_MSK 0x80
+
+/*
+ * vol
+ */
+#define TFA98XX_AUDIO_CTR_VOL (0xff<<8)
+#define TFA98XX_AUDIO_CTR_VOL_POS 8
+#define TFA98XX_AUDIO_CTR_VOL_LEN 8
+#define TFA98XX_AUDIO_CTR_VOL_MAX 255
+#define TFA98XX_AUDIO_CTR_VOL_MSK 0xff00
+
+
+/*
+ * (0x07)-DCDCboost
+ */
+
+/*
+ * ctrl_bstvolt
+ */
+#define TFA98XX_DCDCBOOST_DCVO (0x7<<0)
+#define TFA98XX_DCDCBOOST_DCVO_POS 0
+#define TFA98XX_DCDCBOOST_DCVO_LEN 3
+#define TFA98XX_DCDCBOOST_DCVO_MAX 7
+#define TFA98XX_DCDCBOOST_DCVO_MSK 0x7
+
+/*
+ * ctrl_bstcur
+ */
+#define TFA98XX_DCDCBOOST_DCMCC (0x7<<3)
+#define TFA98XX_DCDCBOOST_DCMCC_POS 3
+#define TFA98XX_DCDCBOOST_DCMCC_LEN 3
+#define TFA98XX_DCDCBOOST_DCMCC_MAX 7
+#define TFA98XX_DCDCBOOST_DCMCC_MSK 0x38
+
+/*
+ * boost_intel
+ */
+#define TFA98XX_DCDCBOOST_DCIE (0x1<<10)
+#define TFA98XX_DCDCBOOST_DCIE_POS 10
+#define TFA98XX_DCDCBOOST_DCIE_LEN 1
+#define TFA98XX_DCDCBOOST_DCIE_MAX 1
+#define TFA98XX_DCDCBOOST_DCIE_MSK 0x400
+
+/*
+ * boost_speed
+ */
+#define TFA98XX_DCDCBOOST_DCSR (0x1<<11)
+#define TFA98XX_DCDCBOOST_DCSR_POS 11
+#define TFA98XX_DCDCBOOST_DCSR_LEN 1
+#define TFA98XX_DCDCBOOST_DCSR_MAX 1
+#define TFA98XX_DCDCBOOST_DCSR_MSK 0x800
+
+
+/*
+ * (0x08)-spkr_calibration
+ */
+
+/*
+ * ext_temp_sel
+ */
+#define TFA98XX_SPKR_CALIBRATION_TROS (0x1<<0)
+#define TFA98XX_SPKR_CALIBRATION_TROS_POS 0
+#define TFA98XX_SPKR_CALIBRATION_TROS_LEN 1
+#define TFA98XX_SPKR_CALIBRATION_TROS_MAX 1
+#define TFA98XX_SPKR_CALIBRATION_TROS_MSK 0x1
+
+/*
+ * ext_temp
+ */
+#define TFA98XX_SPKR_CALIBRATION_EXTTS (0x1ff<<1)
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_POS 1
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_LEN 9
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_MAX 511
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_MSK 0x3fe
+
+
+/*
+ * (0x09)-sys_ctrl
+ */
+
+/*
+ * PowerDown
+ */
+#define TFA98XX_SYS_CTRL_PWDN (0x1<<0)
+#define TFA98XX_SYS_CTRL_PWDN_POS 0
+#define TFA98XX_SYS_CTRL_PWDN_LEN 1
+#define TFA98XX_SYS_CTRL_PWDN_MAX 1
+#define TFA98XX_SYS_CTRL_PWDN_MSK 0x1
+
+/*
+ * reset
+ */
+#define TFA98XX_SYS_CTRL_I2CR (0x1<<1)
+#define TFA98XX_SYS_CTRL_I2CR_POS 1
+#define TFA98XX_SYS_CTRL_I2CR_LEN 1
+#define TFA98XX_SYS_CTRL_I2CR_MAX 1
+#define TFA98XX_SYS_CTRL_I2CR_MSK 0x2
+
+/*
+ * enbl_coolflux
+ */
+#define TFA98XX_SYS_CTRL_CFE (0x1<<2)
+#define TFA98XX_SYS_CTRL_CFE_POS 2
+#define TFA98XX_SYS_CTRL_CFE_LEN 1
+#define TFA98XX_SYS_CTRL_CFE_MAX 1
+#define TFA98XX_SYS_CTRL_CFE_MSK 0x4
+
+/*
+ * enbl_amplifier
+ */
+#define TFA98XX_SYS_CTRL_AMPE (0x1<<3)
+#define TFA98XX_SYS_CTRL_AMPE_POS 3
+#define TFA98XX_SYS_CTRL_AMPE_LEN 1
+#define TFA98XX_SYS_CTRL_AMPE_MAX 1
+#define TFA98XX_SYS_CTRL_AMPE_MSK 0x8
+
+/*
+ * enbl_boost
+ */
+#define TFA98XX_SYS_CTRL_DCA (0x1<<4)
+#define TFA98XX_SYS_CTRL_DCA_POS 4
+#define TFA98XX_SYS_CTRL_DCA_LEN 1
+#define TFA98XX_SYS_CTRL_DCA_MAX 1
+#define TFA98XX_SYS_CTRL_DCA_MSK 0x10
+
+/*
+ * cf_configured
+ */
+#define TFA98XX_SYS_CTRL_SBSL (0x1<<5)
+#define TFA98XX_SYS_CTRL_SBSL_POS 5
+#define TFA98XX_SYS_CTRL_SBSL_LEN 1
+#define TFA98XX_SYS_CTRL_SBSL_MAX 1
+#define TFA98XX_SYS_CTRL_SBSL_MSK 0x20
+
+/*
+ * sel_enbl_amplifier
+ */
+#define TFA98XX_SYS_CTRL_AMPC (0x1<<6)
+#define TFA98XX_SYS_CTRL_AMPC_POS 6
+#define TFA98XX_SYS_CTRL_AMPC_LEN 1
+#define TFA98XX_SYS_CTRL_AMPC_MAX 1
+#define TFA98XX_SYS_CTRL_AMPC_MSK 0x40
+
+/*
+ * dcdcoff_mode
+ */
+#define TFA98XX_SYS_CTRL_DCDIS (0x1<<7)
+#define TFA98XX_SYS_CTRL_DCDIS_POS 7
+#define TFA98XX_SYS_CTRL_DCDIS_LEN 1
+#define TFA98XX_SYS_CTRL_DCDIS_MAX 1
+#define TFA98XX_SYS_CTRL_DCDIS_MSK 0x80
+
+/*
+ * cttr_iddqtest
+ */
+#define TFA98XX_SYS_CTRL_PSDR (0x1<<8)
+#define TFA98XX_SYS_CTRL_PSDR_POS 8
+#define TFA98XX_SYS_CTRL_PSDR_LEN 1
+#define TFA98XX_SYS_CTRL_PSDR_MAX 1
+#define TFA98XX_SYS_CTRL_PSDR_MSK 0x100
+
+/*
+ * ctrl_coil_value
+ */
+#define TFA98XX_SYS_CTRL_DCCV (0x3<<9)
+#define TFA98XX_SYS_CTRL_DCCV_POS 9
+#define TFA98XX_SYS_CTRL_DCCV_LEN 2
+#define TFA98XX_SYS_CTRL_DCCV_MAX 3
+#define TFA98XX_SYS_CTRL_DCCV_MSK 0x600
+
+/*
+ * ctrl_sel_cf_clock
+ */
+#define TFA98XX_SYS_CTRL_CCFD (0x3<<11)
+#define TFA98XX_SYS_CTRL_CCFD_POS 11
+#define TFA98XX_SYS_CTRL_CCFD_LEN 2
+#define TFA98XX_SYS_CTRL_CCFD_MAX 3
+#define TFA98XX_SYS_CTRL_CCFD_MSK 0x1800
+
+/*
+ * intf_sel
+ */
+#define TFA98XX_SYS_CTRL_ISEL (0x1<<13)
+#define TFA98XX_SYS_CTRL_ISEL_POS 13
+#define TFA98XX_SYS_CTRL_ISEL_LEN 1
+#define TFA98XX_SYS_CTRL_ISEL_MAX 1
+#define TFA98XX_SYS_CTRL_ISEL_MSK 0x2000
+
+/*
+ * sel_ws_bck
+ */
+#define TFA98XX_SYS_CTRL_IPLL (0x1<<14)
+#define TFA98XX_SYS_CTRL_IPLL_POS 14
+#define TFA98XX_SYS_CTRL_IPLL_LEN 1
+#define TFA98XX_SYS_CTRL_IPLL_MAX 1
+#define TFA98XX_SYS_CTRL_IPLL_MSK 0x4000
+
+
+/*
+ * (0x0a)-I2S_sel_reg
+ */
+
+/*
+ * sel_i2so_l
+ */
+#define TFA98XX_I2S_SEL_REG_DOLS (0x7<<0)
+#define TFA98XX_I2S_SEL_REG_DOLS_POS 0
+#define TFA98XX_I2S_SEL_REG_DOLS_LEN 3
+#define TFA98XX_I2S_SEL_REG_DOLS_MAX 7
+#define TFA98XX_I2S_SEL_REG_DOLS_MSK 0x7
+
+/*
+ * sel_i2so_r
+ */
+#define TFA98XX_I2S_SEL_REG_DORS (0x7<<3)
+#define TFA98XX_I2S_SEL_REG_DORS_POS 3
+#define TFA98XX_I2S_SEL_REG_DORS_LEN 3
+#define TFA98XX_I2S_SEL_REG_DORS_MAX 7
+#define TFA98XX_I2S_SEL_REG_DORS_MSK 0x38
+
+/*
+ * ctrl_spkr_coil
+ */
+#define TFA98XX_I2S_SEL_REG_SPKL (0x7<<6)
+#define TFA98XX_I2S_SEL_REG_SPKL_POS 6
+#define TFA98XX_I2S_SEL_REG_SPKL_LEN 3
+#define TFA98XX_I2S_SEL_REG_SPKL_MAX 7
+#define TFA98XX_I2S_SEL_REG_SPKL_MSK 0x1c0
+
+/*
+ * ctrl_spr_res
+ */
+#define TFA98XX_I2S_SEL_REG_SPKR (0x3<<9)
+#define TFA98XX_I2S_SEL_REG_SPKR_POS 9
+#define TFA98XX_I2S_SEL_REG_SPKR_LEN 2
+#define TFA98XX_I2S_SEL_REG_SPKR_MAX 3
+#define TFA98XX_I2S_SEL_REG_SPKR_MSK 0x600
+
+/*
+ * ctrl_dcdc_spkr_i_comp_gain
+ */
+#define TFA98XX_I2S_SEL_REG_DCFG (0xf<<11)
+#define TFA98XX_I2S_SEL_REG_DCFG_POS 11
+#define TFA98XX_I2S_SEL_REG_DCFG_LEN 4
+#define TFA98XX_I2S_SEL_REG_DCFG_MAX 15
+#define TFA98XX_I2S_SEL_REG_DCFG_MSK 0x7800
+
+
+/*
+ * (0x0b)-Hidden_mtp_key2
+ */
+
+/*
+ * MTP_key2
+ */
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK (0xff<<0)
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_POS 0
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_LEN 8
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_MAX 255
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_MSK 0xff
+
+
+/*
+ * (0x0f)-interrupt_reg
+ */
+
+/*
+ * flag_por_mask
+ */
+#define TFA98XX_INTERRUPT_REG_VDDD (0x1<<0)
+#define TFA98XX_INTERRUPT_REG_VDDD_POS 0
+#define TFA98XX_INTERRUPT_REG_VDDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_VDDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_VDDD_MSK 0x1
+
+/*
+ * flag_otpok_mask
+ */
+#define TFA98XX_INTERRUPT_REG_OTDD (0x1<<1)
+#define TFA98XX_INTERRUPT_REG_OTDD_POS 1
+#define TFA98XX_INTERRUPT_REG_OTDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_OTDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_OTDD_MSK 0x2
+
+/*
+ * flag_ovpok_mask
+ */
+#define TFA98XX_INTERRUPT_REG_OVDD (0x1<<2)
+#define TFA98XX_INTERRUPT_REG_OVDD_POS 2
+#define TFA98XX_INTERRUPT_REG_OVDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_OVDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_OVDD_MSK 0x4
+
+/*
+ * flag_uvpok_mask
+ */
+#define TFA98XX_INTERRUPT_REG_UVDD (0x1<<3)
+#define TFA98XX_INTERRUPT_REG_UVDD_POS 3
+#define TFA98XX_INTERRUPT_REG_UVDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_UVDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_UVDD_MSK 0x8
+
+/*
+ * flag_ocp_alarm_mask
+ */
+#define TFA98XX_INTERRUPT_REG_OCDD (0x1<<4)
+#define TFA98XX_INTERRUPT_REG_OCDD_POS 4
+#define TFA98XX_INTERRUPT_REG_OCDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_OCDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_OCDD_MSK 0x10
+
+/*
+ * flag_clocks_stable_mask
+ */
+#define TFA98XX_INTERRUPT_REG_CLKD (0x1<<5)
+#define TFA98XX_INTERRUPT_REG_CLKD_POS 5
+#define TFA98XX_INTERRUPT_REG_CLKD_LEN 1
+#define TFA98XX_INTERRUPT_REG_CLKD_MAX 1
+#define TFA98XX_INTERRUPT_REG_CLKD_MSK 0x20
+
+/*
+ * flag_pwrokbst_mask
+ */
+#define TFA98XX_INTERRUPT_REG_DCCD (0x1<<6)
+#define TFA98XX_INTERRUPT_REG_DCCD_POS 6
+#define TFA98XX_INTERRUPT_REG_DCCD_LEN 1
+#define TFA98XX_INTERRUPT_REG_DCCD_MAX 1
+#define TFA98XX_INTERRUPT_REG_DCCD_MSK 0x40
+
+/*
+ * flag_cf_speakererror_mask
+ */
+#define TFA98XX_INTERRUPT_REG_SPKD (0x1<<7)
+#define TFA98XX_INTERRUPT_REG_SPKD_POS 7
+#define TFA98XX_INTERRUPT_REG_SPKD_LEN 1
+#define TFA98XX_INTERRUPT_REG_SPKD_MAX 1
+#define TFA98XX_INTERRUPT_REG_SPKD_MSK 0x80
+
+/*
+ * flag_watchdog_reset_mask
+ */
+#define TFA98XX_INTERRUPT_REG_WDD (0x1<<8)
+#define TFA98XX_INTERRUPT_REG_WDD_POS 8
+#define TFA98XX_INTERRUPT_REG_WDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_WDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_WDD_MSK 0x100
+
+/*
+ * enable_interrupt
+ */
+#define TFA98XX_INTERRUPT_REG_INT (0x1<<14)
+#define TFA98XX_INTERRUPT_REG_INT_POS 14
+#define TFA98XX_INTERRUPT_REG_INT_LEN 1
+#define TFA98XX_INTERRUPT_REG_INT_MAX 1
+#define TFA98XX_INTERRUPT_REG_INT_MSK 0x4000
+
+/*
+ * invert_int_polarity
+ */
+#define TFA98XX_INTERRUPT_REG_INTP (0x1<<15)
+#define TFA98XX_INTERRUPT_REG_INTP_POS 15
+#define TFA98XX_INTERRUPT_REG_INTP_LEN 1
+#define TFA98XX_INTERRUPT_REG_INTP_MAX 1
+#define TFA98XX_INTERRUPT_REG_INTP_MSK 0x8000
+
+
+/*
+ * (0x10)-pdm_ctrl
+ */
+
+/*
+ * pdm_i2s_input
+ */
+#define TFA98XX_PDM_CTRL_PDMSEL (0x1<<0)
+#define TFA98XX_PDM_CTRL_PDMSEL_POS 0
+#define TFA98XX_PDM_CTRL_PDMSEL_LEN 1
+#define TFA98XX_PDM_CTRL_PDMSEL_MAX 1
+#define TFA98XX_PDM_CTRL_PDMSEL_MSK 0x1
+
+/*
+ * I2S_master_ena
+ */
+#define TFA98XX_PDM_CTRL_I2SMOUTEN (0x1<<1)
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_POS 1
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_LEN 1
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_MAX 1
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_MSK 0x2
+
+/*
+ * pdm_out_sel_r
+ */
+#define TFA98XX_PDM_CTRL_PDMORSEL (0x3<<2)
+#define TFA98XX_PDM_CTRL_PDMORSEL_POS 2
+#define TFA98XX_PDM_CTRL_PDMORSEL_LEN 2
+#define TFA98XX_PDM_CTRL_PDMORSEL_MAX 3
+#define TFA98XX_PDM_CTRL_PDMORSEL_MSK 0xc
+
+/*
+ * pdm_out_sel_l
+ */
+#define TFA98XX_PDM_CTRL_PDMOLSEL (0x3<<4)
+#define TFA98XX_PDM_CTRL_PDMOLSEL_POS 4
+#define TFA98XX_PDM_CTRL_PDMOLSEL_LEN 2
+#define TFA98XX_PDM_CTRL_PDMOLSEL_MAX 3
+#define TFA98XX_PDM_CTRL_PDMOLSEL_MSK 0x30
+
+/*
+ * micdat_out_sel
+ */
+#define TFA98XX_PDM_CTRL_PADSEL (0x3<<6)
+#define TFA98XX_PDM_CTRL_PADSEL_POS 6
+#define TFA98XX_PDM_CTRL_PADSEL_LEN 2
+#define TFA98XX_PDM_CTRL_PADSEL_MAX 3
+#define TFA98XX_PDM_CTRL_PADSEL_MSK 0xc0
+
+
+/*
+ * (0x11)-pdm_out_ctrl
+ */
+
+/*
+ * secure_dly
+ */
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN (0x1<<0)
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_POS 0
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_MSK 0x1
+
+/*
+ * d_out_valid_rf_mux
+ */
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF (0x1<<1)
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_POS 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_MSK 0x2
+
+/*
+ * Speak_As_Mic_en
+ */
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN (0x1<<4)
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_POS 4
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_MSK 0x10
+
+/*
+ * speak_as_mic_lp_mode
+ */
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN (0x1<<5)
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_POS 5
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_MSK 0x20
+
+/*
+ * pdm_out_rate
+ */
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN (0x1<<6)
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_POS 6
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_MSK 0x40
+
+
+/*
+ * (0x12)-pdm_ds4_r
+ */
+
+/*
+ * ds4_g1_r
+ */
+#define TFA98XX_PDM_DS4_R_PDMORG1 (0xf<<0)
+#define TFA98XX_PDM_DS4_R_PDMORG1_POS 0
+#define TFA98XX_PDM_DS4_R_PDMORG1_LEN 4
+#define TFA98XX_PDM_DS4_R_PDMORG1_MAX 15
+#define TFA98XX_PDM_DS4_R_PDMORG1_MSK 0xf
+
+/*
+ * ds4_g2_r
+ */
+#define TFA98XX_PDM_DS4_R_PDMORG2 (0xf<<4)
+#define TFA98XX_PDM_DS4_R_PDMORG2_POS 4
+#define TFA98XX_PDM_DS4_R_PDMORG2_LEN 4
+#define TFA98XX_PDM_DS4_R_PDMORG2_MAX 15
+#define TFA98XX_PDM_DS4_R_PDMORG2_MSK 0xf0
+
+
+/*
+ * (0x13)-pdm_ds4_l
+ */
+
+/*
+ * ds4_g1_l
+ */
+#define TFA98XX_PDM_DS4_L_PDMOLG1 (0xf<<0)
+#define TFA98XX_PDM_DS4_L_PDMOLG1_POS 0
+#define TFA98XX_PDM_DS4_L_PDMOLG1_LEN 4
+#define TFA98XX_PDM_DS4_L_PDMOLG1_MAX 15
+#define TFA98XX_PDM_DS4_L_PDMOLG1_MSK 0xf
+
+/*
+ * ds4_g2_l
+ */
+#define TFA98XX_PDM_DS4_L_PDMOLG2 (0xf<<4)
+#define TFA98XX_PDM_DS4_L_PDMOLG2_POS 4
+#define TFA98XX_PDM_DS4_L_PDMOLG2_LEN 4
+#define TFA98XX_PDM_DS4_L_PDMOLG2_MAX 15
+#define TFA98XX_PDM_DS4_L_PDMOLG2_MSK 0xf0
+
+
+/*
+ * (0x22)-ctrl_saam_pga
+ */
+
+/*
+ * Ctrl_saam_pga_gain
+ */
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN (0x7<<0)
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_POS 0
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_LEN 3
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_MAX 7
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_MSK 0x7
+
+/*
+ * ctrl_saam_pga_src
+ */
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL (0x1<<5)
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_POS 5
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_LEN 1
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_MAX 1
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_MSK 0x20
+
+
+/*
+ * (0x25)-misc_ctrl
+ */
+
+/*
+ * pll_fcco
+ */
+#define TFA98XX_MISC_CTRL_PLLCCOSEL (0x1<<0)
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_POS 0
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_LEN 1
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_MAX 1
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_MSK 0x1
+
+
+/*
+ * (0x46)-CurrentSense1
+ */
+
+/*
+ * bypass_gc
+ */
+#define TFA98XX_CURRENTSENSE1_CSBYPGC (0x1<<0)
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_POS 0
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_LEN 1
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_MAX 1
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_MSK 0x1
+
+
+/*
+ * (0x49)-CurrentSense4
+ */
+
+/*
+ * ctrl_bypassclip
+ */
+#define TFA98XX_CURRENTSENSE4_CLIP (0x1<<0)
+#define TFA98XX_CURRENTSENSE4_CLIP_POS 0
+#define TFA98XX_CURRENTSENSE4_CLIP_LEN 1
+#define TFA98XX_CURRENTSENSE4_CLIP_MAX 1
+#define TFA98XX_CURRENTSENSE4_CLIP_MSK 0x1
+
+/*
+ * ctrl_bypassclip2
+ */
+#define TFA98XX_CURRENTSENSE4_CLIP2 (0x1<<1)
+#define TFA98XX_CURRENTSENSE4_CLIP2_POS 1
+#define TFA98XX_CURRENTSENSE4_CLIP2_LEN 1
+#define TFA98XX_CURRENTSENSE4_CLIP2_MAX 1
+#define TFA98XX_CURRENTSENSE4_CLIP2_MSK 0x2
+
+
+/*
+ * (0x62)-Hidden_mtp_ctrl_reg3
+ */
+
+
+/*
+ * (0x70)-cf_controls
+ */
+
+/*
+ * cf_rst_dsp
+ */
+#define TFA98XX_CF_CONTROLS_RST (0x1<<0)
+#define TFA98XX_CF_CONTROLS_RST_POS 0
+#define TFA98XX_CF_CONTROLS_RST_LEN 1
+#define TFA98XX_CF_CONTROLS_RST_MAX 1
+#define TFA98XX_CF_CONTROLS_RST_MSK 0x1
+
+/*
+ * cf_dmem
+ */
+#define TFA98XX_CF_CONTROLS_DMEM (0x3<<1)
+#define TFA98XX_CF_CONTROLS_DMEM_POS 1
+#define TFA98XX_CF_CONTROLS_DMEM_LEN 2
+#define TFA98XX_CF_CONTROLS_DMEM_MAX 3
+#define TFA98XX_CF_CONTROLS_DMEM_MSK 0x6
+
+/*
+ * cf_aif
+ */
+#define TFA98XX_CF_CONTROLS_AIF (0x1<<3)
+#define TFA98XX_CF_CONTROLS_AIF_POS 3
+#define TFA98XX_CF_CONTROLS_AIF_LEN 1
+#define TFA98XX_CF_CONTROLS_AIF_MAX 1
+#define TFA98XX_CF_CONTROLS_AIF_MSK 0x8
+
+/*
+ * cf_int
+ */
+#define TFA98XX_CF_CONTROLS_CFINT (0x1<<4)
+#define TFA98XX_CF_CONTROLS_CFINT_POS 4
+#define TFA98XX_CF_CONTROLS_CFINT_LEN 1
+#define TFA98XX_CF_CONTROLS_CFINT_MAX 1
+#define TFA98XX_CF_CONTROLS_CFINT_MSK 0x10
+
+/*
+ * cf_req
+ */
+#define TFA98XX_CF_CONTROLS_REQ (0xff<<8)
+#define TFA98XX_CF_CONTROLS_REQ_POS 8
+#define TFA98XX_CF_CONTROLS_REQ_LEN 8
+#define TFA98XX_CF_CONTROLS_REQ_MAX 255
+#define TFA98XX_CF_CONTROLS_REQ_MSK 0xff00
+
+
+/*
+ * (0x71)-cf_mad
+ */
+
+/*
+ * cf_madd
+ */
+#define TFA9891_CF_MAD_MADD (0xffff<<0)
+#define TFA9891_CF_MAD_MADD_POS 0
+#define TFA9891_CF_MAD_MADD_LEN 16
+#define TFA9891_CF_MAD_MADD_MAX 65535
+#define TFA9891_CF_MAD_MADD_MSK 0xffff
+
+
+/*
+ * (0x72)-cf_mem
+ */
+
+/*
+ * cf_mema
+ */
+#define TFA9891_CF_MEM_MEMA (0xffff<<0)
+#define TFA9891_CF_MEM_MEMA_POS 0
+#define TFA9891_CF_MEM_MEMA_LEN 16
+#define TFA9891_CF_MEM_MEMA_MAX 65535
+#define TFA9891_CF_MEM_MEMA_MSK 0xffff
+
+
+/*
+ * (0x73)-cf_status
+ */
+
+/*
+ * cf_err
+ */
+#define TFA9891_CF_STATUS_ERR (0xff<<0)
+#define TFA9891_CF_STATUS_ERR_POS 0
+#define TFA9891_CF_STATUS_ERR_LEN 8
+#define TFA9891_CF_STATUS_ERR_MAX 255
+#define TFA9891_CF_STATUS_ERR_MSK 0xff
+
+/*
+ * cf_ack
+ */
+#define TFA9891_CF_STATUS_ACK (0xff<<8)
+#define TFA9891_CF_STATUS_ACK_POS 8
+#define TFA9891_CF_STATUS_ACK_LEN 8
+#define TFA9891_CF_STATUS_ACK_MAX 255
+#define TFA9891_CF_STATUS_ACK_MSK 0xff00
+
+
+/*
+ * (0x80)-Key2Protected_spkr_cal_mtp
+ */
+
+/*
+ * calibration_onetime
+ */
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC (0x1<<0)
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_POS 0
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_LEN 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_MAX 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_MSK 0x1
+
+/*
+ * calibr_ron_done
+ */
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX (0x1<<1)
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_POS 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_LEN 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_MAX 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_MSK 0x2
+
+#endif /* TFA9891_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9891_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9891_tfafieldnames.h
new file mode 100644
index 00000000000..99cb5ab6bec
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9891_tfafieldnames.h
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*
+ * tfa9891_tfafieldnames.h
+ *
+ * Created on: Jul 16, 2015
+ * Author: wim
+ */
+
+#ifndef TFA_INC_TFA9891_TFAFIELDNAMES_H_
+#define TFA_INC_TFA9891_TFAFIELDNAMES_H_
+
+/** Filename: Tfa9891_TfaFieldnames.h
+ * This file was generated automatically on 07/16/15 at 15:00:02.
+ * Source file: TFA9891_I2C_list_V13.xls
+ */
+
+#define TFA9891_I2CVERSION 13
+
+
+#define TFA9891_NAMETABLE static tfaBfName_t Tfa9891DatasheetNames[]= {\
+ { 0x0, "VDDS"}, /* POR , */\
+ { 0x10, "PLLS"}, /* PLL , */\
+ { 0x20, "OTDS"}, /* OTP , */\
+ { 0x30, "OVDS"}, /* OVP , */\
+ { 0x40, "UVDS"}, /* UVP , */\
+ { 0x50, "OCDS"}, /* OCP , */\
+ { 0x60, "CLKS"}, /* Clocks , */\
+ { 0x70, "CLIPS"}, /* CLIP , */\
+ { 0x80, "MTPB"}, /* MTP , */\
+ { 0x90, "DCCS"}, /* BOOST , */\
+ { 0xa0, "SPKS"}, /* Speaker , */\
+ { 0xb0, "ACS"}, /* cold start flag , */\
+ { 0xc0, "SWS"}, /* flag engage , */\
+ { 0xd0, "WDS"}, /* flag watchdog reset , */\
+ { 0xe0, "AMPS"}, /* amplifier is enabled by manager , */\
+ { 0xf0, "AREFS"}, /* references are enabled by manager , */\
+ { 0x109, "BATS"}, /* Battery voltage readout; 0[V]..5.5[V] , */\
+ { 0x208, "TEMPS"}, /* Temperature readout , */\
+ { 0x307, "REV"}, /* Device Revision , */\
+ { 0x402, "I2SF"}, /* I2SFormat data 1 input , */\
+ { 0x431, "CHS12"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "CHS3"}, /* Channel Selection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x481, "I2SDOC"}, /* Selection for I2S data out , */\
+ { 0x4a0, "DISP"}, /* idp protection , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "I2SSR"}, /* sample rate setting , */\
+ { 0x501, "BSSCR"}, /* ProtectionAttackTime , */\
+ { 0x523, "BSST"}, /* ProtectionThreshold , */\
+ { 0x561, "BSSRL"}, /* ProtectionMaximumReduction , */\
+ { 0x582, "BSSRR"}, /* Protection Release Timer , */\
+ { 0x5b1, "BSSHY"}, /* ProtectionHysterese , */\
+ { 0x5e0, "BSSR"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "BSSBY"}, /* bypass clipper battery protection , */\
+ { 0x600, "DPSA"}, /* Enable dynamic powerstage activation , */\
+ { 0x613, "AMPSL"}, /* control slope , */\
+ { 0x650, "CFSM"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "BSSS"}, /* batsensesteepness , */\
+ { 0x687, "VOL"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "DCVO"}, /* Boost voltage , */\
+ { 0x732, "DCMCC"}, /* Max boost coil current , */\
+ { 0x7a0, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7b0, "DCSR"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x800, "TROS"}, /* select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "EXTTS"}, /* external temperature setting to be given by host , */\
+ { 0x900, "PWDN"}, /* ON/OFF , */\
+ { 0x910, "I2CR"}, /* I2CReset , */\
+ { 0x920, "CFE"}, /* EnableCoolFlux , */\
+ { 0x930, "AMPE"}, /* EnableAmplifier , */\
+ { 0x940, "DCA"}, /* EnableBoost , */\
+ { 0x950, "SBSL"}, /* Coolflux configured , */\
+ { 0x960, "AMPC"}, /* Selection on how AmplifierEnabling , */\
+ { 0x970, "DCDIS"}, /* DCDC not connected , */\
+ { 0x980, "PSDR"}, /* Iddq test amplifier , */\
+ { 0x991, "DCCV"}, /* Coil Value , */\
+ { 0x9b1, "CCFD"}, /* Selection CoolFluxClock , */\
+ { 0x9d0, "ISEL"}, /* Interface Selection , */\
+ { 0x9e0, "IPLL"}, /* selection input PLL for lock , */\
+ { 0xa02, "DOLS"}, /* Output selection dataout left channel , */\
+ { 0xa32, "DORS"}, /* Output selection dataout right channel , */\
+ { 0xa62, "SPKL"}, /* Selection speaker induction , */\
+ { 0xa91, "SPKR"}, /* Selection speaker impedance , */\
+ { 0xab3, "DCFG"}, /* DCDC speaker current compensation gain , */\
+ { 0xb07, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xf00, "VDDD"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "OTDD"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "OVDD"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "UVDD"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "OCDD"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "CLKD"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "DCCD"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "SPKD"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "WDD"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xfe0, "INT"}, /* enabling interrupt , */\
+ { 0xff0, "INTP"}, /* Setting polarity interupt , */\
+ { 0x1000, "PDMSEL"}, /* Audio input interface mode , */\
+ { 0x1010, "I2SMOUTEN"}, /* I2S Master enable (CLK and WS pads) , */\
+ { 0x1021, "PDMORSEL"}, /* PDM Output right channel source selection , */\
+ { 0x1041, "PDMOLSEL"}, /* PDM Output Left/Mono channel source selection , */\
+ { 0x1061, "PADSEL"}, /* Output interface mode and ball selection , */\
+ { 0x1100, "PDMOSDEN"}, /* Secure delay Cell , */\
+ { 0x1110, "PDMOSDCF"}, /* Rising Falling Resync control Mux , */\
+ { 0x1140, "SAAMEN"}, /* Speaker As a Mic feature ON/OFF , */\
+ { 0x1150, "SAAMLPEN"}, /* speaker_as_mic low power mode (only in PDM_out mode), */\
+ { 0x1160, "PDMOINTEN"}, /* PDM output interpolation ratio , */\
+ { 0x1203, "PDMORG1"}, /* PDM Interpolator Right Channel DS4 G1 Gain Value , */\
+ { 0x1243, "PDMORG2"}, /* PDM Interpolator Right Channel DS4 G2 Gain Value , */\
+ { 0x1303, "PDMOLG1"}, /* PDM Interpolator Left Channel DS4 G1 Gain Value , */\
+ { 0x1343, "PDMOLG2"}, /* PDM Interpolator Left Channel DS4 G2 Gain Value , */\
+ { 0x2202, "SAAMGAIN"}, /* pga gain , */\
+ { 0x2250, "SAAMPGACTRL"}, /* 0 = active input common mode voltage source at the attenuator/PGA level, */\
+ { 0x2500, "PLLCCOSEL"}, /* pll cco frequency , */\
+ { 0x4600, "CSBYPGC"}, /* bypass_gc, bypasses the CS gain correction , */\
+ { 0x4900, "CLIP"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x4910, "CLIP2"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x62b0, "CIMTP"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x7000, "RST"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "DMEM"}, /* Target memory for access , */\
+ { 0x7030, "AIF"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "CFINT"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "REQ"}, /* request for access (8 channels) , */\
+ { 0x710f, "MADD"}, /* memory-address to be accessed , */\
+ { 0x720f, "MEMA"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "ERR"}, /* cf error Flags , */\
+ { 0x7387, "ACK"}, /* acknowledge of requests (8 channels")" , */\
+ { 0x8000, "MTPOTC"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "MTPEX"}, /* (key2 protected) calibration of Ron has been executed, */\
+ { 0x8045, "SWPROFIL" },\
+ { 0x80a5, "SWVSTEP" },\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9891_BITNAMETABLE static tfaBfName_t Tfa9891BitNames[]= {\
+ { 0x0, "POR"}, /* POR , */\
+ { 0x10, "PLL_LOCK"}, /* PLL , */\
+ { 0x20, "flag_otpok"}, /* OTP , */\
+ { 0x30, "flag_ovpok"}, /* OVP , */\
+ { 0x40, "flag_uvpok"}, /* UVP , */\
+ { 0x50, "flag_OCP_alarm"}, /* OCP , */\
+ { 0x60, "flag_clocks_stable"}, /* Clocks , */\
+ { 0x70, "CLIP"}, /* CLIP , */\
+ { 0x80, "mtp_busy"}, /* MTP , */\
+ { 0x90, "flag_pwrokbst"}, /* BOOST , */\
+ { 0xa0, "flag_cf_speakererror"}, /* Speaker , */\
+ { 0xb0, "flag_cold_started"}, /* cold start flag , */\
+ { 0xc0, "flag_engage"}, /* flag engage , */\
+ { 0xd0, "flag_watchdog_reset"}, /* flag watchdog reset , */\
+ { 0xe0, "flag_enbl_amp"}, /* amplifier is enabled by manager , */\
+ { 0xf0, "flag_enbl_ref"}, /* references are enabled by manager , */\
+ { 0x109, "bat_adc"}, /* Battery voltage readout; 0[V]..5.5[V] , */\
+ { 0x208, "temp_adc"}, /* Temperature readout , */\
+ { 0x307, "rev_reg"}, /* Device Revision , */\
+ { 0x402, "i2s_seti"}, /* I2SFormat data 1 input , */\
+ { 0x431, "chan_sel1"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "lr_sw_i2si2"}, /* Channel Selection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "input_sel"}, /* Input selection for amplifier , */\
+ { 0x481, "datao_sel"}, /* Selection for I2S data out , */\
+ { 0x4a0, "disable_idp"}, /* idp protection , */\
+ { 0x4b0, "enbl_datao"}, /* Enable data output , */\
+ { 0x4c3, "i2s_fs"}, /* sample rate setting , */\
+ { 0x501, "vbat_prot_attacktime"}, /* ProtectionAttackTime , */\
+ { 0x523, "vbat_prot_thlevel"}, /* ProtectionThreshold , */\
+ { 0x561, "vbat_prot_max_reduct"}, /* ProtectionMaximumReduction , */\
+ { 0x582, "vbat_prot_release_t"}, /* Protection Release Timer , */\
+ { 0x5b1, "vbat_prot_hysterese"}, /* ProtectionHysterese , */\
+ { 0x5d0, "reset_min_vbat"}, /* reset clipper , */\
+ { 0x5e0, "sel_vbat"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "bypass_clipper"}, /* bypass clipper battery protection , */\
+ { 0x600, "dpsa"}, /* Enable dynamic powerstage activation , */\
+ { 0x613, "ctrl_slope"}, /* control slope , */\
+ { 0x650, "cf_mute"}, /* Soft mute in CoolFlux , */\
+ { 0x660, "sel_other_vamp"}, /* Input selection for the second channel of the DCDC inteligent mode detector, */\
+ { 0x670, "ctrl_batsensesteepness"}, /* batsensesteepness , */\
+ { 0x687, "vol"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "ctrl_bstvolt"}, /* Boost voltage , */\
+ { 0x732, "ctrl_bstcur"}, /* Max boost coil current , */\
+ { 0x761, "ctrl_slopebst_1_0"}, /* Setting for the slope of the boost converter power stage, */\
+ { 0x781, "ctrl_slopebst_3_2"}, /* Setting for the part of the power transistor voltage to be used in peak current mode control, */\
+ { 0x7a0, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7b0, "boost_speed"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x7c1, "ctrl_delay_comp_dcdc"}, /* delay compensation in current patg compared to delay in the audio path (relative) , */\
+ { 0x7e0, "boost_input"}, /* Selection intelligent boost detector input , */\
+ { 0x7f0, "ctrl_supplysense"}, /* ADC10 input selection , */\
+ { 0x800, "ext_temp_sel"}, /* select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "ext_temp"}, /* external temperature setting to be given by host , */\
+ { 0x8a0, "ctrl_spk_coilpvp_bst"}, /* Peak voltage protection boost converter , */\
+ { 0x8b2, "ctrl_dcdc_synchronisation"}, /* DCDC synchronisation off + 7 positions , */\
+ { 0x8e0, "ctrl_cs_samplevalid"}, /* sample valid moment for CS in single sample moment mode, */\
+ { 0x900, "PowerDown"}, /* ON/OFF , */\
+ { 0x910, "reset"}, /* I2CReset , */\
+ { 0x920, "enbl_coolflux"}, /* EnableCoolFlux , */\
+ { 0x930, "enbl_amplifier"}, /* EnableAmplifier , */\
+ { 0x940, "enbl_boost"}, /* EnableBoost , */\
+ { 0x950, "cf_configured"}, /* Coolflux configured , */\
+ { 0x960, "sel_enbl_amplifier"}, /* Selection on how AmplifierEnabling , */\
+ { 0x970, "dcdcoff_mode"}, /* DCDC not connected , */\
+ { 0x980, "cttr_iddqtest"}, /* Iddq test amplifier , */\
+ { 0x991, "ctrl_coil_value"}, /* Coil Value , */\
+ { 0x9b1, "ctrl_sel_cf_clock"}, /* Selection CoolFluxClock , */\
+ { 0x9d0, "intf_sel"}, /* Interface Selection , */\
+ { 0x9e0, "sel_ws_bck"}, /* selection input PLL for lock , */\
+ { 0xa02, "sel_i2so_l"}, /* Output selection dataout left channel , */\
+ { 0xa32, "sel_i2so_r"}, /* Output selection dataout right channel , */\
+ { 0xa62, "ctrl_spkr_coil"}, /* Selection speaker induction , */\
+ { 0xa91, "ctrl_spr_res"}, /* Selection speaker impedance , */\
+ { 0xab3, "ctrl_dcdc_spkr_i_comp_gain"}, /* DCDC speaker current compensation gain , */\
+ { 0xaf0, "ctrl_dcdc_spkr_i_comp_sign"}, /* DCDC speaker current compensation sign , */\
+ { 0xb07, "MTP_key2"}, /* MTP KEY2 register , */\
+ { 0xc0c, "clk_sync_delay"}, /* Delay count for clock synchronisation , */\
+ { 0xcf0, "enbl_clk_sync"}, /* Enable CGU clock synchronisation , */\
+ { 0xd0c, "adc_sync_delay"}, /* Delay count for ADC synchronisation , */\
+ { 0xdf0, "enable_adc_sync"}, /* Enable ADC synchronisation , */\
+ { 0xe00, "bypass_dcdc_curr_prot"}, /* to switch off dcdc reduction with bat prot , */\
+ { 0xe24, "ctrl_digtoana6_2"}, /* for extra connections digital to analog , */\
+ { 0xe70, "switch_on_icomp"}, /* icomp dem switch , */\
+ { 0xe87, "reserve_reg_1_7_0"}, /* reserved , */\
+ { 0xf00, "flag_por_mask"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "flag_otpok_mask"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "flag_ovpok_mask"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "flag_uvpok_mask"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "flag_ocp_alarm_mask"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "flag_clocks_stable_mask"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "flag_pwrokbst_mask"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "flag_cf_speakererror_mask"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "flag_watchdog_reset_mask"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xf90, "flag_lost_clk_mask"}, /* mask flag_lost_clk for interupt generation , */\
+ { 0xfe0, "enable_interrupt"}, /* enabling interrupt , */\
+ { 0xff0, "invert_int_polarity"}, /* Setting polarity interupt , */\
+ { 0x1000, "pdm_i2s_input"}, /* Audio input interface mode , */\
+ { 0x1010, "I2S_master_ena"}, /* I2S Master enable (CLK and WS pads) , */\
+ { 0x1021, "pdm_out_sel_r"}, /* PDM Output right channel source selection , */\
+ { 0x1041, "pdm_out_sel_l"}, /* PDM Output Left/Mono channel source selection , */\
+ { 0x1061, "micdat_out_sel"}, /* Output interface mode and ball selection , */\
+ { 0x1100, "secure_dly"}, /* Secure delay Cell , */\
+ { 0x1110, "d_out_valid_rf_mux"}, /* Rising Falling Resync control Mux , */\
+ { 0x1140, "Speak_As_Mic_en"}, /* Speaker As a Mic feature ON/OFF , */\
+ { 0x1150, "speak_as_mic_lp_mode"}, /* speaker_as_mic low power mode (only in PDM_out mode), */\
+ { 0x1160, "pdm_out_rate"}, /* PDM output interpolation ratio , */\
+ { 0x1203, "ds4_g1_r"}, /* PDM Interpolator Right Channel DS4 G1 Gain Value , */\
+ { 0x1243, "ds4_g2_r"}, /* PDM Interpolator Right Channel DS4 G2 Gain Value , */\
+ { 0x1303, "ds4_g1_l"}, /* PDM Interpolator Left Channel DS4 G1 Gain Value , */\
+ { 0x1343, "ds4_g2_l"}, /* PDM Interpolator Left Channel DS4 G2 Gain Value , */\
+ { 0x1400, "clk_secure_dly"}, /* Secure delay Cell on clock path , */\
+ { 0x1410, "data_secure_dly"}, /* Secure delay Cell enable on PDM data path , */\
+ { 0x2202, "Ctrl_saam_pga_gain"}, /* pga gain , */\
+ { 0x2250, "ctrl_saam_pga_src"}, /* 0 = active input common mode voltage source at the attenuator/PGA level, */\
+ { 0x2300, "flag_saam_spare"}, /* spare flag , */\
+ { 0x2400, "ctrl_saam_pga_tm"}, /* enables PGA test mode , */\
+ { 0x2500, "pll_fcco"}, /* pll cco frequency , */\
+ { 0x3000, "flag_hi_small"}, /* positive small window dcdc converter , */\
+ { 0x3010, "flag_hi_large"}, /* positive large window dcdc converter , */\
+ { 0x3020, "flag_lo_small"}, /* negative small window dcdc converter , */\
+ { 0x3030, "flag_lo_large"}, /* negative large window dcdc converter , */\
+ { 0x3040, "flag_voutcomp"}, /* flag_voutcomp, indication Vset is larger than Vbat, */\
+ { 0x3050, "flag_voutcomp93"}, /* flag_voutcomp93, indication Vset is larger than 1.07* Vbat , */\
+ { 0x3060, "flag_voutcomp86"}, /* flag_voutcomp86, indication Vset is larger than 1.14* Vbat , */\
+ { 0x3070, "flag_hiz"}, /* flag_hiz, indication Vbst is larger than Vbat , */\
+ { 0x3080, "flag_hi_peak"}, /* flag_hi_peak, indication hi_peak , */\
+ { 0x3090, "flag_ocpokbst"}, /* flag_ocpokbst, indication no over current in boost converter pmos switch, */\
+ { 0x30a0, "flag_peakcur"}, /* flag_peakcur, indication current is max in dcdc converter, */\
+ { 0x30b0, "flag_ocpokap"}, /* flag_ocpokap, indication no over current in amplifier "a" pmos output stage, */\
+ { 0x30c0, "flag_ocpokan"}, /* flag_ocpokan, indication no over current in amplifier "a" nmos output stage, */\
+ { 0x30d0, "flag_ocpokbp"}, /* flag_ocpokbp, indication no over current in amplifier "b" pmos output stage, */\
+ { 0x30e0, "flag_ocpokbn"}, /* flag_ocpokbn, indication no over current in amplifier"b" nmos output stage, */\
+ { 0x30f0, "lost_clk"}, /* lost_clk, lost clock indication CGU , */\
+ { 0x310f, "mtp_man_data_out"}, /* single word read from MTP (manual copy) , */\
+ { 0x3200, "key01_locked"}, /* key01_locked, indication key 1 is locked , */\
+ { 0x3210, "key02_locked"}, /* key02_locked, indication key 2 is locked , */\
+ { 0x3225, "mtp_ecc_tcout"}, /* mtp_ecc_tcout , */\
+ { 0x3280, "mtpctrl_valid_test_rd"}, /* mtp test readout for read , */\
+ { 0x3290, "mtpctrl_valid_test_wr"}, /* mtp test readout for write , */\
+ { 0x32a0, "flag_in_alarm_state"}, /* alarm state , */\
+ { 0x32b0, "mtp_ecc_err2"}, /* two or more bit errors detected in MTP, can not reconstruct value, */\
+ { 0x32c0, "mtp_ecc_err1"}, /* one bit error detected in MTP, reconstructed value, */\
+ { 0x32d0, "mtp_mtp_hvf"}, /* high voltage ready flag for MTP , */\
+ { 0x32f0, "mtp_zero_check_fail"}, /* zero check failed (tbd) for MTP , */\
+ { 0x3300, "flag_adc10_ready"}, /* flag_adc10_ready, indication adc10 is ready , */\
+ { 0x3310, "flag_clipa_high"}, /* flag_clipa_high, indication pmos amplifier "a" is clipping, */\
+ { 0x3320, "flag_clipa_low"}, /* flag_clipa_low, indication nmos amplifier "a" is clipping, */\
+ { 0x3330, "flag_clipb_high"}, /* flag_clipb_high, indication pmos amplifier "b" is clipping, */\
+ { 0x3340, "flag_clipb_low"}, /* flag_clipb_low, indication nmos amplifier "b" is clipping, */\
+ { 0x3359, "data_adc10_tempbat"}, /* adc 10 data output for testing , */\
+ { 0x33f0, "flag_vddd_comp_nok"}, /* power switch flag 2 for testing , */\
+ { 0x400f, "hid_code"}, /* hidden code , */\
+ { 0x4100, "bypass_hp"}, /* Bypass_High Pass Filter , */\
+ { 0x4110, "hard_mute"}, /* Hard Mute , */\
+ { 0x4120, "soft_mute"}, /* Soft Mute , */\
+ { 0x4134, "PWM_Delay"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "PWM_Shape"}, /* PWM Shape , */\
+ { 0x4190, "PWM_BitLength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4207, "ctrl_drive"}, /* drive bits to select amount of power stages amplifier, */\
+ { 0x4281, "dpsalevel"}, /* DPSA Threshold level , */\
+ { 0x42a1, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x42c0, "ctrl_coincidence"}, /* Prevent simultaneously switching of output stage , */\
+ { 0x42d0, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x42e0, "ctrl_test_sdeltaoffset"}, /* ctrl_test_sdeltaoffset , */\
+ { 0x42f0, "ctrl_test_sdeltaclk"}, /* ctrl_test_sdeltaclk , */\
+ { 0x4309, "ctrl_drivebst"}, /* Drive bits to select the powertransistor sections boost converter, */\
+ { 0x43a0, "ctrl_ocptestbst"}, /* Boost OCP. , */\
+ { 0x43c0, "enbl_hi_peak"}, /* enable for high peak comparator , */\
+ { 0x43d0, "test_abistfft_enbl"}, /* FFT coolflux , */\
+ { 0x43e0, "ctrl_sensetest_amp"}, /* sensetest amplifier , */\
+ { 0x43f0, "test_bcontrol"}, /* test _bcontrol , */\
+ { 0x4400, "ctrl_reversebst"}, /* OverCurrent Protection selection of power stage boost converter, */\
+ { 0x4410, "ctrl_sensetest"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0x4420, "enbl_engagebst"}, /* Enable power stage dcdc controller , */\
+ { 0x4430, "enbl_hi_small"}, /* Enable bit of hi (small) comparator , */\
+ { 0x4440, "enbl_hi_large"}, /* Enable bit of hi (large) comparator , */\
+ { 0x4450, "enbl_lo_small"}, /* Enable bit of lo (small) comparator , */\
+ { 0x4460, "enbl_lo_large"}, /* Enable bit of lo (large) comparator , */\
+ { 0x4470, "enbl_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x4480, "enbl_voutcomp"}, /* Enable vout comparators , */\
+ { 0x4490, "enbl_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x44a0, "enbl_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x44b0, "enbl_hizcom"}, /* Enable hiz comparator , */\
+ { 0x44c0, "enbl_pcdac"}, /* Enable peak current dac , */\
+ { 0x44d0, "enbl_pccomp"}, /* Enable peak current comparator , */\
+ { 0x44e0, "enbl_windac"}, /* Enable window dac , */\
+ { 0x44f0, "enbl_powerbst"}, /* Enable line of the powerstage , */\
+ { 0x4507, "ocp_thr"}, /* ocp_thr threshold level for OCP , */\
+ { 0x4580, "bypass_glitchfilter"}, /* Bypass glitchfilter , */\
+ { 0x4590, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0x45a0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0x45b0, "bypass_otp"}, /* Bypass OTP , */\
+ { 0x45c0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0x45d0, "bypass_ocpcounter"}, /* BypassOCPCounter , */\
+ { 0x45e0, "bypass_lost_clk"}, /* Bypasslost_clk detector , */\
+ { 0x45f0, "vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0x4600, "bypass_gc"}, /* bypass_gc, bypasses the CS gain correction , */\
+ { 0x4610, "cs_gain_control"}, /* gain control by means of MTP or i2c , */\
+ { 0x4627, "cs_gain"}, /* + / - 128 steps in steps of 1/4 % 2's compliment , */\
+ { 0x46a0, "bypass_lp"}, /* bypass Low-Pass filter in temperature sensor , */\
+ { 0x46b0, "bypass_pwmcounter"}, /* bypass_pwmcounter , */\
+ { 0x46c0, "ctrl_cs_negfixed"}, /* does not switch to neg , */\
+ { 0x46d2, "ctrl_cs_neghyst"}, /* switches to neg depending on level , */\
+ { 0x4700, "switch_fb"}, /* switch_fb , */\
+ { 0x4713, "se_hyst"}, /* se_hyst , */\
+ { 0x4754, "se_level"}, /* se_level , */\
+ { 0x47a5, "ktemp"}, /* temperature compensation trimming , */\
+ { 0x4800, "ctrl_negin"}, /* negin , */\
+ { 0x4810, "ctrl_cs_sein"}, /* cs_sein , */\
+ { 0x4820, "ctrl_coincidencecs"}, /* Coincidence current sense , */\
+ { 0x4830, "ctrl_iddqtestbst"}, /* for iddq testing in powerstage of boost convertor , */\
+ { 0x4840, "ctrl_coincidencebst"}, /* Switch protection on to prevent simultaniously switching power stages bst and amp, */\
+ { 0x4851, "clock_sh_sel"}, /* Clock SH selection , */\
+ { 0x4876, "delay_se_neg"}, /* delay of se and neg , */\
+ { 0x48e1, "ctrl_cs_ttrack"}, /* sample & hold track time , */\
+ { 0x4900, "ctrl_bypassclip"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x4910, "ctrl_bypassclip2"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x4920, "ctrl_clkgateCFoff"}, /* to disable clock gating in the coolflux , */\
+ { 0x4930, "ctrl_testabst"}, /* testabst , */\
+ { 0x4940, "ctrl_clipfast"}, /* clock switch for battery protection clipper, it switches back to old frequency, */\
+ { 0x4950, "ctrl_cs_8ohm"}, /* 8 ohm mode for current sense (gain mode) , */\
+ { 0x4960, "reserved"}, /* reserved , */\
+ { 0x4974, "delay_clock_sh"}, /* delay_sh, tunes S7H delay , */\
+ { 0x49c0, "inv_clksh"}, /* Invert the sample/hold clock for current sense ADC, */\
+ { 0x49d0, "inv_neg"}, /* Invert neg signal , */\
+ { 0x49e0, "inv_se"}, /* Invert se signal , */\
+ { 0x49f0, "setse"}, /* switches between Single Ende and differentail mode, */\
+ { 0x4a12, "ctrl_adc10_sel"}, /* select the input to convert the 10b ADC , */\
+ { 0x4a60, "ctrl_adc10_reset"}, /* Global asynchronous reset (active HIGH) 10 bit ADC, */\
+ { 0x4a81, "ctrl_adc10_test"}, /* Test mode selection signal 10 bit ADC , */\
+ { 0x4aa0, "ctrl_bypass_lp_vbat"}, /* lp filter in batt sensor , */\
+ { 0x4ae0, "ctrl_dc_offset"}, /* switch offset control on/off, is decimator offset control, */\
+ { 0x4af0, "ctrl_tsense_hibias"}, /* bit to set the biasing in temp sensor to high , */\
+ { 0x4b00, "ctrl_adc13_iset"}, /* Micadc Setting of current consumption. Debug use only, */\
+ { 0x4b14, "ctrl_adc13_gain"}, /* Micadc gain setting (2-compl) , */\
+ { 0x4b61, "ctrl_adc13_slowdel"}, /* Micadc Delay setting for internal clock. Debug use only, */\
+ { 0x4b83, "ctrl_adc13_offset"}, /* Micadc ADC offset setting , */\
+ { 0x4bc0, "ctrl_adc13_bsoinv"}, /* Micadc bit stream output invert mode for test , */\
+ { 0x4bd0, "ctrl_adc13_resonator_enable"}, /* Micadc Give extra SNR with less stability. Debug use only, */\
+ { 0x4be0, "ctrl_testmicadc"}, /* Mux at input of MICADC for test purpose , */\
+ { 0x4c0f, "ctrl_offset"}, /* offset control for ABIST testing , */\
+ { 0x4d05, "ctrl_windac"}, /* for testing direct control windac , */\
+ { 0x4d65, "ctrl_peakcur"}, /* Control peakcur , */\
+ { 0x4dc3, "pwm_dcc_cnt"}, /* control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0x4e04, "ctrl_slopecur"}, /* for testing direct control slopecur , */\
+ { 0x4e53, "ctrl_dem"}, /* dyn element matching control, rest of codes are optional, */\
+ { 0x4e93, "ctrl_demmismatch"}, /* dyn element matching add offset , */\
+ { 0x4ed0, "enbl_pwm_dcc"}, /* to enable direct control of pwm duty cycle , */\
+ { 0x5007, "gain"}, /* gain setting of the gain multiplier gain need to increase with factor 1.41 (3dB), */\
+ { 0x5081, "ctrl_sourceb"}, /* Set OUTB to , */\
+ { 0x50a1, "ctrl_sourcea"}, /* Set OUTA to , */\
+ { 0x50c1, "ctrl_sourcebst"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0x50e1, "ctrl_test_mono"}, /* ABIST mode to add both amplifier halfs as stereo or one amplifier half as mono, */\
+ { 0x5104, "pulselengthbst"}, /* pulselength setting test input for boost converter , */\
+ { 0x5150, "ctrl_bypasslatchbst"}, /* bypass_latch in boost converter , */\
+ { 0x5160, "invertbst"}, /* invert pwmbst test signal , */\
+ { 0x5174, "pulselength"}, /* pulselength setting test input for amplifier , */\
+ { 0x51c0, "ctrl_bypasslatch"}, /* bypass_latch in boost convert , */\
+ { 0x51d0, "invertb"}, /* invert pwmb test signal , */\
+ { 0x51e0, "inverta"}, /* invert pwma test signal , */\
+ { 0x51f0, "ctrl_bypass_ctrlloop"}, /* bypass_ctrlloop bypasses the control loop of the amplifier, */\
+ { 0x5200, "ctrl_test_discrete"}, /* tbd for rdson testing , */\
+ { 0x5210, "ctrl_test_rdsona"}, /* tbd for rdson testing , */\
+ { 0x5220, "ctrl_test_rdsonb"}, /* tbd for rdson testing , */\
+ { 0x5230, "ctrl_test_rdsonbst"}, /* tbd for rdson testing , */\
+ { 0x5240, "ctrl_test_cvia"}, /* tbd for rdson testing , */\
+ { 0x5250, "ctrl_test_cvib"}, /* tbd for rdson testing , */\
+ { 0x5260, "ctrl_test_cvibst"}, /* tbd for rdson testing , */\
+ { 0x5290, "test_bypass_pwmdiscretea"}, /* for testing ( ABIST) , */\
+ { 0x52a0, "test_bypass_pwmdiscreteb"}, /* for testing ( ABIST) , */\
+ { 0x52b0, "ctrl_clipc_forcehigh"}, /* test signal for clipcontrol , */\
+ { 0x52c0, "ctrl_clipc_forcelow"}, /* test signal for clipcontrol , */\
+ { 0x52d0, "ctrl_test_sdelta"}, /* for testing ( ABIST) , */\
+ { 0x52e0, "ctrl_test_swhvp"}, /* for testing ( ABIST) , */\
+ { 0x52f0, "test_gain_reduction"}, /* test gain reduction , */\
+ { 0x5303, "ctrl_digimux_out_test1"}, /* Digimux TEST1 out , */\
+ { 0x5343, "ctrl_digimux_out_test2"}, /* Digimux TEST2 out. output flag_clipa_low depending on cntr_bypassclip setting, */\
+ { 0x5383, "ctrl_digimux_out_data1"}, /* Digimux DATA1 out (output flag_clipb_high depending on cntr_bypassclip setting), */\
+ { 0x53c3, "ctrl_digimux_out_data3"}, /* Digimux DATA3 out (output flag_clipx_x depending on cntr_bypassclip setting), */\
+ { 0x5400, "hs_mode"}, /* hs_mode, high speed mode I2C bus , */\
+ { 0x5412, "test_parametric_io"}, /* test_parametric_io for testing pads , */\
+ { 0x5440, "enbl_ringo"}, /* enbl_ringo, for test purpose to check with ringo , */\
+ { 0x5480, "ctrl_cliplevel"}, /* Clip level , */\
+ { 0x5491, "ctrl_anamux_sel"}, /* anamux selection , */\
+ { 0x54b0, "test_vdddsw_dio"}, /* to overrule the power switches for memory , */\
+ { 0x54c0, "ctrl_bypass_diosw_ovp"}, /* To disable the overvoltage protection of vddd_dio_sw, */\
+ { 0x54d0, "test_vddd_sw"}, /* test vdd sw , */\
+ { 0x54e0, "test_vddd_sw_comp"}, /* test vdd sw comp , */\
+ { 0x550e, "enbl_amp"}, /* enbl_amp for testing to enable all analoge blocks in amplifier, */\
+ { 0x55f0, "fr_fsp"}, /* extr free running clock mode for testing , */\
+ { 0x5600, "use_direct_ctrls"}, /* use_direct_ctrls, to overrule several functions direct for testing, */\
+ { 0x5610, "rst_datapath"}, /* rst_datapath, datapath reset , */\
+ { 0x5620, "rst_cgu"}, /* rst_cgu, cgu reset , */\
+ { 0x5637, "enbl_ref"}, /* for testing to enable all analoge blocks in references, */\
+ { 0x56b0, "enbl_engage"}, /* Enable output stage amplifier , */\
+ { 0x56c0, "use_direct_clk_ctrl"}, /* use_direct_clk_ctrl, to overrule several functions direct for testing, */\
+ { 0x56d0, "use_direct_pll_ctrl"}, /* use_direct_pll_ctrl, to overrule several functions direct for test, */\
+ { 0x56e0, "use_direct_ctrls_2"}, /* use_direct_sourseamp_ctrls, to overrule several functions direct for testing, */\
+ { 0x5707, "ctrl_anamux_out_test1"}, /* Anamux control , */\
+ { 0x5782, "ctrl_zero"}, /* Bandwith control feedbackloop , */\
+ { 0x57b0, "enbl_ldo_stress"}, /* LDO stress function frinch capacitors , */\
+ { 0x57c0, "ctrl_ocptest"}, /* ctrl_ocptest, deactivates the over current protection in the power stages of the amplifier. The ocp flag signals stay active., */\
+ { 0x57e0, "ctrl_otptest"}, /* otptest, test mode otp amplifier , */\
+ { 0x57f0, "ctrl_reverse"}, /* CTRL revers , */\
+ { 0x5802, "pll_mdec_msb"}, /* most significant bits pll_mdec , */\
+ { 0x5833, "pll_selr"}, /* pll_selr , */\
+ { 0x5874, "pll_selp"}, /* pll_selp , */\
+ { 0x58c3, "pll_seli"}, /* pll_seli , */\
+ { 0x5900, "pll_psel"}, /* pll_psel , */\
+ { 0x5910, "use_direct_pll_psel"}, /* use_direct_pll_psel , */\
+ { 0x5923, "nbck"}, /* NBCK , */\
+ { 0x5960, "auto_nbck"}, /* AUTO_NBCK , */\
+ { 0x5970, "pll_frm"}, /* pll_frm , */\
+ { 0x5980, "pll_directi"}, /* pll_directi , */\
+ { 0x5990, "pll_directo"}, /* pll_directo , */\
+ { 0x59a0, "enbl_PLL"}, /* enbl_PLL , */\
+ { 0x59b0, "sel_clkout"}, /* SEL_CLKOUT , */\
+ { 0x59e0, "fr_lost_clk"}, /* fr_lost_clk , */\
+ { 0x59f0, "pll_bypass"}, /* pll_bypass , */\
+ { 0x5a0f, "tsig_freq"}, /* tsig_freq, internal sinus test generator, frequency control, */\
+ { 0x5b02, "tsig_freq_msb"}, /* select internal sinus test generator, frequency control msb bits, */\
+ { 0x5b30, "inject_tsig"}, /* inject_tsig, control bit to switch to internal sinus test generator, */\
+ { 0x5b44, "ctrl_adc10_prog_sample"}, /* control ADC10 , */\
+ { 0x5c01, "pll_ndec_msb"}, /* most significant bits of pll_ndec , */\
+ { 0x5c2d, "pll_mdec"}, /* bits 13..0 of pll_mdec , */\
+ { 0x5d06, "pll_pdec"}, /* pll_pdec , */\
+ { 0x5d87, "pll_ndec"}, /* bits 7..0 of pll_ndec , */\
+ { 0x5e00, "pdm_ch_sel_reg"}, /* PDM channel selection , */\
+ { 0x5e10, "pdm_iis_rst_reg"}, /* PDM Interface reset , */\
+ { 0x5e20, "clk_src_sel_reg"}, /* WS Source Selection , */\
+ { 0x5e70, "pdm_resync_bypass"}, /* PDM resynchronization bypass , */\
+ { 0x6007, "MTP_key1"}, /* MTP Key1 , */\
+ { 0x6185, "mtp_ecc_tcin"}, /* Mtp_ecc_tcin , */\
+ { 0x6203, "mtp_man_address_in"}, /* address from i2cregs for writing one word single mtp, */\
+ { 0x6260, "mtp_ecc_eeb"}, /* enable code bit generation (active low!) , */\
+ { 0x6270, "mtp_ecc_ecb"}, /* enable correction signal (active low!) , */\
+ { 0x6280, "man_copy_mtp_to_iic"}, /* start copying single word from mtp to i2cregs_mtp , */\
+ { 0x6290, "man_copy_iic_to_mtp"}, /* start copying single word from i2cregs_mtp to mtp [Key 1 protected], */\
+ { 0x62a0, "auto_copy_mtp_to_iic"}, /* start copying all the data from mtp to i2cregs_mtp, */\
+ { 0x62b0, "auto_copy_iic_to_mtp"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x62d2, "mtp_speed_mode"}, /* Speed mode , */\
+ { 0x6340, "mtp_dircet_enable"}, /* mtp_direct_enable (key1 protected) , */\
+ { 0x6350, "mtp_direct_wr"}, /* mtp_direct_wr (key1 protected) direct value for mtp pin wr. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6360, "mtp_direct_rd"}, /* mtp_direct_rd (key1 protected) direct value for mtp pin rd. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6370, "mtp_direct_rst"}, /* mtp_direct_rst (key1 protected) direct value for mtp pin rst. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6380, "mtp_direct_ers"}, /* mtp_direct_ers (key1 protected) direct value for mtp pin ers. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6390, "mtp_direct_prg"}, /* mtp_direct_prg (key1 protected) direct value for mtp pin prg. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x63a0, "mtp_direct_epp"}, /* mtp_direct_epp (key1 protected) direct value for mtp pin epp. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x63b4, "mtp_direct_test"}, /* mtp_direct_test (key1 protected) , */\
+ { 0x640f, "mtp_man_data_in"}, /* single wordt be written to MTP (manual copy) , */\
+ { 0x7000, "cf_rst_dsp"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "cf_dmem"}, /* Target memory for access , */\
+ { 0x7030, "cf_aif"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "cf_int"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "cf_req"}, /* request for access (8 channels) , */\
+ { 0x710f, "cf_madd"}, /* memory-address to be accessed , */\
+ { 0x720f, "cf_mema"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "cf_err"}, /* cf error Flags , */\
+ { 0x7387, "cf_ack"}, /* acknowledge of requests (8 channels")" , */\
+ { 0x8000, "calibration_onetime"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "calibr_ron_done"}, /* (key2 protected) calibration of Ron has been executed, */\
+ { 0x8105, "calibr_vout_offset"}, /* calibr_vout_offset (DCDCoffset) 2's compliment (key1 protected), */\
+ { 0x8163, "calibr_delta_gain"}, /* delta gain for vamp (alpha) 2's compliment (key1 protected), */\
+ { 0x81a5, "calibr_offs_amp"}, /* offset for vamp (Ampoffset) 2's compliment (key1 protected), */\
+ { 0x8207, "calibr_gain_cs"}, /* gain current sense (Imeasalpha) 2's compliment (key1 protected), */\
+ { 0x8284, "calibr_temp_offset"}, /* temperature offset 2's compliment (key1 protected), */\
+ { 0x82d2, "calibr_temp_gain"}, /* temperature gain 2's compliment (key1 protected) , */\
+ { 0x830f, "calibr_ron"}, /* Ron resistance of coil (key1 protected) , */\
+ { 0x8406, "ctrl_offset_a"}, /* Offset of amplifier level shifter , */\
+ { 0x8486, "ctrl_offset_b"}, /* Offset of amplifier level shifter , */\
+ { 0x850f, "type_bits_HW"}, /* HW Bits , */\
+ { 0x860f, "type_bits1_SW"}, /* MTP-control SW1 , */\
+ { 0x870f, "type_bits2_SW"}, /* MTP-control SW2 , */\
+ { 0x8a0f, "production_data1"}, /* (key1 protected) , */\
+ { 0x8b0f, "production_data2"}, /* (key1 protected) , */\
+ { 0x8c0f, "production_data3"}, /* (key1 protected) , */\
+ { 0x8d0f, "production_data4"}, /* (key1 protected) , */\
+ { 0x8e0f, "production_data5"}, /* (key1 protected) , */\
+ { 0x8f0f, "production_data6"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+
+#endif /* TFA_INC_TFA9891_TFAFIELDNAMES_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames.h
new file mode 100644
index 00000000000..afdf6f5e7e0
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames.h
@@ -0,0 +1,1079 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9894_tfaFieldnames_N1Last.h
+ * This file was generated automatically on 09/28/18 at 11:24:56.
+ * Source file: TFA9894_N1A1_I2C_RegisterMap.xlsx
+ */
+
+#ifndef _TFA9894_TFAFIELDNAMES_H
+#define _TFA9894_TFAFIELDNAMES_H
+
+
+#define TFA9894_I2CVERSION 17.0
+
+typedef enum Tfa9894BfEnumList {
+ TFA9894_BF_PWDN = 0x0000, /*!< Powerdown control */
+ TFA9894_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9894_BF_CFE = 0x0020, /*!< Enable CoolFlux DSP */
+ TFA9894_BF_AMPE = 0x0030, /*!< Enable Amplifier */
+ TFA9894_BF_DCA = 0x0040, /*!< Enable DCDC Boost converter */
+ TFA9894_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA9894_BF_AMPC = 0x0060, /*!< CoolFlux control over amplifier */
+ TFA9894_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9894_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9894_BF_BYPOCP= 0x00a0, /*!< Bypass OCP */
+ TFA9894_BF_TSTOCP= 0x00b0, /*!< OCP testing control */
+ TFA9894_BF_BSSS = 0x00c0, /*!< Vbat protection steepness */
+ TFA9894_BF_HPFBYP= 0x00d0, /*!< Bypass High Pass Filter */
+ TFA9894_BF_DPSA = 0x00e0, /*!< Enable DPSA */
+ TFA9894_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9894_BF_MANSCONF= 0x0120, /*!< Device I2C settings configured */
+ TFA9894_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA9894_BF_MANROBOD= 0x0140, /*!< Reaction on BOD */
+ TFA9894_BF_BODE = 0x0150, /*!< Enable BOD (only in direct control mode) */
+ TFA9894_BF_BODHYS= 0x0160, /*!< Enable Hysteresis of BOD */
+ TFA9894_BF_BODFILT= 0x0171, /*!< BOD filter */
+ TFA9894_BF_BODTHLVL= 0x0191, /*!< BOD threshold */
+ TFA9894_BF_MUTETO= 0x01b0, /*!< Time out SB mute sequence */
+ TFA9894_BF_MANWDE= 0x01c0, /*!< Watchdog enable */
+ TFA9894_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9894_BF_FAIMVBGOVRRL= 0x01f0, /*!< Overrule the enabling of VBG for faim erase/write access */
+ TFA9894_BF_AUDFS = 0x0203, /*!< Audio sample rate Fs */
+ TFA9894_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9894_BF_FRACTDEL= 0x0255, /*!< Current sense fractional delay */
+ TFA9894_BF_TDMPRES= 0x02b1, /*!< Control for HW manager */
+ TFA9894_BF_AMPOCRT= 0x02d2, /*!< Amplifier on-off criteria for shutdown */
+ TFA9894_BF_REV = 0x030f, /*!< Revision info */
+ TFA9894_BF_REFCKEXT= 0x0401, /*!< PLL external reference clock */
+ TFA9894_BF_REFCKSEL= 0x0420, /*!< PLL internal reference clock */
+ TFA9894_BF_MCLKSEL= 0x0432, /*!< Master Clock Selection */
+ TFA9894_BF_MANAOOSC= 0x0460, /*!< Internal OSC1M off at PWDN */
+ TFA9894_BF_ACKCLDDIS= 0x0470, /*!< Automatic PLL reference clock selection for cold start */
+ TFA9894_BF_SPKSSEN= 0x0510, /*!< Enable speaker sub-system */
+ TFA9894_BF_MTPSSEN= 0x0520, /*!< Enable FAIM sub-system */
+ TFA9894_BF_WDTCLKEN= 0x0530, /*!< Enable Coolflux watchdog clock */
+ TFA9894_BF_VDDS = 0x1000, /*!< POR */
+ TFA9894_BF_PLLS = 0x1010, /*!< PLL Lock */
+ TFA9894_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9894_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9894_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9894_BF_OCDS = 0x1050, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9894_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9894_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9894_BF_NOCLK = 0x1080, /*!< Lost clock */
+ TFA9894_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA9894_BF_WDS = 0x10a0, /*!< Watchdog */
+ TFA9894_BF_SWS = 0x10b0, /*!< Amplifier engage */
+ TFA9894_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9894_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9894_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9894_BF_BODNOK= 0x10f0, /*!< BOD Flag - VDD NOT OK */
+ TFA9894_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9894_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9894_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9894_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9894_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9894_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9894_BF_SPKS = 0x1170, /*!< Speaker status */
+ TFA9894_BF_CLKOOR= 0x1180, /*!< External clock status */
+ TFA9894_BF_MANALARM= 0x1190, /*!< Alarm state */
+ TFA9894_BF_TDMERR= 0x11a0, /*!< TDM error */
+ TFA9894_BF_TDMLUTER= 0x11b0, /*!< TDM lookup table error */
+ TFA9894_BF_OCPOAP= 0x1200, /*!< OCPOK pmos A */
+ TFA9894_BF_OCPOAN= 0x1210, /*!< OCPOK nmos A */
+ TFA9894_BF_OCPOBP= 0x1220, /*!< OCPOK pmos B */
+ TFA9894_BF_OCPOBN= 0x1230, /*!< OCPOK nmos B */
+ TFA9894_BF_CLIPS = 0x1240, /*!< Amplifier clipping */
+ TFA9894_BF_MANMUTE= 0x1250, /*!< Audio mute sequence */
+ TFA9894_BF_MANOPER= 0x1260, /*!< Device in Operating state */
+ TFA9894_BF_LP1 = 0x1270, /*!< Low power MODE1 detection */
+ TFA9894_BF_LA = 0x1280, /*!< Low amplitude detection */
+ TFA9894_BF_VDDPH = 0x1290, /*!< VDDP greater than VBAT flag */
+ TFA9894_BF_TDMSTAT= 0x1402, /*!< TDM Status bits */
+ TFA9894_BF_MANSTATE= 0x1433, /*!< Device Manager status */
+ TFA9894_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9894_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9894_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9894_BF_VDDPS = 0x1709, /*!< IC VDDP voltage (1023*VDDP/13V) */
+ TFA9894_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9894_BF_TDMSPKE= 0x2010, /*!< Control audio tdm channel in sink0 */
+ TFA9894_BF_TDMDCE= 0x2020, /*!< Control audio tdm channel in sink1 */
+ TFA9894_BF_TDMCSE= 0x2030, /*!< Source 0 enable */
+ TFA9894_BF_TDMVSE= 0x2040, /*!< Source 1 enable */
+ TFA9894_BF_TDMCFE= 0x2050, /*!< Source 2 enable */
+ TFA9894_BF_TDMCF2E= 0x2060, /*!< Source 3 enable */
+ TFA9894_BF_TDMCLINV= 0x2070, /*!< Reception data to BCK clock */
+ TFA9894_BF_TDMFSPOL= 0x2080, /*!< FS polarity */
+ TFA9894_BF_TDMDEL= 0x2090, /*!< Data delay to FS */
+ TFA9894_BF_TDMADJ= 0x20a0, /*!< Data adjustment */
+ TFA9894_BF_TDMOOMP= 0x20b1, /*!< Received audio compression */
+ TFA9894_BF_TDMNBCK= 0x2103, /*!< TDM NBCK - Bit clock to FS ratio */
+ TFA9894_BF_TDMFSLN= 0x2143, /*!< FS length (master mode only) */
+ TFA9894_BF_TDMSLOTS= 0x2183, /*!< N-slots in Frame */
+ TFA9894_BF_TDMTXDFO= 0x21c1, /*!< Format unused bits */
+ TFA9894_BF_TDMTXUS0= 0x21e1, /*!< Format unused slots DATAO */
+ TFA9894_BF_TDMSLLN= 0x2204, /*!< N-bits in slot */
+ TFA9894_BF_TDMBRMG= 0x2254, /*!< N-bits remaining */
+ TFA9894_BF_TDMSSIZE= 0x22a4, /*!< Sample size per slot */
+ TFA9894_BF_TDMSPKS= 0x2303, /*!< TDM slot for sink 0 */
+ TFA9894_BF_TDMDCS= 0x2343, /*!< TDM slot for sink 1 */
+ TFA9894_BF_TDMCFSEL= 0x2381, /*!< TDM Source 2 data selection */
+ TFA9894_BF_TDMCF2SEL= 0x23a1, /*!< TDM Source 3 data selection */
+ TFA9894_BF_TDMCSS= 0x2403, /*!< Slot Position of source 0 data */
+ TFA9894_BF_TDMVSS= 0x2443, /*!< Slot Position of source 1 data */
+ TFA9894_BF_TDMCFS= 0x2483, /*!< Slot Position of source 2 data */
+ TFA9894_BF_TDMCF2S= 0x24c3, /*!< Slot Position of source 3 data */
+ TFA9894_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9894_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9894_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9894_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9894_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9894_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9894_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9894_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9894_BF_ISTCFMER= 0x4080, /*!< Status cfma error */
+ TFA9894_BF_ISTCFMAC= 0x4090, /*!< Status cfma ack */
+ TFA9894_BF_ISTSPKS= 0x40a0, /*!< Status coolflux speaker error */
+ TFA9894_BF_ISTACS= 0x40b0, /*!< Status cold started */
+ TFA9894_BF_ISTWDS= 0x40c0, /*!< Status watchdog reset */
+ TFA9894_BF_ISTBODNOK= 0x40d0, /*!< Status brown out detect */
+ TFA9894_BF_ISTLP1= 0x40e0, /*!< Status low power mode1 detect */
+ TFA9894_BF_ISTCLKOOR= 0x40f0, /*!< Status clock out of range */
+ TFA9894_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9894_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9894_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9894_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9894_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9894_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9894_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9894_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9894_BF_ICLCFMER= 0x4480, /*!< Clear cfma err */
+ TFA9894_BF_ICLCFMAC= 0x4490, /*!< Clear cfma ack */
+ TFA9894_BF_ICLSPKS= 0x44a0, /*!< Clear coolflux speaker error */
+ TFA9894_BF_ICLACS= 0x44b0, /*!< Clear cold started */
+ TFA9894_BF_ICLWDS= 0x44c0, /*!< Clear watchdog reset */
+ TFA9894_BF_ICLBODNOK= 0x44d0, /*!< Clear brown out detect */
+ TFA9894_BF_ICLLP1= 0x44e0, /*!< Clear low power mode1 detect */
+ TFA9894_BF_ICLCLKOOR= 0x44f0, /*!< Clear clock out of range */
+ TFA9894_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9894_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9894_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9894_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9894_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9894_BF_IEMANALARM= 0x4850, /*!< Enable Manager Alarm state */
+ TFA9894_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9894_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9894_BF_IECFMER= 0x4880, /*!< Enable cfma err */
+ TFA9894_BF_IECFMAC= 0x4890, /*!< Enable cfma ack */
+ TFA9894_BF_IESPKS= 0x48a0, /*!< Enable coolflux speaker error */
+ TFA9894_BF_IEACS = 0x48b0, /*!< Enable cold started */
+ TFA9894_BF_IEWDS = 0x48c0, /*!< Enable watchdog reset */
+ TFA9894_BF_IEBODNOK= 0x48d0, /*!< Enable brown out detect */
+ TFA9894_BF_IELP1 = 0x48e0, /*!< Enable low power mode1 detect */
+ TFA9894_BF_IECLKOOR= 0x48f0, /*!< Enable clock out of range */
+ TFA9894_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9894_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9894_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9894_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9894_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9894_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9894_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9894_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9894_BF_IPOCFMER= 0x4c80, /*!< Polarity cfma err */
+ TFA9894_BF_IPOCFMAC= 0x4c90, /*!< Polarity cfma ack */
+ TFA9894_BF_IPOSPKS= 0x4ca0, /*!< Polarity coolflux speaker error */
+ TFA9894_BF_IPOACS= 0x4cb0, /*!< Polarity cold started */
+ TFA9894_BF_IPOWDS= 0x4cc0, /*!< Polarity watchdog reset */
+ TFA9894_BF_IPOBODNOK= 0x4cd0, /*!< Polarity brown out detect */
+ TFA9894_BF_IPOLP1= 0x4ce0, /*!< Polarity low power mode1 detect */
+ TFA9894_BF_IPOCLKOOR= 0x4cf0, /*!< Polarity clock out of range */
+ TFA9894_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9894_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9894_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9894_BF_BSSRR = 0x5082, /*!< Battery safeguard release time */
+ TFA9894_BF_BSSHY = 0x50b1, /*!< Battery Safeguard hysteresis */
+ TFA9894_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9894_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA9894_BF_CFSM = 0x5130, /*!< Coolflux firmware soft mute control */
+ TFA9894_BF_VOL = 0x5187, /*!< CF firmware volume control */
+ TFA9894_BF_CLIPCTRL= 0x5202, /*!< Clip control setting */
+ TFA9894_BF_SLOPEE= 0x5230, /*!< Enables slope control */
+ TFA9894_BF_SLOPESET= 0x5240, /*!< Slope speed setting (binary coded) */
+ TFA9894_BF_AMPGAIN= 0x5287, /*!< Amplifier gain */
+ TFA9894_BF_TDMDCG= 0x5703, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9894_BF_TDMSPKG= 0x5743, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9894_BF_DCINSEL= 0x5781, /*!< VAMP_OUT2 input selection */
+ TFA9894_BF_LNMODE= 0x5881, /*!< Low noise gain mode control */
+ TFA9894_BF_LPM1MODE= 0x5ac1, /*!< Low power mode control */
+ TFA9894_BF_TDMSRCMAP= 0x5d02, /*!< TDM source mapping */
+ TFA9894_BF_TDMSRCAS= 0x5d31, /*!< Sensed value A */
+ TFA9894_BF_TDMSRCBS= 0x5d51, /*!< Sensed value B */
+ TFA9894_BF_TDMSRCACLIP= 0x5d71, /*!< Clip information (analog /digital) for source0 */
+ TFA9894_BF_TDMSRCBCLIP= 0x5d91, /*!< Clip information (analog /digital) for source1 */
+ TFA9894_BF_DELCURCOMP= 0x6102, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9894_BF_SIGCURCOMP= 0x6130, /*!< Polarity of compensation for current sense */
+ TFA9894_BF_ENCURCOMP= 0x6140, /*!< Enable current sense compensation */
+ TFA9894_BF_LVLCLPPWM= 0x6152, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9894_BF_DCVOF = 0x7005, /*!< First Boost Voltage Level */
+ TFA9894_BF_DCVOS = 0x7065, /*!< Second Boost Voltage Level */
+ TFA9894_BF_DCMCC = 0x70c3, /*!< Max Coil Current */
+ TFA9894_BF_DCCV = 0x7101, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9894_BF_DCIE = 0x7120, /*!< Adaptive boost mode */
+ TFA9894_BF_DCSR = 0x7130, /*!< Soft ramp up/down */
+ TFA9894_BF_DCDIS = 0x7140, /*!< DCDC on/off */
+ TFA9894_BF_DCPWM = 0x7150, /*!< DCDC PWM only mode */
+ TFA9894_BF_DCTRACK= 0x7160, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_DCENVSEL= 0x7170, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_DCTRIP= 0x7204, /*!< 1st adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894_BF_DCTRIP2= 0x7254, /*!< 2nd adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894_BF_DCTRIPT= 0x72a4, /*!< Track adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_DCTRIPHYSTE= 0x72f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9894_BF_DCHOLD= 0x7304, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_RST = 0x9000, /*!< Reset for Coolflux DSP */
+ TFA9894_BF_DMEM = 0x9011, /*!< Target memory for CFMA using I2C interface */
+ TFA9894_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA9894_BF_CFINT = 0x9040, /*!< Coolflux Interrupt - auto clear */
+ TFA9894_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA9894_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA9894_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA9894_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA9894_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA9894_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA9894_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA9894_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA9894_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA9894_BF_MADD = 0x910f, /*!< CF memory address */
+ TFA9894_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA9894_BF_ERR = 0x9307, /*!< CF error flags */
+ TFA9894_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA9894_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA9894_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA9894_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA9894_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA9894_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA9894_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA9894_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA9894_BF_MTPK = 0xa107, /*!< KEY2 to access KEY2 protected registers, customer key */
+ TFA9894_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9894_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9894_BF_CMTPI = 0xa350, /*!< Start copying all the data from mtp to I2C mtp registers - auto clear */
+ TFA9894_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp - auto clear */
+ TFA9894_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9894_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9894_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9894_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9894_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9894_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9894_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9894_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9894_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9894_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9894_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9894_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9894_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9894BfEnumList_t;
+#define TFA9894_NAMETABLE static tfaBfName_t Tfa9894DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown control , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "AMPE"}, /* Enable Amplifier , */\
+ { 0x40, "DCA"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xa0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xb0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xc0, "BSSS"}, /* Vbat protection steepness , */\
+ { 0xd0, "HPFBYP"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "DPSA"}, /* Enable DPSA , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* Device I2C settings configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x150, "BODE"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "BODFILT"}, /* BOD filter , */\
+ { 0x191, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1b0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "MANWDE"}, /* Watchdog enable , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "FAIMVBGOVRRL"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "AUDFS"}, /* Audio sample rate Fs , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* Current sense fractional delay , */\
+ { 0x2b1, "TDMPRES"}, /* Control for HW manager , */\
+ { 0x2d2, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external reference clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal reference clock , */\
+ { 0x432, "MCLKSEL"}, /* Master Clock Selection , */\
+ { 0x460, "MANAOOSC"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "ACKCLDDIS"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x510, "SPKSSEN"}, /* Enable speaker sub-system , */\
+ { 0x520, "MTPSSEN"}, /* Enable FAIM sub-system , */\
+ { 0x530, "WDTCLKEN"}, /* Enable Coolflux watchdog clock , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL Lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "WDS"}, /* Watchdog , */\
+ { 0x10b0, "SWS"}, /* Amplifier engage , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "SPKS"}, /* Speaker status , */\
+ { 0x1180, "CLKOOR"}, /* External clock status , */\
+ { 0x1190, "MANALARM"}, /* Alarm state , */\
+ { 0x11a0, "TDMERR"}, /* TDM error , */\
+ { 0x11b0, "TDMLUTER"}, /* TDM lookup table error , */\
+ { 0x1200, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1210, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1220, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1230, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1240, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1250, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x1260, "MANOPER"}, /* Device in Operating state , */\
+ { 0x1270, "LP1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "LA"}, /* Low amplitude detection , */\
+ { 0x1290, "VDDPH"}, /* VDDP greater than VBAT flag , */\
+ { 0x1402, "TDMSTAT"}, /* TDM Status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device Manager status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2010, "TDMSPKE"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "TDMDCE"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "TDMCSE"}, /* Source 0 enable , */\
+ { 0x2040, "TDMVSE"}, /* Source 1 enable , */\
+ { 0x2050, "TDMCFE"}, /* Source 2 enable , */\
+ { 0x2060, "TDMCF2E"}, /* Source 3 enable , */\
+ { 0x2070, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2080, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2090, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x20a0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x20b1, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2103, "TDMNBCK"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x2183, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x21c1, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x21e1, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2204, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2254, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x22a4, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2303, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "TDMCFSEL"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "TDMCF2SEL"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "TDMCSS"}, /* Slot Position of source 0 data , */\
+ { 0x2443, "TDMVSS"}, /* Slot Position of source 1 data , */\
+ { 0x2483, "TDMCFS"}, /* Slot Position of source 2 data , */\
+ { 0x24c3, "TDMCF2S"}, /* Slot Position of source 3 data , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x4090, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x40a0, "ISTSPKS"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "ISTACS"}, /* Status cold started , */\
+ { 0x40c0, "ISTWDS"}, /* Status watchdog reset , */\
+ { 0x40d0, "ISTBODNOK"}, /* Status brown out detect , */\
+ { 0x40e0, "ISTLP1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "ISTCLKOOR"}, /* Status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x4490, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x44a0, "ICLSPKS"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "ICLACS"}, /* Clear cold started , */\
+ { 0x44c0, "ICLWDS"}, /* Clear watchdog reset , */\
+ { 0x44d0, "ICLBODNOK"}, /* Clear brown out detect , */\
+ { 0x44e0, "ICLLP1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "ICLCLKOOR"}, /* Clear clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IECFMER"}, /* Enable cfma err , */\
+ { 0x4890, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x48a0, "IESPKS"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "IEACS"}, /* Enable cold started , */\
+ { 0x48c0, "IEWDS"}, /* Enable watchdog reset , */\
+ { 0x48d0, "IEBODNOK"}, /* Enable brown out detect , */\
+ { 0x48e0, "IELP1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "IECLKOOR"}, /* Enable clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4c90, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "IPOSPKS"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4cc0, "IPOWDS"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "IPOBODNOK"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "IPOLP1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "IPOCLKOOR"}, /* Polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery safeguard release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery Safeguard hysteresis , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5130, "CFSM"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "VOL"}, /* CF firmware volume control , */\
+ { 0x5202, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5230, "SLOPEE"}, /* Enables slope control , */\
+ { 0x5240, "SLOPESET"}, /* Slope speed setting (binary coded) , */\
+ { 0x5287, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x5703, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "DCINSEL"}, /* VAMP_OUT2 input selection , */\
+ { 0x5881, "LNMODE"}, /* Low noise gain mode control , */\
+ { 0x5ac1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x5d02, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x5d31, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x5d51, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x5d71, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6102, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6152, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "DCVOF"}, /* First Boost Voltage Level , */\
+ { 0x7065, "DCVOS"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "DCMCC"}, /* Max Coil Current , */\
+ { 0x7101, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7130, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7140, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7150, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7160, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "DCENVSEL"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7204, "DCTRIP"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "DCTRIP2"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "DCTRIPT"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x9000, "RST"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "DMEM"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* CF memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* CF error flags , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa350, "CMTPI"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9894_BITNAMETABLE static tfaBfName_t Tfa9894BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown control , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xa0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xb0, "test_ocp"}, /* OCP testing control , */\
+ { 0xc0, "batsense_steepness"}, /* Vbat protection steepness , */\
+ { 0xd0, "bypass_hp"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* Device I2C settings configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x150, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "bod_delay_set"}, /* BOD filter , */\
+ { 0x191, "bod_lvl_set"}, /* BOD threshold , */\
+ { 0x1b0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "man_enbl_watchdog"}, /* Watchdog enable , */\
+ { 0x1d0, "disable_engage"}, /* Disable Engage , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "faim_enable_vbg"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "audio_fs"}, /* Audio sample rate Fs , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* Current sense fractional delay , */\
+ { 0x2b1, "use_tdm_presence"}, /* Control for HW manager , */\
+ { 0x2d2, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external reference clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal reference clock , */\
+ { 0x432, "mclk_sel"}, /* Master Clock Selection , */\
+ { 0x460, "enbl_osc1m_auto_off"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "disable_auto_sel_refclk"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker sub-system , */\
+ { 0x520, "enbl_faim_ss"}, /* Enable FAIM sub-system , */\
+ { 0x530, "enbl_wdt_clk"}, /* Enable Coolflux watchdog clock , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to hidden register. (0x5A6B/23147 default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL Lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10b0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_cf_speakererror"}, /* Speaker status , */\
+ { 0x1180, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1190, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x11a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x11b0, "flag_tdm_lut_error"}, /* TDM lookup table error , */\
+ { 0x1200, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1210, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1220, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1230, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1240, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1250, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x1260, "flag_man_operating_state"}, /* Device in Operating state , */\
+ { 0x1270, "flag_lp_detect_mode1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x1290, "flag_vddp_gt_vbat"}, /* VDDP greater than VBAT flag , */\
+ { 0x1402, "tdm_status"}, /* TDM Status bits , */\
+ { 0x1433, "man_state"}, /* Device Manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2010, "tdm_sink0_enable"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "tdm_sink1_enable"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "tdm_source0_enable"}, /* Source 0 enable , */\
+ { 0x2040, "tdm_source1_enable"}, /* Source 1 enable , */\
+ { 0x2050, "tdm_source2_enable"}, /* Source 2 enable , */\
+ { 0x2060, "tdm_source3_enable"}, /* Source 3 enable , */\
+ { 0x2070, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2080, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2090, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x20a0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x20b1, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2103, "tdm_nbck"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x2183, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x21c1, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x21e1, "tdm_txdata_format_unused_slot"}, /* Format unused slots DATAO , */\
+ { 0x2204, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2254, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x22a4, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2303, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "tdm_source2_sel"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "tdm_source3_sel"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "tdm_source0_slot"}, /* Slot Position of source 0 data , */\
+ { 0x2443, "tdm_source1_slot"}, /* Slot Position of source 1 data , */\
+ { 0x2483, "tdm_source2_slot"}, /* Slot Position of source 2 data , */\
+ { 0x24c3, "tdm_source3_slot"}, /* Slot Position of source 3 data , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x4090, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x40a0, "int_out_flag_cf_speakererror"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "int_out_flag_cold_started"}, /* Status cold started , */\
+ { 0x40c0, "int_out_flag_watchdog_reset"}, /* Status watchdog reset , */\
+ { 0x40d0, "int_out_flag_bod_vddd_nok"}, /* Status brown out detect , */\
+ { 0x40e0, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "int_out_flag_clk_out_of_range"}, /* Status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x4490, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x44a0, "int_in_flag_cf_speakererror"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44c0, "int_in_flag_watchdog_reset"}, /* Clear watchdog reset , */\
+ { 0x44d0, "int_in_flag_bod_vddd_nok"}, /* Clear brown out detect , */\
+ { 0x44e0, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "int_in_flag_clk_out_of_range"}, /* Clear clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x4890, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x48a0, "int_enable_flag_cf_speakererror"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48c0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog reset , */\
+ { 0x48d0, "int_enable_flag_bod_vddd_nok"}, /* Enable brown out detect , */\
+ { 0x48e0, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "int_enable_flag_clk_out_of_range"}, /* Enable clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4c90, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "int_polarity_flag_cf_speakererror"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4cc0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "int_polarity_flag_clk_out_of_range"}, /* Polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery safeguard release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5130, "cf_mute"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "cf_volume"}, /* CF firmware volume control , */\
+ { 0x5202, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5230, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x5240, "ctrl_slope"}, /* Slope speed setting (binary coded) , */\
+ { 0x5287, "gain"}, /* Amplifier gain , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for battery safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5370, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5380, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5390, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x53a3, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5452, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x550a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x55b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x55c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5600, "pwm_shape"}, /* PWM shape , */\
+ { 0x5614, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5660, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x5670, "reclock_voltsense"}, /* Reclock the voltage sense PWM signal , */\
+ { 0x5680, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5690, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x56a1, "enbl_odd_up_even_down"}, /* Control for PWM reference sawtooth generartion , */\
+ { 0x5703, "ctrl_att_dcdc"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "ctrl_att_spkr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "vamp_sel2"}, /* VAMP_OUT2 input selection , */\
+ { 0x5805, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x5861, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x5881, "lownoisegain_mode"}, /* Low noise gain mode control , */\
+ { 0x5905, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x5965, "hold_time"}, /* Low noise mode hold time before entering into low noise mode, */\
+ { 0x5a05, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x5a65, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x5ac1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x5b05, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x5b65, "lpm1_hold_time"}, /* Low power mode hold time before entering into low power mode, */\
+ { 0x5bc0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x5c00, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x5c13, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x5c50, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x5c61, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x5d02, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x5d31, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x5d51, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x5d71, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x5e02, "rst_min_vbat_delay"}, /* Delay for reseting the min_vbat value inside HW Clipper (number of Fs pulses), */\
+ { 0x5e30, "rst_min_vbat_sel"}, /* Control for selecting reset signal for min_bat , */\
+ { 0x5f00, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5f12, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x5f42, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x5f78, "spare_out"}, /* Spare out register , */\
+ { 0x600f, "spare_in"}, /* Spare IN , */\
+ { 0x6102, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6152, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "frst_boost_voltage"}, /* First Boost Voltage Level , */\
+ { 0x7065, "scnd_boost_voltage"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "boost_cur"}, /* Max Coil Current , */\
+ { 0x7101, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7130, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7140, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7150, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7160, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7180, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7204, "boost_trip_lvl_1st"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "boost_trip_lvl_2nd"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "boost_trip_lvl_track"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x7350, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x7361, "dcdc_ctrl_maxzercnt"}, /* Number of zero current flags to count before going to pfm mode, */\
+ { 0x7386, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x73f0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x7404, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7451, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7474, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x74c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x74e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x74f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7500, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7510, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7520, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7530, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7540, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7550, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7560, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7570, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7580, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x7595, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7600, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7611, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7631, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7650, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7660, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8040, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8050, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8060, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8105, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP) * signal, */\
+ { 0x8164, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x81b0, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x81c0, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x81d0, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x81e0, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x81f0, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8200, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8210, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8220, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8231, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8250, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8263, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x82a0, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x82b4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8300, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8310, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8320, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8330, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8340, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8350, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8364, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8800, "ctrl_vs_igen_supply"}, /* Control for selecting supply for VS current generator, */\
+ { 0x8810, "ctrl_vs_force_div2"}, /* Select input resistive divider gain , */\
+ { 0x8820, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8901, "volsense_pwm_sel"}, /* Voltage sense source selection control , */\
+ { 0x8920, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8930, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8940, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8950, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8960, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8970, "vs_classd_tran_skip"}, /* Skip voltage sense connection during a classD amplifier transition, */\
+ { 0x8987, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8a00, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8a10, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8a20, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "enbl_vs_adc"}, /* Enable voltage sense ADC , */\
+ { 0x8aa0, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8ab0, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8ac0, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8ad0, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8ae0, "enbl_vs_ldo"}, /* Enable voltage sense LDO , */\
+ { 0x8af0, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "cf_dmem"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* CF memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* CF error flags , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0xa007, "mtpkey1"}, /* KEY1 To access KEY1 protected registers 0x5A/90d (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from MTP to I2C mtp register - auto clear, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp - auto clear, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the FaIM controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the FaIM are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the FaIM are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb000, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb010, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb020, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb030, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb040, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb050, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb060, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb070, "disable_main_ctrl_change_prot"}, /* Disable main control change protection , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* Enable ABIST with FFT on Coolflux DSP , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc530, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc540, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc550, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc560, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc570, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc583, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc5c0, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc607, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO , */\
+ { 0xc687, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT , */\
+ { 0xc707, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 , */\
+ { 0xc800, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xc810, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xc820, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xc830, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xc844, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xc894, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xc903, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xc943, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xca05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xca64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcab3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcaf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xcb09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcba0, "pll_mdec_msb"}, /* MSB of PLL_mdec - I2C direct PLL control mode only, */\
+ { 0xcbb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcbc0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xcbd0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcbe0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcbf0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcc0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xcd06, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xce0f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xcf02, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xcf33, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd000, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd011, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd032, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd064, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd0b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd0c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd109, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd201, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd221, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd241, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd301, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd321, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd340, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xd407, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd480, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd491, "sel_wdt_clk"}, /* Watch dog clock divider settings , */\
+ { 0xd4b0, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd500, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd510, "gainatt_feedback"}, /* Gainatt feedback to tdm , */\
+ { 0xd522, "test_parametric_io"}, /* Test IO parametric , */\
+ { 0xd550, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0xd561, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd580, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd593, "test_spare_out2"}, /* Test spare out 2 , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs"}, /* Voltage sense gain , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "mtpdata4"}, /* MTP4 data , */\
+ { 0xf50f, "calibr_R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xf60f, "mtpdata6"}, /* MTP6 data , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable functionality of dcdcoff_mode bit , */\
+ { 0xf910, "mtp_lock_enbl_coolflux"}, /* Disable functionality of enbl_coolflux bit , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf940, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xf950, "mtp_gate_cgu_clock_for_test"}, /* CGU test clock control , */\
+ { 0xf987, "type_bits_fw"}, /* MTP control for firmware features - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9894_irq {
+ tfa9894_irq_max = -1,
+ tfa9894_irq_all = -1 /* all irqs */};
+
+#define TFA9894_IRQ_NAMETABLE static tfaIrqName_t Tfa9894IrqNames[]= {\
+};
+#endif /* _TFA9894_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames_N2.h b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames_N2.h
new file mode 100644
index 00000000000..ff9ed8a5338
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames_N2.h
@@ -0,0 +1,1130 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9894_tfaFieldnames_N2.h
+ * This file was generated automatically on 09/28/18 at 12:19:41.
+ * Source file: TFA9894_N2A1_I2C_RegisterMap.xlsx
+ */
+
+#ifndef _TFA9894_TFAFIELDNAMES_N2_H
+#define _TFA9894_TFAFIELDNAMES_N2_H
+
+
+#define TFA9894N2_I2CVERSION 25.0
+
+typedef enum Tfa9894N2BfEnumList {
+ TFA9894N2_BF_PWDN = 0x0000, /*!< Powerdown control */
+ TFA9894N2_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9894N2_BF_CFE = 0x0020, /*!< Enable CoolFlux DSP */
+ TFA9894N2_BF_AMPE = 0x0030, /*!< Enable Amplifier */
+ TFA9894N2_BF_DCA = 0x0040, /*!< Enable DCDC Boost converter */
+ TFA9894N2_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA9894N2_BF_AMPC = 0x0060, /*!< CoolFlux control over amplifier */
+ TFA9894N2_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9894N2_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9894N2_BF_BYPOCP= 0x00a0, /*!< Bypass OCP */
+ TFA9894N2_BF_TSTOCP= 0x00b0, /*!< OCP testing control */
+ TFA9894N2_BF_BSSS = 0x00c0, /*!< Vbat protection steepness */
+ TFA9894N2_BF_HPFBYP= 0x00d0, /*!< Bypass High Pass Filter */
+ TFA9894N2_BF_DPSA = 0x00e0, /*!< Enable DPSA */
+ TFA9894N2_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9894N2_BF_MANSCONF= 0x0120, /*!< Device I2C settings configured */
+ TFA9894N2_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA9894N2_BF_MANROBOD= 0x0140, /*!< Reaction on BOD */
+ TFA9894N2_BF_BODE = 0x0150, /*!< Enable BOD (only in direct control mode) */
+ TFA9894N2_BF_BODHYS= 0x0160, /*!< Enable Hysteresis of BOD */
+ TFA9894N2_BF_BODFILT= 0x0171, /*!< BOD filter */
+ TFA9894N2_BF_BODTHLVL= 0x0191, /*!< BOD threshold */
+ TFA9894N2_BF_MUTETO= 0x01b0, /*!< Time out SB mute sequence */
+ TFA9894N2_BF_MANWDE= 0x01c0, /*!< Watchdog enable */
+ TFA9894N2_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9894N2_BF_FAIMVBGOVRRL= 0x01f0, /*!< Overrule the enabling of VBG for faim erase/write access */
+ TFA9894N2_BF_AUDFS = 0x0203, /*!< Audio sample rate Fs */
+ TFA9894N2_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9894N2_BF_FRACTDEL= 0x0255, /*!< Current sense fractional delay */
+ TFA9894N2_BF_TDMPRES= 0x02b1, /*!< Control for HW manager */
+ TFA9894N2_BF_AMPOCRT= 0x02d2, /*!< Amplifier on-off criteria for shutdown */
+ TFA9894N2_BF_REV = 0x030f, /*!< Revision info */
+ TFA9894N2_BF_REFCKEXT= 0x0401, /*!< PLL external reference clock */
+ TFA9894N2_BF_REFCKSEL= 0x0420, /*!< PLL internal reference clock */
+ TFA9894N2_BF_MCLKSEL= 0x0432, /*!< Master Clock Selection */
+ TFA9894N2_BF_MANAOOSC= 0x0460, /*!< Internal OSC1M off at PWDN */
+ TFA9894N2_BF_ACKCLDDIS= 0x0470, /*!< Automatic PLL reference clock selection for cold start */
+ TFA9894N2_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9894N2_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9894N2_BF_PLLSTUP= 0x04a0, /*!< PLL startup time configuration */
+ TFA9894N2_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9894N2_BF_SPKSSEN= 0x0510, /*!< Enable speaker sub-system */
+ TFA9894N2_BF_MTPSSEN= 0x0520, /*!< Enable FAIM sub-system */
+ TFA9894N2_BF_WDTCLKEN= 0x0530, /*!< Enable Coolflux watchdog clock */
+ TFA9894N2_BF_VDDS = 0x1000, /*!< POR */
+ TFA9894N2_BF_PLLS = 0x1010, /*!< PLL Lock */
+ TFA9894N2_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9894N2_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9894N2_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9894N2_BF_OCDS = 0x1050, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9894N2_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9894N2_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9894N2_BF_NOCLK = 0x1080, /*!< Lost clock */
+ TFA9894N2_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA9894N2_BF_WDS = 0x10a0, /*!< Watchdog */
+ TFA9894N2_BF_SWS = 0x10b0, /*!< Amplifier engage */
+ TFA9894N2_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9894N2_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9894N2_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9894N2_BF_BODNOK= 0x10f0, /*!< BOD Flag - VDD NOT OK */
+ TFA9894N2_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9894N2_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9894N2_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9894N2_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9894N2_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9894N2_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9894N2_BF_SPKS = 0x1170, /*!< Speaker status */
+ TFA9894N2_BF_CLKOOR= 0x1180, /*!< External clock status */
+ TFA9894N2_BF_MANALARM= 0x1190, /*!< Alarm state */
+ TFA9894N2_BF_TDMERR= 0x11a0, /*!< TDM error */
+ TFA9894N2_BF_TDMLUTER= 0x11b0, /*!< TDM lookup table error */
+ TFA9894N2_BF_NOAUDCLK= 0x11c0, /*!< Lost Audio clock */
+ TFA9894N2_BF_OCPOAP= 0x1200, /*!< OCPOK pmos A */
+ TFA9894N2_BF_OCPOAN= 0x1210, /*!< OCPOK nmos A */
+ TFA9894N2_BF_OCPOBP= 0x1220, /*!< OCPOK pmos B */
+ TFA9894N2_BF_OCPOBN= 0x1230, /*!< OCPOK nmos B */
+ TFA9894N2_BF_CLIPS = 0x1240, /*!< Amplifier clipping */
+ TFA9894N2_BF_MANMUTE= 0x1250, /*!< Audio mute sequence */
+ TFA9894N2_BF_MANOPER= 0x1260, /*!< Device in Operating state */
+ TFA9894N2_BF_LP1 = 0x1270, /*!< Low power MODE1 detection */
+ TFA9894N2_BF_LA = 0x1280, /*!< Low amplitude detection */
+ TFA9894N2_BF_VDDPH = 0x1290, /*!< VDDP greater than VBAT flag */
+ TFA9894N2_BF_TDMSTAT= 0x1302, /*!< TDM Status bits */
+ TFA9894N2_BF_MANSTATE= 0x1333, /*!< Device Manager status */
+ TFA9894N2_BF_DCMODE= 0x13b1, /*!< DCDC mode status bits */
+ TFA9894N2_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9894N2_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9894N2_BF_VDDPS = 0x1709, /*!< IC VDDP voltage (1023*VDDP/13V) */
+ TFA9894N2_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9894N2_BF_TDMSPKE= 0x2010, /*!< Control audio tdm channel in sink0 */
+ TFA9894N2_BF_TDMDCE= 0x2020, /*!< Control audio tdm channel in sink1 */
+ TFA9894N2_BF_TDMCSE= 0x2030, /*!< Source 0 enable */
+ TFA9894N2_BF_TDMVSE= 0x2040, /*!< Source 1 enable */
+ TFA9894N2_BF_TDMCFE= 0x2050, /*!< Source 2 enable */
+ TFA9894N2_BF_TDMCF2E= 0x2060, /*!< Source 3 enable */
+ TFA9894N2_BF_TDMCLINV= 0x2070, /*!< Reception data to BCK clock */
+ TFA9894N2_BF_TDMFSPOL= 0x2080, /*!< FS polarity */
+ TFA9894N2_BF_TDMDEL= 0x2090, /*!< Data delay to FS */
+ TFA9894N2_BF_TDMADJ= 0x20a0, /*!< Data adjustment */
+ TFA9894N2_BF_TDMOOMP= 0x20b1, /*!< Received audio compression */
+ TFA9894N2_BF_TDMNBCK= 0x2103, /*!< TDM NBCK - Bit clock to FS ratio */
+ TFA9894N2_BF_TDMFSLN= 0x2143, /*!< FS length (master mode only) */
+ TFA9894N2_BF_TDMSLOTS= 0x2183, /*!< N-slots in Frame */
+ TFA9894N2_BF_TDMTXDFO= 0x21c1, /*!< Format unused bits */
+ TFA9894N2_BF_TDMTXUS0= 0x21e1, /*!< Format unused slots DATAO */
+ TFA9894N2_BF_TDMSLLN= 0x2204, /*!< N-bits in slot */
+ TFA9894N2_BF_TDMBRMG= 0x2254, /*!< N-bits remaining */
+ TFA9894N2_BF_TDMSSIZE= 0x22a4, /*!< Sample size per slot */
+ TFA9894N2_BF_TDMSPKS= 0x2303, /*!< TDM slot for sink 0 */
+ TFA9894N2_BF_TDMDCS= 0x2343, /*!< TDM slot for sink 1 */
+ TFA9894N2_BF_TDMCFSEL= 0x2381, /*!< TDM Source 2 data selection */
+ TFA9894N2_BF_TDMCF2SEL= 0x23a1, /*!< TDM Source 3 data selection */
+ TFA9894N2_BF_TDMCSS= 0x2403, /*!< Slot position of source 0 data */
+ TFA9894N2_BF_TDMVSS= 0x2443, /*!< Slot position of source 1 data */
+ TFA9894N2_BF_TDMCFS= 0x2483, /*!< Slot position of source 2 data */
+ TFA9894N2_BF_TDMCF2S= 0x24c3, /*!< Slot position of source 3 data */
+ TFA9894N2_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9894N2_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9894N2_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9894N2_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9894N2_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9894N2_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9894N2_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9894N2_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9894N2_BF_ISTCFMER= 0x4080, /*!< Status cfma error */
+ TFA9894N2_BF_ISTCFMAC= 0x4090, /*!< Status cfma ack */
+ TFA9894N2_BF_ISTSPKS= 0x40a0, /*!< Status coolflux speaker error */
+ TFA9894N2_BF_ISTACS= 0x40b0, /*!< Status cold started */
+ TFA9894N2_BF_ISTWDS= 0x40c0, /*!< Status watchdog reset */
+ TFA9894N2_BF_ISTBODNOK= 0x40d0, /*!< Status brown out detect */
+ TFA9894N2_BF_ISTLP1= 0x40e0, /*!< Status low power mode1 detect */
+ TFA9894N2_BF_ISTCLKOOR= 0x40f0, /*!< Status clock out of range */
+ TFA9894N2_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9894N2_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9894N2_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9894N2_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9894N2_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9894N2_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9894N2_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9894N2_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9894N2_BF_ICLCFMER= 0x4480, /*!< Clear cfma err */
+ TFA9894N2_BF_ICLCFMAC= 0x4490, /*!< Clear cfma ack */
+ TFA9894N2_BF_ICLSPKS= 0x44a0, /*!< Clear coolflux speaker error */
+ TFA9894N2_BF_ICLACS= 0x44b0, /*!< Clear cold started */
+ TFA9894N2_BF_ICLWDS= 0x44c0, /*!< Clear watchdog reset */
+ TFA9894N2_BF_ICLBODNOK= 0x44d0, /*!< Clear brown out detect */
+ TFA9894N2_BF_ICLLP1= 0x44e0, /*!< Clear low power mode1 detect */
+ TFA9894N2_BF_ICLCLKOOR= 0x44f0, /*!< Clear clock out of range */
+ TFA9894N2_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9894N2_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9894N2_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9894N2_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9894N2_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9894N2_BF_IEMANALARM= 0x4850, /*!< Enable Manager Alarm state */
+ TFA9894N2_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9894N2_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9894N2_BF_IECFMER= 0x4880, /*!< Enable cfma err */
+ TFA9894N2_BF_IECFMAC= 0x4890, /*!< Enable cfma ack */
+ TFA9894N2_BF_IESPKS= 0x48a0, /*!< Enable coolflux speaker error */
+ TFA9894N2_BF_IEACS = 0x48b0, /*!< Enable cold started */
+ TFA9894N2_BF_IEWDS = 0x48c0, /*!< Enable watchdog reset */
+ TFA9894N2_BF_IEBODNOK= 0x48d0, /*!< Enable brown out detect */
+ TFA9894N2_BF_IELP1 = 0x48e0, /*!< Enable low power mode1 detect */
+ TFA9894N2_BF_IECLKOOR= 0x48f0, /*!< Enable clock out of range */
+ TFA9894N2_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9894N2_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9894N2_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9894N2_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9894N2_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9894N2_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9894N2_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9894N2_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9894N2_BF_IPOCFMER= 0x4c80, /*!< Polarity cfma err */
+ TFA9894N2_BF_IPOCFMAC= 0x4c90, /*!< Polarity cfma ack */
+ TFA9894N2_BF_IPOSPKS= 0x4ca0, /*!< Polarity coolflux speaker error */
+ TFA9894N2_BF_IPOACS= 0x4cb0, /*!< Polarity cold started */
+ TFA9894N2_BF_IPOWDS= 0x4cc0, /*!< Polarity watchdog reset */
+ TFA9894N2_BF_IPOBODNOK= 0x4cd0, /*!< Polarity brown out detect */
+ TFA9894N2_BF_IPOLP1= 0x4ce0, /*!< Polarity low power mode1 detect */
+ TFA9894N2_BF_IPOCLKOOR= 0x4cf0, /*!< Polarity clock out of range */
+ TFA9894N2_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9894N2_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9894N2_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9894N2_BF_BSSRR = 0x5082, /*!< Battery safeguard release time */
+ TFA9894N2_BF_BSSHY = 0x50b1, /*!< Battery Safeguard hysteresis */
+ TFA9894N2_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9894N2_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA9894N2_BF_CFSM = 0x5130, /*!< Coolflux firmware soft mute control */
+ TFA9894N2_BF_VOL = 0x5187, /*!< CF firmware volume control */
+ TFA9894N2_BF_CLIPCTRL= 0x5202, /*!< Clip control setting */
+ TFA9894N2_BF_SLOPEE= 0x5230, /*!< Enables slope control */
+ TFA9894N2_BF_SLOPESET= 0x5240, /*!< Slope speed setting (binary coded) */
+ TFA9894N2_BF_BYPDLYLINE= 0x5250, /*!< Bypass the interpolator delay line */
+ TFA9894N2_BF_AMPGAIN= 0x5287, /*!< Amplifier gain */
+ TFA9894N2_BF_TDMDCG= 0x5703, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9894N2_BF_TDMSPKG= 0x5743, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9894N2_BF_DCINSEL= 0x5781, /*!< VAMP_OUT2 input selection */
+ TFA9894N2_BF_LNMODE= 0x5881, /*!< Low noise gain mode control */
+ TFA9894N2_BF_LPM1MODE= 0x5ac1, /*!< Low power mode control */
+ TFA9894N2_BF_TDMSRCMAP= 0x5d02, /*!< TDM source mapping */
+ TFA9894N2_BF_TDMSRCAS= 0x5d31, /*!< Sensed value A */
+ TFA9894N2_BF_TDMSRCBS= 0x5d51, /*!< Sensed value B */
+ TFA9894N2_BF_TDMSRCACLIP= 0x5d71, /*!< Clip information (analog /digital) for source0 */
+ TFA9894N2_BF_TDMSRCBCLIP= 0x5d91, /*!< Clip information (analog /digital) for source1 */
+ TFA9894N2_BF_DELCURCOMP= 0x6102, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9894N2_BF_SIGCURCOMP= 0x6130, /*!< Polarity of compensation for current sense */
+ TFA9894N2_BF_ENCURCOMP= 0x6140, /*!< Enable current sense compensation */
+ TFA9894N2_BF_LVLCLPPWM= 0x6152, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9894N2_BF_DCVOF = 0x7005, /*!< First Boost Voltage Level */
+ TFA9894N2_BF_DCVOS = 0x7065, /*!< Second Boost Voltage Level */
+ TFA9894N2_BF_DCMCC = 0x70c3, /*!< Max Coil Current */
+ TFA9894N2_BF_DCCV = 0x7101, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9894N2_BF_DCIE = 0x7120, /*!< Adaptive boost mode */
+ TFA9894N2_BF_DCSR = 0x7130, /*!< Soft ramp up/down */
+ TFA9894N2_BF_DCDIS = 0x7140, /*!< DCDC on/off */
+ TFA9894N2_BF_DCPWM = 0x7150, /*!< DCDC PWM only mode */
+ TFA9894N2_BF_DCTRACK= 0x7160, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_DCENVSEL= 0x7170, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_OVSCTLVL= 0x7195, /*!< Threshold level to activate active overshoot control */
+ TFA9894N2_BF_DCTRIP= 0x7204, /*!< 1st adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894N2_BF_DCTRIP2= 0x7254, /*!< 2nd adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894N2_BF_DCTRIPT= 0x72a4, /*!< Track adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_DCTRIPHYSTE= 0x72f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9894N2_BF_DCHOLD= 0x7304, /*!< Hold time / Hysteresis for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_RST = 0x9000, /*!< Reset for Coolflux DSP */
+ TFA9894N2_BF_DMEM = 0x9011, /*!< Target memory for CFMA using I2C interface */
+ TFA9894N2_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA9894N2_BF_CFINT = 0x9040, /*!< Coolflux Interrupt - auto clear */
+ TFA9894N2_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA9894N2_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA9894N2_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA9894N2_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA9894N2_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA9894N2_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA9894N2_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA9894N2_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA9894N2_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA9894N2_BF_MADD = 0x910f, /*!< CF memory address */
+ TFA9894N2_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA9894N2_BF_ERR = 0x9307, /*!< CF error flags */
+ TFA9894N2_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA9894N2_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA9894N2_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA9894N2_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA9894N2_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA9894N2_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA9894N2_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA9894N2_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA9894N2_BF_MTPK = 0xa107, /*!< KEY2 to access KEY2 protected registers, customer key */
+ TFA9894N2_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9894N2_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9894N2_BF_CMTPI = 0xa350, /*!< Start copying all the data from mtp to I2C mtp registers - auto clear */
+ TFA9894N2_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp - auto clear */
+ TFA9894N2_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9894N2_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9894N2_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9894N2_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9894N2_BF_PLLINSELI= 0xca05, /*!< PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9894N2_BF_PLLINSELP= 0xca64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9894N2_BF_PLLINSELR= 0xcab3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9894N2_BF_PLLNDEC= 0xcb09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLMDECMSB= 0xcba0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLBYPASS= 0xcbb0, /*!< PLL bypass control during functional mode */
+ TFA9894N2_BF_PLLDIRECTI= 0xcbc0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLDIRECTO= 0xcbd0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLFRMSTBL= 0xcbe0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLFRM= 0xcbf0, /*!< PLL free running mode control in functional mode */
+ TFA9894N2_BF_PLLMDECLSB= 0xcc0f, /*!< Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLPDEC= 0xcd06, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_DIRECTPLL= 0xcd70, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9894N2_BF_DIRECTCLK= 0xcd80, /*!< Enabled CGU clock divider direct control mode */
+ TFA9894N2_BF_PLLLIM= 0xcd90, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9894N2_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9894N2_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9894N2_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9894N2_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9894N2_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9894N2_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9894N2_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9894N2_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9894N2_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9894N2BfEnumList_t;
+#define TFA9894N2_NAMETABLE static tfaBfName_t Tfa9894N2DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown control , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "AMPE"}, /* Enable Amplifier , */\
+ { 0x40, "DCA"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xa0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xb0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xc0, "BSSS"}, /* Vbat protection steepness , */\
+ { 0xd0, "HPFBYP"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "DPSA"}, /* Enable DPSA , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* Device I2C settings configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x150, "BODE"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "BODFILT"}, /* BOD filter , */\
+ { 0x191, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1b0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "MANWDE"}, /* Watchdog enable , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "FAIMVBGOVRRL"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "AUDFS"}, /* Audio sample rate Fs , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* Current sense fractional delay , */\
+ { 0x2b1, "TDMPRES"}, /* Control for HW manager , */\
+ { 0x2d2, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external reference clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal reference clock , */\
+ { 0x432, "MCLKSEL"}, /* Master Clock Selection , */\
+ { 0x460, "MANAOOSC"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "ACKCLDDIS"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "PLLSTUP"}, /* PLL startup time configuration , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "SPKSSEN"}, /* Enable speaker sub-system , */\
+ { 0x520, "MTPSSEN"}, /* Enable FAIM sub-system , */\
+ { 0x530, "WDTCLKEN"}, /* Enable Coolflux watchdog clock , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL Lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "WDS"}, /* Watchdog , */\
+ { 0x10b0, "SWS"}, /* Amplifier engage , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "SPKS"}, /* Speaker status , */\
+ { 0x1180, "CLKOOR"}, /* External clock status , */\
+ { 0x1190, "MANALARM"}, /* Alarm state , */\
+ { 0x11a0, "TDMERR"}, /* TDM error , */\
+ { 0x11b0, "TDMLUTER"}, /* TDM lookup table error , */\
+ { 0x11c0, "NOAUDCLK"}, /* Lost Audio clock , */\
+ { 0x1200, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1210, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1220, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1230, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1240, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1250, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x1260, "MANOPER"}, /* Device in Operating state , */\
+ { 0x1270, "LP1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "LA"}, /* Low amplitude detection , */\
+ { 0x1290, "VDDPH"}, /* VDDP greater than VBAT flag , */\
+ { 0x1302, "TDMSTAT"}, /* TDM Status bits , */\
+ { 0x1333, "MANSTATE"}, /* Device Manager status , */\
+ { 0x13b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2010, "TDMSPKE"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "TDMDCE"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "TDMCSE"}, /* Source 0 enable , */\
+ { 0x2040, "TDMVSE"}, /* Source 1 enable , */\
+ { 0x2050, "TDMCFE"}, /* Source 2 enable , */\
+ { 0x2060, "TDMCF2E"}, /* Source 3 enable , */\
+ { 0x2070, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2080, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2090, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x20a0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x20b1, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2103, "TDMNBCK"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x2183, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x21c1, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x21e1, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2204, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2254, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x22a4, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2303, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "TDMCFSEL"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "TDMCF2SEL"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "TDMCSS"}, /* Slot position of source 0 data , */\
+ { 0x2443, "TDMVSS"}, /* Slot position of source 1 data , */\
+ { 0x2483, "TDMCFS"}, /* Slot position of source 2 data , */\
+ { 0x24c3, "TDMCF2S"}, /* Slot position of source 3 data , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x4090, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x40a0, "ISTSPKS"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "ISTACS"}, /* Status cold started , */\
+ { 0x40c0, "ISTWDS"}, /* Status watchdog reset , */\
+ { 0x40d0, "ISTBODNOK"}, /* Status brown out detect , */\
+ { 0x40e0, "ISTLP1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "ISTCLKOOR"}, /* Status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x4490, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x44a0, "ICLSPKS"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "ICLACS"}, /* Clear cold started , */\
+ { 0x44c0, "ICLWDS"}, /* Clear watchdog reset , */\
+ { 0x44d0, "ICLBODNOK"}, /* Clear brown out detect , */\
+ { 0x44e0, "ICLLP1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "ICLCLKOOR"}, /* Clear clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IECFMER"}, /* Enable cfma err , */\
+ { 0x4890, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x48a0, "IESPKS"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "IEACS"}, /* Enable cold started , */\
+ { 0x48c0, "IEWDS"}, /* Enable watchdog reset , */\
+ { 0x48d0, "IEBODNOK"}, /* Enable brown out detect , */\
+ { 0x48e0, "IELP1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "IECLKOOR"}, /* Enable clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4c90, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "IPOSPKS"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4cc0, "IPOWDS"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "IPOBODNOK"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "IPOLP1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "IPOCLKOOR"}, /* Polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery safeguard release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery Safeguard hysteresis , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5130, "CFSM"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "VOL"}, /* CF firmware volume control , */\
+ { 0x5202, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5230, "SLOPEE"}, /* Enables slope control , */\
+ { 0x5240, "SLOPESET"}, /* Slope speed setting (binary coded) , */\
+ { 0x5250, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x5287, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x5703, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "DCINSEL"}, /* VAMP_OUT2 input selection , */\
+ { 0x5881, "LNMODE"}, /* Low noise gain mode control , */\
+ { 0x5ac1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x5d02, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x5d31, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x5d51, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x5d71, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6102, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6152, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "DCVOF"}, /* First Boost Voltage Level , */\
+ { 0x7065, "DCVOS"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "DCMCC"}, /* Max Coil Current , */\
+ { 0x7101, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7130, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7140, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7150, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7160, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "DCENVSEL"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7195, "OVSCTLVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7204, "DCTRIP"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "DCTRIP2"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "DCTRIPT"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "DCHOLD"}, /* Hold time / Hysteresis for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x9000, "RST"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "DMEM"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* CF memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* CF error flags , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa350, "CMTPI"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xca05, "PLLINSELI"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xca64, "PLLINSELP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcab3, "PLLINSELR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcb09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcba0, "PLLMDECMSB"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbb0, "PLLBYPASS"}, /* PLL bypass control during functional mode , */\
+ { 0xcbc0, "PLLDIRECTI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbd0, "PLLDIRECTO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbe0, "PLLFRMSTBL"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbf0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcc0f, "PLLMDECLSB"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd06, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd70, "DIRECTPLL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xcd80, "DIRECTCLK"}, /* Enabled CGU clock divider direct control mode , */\
+ { 0xcd90, "PLLLIM"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9894N2_BITNAMETABLE static tfaBfName_t Tfa9894N2BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown control , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xa0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xb0, "test_ocp"}, /* OCP testing control , */\
+ { 0xc0, "batsense_steepness"}, /* Vbat protection steepness , */\
+ { 0xd0, "bypass_hp"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* Device I2C settings configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x150, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "bod_delay_set"}, /* BOD filter , */\
+ { 0x191, "bod_lvl_set"}, /* BOD threshold , */\
+ { 0x1b0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "man_enbl_watchdog"}, /* Watchdog enable , */\
+ { 0x1d0, "disable_engage"}, /* Disable Engage , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "faim_enable_vbg"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "audio_fs"}, /* Audio sample rate Fs , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* Current sense fractional delay , */\
+ { 0x2b1, "use_tdm_presence"}, /* Control for HW manager , */\
+ { 0x2d2, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external reference clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal reference clock , */\
+ { 0x432, "mclk_sel"}, /* Master Clock Selection , */\
+ { 0x460, "enbl_osc1m_auto_off"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "disable_auto_sel_refclk"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "pll_slow_startup"}, /* PLL startup time configuration , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker sub-system , */\
+ { 0x520, "enbl_faim_ss"}, /* Enable FAIM sub-system , */\
+ { 0x530, "enbl_wdt_clk"}, /* Enable Coolflux watchdog clock , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to hidden register. (0x5A6B/23147 default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL Lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10b0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_cf_speakererror"}, /* Speaker status , */\
+ { 0x1180, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1190, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x11a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x11b0, "flag_tdm_lut_error"}, /* TDM lookup table error , */\
+ { 0x11c0, "flag_lost_audio_clk"}, /* Lost Audio clock , */\
+ { 0x1200, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1210, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1220, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1230, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1240, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1250, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x1260, "flag_man_operating_state"}, /* Device in Operating state , */\
+ { 0x1270, "flag_lp_detect_mode1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x1290, "flag_vddp_gt_vbat"}, /* VDDP greater than VBAT flag , */\
+ { 0x1302, "tdm_status"}, /* TDM Status bits , */\
+ { 0x1333, "man_state"}, /* Device Manager status , */\
+ { 0x1373, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x13b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2010, "tdm_sink0_enable"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "tdm_sink1_enable"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "tdm_source0_enable"}, /* Source 0 enable , */\
+ { 0x2040, "tdm_source1_enable"}, /* Source 1 enable , */\
+ { 0x2050, "tdm_source2_enable"}, /* Source 2 enable , */\
+ { 0x2060, "tdm_source3_enable"}, /* Source 3 enable , */\
+ { 0x2070, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2080, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2090, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x20a0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x20b1, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2103, "tdm_nbck"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x2183, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x21c1, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x21e1, "tdm_txdata_format_unused_slot"}, /* Format unused slots DATAO , */\
+ { 0x2204, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2254, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x22a4, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2303, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "tdm_source2_sel"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "tdm_source3_sel"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "tdm_source0_slot"}, /* Slot position of source 0 data , */\
+ { 0x2443, "tdm_source1_slot"}, /* Slot position of source 1 data , */\
+ { 0x2483, "tdm_source2_slot"}, /* Slot position of source 2 data , */\
+ { 0x24c3, "tdm_source3_slot"}, /* Slot position of source 3 data , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x4090, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x40a0, "int_out_flag_cf_speakererror"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "int_out_flag_cold_started"}, /* Status cold started , */\
+ { 0x40c0, "int_out_flag_watchdog_reset"}, /* Status watchdog reset , */\
+ { 0x40d0, "int_out_flag_bod_vddd_nok"}, /* Status brown out detect , */\
+ { 0x40e0, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "int_out_flag_clk_out_of_range"}, /* Status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x4490, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x44a0, "int_in_flag_cf_speakererror"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44c0, "int_in_flag_watchdog_reset"}, /* Clear watchdog reset , */\
+ { 0x44d0, "int_in_flag_bod_vddd_nok"}, /* Clear brown out detect , */\
+ { 0x44e0, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "int_in_flag_clk_out_of_range"}, /* Clear clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x4890, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x48a0, "int_enable_flag_cf_speakererror"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48c0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog reset , */\
+ { 0x48d0, "int_enable_flag_bod_vddd_nok"}, /* Enable brown out detect , */\
+ { 0x48e0, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "int_enable_flag_clk_out_of_range"}, /* Enable clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4c90, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "int_polarity_flag_cf_speakererror"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4cc0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "int_polarity_flag_clk_out_of_range"}, /* Polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery safeguard release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5130, "cf_mute"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "cf_volume"}, /* CF firmware volume control , */\
+ { 0x5202, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5230, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x5240, "ctrl_slope"}, /* Slope speed setting (binary coded) , */\
+ { 0x5250, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5287, "gain"}, /* Amplifier gain , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for battery safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5370, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5380, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5390, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x53a3, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5452, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x550a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x55b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x55c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5600, "pwm_shape"}, /* PWM shape , */\
+ { 0x5614, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5660, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x5670, "reclock_voltsense"}, /* Reclock the voltage sense PWM signal , */\
+ { 0x5680, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5690, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x56a1, "enbl_odd_up_even_down"}, /* Control for PWM reference sawtooth generartion , */\
+ { 0x5703, "ctrl_att_dcdc"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "ctrl_att_spkr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "vamp_sel2"}, /* VAMP_OUT2 input selection , */\
+ { 0x5805, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x5861, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x5881, "lownoisegain_mode"}, /* Low noise gain mode control , */\
+ { 0x5905, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x5965, "hold_time"}, /* Low noise mode hold time before entering into low noise mode, */\
+ { 0x5a05, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x5a65, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x5ac1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x5b05, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x5b65, "lpm1_hold_time"}, /* Low power mode hold time before entering into low power mode, */\
+ { 0x5bc0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x5c00, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x5c13, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x5c50, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x5c61, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x5d02, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x5d31, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x5d51, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x5d71, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x5e02, "rst_min_vbat_delay"}, /* Delay for reseting the min_vbat value inside HW Clipper (number of Fs pulses), */\
+ { 0x5e30, "rst_min_vbat_sel"}, /* Control for selecting reset signal for min_bat , */\
+ { 0x5f00, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5f12, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x5f42, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x5f78, "spare_out"}, /* Spare out register , */\
+ { 0x600f, "spare_in"}, /* Spare IN , */\
+ { 0x6102, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6152, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "frst_boost_voltage"}, /* First Boost Voltage Level , */\
+ { 0x7065, "scnd_boost_voltage"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "boost_cur"}, /* Max Coil Current , */\
+ { 0x7101, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7130, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7140, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7150, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7160, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7180, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7195, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7204, "boost_trip_lvl_1st"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "boost_trip_lvl_2nd"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "boost_trip_lvl_track"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "boost_hold_time"}, /* Hold time / Hysteresis for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x7350, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x7361, "dcdc_ctrl_maxzercnt"}, /* Number of zero current flags to count before going to pfm mode, */\
+ { 0x7386, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x73f0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x7404, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7451, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7474, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x74c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x74e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x74f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7500, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7510, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7520, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7530, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7540, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7550, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7560, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7570, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7580, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x7595, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7600, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7611, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7631, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7650, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7660, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8040, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8050, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8060, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8105, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP) * signal, */\
+ { 0x8164, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x81b0, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x81c0, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x81d0, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x81e0, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x81f0, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8200, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8210, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8220, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8231, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8250, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8263, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x82a0, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x82b4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8300, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8310, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8320, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8330, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8340, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8350, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8364, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8800, "ctrl_vs_igen_supply"}, /* Control for selecting supply for VS current generator, */\
+ { 0x8810, "ctrl_vs_force_div2"}, /* Select input resistive divider gain , */\
+ { 0x8820, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8901, "volsense_pwm_sel"}, /* Voltage sense source selection control , */\
+ { 0x8920, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8930, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8940, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8950, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8960, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8970, "vs_classd_tran_skip"}, /* Skip voltage sense connection during a classD amplifier transition, */\
+ { 0x8987, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8a00, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8a10, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8a20, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "enbl_vs_adc"}, /* Enable voltage sense ADC , */\
+ { 0x8aa0, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8ab0, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8ac0, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8ad0, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8ae0, "enbl_vs_ldo"}, /* Enable voltage sense LDO , */\
+ { 0x8af0, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "cf_dmem"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* CF memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* CF error flags , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0xa007, "mtpkey1"}, /* KEY1 To access KEY1 protected registers 0x5A/90d (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from MTP to I2C mtp register - auto clear, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp - auto clear, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the FaIM controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the FaIM are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the FaIM are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb000, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb010, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb020, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb030, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb040, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb050, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb060, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb070, "disable_main_ctrl_change_prot"}, /* Disable main control change protection , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_osc"}, /* Enables OSC in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* Enable ABIST with FFT on Coolflux DSP , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost Converter Over Current Protection , */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc530, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc540, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc550, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc560, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc570, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc583, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc5c0, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc607, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO , */\
+ { 0xc687, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT , */\
+ { 0xc707, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 , */\
+ { 0xc800, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xc810, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xc820, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xc830, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xc844, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xc894, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xc903, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xc943, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xca05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xca64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcab3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcaf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xcb09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcba0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcbc0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbd0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbe0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbf0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcc0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd06, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd70, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xcd80, "use_direct_clk_ctrl"}, /* Enabled CGU clock divider direct control mode , */\
+ { 0xcd90, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xce0f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xcf02, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xcf33, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd000, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd011, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd032, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd064, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd0b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd0c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd109, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd201, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd301, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd321, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd340, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xd407, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd480, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd491, "sel_wdt_clk"}, /* Watch dog clock divider settings , */\
+ { 0xd4b0, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd500, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd510, "gainatt_feedback"}, /* Gainatt feedback to tdm , */\
+ { 0xd522, "test_parametric_io"}, /* Test IO parametric , */\
+ { 0xd550, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0xd561, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd580, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd593, "test_spare_out2"}, /* Test spare out 2 , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs"}, /* Voltage sense gain , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "mtpdata4"}, /* MTP4 data , */\
+ { 0xf50f, "calibr_R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xf60f, "mtpdata6"}, /* MTP6 data , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable functionality of dcdcoff_mode bit , */\
+ { 0xf910, "mtp_lock_enbl_coolflux"}, /* Disable functionality of enbl_coolflux bit , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf940, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xf987, "type_bits_fw"}, /* MTP control for firmware features - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+#if 0
+enum tfa9894_irq {
+ tfa9894_irq_max = -1,
+ tfa9894_irq_all = -1 /* all irqs */};
+#endif//
+#define TFA9894_IRQ_NAMETABLE static tfaIrqName_t Tfa9894IrqNames[]= {\
+};
+#endif /* _TFA9894_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9896_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9896_tfafieldnames.h
new file mode 100644
index 00000000000..e1583a0ddb7
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9896_tfafieldnames.h
@@ -0,0 +1,930 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9896_tfafieldnames.h
+ * This file was generated automatically on 08/15/16 at 09:43:38.
+ * Source file: TFA9896_N1B1_I2C_regmap_V16.xlsx
+ */
+
+#ifndef _TFA9896_TFAFIELDNAMES_H
+#define _TFA9896_TFAFIELDNAMES_H
+
+
+#define TFA9896_I2CVERSION 16
+
+typedef enum TFA9896BfEnumList {
+ TFA9896_BF_VDDS = 0x0000, /*!< Power-on-reset flag (auto clear by reading) */
+ TFA9896_BF_PLLS = 0x0010, /*!< PLL lock to programmed frequency */
+ TFA9896_BF_OTDS = 0x0020, /*!< Over Temperature Protection alarm */
+ TFA9896_BF_OVDS = 0x0030, /*!< Over Voltage Protection alarm */
+ TFA9896_BF_UVDS = 0x0040, /*!< Under Voltage Protection alarm */
+ TFA9896_BF_OCDS = 0x0050, /*!< Over Current Protection alarm */
+ TFA9896_BF_CLKS = 0x0060, /*!< Clocks stable flag */
+ TFA9896_BF_CLIPS = 0x0070, /*!< Amplifier clipping */
+ TFA9896_BF_MTPB = 0x0080, /*!< MTP busy copying data to/from I2C registers */
+ TFA9896_BF_NOCLK = 0x0090, /*!< lost clock detection (reference input clock) */
+ TFA9896_BF_SPKS = 0x00a0, /*!< Speaker error */
+ TFA9896_BF_ACS = 0x00b0, /*!< Cold Start required */
+ TFA9896_BF_SWS = 0x00c0, /*!< Amplifier engage (Amp Switching) */
+ TFA9896_BF_WDS = 0x00d0, /*!< watchdog reset (activates reset) */
+ TFA9896_BF_AMPS = 0x00e0, /*!< Amplifier is enabled by manager */
+ TFA9896_BF_AREFS = 0x00f0, /*!< References are enabled by manager */
+ TFA9896_BF_BATS = 0x0109, /*!< Battery voltage from ADC readout */
+ TFA9896_BF_TEMPS = 0x0208, /*!< Temperature readout from the temperature sensor ( C) */
+ TFA9896_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9896_BF_RCV = 0x0420, /*!< Enable receiver mode */
+ TFA9896_BF_CHS12 = 0x0431, /*!< Channel Selection TDM input for Coolflux */
+ TFA9896_BF_INPLVL= 0x0450, /*!< Input level selection attenuator ( */
+ TFA9896_BF_CHSA = 0x0461, /*!< Input selection for amplifier */
+ TFA9896_BF_AUDFS = 0x04c3, /*!< Audio sample rate setting */
+ TFA9896_BF_BSSCR = 0x0501, /*!< Batteery protection attack time */
+ TFA9896_BF_BSST = 0x0523, /*!< Battery protection threshold level */
+ TFA9896_BF_BSSRL = 0x0561, /*!< Battery protection maximum reduction */
+ TFA9896_BF_BSSRR = 0x0582, /*!< Battery protection release time */
+ TFA9896_BF_BSSHY = 0x05b1, /*!< Battery Protection Hysteresis */
+ TFA9896_BF_BSSR = 0x05e0, /*!< Battery voltage value for read out (only) */
+ TFA9896_BF_BSSBY = 0x05f0, /*!< Bypass clipper battery protection */
+ TFA9896_BF_DPSA = 0x0600, /*!< Enable dynamic powerstage activation (DPSA) */
+ TFA9896_BF_ATTEN = 0x0613, /*!< Gain attenuation setting */
+ TFA9896_BF_CFSM = 0x0650, /*!< Soft mute in CoolFlux */
+ TFA9896_BF_BSSS = 0x0670, /*!< Battery sense steepness */
+ TFA9896_BF_VOL = 0x0687, /*!< Coolflux volume control */
+ TFA9896_BF_DCVO2 = 0x0702, /*!< Second Boost Voltage */
+ TFA9896_BF_DCMCC = 0x0733, /*!< Max boost coil current - step of 175 mA */
+ TFA9896_BF_DCVO1 = 0x0772, /*!< First Boost Voltage */
+ TFA9896_BF_DCIE = 0x07a0, /*!< Adaptive boost mode */
+ TFA9896_BF_DCSR = 0x07b0, /*!< Soft Rampup/down mode for DCDC controller */
+ TFA9896_BF_DCPAVG= 0x07c0, /*!< ctrl_peak2avg for analog part of DCDC */
+ TFA9896_BF_DCPWM = 0x07d0, /*!< DCDC PWM only mode */
+ TFA9896_BF_TROS = 0x0800, /*!< Selection ambient temperature for speaker calibration */
+ TFA9896_BF_EXTTS = 0x0818, /*!< External temperature for speaker calibration (C) */
+ TFA9896_BF_PWDN = 0x0900, /*!< powerdown selection */
+ TFA9896_BF_I2CR = 0x0910, /*!< All I2C registers reset to default */
+ TFA9896_BF_CFE = 0x0920, /*!< Enable CoolFlux */
+ TFA9896_BF_AMPE = 0x0930, /*!< Enable Amplifier */
+ TFA9896_BF_DCA = 0x0940, /*!< Enable DCDC Boost converter */
+ TFA9896_BF_SBSL = 0x0950, /*!< Coolflux configured */
+ TFA9896_BF_AMPC = 0x0960, /*!< Selection if Coolflux enables amplifier */
+ TFA9896_BF_DCDIS = 0x0970, /*!< DCDC boost converter not connected */
+ TFA9896_BF_PSDR = 0x0980, /*!< IDDQ amplifier test selection */
+ TFA9896_BF_INTPAD= 0x09c1, /*!< INT pad (interrupt bump output) configuration */
+ TFA9896_BF_IPLL = 0x09e0, /*!< PLL input reference clock selection */
+ TFA9896_BF_DCTRIP= 0x0a04, /*!< Adaptive boost trip levels (effective only when boost_intel is set to 1) */
+ TFA9896_BF_DCHOLD= 0x0a54, /*!< Hold time for DCDC booster (effective only when boost_intel is set to 1) */
+ TFA9896_BF_MTPK = 0x0b07, /*!< KEY2 to access key2 protected registers (default for engineering) */
+ TFA9896_BF_CVFDLY= 0x0c25, /*!< Fractional delay adjustment between current and voltage sense */
+ TFA9896_BF_OPENMTP= 0x0ec0, /*!< Enable programming of the MTP memory */
+ TFA9896_BF_TDMPRF= 0x1011, /*!< TDM usecase selection control */
+ TFA9896_BF_TDMEN = 0x1030, /*!< TDM interface enable */
+ TFA9896_BF_TDMCKINV= 0x1040, /*!< TDM clock inversion, receive on */
+ TFA9896_BF_TDMFSLN= 0x1053, /*!< TDM FS length */
+ TFA9896_BF_TDMFSPOL= 0x1090, /*!< TDM FS polarity (start frame) */
+ TFA9896_BF_TDMSAMSZ= 0x10a4, /*!< TDM sample size for all TDM sinks and sources */
+ TFA9896_BF_TDMSLOTS= 0x1103, /*!< TDM number of slots */
+ TFA9896_BF_TDMSLLN= 0x1144, /*!< TDM slot length */
+ TFA9896_BF_TDMBRMG= 0x1194, /*!< TDM bits remaining after the last slot */
+ TFA9896_BF_TDMDDEL= 0x11e0, /*!< TDM data delay */
+ TFA9896_BF_TDMDADJ= 0x11f0, /*!< TDM data adjustment */
+ TFA9896_BF_TDMTXFRM= 0x1201, /*!< TDM TXDATA format */
+ TFA9896_BF_TDMUUS0= 0x1221, /*!< TDM TXDATA format unused slot SD0 */
+ TFA9896_BF_TDMUUS1= 0x1241, /*!< TDM TXDATA format unused slot SD1 */
+ TFA9896_BF_TDMSI0EN= 0x1270, /*!< TDM sink0 enable */
+ TFA9896_BF_TDMSI1EN= 0x1280, /*!< TDM sink1 enable */
+ TFA9896_BF_TDMSI2EN= 0x1290, /*!< TDM sink2 enable */
+ TFA9896_BF_TDMSO0EN= 0x12a0, /*!< TDM source0 enable */
+ TFA9896_BF_TDMSO1EN= 0x12b0, /*!< TDM source1 enable */
+ TFA9896_BF_TDMSO2EN= 0x12c0, /*!< TDM source2 enable */
+ TFA9896_BF_TDMSI0IO= 0x12d0, /*!< TDM sink0 IO selection */
+ TFA9896_BF_TDMSI1IO= 0x12e0, /*!< TDM sink1 IO selection */
+ TFA9896_BF_TDMSI2IO= 0x12f0, /*!< TDM sink2 IO selection */
+ TFA9896_BF_TDMSO0IO= 0x1300, /*!< TDM source0 IO selection */
+ TFA9896_BF_TDMSO1IO= 0x1310, /*!< TDM source1 IO selection */
+ TFA9896_BF_TDMSO2IO= 0x1320, /*!< TDM source2 IO selection */
+ TFA9896_BF_TDMSI0SL= 0x1333, /*!< TDM sink0 slot position [GAIN IN] */
+ TFA9896_BF_TDMSI1SL= 0x1373, /*!< TDM sink1 slot position [CH1 IN] */
+ TFA9896_BF_TDMSI2SL= 0x13b3, /*!< TDM sink2 slot position [CH2 IN] */
+ TFA9896_BF_TDMSO0SL= 0x1403, /*!< TDM source0 slot position [GAIN OUT] */
+ TFA9896_BF_TDMSO1SL= 0x1443, /*!< TDM source1 slot position [Voltage Sense] */
+ TFA9896_BF_TDMSO2SL= 0x1483, /*!< TDM source2 slot position [Current Sense] */
+ TFA9896_BF_NBCK = 0x14c3, /*!< TDM NBCK bit clock ratio */
+ TFA9896_BF_INTOVDDS= 0x2000, /*!< flag_por_int_out */
+ TFA9896_BF_INTOPLLS= 0x2010, /*!< flag_pll_lock_int_out */
+ TFA9896_BF_INTOOTDS= 0x2020, /*!< flag_otpok_int_out */
+ TFA9896_BF_INTOOVDS= 0x2030, /*!< flag_ovpok_int_out */
+ TFA9896_BF_INTOUVDS= 0x2040, /*!< flag_uvpok_int_out */
+ TFA9896_BF_INTOOCDS= 0x2050, /*!< flag_ocp_alarm_int_out */
+ TFA9896_BF_INTOCLKS= 0x2060, /*!< flag_clocks_stable_int_out */
+ TFA9896_BF_INTOCLIPS= 0x2070, /*!< flag_clip_int_out */
+ TFA9896_BF_INTOMTPB= 0x2080, /*!< mtp_busy_int_out */
+ TFA9896_BF_INTONOCLK= 0x2090, /*!< flag_lost_clk_int_out */
+ TFA9896_BF_INTOSPKS= 0x20a0, /*!< flag_cf_speakererror_int_out */
+ TFA9896_BF_INTOACS= 0x20b0, /*!< flag_cold_started_int_out */
+ TFA9896_BF_INTOSWS= 0x20c0, /*!< flag_engage_int_out */
+ TFA9896_BF_INTOWDS= 0x20d0, /*!< flag_watchdog_reset_int_out */
+ TFA9896_BF_INTOAMPS= 0x20e0, /*!< flag_enbl_amp_int_out */
+ TFA9896_BF_INTOAREFS= 0x20f0, /*!< flag_enbl_ref_int_out */
+ TFA9896_BF_INTOERR= 0x2200, /*!< flag_cfma_err_int_out */
+ TFA9896_BF_INTOACK= 0x2210, /*!< flag_cfma_ack_int_out */
+ TFA9896_BF_INTIVDDS= 0x2300, /*!< flag_por_int_in */
+ TFA9896_BF_INTIPLLS= 0x2310, /*!< flag_pll_lock_int_in */
+ TFA9896_BF_INTIOTDS= 0x2320, /*!< flag_otpok_int_in */
+ TFA9896_BF_INTIOVDS= 0x2330, /*!< flag_ovpok_int_in */
+ TFA9896_BF_INTIUVDS= 0x2340, /*!< flag_uvpok_int_in */
+ TFA9896_BF_INTIOCDS= 0x2350, /*!< flag_ocp_alarm_int_in */
+ TFA9896_BF_INTICLKS= 0x2360, /*!< flag_clocks_stable_int_in */
+ TFA9896_BF_INTICLIPS= 0x2370, /*!< flag_clip_int_in */
+ TFA9896_BF_INTIMTPB= 0x2380, /*!< mtp_busy_int_in */
+ TFA9896_BF_INTINOCLK= 0x2390, /*!< flag_lost_clk_int_in */
+ TFA9896_BF_INTISPKS= 0x23a0, /*!< flag_cf_speakererror_int_in */
+ TFA9896_BF_INTIACS= 0x23b0, /*!< flag_cold_started_int_in */
+ TFA9896_BF_INTISWS= 0x23c0, /*!< flag_engage_int_in */
+ TFA9896_BF_INTIWDS= 0x23d0, /*!< flag_watchdog_reset_int_in */
+ TFA9896_BF_INTIAMPS= 0x23e0, /*!< flag_enbl_amp_int_in */
+ TFA9896_BF_INTIAREFS= 0x23f0, /*!< flag_enbl_ref_int_in */
+ TFA9896_BF_INTIERR= 0x2500, /*!< flag_cfma_err_int_in */
+ TFA9896_BF_INTIACK= 0x2510, /*!< flag_cfma_ack_int_in */
+ TFA9896_BF_INTENVDDS= 0x2600, /*!< flag_por_int_enable */
+ TFA9896_BF_INTENPLLS= 0x2610, /*!< flag_pll_lock_int_enable */
+ TFA9896_BF_INTENOTDS= 0x2620, /*!< flag_otpok_int_enable */
+ TFA9896_BF_INTENOVDS= 0x2630, /*!< flag_ovpok_int_enable */
+ TFA9896_BF_INTENUVDS= 0x2640, /*!< flag_uvpok_int_enable */
+ TFA9896_BF_INTENOCDS= 0x2650, /*!< flag_ocp_alarm_int_enable */
+ TFA9896_BF_INTENCLKS= 0x2660, /*!< flag_clocks_stable_int_enable */
+ TFA9896_BF_INTENCLIPS= 0x2670, /*!< flag_clip_int_enable */
+ TFA9896_BF_INTENMTPB= 0x2680, /*!< mtp_busy_int_enable */
+ TFA9896_BF_INTENNOCLK= 0x2690, /*!< flag_lost_clk_int_enable */
+ TFA9896_BF_INTENSPKS= 0x26a0, /*!< flag_cf_speakererror_int_enable */
+ TFA9896_BF_INTENACS= 0x26b0, /*!< flag_cold_started_int_enable */
+ TFA9896_BF_INTENSWS= 0x26c0, /*!< flag_engage_int_enable */
+ TFA9896_BF_INTENWDS= 0x26d0, /*!< flag_watchdog_reset_int_enable */
+ TFA9896_BF_INTENAMPS= 0x26e0, /*!< flag_enbl_amp_int_enable */
+ TFA9896_BF_INTENAREFS= 0x26f0, /*!< flag_enbl_ref_int_enable */
+ TFA9896_BF_INTENERR= 0x2800, /*!< flag_cfma_err_int_enable */
+ TFA9896_BF_INTENACK= 0x2810, /*!< flag_cfma_ack_int_enable */
+ TFA9896_BF_INTPOLVDDS= 0x2900, /*!< flag_por_int_pol */
+ TFA9896_BF_INTPOLPLLS= 0x2910, /*!< flag_pll_lock_int_pol */
+ TFA9896_BF_INTPOLOTDS= 0x2920, /*!< flag_otpok_int_pol */
+ TFA9896_BF_INTPOLOVDS= 0x2930, /*!< flag_ovpok_int_pol */
+ TFA9896_BF_INTPOLUVDS= 0x2940, /*!< flag_uvpok_int_pol */
+ TFA9896_BF_INTPOLOCDS= 0x2950, /*!< flag_ocp_alarm_int_pol */
+ TFA9896_BF_INTPOLCLKS= 0x2960, /*!< flag_clocks_stable_int_pol */
+ TFA9896_BF_INTPOLCLIPS= 0x2970, /*!< flag_clip_int_pol */
+ TFA9896_BF_INTPOLMTPB= 0x2980, /*!< mtp_busy_int_pol */
+ TFA9896_BF_INTPOLNOCLK= 0x2990, /*!< flag_lost_clk_int_pol */
+ TFA9896_BF_INTPOLSPKS= 0x29a0, /*!< flag_cf_speakererror_int_pol */
+ TFA9896_BF_INTPOLACS= 0x29b0, /*!< flag_cold_started_int_pol */
+ TFA9896_BF_INTPOLSWS= 0x29c0, /*!< flag_engage_int_pol */
+ TFA9896_BF_INTPOLWDS= 0x29d0, /*!< flag_watchdog_reset_int_pol */
+ TFA9896_BF_INTPOLAMPS= 0x29e0, /*!< flag_enbl_amp_int_pol */
+ TFA9896_BF_INTPOLAREFS= 0x29f0, /*!< flag_enbl_ref_int_pol */
+ TFA9896_BF_INTPOLERR= 0x2b00, /*!< flag_cfma_err_int_pol */
+ TFA9896_BF_INTPOLACK= 0x2b10, /*!< flag_cfma_ack_int_pol */
+ TFA9896_BF_CLIP = 0x4900, /*!< Bypass clip control */
+ TFA9896_BF_CIMTP = 0x62b0, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9896_BF_RST = 0x7000, /*!< Reset CoolFlux DSP */
+ TFA9896_BF_DMEM = 0x7011, /*!< Target memory for access */
+ TFA9896_BF_AIF = 0x7030, /*!< Auto increment flag for memory-address */
+ TFA9896_BF_CFINT = 0x7040, /*!< CF Interrupt - auto clear */
+ TFA9896_BF_REQ = 0x7087, /*!< CF request for accessing the 8 channels */
+ TFA9896_BF_MADD = 0x710f, /*!< Memory address */
+ TFA9896_BF_MEMA = 0x720f, /*!< Activate memory access */
+ TFA9896_BF_ERR = 0x7307, /*!< CF error flags */
+ TFA9896_BF_ACK = 0x7387, /*!< CF acknowledgement of the requests channels */
+ TFA9896_BF_MTPOTC= 0x8000, /*!< Calibration schedule selection */
+ TFA9896_BF_MTPEX = 0x8010, /*!< Calibration of RON status bit */
+} TFA9896BfEnumList_t;
+#define TFA9896_NAMETABLE static tfaBfName_t Tfa9896DatasheetNames[]= {\
+ { 0x0, "VDDS"}, /* Power-on-reset flag (auto clear by reading) , */\
+ { 0x10, "PLLS"}, /* PLL lock to programmed frequency , */\
+ { 0x20, "OTDS"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "OVDS"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "UVDS"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "OCDS"}, /* Over Current Protection alarm , */\
+ { 0x60, "CLKS"}, /* Clocks stable flag , */\
+ { 0x70, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x80, "MTPB"}, /* MTP busy copying data to/from I2C registers , */\
+ { 0x90, "NOCLK"}, /* lost clock detection (reference input clock) , */\
+ { 0xa0, "SPKS"}, /* Speaker error , */\
+ { 0xb0, "ACS"}, /* Cold Start required , */\
+ { 0xc0, "SWS"}, /* Amplifier engage (Amp Switching) , */\
+ { 0xd0, "WDS"}, /* watchdog reset (activates reset) , */\
+ { 0xe0, "AMPS"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "AREFS"}, /* References are enabled by manager , */\
+ { 0x109, "BATS"}, /* Battery voltage from ADC readout , */\
+ { 0x208, "TEMPS"}, /* Temperature readout from the temperature sensor ( C), */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x420, "RCV"}, /* Enable receiver mode , */\
+ { 0x431, "CHS12"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "INPLVL"}, /* Input level selection attenuator ( , */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x4c3, "AUDFS"}, /* Audio sample rate setting , */\
+ { 0x501, "BSSCR"}, /* Batteery protection attack time , */\
+ { 0x523, "BSST"}, /* Battery protection threshold level , */\
+ { 0x561, "BSSRL"}, /* Battery protection maximum reduction , */\
+ { 0x582, "BSSRR"}, /* Battery protection release time , */\
+ { 0x5b1, "BSSHY"}, /* Battery Protection Hysteresis , */\
+ { 0x5e0, "BSSR"}, /* Battery voltage value for read out (only) , */\
+ { 0x5f0, "BSSBY"}, /* Bypass clipper battery protection , */\
+ { 0x600, "DPSA"}, /* Enable dynamic powerstage activation (DPSA) , */\
+ { 0x613, "ATTEN"}, /* Gain attenuation setting , */\
+ { 0x650, "CFSM"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "BSSS"}, /* Battery sense steepness , */\
+ { 0x687, "VOL"}, /* Coolflux volume control , */\
+ { 0x702, "DCVO2"}, /* Second Boost Voltage , */\
+ { 0x733, "DCMCC"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x772, "DCVO1"}, /* First Boost Voltage , */\
+ { 0x7a0, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7b0, "DCSR"}, /* Soft Rampup/down mode for DCDC controller , */\
+ { 0x7c0, "DCPAVG"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x7d0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x800, "TROS"}, /* Selection ambient temperature for speaker calibration , */\
+ { 0x818, "EXTTS"}, /* External temperature for speaker calibration (C) , */\
+ { 0x900, "PWDN"}, /* powerdown selection , */\
+ { 0x910, "I2CR"}, /* All I2C registers reset to default , */\
+ { 0x920, "CFE"}, /* Enable CoolFlux , */\
+ { 0x930, "AMPE"}, /* Enable Amplifier , */\
+ { 0x940, "DCA"}, /* Enable DCDC Boost converter , */\
+ { 0x950, "SBSL"}, /* Coolflux configured , */\
+ { 0x960, "AMPC"}, /* Selection if Coolflux enables amplifier , */\
+ { 0x970, "DCDIS"}, /* DCDC boost converter not connected , */\
+ { 0x980, "PSDR"}, /* IDDQ amplifier test selection , */\
+ { 0x9c1, "INTPAD"}, /* INT pad (interrupt bump output) configuration , */\
+ { 0x9e0, "IPLL"}, /* PLL input reference clock selection , */\
+ { 0xa04, "DCTRIP"}, /* Adaptive boost trip levels (effective only when boost_intel is set to 1), */\
+ { 0xa54, "DCHOLD"}, /* Hold time for DCDC booster (effective only when boost_intel is set to 1), */\
+ { 0xb07, "MTPK"}, /* KEY2 to access key2 protected registers (default for engineering), */\
+ { 0xc25, "CVFDLY"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0xec0, "OPENMTP"}, /* Enable programming of the MTP memory , */\
+ { 0x1011, "TDMPRF"}, /* TDM usecase selection control , */\
+ { 0x1030, "TDMEN"}, /* TDM interface enable , */\
+ { 0x1040, "TDMCKINV"}, /* TDM clock inversion, receive on , */\
+ { 0x1053, "TDMFSLN"}, /* TDM FS length , */\
+ { 0x1090, "TDMFSPOL"}, /* TDM FS polarity (start frame) , */\
+ { 0x10a4, "TDMSAMSZ"}, /* TDM sample size for all TDM sinks and sources , */\
+ { 0x1103, "TDMSLOTS"}, /* TDM number of slots , */\
+ { 0x1144, "TDMSLLN"}, /* TDM slot length , */\
+ { 0x1194, "TDMBRMG"}, /* TDM bits remaining after the last slot , */\
+ { 0x11e0, "TDMDDEL"}, /* TDM data delay , */\
+ { 0x11f0, "TDMDADJ"}, /* TDM data adjustment , */\
+ { 0x1201, "TDMTXFRM"}, /* TDM TXDATA format , */\
+ { 0x1221, "TDMUUS0"}, /* TDM TXDATA format unused slot SD0 , */\
+ { 0x1241, "TDMUUS1"}, /* TDM TXDATA format unused slot SD1 , */\
+ { 0x1270, "TDMSI0EN"}, /* TDM sink0 enable , */\
+ { 0x1280, "TDMSI1EN"}, /* TDM sink1 enable , */\
+ { 0x1290, "TDMSI2EN"}, /* TDM sink2 enable , */\
+ { 0x12a0, "TDMSO0EN"}, /* TDM source0 enable , */\
+ { 0x12b0, "TDMSO1EN"}, /* TDM source1 enable , */\
+ { 0x12c0, "TDMSO2EN"}, /* TDM source2 enable , */\
+ { 0x12d0, "TDMSI0IO"}, /* TDM sink0 IO selection , */\
+ { 0x12e0, "TDMSI1IO"}, /* TDM sink1 IO selection , */\
+ { 0x12f0, "TDMSI2IO"}, /* TDM sink2 IO selection , */\
+ { 0x1300, "TDMSO0IO"}, /* TDM source0 IO selection , */\
+ { 0x1310, "TDMSO1IO"}, /* TDM source1 IO selection , */\
+ { 0x1320, "TDMSO2IO"}, /* TDM source2 IO selection , */\
+ { 0x1333, "TDMSI0SL"}, /* TDM sink0 slot position [GAIN IN] , */\
+ { 0x1373, "TDMSI1SL"}, /* TDM sink1 slot position [CH1 IN] , */\
+ { 0x13b3, "TDMSI2SL"}, /* TDM sink2 slot position [CH2 IN] , */\
+ { 0x1403, "TDMSO0SL"}, /* TDM source0 slot position [GAIN OUT] , */\
+ { 0x1443, "TDMSO1SL"}, /* TDM source1 slot position [Voltage Sense] , */\
+ { 0x1483, "TDMSO2SL"}, /* TDM source2 slot position [Current Sense] , */\
+ { 0x14c3, "NBCK"}, /* TDM NBCK bit clock ratio , */\
+ { 0x2000, "INTOVDDS"}, /* flag_por_int_out , */\
+ { 0x2010, "INTOPLLS"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "INTOOTDS"}, /* flag_otpok_int_out , */\
+ { 0x2030, "INTOOVDS"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "INTOUVDS"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "INTOOCDS"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "INTOCLKS"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "INTOCLIPS"}, /* flag_clip_int_out , */\
+ { 0x2080, "INTOMTPB"}, /* mtp_busy_int_out , */\
+ { 0x2090, "INTONOCLK"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "INTOSPKS"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "INTOACS"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "INTOSWS"}, /* flag_engage_int_out , */\
+ { 0x20d0, "INTOWDS"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "INTOAMPS"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "INTOAREFS"}, /* flag_enbl_ref_int_out , */\
+ { 0x2200, "INTOERR"}, /* flag_cfma_err_int_out , */\
+ { 0x2210, "INTOACK"}, /* flag_cfma_ack_int_out , */\
+ { 0x2300, "INTIVDDS"}, /* flag_por_int_in , */\
+ { 0x2310, "INTIPLLS"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "INTIOTDS"}, /* flag_otpok_int_in , */\
+ { 0x2330, "INTIOVDS"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "INTIUVDS"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "INTIOCDS"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "INTICLKS"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "INTICLIPS"}, /* flag_clip_int_in , */\
+ { 0x2380, "INTIMTPB"}, /* mtp_busy_int_in , */\
+ { 0x2390, "INTINOCLK"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "INTISPKS"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "INTIACS"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "INTISWS"}, /* flag_engage_int_in , */\
+ { 0x23d0, "INTIWDS"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "INTIAMPS"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "INTIAREFS"}, /* flag_enbl_ref_int_in , */\
+ { 0x2500, "INTIERR"}, /* flag_cfma_err_int_in , */\
+ { 0x2510, "INTIACK"}, /* flag_cfma_ack_int_in , */\
+ { 0x2600, "INTENVDDS"}, /* flag_por_int_enable , */\
+ { 0x2610, "INTENPLLS"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "INTENOTDS"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "INTENOVDS"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "INTENUVDS"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "INTENOCDS"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "INTENCLKS"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "INTENCLIPS"}, /* flag_clip_int_enable , */\
+ { 0x2680, "INTENMTPB"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "INTENNOCLK"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "INTENSPKS"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "INTENACS"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "INTENSWS"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "INTENWDS"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "INTENAMPS"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "INTENAREFS"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2800, "INTENERR"}, /* flag_cfma_err_int_enable , */\
+ { 0x2810, "INTENACK"}, /* flag_cfma_ack_int_enable , */\
+ { 0x2900, "INTPOLVDDS"}, /* flag_por_int_pol , */\
+ { 0x2910, "INTPOLPLLS"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "INTPOLOTDS"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "INTPOLOVDS"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "INTPOLUVDS"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "INTPOLOCDS"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "INTPOLCLKS"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "INTPOLCLIPS"}, /* flag_clip_int_pol , */\
+ { 0x2980, "INTPOLMTPB"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "INTPOLNOCLK"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "INTPOLSPKS"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "INTPOLACS"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "INTPOLSWS"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "INTPOLWDS"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "INTPOLAMPS"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "INTPOLAREFS"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2b00, "INTPOLERR"}, /* flag_cfma_err_int_pol , */\
+ { 0x2b10, "INTPOLACK"}, /* flag_cfma_ack_int_pol , */\
+ { 0x4900, "CLIP"}, /* Bypass clip control , */\
+ { 0x62b0, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0x7000, "RST"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "DMEM"}, /* Target memory for access , */\
+ { 0x7030, "AIF"}, /* Auto increment flag for memory-address , */\
+ { 0x7040, "CFINT"}, /* CF Interrupt - auto clear , */\
+ { 0x7087, "REQ"}, /* CF request for accessing the 8 channels , */\
+ { 0x710f, "MADD"}, /* Memory address , */\
+ { 0x720f, "MEMA"}, /* Activate memory access , */\
+ { 0x7307, "ERR"}, /* CF error flags , */\
+ { 0x7387, "ACK"}, /* CF acknowledgement of the requests channels , */\
+ { 0x8000, "MTPOTC"}, /* Calibration schedule selection , */\
+ { 0x8010, "MTPEX"}, /* Calibration of RON status bit , */\
+ { 0x8045, "SWPROFIL" },\
+ { 0x80a5, "SWVSTEP" },\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9896_BITNAMETABLE static tfaBfName_t Tfa9896BitNames[]= {\
+ { 0x0, "flag_por"}, /* Power-on-reset flag (auto clear by reading) , */\
+ { 0x10, "flag_pll_lock"}, /* PLL lock to programmed frequency , */\
+ { 0x20, "flag_otpok"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "flag_ovpok"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "flag_uvpok"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "flag_ocp_alarm"}, /* Over Current Protection alarm , */\
+ { 0x60, "flag_clocks_stable"}, /* Clocks stable flag , */\
+ { 0x70, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x80, "mtp_busy"}, /* MTP busy copying data to/from I2C registers , */\
+ { 0x90, "flag_lost_clk"}, /* lost clock detection (reference input clock) , */\
+ { 0xa0, "flag_cf_speakererror"}, /* Speaker error , */\
+ { 0xb0, "flag_cold_started"}, /* Cold Start required , */\
+ { 0xc0, "flag_engage"}, /* Amplifier engage (Amp Switching) , */\
+ { 0xd0, "flag_watchdog_reset"}, /* watchdog reset (activates reset) , */\
+ { 0xe0, "flag_enbl_amp"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "flag_enbl_ref"}, /* References are enabled by manager , */\
+ { 0x109, "bat_adc"}, /* Battery voltage from ADC readout , */\
+ { 0x208, "temp_adc"}, /* Temperature readout from the temperature sensor ( C), */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x420, "ctrl_rcv"}, /* Enable receiver mode , */\
+ { 0x431, "chan_sel"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "input_level"}, /* Input level selection attenuator ( , */\
+ { 0x461, "vamp_sel"}, /* Input selection for amplifier , */\
+ { 0x4c3, "audio_fs"}, /* Audio sample rate setting , */\
+ { 0x501, "vbat_prot_attacktime"}, /* Batteery protection attack time , */\
+ { 0x523, "vbat_prot_thlevel"}, /* Battery protection threshold level , */\
+ { 0x561, "vbat_prot_max_reduct"}, /* Battery protection maximum reduction , */\
+ { 0x582, "vbat_prot_release_t"}, /* Battery protection release time , */\
+ { 0x5b1, "vbat_prot_hysterese"}, /* Battery Protection Hysteresis , */\
+ { 0x5d0, "reset_min_vbat"}, /* Battery supply safeguard clipper reset ( if CF_DSP is bypassed), */\
+ { 0x5e0, "sel_vbat"}, /* Battery voltage value for read out (only) , */\
+ { 0x5f0, "bypass_clipper"}, /* Bypass clipper battery protection , */\
+ { 0x600, "dpsa"}, /* Enable dynamic powerstage activation (DPSA) , */\
+ { 0x613, "ctrl_att"}, /* Gain attenuation setting , */\
+ { 0x650, "cf_mute"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "batsense_steepness"}, /* Battery sense steepness , */\
+ { 0x687, "vol"}, /* Coolflux volume control , */\
+ { 0x702, "scnd_boost_voltage"}, /* Second Boost Voltage , */\
+ { 0x733, "boost_cur"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x772, "frst_boost_voltage"}, /* First Boost Voltage , */\
+ { 0x7a0, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7b0, "boost_speed"}, /* Soft Rampup/down mode for DCDC controller , */\
+ { 0x7c0, "boost_peak2avg"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x7d0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7e0, "ignore_flag_voutcomp86"}, /* Ignore flag_voutcomp86 (flag from analog) , */\
+ { 0x800, "ext_temp_sel"}, /* Selection ambient temperature for speaker calibration , */\
+ { 0x818, "ext_temp"}, /* External temperature for speaker calibration (C) , */\
+ { 0x900, "powerdown"}, /* powerdown selection , */\
+ { 0x910, "reset"}, /* All I2C registers reset to default , */\
+ { 0x920, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x930, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x940, "enbl_boost"}, /* Enable DCDC Boost converter , */\
+ { 0x950, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x960, "sel_enbl_amplifier"}, /* Selection if Coolflux enables amplifier , */\
+ { 0x970, "dcdcoff_mode"}, /* DCDC boost converter not connected , */\
+ { 0x980, "iddqtest"}, /* IDDQ amplifier test selection , */\
+ { 0x9c1, "int_pad_io"}, /* INT pad (interrupt bump output) configuration , */\
+ { 0x9e0, "sel_fs_bck"}, /* PLL input reference clock selection , */\
+ { 0x9f0, "sel_scl_cf_clock"}, /* Coolflux sub-system clock selection , */\
+ { 0xa04, "boost_trip_lvl"}, /* Adaptive boost trip levels (effective only when boost_intel is set to 1), */\
+ { 0xa54, "boost_hold_time"}, /* Hold time for DCDC booster (effective only when boost_intel is set to 1), */\
+ { 0xaa1, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0xb07, "mtpkey2"}, /* KEY2 to access key2 protected registers (default for engineering), */\
+ { 0xc00, "enbl_volt_sense"}, /* Voltage sense enabling control bit , */\
+ { 0xc10, "vsense_pwm_sel"}, /* Voltage sense source selection , */\
+ { 0xc25, "vi_frac_delay"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0xc80, "sel_voltsense_out"}, /* TDM output data selection for AEC , */\
+ { 0xc90, "vsense_bypass_avg"}, /* Voltage sense average block bypass , */\
+ { 0xd05, "cf_frac_delay"}, /* Fractional delay adjustment between current and voltage sense by firmware, */\
+ { 0xe00, "bypass_dcdc_curr_prot"}, /* Control to switch off dcdc current reduction with bat protection, */\
+ { 0xe10, "bypass_ocp"}, /* Bypass OCP (digital IP block) , */\
+ { 0xe20, "ocptest"}, /* ocptest (analog IP block) enable , */\
+ { 0xe80, "disable_clock_sh_prot"}, /* Disable clock_sh protection , */\
+ { 0xe92, "reserve_reg_15_09"}, /* Spare control bits for future usage , */\
+ { 0xec0, "unprotect_mtp"}, /* Enable programming of the MTP memory , */\
+ { 0xed2, "reserve_reg_15_13"}, /* Spare control bits for future usage , */\
+ { 0xf00, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode forcing each 50us a pwm pulse , */\
+ { 0xf11, "dcdc_ctrl_maxzercnt"}, /* DCDC number of zero current flags required to go to pfm mode, */\
+ { 0xf36, "dcdc_vbat_delta_detect"}, /* DCDC threshold required on a delta Vbat (in PFM mode) switching to PWM mode, */\
+ { 0xfa0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x1011, "tdm_usecase"}, /* TDM usecase selection control , */\
+ { 0x1030, "tdm_enable"}, /* TDM interface enable , */\
+ { 0x1040, "tdm_clk_inversion"}, /* TDM clock inversion, receive on , */\
+ { 0x1053, "tdm_fs_ws_length"}, /* TDM FS length , */\
+ { 0x1090, "tdm_fs_ws_polarity"}, /* TDM FS polarity (start frame) , */\
+ { 0x10a4, "tdm_sample_size"}, /* TDM sample size for all TDM sinks and sources , */\
+ { 0x1103, "tdm_nb_of_slots"}, /* TDM number of slots , */\
+ { 0x1144, "tdm_slot_length"}, /* TDM slot length , */\
+ { 0x1194, "tdm_bits_remaining"}, /* TDM bits remaining after the last slot , */\
+ { 0x11e0, "tdm_data_delay"}, /* TDM data delay , */\
+ { 0x11f0, "tdm_data_adjustment"}, /* TDM data adjustment , */\
+ { 0x1201, "tdm_txdata_format"}, /* TDM TXDATA format , */\
+ { 0x1221, "tdm_txdata_format_unused_slot_sd0"}, /* TDM TXDATA format unused slot SD0 , */\
+ { 0x1241, "tdm_txdata_format_unused_slot_sd1"}, /* TDM TXDATA format unused slot SD1 , */\
+ { 0x1270, "tdm_sink0_enable"}, /* TDM sink0 enable , */\
+ { 0x1280, "tdm_sink1_enable"}, /* TDM sink1 enable , */\
+ { 0x1290, "tdm_sink2_enable"}, /* TDM sink2 enable , */\
+ { 0x12a0, "tdm_source0_enable"}, /* TDM source0 enable , */\
+ { 0x12b0, "tdm_source1_enable"}, /* TDM source1 enable , */\
+ { 0x12c0, "tdm_source2_enable"}, /* TDM source2 enable , */\
+ { 0x12d0, "tdm_sink0_io"}, /* TDM sink0 IO selection , */\
+ { 0x12e0, "tdm_sink1_io"}, /* TDM sink1 IO selection , */\
+ { 0x12f0, "tdm_sink2_io"}, /* TDM sink2 IO selection , */\
+ { 0x1300, "tdm_source0_io"}, /* TDM source0 IO selection , */\
+ { 0x1310, "tdm_source1_io"}, /* TDM source1 IO selection , */\
+ { 0x1320, "tdm_source2_io"}, /* TDM source2 IO selection , */\
+ { 0x1333, "tdm_sink0_slot"}, /* TDM sink0 slot position [GAIN IN] , */\
+ { 0x1373, "tdm_sink1_slot"}, /* TDM sink1 slot position [CH1 IN] , */\
+ { 0x13b3, "tdm_sink2_slot"}, /* TDM sink2 slot position [CH2 IN] , */\
+ { 0x1403, "tdm_source0_slot"}, /* TDM source0 slot position [GAIN OUT] , */\
+ { 0x1443, "tdm_source1_slot"}, /* TDM source1 slot position [Voltage Sense] , */\
+ { 0x1483, "tdm_source2_slot"}, /* TDM source2 slot position [Current Sense] , */\
+ { 0x14c3, "tdm_nbck"}, /* TDM NBCK bit clock ratio , */\
+ { 0x1500, "flag_tdm_lut_error"}, /* TDM LUT error flag , */\
+ { 0x1512, "flag_tdm_status"}, /* TDM interface status bits , */\
+ { 0x1540, "flag_tdm_error"}, /* TDM interface error indicator , */\
+ { 0x1551, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x2000, "flag_por_int_out"}, /* flag_por_int_out , */\
+ { 0x2010, "flag_pll_lock_int_out"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "flag_otpok_int_out"}, /* flag_otpok_int_out , */\
+ { 0x2030, "flag_ovpok_int_out"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "flag_uvpok_int_out"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "flag_ocp_alarm_int_out"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "flag_clocks_stable_int_out"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "flag_clip_int_out"}, /* flag_clip_int_out , */\
+ { 0x2080, "mtp_busy_int_out"}, /* mtp_busy_int_out , */\
+ { 0x2090, "flag_lost_clk_int_out"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "flag_cf_speakererror_int_out"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "flag_cold_started_int_out"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "flag_engage_int_out"}, /* flag_engage_int_out , */\
+ { 0x20d0, "flag_watchdog_reset_int_out"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "flag_enbl_amp_int_out"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "flag_enbl_ref_int_out"}, /* flag_enbl_ref_int_out , */\
+ { 0x2100, "flag_voutcomp_int_out"}, /* flag_voutcomp_int_out , */\
+ { 0x2110, "flag_voutcomp93_int_out"}, /* flag_voutcomp93_int_out , */\
+ { 0x2120, "flag_voutcomp86_int_out"}, /* flag_voutcomp86_int_out , */\
+ { 0x2130, "flag_hiz_int_out"}, /* flag_hiz_int_out , */\
+ { 0x2140, "flag_ocpokbst_int_out"}, /* flag_ocpokbst_int_out , */\
+ { 0x2150, "flag_peakcur_int_out"}, /* flag_peakcur_int_out , */\
+ { 0x2160, "flag_ocpokap_int_out"}, /* flag_ocpokap_int_out , */\
+ { 0x2170, "flag_ocpokan_int_out"}, /* flag_ocpokan_int_out , */\
+ { 0x2180, "flag_ocpokbp_int_out"}, /* flag_ocpokbp_int_out , */\
+ { 0x2190, "flag_ocpokbn_int_out"}, /* flag_ocpokbn_int_out , */\
+ { 0x21a0, "flag_adc10_ready_int_out"}, /* flag_adc10_ready_int_out , */\
+ { 0x21b0, "flag_clipa_high_int_out"}, /* flag_clipa_high_int_out , */\
+ { 0x21c0, "flag_clipa_low_int_out"}, /* flag_clipa_low_int_out , */\
+ { 0x21d0, "flag_clipb_high_int_out"}, /* flag_clipb_high_int_out , */\
+ { 0x21e0, "flag_clipb_low_int_out"}, /* flag_clipb_low_int_out , */\
+ { 0x21f0, "flag_tdm_error_int_out"}, /* flag_tdm_error_int_out , */\
+ { 0x2200, "flag_cfma_err_int_out"}, /* flag_cfma_err_int_out , */\
+ { 0x2210, "flag_cfma_ack_int_out"}, /* flag_cfma_ack_int_out , */\
+ { 0x2300, "flag_por_int_in"}, /* flag_por_int_in , */\
+ { 0x2310, "flag_pll_lock_int_in"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "flag_otpok_int_in"}, /* flag_otpok_int_in , */\
+ { 0x2330, "flag_ovpok_int_in"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "flag_uvpok_int_in"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "flag_ocp_alarm_int_in"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "flag_clocks_stable_int_in"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "flag_clip_int_in"}, /* flag_clip_int_in , */\
+ { 0x2380, "mtp_busy_int_in"}, /* mtp_busy_int_in , */\
+ { 0x2390, "flag_lost_clk_int_in"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "flag_cf_speakererror_int_in"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "flag_cold_started_int_in"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "flag_engage_int_in"}, /* flag_engage_int_in , */\
+ { 0x23d0, "flag_watchdog_reset_int_in"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "flag_enbl_amp_int_in"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "flag_enbl_ref_int_in"}, /* flag_enbl_ref_int_in , */\
+ { 0x2400, "flag_voutcomp_int_in"}, /* flag_voutcomp_int_in , */\
+ { 0x2410, "flag_voutcomp93_int_in"}, /* flag_voutcomp93_int_in , */\
+ { 0x2420, "flag_voutcomp86_int_in"}, /* flag_voutcomp86_int_in , */\
+ { 0x2430, "flag_hiz_int_in"}, /* flag_hiz_int_in , */\
+ { 0x2440, "flag_ocpokbst_int_in"}, /* flag_ocpokbst_int_in , */\
+ { 0x2450, "flag_peakcur_int_in"}, /* flag_peakcur_int_in , */\
+ { 0x2460, "flag_ocpokap_int_in"}, /* flag_ocpokap_int_in , */\
+ { 0x2470, "flag_ocpokan_int_in"}, /* flag_ocpokan_int_in , */\
+ { 0x2480, "flag_ocpokbp_int_in"}, /* flag_ocpokbp_int_in , */\
+ { 0x2490, "flag_ocpokbn_int_in"}, /* flag_ocpokbn_int_in , */\
+ { 0x24a0, "flag_adc10_ready_int_in"}, /* flag_adc10_ready_int_in , */\
+ { 0x24b0, "flag_clipa_high_int_in"}, /* flag_clipa_high_int_in , */\
+ { 0x24c0, "flag_clipa_low_int_in"}, /* flag_clipa_low_int_in , */\
+ { 0x24d0, "flag_clipb_high_int_in"}, /* flag_clipb_high_int_in , */\
+ { 0x24e0, "flag_clipb_low_int_in"}, /* flag_clipb_low_int_in , */\
+ { 0x24f0, "flag_tdm_error_int_in"}, /* flag_tdm_error_int_in , */\
+ { 0x2500, "flag_cfma_err_int_in"}, /* flag_cfma_err_int_in , */\
+ { 0x2510, "flag_cfma_ack_int_in"}, /* flag_cfma_ack_int_in , */\
+ { 0x2600, "flag_por_int_enable"}, /* flag_por_int_enable , */\
+ { 0x2610, "flag_pll_lock_int_enable"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "flag_otpok_int_enable"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "flag_ovpok_int_enable"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "flag_uvpok_int_enable"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "flag_ocp_alarm_int_enable"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "flag_clocks_stable_int_enable"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "flag_clip_int_enable"}, /* flag_clip_int_enable , */\
+ { 0x2680, "mtp_busy_int_enable"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "flag_lost_clk_int_enable"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "flag_cf_speakererror_int_enable"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "flag_cold_started_int_enable"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "flag_engage_int_enable"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "flag_watchdog_reset_int_enable"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "flag_enbl_amp_int_enable"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "flag_enbl_ref_int_enable"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2700, "flag_voutcomp_int_enable"}, /* flag_voutcomp_int_enable , */\
+ { 0x2710, "flag_voutcomp93_int_enable"}, /* flag_voutcomp93_int_enable , */\
+ { 0x2720, "flag_voutcomp86_int_enable"}, /* flag_voutcomp86_int_enable , */\
+ { 0x2730, "flag_hiz_int_enable"}, /* flag_hiz_int_enable , */\
+ { 0x2740, "flag_ocpokbst_int_enable"}, /* flag_ocpokbst_int_enable , */\
+ { 0x2750, "flag_peakcur_int_enable"}, /* flag_peakcur_int_enable , */\
+ { 0x2760, "flag_ocpokap_int_enable"}, /* flag_ocpokap_int_enable , */\
+ { 0x2770, "flag_ocpokan_int_enable"}, /* flag_ocpokan_int_enable , */\
+ { 0x2780, "flag_ocpokbp_int_enable"}, /* flag_ocpokbp_int_enable , */\
+ { 0x2790, "flag_ocpokbn_int_enable"}, /* flag_ocpokbn_int_enable , */\
+ { 0x27a0, "flag_adc10_ready_int_enable"}, /* flag_adc10_ready_int_enable , */\
+ { 0x27b0, "flag_clipa_high_int_enable"}, /* flag_clipa_high_int_enable , */\
+ { 0x27c0, "flag_clipa_low_int_enable"}, /* flag_clipa_low_int_enable , */\
+ { 0x27d0, "flag_clipb_high_int_enable"}, /* flag_clipb_high_int_enable , */\
+ { 0x27e0, "flag_clipb_low_int_enable"}, /* flag_clipb_low_int_enable , */\
+ { 0x27f0, "flag_tdm_error_int_enable"}, /* flag_tdm_error_int_enable , */\
+ { 0x2800, "flag_cfma_err_int_enable"}, /* flag_cfma_err_int_enable , */\
+ { 0x2810, "flag_cfma_ack_int_enable"}, /* flag_cfma_ack_int_enable , */\
+ { 0x2900, "flag_por_int_pol"}, /* flag_por_int_pol , */\
+ { 0x2910, "flag_pll_lock_int_pol"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "flag_otpok_int_pol"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "flag_ovpok_int_pol"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "flag_uvpok_int_pol"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "flag_ocp_alarm_int_pol"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "flag_clocks_stable_int_pol"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "flag_clip_int_pol"}, /* flag_clip_int_pol , */\
+ { 0x2980, "mtp_busy_int_pol"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "flag_lost_clk_int_pol"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "flag_cf_speakererror_int_pol"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "flag_cold_started_int_pol"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "flag_engage_int_pol"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "flag_watchdog_reset_int_pol"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "flag_enbl_amp_int_pol"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "flag_enbl_ref_int_pol"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2a00, "flag_voutcomp_int_pol"}, /* flag_voutcomp_int_pol , */\
+ { 0x2a10, "flag_voutcomp93_int_pol"}, /* flag_voutcomp93_int_pol , */\
+ { 0x2a20, "flag_voutcomp86_int_pol"}, /* flag_voutcomp86_int_pol , */\
+ { 0x2a30, "flag_hiz_int_pol"}, /* flag_hiz_int_pol , */\
+ { 0x2a40, "flag_ocpokbst_int_pol"}, /* flag_ocpokbst_int_pol , */\
+ { 0x2a50, "flag_peakcur_int_pol"}, /* flag_peakcur_int_pol , */\
+ { 0x2a60, "flag_ocpokap_int_pol"}, /* flag_ocpokap_int_pol , */\
+ { 0x2a70, "flag_ocpokan_int_pol"}, /* flag_ocpokan_int_pol , */\
+ { 0x2a80, "flag_ocpokbp_int_pol"}, /* flag_ocpokbp_int_pol , */\
+ { 0x2a90, "flag_ocpokbn_int_pol"}, /* flag_ocpokbn_int_pol , */\
+ { 0x2aa0, "flag_adc10_ready_int_pol"}, /* flag_adc10_ready_int_pol , */\
+ { 0x2ab0, "flag_clipa_high_int_pol"}, /* flag_clipa_high_int_pol , */\
+ { 0x2ac0, "flag_clipa_low_int_pol"}, /* flag_clipa_low_int_pol , */\
+ { 0x2ad0, "flag_clipb_high_int_pol"}, /* flag_clipb_high_int_pol , */\
+ { 0x2ae0, "flag_clipb_low_int_pol"}, /* flag_clipb_low_int_pol , */\
+ { 0x2af0, "flag_tdm_error_int_pol"}, /* flag_tdm_error_int_pol , */\
+ { 0x2b00, "flag_cfma_err_int_pol"}, /* flag_cfma_err_int_pol , */\
+ { 0x2b10, "flag_cfma_ack_int_pol"}, /* flag_cfma_ack_int_pol , */\
+ { 0x3000, "flag_voutcomp"}, /* Status flag_voutcomp, indication Vset is larger than Vbat, */\
+ { 0x3010, "flag_voutcomp93"}, /* Status flag_voutcomp93, indication Vset is larger than 1.07 x Vbat, */\
+ { 0x3020, "flag_voutcomp86"}, /* Status flag voutcomp86, indication Vset is larger than 1.14 x Vbat, */\
+ { 0x3030, "flag_hiz"}, /* Status flag_hiz, indication Vbst is larger than Vbat, */\
+ { 0x3040, "flag_ocpokbst"}, /* Status flag_ocpokbst, indication no over current in boost converter PMOS switch, */\
+ { 0x3050, "flag_peakcur"}, /* Status flag_peakcur, indication current is max in dcdc converter, */\
+ { 0x3060, "flag_ocpokap"}, /* Status flag_ocpokap, indication no over current in amplifier A PMOS output stage, */\
+ { 0x3070, "flag_ocpokan"}, /* Status flag_ocpokan, indication no over current in amplifier A NMOS output stage, */\
+ { 0x3080, "flag_ocpokbp"}, /* Status flag_ocpokbp, indication no over current in amplifier B PMOS output stage, */\
+ { 0x3090, "flag_ocpokbn"}, /* Status flag_ocpokbn, indication no over current in amplifier B NMOS output stage, */\
+ { 0x30a0, "flag_adc10_ready"}, /* Status flag_adc10_ready, indication adc10 is ready, */\
+ { 0x30b0, "flag_clipa_high"}, /* Status flag_clipa_high, indication pmos amplifier A is clipping, */\
+ { 0x30c0, "flag_clipa_low"}, /* Status flag_clipa_low, indication nmos amplifier A is clipping, */\
+ { 0x30d0, "flag_clipb_high"}, /* Status flag_clipb_high, indication pmos amplifier B is clipping, */\
+ { 0x30e0, "flag_clipb_low"}, /* Status flag_clipb_low, indication nmos amplifier B is clipping, */\
+ { 0x310f, "mtp_man_data_out"}, /* MTP manual read out data , */\
+ { 0x3200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0x3210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0x3225, "mtp_ecc_tcout"}, /* MTP error correction test data out , */\
+ { 0x3280, "mtpctrl_valid_test_rd"}, /* MTP test readout for read , */\
+ { 0x3290, "mtpctrl_valid_test_wr"}, /* MTP test readout for write , */\
+ { 0x32a0, "flag_in_alarm_state"}, /* Flag alarm state , */\
+ { 0x32b0, "mtp_ecc_err2"}, /* Two or more bit errors detected in MTP, can not reconstruct value, */\
+ { 0x32c0, "mtp_ecc_err1"}, /* One bit error detected in MTP, reconstructed value, */\
+ { 0x32d0, "mtp_mtp_hvf"}, /* High voltage ready flag for MTP , */\
+ { 0x32f0, "mtp_zero_check_fail"}, /* Zero check failed for MTP , */\
+ { 0x3309, "data_adc10_tempbat"}, /* ADC10 data output for testing battery voltage and temperature, */\
+ { 0x400f, "hid_code"}, /* 5A6Bh, 23147d to access hidden registers (default for engineering), */\
+ { 0x4100, "bypass_hp"}, /* Bypass High Pass Filter , */\
+ { 0x4110, "hard_mute"}, /* Hard Mute , */\
+ { 0x4120, "soft_mute"}, /* Soft Mute , */\
+ { 0x4134, "pwm_delay"}, /* PWM delay setting , */\
+ { 0x4180, "pwm_shape"}, /* PWM Shape , */\
+ { 0x4190, "pwm_bitlength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4203, "drive"}, /* Drive bits to select number of amplifier power stages, */\
+ { 0x4240, "reclock_pwm"}, /* Control for enabling reclocking of PWM signal , */\
+ { 0x4250, "reclock_voltsense"}, /* Control for enabling reclocking of voltage sense signal, */\
+ { 0x4281, "dpsalevel"}, /* DPSA threshold level , */\
+ { 0x42a1, "dpsa_release"}, /* DPSA release time , */\
+ { 0x42c0, "coincidence"}, /* Prevent simultaneously switching of output stage , */\
+ { 0x42d0, "kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x4306, "drivebst"}, /* Drive bits to select the power transistor sections boost converter, */\
+ { 0x4370, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x4381, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x43a0, "ocptestbst"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0); For new ocp (ctrl_reversebst is 1), */\
+ { 0x43d0, "test_abistfft_enbl"}, /* FFT Coolflux , */\
+ { 0x43e0, "bst_dcmbst"}, /* DCM mode control for DCDC during I2C direct control mode, */\
+ { 0x43f0, "test_bcontrol"}, /* test_bcontrol , */\
+ { 0x4400, "reversebst"}, /* OverCurrent Protection selection of power stage boost converter, */\
+ { 0x4410, "sensetest"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0x4420, "enbl_engagebst"}, /* Enable power stage of dcdc controller , */\
+ { 0x4470, "enbl_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x4480, "enbl_voutcomp"}, /* Enable vout comparators , */\
+ { 0x4490, "enbl_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x44a0, "enbl_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x44b0, "enbl_hizcom"}, /* Enable hiz comparator , */\
+ { 0x44c0, "enbl_peakcur"}, /* Enable peak current , */\
+ { 0x44d0, "bypass_ovpglitch"}, /* Bypass OVP Glitch Filter , */\
+ { 0x44e0, "enbl_windac"}, /* Enable window dac , */\
+ { 0x44f0, "enbl_powerbst"}, /* Enable line of the powerstage , */\
+ { 0x4507, "ocp_thr"}, /* OCP threshold level , */\
+ { 0x4580, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0x4590, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0x45a0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0x45b0, "bypass_otp"}, /* Bypass OTP , */\
+ { 0x45d0, "bypass_ocpcounter"}, /* Bypass OCP counter , */\
+ { 0x45e0, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0x45f0, "vpalarm"}, /* vpalarm (UVP/OUP handling) , */\
+ { 0x4600, "bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x4610, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x4627, "cs_gain"}, /* Current sense gain , */\
+ { 0x46a0, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x46b0, "bypass_pwmcounter"}, /* Bypass PWM Counter , */\
+ { 0x46c0, "cs_negfixed"}, /* Current sense does not switch to neg , */\
+ { 0x46d2, "cs_neghyst"}, /* Current sense switches to neg depending on hyseteris level, */\
+ { 0x4700, "switch_fb"}, /* Current sense control switch_fb , */\
+ { 0x4713, "se_hyst"}, /* Current sense control se_hyst , */\
+ { 0x4754, "se_level"}, /* Current sense control se_level , */\
+ { 0x47a5, "ktemp"}, /* Current sense control temperature compensation trimming, */\
+ { 0x4800, "cs_negin"}, /* Current sense control negin , */\
+ { 0x4810, "cs_sein"}, /* Current sense control cs_sein , */\
+ { 0x4820, "cs_coincidence"}, /* Coincidence current sense , */\
+ { 0x4830, "iddqtestbst"}, /* IDDQ testing in powerstage of DCDC boost converter, */\
+ { 0x4840, "coincidencebst"}, /* Switch protection on to prevent simultaneously switching power stages bst and amp, */\
+ { 0x4876, "delay_se_neg"}, /* delay of se and neg , */\
+ { 0x48e1, "cs_ttrack"}, /* Sample and hold track time , */\
+ { 0x4900, "bypass_clip"}, /* Bypass clip control , */\
+ { 0x4920, "cf_cgate_off"}, /* Disable clock gating in the coolflux , */\
+ { 0x4940, "clipfast"}, /* Clock selection for HW clipper for battery safeguard, */\
+ { 0x4950, "cs_8ohm"}, /* 8 ohm mode for current sense (gain mode) , */\
+ { 0x4974, "delay_clock_sh"}, /* delay_sh, tunes S7H delay , */\
+ { 0x49c0, "inv_clksh"}, /* Invert the sample/hold clock for current sense ADC, */\
+ { 0x49d0, "inv_neg"}, /* Invert neg signal , */\
+ { 0x49e0, "inv_se"}, /* Invert se signal , */\
+ { 0x49f0, "setse"}, /* Switches between Single Ended and differential mode; 1 is single ended, */\
+ { 0x4a12, "adc10_sel"}, /* Select the input to convert the 10b ADC , */\
+ { 0x4a60, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0x4a81, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0x4aa0, "bypass_lp_vbat"}, /* LP filter in batt sensor , */\
+ { 0x4ae0, "dc_offset"}, /* Current sense decimator offset control , */\
+ { 0x4af0, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0x4b00, "adc13_iset"}, /* MICADC setting of current consumption (debug use only), */\
+ { 0x4b14, "adc13_gain"}, /* MICADC gain setting (two's complement format) , */\
+ { 0x4b61, "adc13_slowdel"}, /* MICADC delay setting for internal clock (debug use only), */\
+ { 0x4b83, "adc13_offset"}, /* MICADC offset setting , */\
+ { 0x4bc0, "adc13_bsoinv"}, /* MICADC bit stream output invert mode for test , */\
+ { 0x4bd0, "adc13_resonator_enable"}, /* MICADC give extra SNR with less stability (debug use only), */\
+ { 0x4be0, "testmicadc"}, /* Mux at input of MICADC for test purpose , */\
+ { 0x4c0f, "abist_offset"}, /* Offset control for ABIST testing , */\
+ { 0x4d05, "windac"}, /* For testing direct control windac , */\
+ { 0x4dc3, "pwm_dcc_cnt"}, /* control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0x4e04, "slopecur"}, /* For testing direct control slopecur , */\
+ { 0x4e50, "ctrl_dem"}, /* Dynamic element matching control, rest of codes are optional, */\
+ { 0x4ed0, "enbl_pwm_dcc"}, /* Enable direct control of pwm duty cycle , */\
+ { 0x4f00, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x4f10, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x4f20, "bst_ctrl_azbst"}, /* Control of auto-zeroing of zero current comparator, */\
+ { 0x5007, "gain"}, /* Gain setting of the gain multiplier , */\
+ { 0x5081, "sourceb"}, /* PWM OUTB selection control , */\
+ { 0x50a1, "sourcea"}, /* PWM OUTA selection control , */\
+ { 0x50c1, "sourcebst"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0x50e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0x5104, "pulselengthbst"}, /* Pulse length setting test input for boost converter, */\
+ { 0x5150, "bypasslatchbst"}, /* Bypass latch in boost converter , */\
+ { 0x5160, "invertbst"}, /* Invert pwmbst test signal , */\
+ { 0x5174, "pulselength"}, /* Pulse length setting test input for amplifier , */\
+ { 0x51c0, "bypasslatch"}, /* Bypass latch in PWM source selection module , */\
+ { 0x51d0, "invertb"}, /* invert pwmb test signal , */\
+ { 0x51e0, "inverta"}, /* invert pwma test signal , */\
+ { 0x51f0, "bypass_ctrlloop"}, /* bypass_ctrlloop bypasses the control loop of the amplifier, */\
+ { 0x5210, "test_rdsona"}, /* tbd for rdson testing , */\
+ { 0x5220, "test_rdsonb"}, /* tbd for rdson testing , */\
+ { 0x5230, "test_rdsonbst"}, /* tbd for rdson testing , */\
+ { 0x5240, "test_cvia"}, /* tbd for rdson testing , */\
+ { 0x5250, "test_cvib"}, /* tbd for rdson testing , */\
+ { 0x5260, "test_cvibst"}, /* tbd for rdson testing , */\
+ { 0x5306, "digimuxa_sel"}, /* DigimuxA input selection control (see Digimux list for details), */\
+ { 0x5376, "digimuxb_sel"}, /* DigimuxB input selection control (see Digimux list for details), */\
+ { 0x5400, "hs_mode"}, /* I2C high speed mode selection control , */\
+ { 0x5412, "test_parametric_io"}, /* Control for parametric tests of IO cells , */\
+ { 0x5440, "enbl_ringo"}, /* Enable ring oscillator control, for test purpose to check with ringo, */\
+ { 0x5456, "digimuxc_sel"}, /* DigimuxC input selection control (see Digimux list for details), */\
+ { 0x54c0, "dio_ehs"}, /* Slew control for DIO in output mode , */\
+ { 0x54d0, "gainio_ehs"}, /* Slew control for GAINIO in output mode , */\
+ { 0x550d, "enbl_amp"}, /* enbl_amp for testing to enable all analoge blocks in amplifier, */\
+ { 0x5600, "use_direct_ctrls"}, /* Use direct controls to overrule several functions for testing - I2C direct control mode, */\
+ { 0x5610, "rst_datapath"}, /* Reset datapath during direct control mode , */\
+ { 0x5620, "rst_cgu"}, /* Reset CGU during durect control mode , */\
+ { 0x5637, "enbl_ref"}, /* For testing to enable all analoge blocks in references, */\
+ { 0x56b0, "enbl_engage"}, /* Enable output stage amplifier , */\
+ { 0x56c0, "use_direct_clk_ctrl"}, /* use_direct_clk_ctrl, to overrule several functions direct for testing, */\
+ { 0x56d0, "use_direct_pll_ctrl"}, /* use_direct_pll_ctrl, to overrule several functions direct for testing, */\
+ { 0x5707, "anamux"}, /* Anamux control , */\
+ { 0x57e0, "otptest"}, /* otptest, test mode otp amplifier , */\
+ { 0x57f0, "reverse"}, /* 1b = Normal mode, slope is controlled , */\
+ { 0x5813, "pll_selr"}, /* PLL pll_selr , */\
+ { 0x5854, "pll_selp"}, /* PLL pll_selp , */\
+ { 0x58a5, "pll_seli"}, /* PLL pll_seli , */\
+ { 0x5950, "pll_mdec_msb"}, /* Most significant bits of pll_mdec[16] , */\
+ { 0x5960, "pll_ndec_msb"}, /* Most significant bits of pll_ndec[9] , */\
+ { 0x5970, "pll_frm"}, /* PLL pll_frm , */\
+ { 0x5980, "pll_directi"}, /* PLL pll_directi , */\
+ { 0x5990, "pll_directo"}, /* PLL pll_directo , */\
+ { 0x59a0, "enbl_pll"}, /* PLL enbl_pll , */\
+ { 0x59f0, "pll_bypass"}, /* PLL bypass , */\
+ { 0x5a0f, "tsig_freq"}, /* Internal sinus test generator frequency control LSB bits, */\
+ { 0x5b02, "tsig_freq_msb"}, /* Select internal sine wave generator, frequency control MSB bits, */\
+ { 0x5b30, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0x5b44, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0x5c0f, "pll_mdec"}, /* PLL MDEC - I2C direct PLL control mode only , */\
+ { 0x5d06, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0x5d78, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0x6007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0x6185, "mtp_ecc_tcin"}, /* MTP ECC TCIN data , */\
+ { 0x6203, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0x6260, "mtp_ecc_eeb"}, /* Enable code bit generation (active low!) , */\
+ { 0x6270, "mtp_ecc_ecb"}, /* Enable correction signal (active low!) , */\
+ { 0x6280, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0x6290, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0x62a0, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0x62b0, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0x62d2, "mtp_speed_mode"}, /* MTP speed mode , */\
+ { 0x6340, "mtp_direct_enable"}, /* mtp_direct_enable , */\
+ { 0x6350, "mtp_direct_wr"}, /* mtp_direct_wr , */\
+ { 0x6360, "mtp_direct_rd"}, /* mtp_direct_rd , */\
+ { 0x6370, "mtp_direct_rst"}, /* mtp_direct_rst , */\
+ { 0x6380, "mtp_direct_ers"}, /* mtp_direct_ers , */\
+ { 0x6390, "mtp_direct_prg"}, /* mtp_direct_prg , */\
+ { 0x63a0, "mtp_direct_epp"}, /* mtp_direct_epp , */\
+ { 0x63b4, "mtp_direct_test"}, /* mtp_direct_test , */\
+ { 0x640f, "mtp_man_data_in"}, /* Write data for MTP manual write , */\
+ { 0x7000, "cf_rst_dsp"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "cf_dmem"}, /* Target memory for access , */\
+ { 0x7030, "cf_aif"}, /* Auto increment flag for memory-address , */\
+ { 0x7040, "cf_int"}, /* CF Interrupt - auto clear , */\
+ { 0x7087, "cf_req"}, /* CF request for accessing the 8 channels , */\
+ { 0x710f, "cf_madd"}, /* Memory address , */\
+ { 0x720f, "cf_mema"}, /* Activate memory access , */\
+ { 0x7307, "cf_err"}, /* CF error flags , */\
+ { 0x7387, "cf_ack"}, /* CF acknowledgement of the requests channels , */\
+ { 0x8000, "calibration_onetime"}, /* Calibration schedule selection , */\
+ { 0x8010, "calibr_ron_done"}, /* Calibration of RON status bit , */\
+ { 0x8105, "calibr_vout_offset"}, /* calibr_vout_offset (DCDCoffset) 2's compliment (key1 protected), */\
+ { 0x8163, "calibr_delta_gain"}, /* delta gain for vamp (alpha) 2's compliment (key1 protected), */\
+ { 0x81a5, "calibr_offs_amp"}, /* offset for vamp (Ampoffset) 2's compliment (key1 protected), */\
+ { 0x8207, "calibr_gain_cs"}, /* gain current sense (Imeasalpha) 2's compliment (key1 protected), */\
+ { 0x8284, "calibr_temp_offset"}, /* temperature offset 2's compliment (key1 protected), */\
+ { 0x82d2, "calibr_temp_gain"}, /* temperature gain 2's compliment (key1 protected) , */\
+ { 0x830f, "calibr_ron"}, /* calibration value of the RON resistance of the coil, */\
+ { 0x8505, "type_bits_hw"}, /* bit0 = disable function dcdcoff_mode ($09[7]) , */\
+ { 0x8601, "type_bits_1_0_sw"}, /* MTP control SW , */\
+ { 0x8681, "type_bits_9_8_sw"}, /* MTP control SW , */\
+ { 0x870f, "type_bits2_sw"}, /* MTP-control SW2 , */\
+ { 0x8806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0x8870, "htol_iic_addr_en"}, /* HTOL I2C_Address_Enable , */\
+ { 0x8881, "ctrl_ovp_response"}, /* OVP response control , */\
+ { 0x88a0, "disable_ovp_alarm_state"}, /* OVP alarm state control , */\
+ { 0x88b0, "enbl_stretch_ovp"}, /* OVP alram strech control , */\
+ { 0x88c0, "cf_debug_mode"}, /* Coolflux debug mode , */\
+ { 0x8a0f, "production_data1"}, /* production_data1 , */\
+ { 0x8b0f, "production_data2"}, /* production_data2 , */\
+ { 0x8c0f, "production_data3"}, /* production_data3 , */\
+ { 0x8d0f, "production_data4"}, /* production_data4 , */\
+ { 0x8e0f, "production_data5"}, /* production_data5 , */\
+ { 0x8f0f, "production_data6"}, /* production_data6 , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum TFA9896_irq {
+ TFA9896_irq_vdds = 0,
+ TFA9896_irq_plls = 1,
+ TFA9896_irq_ds = 2,
+ TFA9896_irq_vds = 3,
+ TFA9896_irq_uvds = 4,
+ TFA9896_irq_cds = 5,
+ TFA9896_irq_clks = 6,
+ TFA9896_irq_clips = 7,
+ TFA9896_irq_mtpb = 8,
+ TFA9896_irq_clk = 9,
+ TFA9896_irq_spks = 10,
+ TFA9896_irq_acs = 11,
+ TFA9896_irq_sws = 12,
+ TFA9896_irq_wds = 13,
+ TFA9896_irq_amps = 14,
+ TFA9896_irq_arefs = 15,
+ TFA9896_irq_err = 32,
+ TFA9896_irq_ack = 33,
+ TFA9896_irq_max = 34,
+ TFA9896_irq_all = -1 /* all irqs */};
+
+#define TFA9896_IRQ_NAMETABLE static tfaIrqName_t TFA9896IrqNames[]= {\
+ { 0, "VDDS"},\
+ { 1, "PLLS"},\
+ { 2, "DS"},\
+ { 3, "VDS"},\
+ { 4, "UVDS"},\
+ { 5, "CDS"},\
+ { 6, "CLKS"},\
+ { 7, "CLIPS"},\
+ { 8, "MTPB"},\
+ { 9, "CLK"},\
+ { 10, "SPKS"},\
+ { 11, "ACS"},\
+ { 12, "SWS"},\
+ { 13, "WDS"},\
+ { 14, "AMPS"},\
+ { 15, "AREFS"},\
+ { 16, "16"},\
+ { 17, "17"},\
+ { 18, "18"},\
+ { 19, "19"},\
+ { 20, "20"},\
+ { 21, "21"},\
+ { 22, "22"},\
+ { 23, "23"},\
+ { 24, "24"},\
+ { 25, "25"},\
+ { 26, "26"},\
+ { 27, "27"},\
+ { 28, "28"},\
+ { 29, "29"},\
+ { 30, "30"},\
+ { 31, "31"},\
+ { 32, "ERR"},\
+ { 33, "ACK"},\
+ { 34, "34"},\
+};
+#endif /* _TFA9896_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c
new file mode 100644
index 00000000000..7058604d504
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c
@@ -0,0 +1,3391 @@
+/*
+ * tfa98xx.c tfa98xx codec module
+ *
+ *
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#define pr_fmt(fmt) "%s(): " fmt, __func__
+
+#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/debugfs.h>
+#include <linux/version.h>
+#include <linux/input.h>
+#include "config.h"
+#include "tfa98xx.h"
+#include "tfa.h"
+
+ /* required for enum tfa9912_irq */
+#include "tfa98xx_tfafieldnames.h"
+
+#define TFA98XX_VERSION TFA98XX_API_REV_STR
+
+#define I2C_RETRIES 50
+#define I2C_RETRY_DELAY 5 /* ms */
+
+/* Change volume selection behavior:
+ * Uncomment following line to generate a profile change when updating
+ * a volume control (also changes to the profile of the modified volume
+ * control)
+ */
+ /*#define TFA98XX_ALSA_CTRL_PROF_CHG_ON_VOL 1
+ */
+
+ /* Supported rates and data formats */
+#define TFA98XX_RATES SNDRV_PCM_RATE_8000_48000
+#define TFA98XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define TF98XX_MAX_DSP_START_TRY_COUNT 10
+
+/* data accessible by all instances */
+static struct kmem_cache *tfa98xx_cache = NULL; /* Memory pool used for DSP messages */
+/* Mutex protected data */
+static DEFINE_MUTEX(tfa98xx_mutex);
+static LIST_HEAD(tfa98xx_device_list);
+static int tfa98xx_device_count = 0;
+static int tfa98xx_sync_count = 0;
+static LIST_HEAD(profile_list); /* list of user selectable profiles */
+static int tfa98xx_mixer_profiles = 0; /* number of user selectable profiles */
+static int tfa98xx_mixer_profile = 0; /* current mixer profile */
+static struct snd_kcontrol_new *tfa98xx_controls;
+static TfaContainer_t *tfa98xx_container = NULL;
+
+static int tfa98xx_kmsg_regs = 0;
+static int tfa98xx_ftrace_regs = 0;
+
+static char *fw_name = "tfa98xx.cnt";
+module_param(fw_name, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(fw_name, "TFA98xx DSP firmware (container file) name.");
+
+static int trace_level = 0;
+module_param(trace_level, int, S_IRUGO);
+MODULE_PARM_DESC(trace_level, "TFA98xx debug trace level (0=off, bits:1=verbose,2=regdmesg,3=regftrace,4=timing).");
+
+static char *dflt_prof_name = "";
+module_param(dflt_prof_name, charp, S_IRUGO);
+
+static int no_start = 0;
+module_param(no_start, int, S_IRUGO);
+MODULE_PARM_DESC(no_start, "do not start the work queue; for debugging via user\n");
+
+static int no_reset = 0;
+module_param(no_reset, int, S_IRUGO);
+MODULE_PARM_DESC(no_reset, "do not use the reset line; for debugging via user\n");
+
+static int pcm_sample_format = 0; /*Be carefull: setting pcm_sample_format to 3 means TDM settings will be dynamically adapted, please do not set the
+HW TDM Setting in the container file in case of dynamic sample format seletcion*/
+module_param(pcm_sample_format, int, S_IRUGO);
+MODULE_PARM_DESC(pcm_sample_format, "PCM sample format: 0=S16_LE, 1=S24_LE, 2=S32_LE, 3=dynamic\n");
+
+static int pcm_no_constraint = 0;
+module_param(pcm_no_constraint, int, S_IRUGO);
+MODULE_PARM_DESC(pcm_no_constraint, "do not use constraints for PCM parameters\n");
+
+static void tfa98xx_tapdet_check_update(struct tfa98xx *tfa98xx);
+static int tfa98xx_get_fssel(unsigned int rate);
+static void tfa98xx_interrupt_enable(struct tfa98xx *tfa98xx, bool enable);
+
+static int get_profile_from_list(char *buf, int id);
+static int get_profile_id_for_sr(int id, unsigned int rate);
+
+struct tfa98xx_rate {
+ unsigned int rate;
+ unsigned int fssel;
+};
+
+static const struct tfa98xx_rate rate_to_fssel[] = {
+ { 8000, 0 },
+ { 11025, 1 },
+ { 12000, 2 },
+ { 16000, 3 },
+ { 22050, 4 },
+ { 24000, 5 },
+ { 32000, 6 },
+ { 44100, 7 },
+ { 48000, 8 },
+};
+
+
+static inline char *tfa_cont_profile_name(struct tfa98xx *tfa98xx, int prof_idx)
+{
+ if (tfa98xx->tfa->cnt == NULL)
+ return NULL;
+ return tfaContProfileName(tfa98xx->tfa->cnt, tfa98xx->tfa->dev_idx, prof_idx);
+}
+
+static enum tfa_error tfa98xx_write_re25(struct tfa_device *tfa, int value)
+{
+ enum tfa_error err;
+
+ /* clear MTPEX */
+ err = tfa_dev_mtp_set(tfa, TFA_MTP_EX, 0);
+ if (err == tfa_error_ok) {
+ /* set RE25 in shadow regiser */
+ err = tfa_dev_mtp_set(tfa, TFA_MTP_RE25_PRIM, value);
+ }
+ if (err == tfa_error_ok) {
+ /* set MTPEX to copy RE25 into MTP */
+ err = tfa_dev_mtp_set(tfa, TFA_MTP_EX, 2);
+ }
+
+ return err;
+}
+
+/* Wrapper for tfa start */
+static enum tfa_error tfa98xx_tfa_start(struct tfa98xx *tfa98xx, int next_profile, int vstep)
+{
+ enum tfa_error err;
+ ktime_t start_time, stop_time;
+ u64 delta_time;
+
+ start_time = ktime_get_boottime();
+ err = tfa_dev_start(tfa98xx->tfa, next_profile, vstep);
+
+ if (trace_level & 8) {
+ stop_time = ktime_get_boottime();
+ delta_time = ktime_to_ns(ktime_sub(stop_time, start_time));
+ do_div(delta_time, 1000);
+ dev_dbg(&tfa98xx->i2c->dev, "tfa_dev_start(%d,%d) time = %lld us\n",
+ next_profile, vstep, delta_time);
+ }
+
+ if ((err == tfa_error_ok) && (tfa98xx->set_mtp_cal)) {
+ enum tfa_error err_cal;
+ err_cal = tfa98xx_write_re25(tfa98xx->tfa, tfa98xx->cal_data);
+ if (err_cal != tfa_error_ok) {
+ pr_err("Error, setting calibration value in mtp, err=%d\n", err_cal);
+ }
+ else {
+ tfa98xx->set_mtp_cal = false;
+ pr_info("Calibration value (%d) set in mtp\n",
+ tfa98xx->cal_data);
+ }
+ }
+
+ /* Check and update tap-detection state (in case of profile change) */
+ tfa98xx_tapdet_check_update(tfa98xx);
+
+ /* Remove sticky bit by reading it once */
+ tfa_get_noclk(tfa98xx->tfa);
+
+ /* A cold start erases the configuration, including interrupts setting.
+ * Restore it if required
+ */
+ tfa98xx_interrupt_enable(tfa98xx, true);
+
+ return err;
+}
+
+static int tfa98xx_input_open(struct input_dev *dev)
+{
+ struct tfa98xx *tfa98xx = input_get_drvdata(dev);
+ dev_dbg(tfa98xx->codec->dev, "opening device file\n");
+
+ /* note: open function is called only once by the framework.
+ * No need to count number of open file instances.
+ */
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK) {
+ dev_dbg(&tfa98xx->i2c->dev,
+ "DSP not loaded, cannot start tap-detection\n");
+ return -EIO;
+ }
+
+ /* enable tap-detection service */
+ tfa98xx->tapdet_open = true;
+ tfa98xx_tapdet_check_update(tfa98xx);
+
+ return 0;
+}
+
+static void tfa98xx_input_close(struct input_dev *dev)
+{
+ struct tfa98xx *tfa98xx = input_get_drvdata(dev);
+
+ dev_dbg(tfa98xx->codec->dev, "closing device file\n");
+
+ /* Note: close function is called if the device is unregistered */
+
+ /* disable tap-detection service */
+ tfa98xx->tapdet_open = false;
+ tfa98xx_tapdet_check_update(tfa98xx);
+}
+
+static int tfa98xx_register_inputdev(struct tfa98xx *tfa98xx)
+{
+ int err;
+ struct input_dev *input;
+ input = input_allocate_device();
+
+ if (!input) {
+ dev_err(tfa98xx->codec->dev, "Unable to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ input->evbit[0] = BIT_MASK(EV_KEY);
+ input->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
+ input->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
+ input->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
+ input->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+ input->keybit[BIT_WORD(BTN_4)] |= BIT_MASK(BTN_4);
+ input->keybit[BIT_WORD(BTN_5)] |= BIT_MASK(BTN_5);
+ input->keybit[BIT_WORD(BTN_6)] |= BIT_MASK(BTN_6);
+ input->keybit[BIT_WORD(BTN_7)] |= BIT_MASK(BTN_7);
+ input->keybit[BIT_WORD(BTN_8)] |= BIT_MASK(BTN_8);
+ input->keybit[BIT_WORD(BTN_9)] |= BIT_MASK(BTN_9);
+
+ input->open = tfa98xx_input_open;
+ input->close = tfa98xx_input_close;
+
+ input->name = "tfa98xx-tapdetect";
+
+ input->id.bustype = BUS_I2C;
+ input_set_drvdata(input, tfa98xx);
+
+ err = input_register_device(input);
+ if (err) {
+ dev_err(tfa98xx->codec->dev, "Unable to register input device\n");
+ goto err_free_dev;
+ }
+
+ dev_dbg(tfa98xx->codec->dev, "Input device for tap-detection registered: %s\n",
+ input->name);
+ tfa98xx->input = input;
+ return 0;
+
+err_free_dev:
+ input_free_device(input);
+ return err;
+}
+
+/*
+ * Check if an input device for tap-detection can and shall be registered.
+ * Register it if appropriate.
+ * If already registered, check if still relevant and remove it if necessary.
+ * unregister: true to request inputdev unregistration.
+ */
+static void __tfa98xx_inputdev_check_register(struct tfa98xx *tfa98xx, bool unregister)
+{
+ bool tap_profile = false;
+ unsigned int i;
+ for (i = 0; i < tfa_cnt_get_dev_nprof(tfa98xx->tfa); i++) {
+ if (strstr(tfa_cont_profile_name(tfa98xx, i), ".tap")) {
+ tap_profile = true;
+ tfa98xx->tapdet_profiles |= 1 << i;
+ dev_dbg(tfa98xx->codec->dev,
+ "found a tap-detection profile (%d - %s)\n",
+ i, tfa_cont_profile_name(tfa98xx, i));
+ }
+ }
+
+ /* Check for device support:
+ * - at device level
+ * - at container (profile) level
+ */
+ if (!(tfa98xx->flags & TFA98XX_FLAG_TAPDET_AVAILABLE) ||
+ !tap_profile ||
+ unregister) {
+ /* No input device supported or required */
+ if (tfa98xx->input) {
+ input_unregister_device(tfa98xx->input);
+ tfa98xx->input = NULL;
+ }
+ return;
+ }
+
+ /* input device required */
+ if (tfa98xx->input)
+ dev_dbg(tfa98xx->codec->dev, "Input device already registered, skipping\n");
+ else
+ tfa98xx_register_inputdev(tfa98xx);
+}
+
+static void tfa98xx_inputdev_check_register(struct tfa98xx *tfa98xx)
+{
+ __tfa98xx_inputdev_check_register(tfa98xx, false);
+}
+
+static void tfa98xx_inputdev_unregister(struct tfa98xx *tfa98xx)
+{
+ __tfa98xx_inputdev_check_register(tfa98xx, true);
+}
+
+#ifdef CONFIG_DEBUG_FS
+/* OTC reporting
+ * Returns the MTP0 OTC bit value
+ */
+static int tfa98xx_dbgfs_otc_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int value;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ value = tfa_dev_mtp_get(tfa98xx->tfa, TFA_MTP_OTC);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (value < 0) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, value);
+ return -EIO;
+ }
+
+ *val = value;
+ /* pr_debug("[0x%x] OTC : %d\n", tfa98xx->i2c->addr, value); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_otc_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error err;
+
+ if (val != 0 && val != 1) {
+ pr_err("[0x%x] Unexpected value %llu\n", tfa98xx->i2c->addr, val);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ err = tfa_dev_mtp_set(tfa98xx->tfa, TFA_MTP_OTC, val);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (err != tfa_error_ok) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, err);
+ return -EIO;
+ }
+
+ /* pr_debug("[0x%x] OTC < %llu\n", tfa98xx->i2c->addr, val); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_mtpex_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int value;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ value = tfa_dev_mtp_get(tfa98xx->tfa, TFA_MTP_EX);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (value < 0) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, value);
+ return -EIO;
+ }
+
+
+ *val = value;
+ /* pr_debug("[0x%x] MTPEX : %d\n", tfa98xx->i2c->addr, value); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_mtpex_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error err;
+
+ if (val != 0) {
+ pr_err("[0x%x] Can only clear MTPEX (0 value expected)\n", tfa98xx->i2c->addr);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ err = tfa_dev_mtp_set(tfa98xx->tfa, TFA_MTP_EX, val);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (err != tfa_error_ok) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, err);
+ return -EIO;
+ }
+
+ /* pr_debug("[0x%x] MTPEX < 0\n", tfa98xx->i2c->addr); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_temp_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ *val = tfa98xx_get_exttemp(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ /* pr_debug("[0x%x] TEMP : %llu\n", tfa98xx->i2c->addr, *val); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_temp_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa98xx_set_exttemp(tfa98xx->tfa, (short)val);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ /* pr_debug("[0x%x] TEMP < %llu\n", tfa98xx->i2c->addr, val); */
+
+ return 0;
+}
+
+static ssize_t tfa98xx_dbgfs_start_set(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error ret;
+ char buf[32];
+ const char ref[] = "please calibrate now";
+ int buf_size, cal_profile = 0;
+
+ /* check string length, and account for eol */
+ if (count > sizeof(ref) + 1 || count < (sizeof(ref) - 1))
+ return -EINVAL;
+
+ buf_size = min(count, (size_t)(sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ /* Compare string, excluding the trailing \0 and the potentials eol */
+ if (strncmp(buf, ref, sizeof(ref) - 1))
+ return -EINVAL;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa_calibrate(tfa98xx->tfa);
+ if (ret == tfa_error_ok) {
+ cal_profile = tfaContGetCalProfile(tfa98xx->tfa);
+ if (cal_profile < 0) {
+ pr_warn("[0x%x] Calibration profile not found\n",
+ tfa98xx->i2c->addr);
+ }
+
+ ret = tfa98xx_tfa_start(tfa98xx, cal_profile, tfa98xx->vstep);
+ }
+ if (ret == tfa_error_ok)
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (ret) {
+ pr_info("[0x%x] Calibration start failed (%d)\n", tfa98xx->i2c->addr, ret);
+ return -EIO;
+ }
+ else {
+ pr_info("[0x%x] Calibration started\n", tfa98xx->i2c->addr);
+ }
+
+ return count;
+}
+
+static ssize_t tfa98xx_dbgfs_r_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ char *str;
+ uint16_t status;
+ int ret;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+
+ /* Need to ensure DSP is access-able, use mtp read access for this
+ * purpose
+ */
+ ret = tfa98xx_get_mtp(tfa98xx->tfa, &status);
+ if (ret) {
+ ret = -EIO;
+ pr_err("[0x%x] MTP read failed\n", tfa98xx->i2c->addr);
+ goto r_c_err;
+ }
+
+ ret = tfaRunSpeakerCalibration(tfa98xx->tfa);
+ if (ret) {
+ ret = -EIO;
+ pr_err("[0x%x] calibration failed\n", tfa98xx->i2c->addr);
+ goto r_c_err;
+ }
+
+ str = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!str) {
+ ret = -ENOMEM;
+ pr_err("[0x%x] memory allocation failed\n", tfa98xx->i2c->addr);
+ goto r_c_err;
+ }
+
+ if (tfa98xx->tfa->spkr_count > 1) {
+ ret = snprintf(str, PAGE_SIZE,
+ "Prim:%d mOhms, Sec:%d mOhms\n",
+ tfa98xx->tfa->mohm[0],
+ tfa98xx->tfa->mohm[1]);
+ }
+ else {
+ ret = snprintf(str, PAGE_SIZE,
+ "Prim:%d mOhms\n",
+ tfa98xx->tfa->mohm[0]);
+ }
+
+ /* pr_debug("[0x%x] calib_done: %s", tfa98xx->i2c->addr, str); */
+
+ if (ret < 0)
+ goto r_err;
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, str, ret);
+
+r_err:
+ kfree(str);
+r_c_err:
+ mutex_unlock(&tfa98xx->dsp_lock);
+ return ret;
+}
+
+static ssize_t tfa98xx_dbgfs_version_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ char str[] = TFA98XX_VERSION "\n";
+ int ret;
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, str, sizeof(str));
+
+ return ret;
+}
+
+static ssize_t tfa98xx_dbgfs_dsp_state_get(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int ret = 0;
+ char *str;
+
+ switch (tfa98xx->dsp_init) {
+ case TFA98XX_DSP_INIT_STOPPED:
+ str = "Stopped\n";
+ break;
+ case TFA98XX_DSP_INIT_RECOVER:
+ str = "Recover requested\n";
+ break;
+ case TFA98XX_DSP_INIT_FAIL:
+ str = "Failed init\n";
+ break;
+ case TFA98XX_DSP_INIT_PENDING:
+ str = "Pending init\n";
+ break;
+ case TFA98XX_DSP_INIT_DONE:
+ str = "Init complete\n";
+ break;
+ default:
+ str = "Invalid\n";
+ }
+
+ /* pr_debug("[0x%x] dsp_state : %s\n", tfa98xx->i2c->addr, str); */
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, str, strlen(str));
+ return ret;
+}
+
+static ssize_t tfa98xx_dbgfs_dsp_state_set(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error ret;
+ char buf[32];
+ const char start_cmd[] = "start";
+ const char stop_cmd[] = "stop";
+ const char mon_start_cmd[] = "monitor start";
+ const char mon_stop_cmd[] = "monitor stop";
+ int buf_size;
+
+ buf_size = min(count, (size_t)(sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ /* Compare strings, excluding the trailing \0 */
+ if (!strncmp(buf, start_cmd, sizeof(start_cmd) - 1)) {
+ pr_info("[0x%x] Manual triggering of dsp start...\n", tfa98xx->i2c->addr);
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ /* pr_debug("[0x%x] tfa_dev_start complete: %d\n", tfa98xx->i2c->addr, ret); */
+ }
+ else if (!strncmp(buf, stop_cmd, sizeof(stop_cmd) - 1)) {
+ pr_info("[0x%x] Manual triggering of dsp stop...\n", tfa98xx->i2c->addr);
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa_dev_stop(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ /* pr_debug("[0x%x] tfa_dev_stop complete: %d\n", tfa98xx->i2c->addr, ret); */
+ }
+ else if (!strncmp(buf, mon_start_cmd, sizeof(mon_start_cmd) - 1)) {
+ pr_info("[0x%x] Manual start of monitor thread...\n", tfa98xx->i2c->addr);
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->monitor_work, HZ);
+ }
+ else if (!strncmp(buf, mon_stop_cmd, sizeof(mon_stop_cmd) - 1)) {
+ pr_info("[0x%x] Manual stop of monitor thread...\n", tfa98xx->i2c->addr);
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+ }
+ else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t tfa98xx_dbgfs_fw_state_get(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ char *str;
+
+ switch (tfa98xx->dsp_fw_state) {
+ case TFA98XX_DSP_FW_NONE:
+ str = "None\n";
+ break;
+ case TFA98XX_DSP_FW_PENDING:
+ str = "Pending\n";
+ break;
+ case TFA98XX_DSP_FW_FAIL:
+ str = "Fail\n";
+ break;
+ case TFA98XX_DSP_FW_OK:
+ str = "Ok\n";
+ break;
+ default:
+ str = "Invalid\n";
+ }
+
+ /* pr_debug("[0x%x] fw_state : %s", tfa98xx->i2c->addr, str); */
+
+ return simple_read_from_buffer(user_buf, count, ppos, str, strlen(str));
+}
+
+static ssize_t tfa98xx_dbgfs_rpc_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int ret = 0;
+ uint8_t *buffer;
+ enum Tfa98xx_Error error;
+
+ if (tfa98xx->tfa == NULL) {
+ /* pr_debug("[0x%x] dsp is not available\n", tfa98xx->i2c->addr); */
+ return -ENODEV;
+ }
+
+ if (count == 0)
+ return 0;
+
+ buffer = kmalloc(count, GFP_KERNEL);
+ if (buffer == NULL) {
+ /* pr_debug("[0x%x] can not allocate memory\n", tfa98xx->i2c->addr); */
+ return -ENOMEM;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ error = tfa_dsp_msg_read(tfa98xx->tfa, count, buffer);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ if (error != Tfa98xx_Error_Ok) {
+ /* pr_debug("[0x%x] tfa_dsp_msg_read error: %d\n", tfa98xx->i2c->addr, error); */
+ kfree(buffer);
+ return -EFAULT;
+ }
+
+ ret = copy_to_user(user_buf, buffer, count);
+ kfree(buffer);
+ if (ret)
+ return -EFAULT;
+
+ *ppos += count;
+ return count;
+}
+
+static ssize_t tfa98xx_dbgfs_rpc_send(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ TfaFileDsc_t *msg_file;
+ enum Tfa98xx_Error error;
+ int err = 0;
+
+ if (tfa98xx->tfa == NULL) {
+ /* pr_debug("[0x%x] dsp is not available\n", tfa98xx->i2c->addr); */
+ return -ENODEV;
+ }
+
+ if (count == 0)
+ return 0;
+
+ /* msg_file.name is not used */
+ msg_file = kmalloc(count + sizeof(TfaFileDsc_t), GFP_KERNEL);
+ if (msg_file == NULL) {
+ /* pr_debug("[0x%x] can not allocate memory\n", tfa98xx->i2c->addr); */
+ return -ENOMEM;
+ }
+ msg_file->size = count;
+
+ if (copy_from_user(msg_file->data, user_buf, count))
+ return -EFAULT;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ if ((msg_file->data[0] == 'M') && (msg_file->data[1] == 'G')) {
+ error = tfaContWriteFile(tfa98xx->tfa, msg_file, 0, 0); /* int vstep_idx, int vstep_msg_idx both 0 */
+ if (error != Tfa98xx_Error_Ok) {
+ /* pr_debug("[0x%x] tfaContWriteFile error: %d\n", tfa98xx->i2c->addr, error); */
+ err = -EIO;
+ }
+ }
+ else {
+ error = tfa_dsp_msg(tfa98xx->tfa, msg_file->size, msg_file->data);
+ if (error != Tfa98xx_Error_Ok) {
+ /* pr_debug("[0x%x] dsp_msg error: %d\n", tfa98xx->i2c->addr, error); */
+ err = -EIO;
+ }
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ kfree(msg_file);
+
+ if (err)
+ return err;
+ return count;
+}
+/* -- RPC */
+
+static int tfa98xx_dbgfs_pga_gain_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ unsigned int value;
+
+ value = tfa_get_pga_gain(tfa98xx->tfa);
+ if (value < 0)
+ return -EINVAL;
+
+ *val = value;
+ return 0;
+}
+
+static int tfa98xx_dbgfs_pga_gain_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ uint16_t value;
+ int err;
+
+ value = val & 0xffff;
+ if (value > 7)
+ return -EINVAL;
+
+ err = tfa_set_pga_gain(tfa98xx->tfa, value);
+ if (err < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_calib_otc_fops, tfa98xx_dbgfs_otc_get,
+ tfa98xx_dbgfs_otc_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_calib_mtpex_fops, tfa98xx_dbgfs_mtpex_get,
+ tfa98xx_dbgfs_mtpex_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_calib_temp_fops, tfa98xx_dbgfs_temp_get,
+ tfa98xx_dbgfs_temp_set, "%llu\n");
+
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_pga_gain_fops, tfa98xx_dbgfs_pga_gain_get,
+ tfa98xx_dbgfs_pga_gain_set, "%llu\n");
+
+static const struct file_operations tfa98xx_dbgfs_calib_start_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = tfa98xx_dbgfs_start_set,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_r_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_r_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_version_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_version_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_dsp_state_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_dsp_state_get,
+ .write = tfa98xx_dbgfs_dsp_state_set,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_fw_state_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_fw_state_get,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_rpc_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_rpc_read,
+ .write = tfa98xx_dbgfs_rpc_send,
+ .llseek = default_llseek,
+};
+
+static void tfa98xx_debug_init(struct tfa98xx *tfa98xx, struct i2c_client *i2c)
+{
+ char name[50];
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s-%x", i2c->name, i2c->addr);
+ tfa98xx->dbg_dir = debugfs_create_dir(name, NULL);
+ debugfs_create_file("OTC", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_otc_fops);
+ debugfs_create_file("MTPEX", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_mtpex_fops);
+ debugfs_create_file("TEMP", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_temp_fops);
+ debugfs_create_file("calibrate", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_start_fops);
+ debugfs_create_file("R", S_IRUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_r_fops);
+ debugfs_create_file("version", S_IRUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_version_fops);
+ debugfs_create_file("dsp-state", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_dsp_state_fops);
+ debugfs_create_file("fw-state", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_fw_state_fops);
+ debugfs_create_file("rpc", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_rpc_fops);
+
+ if (tfa98xx->flags & TFA98XX_FLAG_SAAM_AVAILABLE) {
+ dev_dbg(tfa98xx->dev, "Adding pga_gain debug interface\n");
+ debugfs_create_file("pga_gain", S_IRUGO, tfa98xx->dbg_dir,
+ tfa98xx->i2c,
+ &tfa98xx_dbgfs_pga_gain_fops);
+ }
+}
+
+static void tfa98xx_debug_remove(struct tfa98xx *tfa98xx)
+{
+ if (tfa98xx->dbg_dir)
+ debugfs_remove_recursive(tfa98xx->dbg_dir);
+}
+#endif
+
+
+/* copies the profile basename (i.e. part until .) into buf */
+static void get_profile_basename(char* buf, char* profile)
+{
+ int cp_len = 0, idx = 0;
+ char *pch;
+
+ pch = strchr(profile, '.');
+ idx = pch - profile;
+ cp_len = (pch != NULL) ? idx : (int)strlen(profile);
+ memcpy(buf, profile, cp_len);
+ buf[cp_len] = 0;
+}
+
+/* return the profile name accociated with id from the profile list */
+static int get_profile_from_list(char *buf, int id)
+{
+ struct tfa98xx_baseprofile *bprof;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+ if (bprof->item_id == id) {
+ strcpy(buf, bprof->basename);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* search for the profile in the profile list */
+static int is_profile_in_list(char *profile, int len)
+{
+ struct tfa98xx_baseprofile *bprof;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+
+ if ((len == bprof->len) && (0 == strncmp(bprof->basename, profile, len)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * for the profile with id, look if the requested samplerate is
+ * supported, if found return the (container)profile for this
+ * samplerate, on error or if not found return -1
+ */
+static int get_profile_id_for_sr(int id, unsigned int rate)
+{
+ int idx = 0;
+ struct tfa98xx_baseprofile *bprof;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+ if (id == bprof->item_id) {
+ idx = tfa98xx_get_fssel(rate);
+ if (idx < 0) {
+ /* samplerate not supported */
+ return -1;
+ }
+
+ return bprof->sr_rate_sup[idx];
+ }
+ }
+
+ /* profile not found */
+ return -1;
+}
+
+/* check if this profile is a calibration profile */
+static int is_calibration_profile(char *profile)
+{
+ if (strstr(profile, ".cal") != NULL)
+ return 1;
+ return 0;
+}
+
+/*
+ * adds the (container)profile index of the samplerate found in
+ * the (container)profile to a fixed samplerate table in the (mixer)profile
+ */
+static int add_sr_to_profile(struct tfa98xx *tfa98xx, char *basename, int len, int profile)
+{
+ struct tfa98xx_baseprofile *bprof;
+ int idx = 0;
+ unsigned int sr = 0;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+ if ((len == bprof->len) && (0 == strncmp(bprof->basename, basename, len))) {
+ /* add supported samplerate for this profile */
+ sr = tfa98xx_get_profile_sr(tfa98xx->tfa, profile);
+ if (!sr) {
+ pr_err("unable to identify supported sample rate for %s\n", bprof->basename);
+ return -1;
+ }
+
+ /* get the index for this samplerate */
+ idx = tfa98xx_get_fssel(sr);
+ if (idx < 0 || idx >= TFA98XX_NUM_RATES) {
+ pr_err("invalid index for samplerate %d\n", idx);
+ return -1;
+ }
+
+ /* enter the (container)profile for this samplerate at the corresponding index */
+ bprof->sr_rate_sup[idx] = profile;
+
+ /* pr_debug("added profile:samplerate = [%d:%d] for mixer profile: %s\n", profile, sr, bprof->basename); */
+ }
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
+static struct snd_soc_codec *snd_soc_kcontrol_codec(struct snd_kcontrol *kcontrol)
+{
+ return snd_kcontrol_chip(kcontrol);
+}
+#endif
+
+static int tfa98xx_get_vstep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int mixer_profile = kcontrol->private_value;
+ int ret = 0;
+ int profile;
+
+ profile = get_profile_id_for_sr(mixer_profile, tfa98xx->rate);
+ if (profile < 0) {
+ pr_err("tfa98xx: tfa98xx_get_vstep: invalid profile %d (mixer_profile=%d, rate=%d)\n", profile, mixer_profile, tfa98xx->rate);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int vstep = tfa98xx->prof_vsteps[profile];
+
+ ucontrol->value.integer.value[tfa98xx->tfa->dev_idx] =
+ tfacont_get_max_vstep(tfa98xx->tfa, profile)
+ - vstep - 1;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return ret;
+}
+
+static int tfa98xx_set_vstep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int mixer_profile = kcontrol->private_value;
+ int profile;
+ int err = 0;
+ int change = 0;
+
+ if (no_start != 0)
+ return 0;
+
+ profile = get_profile_id_for_sr(mixer_profile, tfa98xx->rate);
+ if (profile < 0) {
+ pr_err("tfa98xx: tfa98xx_set_vstep: invalid profile %d (mixer_profile=%d, rate=%d)\n", profile, mixer_profile, tfa98xx->rate);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int vstep, vsteps;
+ int ready = 0;
+ int new_vstep;
+ int value = ucontrol->value.integer.value[tfa98xx->tfa->dev_idx];
+
+ vstep = tfa98xx->prof_vsteps[profile];
+ vsteps = tfacont_get_max_vstep(tfa98xx->tfa, profile);
+
+ if (vstep == vsteps - value - 1)
+ continue;
+
+ new_vstep = vsteps - value - 1;
+
+ if (new_vstep < 0)
+ new_vstep = 0;
+
+ tfa98xx->prof_vsteps[profile] = new_vstep;
+
+#ifndef TFA98XX_ALSA_CTRL_PROF_CHG_ON_VOL
+ if (profile == tfa98xx->profile) {
+#endif
+ /* this is the active profile, program the new vstep */
+ tfa98xx->vstep = new_vstep;
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa98xx_dsp_system_stable(tfa98xx->tfa, &ready);
+
+ if (ready) {
+ err = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ if (err) {
+ pr_err("Write vstep error: %d\n", err);
+ }
+ else {
+ /* pr_debug("Succesfully changed vstep index!\n"); */
+ change = 1;
+ }
+ }
+
+ mutex_unlock(&tfa98xx->dsp_lock);
+#ifndef TFA98XX_ALSA_CTRL_PROF_CHG_ON_VOL
+ }
+#endif
+ /* pr_debug("%d: vstep:%d, (control value: %d) - profile %d\n",
+ tfa98xx->tfa->dev_idx, new_vstep, value, profile); */
+ }
+
+ if (change) {
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ }
+
+ mutex_unlock(&tfa98xx_mutex);
+
+ return change;
+}
+
+static int tfa98xx_info_vstep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+
+ int mixer_profile = tfa98xx_mixer_profile;
+ int profile = get_profile_id_for_sr(mixer_profile, tfa98xx->rate);
+ if (profile < 0) {
+ pr_err("tfa98xx: tfa98xx_info_vstep: invalid profile %d (mixer_profile=%d, rate=%d)\n", profile, mixer_profile, tfa98xx->rate);
+ return -EINVAL;
+ }
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ mutex_lock(&tfa98xx_mutex);
+ uinfo->count = tfa98xx_device_count;
+ mutex_unlock(&tfa98xx_mutex);
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = max(0, tfacont_get_max_vstep(tfa98xx->tfa, profile) - 1);
+ /* pr_debug("vsteps count: %d [prof=%d]\n", tfacont_get_max_vstep(tfa98xx->tfa, profile),
+ profile); */
+ return 0;
+}
+
+static int tfa98xx_get_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&tfa98xx_mutex);
+ ucontrol->value.integer.value[0] = tfa98xx_mixer_profile;
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static int tfa98xx_set_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int change = 0;
+ int new_profile;
+ int prof_idx, cur_prof_idx;
+ int profile_count = tfa98xx_mixer_profiles;
+ int profile = tfa98xx_mixer_profile;
+
+ if (no_start != 0)
+ return 0;
+
+ new_profile = ucontrol->value.integer.value[0];
+ if (new_profile == profile)
+ return 0;
+
+ if ((new_profile < 0) || (new_profile >= profile_count)) {
+ pr_err("not existing profile (%d)\n", new_profile);
+ return -EINVAL;
+ }
+
+ /* get the container profile for the requested sample rate */
+ prof_idx = get_profile_id_for_sr(new_profile, tfa98xx->rate);
+ cur_prof_idx = get_profile_id_for_sr(profile, tfa98xx->rate);
+ if (prof_idx < 0 || cur_prof_idx < 0) {
+ pr_err("tfa98xx: sample rate [%d] not supported for this mixer profile [%d -> %d].\n",
+ tfa98xx->rate, profile, new_profile);
+ return 0;
+ }
+ /* pr_debug("selected container profile [%d -> %d]\n", cur_prof_idx, prof_idx); */
+ /* pr_debug("switch profile [%s -> %s]\n",
+ tfa_cont_profile_name(tfa98xx, cur_prof_idx),
+ tfa_cont_profile_name(tfa98xx, prof_idx)); */
+
+ /* update mixer profile */
+ tfa98xx_mixer_profile = new_profile;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int err;
+ int ready = 0;
+
+ /* update 'real' profile (container profile) */
+ tfa98xx->profile = prof_idx;
+ tfa98xx->vstep = tfa98xx->prof_vsteps[prof_idx];
+
+ /* Don't call tfa_dev_start() if there is no clock. */
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa98xx_dsp_system_stable(tfa98xx->tfa, &ready);
+ if (strstr(tfa_cont_profile_name(tfa98xx, cur_prof_idx), ".standby") != NULL) {
+ pr_info("Force to start at exiting from standby: [%d -> %d]\n",
+ cur_prof_idx, prof_idx);
+ ready = 1;
+ }
+ if (ready) {
+ /* Also re-enables the interrupts */
+ err = tfa98xx_tfa_start(tfa98xx, prof_idx, tfa98xx->vstep);
+ if (err) {
+ pr_info("Write profile error: %d\n", err);
+ }
+ else {
+ /* pr_debug("Changed to profile %d (vstep = %d)\n",
+ prof_idx, tfa98xx->vstep); */
+ change = 1;
+ }
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ /* Flag DSP as invalidated as the profile change may invalidate the
+ * current DSP configuration. That way, further stream start can
+ * trigger a tfa_dev_start.
+ */
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_INVALIDATED;
+ }
+
+ if (change) {
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ }
+
+ mutex_unlock(&tfa98xx_mutex);
+
+ return change;
+}
+
+static int tfa98xx_info_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ char profile_name[MAX_CONTROL_NAME] = { 0 };
+ int count = tfa98xx_mixer_profiles, err = -1;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = count;
+
+ if (uinfo->value.enumerated.item >= count)
+ uinfo->value.enumerated.item = count - 1;
+
+ err = get_profile_from_list(profile_name, uinfo->value.enumerated.item);
+ if (err != 0)
+ return -EINVAL;
+
+ strcpy(uinfo->value.enumerated.name, profile_name);
+
+ return 0;
+}
+
+static int tfa98xx_info_stop_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ mutex_lock(&tfa98xx_mutex);
+ uinfo->count = tfa98xx_device_count;
+ mutex_unlock(&tfa98xx_mutex);
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+
+ return 0;
+}
+
+static int tfa98xx_get_stop_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ ucontrol->value.integer.value[tfa98xx->tfa->dev_idx] = 0;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static int tfa98xx_set_stop_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int ready = 0;
+ int i = tfa98xx->tfa->dev_idx;
+
+ /* pr_debug("%d: %ld\n", i, ucontrol->value.integer.value[i]); */
+
+ tfa98xx_dsp_system_stable(tfa98xx->tfa, &ready);
+
+ if ((ucontrol->value.integer.value[i] != 0) && ready) {
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK)
+ continue;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_stop(tfa98xx->tfa);
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_STOPPED;
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+
+ ucontrol->value.integer.value[i] = 0;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 1;
+}
+
+static int tfa98xx_info_cal_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ mutex_lock(&tfa98xx_mutex);
+ uinfo->count = tfa98xx_device_count;
+ mutex_unlock(&tfa98xx_mutex);
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xffff; /* 16 bit value */
+
+ return 0;
+}
+
+static int tfa98xx_set_cal_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ enum tfa_error err;
+ int i = tfa98xx->tfa->dev_idx;
+
+ tfa98xx->cal_data = (uint16_t)ucontrol->value.integer.value[i];
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ err = tfa98xx_write_re25(tfa98xx->tfa, tfa98xx->cal_data);
+ tfa98xx->set_mtp_cal = (err != tfa_error_ok);
+ if (tfa98xx->set_mtp_cal == false) {
+ pr_info("Calibration value (%d) set in mtp\n",
+ tfa98xx->cal_data);
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 1;
+}
+
+static int tfa98xx_get_cal_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ ucontrol->value.integer.value[tfa98xx->tfa->dev_idx] = tfa_dev_mtp_get(tfa98xx->tfa, TFA_MTP_RE25_PRIM);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static int tfa98xx_create_controls(struct tfa98xx *tfa98xx)
+{
+ int prof, nprof, mix_index = 0;
+ int nr_controls = 0, id = 0;
+ char *name;
+ struct tfa98xx_baseprofile *bprofile;
+
+ /* Create the following controls:
+ * - enum control to select the active profile
+ * - one volume control for each profile hosting a vstep
+ * - Stop control on TFA1 devices
+ */
+
+ nr_controls = 2; /* Profile and stop control */
+
+ if (tfa98xx->flags & TFA98XX_FLAG_CALIBRATION_CTL)
+ nr_controls += 1; /* calibration */
+
+ /* allocate the tfa98xx_controls base on the nr of profiles */
+ nprof = tfa_cnt_get_dev_nprof(tfa98xx->tfa);
+ for (prof = 0; prof < nprof; prof++) {
+ if (tfacont_get_max_vstep(tfa98xx->tfa, prof))
+ nr_controls++; /* Playback Volume control */
+ }
+
+ tfa98xx_controls = devm_kzalloc(tfa98xx->codec->dev,
+ nr_controls * sizeof(tfa98xx_controls[0]), GFP_KERNEL);
+ if (!tfa98xx_controls)
+ return -ENOMEM;
+
+ /* Create a mixer item for selecting the active profile */
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+ scnprintf(name, MAX_CONTROL_NAME, "%s Profile", tfa98xx->fw.name);
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_profile;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_profile;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_profile;
+ // tfa98xx_controls[mix_index].private_value = profs; /* save number of profiles */
+ mix_index++;
+
+ /* create mixer items for each profile that has volume */
+ for (prof = 0; prof < nprof; prof++) {
+ /* create an new empty profile */
+ bprofile = devm_kzalloc(tfa98xx->codec->dev, sizeof(*bprofile), GFP_KERNEL);
+ if (!bprofile)
+ return -ENOMEM;
+
+ bprofile->len = 0;
+ bprofile->item_id = -1;
+ INIT_LIST_HEAD(&bprofile->list);
+
+ /* copy profile name into basename until the . */
+ get_profile_basename(bprofile->basename, tfa_cont_profile_name(tfa98xx, prof));
+ bprofile->len = strlen(bprofile->basename);
+
+ /*
+ * search the profile list for a profile with basename, if it is not found then
+ * add it to the list and add a new mixer control (if it has vsteps)
+ * also, if it is a calibration profile, do not add it to the list
+ */
+ if ((is_profile_in_list(bprofile->basename, bprofile->len) == 0) &&
+ is_calibration_profile(tfa_cont_profile_name(tfa98xx, prof)) == 0) {
+ /* the profile is not present, add it to the list */
+ list_add(&bprofile->list, &profile_list);
+ bprofile->item_id = id++;
+
+ /* pr_debug("profile added [%d]: %s\n", bprofile->item_id, bprofile->basename); */
+
+ if (tfacont_get_max_vstep(tfa98xx->tfa, prof)) {
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s %s Playback Volume",
+ tfa98xx->fw.name, bprofile->basename);
+
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_vstep;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_vstep;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_vstep;
+ tfa98xx_controls[mix_index].private_value = bprofile->item_id; /* save profile index */
+ mix_index++;
+ }
+ }
+
+ /* look for the basename profile in the list of mixer profiles and add the
+ container profile index to the supported samplerates of this mixer profile */
+ add_sr_to_profile(tfa98xx, bprofile->basename, bprofile->len, prof);
+ }
+
+ /* set the number of user selectable profiles in the mixer */
+ tfa98xx_mixer_profiles = id;
+
+ /* Create a mixer item for stop control on TFA1 */
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s Stop", tfa98xx->fw.name);
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_stop_ctl;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_stop_ctl;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_stop_ctl;
+ mix_index++;
+
+ if (tfa98xx->flags & TFA98XX_FLAG_CALIBRATION_CTL) {
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s Calibration", tfa98xx->fw.name);
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_cal_ctl;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_cal_ctl;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_cal_ctl;
+ mix_index++;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ return snd_soc_add_component_controls(tfa98xx->codec,
+ tfa98xx_controls, mix_index);
+#else
+ return snd_soc_add_codec_controls(tfa98xx->codec,
+ tfa98xx_controls, mix_index);
+#endif
+}
+
+static void *tfa98xx_devm_kstrdup(struct device *dev, char *buf)
+{
+ char *str = devm_kzalloc(dev, strlen(buf) + 1, GFP_KERNEL);
+ if (!str)
+ return str;
+ memcpy(str, buf, strlen(buf));
+ return str;
+}
+
+static int tfa98xx_append_i2c_address(struct device *dev,
+ struct i2c_client *i2c,
+ struct snd_soc_dapm_widget *widgets,
+ int num_widgets,
+ struct snd_soc_dai_driver *dai_drv,
+ int num_dai)
+{
+ char buf[50];
+ int i;
+ int i2cbus = i2c->adapter->nr;
+ int addr = i2c->addr;
+ if (dai_drv && num_dai > 0)
+ for (i = 0; i < num_dai; i++) {
+ snprintf(buf, 50, "%s-%x-%x", dai_drv[i].name, i2cbus,
+ addr);
+ dai_drv[i].name = tfa98xx_devm_kstrdup(dev, buf);
+
+ snprintf(buf, 50, "%s-%x-%x",
+ dai_drv[i].playback.stream_name,
+ i2cbus, addr);
+ dai_drv[i].playback.stream_name = tfa98xx_devm_kstrdup(dev, buf);
+
+ snprintf(buf, 50, "%s-%x-%x",
+ dai_drv[i].capture.stream_name,
+ i2cbus, addr);
+ dai_drv[i].capture.stream_name = tfa98xx_devm_kstrdup(dev, buf);
+ }
+
+ /* the idea behind this is convert:
+ * SND_SOC_DAPM_AIF_IN("AIF IN", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
+ * into:
+ * SND_SOC_DAPM_AIF_IN("AIF IN", "AIF Playback-2-36", 0, SND_SOC_NOPM, 0, 0),
+ */
+ if (widgets && num_widgets > 0)
+ for (i = 0; i < num_widgets; i++) {
+ if (!widgets[i].sname)
+ continue;
+ if ((widgets[i].id == snd_soc_dapm_aif_in)
+ || (widgets[i].id == snd_soc_dapm_aif_out)) {
+ snprintf(buf, 50, "%s-%x-%x", widgets[i].sname,
+ i2cbus, addr);
+ widgets[i].sname = tfa98xx_devm_kstrdup(dev, buf);
+ }
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dapm_widget tfa98xx_dapm_widgets_common[] = {
+ /* Stream widgets */
+ SND_SOC_DAPM_AIF_IN("AIF IN", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF OUT", "AIF Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("OUTL"),
+ SND_SOC_DAPM_INPUT("AEC Loopback"),
+};
+
+static struct snd_soc_dapm_widget tfa98xx_dapm_widgets_stereo[] = {
+ SND_SOC_DAPM_OUTPUT("OUTR"),
+};
+
+static struct snd_soc_dapm_widget tfa98xx_dapm_widgets_saam[] = {
+ SND_SOC_DAPM_INPUT("SAAM MIC"),
+};
+
+static struct snd_soc_dapm_widget tfa9888_dapm_inputs[] = {
+ SND_SOC_DAPM_INPUT("DMIC1"),
+ SND_SOC_DAPM_INPUT("DMIC2"),
+ SND_SOC_DAPM_INPUT("DMIC3"),
+ SND_SOC_DAPM_INPUT("DMIC4"),
+};
+
+static const struct snd_soc_dapm_route tfa98xx_dapm_routes_common[] = {
+ { "OUTL", NULL, "AIF IN" },
+ { "AIF OUT", NULL, "AEC Loopback" },
+};
+
+static const struct snd_soc_dapm_route tfa98xx_dapm_routes_saam[] = {
+ { "AIF OUT", NULL, "SAAM MIC" },
+};
+
+static const struct snd_soc_dapm_route tfa98xx_dapm_routes_stereo[] = {
+ { "OUTR", NULL, "AIF IN" },
+};
+
+static const struct snd_soc_dapm_route tfa9888_input_dapm_routes[] = {
+ { "AIF OUT", NULL, "DMIC1" },
+ { "AIF OUT", NULL, "DMIC2" },
+ { "AIF OUT", NULL, "DMIC3" },
+ { "AIF OUT", NULL, "DMIC4" },
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
+static struct snd_soc_dapm_context *snd_soc_codec_get_dapm(struct snd_soc_codec *codec)
+{
+ return &codec->dapm;
+}
+#endif
+
+static void tfa98xx_add_widgets(struct tfa98xx *tfa98xx)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(tfa98xx->codec);
+#else
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(tfa98xx->codec);
+#endif
+ struct snd_soc_dapm_widget *widgets;
+ unsigned int num_dapm_widgets = ARRAY_SIZE(tfa98xx_dapm_widgets_common);
+
+ widgets = devm_kzalloc(&tfa98xx->i2c->dev,
+ sizeof(struct snd_soc_dapm_widget) *
+ ARRAY_SIZE(tfa98xx_dapm_widgets_common),
+ GFP_KERNEL);
+ if (!widgets)
+ return;
+ memcpy(widgets, tfa98xx_dapm_widgets_common,
+ sizeof(struct snd_soc_dapm_widget) *
+ ARRAY_SIZE(tfa98xx_dapm_widgets_common));
+
+ tfa98xx_append_i2c_address(&tfa98xx->i2c->dev,
+ tfa98xx->i2c,
+ widgets,
+ num_dapm_widgets,
+ NULL,
+ 0);
+
+ snd_soc_dapm_new_controls(dapm, widgets,
+ ARRAY_SIZE(tfa98xx_dapm_widgets_common));
+ snd_soc_dapm_add_routes(dapm, tfa98xx_dapm_routes_common,
+ ARRAY_SIZE(tfa98xx_dapm_routes_common));
+
+ if (tfa98xx->flags & TFA98XX_FLAG_STEREO_DEVICE) {
+ snd_soc_dapm_new_controls(dapm, tfa98xx_dapm_widgets_stereo,
+ ARRAY_SIZE(tfa98xx_dapm_widgets_stereo));
+ snd_soc_dapm_add_routes(dapm, tfa98xx_dapm_routes_stereo,
+ ARRAY_SIZE(tfa98xx_dapm_routes_stereo));
+ }
+
+ if (tfa98xx->flags & TFA98XX_FLAG_MULTI_MIC_INPUTS) {
+ snd_soc_dapm_new_controls(dapm, tfa9888_dapm_inputs,
+ ARRAY_SIZE(tfa9888_dapm_inputs));
+ snd_soc_dapm_add_routes(dapm, tfa9888_input_dapm_routes,
+ ARRAY_SIZE(tfa9888_input_dapm_routes));
+ }
+
+ if (tfa98xx->flags & TFA98XX_FLAG_SAAM_AVAILABLE) {
+ snd_soc_dapm_new_controls(dapm, tfa98xx_dapm_widgets_saam,
+ ARRAY_SIZE(tfa98xx_dapm_widgets_saam));
+ snd_soc_dapm_add_routes(dapm, tfa98xx_dapm_routes_saam,
+ ARRAY_SIZE(tfa98xx_dapm_routes_saam));
+ }
+}
+
+/* I2C wrapper functions */
+enum Tfa98xx_Error tfa98xx_write_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short value)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ int ret;
+ int retries = I2C_RETRIES;
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+ if (!tfa98xx || !tfa98xx->regmap) {
+ pr_err("No tfa98xx regmap available\n");
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+retry:
+ ret = regmap_write(tfa98xx->regmap, subaddress, value);
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ return Tfa98xx_Error_Fail;
+ }
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx->i2c->dev, " WR reg=0x%02x, val=0x%04x %s\n",
+ subaddress, value,
+ ret < 0 ? "Error!!" : "");
+
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\tWR reg=0x%02x, val=0x%04x %s\n",
+ subaddress, value,
+ ret < 0 ? "Error!!" : "");
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_read_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short *val)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ unsigned int value;
+ int retries = I2C_RETRIES;
+ int ret;
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+ if (!tfa98xx || !tfa98xx->regmap) {
+ pr_err("No tfa98xx regmap available\n");
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+retry:
+ ret = regmap_read(tfa98xx->regmap, subaddress, &value);
+ if (ret < 0) {
+ pr_warn("i2c error at subaddress 0x%x, retries left: %d\n", subaddress, retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ return Tfa98xx_Error_Fail;
+ }
+ *val = value & 0xffff;
+
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx->i2c->dev, "RD reg=0x%02x, val=0x%04x %s\n",
+ subaddress, *val,
+ ret < 0 ? "Error!!" : "");
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\tRD reg=0x%02x, val=0x%04x %s\n",
+ subaddress, *val,
+ ret < 0 ? "Error!!" : "");
+
+ return error;
+}
+
+
+/*
+ * init external dsp
+ */
+enum Tfa98xx_Error
+ tfa98xx_init_dsp(struct tfa_device *tfa)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+
+int tfa98xx_get_dsp_status(struct tfa_device *tfa)
+{
+ return 0;
+}
+
+/*
+ * write external dsp message
+ */
+enum Tfa98xx_Error
+ tfa98xx_write_dsp(struct tfa_device *tfa, int num_bytes, const char *command_buffer)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+
+/*
+ * read external dsp message
+ */
+enum Tfa98xx_Error
+ tfa98xx_read_dsp(struct tfa_device *tfa, int num_bytes, unsigned char *result_buffer)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+/*
+ * write/read external dsp message
+ */
+enum Tfa98xx_Error
+ tfa98xx_writeread_dsp(struct tfa_device *tfa, int command_length, void *command_buffer,
+ int result_length, void *result_buffer)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+
+enum Tfa98xx_Error tfa98xx_read_data(struct tfa_device *tfa,
+ unsigned char reg,
+ int len, unsigned char value[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ struct i2c_client *tfa98xx_client;
+ int err;
+ int tries = 0;
+ unsigned char *reg_buf = NULL;
+ struct i2c_msg msgs[] = {
+ {
+ .flags = 0,
+ .len = 1,
+ .buf = NULL,
+ }, {
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = value,
+ },
+ };
+ reg_buf = (unsigned char *)kmalloc(sizeof(reg), GFP_DMA); //GRP_KERNEL also works,
+ if (!reg_buf) {
+ return -ENOMEM;;
+ }
+
+ *reg_buf = reg;
+ msgs[0].buf = reg_buf;
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+ if (tfa98xx->i2c) {
+ tfa98xx_client = tfa98xx->i2c;
+ msgs[0].addr = tfa98xx_client->addr;
+ msgs[1].addr = tfa98xx_client->addr;
+
+ do {
+ err = i2c_transfer(tfa98xx_client->adapter, msgs,
+ ARRAY_SIZE(msgs));
+ if (err != ARRAY_SIZE(msgs))
+ msleep_interruptible(I2C_RETRY_DELAY);
+ } while ((err != ARRAY_SIZE(msgs)) && (++tries < I2C_RETRIES));
+
+ if (err != ARRAY_SIZE(msgs)) {
+ dev_err(&tfa98xx_client->dev, "read transfer error %d\n",
+ err);
+ error = Tfa98xx_Error_Fail;
+ }
+
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx_client->dev, "RD-DAT reg=0x%02x, len=%d\n",
+ reg, len);
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\t\tRD-DAT reg=0x%02x, len=%d\n",
+ reg, len);
+ }
+ else {
+ pr_err("No device available\n");
+ error = Tfa98xx_Error_Fail;
+ }
+ kfree(reg_buf);
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_write_raw(struct tfa_device *tfa,
+ int len,
+ const unsigned char data[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ int ret;
+ int retries = I2C_RETRIES;
+
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+
+retry:
+ ret = i2c_master_send(tfa98xx->i2c, data, len);
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ }
+
+ if (ret == len) {
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx->i2c->dev, " WR-RAW len=%d\n", len);
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\t\tWR-RAW len=%d\n", len);
+ return Tfa98xx_Error_Ok;
+ }
+ pr_err(" WR-RAW (len=%d) Error I2C send size mismatch %d\n", len, ret);
+ error = Tfa98xx_Error_Fail;
+
+ return error;
+}
+
+/* Interrupts management */
+
+static void tfa98xx_interrupt_enable_tfa2(struct tfa98xx *tfa98xx, bool enable)
+{
+ /* Only for 0x72 we need to enable NOCLK interrupts */
+ if (tfa98xx->flags & TFA98XX_FLAG_REMOVE_PLOP_NOISE)
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_stnoclk, enable);
+
+ if (tfa98xx->flags & TFA98XX_FLAG_LP_MODES) {
+ tfa_irq_ena(tfa98xx->tfa, 36, enable); /* FIXME: IELP0 does not excist for 9912 */
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_stclpr, enable);
+ }
+}
+
+/* Check if tap-detection can and shall be enabled.
+ * Configure SPK interrupt accordingly or setup polling mode
+ * Tap-detection shall be active if:
+ * - the service is enabled (tapdet_open), AND
+ * - the current profile is a tap-detection profile
+ * On TFA1 familiy of devices, activating tap-detection means enabling the SPK
+ * interrupt if available.
+ * We also update the tapdet_enabled and tapdet_poll variables.
+ */
+static void tfa98xx_tapdet_check_update(struct tfa98xx *tfa98xx)
+{
+ unsigned int enable = false;
+
+ /* Support tap-detection on TFA1 family of devices */
+ if ((tfa98xx->flags & TFA98XX_FLAG_TAPDET_AVAILABLE) == 0)
+ return;
+
+ if (tfa98xx->tapdet_open &&
+ (tfa98xx->tapdet_profiles & (1 << tfa98xx->profile)))
+ enable = true;
+
+ if (!gpio_is_valid(tfa98xx->irq_gpio)) {
+ /* interrupt not available, setup polling mode */
+ tfa98xx->tapdet_poll = true;
+ if (enable)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->tapdet_work, HZ / 10);
+ else
+ cancel_delayed_work_sync(&tfa98xx->tapdet_work);
+ dev_dbg(tfa98xx->codec->dev,
+ "Polling for tap-detection: %s (%d; 0x%x, %d)\n",
+ enable ? "enabled" : "disabled",
+ tfa98xx->tapdet_open, tfa98xx->tapdet_profiles,
+ tfa98xx->profile);
+
+ }
+ else {
+ dev_dbg(tfa98xx->codec->dev,
+ "Interrupt for tap-detection: %s (%d; 0x%x, %d)\n",
+ enable ? "enabled" : "disabled",
+ tfa98xx->tapdet_open, tfa98xx->tapdet_profiles,
+ tfa98xx->profile);
+ /* enabled interrupt */
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_sttapdet, enable);
+ }
+
+ /* check disabled => enabled transition to clear pending events */
+ if (!tfa98xx->tapdet_enabled && enable) {
+ /* clear pending event if any */
+ tfa_irq_clear(tfa98xx->tfa, tfa9912_irq_sttapdet);
+ }
+
+ if (!tfa98xx->tapdet_poll)
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_sttapdet, 1); /* enable again */
+}
+
+/* global enable / disable interrupts */
+static void tfa98xx_interrupt_enable(struct tfa98xx *tfa98xx, bool enable)
+{
+ if (tfa98xx->flags & TFA98XX_FLAG_SKIP_INTERRUPTS)
+ return;
+
+ if (tfa98xx->tfa->tfa_family == 2)
+ tfa98xx_interrupt_enable_tfa2(tfa98xx, enable);
+}
+
+/* Firmware management */
+static void tfa98xx_container_loaded(const struct firmware *cont, void *context)
+{
+ TfaContainer_t *container;
+ struct tfa98xx *tfa98xx = context;
+ enum tfa_error tfa_err;
+ int container_size;
+ int ret;
+
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_FAIL;
+
+ if (!cont) {
+ pr_err("Failed to read %s\n", fw_name);
+ return;
+ }
+
+ /* pr_debug("loaded %s - size: %zu\n", fw_name, cont->size); */
+
+ mutex_lock(&tfa98xx_mutex);
+ if (tfa98xx_container == NULL) {
+ container = kzalloc(cont->size, GFP_KERNEL);
+ if (container == NULL) {
+ mutex_unlock(&tfa98xx_mutex);
+ release_firmware(cont);
+ pr_err("Error allocating memory\n");
+ return;
+ }
+
+ container_size = cont->size;
+ memcpy(container, cont->data, container_size);
+ release_firmware(cont);
+
+ /* pr_debug("%.2s%.2s\n", container->version, container->subversion); */
+ /* pr_debug("%.8s\n", container->customer); */
+ /* pr_debug("%.8s\n", container->application); */
+ /* pr_debug("%.8s\n", container->type); */
+ /* pr_debug("%d ndev\n", container->ndev); */
+ /* pr_debug("%d nprof\n", container->nprof); */
+
+ tfa_err = tfa_load_cnt(container, container_size);
+ if (tfa_err != tfa_error_ok) {
+ mutex_unlock(&tfa98xx_mutex);
+ kfree(container);
+ dev_err(tfa98xx->dev, "Cannot load container file, aborting\n");
+ return;
+ }
+
+ tfa98xx_container = container;
+ }
+ else {
+ /* pr_debug("container file already loaded...\n"); */
+ container = tfa98xx_container;
+ release_firmware(cont);
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ tfa98xx->tfa->cnt = container;
+
+ /*
+ i2c transaction limited to 64k
+ (Documentation/i2c/writing-clients)
+ */
+ tfa98xx->tfa->buffer_size = 65536;
+
+ /* DSP messages via i2c */
+ tfa98xx->tfa->has_msg = 0;
+
+ if (tfa_dev_probe(tfa98xx->i2c->addr, tfa98xx->tfa) != 0) {
+ dev_err(tfa98xx->dev, "Failed to probe TFA98xx @ 0x%.2x\n", tfa98xx->i2c->addr);
+ return;
+ }
+
+ tfa98xx->tfa->dev_idx = tfa_cont_get_idx(tfa98xx->tfa);
+ if (tfa98xx->tfa->dev_idx < 0) {
+ dev_err(tfa98xx->dev, "Failed to find TFA98xx @ 0x%.2x in container file\n", tfa98xx->i2c->addr);
+ return;
+ }
+
+ /* Enable debug traces */
+ tfa98xx->tfa->verbose = trace_level & 1;
+
+ /* prefix is the application name from the cnt */
+ tfa_cnt_get_app_name(tfa98xx->tfa, tfa98xx->fw.name);
+
+ /* set default profile/vstep */
+ tfa98xx->profile = 0;
+ tfa98xx->vstep = 0;
+
+ /* Override default profile if requested */
+ if (strcmp(dflt_prof_name, "")) {
+ unsigned int i;
+ int nprof = tfa_cnt_get_dev_nprof(tfa98xx->tfa);
+ for (i = 0; i < nprof; i++) {
+ if (strcmp(tfa_cont_profile_name(tfa98xx, i),
+ dflt_prof_name) == 0) {
+ tfa98xx->profile = i;
+ dev_dbg(tfa98xx->dev,
+ "changing default profile to %s (%d)\n",
+ dflt_prof_name, tfa98xx->profile);
+ break;
+ }
+ }
+ if (i >= nprof)
+ dev_dbg(tfa98xx->dev,
+ "Default profile override failed (%s profile not found)\n",
+ dflt_prof_name);
+ }
+
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_OK;
+ /* pr_debug("Firmware init complete\n"); */
+
+ if (no_start != 0)
+ return;
+
+ /* Only controls for master device */
+ if (tfa98xx->tfa->dev_idx == 0)
+ tfa98xx_create_controls(tfa98xx);
+
+ tfa98xx_inputdev_check_register(tfa98xx);
+
+ if (tfa_is_cold(tfa98xx->tfa) == 0) {
+ /* pr_debug("Warning: device 0x%.2x is still warm\n", tfa98xx->i2c->addr); */
+ tfa_reset(tfa98xx->tfa);
+ }
+
+ /* Preload settings using internal clock on TFA2 */
+ if (tfa98xx->tfa->tfa_family == 2) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ if (ret == Tfa98xx_Error_Not_Supported)
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_FAIL;
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ tfa98xx_interrupt_enable(tfa98xx, true);
+}
+
+static int tfa98xx_load_container(struct tfa98xx *tfa98xx)
+{
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_PENDING;
+
+ return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ fw_name, tfa98xx->dev, GFP_KERNEL,
+ tfa98xx, tfa98xx_container_loaded);
+}
+
+
+static void tfa98xx_tapdet(struct tfa98xx *tfa98xx)
+{
+ unsigned int tap_pattern;
+ int btn;
+
+ /* check tap pattern (BTN_0 is "error" wrong tap indication */
+ tap_pattern = tfa_get_tap_pattern(tfa98xx->tfa);
+ switch (tap_pattern) {
+ case 0xffffffff:
+ pr_info("More than 4 taps detected! (flagTapPattern = -1)\n");
+ btn = BTN_0;
+ break;
+ case 0xfffffffe:
+ case 0xfe:
+ pr_info("Illegal tap detected!\n");
+ btn = BTN_0;
+ break;
+ case 0:
+ pr_info("Unrecognized pattern! (flagTapPattern = 0)\n");
+ btn = BTN_0;
+ break;
+ default:
+ pr_info("Detected pattern: %d\n", tap_pattern);
+ btn = BTN_0 + tap_pattern;
+ break;
+ }
+
+ input_report_key(tfa98xx->input, btn, 1);
+ input_report_key(tfa98xx->input, btn, 0);
+ input_sync(tfa98xx->input);
+
+ /* acknowledge event done by clearing interrupt */
+
+}
+
+static void tfa98xx_tapdet_work(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx;
+
+ //TODO check is this is still needed for tap polling
+ tfa98xx = container_of(work, struct tfa98xx, tapdet_work.work);
+
+ if (tfa_irq_get(tfa98xx->tfa, tfa9912_irq_sttapdet))
+ tfa98xx_tapdet(tfa98xx);
+
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->tapdet_work, HZ / 10);
+}
+static void tfa98xx_nmode_update_work(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx;
+
+ //MCH_TO_TEST, checking if noise mode update is required or not
+ tfa98xx = container_of(work, struct tfa98xx, nmodeupdate_work.work);
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_adapt_noisemode(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->nmodeupdate_work,5 * HZ);
+}
+static void tfa98xx_monitor(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ tfa98xx = container_of(work, struct tfa98xx, monitor_work.work);
+
+ /* Check for tap-detection - bypass monitor if it is active */
+ if (!tfa98xx->input) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ error = tfa_status(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ if (error == Tfa98xx_Error_DSP_not_running) {
+ if (tfa98xx->dsp_init == TFA98XX_DSP_INIT_DONE) {
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_RECOVER;
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->init_work, 0);
+ }
+ }
+ }
+
+ /* reschedule */
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->monitor_work, 5 * HZ);
+}
+
+static void tfa98xx_dsp_init(struct tfa98xx *tfa98xx)
+{
+ int ret;
+ bool failed = false;
+ bool reschedule = false;
+ bool sync = false;
+
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK) {
+ /* pr_debug("Skipping tfa_dev_start (no FW: %d)\n", tfa98xx->dsp_fw_state); */
+ return;
+ }
+
+ if (tfa98xx->dsp_init == TFA98XX_DSP_INIT_DONE) {
+ /* pr_debug("Stream already started, skipping DSP power-on\n"); */
+ return;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_PENDING;
+
+ if (tfa98xx->init_count < TF98XX_MAX_DSP_START_TRY_COUNT) {
+ /* directly try to start DSP */
+ ret = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ if (ret == Tfa98xx_Error_Not_Supported) {
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_FAIL;
+ dev_err(&tfa98xx->i2c->dev, "Failed starting device\n");
+ failed = true;
+ }
+ else if (ret != Tfa98xx_Error_Ok) {
+ /* It may fail as we may not have a valid clock at that
+ * time, so re-schedule and re-try later.
+ */
+ dev_err(&tfa98xx->i2c->dev,
+ "tfa_dev_start failed! (err %d) - %d\n",
+ ret, tfa98xx->init_count);
+ reschedule = true;
+ }
+ else {
+ sync = true;
+
+ /* Subsystem ready, tfa init complete */
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_DONE;
+ dev_dbg(&tfa98xx->i2c->dev,
+ "tfa_dev_start success (%d)\n",
+ tfa98xx->init_count);
+ /* cancel other pending init works */
+ cancel_delayed_work(&tfa98xx->init_work);
+ tfa98xx->init_count = 0;
+ }
+ }
+ else {
+ /* exceeded max number ot start tentatives, cancel start */
+ dev_err(&tfa98xx->i2c->dev,
+ "Failed starting device (%d)\n",
+ tfa98xx->init_count);
+ failed = true;
+ }
+ if (reschedule) {
+ /* reschedule this init work for later */
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->init_work,
+ msecs_to_jiffies(5));
+ tfa98xx->init_count++;
+ }
+ if (failed) {
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_FAIL;
+ /* cancel other pending init works */
+ cancel_delayed_work(&tfa98xx->init_work);
+ tfa98xx->init_count = 0;
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (sync) {
+ /* check if all devices have started */
+ bool do_sync;
+ mutex_lock(&tfa98xx_mutex);
+
+ if (tfa98xx_sync_count < tfa98xx_device_count)
+ tfa98xx_sync_count++;
+
+ do_sync = (tfa98xx_sync_count >= tfa98xx_device_count);
+ mutex_unlock(&tfa98xx_mutex);
+
+ /* when all devices have started then unmute */
+ if (do_sync) {
+ tfa98xx_sync_count = 0;
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+
+ /*
+ * start monitor thread to check IC status bit
+ * periodically, and re-init IC to recover if
+ * needed.
+ */
+ if (tfa98xx->tfa->tfa_family == 1 || tfa98xx->tfa->dev_ops.tfa_status != NULL)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->monitor_work,
+ 1 * HZ);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+
+ }
+ }
+
+
+ return;
+}
+
+
+static void tfa98xx_dsp_init_work(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx = container_of(work, struct tfa98xx, init_work.work);
+
+ tfa98xx_dsp_init(tfa98xx);
+}
+
+static void tfa98xx_interrupt(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx = container_of(work, struct tfa98xx, interrupt_work.work);
+
+ pr_info("\n");
+
+ if (tfa98xx->flags & TFA98XX_FLAG_TAPDET_AVAILABLE) {
+ /* check for tap interrupt */
+ if (tfa_irq_get(tfa98xx->tfa, tfa9912_irq_sttapdet)) {
+ tfa98xx_tapdet(tfa98xx);
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa98xx->tfa, tfa9912_irq_sttapdet);
+ }
+ } /* TFA98XX_FLAG_TAPDET_AVAILABLE */
+
+ if (tfa98xx->flags & TFA98XX_FLAG_REMOVE_PLOP_NOISE) {
+ int start_triggered;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ start_triggered = tfa_plop_noise_interrupt(tfa98xx->tfa, tfa98xx->profile, tfa98xx->vstep);
+ /* Only enable when the return value is 1, otherwise the interrupt is triggered twice */
+ if (start_triggered)
+ tfa98xx_interrupt_enable(tfa98xx, true);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ } /* TFA98XX_FLAG_REMOVE_PLOP_NOISE */
+
+ if (tfa98xx->flags & TFA98XX_FLAG_LP_MODES) {
+ tfa_lp_mode_interrupt(tfa98xx->tfa);
+ } /* TFA98XX_FLAG_LP_MODES */
+
+ /* unmask interrupts masked in IRQ handler */
+ tfa_irq_unmask(tfa98xx->tfa);
+}
+
+static int tfa98xx_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = dai->component;
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = dai->codec;
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ unsigned int sr;
+ int len, prof, nprof, idx = 0;
+ char *basename;
+ u64 formats;
+ int err;
+
+ /*
+ * Support CODEC to CODEC links,
+ * these are called with a NULL runtime pointer.
+ */
+ if (!substream->runtime)
+ return 0;
+
+ if (pcm_no_constraint != 0)
+ return 0;
+
+ switch (pcm_sample_format) {
+ case 0:
+ formats = SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ case 1:
+ formats = SNDRV_PCM_FMTBIT_S24_LE;
+ break;
+ case 2:
+ formats = SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ default:
+ formats = TFA98XX_FORMATS;
+ break;
+ }
+
+ err = snd_pcm_hw_constraint_mask64(substream->runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT, formats);
+ if (err < 0)
+ return err;
+
+ if (no_start != 0)
+ return 0;
+
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK) {
+ dev_dbg(codec->dev, "Container file not loaded\n");
+ return -EINVAL;
+ }
+
+ basename = kzalloc(MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!basename)
+ return -ENOMEM;
+
+ /* copy profile name into basename until the . */
+ get_profile_basename(basename, tfa_cont_profile_name(tfa98xx, tfa98xx->profile));
+ len = strlen(basename);
+
+ /* loop over all profiles and get the supported samples rate(s) from
+ * the profiles with the same basename
+ */
+ nprof = tfa_cnt_get_dev_nprof(tfa98xx->tfa);
+ tfa98xx->rate_constraint.list = &tfa98xx->rate_constraint_list[0];
+ tfa98xx->rate_constraint.count = 0;
+ for (prof = 0; prof < nprof; prof++) {
+ if (0 == strncmp(basename, tfa_cont_profile_name(tfa98xx, prof), len)) {
+ /* Check which sample rate is supported with current profile,
+ * and enforce this.
+ */
+ sr = tfa98xx_get_profile_sr(tfa98xx->tfa, prof);
+ if (!sr)
+ dev_dbg(codec->dev, "Unable to identify supported sample rate\n");
+
+ if (tfa98xx->rate_constraint.count >= TFA98XX_NUM_RATES) {
+ dev_err(codec->dev, "too many sample rates\n");
+ }
+ else {
+ tfa98xx->rate_constraint_list[idx++] = sr;
+ tfa98xx->rate_constraint.count += 1;
+ }
+ }
+ }
+
+ kfree(basename);
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &tfa98xx->rate_constraint);
+}
+
+static int tfa98xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec_dai->component);
+#else
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec_dai->codec);
+#endif
+ tfa98xx->sysclk = freq;
+ return 0;
+}
+
+static int tfa98xx_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int slot_width)
+{
+ /* pr_debug("\n"); */
+ return 0;
+}
+
+static int tfa98xx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(dai->component);
+ struct snd_soc_component *codec = dai->component;
+#else
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(dai->codec);
+ struct snd_soc_codec *codec = dai->codec;
+#endif
+ /* pr_debug("fmt=0x%x\n", fmt); */
+
+ /* Supported mode: regular I2S, slave, or PDM */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_DSP_A:
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+ dev_err(codec->dev, "Invalid Codec master mode\n");
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_PDM:
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported DAI format %d\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ tfa98xx->audio_mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ return 0;
+}
+
+static int tfa98xx_get_fssel(unsigned int rate)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(rate_to_fssel); i++) {
+ if (rate_to_fssel[i].rate == rate) {
+ return rate_to_fssel[i].fssel;
+ }
+ }
+ return -EINVAL;
+}
+
+static int tfa98xx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = dai->component;
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = dai->codec;
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ unsigned int rate;
+ int prof_idx;
+
+ /* Supported */
+ rate = params_rate(params);
+ tfa98xx->tfa->bitwidth = params_width(params);
+ tfa98xx->tfa->dynamicTDMmode = pcm_sample_format;
+ /* pr_debug("Requested rate: %d, sample size: %d, physical size: %d\n",
+ rate, snd_pcm_format_width(params_format(params)),
+ snd_pcm_format_physical_width(params_format(params))); */
+
+ if (no_start != 0)
+ return 0;
+ /* set TDM bit width */
+ /* pr_debug("%s: Requested width: %d\n", __func__,
+ params_width(params)); */
+ if ((tfa98xx->tfa->dynamicTDMmode == 3) && tfa_dev_set_tdm_bitwidth(tfa98xx->tfa,tfa98xx->tfa->bitwidth))
+ return -EINVAL;
+ /* check if samplerate is supported for this mixer profile */
+ prof_idx = get_profile_id_for_sr(tfa98xx_mixer_profile, rate);
+ if (prof_idx < 0) {
+ pr_err("tfa98xx: invalid sample rate %d.\n", rate);
+ return -EINVAL;
+ }
+ /* pr_debug("mixer profile:container profile = [%d:%d]\n", tfa98xx_mixer_profile, prof_idx); */
+
+
+ /* update 'real' profile (container profile) */
+ tfa98xx->profile = prof_idx;
+
+ /* update to new rate */
+ tfa98xx->rate = tfa98xx->tfa->rate = rate;
+
+ return 0;
+}
+
+static int tfa98xx_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = dai->component;
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = dai->codec;
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ dev_dbg(&tfa98xx->i2c->dev, "%s: state: %d\n", __func__, mute);
+
+ if (no_start) {
+ /* pr_debug("no_start parameter set no tfa_dev_start or tfa_dev_stop, returning\n"); */
+ return 0;
+ }
+
+ if (mute) {
+ /* stop DSP only when both playback and capture streams
+ * are deactivated
+ */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tfa98xx->pstream = 0;
+ else
+ tfa98xx->cstream = 0;
+ if (tfa98xx->pstream != 0 || tfa98xx->cstream != 0)
+ return 0;
+
+ mutex_lock(&tfa98xx_mutex);
+ tfa98xx_sync_count = 0;
+ mutex_unlock(&tfa98xx_mutex);
+
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK)
+ return 0;
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_stop(tfa98xx->tfa);
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_STOPPED;
+ mutex_unlock(&tfa98xx->dsp_lock);
+ if(tfa98xx->flags & TFA98XX_FLAG_ADAPT_NOISE_MODE)
+ cancel_delayed_work_sync(&tfa98xx->nmodeupdate_work);
+ }
+ else {
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tfa98xx->pstream = 1;
+ else
+ tfa98xx->cstream = 1;
+
+ /* Start DSP */
+#if 1
+ if (tfa98xx->dsp_init != TFA98XX_DSP_INIT_PENDING)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->init_work, 0);
+#else
+ tfa98xx_dsp_init(tfa98xx);
+#endif//
+ if(tfa98xx->flags & TFA98XX_FLAG_ADAPT_NOISE_MODE)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->nmodeupdate_work,
+ 0);
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops tfa98xx_dai_ops = {
+ .startup = tfa98xx_startup,
+ .set_fmt = tfa98xx_set_fmt,
+ .set_sysclk = tfa98xx_set_dai_sysclk,
+ .set_tdm_slot = tfa98xx_set_tdm_slot,
+ .hw_params = tfa98xx_hw_params,
+ .mute_stream = tfa98xx_mute,
+};
+
+static struct snd_soc_dai_driver tfa98xx_dai[] = {
+ {
+ .name = "tfa98xx-aif",
+ .id = 1,
+ .playback = {
+ .stream_name = "AIF Playback",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TFA98XX_RATES,
+ .formats = TFA98XX_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TFA98XX_RATES,
+ .formats = TFA98XX_FORMATS,
+ },
+ .ops = &tfa98xx_dai_ops,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+ .symmetric_rates = 1,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ .symmetric_rate = 1,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) && LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ .symmetric_channels = 1,
+ .symmetric_sample_bits = 1,
+#endif
+ },
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+static int tfa98xx_probe(struct snd_soc_component *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+static int tfa98xx_probe(struct snd_soc_codec *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int ret;
+
+ /* pr_debug("\n"); */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ snd_soc_component_init_regmap(codec, tfa98xx->regmap);
+#endif
+ /* setup work queue, will be used to initial DSP on first boot up */
+ tfa98xx->tfa98xx_wq = create_singlethread_workqueue("tfa98xx");
+ if (!tfa98xx->tfa98xx_wq)
+ return -ENOMEM;
+
+ INIT_DELAYED_WORK(&tfa98xx->init_work, tfa98xx_dsp_init_work);
+ INIT_DELAYED_WORK(&tfa98xx->monitor_work, tfa98xx_monitor);
+ INIT_DELAYED_WORK(&tfa98xx->interrupt_work, tfa98xx_interrupt);
+ INIT_DELAYED_WORK(&tfa98xx->tapdet_work, tfa98xx_tapdet_work);
+ INIT_DELAYED_WORK(&tfa98xx->nmodeupdate_work, tfa98xx_nmode_update_work);
+
+ tfa98xx->codec = codec;
+
+ ret = tfa98xx_load_container(tfa98xx);
+ /* pr_debug("Container loading requested: %d\n", ret); */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
+ codec->control_data = tfa98xx->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+#endif
+ tfa98xx_add_widgets(tfa98xx);
+
+ dev_dbg(codec->dev, "tfa98xx codec registered (%s)",
+ tfa98xx->fw.name);
+
+ return ret;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+static void tfa98xx_remove(struct snd_soc_component *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+static int tfa98xx_remove(struct snd_soc_codec *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ /* pr_debug("\n"); */
+
+ tfa98xx_interrupt_enable(tfa98xx, false);
+
+ tfa98xx_inputdev_unregister(tfa98xx);
+
+ cancel_delayed_work_sync(&tfa98xx->interrupt_work);
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ cancel_delayed_work_sync(&tfa98xx->tapdet_work);
+ cancel_delayed_work_sync(&tfa98xx->nmodeupdate_work);
+
+ if (tfa98xx->tfa98xx_wq)
+ destroy_workqueue(tfa98xx->tfa98xx_wq);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ return;
+#else
+ return 0;
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
+static struct regmap *tfa98xx_get_regmap(struct device *dev)
+{
+ struct tfa98xx *tfa98xx = dev_get_drvdata(dev);
+
+ return tfa98xx->regmap;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+static struct snd_soc_component_driver soc_codec_dev_tfa98xx = {
+#else
+static struct snd_soc_codec_driver soc_codec_dev_tfa98xx = {
+#endif
+ .probe = tfa98xx_probe,
+ .remove = tfa98xx_remove,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
+ .get_regmap = tfa98xx_get_regmap,
+#endif
+};
+
+
+static bool tfa98xx_writeable_register(struct device *dev, unsigned int reg)
+{
+ /* enable read access for all registers */
+ return 1;
+}
+
+static bool tfa98xx_readable_register(struct device *dev, unsigned int reg)
+{
+ /* enable read access for all registers */
+ return 1;
+}
+
+static bool tfa98xx_volatile_register(struct device *dev, unsigned int reg)
+{
+ /* enable read access for all registers */
+ return 1;
+}
+
+static const struct regmap_config tfa98xx_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = TFA98XX_MAX_REGISTER,
+ .writeable_reg = tfa98xx_writeable_register,
+ .readable_reg = tfa98xx_readable_register,
+ .volatile_reg = tfa98xx_volatile_register,
+ .cache_type = REGCACHE_NONE,
+};
+
+static void tfa98xx_irq_tfa2(struct tfa98xx *tfa98xx)
+{
+ pr_info("\n");
+
+ /*
+ * mask interrupts
+ * will be unmasked after handling interrupts in workqueue
+ */
+ tfa_irq_mask(tfa98xx->tfa);
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->interrupt_work, 0);
+}
+
+
+static irqreturn_t tfa98xx_irq(int irq, void *data)
+{
+ struct tfa98xx *tfa98xx = data;
+
+ if (tfa98xx->tfa->tfa_family == 2)
+ tfa98xx_irq_tfa2(tfa98xx);
+
+ return IRQ_HANDLED;
+}
+
+static int tfa98xx_ext_reset(struct tfa98xx *tfa98xx)
+{
+ if (tfa98xx && gpio_is_valid(tfa98xx->reset_gpio)) {
+ int reset = tfa98xx->reset_polarity;
+ gpio_set_value_cansleep(tfa98xx->reset_gpio, reset);
+ mdelay(1);
+ gpio_set_value_cansleep(tfa98xx->reset_gpio, !reset);
+ mdelay(1);
+ }
+ return 0;
+}
+
+static int tfa98xx_parse_dt(struct device *dev, struct tfa98xx *tfa98xx,
+ struct device_node *np) {
+ u32 value;
+ int ret;
+ tfa98xx->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+ if (tfa98xx->reset_gpio < 0)
+ dev_dbg(dev, "No reset GPIO provided, will not HW reset device\n");
+
+ tfa98xx->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0);
+ if (tfa98xx->irq_gpio < 0)
+ dev_dbg(dev, "No IRQ GPIO provided.\n");
+ ret = of_property_read_u32(np,"reset-polarity",&value);
+ if(ret< 0)
+ {
+ tfa98xx->reset_polarity = HIGH;
+ }else {
+ tfa98xx->reset_polarity = (value == 0) ? LOW : HIGH;
+ }
+ dev_dbg(dev, "reset-polarity:%d\n",tfa98xx->reset_polarity);
+ return 0;
+}
+
+static ssize_t tfa98xx_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 tfa98xx *tfa98xx = dev_get_drvdata(dev);
+
+ if (count != 1) {
+ /* pr_debug("invalid register address"); */
+ return -EINVAL;
+ }
+
+ tfa98xx->reg = buf[0];
+
+ return 1;
+}
+
+static ssize_t tfa98xx_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 tfa98xx *tfa98xx = dev_get_drvdata(dev);
+ u8 *data;
+ int ret;
+ int retries = I2C_RETRIES;
+
+ data = kmalloc(count + 1, GFP_KERNEL);
+ if (data == NULL) {
+ /* pr_debug("can not allocate memory\n"); */
+ return -ENOMEM;
+ }
+
+ data[0] = tfa98xx->reg;
+ memcpy(&data[1], buf, count);
+
+retry:
+ ret = i2c_master_send(tfa98xx->i2c, data, count + 1);
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ }
+
+ kfree(data);
+
+ /* the number of data bytes written without the register address */
+ return ((ret > 1) ? count : -EIO);
+}
+
+static ssize_t tfa98xx_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 tfa98xx *tfa98xx = dev_get_drvdata(dev);
+ struct i2c_msg msgs[] = {
+ {
+ .addr = tfa98xx->i2c->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &tfa98xx->reg,
+ },
+ {
+ .addr = tfa98xx->i2c->addr,
+ .flags = I2C_M_RD,
+ .len = count,
+ .buf = buf,
+ },
+ };
+ int ret;
+ int retries = I2C_RETRIES;
+retry:
+ ret = i2c_transfer(tfa98xx->i2c->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ return ret;
+ }
+ /* ret contains the number of i2c transaction */
+ /* return the number of bytes read */
+ return ((ret > 1) ? count : -EIO);
+}
+
+static struct bin_attribute dev_attr_rw = {
+ .attr = {
+ .name = "rw",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .size = 0,
+ .read = tfa98xx_rw_read,
+ .write = tfa98xx_rw_write,
+};
+
+static struct bin_attribute dev_attr_reg = {
+ .attr = {
+ .name = "reg",
+ .mode = S_IWUSR,
+ },
+ .size = 0,
+ .read = NULL,
+ .write = tfa98xx_reg_write,
+};
+
+static int tfa98xx_i2c_probe(struct i2c_client *i2c)
+{
+ struct snd_soc_dai_driver *dai;
+ struct tfa98xx *tfa98xx;
+ struct device_node *np = i2c->dev.of_node;
+ int irq_flags;
+ unsigned int reg;
+ int ret;
+
+ pr_info("addr=0x%x\n", i2c->addr);
+
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
+ dev_err(&i2c->dev, "check_functionality failed\n");
+ return -EIO;
+ }
+
+ tfa98xx = devm_kzalloc(&i2c->dev, sizeof(struct tfa98xx), GFP_KERNEL);
+ if (tfa98xx == NULL)
+ return -ENOMEM;
+
+ tfa98xx->dev = &i2c->dev;
+ tfa98xx->i2c = i2c;
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_STOPPED;
+ tfa98xx->rate = 48000; /* init to the default sample rate (48kHz) */
+ tfa98xx->tfa = NULL;
+
+ tfa98xx->regmap = devm_regmap_init_i2c(i2c, &tfa98xx_regmap);
+ if (IS_ERR(tfa98xx->regmap)) {
+ ret = PTR_ERR(tfa98xx->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(i2c, tfa98xx);
+ mutex_init(&tfa98xx->dsp_lock);
+ init_waitqueue_head(&tfa98xx->wq);
+
+ if (np) {
+ ret = tfa98xx_parse_dt(&i2c->dev, tfa98xx, np);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to parse DT node\n");
+ return ret;
+ }
+ if (no_start)
+ tfa98xx->irq_gpio = -1;
+ if (no_reset)
+ tfa98xx->reset_gpio = -1;
+ }
+ else {
+ tfa98xx->reset_gpio = -1;
+ tfa98xx->irq_gpio = -1;
+ }
+
+ if (gpio_is_valid(tfa98xx->reset_gpio)) {
+ ret = devm_gpio_request_one(&i2c->dev, tfa98xx->reset_gpio,
+ GPIOF_OUT_INIT_LOW, "TFA98XX_RST");
+ if (ret)
+ return ret;
+ }
+
+ if (gpio_is_valid(tfa98xx->irq_gpio)) {
+ ret = devm_gpio_request_one(&i2c->dev, tfa98xx->irq_gpio,
+ GPIOF_DIR_IN, "TFA98XX_INT");
+ if (ret)
+ return ret;
+ }
+
+ /* Power up! */
+ tfa98xx_ext_reset(tfa98xx);
+
+ if ((no_start == 0) && (no_reset == 0)) {
+ ret = regmap_read(tfa98xx->regmap, 0x03, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read Revision register: %d\n",
+ ret);
+ return -EIO;
+ }
+ switch (reg & 0xff) {
+ case 0x72: /* tfa9872 */
+ pr_info("TFA9872 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_REMOVE_PLOP_NOISE;
+ /* tfa98xx->flags |= TFA98XX_FLAG_LP_MODES; */
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x73: /* tfa9873 */
+ pr_info("TFA9873 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ tfa98xx->flags |= TFA98XX_FLAG_ADAPT_NOISE_MODE; /***MCH_TO_TEST***/
+ break;
+ case 0x74: /* tfa9874 */
+ pr_info("TFA9874 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x75: /* tfa9875*/
+ pr_info("TFA9875 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x78: /* tfa9878 */
+ pr_info("TFA9878 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x88: /* tfa9888 */
+ pr_info("TFA9888 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_STEREO_DEVICE;
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x13: /* tfa9912 */
+ pr_info("TFA9912 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ /* tfa98xx->flags |= TFA98XX_FLAG_TAPDET_AVAILABLE; */
+ break;
+ case 0x94: /* tfa9894 */
+ pr_info("TFA9894 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x80: /* tfa9890 */
+ case 0x81: /* tfa9890 */
+ pr_info("TFA9890 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ break;
+ case 0x92: /* tfa9891 */
+ pr_info("TFA9891 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SAAM_AVAILABLE;
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ break;
+ case 0x12: /* tfa9895 */
+ pr_info("TFA9895 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ break;
+ case 0x97:
+ pr_info("TFA9897 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x96:
+ pr_info("TFA9896 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ default:
+ pr_info("Unsupported device revision (0x%x)\n", reg & 0xff);
+ return -EINVAL;
+ }
+ }
+
+ tfa98xx->tfa = devm_kzalloc(&i2c->dev, sizeof(struct tfa_device), GFP_KERNEL);
+ if (tfa98xx->tfa == NULL)
+ return -ENOMEM;
+
+ tfa98xx->tfa->data = (void *)tfa98xx;
+ tfa98xx->tfa->cachep = tfa98xx_cache;
+
+ /* Modify the stream names, by appending the i2c device address.
+ * This is used with multicodec, in order to discriminate the devices.
+ * Stream names appear in the dai definition and in the stream .
+ * We create copies of original structures because each device will
+ * have its own instance of this structure, with its own address.
+ */
+ dai = devm_kzalloc(&i2c->dev, sizeof(tfa98xx_dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+ memcpy(dai, tfa98xx_dai, sizeof(tfa98xx_dai));
+
+ tfa98xx_append_i2c_address(&i2c->dev,
+ i2c,
+ NULL,
+ 0,
+ dai,
+ ARRAY_SIZE(tfa98xx_dai));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ ret = devm_snd_soc_register_component(&i2c->dev,
+ &soc_codec_dev_tfa98xx, dai,
+ ARRAY_SIZE(tfa98xx_dai));
+#else
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_tfa98xx, dai,
+ ARRAY_SIZE(tfa98xx_dai));
+#endif
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register TFA98xx: %d\n", ret);
+ return ret;
+ }
+
+ if (gpio_is_valid(tfa98xx->irq_gpio) &&
+ !(tfa98xx->flags & TFA98XX_FLAG_SKIP_INTERRUPTS)) {
+ /* register irq handler */
+ irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ ret = devm_request_threaded_irq(&i2c->dev,
+ gpio_to_irq(tfa98xx->irq_gpio),
+ NULL, tfa98xx_irq, irq_flags,
+ "tfa98xx", tfa98xx);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ gpio_to_irq(tfa98xx->irq_gpio), ret);
+ return ret;
+ }
+ }
+ else {
+ dev_dbg(&i2c->dev, "Skipping IRQ registration\n");
+ /* disable feature support if gpio was invalid */
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ if (no_start == 0)
+ tfa98xx_debug_init(tfa98xx, i2c);
+#endif
+ /* Register the sysfs files for climax backdoor access */
+ ret = device_create_bin_file(&i2c->dev, &dev_attr_rw);
+ if (ret)
+ dev_dbg(&i2c->dev, "error creating sysfs files\n");
+ ret = device_create_bin_file(&i2c->dev, &dev_attr_reg);
+ if (ret)
+ dev_dbg(&i2c->dev, "error creating sysfs files\n");
+
+ pr_info("%s Probe completed successfully!\n", __func__);
+
+ INIT_LIST_HEAD(&tfa98xx->list);
+
+ mutex_lock(&tfa98xx_mutex);
+ tfa98xx_device_count++;
+ list_add(&tfa98xx->list, &tfa98xx_device_list);
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static void tfa98xx_i2c_remove(struct i2c_client *i2c)
+{
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+
+ /* pr_debug("addr=0x%x\n", i2c->addr); */
+
+ tfa98xx_interrupt_enable(tfa98xx, false);
+
+ cancel_delayed_work_sync(&tfa98xx->interrupt_work);
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ cancel_delayed_work_sync(&tfa98xx->tapdet_work);
+ cancel_delayed_work_sync(&tfa98xx->nmodeupdate_work);
+
+ device_remove_bin_file(&i2c->dev, &dev_attr_reg);
+ device_remove_bin_file(&i2c->dev, &dev_attr_rw);
+#ifdef CONFIG_DEBUG_FS
+ tfa98xx_debug_remove(tfa98xx);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ snd_soc_unregister_component(&i2c->dev);
+#else
+ snd_soc_unregister_codec(&i2c->dev);
+#endif
+ if (gpio_is_valid(tfa98xx->irq_gpio))
+ devm_gpiod_put(&i2c->dev, gpio_to_desc(tfa98xx->irq_gpio));
+ if (gpio_is_valid(tfa98xx->reset_gpio))
+ devm_gpiod_put(&i2c->dev, gpio_to_desc(tfa98xx->reset_gpio));
+
+ mutex_lock(&tfa98xx_mutex);
+ list_del(&tfa98xx->list);
+ tfa98xx_device_count--;
+ if (tfa98xx_device_count == 0) {
+ kfree(tfa98xx_container);
+ tfa98xx_container = NULL;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return;
+}
+
+static const struct i2c_device_id tfa98xx_i2c_id[] = {
+ { "tfa98xx", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tfa98xx_i2c_id);
+
+#ifdef CONFIG_OF
+static struct of_device_id tfa98xx_dt_match[] = {
+ {.compatible = "nxp,tfa9894" },
+ {.compatible = "tfa,tfa98xx" },
+ {.compatible = "tfa,tfa9872" },
+ {.compatible = "tfa,tfa9873" },
+ {.compatible = "tfa,tfa9875" },
+ {.compatible = "tfa,tfa9874" },
+ {.compatible = "tfa,tfa9878" },
+ {.compatible = "tfa,tfa9888" },
+ {.compatible = "tfa,tfa9890" },
+ {.compatible = "tfa,tfa9891" },
+ {.compatible = "tfa,tfa9894" },
+ {.compatible = "tfa,tfa9895" },
+ {.compatible = "tfa,tfa9896" },
+ {.compatible = "tfa,tfa9897" },
+ {.compatible = "tfa,tfa9912" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tfa98xx_dt_match);
+#endif
+
+static struct i2c_driver tfa98xx_i2c_driver = {
+ .driver = {
+ .name = "tfa98xx",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tfa98xx_dt_match),
+ },
+ .probe = tfa98xx_i2c_probe,
+ .remove = tfa98xx_i2c_remove,
+ .id_table = tfa98xx_i2c_id,
+};
+
+static int __init tfa98xx_i2c_init(void)
+{
+ int ret = 0;
+
+ pr_info("TFA98XX driver version %s\n", TFA98XX_VERSION);
+
+ /* Enable debug traces */
+ tfa98xx_kmsg_regs = trace_level & 2;
+ tfa98xx_ftrace_regs = trace_level & 4;
+
+ /* Initialize kmem_cache */
+ tfa98xx_cache = kmem_cache_create("tfa98xx_cache", /* Cache name /proc/slabinfo */
+ PAGE_SIZE, /* Structure size, we should fit in single page */
+ 0, /* Structure alignment */
+ (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT |
+ SLAB_MEM_SPREAD), /* Cache property */
+ NULL); /* Object constructor */
+ if (!tfa98xx_cache) {
+ pr_err("tfa98xx can't create memory pool\n");
+ ret = -ENOMEM;
+ }
+
+ ret = i2c_add_driver(&tfa98xx_i2c_driver);
+
+ return ret;
+}
+module_init(tfa98xx_i2c_init);
+
+static void __exit tfa98xx_i2c_exit(void)
+{
+ i2c_del_driver(&tfa98xx_i2c_driver);
+ kmem_cache_destroy(tfa98xx_cache);
+}
+module_exit(tfa98xx_i2c_exit);
+
+MODULE_DESCRIPTION("ASoC TFA98XX driver");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.h
new file mode 100644
index 00000000000..cedb1169e38
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __TFA98XX_INC__
+#define __TFA98XX_INC__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include "tfa_device.h"
+#include "tfa_container.h"
+#include "config.h"
+
+/* max. length of a alsa mixer control name */
+#define MAX_CONTROL_NAME 48
+
+#define TFA98XX_MAX_REGISTER 0xff
+
+#define TFA98XX_FLAG_SKIP_INTERRUPTS (1 << 0)
+#define TFA98XX_FLAG_SAAM_AVAILABLE (1 << 1)
+#define TFA98XX_FLAG_STEREO_DEVICE (1 << 2)
+#define TFA98XX_FLAG_MULTI_MIC_INPUTS (1 << 3)
+#define TFA98XX_FLAG_TAPDET_AVAILABLE (1 << 4)
+#define TFA98XX_FLAG_CALIBRATION_CTL (1 << 5)
+#define TFA98XX_FLAG_REMOVE_PLOP_NOISE (1 << 6)
+#define TFA98XX_FLAG_LP_MODES (1 << 7)
+#define TFA98XX_FLAG_TDM_DEVICE (1 << 8)
+#define TFA98XX_FLAG_ADAPT_NOISE_MODE (1 << 9)
+
+#define TFA98XX_NUM_RATES 9
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+#define FW_ACTION_HOTPLUG 1
+#endif
+
+/* DSP init status */
+enum tfa98xx_dsp_init_state {
+ TFA98XX_DSP_INIT_STOPPED, /* DSP not running */
+ TFA98XX_DSP_INIT_RECOVER, /* DSP error detected at runtime */
+ TFA98XX_DSP_INIT_FAIL, /* DSP init failed */
+ TFA98XX_DSP_INIT_PENDING, /* DSP start requested */
+ TFA98XX_DSP_INIT_DONE, /* DSP running */
+ TFA98XX_DSP_INIT_INVALIDATED, /* DSP was running, requires re-init */
+};
+
+enum tfa98xx_dsp_fw_state {
+ TFA98XX_DSP_FW_NONE = 0,
+ TFA98XX_DSP_FW_PENDING,
+ TFA98XX_DSP_FW_FAIL,
+ TFA98XX_DSP_FW_OK,
+};
+
+struct tfa98xx_firmware {
+ void *base;
+ struct tfa98xx_device *dev;
+ char name[9]; //TODO get length from tfa parameter defs
+};
+
+struct tfa98xx_baseprofile {
+ char basename[MAX_CONTROL_NAME]; /* profile basename */
+ int len; /* profile length */
+ int item_id; /* profile id */
+ int sr_rate_sup[TFA98XX_NUM_RATES]; /* sample rates supported by this profile */
+ struct list_head list; /* list of all profiles */
+};
+enum tfa_reset_polarity{
+ LOW=0,
+ HIGH=1
+};
+struct tfa98xx {
+ struct regmap *regmap;
+ struct i2c_client *i2c;
+ struct regulator *vdd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec;
+#else
+ struct snd_soc_codec *codec;
+#endif
+ struct workqueue_struct *tfa98xx_wq;
+ struct delayed_work init_work;
+ struct delayed_work monitor_work;
+ struct delayed_work interrupt_work;
+ struct delayed_work tapdet_work;
+ struct delayed_work nmodeupdate_work;
+ struct mutex dsp_lock;
+ int dsp_init;
+ int dsp_fw_state;
+ int sysclk;
+ int rst_gpio;
+ u16 rev;
+ int audio_mode;
+ struct tfa98xx_firmware fw;
+ char *fw_name;
+ int rate;
+ wait_queue_head_t wq;
+ struct device *dev;
+ unsigned int init_count;
+ int pstream;
+ int cstream;
+ struct input_dev *input;
+ bool tapdet_enabled; /* service enabled */
+ bool tapdet_open; /* device file opened */
+ unsigned int tapdet_profiles; /* tapdet profile bitfield */
+ bool tapdet_poll; /* tapdet running on polling mode */
+
+ unsigned int rate_constraint_list[TFA98XX_NUM_RATES];
+ struct snd_pcm_hw_constraint_list rate_constraint;
+
+ int reset_gpio;
+ int power_gpio;
+ int irq_gpio;
+ enum tfa_reset_polarity reset_polarity;
+ struct list_head list;
+ struct tfa_device *tfa;
+ int vstep;
+ int profile;
+ int prof_vsteps[TFACONT_MAXPROFS]; /* store vstep per profile (single device) */
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dbg_dir;
+#endif
+ u8 reg;
+ unsigned int flags;
+ bool set_mtp_cal;
+ uint16_t cal_data;
+};
+
+
+#endif /* __TFA98XX_INC__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx_genregs_N1C.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_genregs_N1C.h
new file mode 100644
index 00000000000..5ccc2db5baf
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_genregs_N1C.h
@@ -0,0 +1,3864 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa98xx_genregs.h
+ * This file was generated automatically on 09/01/15 at 09:40:23.
+ * Source file: TFA9888_N1C_I2C_regmap_V1.xlsx
+ */
+
+#ifndef TFA2_GENREGS_H
+#define TFA2_GENREGS_H
+
+
+#define TFA98XX_SYS_CONTROL0 0x00
+#define TFA98XX_SYS_CONTROL1 0x01
+#define TFA98XX_SYS_CONTROL2 0x02
+#define TFA98XX_DEVICE_REVISION 0x03
+#define TFA98XX_CLOCK_CONTROL 0x04
+#define TFA98XX_CLOCK_GATING_CONTROL 0x05
+#define TFA98XX_SIDE_TONE_CONFIG 0x0d
+#define TFA98XX_CTRL_DIGTOANA_REG 0x0e
+#define TFA98XX_STATUS_FLAGS0 0x10
+#define TFA98XX_STATUS_FLAGS1 0x11
+#define TFA98XX_STATUS_FLAGS2 0x12
+#define TFA98XX_STATUS_FLAGS3 0x13
+#define TFA98XX_STATUS_FLAGS4 0x14
+#define TFA98XX_BATTERY_VOLTAGE 0x15
+#define TFA98XX_TEMPERATURE 0x16
+#define TFA98XX_TDM_CONFIG0 0x20
+#define TFA98XX_TDM_CONFIG1 0x21
+#define TFA98XX_TDM_CONFIG2 0x22
+#define TFA98XX_TDM_CONFIG3 0x23
+#define TFA98XX_TDM_CONFIG4 0x24
+#define TFA98XX_TDM_CONFIG5 0x25
+#define TFA98XX_TDM_CONFIG6 0x26
+#define TFA98XX_TDM_CONFIG7 0x27
+#define TFA98XX_TDM_CONFIG8 0x28
+#define TFA98XX_TDM_CONFIG9 0x29
+#define TFA98XX_PDM_CONFIG0 0x31
+#define TFA98XX_PDM_CONFIG1 0x32
+#define TFA98XX_HAPTIC_DRIVER_CONFIG 0x33
+#define TFA98XX_GPIO_DATAIN_REG 0x34
+#define TFA98XX_GPIO_CONFIG 0x35
+#define TFA98XX_INTERRUPT_OUT_REG1 0x40
+#define TFA98XX_INTERRUPT_OUT_REG2 0x41
+#define TFA98XX_INTERRUPT_OUT_REG3 0x42
+#define TFA98XX_INTERRUPT_IN_REG1 0x44
+#define TFA98XX_INTERRUPT_IN_REG2 0x45
+#define TFA98XX_INTERRUPT_IN_REG3 0x46
+#define TFA98XX_INTERRUPT_ENABLE_REG1 0x48
+#define TFA98XX_INTERRUPT_ENABLE_REG2 0x49
+#define TFA98XX_INTERRUPT_ENABLE_REG3 0x4a
+#define TFA98XX_STATUS_POLARITY_REG1 0x4c
+#define TFA98XX_STATUS_POLARITY_REG2 0x4d
+#define TFA98XX_STATUS_POLARITY_REG3 0x4e
+#define TFA98XX_BAT_PROT_CONFIG 0x50
+#define TFA98XX_AUDIO_CONTROL 0x51
+#define TFA98XX_AMPLIFIER_CONFIG 0x52
+#define TFA98XX_AUDIO_CONTROL2 0x5a
+#define TFA98XX_DCDC_CONTROL0 0x70
+#define TFA98XX_CF_CONTROLS 0x90
+#define TFA98XX_CF_MAD 0x91
+#define TFA98XX_CF_MEM 0x92
+#define TFA98XX_CF_STATUS 0x93
+#define TFA98XX_MTPKEY2_REG 0xa1
+#define TFA98XX_MTP_STATUS 0xa2
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL 0xa3
+#define TFA98XX_MTP_DATA_OUT_MSB 0xa5
+#define TFA98XX_MTP_DATA_OUT_LSB 0xa6
+#define TFA98XX_TEMP_SENSOR_CONFIG 0xb1
+#define TFA98XX_KEY2_PROTECTED_MTP0 0xf0
+#define TFA98XX_KEY1_PROTECTED_MTP4 0xf4
+#define TFA98XX_KEY1_PROTECTED_MTP5 0xf5
+
+/*
+ * (0x00)-sys_control0
+ */
+
+/*
+ * powerdown
+ */
+#define TFA98XX_SYS_CONTROL0_PWDN (0x1<<0)
+#define TFA98XX_SYS_CONTROL0_PWDN_POS 0
+#define TFA98XX_SYS_CONTROL0_PWDN_LEN 1
+#define TFA98XX_SYS_CONTROL0_PWDN_MAX 1
+#define TFA98XX_SYS_CONTROL0_PWDN_MSK 0x1
+
+/*
+ * reset
+ */
+#define TFA98XX_SYS_CONTROL0_I2CR (0x1<<1)
+#define TFA98XX_SYS_CONTROL0_I2CR_POS 1
+#define TFA98XX_SYS_CONTROL0_I2CR_LEN 1
+#define TFA98XX_SYS_CONTROL0_I2CR_MAX 1
+#define TFA98XX_SYS_CONTROL0_I2CR_MSK 0x2
+
+/*
+ * enbl_coolflux
+ */
+#define TFA98XX_SYS_CONTROL0_CFE (0x1<<2)
+#define TFA98XX_SYS_CONTROL0_CFE_POS 2
+#define TFA98XX_SYS_CONTROL0_CFE_LEN 1
+#define TFA98XX_SYS_CONTROL0_CFE_MAX 1
+#define TFA98XX_SYS_CONTROL0_CFE_MSK 0x4
+
+/*
+ * enbl_amplifier
+ */
+#define TFA98XX_SYS_CONTROL0_AMPE (0x1<<3)
+#define TFA98XX_SYS_CONTROL0_AMPE_POS 3
+#define TFA98XX_SYS_CONTROL0_AMPE_LEN 1
+#define TFA98XX_SYS_CONTROL0_AMPE_MAX 1
+#define TFA98XX_SYS_CONTROL0_AMPE_MSK 0x8
+
+/*
+ * enbl_boost
+ */
+#define TFA98XX_SYS_CONTROL0_DCA (0x1<<4)
+#define TFA98XX_SYS_CONTROL0_DCA_POS 4
+#define TFA98XX_SYS_CONTROL0_DCA_LEN 1
+#define TFA98XX_SYS_CONTROL0_DCA_MAX 1
+#define TFA98XX_SYS_CONTROL0_DCA_MSK 0x10
+
+/*
+ * coolflux_configured
+ */
+#define TFA98XX_SYS_CONTROL0_SBSL (0x1<<5)
+#define TFA98XX_SYS_CONTROL0_SBSL_POS 5
+#define TFA98XX_SYS_CONTROL0_SBSL_LEN 1
+#define TFA98XX_SYS_CONTROL0_SBSL_MAX 1
+#define TFA98XX_SYS_CONTROL0_SBSL_MSK 0x20
+
+/*
+ * sel_enbl_amplifier
+ */
+#define TFA98XX_SYS_CONTROL0_AMPC (0x1<<6)
+#define TFA98XX_SYS_CONTROL0_AMPC_POS 6
+#define TFA98XX_SYS_CONTROL0_AMPC_LEN 1
+#define TFA98XX_SYS_CONTROL0_AMPC_MAX 1
+#define TFA98XX_SYS_CONTROL0_AMPC_MSK 0x40
+
+/*
+ * int_pad_io
+ */
+#define TFA98XX_SYS_CONTROL0_INTP (0x3<<7)
+#define TFA98XX_SYS_CONTROL0_INTP_POS 7
+#define TFA98XX_SYS_CONTROL0_INTP_LEN 2
+#define TFA98XX_SYS_CONTROL0_INTP_MAX 3
+#define TFA98XX_SYS_CONTROL0_INTP_MSK 0x180
+
+/*
+ * fs_pulse_sel
+ */
+#define TFA98XX_SYS_CONTROL0_FSSSEL (0x3<<9)
+#define TFA98XX_SYS_CONTROL0_FSSSEL_POS 9
+#define TFA98XX_SYS_CONTROL0_FSSSEL_LEN 2
+#define TFA98XX_SYS_CONTROL0_FSSSEL_MAX 3
+#define TFA98XX_SYS_CONTROL0_FSSSEL_MSK 0x600
+
+/*
+ * bypass_ocp
+ */
+#define TFA98XX_SYS_CONTROL0_BYPOCP (0x1<<11)
+#define TFA98XX_SYS_CONTROL0_BYPOCP_POS 11
+#define TFA98XX_SYS_CONTROL0_BYPOCP_LEN 1
+#define TFA98XX_SYS_CONTROL0_BYPOCP_MAX 1
+#define TFA98XX_SYS_CONTROL0_BYPOCP_MSK 0x800
+
+/*
+ * test_ocp
+ */
+#define TFA98XX_SYS_CONTROL0_TSTOCP (0x1<<12)
+#define TFA98XX_SYS_CONTROL0_TSTOCP_POS 12
+#define TFA98XX_SYS_CONTROL0_TSTOCP_LEN 1
+#define TFA98XX_SYS_CONTROL0_TSTOCP_MAX 1
+#define TFA98XX_SYS_CONTROL0_TSTOCP_MSK 0x1000
+
+
+/*
+ * (0x01)-sys_control1
+ */
+
+/*
+ * vamp_sel
+ */
+#define TFA98XX_SYS_CONTROL1_AMPINSEL (0x3<<0)
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_POS 0
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_LEN 2
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_MAX 3
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_MSK 0x3
+
+/*
+ * src_set_configured
+ */
+#define TFA98XX_SYS_CONTROL1_MANSCONF (0x1<<2)
+#define TFA98XX_SYS_CONTROL1_MANSCONF_POS 2
+#define TFA98XX_SYS_CONTROL1_MANSCONF_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANSCONF_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANSCONF_MSK 0x4
+
+/*
+ * execute_cold_start
+ */
+#define TFA98XX_SYS_CONTROL1_MANCOLD (0x1<<3)
+#define TFA98XX_SYS_CONTROL1_MANCOLD_POS 3
+#define TFA98XX_SYS_CONTROL1_MANCOLD_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANCOLD_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANCOLD_MSK 0x8
+
+/*
+ * enbl_osc1m_auto_off
+ */
+#define TFA98XX_SYS_CONTROL1_MANAOOSC (0x1<<4)
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_POS 4
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_MSK 0x10
+
+/*
+ * man_enbl_brown_out
+ */
+#define TFA98XX_SYS_CONTROL1_MANROBOD (0x1<<5)
+#define TFA98XX_SYS_CONTROL1_MANROBOD_POS 5
+#define TFA98XX_SYS_CONTROL1_MANROBOD_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANROBOD_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANROBOD_MSK 0x20
+
+/*
+ * enbl_bod
+ */
+#define TFA98XX_SYS_CONTROL1_BODE (0x1<<6)
+#define TFA98XX_SYS_CONTROL1_BODE_POS 6
+#define TFA98XX_SYS_CONTROL1_BODE_LEN 1
+#define TFA98XX_SYS_CONTROL1_BODE_MAX 1
+#define TFA98XX_SYS_CONTROL1_BODE_MSK 0x40
+
+/*
+ * enbl_bod_hyst
+ */
+#define TFA98XX_SYS_CONTROL1_BODHYS (0x1<<7)
+#define TFA98XX_SYS_CONTROL1_BODHYS_POS 7
+#define TFA98XX_SYS_CONTROL1_BODHYS_LEN 1
+#define TFA98XX_SYS_CONTROL1_BODHYS_MAX 1
+#define TFA98XX_SYS_CONTROL1_BODHYS_MSK 0x80
+
+/*
+ * bod_delay
+ */
+#define TFA98XX_SYS_CONTROL1_BODFILT (0x3<<8)
+#define TFA98XX_SYS_CONTROL1_BODFILT_POS 8
+#define TFA98XX_SYS_CONTROL1_BODFILT_LEN 2
+#define TFA98XX_SYS_CONTROL1_BODFILT_MAX 3
+#define TFA98XX_SYS_CONTROL1_BODFILT_MSK 0x300
+
+/*
+ * bod_lvlsel
+ */
+#define TFA98XX_SYS_CONTROL1_BODTHLVL (0x3<<10)
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_POS 10
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_LEN 2
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_MAX 3
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_MSK 0xc00
+
+/*
+ * disable_mute_time_out
+ */
+#define TFA98XX_SYS_CONTROL1_MUTETO (0x1<<13)
+#define TFA98XX_SYS_CONTROL1_MUTETO_POS 13
+#define TFA98XX_SYS_CONTROL1_MUTETO_LEN 1
+#define TFA98XX_SYS_CONTROL1_MUTETO_MAX 1
+#define TFA98XX_SYS_CONTROL1_MUTETO_MSK 0x2000
+
+/*
+ * pwm_sel_rcv_ns
+ */
+#define TFA98XX_SYS_CONTROL1_RCVNS (0x1<<14)
+#define TFA98XX_SYS_CONTROL1_RCVNS_POS 14
+#define TFA98XX_SYS_CONTROL1_RCVNS_LEN 1
+#define TFA98XX_SYS_CONTROL1_RCVNS_MAX 1
+#define TFA98XX_SYS_CONTROL1_RCVNS_MSK 0x4000
+
+/*
+ * man_enbl_watchdog
+ */
+#define TFA98XX_SYS_CONTROL1_MANWDE (0x1<<15)
+#define TFA98XX_SYS_CONTROL1_MANWDE_POS 15
+#define TFA98XX_SYS_CONTROL1_MANWDE_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANWDE_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANWDE_MSK 0x8000
+
+
+/*
+ * (0x02)-sys_control2
+ */
+
+/*
+ * audio_fs
+ */
+#define TFA98XX_SYS_CONTROL2_AUDFS (0xf<<0)
+#define TFA98XX_SYS_CONTROL2_AUDFS_POS 0
+#define TFA98XX_SYS_CONTROL2_AUDFS_LEN 4
+#define TFA98XX_SYS_CONTROL2_AUDFS_MAX 15
+#define TFA98XX_SYS_CONTROL2_AUDFS_MSK 0xf
+
+/*
+ * input_level
+ */
+#define TFA98XX_SYS_CONTROL2_INPLEV (0x1<<4)
+#define TFA98XX_SYS_CONTROL2_INPLEV_POS 4
+#define TFA98XX_SYS_CONTROL2_INPLEV_LEN 1
+#define TFA98XX_SYS_CONTROL2_INPLEV_MAX 1
+#define TFA98XX_SYS_CONTROL2_INPLEV_MSK 0x10
+
+/*
+ * cs_frac_delay
+ */
+#define TFA98XX_SYS_CONTROL2_FRACTDEL (0x3f<<5)
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_POS 5
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_LEN 6
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_MAX 63
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_MSK 0x7e0
+
+/*
+ * bypass_hvbat_filter
+ */
+#define TFA98XX_SYS_CONTROL2_BYPHVBF (0x1<<11)
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_POS 11
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_LEN 1
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_MAX 1
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_MSK 0x800
+
+/*
+ * ctrl_rcvldop_bypass
+ */
+#define TFA98XX_SYS_CONTROL2_LDOBYP (0x1<<12)
+#define TFA98XX_SYS_CONTROL2_LDOBYP_POS 12
+#define TFA98XX_SYS_CONTROL2_LDOBYP_LEN 1
+#define TFA98XX_SYS_CONTROL2_LDOBYP_MAX 1
+#define TFA98XX_SYS_CONTROL2_LDOBYP_MSK 0x1000
+
+
+/*
+ * (0x03)-device_revision
+ */
+
+/*
+ * device_rev
+ */
+#define TFA98XX_DEVICE_REVISION_REV (0xffff<<0)
+#define TFA98XX_DEVICE_REVISION_REV_POS 0
+#define TFA98XX_DEVICE_REVISION_REV_LEN 16
+#define TFA98XX_DEVICE_REVISION_REV_MAX 65535
+#define TFA98XX_DEVICE_REVISION_REV_MSK 0xffff
+
+
+/*
+ * (0x04)-clock_control
+ */
+
+/*
+ * pll_clkin_sel
+ */
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT (0x3<<0)
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_POS 0
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_LEN 2
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_MAX 3
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_MSK 0x3
+
+/*
+ * pll_clkin_sel_osc
+ */
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL (0x1<<2)
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_POS 2
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_LEN 1
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_MAX 1
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_MSK 0x4
+
+
+/*
+ * (0x05)-clock_gating_control
+ */
+
+/*
+ * enbl_spkr_ss_left
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE (0x1<<0)
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_POS 0
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_MSK 0x1
+
+/*
+ * enbl_spkr_ss_right
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE (0x1<<1)
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_POS 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_MSK 0x2
+
+/*
+ * enbl_volsense_left
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE (0x1<<2)
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_POS 2
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_MSK 0x4
+
+/*
+ * enbl_volsense_right
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE (0x1<<3)
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_POS 3
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_MSK 0x8
+
+/*
+ * enbl_cursense_left
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE (0x1<<4)
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_POS 4
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_MSK 0x10
+
+/*
+ * enbl_cursense_right
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE (0x1<<5)
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_POS 5
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_MSK 0x20
+
+/*
+ * enbl_pdm_ss
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME (0x1<<6)
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_POS 6
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_MSK 0x40
+
+
+/*
+ * (0x0d)-side_tone_config
+ */
+
+/*
+ * side_tone_gain
+ */
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN (0x1ff<<1)
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_POS 1
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_LEN 9
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_MAX 511
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_MSK 0x3fe
+
+/*
+ * mute_side_tone
+ */
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE (0x1<<10)
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_POS 10
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_LEN 1
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_MAX 1
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_MSK 0x400
+
+
+/*
+ * (0x0e)-ctrl_digtoana_reg
+ */
+
+/*
+ * ctrl_digtoana
+ */
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP (0x7f<<0)
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_POS 0
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_LEN 7
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_MAX 127
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_MSK 0x7f
+
+
+/*
+ * (0x10)-status_flags0
+ */
+
+/*
+ * flag_por
+ */
+#define TFA98XX_STATUS_FLAGS0_VDDS (0x1<<0)
+#define TFA98XX_STATUS_FLAGS0_VDDS_POS 0
+#define TFA98XX_STATUS_FLAGS0_VDDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_VDDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_VDDS_MSK 0x1
+
+/*
+ * flag_pll_lock
+ */
+#define TFA98XX_STATUS_FLAGS0_PLLS (0x1<<1)
+#define TFA98XX_STATUS_FLAGS0_PLLS_POS 1
+#define TFA98XX_STATUS_FLAGS0_PLLS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_PLLS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_PLLS_MSK 0x2
+
+/*
+ * flag_otpok
+ */
+#define TFA98XX_STATUS_FLAGS0_OTDS (0x1<<2)
+#define TFA98XX_STATUS_FLAGS0_OTDS_POS 2
+#define TFA98XX_STATUS_FLAGS0_OTDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_OTDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_OTDS_MSK 0x4
+
+/*
+ * flag_ovpok
+ */
+#define TFA98XX_STATUS_FLAGS0_OVDS (0x1<<3)
+#define TFA98XX_STATUS_FLAGS0_OVDS_POS 3
+#define TFA98XX_STATUS_FLAGS0_OVDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_OVDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_OVDS_MSK 0x8
+
+/*
+ * flag_uvpok
+ */
+#define TFA98XX_STATUS_FLAGS0_UVDS (0x1<<4)
+#define TFA98XX_STATUS_FLAGS0_UVDS_POS 4
+#define TFA98XX_STATUS_FLAGS0_UVDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_UVDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_UVDS_MSK 0x10
+
+/*
+ * flag_clocks_stable
+ */
+#define TFA98XX_STATUS_FLAGS0_CLKS (0x1<<6)
+#define TFA98XX_STATUS_FLAGS0_CLKS_POS 5
+#define TFA98XX_STATUS_FLAGS0_CLKS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_CLKS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_CLKS_MSK 0x20
+
+/*
+ * flag_mtp_busy
+ */
+#define TFA98XX_STATUS_FLAGS0_MTPB (0x1<<6)
+#define TFA98XX_STATUS_FLAGS0_MTPB_POS 6
+#define TFA98XX_STATUS_FLAGS0_MTPB_LEN 1
+#define TFA98XX_STATUS_FLAGS0_MTPB_MAX 1
+#define TFA98XX_STATUS_FLAGS0_MTPB_MSK 0x40
+
+/*
+ * flag_lost_clk
+ */
+#define TFA98XX_STATUS_FLAGS0_NOCLK (0x1<<7)
+#define TFA98XX_STATUS_FLAGS0_NOCLK_POS 7
+#define TFA98XX_STATUS_FLAGS0_NOCLK_LEN 1
+#define TFA98XX_STATUS_FLAGS0_NOCLK_MAX 1
+#define TFA98XX_STATUS_FLAGS0_NOCLK_MSK 0x80
+
+/*
+ * flag_cf_speakererror
+ */
+#define TFA98XX_STATUS_FLAGS0_SPKS (0x1<<8)
+#define TFA98XX_STATUS_FLAGS0_SPKS_POS 8
+#define TFA98XX_STATUS_FLAGS0_SPKS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_SPKS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_SPKS_MSK 0x100
+
+/*
+ * flag_cold_started
+ */
+#define TFA98XX_STATUS_FLAGS0_ACS (0x1<<9)
+#define TFA98XX_STATUS_FLAGS0_ACS_POS 9
+#define TFA98XX_STATUS_FLAGS0_ACS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_ACS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_ACS_MSK 0x200
+
+/*
+ * flag_engage
+ */
+#define TFA98XX_STATUS_FLAGS0_SWS (0x1<<10)
+#define TFA98XX_STATUS_FLAGS0_SWS_POS 10
+#define TFA98XX_STATUS_FLAGS0_SWS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_SWS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_SWS_MSK 0x400
+
+/*
+ * flag_watchdog_reset
+ */
+#define TFA98XX_STATUS_FLAGS0_WDS (0x1<<11)
+#define TFA98XX_STATUS_FLAGS0_WDS_POS 11
+#define TFA98XX_STATUS_FLAGS0_WDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_WDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_WDS_MSK 0x800
+
+/*
+ * flag_enbl_amp
+ */
+#define TFA98XX_STATUS_FLAGS0_AMPS (0x1<<12)
+#define TFA98XX_STATUS_FLAGS0_AMPS_POS 12
+#define TFA98XX_STATUS_FLAGS0_AMPS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_AMPS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_AMPS_MSK 0x1000
+
+/*
+ * flag_enbl_ref
+ */
+#define TFA98XX_STATUS_FLAGS0_AREFS (0x1<<13)
+#define TFA98XX_STATUS_FLAGS0_AREFS_POS 13
+#define TFA98XX_STATUS_FLAGS0_AREFS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_AREFS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_AREFS_MSK 0x2000
+
+/*
+ * flag_adc10_ready
+ */
+#define TFA98XX_STATUS_FLAGS0_ADCCR (0x1<<14)
+#define TFA98XX_STATUS_FLAGS0_ADCCR_POS 14
+#define TFA98XX_STATUS_FLAGS0_ADCCR_LEN 1
+#define TFA98XX_STATUS_FLAGS0_ADCCR_MAX 1
+#define TFA98XX_STATUS_FLAGS0_ADCCR_MSK 0x4000
+
+/*
+ * flag_bod_vddd_nok
+ */
+#define TFA98XX_STATUS_FLAGS0_BODNOK (0x1<<15)
+#define TFA98XX_STATUS_FLAGS0_BODNOK_POS 15
+#define TFA98XX_STATUS_FLAGS0_BODNOK_LEN 1
+#define TFA98XX_STATUS_FLAGS0_BODNOK_MAX 1
+#define TFA98XX_STATUS_FLAGS0_BODNOK_MSK 0x8000
+
+
+/*
+ * (0x11)-status_flags1
+ */
+
+/*
+ * flag_bst_bstcur
+ */
+#define TFA98XX_STATUS_FLAGS1_DCIL (0x1<<0)
+#define TFA98XX_STATUS_FLAGS1_DCIL_POS 0
+#define TFA98XX_STATUS_FLAGS1_DCIL_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCIL_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCIL_MSK 0x1
+
+/*
+ * flag_bst_hiz
+ */
+#define TFA98XX_STATUS_FLAGS1_DCDCA (0x1<<1)
+#define TFA98XX_STATUS_FLAGS1_DCDCA_POS 1
+#define TFA98XX_STATUS_FLAGS1_DCDCA_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCDCA_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCDCA_MSK 0x2
+
+/*
+ * flag_bst_ocpok
+ */
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK (0x1<<2)
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_POS 2
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_MSK 0x4
+
+/*
+ * flag_bst_voutcomp
+ */
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT (0x1<<4)
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_POS 4
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_MSK 0x10
+
+/*
+ * flag_bst_voutcomp86
+ */
+#define TFA98XX_STATUS_FLAGS1_DCH114 (0x1<<5)
+#define TFA98XX_STATUS_FLAGS1_DCH114_POS 5
+#define TFA98XX_STATUS_FLAGS1_DCH114_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCH114_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCH114_MSK 0x20
+
+/*
+ * flag_bst_voutcomp93
+ */
+#define TFA98XX_STATUS_FLAGS1_DCH107 (0x1<<6)
+#define TFA98XX_STATUS_FLAGS1_DCH107_POS 6
+#define TFA98XX_STATUS_FLAGS1_DCH107_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCH107_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCH107_MSK 0x40
+
+/*
+ * flag_soft_mute_busy
+ */
+#define TFA98XX_STATUS_FLAGS1_STMUTEB (0x1<<7)
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_POS 7
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_LEN 1
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_MAX 1
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_MSK 0x80
+
+/*
+ * flag_soft_mute_state
+ */
+#define TFA98XX_STATUS_FLAGS1_STMUTE (0x1<<8)
+#define TFA98XX_STATUS_FLAGS1_STMUTE_POS 8
+#define TFA98XX_STATUS_FLAGS1_STMUTE_LEN 1
+#define TFA98XX_STATUS_FLAGS1_STMUTE_MAX 1
+#define TFA98XX_STATUS_FLAGS1_STMUTE_MSK 0x100
+
+/*
+ * flag_tdm_lut_error
+ */
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER (0x1<<9)
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_POS 9
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_LEN 1
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_MAX 1
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_MSK 0x200
+
+/*
+ * flag_tdm_status
+ */
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT (0x7<<10)
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_POS 10
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_LEN 3
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_MAX 7
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_MSK 0x1c00
+
+/*
+ * flag_tdm_error
+ */
+#define TFA98XX_STATUS_FLAGS1_TDMERR (0x1<<13)
+#define TFA98XX_STATUS_FLAGS1_TDMERR_POS 13
+#define TFA98XX_STATUS_FLAGS1_TDMERR_LEN 1
+#define TFA98XX_STATUS_FLAGS1_TDMERR_MAX 1
+#define TFA98XX_STATUS_FLAGS1_TDMERR_MSK 0x2000
+
+/*
+ * flag_haptic_busy
+ */
+#define TFA98XX_STATUS_FLAGS1_HAPTIC (0x1<<14)
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_POS 14
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_LEN 1
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_MAX 1
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_MSK 0x4000
+
+
+/*
+ * (0x12)-status_flags2
+ */
+
+/*
+ * flag_ocpokap_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL (0x1<<0)
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_POS 0
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_MSK 0x1
+
+/*
+ * flag_ocpokan_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOANL (0x1<<1)
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_POS 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_MSK 0x2
+
+/*
+ * flag_ocpokbp_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL (0x1<<2)
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_POS 2
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_MSK 0x4
+
+/*
+ * flag_ocpokbn_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL (0x1<<3)
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_POS 3
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_MSK 0x8
+
+/*
+ * flag_clipa_high_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL (0x1<<4)
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_POS 4
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_MSK 0x10
+
+/*
+ * flag_clipa_low_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPALL (0x1<<5)
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_POS 5
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_MSK 0x20
+
+/*
+ * flag_clipb_high_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL (0x1<<6)
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_POS 6
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_MSK 0x40
+
+/*
+ * flag_clipb_low_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL (0x1<<7)
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_POS 7
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_MSK 0x80
+
+/*
+ * flag_ocpokap_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC (0x1<<8)
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_POS 8
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_MSK 0x100
+
+/*
+ * flag_ocpokan_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC (0x1<<9)
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_POS 9
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_MSK 0x200
+
+/*
+ * flag_ocpokbp_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC (0x1<<10)
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_POS 10
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_MSK 0x400
+
+/*
+ * flag_ocpokbn_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC (0x1<<11)
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_POS 11
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_MSK 0x800
+
+/*
+ * flag_rcvldop_ready
+ */
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR (0x1<<12)
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_POS 12
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_LEN 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_MAX 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_MSK 0x1000
+
+/*
+ * flag_rcvldop_bypassready
+ */
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR (0x1<<13)
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_POS 13
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_LEN 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_MAX 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_MSK 0x2000
+
+/*
+ * flag_ocp_alarm_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCDSL (0x1<<14)
+#define TFA98XX_STATUS_FLAGS2_OCDSL_POS 14
+#define TFA98XX_STATUS_FLAGS2_OCDSL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCDSL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCDSL_MSK 0x4000
+
+/*
+ * flag_clip_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPSL (0x1<<15)
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_POS 15
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_MSK 0x8000
+
+
+/*
+ * (0x13)-status_flags3
+ */
+
+/*
+ * flag_ocpokap_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR (0x1<<0)
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_POS 0
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_MSK 0x1
+
+/*
+ * flag_ocpokan_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOANR (0x1<<1)
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_POS 1
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_MSK 0x2
+
+/*
+ * flag_ocpokbp_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR (0x1<<2)
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_POS 2
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_MSK 0x4
+
+/*
+ * flag_ocpokbn_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR (0x1<<3)
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_POS 3
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_MSK 0x8
+
+/*
+ * flag_clipa_high_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR (0x1<<4)
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_POS 4
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_MSK 0x10
+
+/*
+ * flag_clipa_low_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPALR (0x1<<5)
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_POS 5
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_MSK 0x20
+
+/*
+ * flag_clipb_high_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR (0x1<<6)
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_POS 6
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_MSK 0x40
+
+/*
+ * flag_clipb_low_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR (0x1<<7)
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_POS 7
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_MSK 0x80
+
+/*
+ * flag_ocp_alarm_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCDSR (0x1<<8)
+#define TFA98XX_STATUS_FLAGS3_OCDSR_POS 8
+#define TFA98XX_STATUS_FLAGS3_OCDSR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCDSR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCDSR_MSK 0x100
+
+/*
+ * flag_clip_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPSR (0x1<<9)
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_POS 9
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_MSK 0x200
+
+/*
+ * flag_mic_ocpok
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC (0x1<<10)
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_POS 10
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_MSK 0x400
+
+/*
+ * flag_man_alarm_state
+ */
+#define TFA98XX_STATUS_FLAGS3_MANALARM (0x1<<11)
+#define TFA98XX_STATUS_FLAGS3_MANALARM_POS 11
+#define TFA98XX_STATUS_FLAGS3_MANALARM_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANALARM_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANALARM_MSK 0x800
+
+/*
+ * flag_man_wait_src_settings
+ */
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1 (0x1<<12)
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_POS 12
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_MSK 0x1000
+
+/*
+ * flag_man_wait_cf_config
+ */
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2 (0x1<<13)
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_POS 13
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_MSK 0x2000
+
+/*
+ * flag_man_start_mute_audio
+ */
+#define TFA98XX_STATUS_FLAGS3_MANMUTE (0x1<<14)
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_POS 14
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_MSK 0x4000
+
+/*
+ * flag_man_operating_state
+ */
+#define TFA98XX_STATUS_FLAGS3_MANOPER (0x1<<15)
+#define TFA98XX_STATUS_FLAGS3_MANOPER_POS 15
+#define TFA98XX_STATUS_FLAGS3_MANOPER_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANOPER_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANOPER_MSK 0x8000
+
+
+/*
+ * (0x14)-status_flags4
+ */
+
+/*
+ * flag_cf_speakererror_left
+ */
+#define TFA98XX_STATUS_FLAGS4_SPKSL (0x1<<0)
+#define TFA98XX_STATUS_FLAGS4_SPKSL_POS 0
+#define TFA98XX_STATUS_FLAGS4_SPKSL_LEN 1
+#define TFA98XX_STATUS_FLAGS4_SPKSL_MAX 1
+#define TFA98XX_STATUS_FLAGS4_SPKSL_MSK 0x1
+
+/*
+ * flag_cf_speakererror_right
+ */
+#define TFA98XX_STATUS_FLAGS4_SPKSR (0x1<<1)
+#define TFA98XX_STATUS_FLAGS4_SPKSR_POS 1
+#define TFA98XX_STATUS_FLAGS4_SPKSR_LEN 1
+#define TFA98XX_STATUS_FLAGS4_SPKSR_MAX 1
+#define TFA98XX_STATUS_FLAGS4_SPKSR_MSK 0x2
+
+/*
+ * flag_clk_out_of_range
+ */
+#define TFA98XX_STATUS_FLAGS4_CLKOOR (0x1<<2)
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_POS 2
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_LEN 1
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_MAX 1
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_MSK 0x4
+
+/*
+ * man_state
+ */
+#define TFA98XX_STATUS_FLAGS4_MANSTATE (0xf<<3)
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_POS 3
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_LEN 4
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_MAX 15
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_MSK 0x78
+
+
+/*
+ * (0x15)-battery_voltage
+ */
+
+/*
+ * bat_adc
+ */
+#define TFA98XX_BATTERY_VOLTAGE_BATS (0x3ff<<0)
+#define TFA98XX_BATTERY_VOLTAGE_BATS_POS 0
+#define TFA98XX_BATTERY_VOLTAGE_BATS_LEN 10
+#define TFA98XX_BATTERY_VOLTAGE_BATS_MAX 1023
+#define TFA98XX_BATTERY_VOLTAGE_BATS_MSK 0x3ff
+
+
+/*
+ * (0x16)-temperature
+ */
+
+/*
+ * temp_adc
+ */
+#define TFA98XX_TEMPERATURE_TEMPS (0x1ff<<0)
+#define TFA98XX_TEMPERATURE_TEMPS_POS 0
+#define TFA98XX_TEMPERATURE_TEMPS_LEN 9
+#define TFA98XX_TEMPERATURE_TEMPS_MAX 511
+#define TFA98XX_TEMPERATURE_TEMPS_MSK 0x1ff
+
+
+/*
+ * (0x20)-tdm_config0
+ */
+
+/*
+ * tdm_usecase
+ */
+#define TFA98XX_TDM_CONFIG0_TDMUC (0xf<<0)
+#define TFA98XX_TDM_CONFIG0_TDMUC_POS 0
+#define TFA98XX_TDM_CONFIG0_TDMUC_LEN 4
+#define TFA98XX_TDM_CONFIG0_TDMUC_MAX 15
+#define TFA98XX_TDM_CONFIG0_TDMUC_MSK 0xf
+
+/*
+ * tdm_enable
+ */
+#define TFA98XX_TDM_CONFIG0_TDME (0x1<<4)
+#define TFA98XX_TDM_CONFIG0_TDME_POS 4
+#define TFA98XX_TDM_CONFIG0_TDME_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDME_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDME_MSK 0x10
+
+/*
+ * tdm_mode
+ */
+#define TFA98XX_TDM_CONFIG0_TDMMODE (0x1<<5)
+#define TFA98XX_TDM_CONFIG0_TDMMODE_POS 5
+#define TFA98XX_TDM_CONFIG0_TDMMODE_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDMMODE_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDMMODE_MSK 0x20
+
+/*
+ * tdm_clk_inversion
+ */
+#define TFA98XX_TDM_CONFIG0_TDMCLINV (0x1<<6)
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_POS 6
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_MSK 0x40
+
+/*
+ * tdm_fs_ws_length
+ */
+#define TFA98XX_TDM_CONFIG0_TDMFSLN (0xf<<7)
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_POS 7
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_LEN 4
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_MAX 15
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_MSK 0x780
+
+/*
+ * tdm_fs_ws_polarity
+ */
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL (0x1<<11)
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_POS 11
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_MSK 0x800
+
+/*
+ * tdm_nbck
+ */
+#define TFA98XX_TDM_CONFIG0_TDMNBCK (0xf<<12)
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_POS 12
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_LEN 4
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_MAX 15
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_MSK 0xf000
+
+
+/*
+ * (0x21)-tdm_config1
+ */
+
+/*
+ * tdm_nb_of_slots
+ */
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS (0xf<<0)
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_POS 0
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_LEN 4
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_MAX 15
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_MSK 0xf
+
+/*
+ * tdm_slot_length
+ */
+#define TFA98XX_TDM_CONFIG1_TDMSLLN (0x1f<<4)
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_POS 4
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_LEN 5
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_MAX 31
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_MSK 0x1f0
+
+/*
+ * tdm_bits_remaining
+ */
+#define TFA98XX_TDM_CONFIG1_TDMBRMG (0x1f<<9)
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_POS 9
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_LEN 5
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_MAX 31
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_MSK 0x3e00
+
+/*
+ * tdm_data_delay
+ */
+#define TFA98XX_TDM_CONFIG1_TDMDEL (0x1<<14)
+#define TFA98XX_TDM_CONFIG1_TDMDEL_POS 14
+#define TFA98XX_TDM_CONFIG1_TDMDEL_LEN 1
+#define TFA98XX_TDM_CONFIG1_TDMDEL_MAX 1
+#define TFA98XX_TDM_CONFIG1_TDMDEL_MSK 0x4000
+
+/*
+ * tdm_data_adjustment
+ */
+#define TFA98XX_TDM_CONFIG1_TDMADJ (0x1<<15)
+#define TFA98XX_TDM_CONFIG1_TDMADJ_POS 15
+#define TFA98XX_TDM_CONFIG1_TDMADJ_LEN 1
+#define TFA98XX_TDM_CONFIG1_TDMADJ_MAX 1
+#define TFA98XX_TDM_CONFIG1_TDMADJ_MSK 0x8000
+
+
+/*
+ * (0x22)-tdm_config2
+ */
+
+/*
+ * tdm_audio_sample_compression
+ */
+#define TFA98XX_TDM_CONFIG2_TDMOOMP (0x3<<0)
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_POS 0
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_MSK 0x3
+
+/*
+ * tdm_sample_size
+ */
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE (0x1f<<2)
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_POS 2
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_LEN 5
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_MAX 31
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_MSK 0x7c
+
+/*
+ * tdm_txdata_format
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO (0x3<<7)
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_POS 7
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_MSK 0x180
+
+/*
+ * tdm_txdata_format_unused_slot_sd0
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0 (0x3<<9)
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_POS 9
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_MSK 0x600
+
+/*
+ * tdm_txdata_format_unused_slot_sd1
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1 (0x3<<11)
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_POS 11
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_MSK 0x1800
+
+/*
+ * tdm_txdata_format_unused_slot_sd2
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2 (0x3<<13)
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_POS 13
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_MSK 0x6000
+
+
+/*
+ * (0x23)-tdm_config3
+ */
+
+/*
+ * tdm_sink1_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMLE (0x1<<1)
+#define TFA98XX_TDM_CONFIG3_TDMLE_POS 1
+#define TFA98XX_TDM_CONFIG3_TDMLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMLE_MSK 0x2
+
+/*
+ * tdm_sink2_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMRE (0x1<<2)
+#define TFA98XX_TDM_CONFIG3_TDMRE_POS 2
+#define TFA98XX_TDM_CONFIG3_TDMRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMRE_MSK 0x4
+
+/*
+ * tdm_source1_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMVSRE (0x1<<4)
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_POS 4
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_MSK 0x10
+
+/*
+ * tdm_source2_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCSRE (0x1<<5)
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_POS 5
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_MSK 0x20
+
+/*
+ * tdm_source3_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMVSLE (0x1<<6)
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_POS 6
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_MSK 0x40
+
+/*
+ * tdm_source4_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCSLE (0x1<<7)
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_POS 7
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_MSK 0x80
+
+/*
+ * tdm_source5_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCFRE (0x1<<8)
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_POS 8
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_MSK 0x100
+
+/*
+ * tdm_source6_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCFLE (0x1<<9)
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_POS 9
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_MSK 0x200
+
+/*
+ * tdm_source7_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCF3E (0x1<<10)
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_POS 10
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_MSK 0x400
+
+/*
+ * tdm_source8_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCF4E (0x1<<11)
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_POS 11
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_MSK 0x800
+
+/*
+ * tdm_source9_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMPD1E (0x1<<12)
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_POS 12
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_MSK 0x1000
+
+/*
+ * tdm_source10_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMPD2E (0x1<<13)
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_POS 13
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_MSK 0x2000
+
+
+/*
+ * (0x24)-tdm_config4
+ */
+
+/*
+ * tdm_sink1_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMLIO (0x3<<2)
+#define TFA98XX_TDM_CONFIG4_TDMLIO_POS 2
+#define TFA98XX_TDM_CONFIG4_TDMLIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMLIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMLIO_MSK 0xc
+
+/*
+ * tdm_sink2_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMRIO (0x3<<4)
+#define TFA98XX_TDM_CONFIG4_TDMRIO_POS 4
+#define TFA98XX_TDM_CONFIG4_TDMRIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMRIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMRIO_MSK 0x30
+
+/*
+ * tdm_source1_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO (0x3<<8)
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_POS 8
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_MSK 0x300
+
+/*
+ * tdm_source2_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO (0x3<<10)
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_POS 10
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_MSK 0xc00
+
+/*
+ * tdm_source3_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO (0x3<<12)
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_POS 12
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_MSK 0x3000
+
+/*
+ * tdm_source4_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO (0x3<<14)
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_POS 14
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_MSK 0xc000
+
+
+/*
+ * (0x25)-tdm_config5
+ */
+
+/*
+ * tdm_source5_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO (0x3<<0)
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_POS 0
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_MSK 0x3
+
+/*
+ * tdm_source6_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO (0x3<<2)
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_POS 2
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_MSK 0xc
+
+/*
+ * tdm_source7_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO (0x3<<4)
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_POS 4
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_MSK 0x30
+
+/*
+ * tdm_source8_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO (0x3<<6)
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_POS 6
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_MSK 0xc0
+
+/*
+ * tdm_source9_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO (0x3<<8)
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_POS 8
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_MSK 0x300
+
+/*
+ * tdm_source10_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO (0x3<<10)
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_POS 10
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_MSK 0xc00
+
+
+/*
+ * (0x26)-tdm_config6
+ */
+
+/*
+ * tdm_sink1_slot
+ */
+#define TFA98XX_TDM_CONFIG6_TDMLS (0xf<<4)
+#define TFA98XX_TDM_CONFIG6_TDMLS_POS 4
+#define TFA98XX_TDM_CONFIG6_TDMLS_LEN 4
+#define TFA98XX_TDM_CONFIG6_TDMLS_MAX 15
+#define TFA98XX_TDM_CONFIG6_TDMLS_MSK 0xf0
+
+/*
+ * tdm_sink2_slot
+ */
+#define TFA98XX_TDM_CONFIG6_TDMRS (0xf<<8)
+#define TFA98XX_TDM_CONFIG6_TDMRS_POS 8
+#define TFA98XX_TDM_CONFIG6_TDMRS_LEN 4
+#define TFA98XX_TDM_CONFIG6_TDMRS_MAX 15
+#define TFA98XX_TDM_CONFIG6_TDMRS_MSK 0xf00
+
+
+/*
+ * (0x27)-tdm_config7
+ */
+
+/*
+ * tdm_source1_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMVSRS (0xf<<0)
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_POS 0
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_MSK 0xf
+
+/*
+ * tdm_source2_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMCSRS (0xf<<4)
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_POS 4
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_MSK 0xf0
+
+/*
+ * tdm_source3_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMVSLS (0xf<<8)
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_POS 8
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_MSK 0xf00
+
+/*
+ * tdm_source4_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMCSLS (0xf<<12)
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_POS 12
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_MSK 0xf000
+
+
+/*
+ * (0x28)-tdm_config8
+ */
+
+/*
+ * tdm_source5_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCFRS (0xf<<0)
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_POS 0
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_MSK 0xf
+
+/*
+ * tdm_source6_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCFLS (0xf<<4)
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_POS 4
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_MSK 0xf0
+
+/*
+ * tdm_source7_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCF3S (0xf<<8)
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_POS 8
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_MSK 0xf00
+
+/*
+ * tdm_source8_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCF4S (0xf<<12)
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_POS 12
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_MSK 0xf000
+
+
+/*
+ * (0x29)-tdm_config9
+ */
+
+/*
+ * tdm_source9_slot
+ */
+#define TFA98XX_TDM_CONFIG9_TDMPD1S (0xf<<0)
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_POS 0
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_LEN 4
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_MAX 15
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_MSK 0xf
+
+/*
+ * tdm_source10_slot
+ */
+#define TFA98XX_TDM_CONFIG9_TDMPD2S (0xf<<4)
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_POS 4
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_LEN 4
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_MAX 15
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_MSK 0xf0
+
+
+/*
+ * (0x31)-pdm_config0
+ */
+
+/*
+ * pdm_mode
+ */
+#define TFA98XX_PDM_CONFIG0_PDMSM (0x1<<0)
+#define TFA98XX_PDM_CONFIG0_PDMSM_POS 0
+#define TFA98XX_PDM_CONFIG0_PDMSM_LEN 1
+#define TFA98XX_PDM_CONFIG0_PDMSM_MAX 1
+#define TFA98XX_PDM_CONFIG0_PDMSM_MSK 0x1
+
+/*
+ * pdm_side_tone_sel
+ */
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL (0x3<<1)
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_POS 1
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_LEN 2
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_MAX 3
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_MSK 0x6
+
+/*
+ * pdm_left_sel
+ */
+#define TFA98XX_PDM_CONFIG0_PDMLSEL (0x1<<3)
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_POS 3
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_LEN 1
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_MAX 1
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_MSK 0x8
+
+/*
+ * pdm_right_sel
+ */
+#define TFA98XX_PDM_CONFIG0_PDMRSEL (0x1<<4)
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_POS 4
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_LEN 1
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_MAX 1
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_MSK 0x10
+
+/*
+ * enbl_micvdd
+ */
+#define TFA98XX_PDM_CONFIG0_MICVDDE (0x1<<5)
+#define TFA98XX_PDM_CONFIG0_MICVDDE_POS 5
+#define TFA98XX_PDM_CONFIG0_MICVDDE_LEN 1
+#define TFA98XX_PDM_CONFIG0_MICVDDE_MAX 1
+#define TFA98XX_PDM_CONFIG0_MICVDDE_MSK 0x20
+
+
+/*
+ * (0x32)-pdm_config1
+ */
+
+/*
+ * pdm_nbck
+ */
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT (0x3<<0)
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_POS 0
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_LEN 2
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_MAX 3
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_MSK 0x3
+
+/*
+ * pdm_gain
+ */
+#define TFA98XX_PDM_CONFIG1_PDMGAIN (0xf<<2)
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_POS 2
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_LEN 4
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_MAX 15
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_MSK 0x3c
+
+/*
+ * sel_pdm_out_data
+ */
+#define TFA98XX_PDM_CONFIG1_PDMOSEL (0xf<<6)
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_POS 6
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_LEN 4
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_MAX 15
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_MSK 0x3c0
+
+/*
+ * sel_cf_haptic_data
+ */
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD (0x1<<10)
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_POS 10
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_LEN 1
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_MAX 1
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_MSK 0x400
+
+
+/*
+ * (0x33)-haptic_driver_config
+ */
+
+/*
+ * haptic_duration
+ */
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME (0xff<<0)
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_POS 0
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_LEN 8
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_MAX 255
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_MSK 0xff
+
+/*
+ * haptic_data
+ */
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL (0xff<<8)
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_POS 8
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_LEN 8
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_MAX 255
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_MSK 0xff00
+
+
+/*
+ * (0x34)-gpio_datain_reg
+ */
+
+/*
+ * gpio_datain
+ */
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN (0xf<<0)
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_POS 0
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_LEN 4
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_MAX 15
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_MSK 0xf
+
+
+/*
+ * (0x35)-gpio_config
+ */
+
+/*
+ * gpio_ctrl
+ */
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL (0x1<<0)
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_POS 0
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_LEN 1
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_MAX 1
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_MSK 0x1
+
+/*
+ * gpio_dir
+ */
+#define TFA98XX_GPIO_CONFIG_GPIOCONF (0xf<<1)
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_POS 1
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_LEN 4
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_MAX 15
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_MSK 0x1e
+
+/*
+ * gpio_dataout
+ */
+#define TFA98XX_GPIO_CONFIG_GPIODOUT (0xf<<5)
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_POS 5
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_LEN 4
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_MAX 15
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_MSK 0x1e0
+
+
+/*
+ * (0x40)-interrupt_out_reg1
+ */
+
+/*
+ * int_out_flag_por
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS (0x1<<0)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_POS 0
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_MSK 0x1
+
+/*
+ * int_out_flag_pll_lock
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS (0x1<<1)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_POS 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_MSK 0x2
+
+/*
+ * int_out_flag_otpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS (0x1<<2)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_POS 2
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_MSK 0x4
+
+/*
+ * int_out_flag_ovpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS (0x1<<3)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_POS 3
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_MSK 0x8
+
+/*
+ * int_out_flag_uvpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS (0x1<<4)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_POS 4
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_MSK 0x10
+
+/*
+ * int_out_flag_clocks_stable
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS (0x1<<5)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_POS 5
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_MSK 0x20
+
+/*
+ * int_out_flag_mtp_busy
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB (0x1<<6)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_POS 6
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_MSK 0x40
+
+/*
+ * int_out_flag_lost_clk
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK (0x1<<7)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_POS 7
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_MSK 0x80
+
+/*
+ * int_out_flag_cf_speakererror
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS (0x1<<8)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_POS 8
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_MSK 0x100
+
+/*
+ * int_out_flag_cold_started
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS (0x1<<9)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_POS 9
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_MSK 0x200
+
+/*
+ * int_out_flag_engage
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS (0x1<<10)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_POS 10
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_MSK 0x400
+
+/*
+ * int_out_flag_watchdog_reset
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS (0x1<<11)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_POS 11
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_MSK 0x800
+
+/*
+ * int_out_flag_enbl_amp
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS (0x1<<12)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_POS 12
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_MSK 0x1000
+
+/*
+ * int_out_flag_enbl_ref
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS (0x1<<13)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_POS 13
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_MSK 0x2000
+
+/*
+ * int_out_flag_adc10_ready
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR (0x1<<14)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_POS 14
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_MSK 0x4000
+
+/*
+ * int_out_flag_bod_vddd_nok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK (0x1<<15)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_POS 15
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_MSK 0x8000
+
+
+/*
+ * (0x41)-interrupt_out_reg2
+ */
+
+/*
+ * int_out_flag_bst_bstcur
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU (0x1<<0)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_POS 0
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_MSK 0x1
+
+/*
+ * int_out_flag_bst_hiz
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI (0x1<<1)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_POS 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_MSK 0x2
+
+/*
+ * int_out_flag_bst_ocpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC (0x1<<2)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_POS 2
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_MSK 0x4
+
+/*
+ * int_out_flag_bst_peakcur
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR (0x1<<3)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_POS 3
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_MSK 0x8
+
+/*
+ * int_out_flag_bst_voutcomp
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC (0x1<<4)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_POS 4
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_MSK 0x10
+
+/*
+ * int_out_flag_bst_voutcomp86
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86 (0x1<<5)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_POS 5
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_MSK 0x20
+
+/*
+ * int_out_flag_bst_voutcomp93
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93 (0x1<<6)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_POS 6
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_MSK 0x40
+
+/*
+ * int_out_flag_rcvldop_ready
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD (0x1<<7)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_POS 7
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_MSK 0x80
+
+/*
+ * int_out_flag_ocp_alarm_left
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL (0x1<<8)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_POS 8
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_MSK 0x100
+
+/*
+ * int_out_flag_ocp_alarm_right
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR (0x1<<9)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_POS 9
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_MSK 0x200
+
+/*
+ * int_out_flag_man_wait_src_settings
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC (0x1<<10)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_POS 10
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_MSK 0x400
+
+/*
+ * int_out_flag_man_wait_cf_config
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC (0x1<<11)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_POS 11
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_MSK 0x800
+
+/*
+ * int_out_flag_man_start_mute_audio
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU (0x1<<12)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_POS 12
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_MSK 0x1000
+
+/*
+ * int_out_flag_cfma_err
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER (0x1<<13)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_POS 13
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_MSK 0x2000
+
+/*
+ * int_out_flag_cfma_ack
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC (0x1<<14)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_POS 14
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_MSK 0x4000
+
+/*
+ * int_out_flag_clk_out_of_range
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR (0x1<<15)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_POS 15
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_MSK 0x8000
+
+
+/*
+ * (0x42)-interrupt_out_reg3
+ */
+
+/*
+ * int_out_flag_tdm_error
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER (0x1<<0)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_POS 0
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_MSK 0x1
+
+/*
+ * int_out_flag_clip_left
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL (0x1<<1)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_POS 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_MSK 0x2
+
+/*
+ * int_out_flag_clip_right
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR (0x1<<2)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_POS 2
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_MSK 0x4
+
+/*
+ * int_out_flag_mic_ocpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM (0x1<<3)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_POS 3
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_MSK 0x8
+
+
+/*
+ * (0x44)-interrupt_in_reg1
+ */
+
+/*
+ * int_in_flag_por
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS (0x1<<0)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_POS 0
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_MSK 0x1
+
+/*
+ * int_in_flag_pll_lock
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS (0x1<<1)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_POS 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_MSK 0x2
+
+/*
+ * int_in_flag_otpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS (0x1<<2)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_POS 2
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_MSK 0x4
+
+/*
+ * int_in_flag_ovpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS (0x1<<3)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_POS 3
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_MSK 0x8
+
+/*
+ * int_in_flag_uvpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS (0x1<<4)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_POS 4
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_MSK 0x10
+
+/*
+ * int_in_flag_clocks_stable
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS (0x1<<5)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_POS 5
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_MSK 0x20
+
+/*
+ * int_in_flag_mtp_busy
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB (0x1<<6)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_POS 6
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_MSK 0x40
+
+/*
+ * int_in_flag_lost_clk
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK (0x1<<7)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_POS 7
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_MSK 0x80
+
+/*
+ * int_in_flag_cf_speakererror
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS (0x1<<8)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_POS 8
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_MSK 0x100
+
+/*
+ * int_in_flag_cold_started
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS (0x1<<9)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_POS 9
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_MSK 0x200
+
+/*
+ * int_in_flag_engage
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS (0x1<<10)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_POS 10
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_MSK 0x400
+
+/*
+ * int_in_flag_watchdog_reset
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS (0x1<<11)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_POS 11
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_MSK 0x800
+
+/*
+ * int_in_flag_enbl_amp
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS (0x1<<12)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_POS 12
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_MSK 0x1000
+
+/*
+ * int_in_flag_enbl_ref
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS (0x1<<13)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_POS 13
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_MSK 0x2000
+
+/*
+ * int_in_flag_adc10_ready
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR (0x1<<14)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_POS 14
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_MSK 0x4000
+
+/*
+ * int_in_flag_bod_vddd_nok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK (0x1<<15)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_POS 15
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_MSK 0x8000
+
+
+/*
+ * (0x45)-interrupt_in_reg2
+ */
+
+/*
+ * int_in_flag_bst_bstcur
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU (0x1<<0)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_POS 0
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_MSK 0x1
+
+/*
+ * int_in_flag_bst_hiz
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI (0x1<<1)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_POS 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_MSK 0x2
+
+/*
+ * int_in_flag_bst_ocpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC (0x1<<2)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_POS 2
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_MSK 0x4
+
+/*
+ * int_in_flag_bst_peakcur
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC (0x1<<3)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_POS 3
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_MSK 0x8
+
+/*
+ * int_in_flag_bst_voutcomp
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC (0x1<<4)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_POS 4
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_MSK 0x10
+
+/*
+ * int_in_flag_bst_voutcomp86
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86 (0x1<<5)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_POS 5
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_MSK 0x20
+
+/*
+ * int_in_flag_bst_voutcomp93
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93 (0x1<<6)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_POS 6
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_MSK 0x40
+
+/*
+ * int_in_flag_rcvldop_ready
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD (0x1<<7)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_POS 7
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_MSK 0x80
+
+/*
+ * int_in_flag_ocp_alarm_left
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL (0x1<<8)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_POS 8
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_MSK 0x100
+
+/*
+ * int_in_flag_ocp_alarm_right
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR (0x1<<9)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_POS 9
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_MSK 0x200
+
+/*
+ * int_in_flag_man_wait_src_settings
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC (0x1<<10)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_POS 10
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_MSK 0x400
+
+/*
+ * int_in_flag_man_wait_cf_config
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC (0x1<<11)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_POS 11
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_MSK 0x800
+
+/*
+ * int_in_flag_man_start_mute_audio
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU (0x1<<12)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_POS 12
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_MSK 0x1000
+
+/*
+ * int_in_flag_cfma_err
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER (0x1<<13)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_POS 13
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_MSK 0x2000
+
+/*
+ * int_in_flag_cfma_ack
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC (0x1<<14)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_POS 14
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_MSK 0x4000
+
+/*
+ * int_in_flag_clk_out_of_range
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR (0x1<<15)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_POS 15
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_MSK 0x8000
+
+
+/*
+ * (0x46)-interrupt_in_reg3
+ */
+
+/*
+ * int_in_flag_tdm_error
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER (0x1<<0)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_POS 0
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_MSK 0x1
+
+/*
+ * int_in_flag_clip_left
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL (0x1<<1)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_POS 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_MSK 0x2
+
+/*
+ * int_in_flag_clip_right
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR (0x1<<2)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_POS 2
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_MSK 0x4
+
+/*
+ * int_in_flag_mic_ocpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM (0x1<<3)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_POS 3
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_MSK 0x8
+
+
+/*
+ * (0x48)-interrupt_enable_reg1
+ */
+
+/*
+ * int_enable_flag_por
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS (0x1<<0)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_POS 0
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_MSK 0x1
+
+/*
+ * int_enable_flag_pll_lock
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS (0x1<<1)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_POS 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_MSK 0x2
+
+/*
+ * int_enable_flag_otpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS (0x1<<2)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_POS 2
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_MSK 0x4
+
+/*
+ * int_enable_flag_ovpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS (0x1<<3)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_POS 3
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_MSK 0x8
+
+/*
+ * int_enable_flag_uvpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS (0x1<<4)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_POS 4
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_MSK 0x10
+
+/*
+ * int_enable_flag_clocks_stable
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS (0x1<<5)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_POS 5
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_MSK 0x20
+
+/*
+ * int_enable_flag_mtp_busy
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB (0x1<<6)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_POS 6
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_MSK 0x40
+
+/*
+ * int_enable_flag_lost_clk
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK (0x1<<7)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_POS 7
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_MSK 0x80
+
+/*
+ * int_enable_flag_cf_speakererror
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS (0x1<<8)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_POS 8
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_MSK 0x100
+
+/*
+ * int_enable_flag_cold_started
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS (0x1<<9)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_POS 9
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_MSK 0x200
+
+/*
+ * int_enable_flag_engage
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS (0x1<<10)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_POS 10
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_MSK 0x400
+
+/*
+ * int_enable_flag_watchdog_reset
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS (0x1<<11)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_POS 11
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_MSK 0x800
+
+/*
+ * int_enable_flag_enbl_amp
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS (0x1<<12)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_POS 12
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_MSK 0x1000
+
+/*
+ * int_enable_flag_enbl_ref
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS (0x1<<13)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_POS 13
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_MSK 0x2000
+
+/*
+ * int_enable_flag_adc10_ready
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR (0x1<<14)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_POS 14
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_MSK 0x4000
+
+/*
+ * int_enable_flag_bod_vddd_nok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK (0x1<<15)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_POS 15
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_MSK 0x8000
+
+
+/*
+ * (0x49)-interrupt_enable_reg2
+ */
+
+/*
+ * int_enable_flag_bst_bstcur
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU (0x1<<0)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_POS 0
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_MSK 0x1
+
+/*
+ * int_enable_flag_bst_hiz
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI (0x1<<1)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_POS 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_MSK 0x2
+
+/*
+ * int_enable_flag_bst_ocpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC (0x1<<2)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_POS 2
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_MSK 0x4
+
+/*
+ * int_enable_flag_bst_peakcur
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC (0x1<<3)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_POS 3
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_MSK 0x8
+
+/*
+ * int_enable_flag_bst_voutcomp
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC (0x1<<4)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_POS 4
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_MSK 0x10
+
+/*
+ * int_enable_flag_bst_voutcomp86
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86 (0x1<<5)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_POS 5
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_MSK 0x20
+
+/*
+ * int_enable_flag_bst_voutcomp93
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93 (0x1<<6)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_POS 6
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_MSK 0x40
+
+/*
+ * int_enable_flag_rcvldop_ready
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD (0x1<<7)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_POS 7
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_MSK 0x80
+
+/*
+ * int_enable_flag_ocp_alarm_left
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL (0x1<<8)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_POS 8
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_MSK 0x100
+
+/*
+ * int_enable_flag_ocp_alarm_right
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR (0x1<<9)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_POS 9
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_MSK 0x200
+
+/*
+ * int_enable_flag_man_wait_src_settings
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC (0x1<<10)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_POS 10
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_MSK 0x400
+
+/*
+ * int_enable_flag_man_wait_cf_config
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC (0x1<<11)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_POS 11
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_MSK 0x800
+
+/*
+ * int_enable_flag_man_start_mute_audio
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU (0x1<<12)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_POS 12
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_MSK 0x1000
+
+/*
+ * int_enable_flag_cfma_err
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER (0x1<<13)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_POS 13
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_MSK 0x2000
+
+/*
+ * int_enable_flag_cfma_ack
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC (0x1<<14)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_POS 14
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_MSK 0x4000
+
+/*
+ * int_enable_flag_clk_out_of_range
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR (0x1<<15)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_POS 15
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_MSK 0x8000
+
+
+/*
+ * (0x4a)-interrupt_enable_reg3
+ */
+
+/*
+ * int_enable_flag_tdm_error
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER (0x1<<0)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_POS 0
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_MSK 0x1
+
+/*
+ * int_enable_flag_clip_left
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL (0x1<<1)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_POS 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_MSK 0x2
+
+/*
+ * int_enable_flag_clip_right
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR (0x1<<2)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_POS 2
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_MSK 0x4
+
+/*
+ * int_enable_flag_mic_ocpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1 (0x1<<3)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_POS 3
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_MSK 0x8
+
+
+/*
+ * (0x4c)-status_polarity_reg1
+ */
+
+/*
+ * int_polarity_flag_por
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS (0x1<<0)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_POS 0
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_MSK 0x1
+
+/*
+ * int_polarity_flag_pll_lock
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS (0x1<<1)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_POS 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_MSK 0x2
+
+/*
+ * int_polarity_flag_otpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS (0x1<<2)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_POS 2
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_MSK 0x4
+
+/*
+ * int_polarity_flag_ovpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS (0x1<<3)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_POS 3
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_MSK 0x8
+
+/*
+ * int_polarity_flag_uvpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS (0x1<<4)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_POS 4
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_MSK 0x10
+
+/*
+ * int_polarity_flag_clocks_stable
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS (0x1<<5)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_POS 5
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_MSK 0x20
+
+/*
+ * int_polarity_flag_mtp_busy
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB (0x1<<6)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_POS 6
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_MSK 0x40
+
+/*
+ * int_polarity_flag_lost_clk
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK (0x1<<7)
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_POS 7
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_MSK 0x80
+
+/*
+ * int_polarity_flag_cf_speakererror
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS (0x1<<8)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_POS 8
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_MSK 0x100
+
+/*
+ * int_polarity_flag_cold_started
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS (0x1<<9)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_POS 9
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_MSK 0x200
+
+/*
+ * int_polarity_flag_engage
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS (0x1<<10)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_POS 10
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_MSK 0x400
+
+/*
+ * int_polarity_flag_watchdog_reset
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS (0x1<<11)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_POS 11
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_MSK 0x800
+
+/*
+ * int_polarity_flag_enbl_amp
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS (0x1<<12)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_POS 12
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_MSK 0x1000
+
+/*
+ * int_polarity_flag_enbl_ref
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS (0x1<<13)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_POS 13
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_MSK 0x2000
+
+/*
+ * int_polarity_flag_adc10_ready
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR (0x1<<14)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_POS 14
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_MSK 0x4000
+
+/*
+ * int_polarity_flag_bod_vddd_nok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK (0x1<<15)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_POS 15
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_MSK 0x8000
+
+
+/*
+ * (0x4d)-status_polarity_reg2
+ */
+
+/*
+ * int_polarity_flag_bst_bstcur
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU (0x1<<0)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_POS 0
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_MSK 0x1
+
+/*
+ * int_polarity_flag_bst_hiz
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI (0x1<<1)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_POS 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_MSK 0x2
+
+/*
+ * int_polarity_flag_bst_ocpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC (0x1<<2)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_POS 2
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_MSK 0x4
+
+/*
+ * int_polarity_flag_bst_peakcur
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC (0x1<<3)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_POS 3
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_MSK 0x8
+
+/*
+ * int_polarity_flag_bst_voutcomp
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC (0x1<<4)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_POS 4
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_MSK 0x10
+
+/*
+ * int_polarity_flag_bst_voutcomp86
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86 (0x1<<5)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_POS 5
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_MSK 0x20
+
+/*
+ * int_polarity_flag_bst_voutcomp93
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93 (0x1<<6)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_POS 6
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_MSK 0x40
+
+/*
+ * int_polarity_flag_rcvldop_ready
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD (0x1<<7)
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_POS 7
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_MSK 0x80
+
+/*
+ * int_polarity_flag_ocp_alarm_left
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL (0x1<<8)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_POS 8
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_MSK 0x100
+
+/*
+ * int_polarity_flag_ocp_alarm_right
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR (0x1<<9)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_POS 9
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_MSK 0x200
+
+/*
+ * int_polarity_flag_man_wait_src_settings
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC (0x1<<10)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_POS 10
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_MSK 0x400
+
+/*
+ * int_polarity_flag_man_wait_cf_config
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC (0x1<<11)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_POS 11
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_MSK 0x800
+
+/*
+ * int_polarity_flag_man_start_mute_audio
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU (0x1<<12)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_POS 12
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_MSK 0x1000
+
+/*
+ * int_polarity_flag_cfma_err
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER (0x1<<13)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_POS 13
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_MSK 0x2000
+
+/*
+ * int_polarity_flag_cfma_ack
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC (0x1<<14)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_POS 14
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_MSK 0x4000
+
+/*
+ * int_polarity_flag_clk_out_of_range
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR (0x1<<15)
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_POS 15
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_MSK 0x8000
+
+
+/*
+ * (0x4e)-status_polarity_reg3
+ */
+
+/*
+ * int_polarity_flag_tdm_error
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER (0x1<<0)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_POS 0
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_MSK 0x1
+
+/*
+ * int_polarity_flag_clip_left
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL (0x1<<1)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_POS 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_MSK 0x2
+
+/*
+ * int_polarity_flag_clip_right
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR (0x1<<2)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_POS 2
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_MSK 0x4
+
+/*
+ * int_polarity_flag_mic_ocpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM (0x1<<3)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_POS 3
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_MSK 0x8
+
+
+/*
+ * (0x50)-bat_prot_config
+ */
+
+/*
+ * vbat_prot_attack_time
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR (0x3<<0)
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_POS 0
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_LEN 2
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_MAX 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_MSK 0x3
+
+/*
+ * vbat_prot_thlevel
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSST (0xf<<2)
+#define TFA98XX_BAT_PROT_CONFIG_BSST_POS 2
+#define TFA98XX_BAT_PROT_CONFIG_BSST_LEN 4
+#define TFA98XX_BAT_PROT_CONFIG_BSST_MAX 15
+#define TFA98XX_BAT_PROT_CONFIG_BSST_MSK 0x3c
+
+/*
+ * vbat_prot_max_reduct
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL (0x3<<6)
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_POS 6
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_LEN 2
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_MAX 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_MSK 0xc0
+
+/*
+ * vbat_prot_release_time
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR (0x7<<8)
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_POS 8
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_LEN 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_MAX 7
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_MSK 0x700
+
+/*
+ * vbat_prot_hysterese
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY (0x3<<11)
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_POS 11
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_LEN 2
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_MAX 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_MSK 0x1800
+
+/*
+ * sel_vbat
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSR (0x1<<14)
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_POS 14
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_LEN 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_MAX 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_MSK 0x4000
+
+/*
+ * bypass_clipper
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY (0x1<<15)
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_POS 15
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_LEN 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_MAX 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_MSK 0x8000
+
+
+/*
+ * (0x51)-audio_control
+ */
+
+/*
+ * batsense_steepness
+ */
+#define TFA98XX_AUDIO_CONTROL_BSSS (0x1<<0)
+#define TFA98XX_AUDIO_CONTROL_BSSS_POS 0
+#define TFA98XX_AUDIO_CONTROL_BSSS_LEN 1
+#define TFA98XX_AUDIO_CONTROL_BSSS_MAX 1
+#define TFA98XX_AUDIO_CONTROL_BSSS_MSK 0x1
+
+/*
+ * soft_mute
+ */
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE (0x1<<1)
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_POS 1
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_LEN 1
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_MAX 1
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_MSK 0x2
+
+/*
+ * cf_mute_left
+ */
+#define TFA98XX_AUDIO_CONTROL_CFSML (0x1<<2)
+#define TFA98XX_AUDIO_CONTROL_CFSML_POS 2
+#define TFA98XX_AUDIO_CONTROL_CFSML_LEN 1
+#define TFA98XX_AUDIO_CONTROL_CFSML_MAX 1
+#define TFA98XX_AUDIO_CONTROL_CFSML_MSK 0x4
+
+/*
+ * cf_mute_right
+ */
+#define TFA98XX_AUDIO_CONTROL_CFSMR (0x1<<3)
+#define TFA98XX_AUDIO_CONTROL_CFSMR_POS 3
+#define TFA98XX_AUDIO_CONTROL_CFSMR_LEN 1
+#define TFA98XX_AUDIO_CONTROL_CFSMR_MAX 1
+#define TFA98XX_AUDIO_CONTROL_CFSMR_MSK 0x8
+
+/*
+ * bypass_hp_left
+ */
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL (0x1<<4)
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_POS 4
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_LEN 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_MAX 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_MSK 0x10
+
+/*
+ * bypass_hp_right
+ */
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR (0x1<<5)
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_POS 5
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_LEN 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_MAX 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_MSK 0x20
+
+/*
+ * enbl_dpsa_left
+ */
+#define TFA98XX_AUDIO_CONTROL_DPSAL (0x1<<6)
+#define TFA98XX_AUDIO_CONTROL_DPSAL_POS 6
+#define TFA98XX_AUDIO_CONTROL_DPSAL_LEN 1
+#define TFA98XX_AUDIO_CONTROL_DPSAL_MAX 1
+#define TFA98XX_AUDIO_CONTROL_DPSAL_MSK 0x40
+
+/*
+ * enbl_dpsa_right
+ */
+#define TFA98XX_AUDIO_CONTROL_DPSAR (0x1<<7)
+#define TFA98XX_AUDIO_CONTROL_DPSAR_POS 7
+#define TFA98XX_AUDIO_CONTROL_DPSAR_LEN 1
+#define TFA98XX_AUDIO_CONTROL_DPSAR_MAX 1
+#define TFA98XX_AUDIO_CONTROL_DPSAR_MSK 0x80
+
+/*
+ * cf_volume
+ */
+#define TFA98XX_AUDIO_CONTROL_VOL (0xff<<8)
+#define TFA98XX_AUDIO_CONTROL_VOL_POS 8
+#define TFA98XX_AUDIO_CONTROL_VOL_LEN 8
+#define TFA98XX_AUDIO_CONTROL_VOL_MAX 255
+#define TFA98XX_AUDIO_CONTROL_VOL_MSK 0xff00
+
+
+/*
+ * (0x52)-amplifier_config
+ */
+
+/*
+ * ctrl_rcv
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV (0x1<<0)
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_POS 0
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_LEN 1
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_MAX 1
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_MSK 0x1
+
+/*
+ * ctrl_cc
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL (0x7<<2)
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_POS 2
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_LEN 3
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_MAX 7
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_MSK 0x1c
+
+/*
+ * gain
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN (0xff<<5)
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_POS 5
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_LEN 8
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_MAX 255
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_MSK 0x1fe0
+
+/*
+ * ctrl_slopectrl
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE (0x1<<13)
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_POS 13
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_LEN 1
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_MAX 1
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_MSK 0x2000
+
+/*
+ * ctrl_slope
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET (0x3<<14)
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_POS 14
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_LEN 2
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_MAX 3
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_MSK 0xc000
+
+
+/*
+ * (0x5a)-audio_control2
+ */
+
+/*
+ * cf_volume_sec
+ */
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC (0xff<<0)
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_POS 0
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_LEN 8
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_MAX 255
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_MSK 0xff
+
+/*
+ * sw_profile
+ */
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL (0xff<<8)
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_POS 8
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_LEN 8
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_MAX 255
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_MSK 0xff00
+
+
+/*
+ * (0x70)-dcdc_control0
+ */
+
+/*
+ * boost_volt
+ */
+#define TFA98XX_DCDC_CONTROL0_DCVO (0x7<<0)
+#define TFA98XX_DCDC_CONTROL0_DCVO_POS 0
+#define TFA98XX_DCDC_CONTROL0_DCVO_LEN 3
+#define TFA98XX_DCDC_CONTROL0_DCVO_MAX 7
+#define TFA98XX_DCDC_CONTROL0_DCVO_MSK 0x7
+
+/*
+ * boost_cur
+ */
+#define TFA98XX_DCDC_CONTROL0_DCMCC (0xf<<3)
+#define TFA98XX_DCDC_CONTROL0_DCMCC_POS 3
+#define TFA98XX_DCDC_CONTROL0_DCMCC_LEN 4
+#define TFA98XX_DCDC_CONTROL0_DCMCC_MAX 15
+#define TFA98XX_DCDC_CONTROL0_DCMCC_MSK 0x78
+
+/*
+ * bst_coil_value
+ */
+#define TFA98XX_DCDC_CONTROL0_DCCV (0x3<<7)
+#define TFA98XX_DCDC_CONTROL0_DCCV_POS 7
+#define TFA98XX_DCDC_CONTROL0_DCCV_LEN 2
+#define TFA98XX_DCDC_CONTROL0_DCCV_MAX 3
+#define TFA98XX_DCDC_CONTROL0_DCCV_MSK 0x180
+
+/*
+ * boost_intel
+ */
+#define TFA98XX_DCDC_CONTROL0_DCIE (0x1<<9)
+#define TFA98XX_DCDC_CONTROL0_DCIE_POS 9
+#define TFA98XX_DCDC_CONTROL0_DCIE_LEN 1
+#define TFA98XX_DCDC_CONTROL0_DCIE_MAX 1
+#define TFA98XX_DCDC_CONTROL0_DCIE_MSK 0x200
+
+/*
+ * boost_speed
+ */
+#define TFA98XX_DCDC_CONTROL0_DCSR (0x1<<10)
+#define TFA98XX_DCDC_CONTROL0_DCSR_POS 10
+#define TFA98XX_DCDC_CONTROL0_DCSR_LEN 1
+#define TFA98XX_DCDC_CONTROL0_DCSR_MAX 1
+#define TFA98XX_DCDC_CONTROL0_DCSR_MSK 0x400
+
+/*
+ * dcdc_synchronisation
+ */
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP (0x7<<11)
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_POS 11
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_LEN 3
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_MAX 7
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_MSK 0x3800
+
+/*
+ * dcdcoff_mode
+ */
+#define TFA98XX_DCDC_CONTROL0_DCDIS (0x1<<14)
+#define TFA98XX_DCDC_CONTROL0_DCDIS_POS 14
+#define TFA98XX_DCDC_CONTROL0_DCDIS_LEN 1
+#define TFA98XX_DCDC_CONTROL0_DCDIS_MAX 1
+#define TFA98XX_DCDC_CONTROL0_DCDIS_MSK 0x4000
+
+
+/*
+ * (0x90)-cf_controls
+ */
+
+/*
+ * cf_rst_dsp
+ */
+#define TFA98XX_CF_CONTROLS_RST (0x1<<0)
+#define TFA98XX_CF_CONTROLS_RST_POS 0
+#define TFA98XX_CF_CONTROLS_RST_LEN 1
+#define TFA98XX_CF_CONTROLS_RST_MAX 1
+#define TFA98XX_CF_CONTROLS_RST_MSK 0x1
+
+/*
+ * cf_dmem
+ */
+#define TFA98XX_CF_CONTROLS_DMEM (0x3<<1)
+#define TFA98XX_CF_CONTROLS_DMEM_POS 1
+#define TFA98XX_CF_CONTROLS_DMEM_LEN 2
+#define TFA98XX_CF_CONTROLS_DMEM_MAX 3
+#define TFA98XX_CF_CONTROLS_DMEM_MSK 0x6
+
+/*
+ * cf_aif
+ */
+#define TFA98XX_CF_CONTROLS_AIF (0x1<<3)
+#define TFA98XX_CF_CONTROLS_AIF_POS 3
+#define TFA98XX_CF_CONTROLS_AIF_LEN 1
+#define TFA98XX_CF_CONTROLS_AIF_MAX 1
+#define TFA98XX_CF_CONTROLS_AIF_MSK 0x8
+
+/*
+ * cf_int
+ */
+#define TFA98XX_CF_CONTROLS_CFINT (0x1<<4)
+#define TFA98XX_CF_CONTROLS_CFINT_POS 4
+#define TFA98XX_CF_CONTROLS_CFINT_LEN 1
+#define TFA98XX_CF_CONTROLS_CFINT_MAX 1
+#define TFA98XX_CF_CONTROLS_CFINT_MSK 0x10
+
+/*
+ * cf_cgate_off
+ */
+#define TFA98XX_CF_CONTROLS_CFCGATE (0x1<<5)
+#define TFA98XX_CF_CONTROLS_CFCGATE_POS 5
+#define TFA98XX_CF_CONTROLS_CFCGATE_LEN 1
+#define TFA98XX_CF_CONTROLS_CFCGATE_MAX 1
+#define TFA98XX_CF_CONTROLS_CFCGATE_MSK 0x20
+
+/*
+ * cf_req_cmd
+ */
+#define TFA98XX_CF_CONTROLS_REQCMD (0x1<<8)
+#define TFA98XX_CF_CONTROLS_REQCMD_POS 8
+#define TFA98XX_CF_CONTROLS_REQCMD_LEN 1
+#define TFA98XX_CF_CONTROLS_REQCMD_MAX 1
+#define TFA98XX_CF_CONTROLS_REQCMD_MSK 0x100
+
+/*
+ * cf_req_reset
+ */
+#define TFA98XX_CF_CONTROLS_REQRST (0x1<<9)
+#define TFA98XX_CF_CONTROLS_REQRST_POS 9
+#define TFA98XX_CF_CONTROLS_REQRST_LEN 1
+#define TFA98XX_CF_CONTROLS_REQRST_MAX 1
+#define TFA98XX_CF_CONTROLS_REQRST_MSK 0x200
+
+/*
+ * cf_req_mips
+ */
+#define TFA98XX_CF_CONTROLS_REQMIPS (0x1<<10)
+#define TFA98XX_CF_CONTROLS_REQMIPS_POS 10
+#define TFA98XX_CF_CONTROLS_REQMIPS_LEN 1
+#define TFA98XX_CF_CONTROLS_REQMIPS_MAX 1
+#define TFA98XX_CF_CONTROLS_REQMIPS_MSK 0x400
+
+/*
+ * cf_req_mute_ready
+ */
+#define TFA98XX_CF_CONTROLS_REQMUTED (0x1<<11)
+#define TFA98XX_CF_CONTROLS_REQMUTED_POS 11
+#define TFA98XX_CF_CONTROLS_REQMUTED_LEN 1
+#define TFA98XX_CF_CONTROLS_REQMUTED_MAX 1
+#define TFA98XX_CF_CONTROLS_REQMUTED_MSK 0x800
+
+/*
+ * cf_req_volume_ready
+ */
+#define TFA98XX_CF_CONTROLS_REQVOL (0x1<<12)
+#define TFA98XX_CF_CONTROLS_REQVOL_POS 12
+#define TFA98XX_CF_CONTROLS_REQVOL_LEN 1
+#define TFA98XX_CF_CONTROLS_REQVOL_MAX 1
+#define TFA98XX_CF_CONTROLS_REQVOL_MSK 0x1000
+
+/*
+ * cf_req_damage
+ */
+#define TFA98XX_CF_CONTROLS_REQDMG (0x1<<13)
+#define TFA98XX_CF_CONTROLS_REQDMG_POS 13
+#define TFA98XX_CF_CONTROLS_REQDMG_LEN 1
+#define TFA98XX_CF_CONTROLS_REQDMG_MAX 1
+#define TFA98XX_CF_CONTROLS_REQDMG_MSK 0x2000
+
+/*
+ * cf_req_calibrate_ready
+ */
+#define TFA98XX_CF_CONTROLS_REQCAL (0x1<<14)
+#define TFA98XX_CF_CONTROLS_REQCAL_POS 14
+#define TFA98XX_CF_CONTROLS_REQCAL_LEN 1
+#define TFA98XX_CF_CONTROLS_REQCAL_MAX 1
+#define TFA98XX_CF_CONTROLS_REQCAL_MSK 0x4000
+
+/*
+ * cf_req_reserved
+ */
+#define TFA98XX_CF_CONTROLS_REQRSV (0x1<<15)
+#define TFA98XX_CF_CONTROLS_REQRSV_POS 15
+#define TFA98XX_CF_CONTROLS_REQRSV_LEN 1
+#define TFA98XX_CF_CONTROLS_REQRSV_MAX 1
+#define TFA98XX_CF_CONTROLS_REQRSV_MSK 0x8000
+
+
+/*
+ * (0x91)-cf_mad
+ */
+
+/*
+ * cf_madd
+ */
+#define TFA98XX_CF_MAD_MADD (0xffff<<0)
+#define TFA98XX_CF_MAD_MADD_POS 0
+#define TFA98XX_CF_MAD_MADD_LEN 16
+#define TFA98XX_CF_MAD_MADD_MAX 65535
+#define TFA98XX_CF_MAD_MADD_MSK 0xffff
+
+
+/*
+ * (0x92)-cf_mem
+ */
+
+/*
+ * cf_mema
+ */
+#define TFA98XX_CF_MEM_MEMA (0xffff<<0)
+#define TFA98XX_CF_MEM_MEMA_POS 0
+#define TFA98XX_CF_MEM_MEMA_LEN 16
+#define TFA98XX_CF_MEM_MEMA_MAX 65535
+#define TFA98XX_CF_MEM_MEMA_MSK 0xffff
+
+
+/*
+ * (0x93)-cf_status
+ */
+
+/*
+ * cf_err
+ */
+#define TFA98XX_CF_STATUS_ERR (0xff<<0)
+#define TFA98XX_CF_STATUS_ERR_POS 0
+#define TFA98XX_CF_STATUS_ERR_LEN 8
+#define TFA98XX_CF_STATUS_ERR_MAX 255
+#define TFA98XX_CF_STATUS_ERR_MSK 0xff
+
+/*
+ * cf_ack_cmd
+ */
+#define TFA98XX_CF_STATUS_ACKCMD (0x1<<8)
+#define TFA98XX_CF_STATUS_ACKCMD_POS 8
+#define TFA98XX_CF_STATUS_ACKCMD_LEN 1
+#define TFA98XX_CF_STATUS_ACKCMD_MAX 1
+#define TFA98XX_CF_STATUS_ACKCMD_MSK 0x100
+
+/*
+ * cf_ack_reset
+ */
+#define TFA98XX_CF_STATUS_ACKRST (0x1<<9)
+#define TFA98XX_CF_STATUS_ACKRST_POS 9
+#define TFA98XX_CF_STATUS_ACKRST_LEN 1
+#define TFA98XX_CF_STATUS_ACKRST_MAX 1
+#define TFA98XX_CF_STATUS_ACKRST_MSK 0x200
+
+/*
+ * cf_ack_mips
+ */
+#define TFA98XX_CF_STATUS_ACKMIPS (0x1<<10)
+#define TFA98XX_CF_STATUS_ACKMIPS_POS 10
+#define TFA98XX_CF_STATUS_ACKMIPS_LEN 1
+#define TFA98XX_CF_STATUS_ACKMIPS_MAX 1
+#define TFA98XX_CF_STATUS_ACKMIPS_MSK 0x400
+
+/*
+ * cf_ack_mute_ready
+ */
+#define TFA98XX_CF_STATUS_ACKMUTED (0x1<<11)
+#define TFA98XX_CF_STATUS_ACKMUTED_POS 11
+#define TFA98XX_CF_STATUS_ACKMUTED_LEN 1
+#define TFA98XX_CF_STATUS_ACKMUTED_MAX 1
+#define TFA98XX_CF_STATUS_ACKMUTED_MSK 0x800
+
+/*
+ * cf_ack_volume_ready
+ */
+#define TFA98XX_CF_STATUS_ACKVOL (0x1<<12)
+#define TFA98XX_CF_STATUS_ACKVOL_POS 12
+#define TFA98XX_CF_STATUS_ACKVOL_LEN 1
+#define TFA98XX_CF_STATUS_ACKVOL_MAX 1
+#define TFA98XX_CF_STATUS_ACKVOL_MSK 0x1000
+
+/*
+ * cf_ack_damage
+ */
+#define TFA98XX_CF_STATUS_ACKDMG (0x1<<13)
+#define TFA98XX_CF_STATUS_ACKDMG_POS 13
+#define TFA98XX_CF_STATUS_ACKDMG_LEN 1
+#define TFA98XX_CF_STATUS_ACKDMG_MAX 1
+#define TFA98XX_CF_STATUS_ACKDMG_MSK 0x2000
+
+/*
+ * cf_ack_calibrate_ready
+ */
+#define TFA98XX_CF_STATUS_ACKCAL (0x1<<14)
+#define TFA98XX_CF_STATUS_ACKCAL_POS 14
+#define TFA98XX_CF_STATUS_ACKCAL_LEN 1
+#define TFA98XX_CF_STATUS_ACKCAL_MAX 1
+#define TFA98XX_CF_STATUS_ACKCAL_MSK 0x4000
+
+/*
+ * cf_ack_reserved
+ */
+#define TFA98XX_CF_STATUS_ACKRSV (0x1<<15)
+#define TFA98XX_CF_STATUS_ACKRSV_POS 15
+#define TFA98XX_CF_STATUS_ACKRSV_LEN 1
+#define TFA98XX_CF_STATUS_ACKRSV_MAX 1
+#define TFA98XX_CF_STATUS_ACKRSV_MSK 0x8000
+
+
+/*
+ * (0xa1)-mtpkey2_reg
+ */
+
+/*
+ * mtpkey2
+ */
+#define TFA98XX_MTPKEY2_REG_MTPK (0xff<<0)
+#define TFA98XX_MTPKEY2_REG_MTPK_POS 0
+#define TFA98XX_MTPKEY2_REG_MTPK_LEN 8
+#define TFA98XX_MTPKEY2_REG_MTPK_MAX 255
+#define TFA98XX_MTPKEY2_REG_MTPK_MSK 0xff
+
+
+/*
+ * (0xa2)-mtp_status
+ */
+
+/*
+ * key01_locked
+ */
+#define TFA98XX_MTP_STATUS_KEY1LOCKED (0x1<<0)
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_POS 0
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_LEN 1
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_MAX 1
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_MSK 0x1
+
+/*
+ * key02_locked
+ */
+#define TFA98XX_MTP_STATUS_KEY2LOCKED (0x1<<1)
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_POS 1
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_LEN 1
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_MAX 1
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_MSK 0x2
+
+
+/*
+ * (0xa3)-KEY_protected_mtp_control
+ */
+
+/*
+ * auto_copy_iic_to_mtp
+ */
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP (0x1<<6)
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_POS 6
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_LEN 1
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_MAX 1
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_MSK 0x40
+
+
+/*
+ * (0xa5)-mtp_data_out_msb
+ */
+
+/*
+ * mtp_man_data_out_msb
+ */
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB (0xffff<<0)
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_POS 0
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_LEN 16
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_MAX 65535
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_MSK 0xffff
+
+
+/*
+ * (0xa6)-mtp_data_out_lsb
+ */
+
+/*
+ * mtp_man_data_out_lsb
+ */
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB (0xffff<<0)
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_POS 0
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_LEN 16
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_MAX 65535
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_MSK 0xffff
+
+
+/*
+ * (0xb1)-temp_sensor_config
+ */
+
+/*
+ * ext_temp
+ */
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS (0x1ff<<0)
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_POS 0
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_LEN 9
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_MAX 511
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_MSK 0x1ff
+
+/*
+ * ext_temp_sel
+ */
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS (0x1<<9)
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_POS 9
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_LEN 1
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_MAX 1
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_MSK 0x200
+
+
+/*
+ * (0xf0)-KEY2_protected_MTP0
+ */
+
+/*
+ * calibration_onetime
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC (0x1<<0)
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_POS 0
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MSK 0x1
+
+/*
+ * calibr_ron_done
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX (0x1<<1)
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_POS 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK 0x2
+
+/*
+ * calibr_dcdc_api_calibrate
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI (0x1<<2)
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_POS 2
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_MSK 0x4
+
+/*
+ * calibr_dcdc_delta_sign
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB (0x1<<3)
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_POS 3
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_MSK 0x8
+
+/*
+ * calibr_dcdc_delta
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF (0x7<<4)
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_POS 4
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_LEN 3
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_MAX 7
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_MSK 0x70
+
+
+/*
+ * (0xf4)-KEY1_protected_MTP4
+ */
+
+
+/*
+ * (0xf5)-KEY1_protected_MTP5
+ */
+
+#endif /* TFA98XX_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx_parameters.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_parameters.h
new file mode 100644
index 00000000000..4b5c7bd486a
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_parameters.h
@@ -0,0 +1,736 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*
+ * tfa98xx_parameters.h
+ *
+ * Created on: Jul 22, 2013
+ * Author: NLV02095
+ */
+
+#ifndef TFA98XXPARAMETERS_H_
+#define TFA98XXPARAMETERS_H_
+
+//#include "config.h"
+// workaround for Visual Studio:
+// fatal error C1083: Cannot open include file: 'config.h': No such file or directory
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
+#include "tfa_service.h"
+
+#if (defined(WIN32) || defined(_X64))
+/* These warnings are disabled because it is only given by Windows and there is no easy fix */
+#pragma warning(disable:4200)
+#pragma warning(disable:4214)
+#endif
+
+/*
+ * profiles & volumesteps
+ *
+ */
+#define TFA_MAX_PROFILES (64)
+#define TFA_MAX_VSTEPS (64)
+#define TFA_MAX_VSTEP_MSG_MARKER (100) /* This marker is used to indicate if all msgs need to be written to the device */
+#define TFA_MAX_MSGS (10)
+
+// the pack pragma is required to make that the size in memory
+// matches the actual variable lenghts
+// This is to assure that the binary files can be transported between
+// different platforms.
+#pragma pack (push, 1)
+
+/*
+ * typedef for 24 bit value using 3 bytes
+ */
+typedef struct uint24 {
+ uint8_t b[3];
+} uint24_t;
+/*
+ * the generic header
+ * all char types are in ASCII
+ */
+typedef struct TfaHeader {
+ uint16_t id;
+ char version[2]; // "V_" : V=version, vv=subversion
+ char subversion[2]; // "vv" : vv=subversion
+ uint16_t size; // data size in bytes following CRC
+ uint32_t CRC; // 32-bits CRC for following data
+ char customer[8]; // “name of customer”
+ char application[8]; // “application name”
+ char type[8]; // “application type name”
+} TfaHeader_t;
+
+typedef enum TfaSamplerate {
+ fs_8k, // 8kHz
+ fs_11k025, // 11.025kHz
+ fs_12k, // 12kHz
+ fs_16k, // 16kHz
+ fs_22k05, // 22.05kHz
+ fs_24k, // 24kHz
+ fs_32k, // 32kHz
+ fs_44k1, // 44.1kHz
+ fs_48k, // 48kHz
+ fs_96k, // 96kHz
+ fs_count // Should always be last item.
+} TfaSamplerate_t;
+
+// Keep in sync with TfaSamplerate_t !
+static const int TfaSamplerateHz[fs_count] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000 };
+
+
+/*
+ * coolflux direct memory access
+ */
+typedef struct TfaDspMem {
+ uint8_t type; /* 0--3: p, x, y, iomem */
+ uint16_t address; /* target address */
+ uint8_t size; /* data size in words */
+ int words[]; /* payload in signed 32bit integer (two's complement) */
+} TfaDspMem_t;
+
+/*
+ * the biquad coefficients for the API together with index in filter
+ * the biquad_index is the actual index in the equalizer +1
+ */
+#define BIQUAD_COEFF_SIZE 6
+
+/*
+* Output fixed point coeffs structure
+*/
+typedef struct {
+ int a2;
+ int a1;
+ int b2;
+ int b1;
+ int b0;
+}TfaBiquad_t;
+
+typedef struct TfaBiquadOld {
+ uint8_t bytes[BIQUAD_COEFF_SIZE*sizeof(uint24_t)];
+}TfaBiquadOld_t;
+
+typedef struct TfaBiquadFloat {
+ float headroom;
+ float b0;
+ float b1;
+ float b2;
+ float a1;
+ float a2;
+} TfaBiquadFloat_t;
+
+/*
+* EQ filter definitions
+* Note: This is not in line with smartstudio (JV: 12/12/2016)
+*/
+typedef enum TfaFilterType {
+ fCustom, //User defined biquad coefficients
+ fFlat, //Vary only gain
+ fLowpass, //2nd order Butterworth low pass
+ fHighpass, //2nd order Butterworth high pass
+ fLowshelf,
+ fHighshelf,
+ fNotch,
+ fPeak,
+ fBandpass,
+ f1stLP,
+ f1stHP,
+ fElliptic
+} TfaFilterType_t;
+
+/*
+ * filter parameters for biquad (re-)calculation
+ */
+typedef struct TfaFilter {
+ TfaBiquadOld_t biquad;
+ uint8_t enabled;
+ uint8_t type; // (== enum FilterTypes, assure 8bits length)
+ float frequency;
+ float Q;
+ float gain;
+} TfaFilter_t ; //8 * float + int32 + byte == 37
+
+/*
+ * biquad params for calculation
+*/
+
+#define TFA_BQ_EQ_INDEX 0
+#define TFA_BQ_ANTI_ALIAS_INDEX 10
+#define TFA_BQ_INTEGRATOR_INDEX 13
+
+/*
+* Loudspeaker Compensation filter definitions
+*/
+typedef struct TfaLsCompensationFilter {
+ TfaBiquad_t biquad;
+ uint8_t lsCompOn; // Loudspeaker compensation on/off; when 'off', the DSP code doesn't apply the bwExt => bwExtOn GUI flag should be gray to avoid confusion
+ uint8_t bwExtOn; // Bandwidth extension on/off
+ float fRes; // [Hz] speaker resonance frequency
+ float Qt; // Speaker resonance Q-factor
+ float fBwExt; // [Hz] Band width extension frequency
+ float samplingFreq;// [Hz] Sampling frequency
+} TfaLsCompensationFilter_t;
+
+/*
+* Anti Aliasing Elliptic filter definitions
+*/
+typedef struct TfaAntiAliasFilter {
+ TfaBiquad_t biquad; /**< Output results fixed point coeffs */
+ uint8_t enabled;
+ float cutOffFreq; // cut off frequency
+ float samplingFreq; // sampling frequency
+ float rippleDb; // range: [0.1 3.0]
+ float rolloff; // range: [-1.0 1.0]
+} TfaAntiAliasFilter_t;
+
+/**
+* Integrator filter input definitions
+*/
+typedef struct TfaIntegratorFilter {
+ TfaBiquad_t biquad; /**< Output results fixed point coeffs */
+ uint8_t type; /**< Butterworth filter type: high or low pass */
+ float cutOffFreq; /**< cut off frequency in Hertz; range: [100.0 4000.0] */
+ float samplingFreq; /**< sampling frequency in Hertz */
+ float leakage; /**< leakage factor; range [0.0 1.0] */
+} TfaIntegratorFilter_t;
+
+
+typedef struct TfaEqFilter {
+ TfaBiquad_t biquad;
+ uint8_t enabled;
+ uint8_t type; // (== enum FilterTypes, assure 8bits length)
+ float cutOffFreq; // cut off frequency, // range: [100.0 4000.0]
+ float samplingFreq; // sampling frequency
+ float Q; // range: [0.5 5.0]
+ float gainDb; // range: [-10.0 10.0]
+} TfaEqFilter_t ; //8 * float + int32 + byte == 37
+
+typedef struct TfaContAntiAlias {
+ int8_t index; /**< index determines destination type; anti-alias, integrator,eq */
+ uint8_t type;
+ float cutOffFreq; // cut off frequency
+ float samplingFreq;
+ float rippleDb; // integrator leakage
+ float rolloff;
+ uint8_t bytes[5*3]; // payload 5*24buts coeffs
+}TfaContAntiAlias_t;
+
+typedef struct TfaContIntegrator {
+ int8_t index; /**< index determines destination type; anti-alias, integrator,eq */
+ uint8_t type;
+ float cutOffFreq; // cut off frequency
+ float samplingFreq;
+ float leakage; // integrator leakage
+ float reserved;
+ uint8_t bytes[5*3]; // payload 5*24buts coeffs
+}TfaContIntegrator_t;
+
+typedef struct TfaContEq {
+ int8_t index;
+ uint8_t type; // (== enum FilterTypes, assure 8bits length)
+ float cutOffFreq; // cut off frequency, // range: [100.0 4000.0]
+ float samplingFreq; // sampling frequency
+ float Q; // range: [0.5 5.0]
+ float gainDb; // range: [-10.0 10.0]
+ uint8_t bytes[5*3]; // payload 5*24buts coeffs
+} TfaContEq_t ; //8 * float + int32 + byte == 37
+
+typedef union TfaContBiquad {
+ TfaContEq_t eq;
+ TfaContAntiAlias_t aa;
+ TfaContIntegrator_t in;
+}TfaContBiquad_t;
+
+#define TFA_BQ_EQ_INDEX 0
+#define TFA_BQ_ANTI_ALIAS_INDEX 10
+#define TFA_BQ_INTEGRATOR_INDEX 13
+#define TFA98XX_MAX_EQ 10
+
+typedef struct TfaEqualizer {
+ TfaFilter_t filter[TFA98XX_MAX_EQ];
+} TfaEqualizer_t;
+
+/*
+ * files
+ */
+#define HDR(c1,c2) (c2<<8|c1) // little endian
+typedef enum TfaHeaderType {
+ paramsHdr = HDR('P','M'), /* containter file */
+ volstepHdr = HDR('V','P'),
+ patchHdr = HDR('P','A'),
+ speakerHdr = HDR('S','P'),
+ presetHdr = HDR('P','R'),
+ configHdr = HDR('C','O'),
+ equalizerHdr = HDR('E','Q'),
+ drcHdr = HDR('D','R'),
+ msgHdr = HDR('M','G'), /* generic message */
+ infoHdr = HDR('I','N')
+} TfaHeaderType_t;
+
+/*
+ * equalizer file
+ */
+#define TFA_EQ_VERSION '1'
+#define TFA_EQ_SUBVERSION "00"
+typedef struct TfaEqualizerFile {
+ TfaHeader_t hdr;
+ uint8_t samplerate; // ==enum samplerates, assure 8 bits
+ TfaFilter_t filter[TFA98XX_MAX_EQ];// note: API index counts from 1..10
+} TfaEqualizerFile_t;
+
+/*
+ * patch file
+ */
+#define TFA_PA_VERSION '1'
+#define TFA_PA_SUBVERSION "00"
+typedef struct TfaPatchFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaPatch_t;
+
+/*
+ * generic message file
+ * - the payload of this file includes the opcode and is send straight to the DSP
+ */
+#define TFA_MG_VERSION '3'
+#define TFA_MG_SUBVERSION "00"
+typedef struct TfaMsgFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaMsgFile_t;
+
+/*
+ * NOTE the tfa98xx API defines the enum Tfa98xx_config_type that defines
+ * the subtypes as decribes below.
+ * tfa98xx_dsp_config_parameter_type() can be used to get the
+ * supported type for the active device..
+ */
+/*
+ * config file V1 sub 1
+ */
+#define TFA_CO_VERSION '1'
+#define TFA_CO3_VERSION '3'
+#define TFA_CO_SUBVERSION1 "01"
+typedef struct TfaConfigS1File {
+ TfaHeader_t hdr;
+ uint8_t data[55*3];
+} TfaConfigS1_t;
+
+/*
+ * config file V1 sub 2
+ */
+#define TFA_CO_SUBVERSION2 "02"
+typedef struct TfaConfigS2File {
+ TfaHeader_t hdr;
+ uint8_t data[67*3];
+} TfaConfigS2_t;
+
+/*
+ * config file V1 sub 3
+ */
+#define TFA_CO_SUBVERSION3 "03"
+typedef struct TfaConfigS3File {
+ TfaHeader_t hdr;
+ uint8_t data[67*3];
+} TfaConfigS3_t;
+
+/*
+ * config file V1.0
+ */
+#define TFA_CO_SUBVERSION "00"
+typedef struct TfaConfigFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaConfig_t;
+
+/*
+ * preset file
+ */
+#define TFA_PR_VERSION '1'
+#define TFA_PR_SUBVERSION "00"
+typedef struct TfaPresetFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaPreset_t;
+
+/*
+ * drc file
+ */
+#define TFA_DR_VERSION '1'
+#define TFA_DR_SUBVERSION "00"
+typedef struct TfaDrcFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaDrc_t;
+
+/*
+ * drc file
+ * for tfa 2 there is also a xml-version
+ */
+#define TFA_DR3_VERSION '3'
+#define TFA_DR3_SUBVERSION "00"
+typedef struct TfaDrcFile2 {
+ TfaHeader_t hdr;
+ uint8_t version[3];
+ uint8_t data[];
+} TfaDrc2_t;
+
+/*
+ * volume step structures
+ */
+// VP01
+#define TFA_VP1_VERSION '1'
+#define TFA_VP1_SUBVERSION "01"
+typedef struct TfaVolumeStep1 {
+ float attenuation; // IEEE single float
+ uint8_t preset[TFA98XX_PRESET_LENGTH];
+} TfaVolumeStep1_t;
+
+// VP02
+#define TFA_VP2_VERSION '2'
+#define TFA_VP2_SUBVERSION "01"
+typedef struct TfaVolumeStep2 {
+ float attenuation; // IEEE single float
+ uint8_t preset[TFA98XX_PRESET_LENGTH];
+ TfaFilter_t filter[TFA98XX_MAX_EQ];// note: API index counts from 1..10
+} TfaVolumeStep2_t;
+
+/*
+ * volumestep file
+ */
+#define TFA_VP_VERSION '1'
+#define TFA_VP_SUBVERSION "00"
+typedef struct TfaVolumeStepFile {
+ TfaHeader_t hdr;
+ uint8_t vsteps; // can also be calulated from size+type
+ uint8_t samplerate; // ==enum samplerates, assure 8 bits
+ uint8_t payload; //start of variable length contents:N times volsteps
+}TfaVolumeStepFile_t;
+/*
+ * volumestep2 file
+ */
+typedef struct TfaVolumeStep2File {
+ TfaHeader_t hdr;
+ uint8_t vsteps; // can also be calulated from size+type
+ uint8_t samplerate; // ==enum samplerates, assure 8 bits
+ TfaVolumeStep2_t vstep[]; //start of variable length contents:N times volsteps
+}TfaVolumeStep2File_t;
+
+/*
+ * volumestepMax2 file
+ */
+typedef struct TfaVolumeStepMax2File {
+ TfaHeader_t hdr;
+ uint8_t version[3];
+ uint8_t NrOfVsteps;
+ uint8_t vstepsBin[];
+}TfaVolumeStepMax2File_t;
+
+/*
+ * volumestepMax2 file
+ * This volumestep should ONLY be used for the use of bin2hdr!
+ * This can only be used to find the messagetype of the vstep (without header)
+ */
+typedef struct TfaVolumeStepMax2_1File {
+ uint8_t version[3];
+ uint8_t NrOfVsteps;
+ uint8_t vstepsBin[];
+}TfaVolumeStepMax2_1File_t;
+
+struct TfaVolumeStepRegisterInfo {
+ uint8_t NrOfRegisters;
+ uint16_t registerInfo[];
+};
+
+struct TfaVolumeStepMessageInfo {
+ uint8_t NrOfMessages;
+ uint8_t MessageType;
+ uint24_t MessageLength;
+ uint8_t CmdId[3];
+ uint8_t ParameterData[];
+};
+/**************************old v2 *************************************************/
+
+/*
+ * subv 00 volumestep file
+ */
+typedef struct TfaOldHeader {
+ uint16_t id;
+ char version[2]; // "V_" : V=version, vv=subversion
+ char subversion[2]; // "vv" : vv=subversion
+ uint16_t size; // data size in bytes following CRC
+ uint32_t CRC; // 32-bits CRC for following data
+} TfaOldHeader_t;
+
+typedef struct TfaOldFilter {
+ double bq[5];
+ int32_t type;
+ double frequency;
+ double Q;
+ double gain;
+ uint8_t enabled;
+} TfaOldFilter_t ;
+
+typedef struct TfaOldVolumeStep2 {
+ float attenuation; // IEEE single float
+ uint8_t preset[TFA98XX_PRESET_LENGTH];
+ TfaOldFilter_t eq[10];
+} TfaOldVolumeStep2_t;
+
+typedef struct TfaOldVolumeStepFile {
+ TfaOldHeader_t hdr;
+ TfaOldVolumeStep2_t step[];
+}TfaOldVolumeStep2File_t;
+/**************************end old v2 *************************************************/
+
+/*
+ * speaker file header
+ */
+struct TfaSpkHeader {
+ struct TfaHeader hdr;
+ char name[8]; // speaker nick name (e.g. “dumbo”)
+ char vendor[16];
+ char type[8];
+ // dimensions (mm)
+ uint8_t height;
+ uint8_t width;
+ uint8_t depth;
+ uint16_t ohm;
+};
+
+/*
+ * speaker file
+ */
+#define TFA_SP_VERSION '1'
+#define TFA_SP_SUBVERSION "00"
+typedef struct TfaSpeakerFile {
+ TfaHeader_t hdr;
+ char name[8]; // speaker nick name (e.g. “dumbo”)
+ char vendor[16];
+ char type[8];
+ // dimensions (mm)
+ uint8_t height;
+ uint8_t width;
+ uint8_t depth;
+ uint8_t ohm_primary;
+ uint8_t ohm_secondary;
+ uint8_t data[]; //payload TFA98XX_SPEAKERPARAMETER_LENGTH
+} TfaSpeakerFile_t;
+
+#define TFA_VP3_VERSION '3'
+#define TFA_VP3_SUBVERSION "00"
+
+struct TfaFWVer {
+ uint8_t Major;
+ uint8_t minor;
+ uint8_t minor_update:6;
+ uint8_t Update:2;
+};
+
+struct TfaFWMsg {
+ struct TfaFWVer fwVersion;
+ struct TfaMsg payload;
+};
+
+typedef struct TfaLiveData {
+ char name[25];
+ char addrs[25];
+ int tracker;
+ int scalefactor;
+} TfaLiveData_t;
+
+#define TFA_SP3_VERSION '3'
+#define TFA_SP3_SUBVERSION "00"
+struct TfaSpeakerFileMax2 {
+ TfaHeader_t hdr;
+ char name[8]; // speaker nick name (e.g. “dumbo”)
+ char vendor[16];
+ char type[8];
+ // dimensions (mm)
+ uint8_t height;
+ uint8_t width;
+ uint8_t depth;
+ uint8_t ohm_primary;
+ uint8_t ohm_secondary;
+ struct TfaFWMsg FWmsg; //payload including FW ver and Cmd ID
+};
+
+/*
+ * parameter container file
+ */
+/*
+ * descriptors
+ * Note 1: append new DescriptorType at the end
+ * Note 2: add new descriptors to dsc_name[] in tfaContUtil.c
+ */
+typedef enum TfaDescriptorType {
+ dscDevice, // device list
+ dscProfile, // profile list
+ dscRegister, // register patch
+ dscString, // ascii, zero terminated string
+ dscFile, // filename + file contents
+ dscPatch, // patch file
+ dscMarker, // marker to indicate end of a list
+ dscMode,
+ dscSetInputSelect,
+ dscSetOutputSelect,
+ dscSetProgramConfig,
+ dscSetLagW,
+ dscSetGains,
+ dscSetvBatFactors,
+ dscSetSensesCal,
+ dscSetSensesDelay,
+ dscBitfield,
+ dscDefault, // used to reset bitfields to there default values
+ dscLiveData,
+ dscLiveDataString,
+ dscGroup,
+ dscCmd,
+ dscSetMBDrc,
+ dscFilter,
+ dscNoInit,
+ dscFeatures,
+ dscCfMem, // coolflux memory x,y,io
+ dscSetFwkUseCase,
+ dscSetVddpConfig,
+ dsc_last // trailer
+} TfaDescriptorType_t;
+
+#define TFA_BITFIELDDSCMSK 0x7fffffff
+typedef struct TfaDescPtr {
+ uint32_t offset:24;
+ uint32_t type:8; // (== enum TfaDescriptorType, assure 8bits length)
+}TfaDescPtr_t;
+
+/*
+ * generic file descriptor
+ */
+typedef struct TfaFileDsc {
+ TfaDescPtr_t name;
+ uint32_t size; // file data length in bytes
+ uint8_t data[]; //payload
+} TfaFileDsc_t;
+
+
+/*
+ * device descriptor list
+ */
+typedef struct TfaDeviceList {
+ uint8_t length; // nr of items in the list
+ uint8_t bus; // bus
+ uint8_t dev; // device
+ uint8_t func; // subfunction or subdevice
+ uint32_t devid; // device hw fw id
+ TfaDescPtr_t name; // device name
+ TfaDescPtr_t list[]; // items list
+} TfaDeviceList_t;
+
+/*
+ * profile descriptor list
+ */
+typedef struct TfaProfileList {
+ uint32_t length:8; // nr of items in the list + name
+ uint32_t group:8; // profile group number
+ uint32_t ID:16; // profile ID
+ TfaDescPtr_t name; // profile name
+ TfaDescPtr_t list[]; // items list (lenght-1 items)
+} TfaProfileList_t;
+#define TFA_PROFID 0x1234
+
+/*
+ * livedata descriptor list
+ */
+typedef struct TfaLiveDataList {
+ uint32_t length:8; // nr of items in the list
+ uint32_t ID:24; // profile ID
+ TfaDescPtr_t name; // livedata name
+ TfaDescPtr_t list[]; // items list
+} TfaLiveDataList_t;
+#define TFA_LIVEDATAID 0x5678
+
+/*
+ * Bitfield descriptor
+ */
+typedef struct TfaBitfield {
+ uint16_t value;
+ uint16_t field; // ==datasheet defined, 16 bits
+} TfaBitfield_t;
+
+/*
+ * Bitfield enumuration bits descriptor
+ */
+typedef struct TfaBfEnum {
+ unsigned int len:4; // this is the actual length-1
+ unsigned int pos:4;
+ unsigned int address:8;
+} TfaBfEnum_t;
+
+/*
+ * Register patch descriptor
+ */
+typedef struct TfaRegpatch {
+ uint8_t address; // register address
+ uint16_t value; // value to write
+ uint16_t mask; // mask of bits to write
+} TfaRegpatch_t;
+
+/*
+ * Mode descriptor
+ */
+typedef struct TfaUseCase {
+ int value; // mode value, maps to enum Tfa98xx_Mode
+} TfaMode_t;
+
+/*
+ * NoInit descriptor
+ */
+typedef struct TfaNoInit {
+ uint8_t value; // noInit value
+} TfaNoInit_t;
+
+/*
+ * Features descriptor
+ */
+typedef struct TfaFeatures {
+ uint16_t value[3]; // features value
+} TfaFeatures_t;
+
+
+/*
+ * the container file
+ * - the size field is 32bits long (generic=16)
+ * - all char types are in ASCII
+ */
+#define TFA_PM_VERSION '1'
+#define TFA_PM3_VERSION '3'
+#define TFA_PM_SUBVERSION '1'
+typedef struct TfaContainer {
+ char id[2]; // "XX" : XX=type
+ char version[2]; // "V_" : V=version, vv=subversion
+ char subversion[2]; // "vv" : vv=subversion
+ uint32_t size; // data size in bytes following CRC
+ uint32_t CRC; // 32-bits CRC for following data
+ uint16_t rev; // "extra chars for rev nr"
+ char customer[8]; // “name of customer”
+ char application[8]; // “application name”
+ char type[8]; // “application type name”
+ uint16_t ndev; // "nr of device lists"
+ uint16_t nprof; // "nr of profile lists"
+ uint16_t nliveData; // "nr of livedata lists"
+ TfaDescPtr_t index[]; // start of item index table
+} TfaContainer_t;
+
+#pragma pack (pop)
+
+#endif /* TFA98XXPARAMETERS_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_tfafieldnames.h
new file mode 100644
index 00000000000..d5b397bf0c4
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_tfafieldnames.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+typedef struct TfaBfName {
+ unsigned short bfEnum;
+ char *bfName;
+} tfaBfName_t;
+
+typedef struct TfaIrqName {
+ unsigned short irqEnum;
+ char *irqName;
+} tfaIrqName_t;
+
+#include "tfa1_tfafieldnames.h"
+#include "tfa2_tfafieldnames_N1C.h"
+/* diffs for specific devices */
+#include "tfa9887_tfafieldnames.h"
+#include "tfa9890_tfafieldnames.h"
+#include "tfa9891_tfafieldnames.h"
+#include "tfa9872_tfafieldnames.h"
+#include "tfa9912_tfafieldnames.h"
+#include "tfa9896_tfafieldnames.h"
+#include "tfa9873_tfafieldnames.h"
+#include "tfa9873_tfafieldnames_B0.h"
+#include "tfa9874_tfafieldnames.h"
+#include "tfa9878_tfafieldnames.h"
+#include "tfa9894_tfafieldnames.h"
+#include "tfa9894_tfafieldnames_N2.h"
+#include "tfa9875_tfafieldnames.h"
+#include "tfa9875_tfafieldnames_A1.h"
+
+/* missing 'common' defs break the build but unused in TFA1 context */
+#define TFA1_BF_AMPINSEL -1
+#define TFA1_BF_MANSCONF -1
+#define TFA1_BF_MANCOLD -1
+#define TFA1_BF_INTSMUTE -1
+#define TFA1_BF_CFSMR -1
+#define TFA1_BF_CFSML -1
+#define TFA1_BF_DCMCCAPI -1
+#define TFA1_BF_DCMCCSB -1
+#define TFA1_BF_USERDEF -1
+#define TFA1_BF_MANSTATE -1
+#define TFA1_BF_MANOPER -1
+#define TFA1_BF_REFCKSEL -1
+#define TFA1_BF_VOLSEC -1
+#define TFA1_BF_FRACTDEL -1
+#define TFA1_BF_ACKDMG -1
+#define TFA1_BF_SSRIGHTE -1
+#define TFA1_BF_SSLEFTE -1
+#define TFA1_BF_R25CL -1
+#define TFA1_BF_R25CR -1
+#define TFA1_BF_SWPROFIL 0x8045 /*!< profile save */
+#define TFA1_BF_SWVSTEP 0x80a5 /*!< vstep save */
+
+/* missing 'common' defs break the build */
+#define TFA2_BF_CFSM -1
+
+
+/* MTP access uses registers
+ * defs are derived from corresponding bitfield names as used in the BF macros
+ */
+#define MTPKEY2 MTPK /* unlock key2 MTPK */
+#define MTP0 MTPOTC /* MTP data */
+#define MTP_CONTROL CIMTP /* copy i2c to mtp */
+
+/* interrupt enable register uses HW name in TFA2 */
+#define TFA2_BF_INTENVDDS TFA2_BF_IEVDDS
+
+
+/* TFA9891 specific bit field names */
+#define TFA1_BF_SAAMGAIN 0x2202
+#define TFA2_BF_SAAMGAIN -1
+
+/* TFA9872 specific bit field names */
+#define TFA2_BF_IELP0 TFA9872_BF_IELP0
+#define TFA2_BF_ISTLP0 TFA9872_BF_ISTLP0
+#define TFA2_BF_IPOLP0 TFA9872_BF_IPOLP0
+#define TFA2_BF_IELP1 TFA9872_BF_IELP1
+#define TFA2_BF_ISTLP1 TFA9872_BF_ISTLP1
+#define TFA2_BF_IPOLP1 TFA9872_BF_IPOLP1
+#define TFA2_BF_LP0 TFA9872_BF_LP0
+#define TFA2_BF_LP1 TFA9872_BF_LP1
+#define TFA2_BF_R25C TFA9872_BF_R25C
+#define TFA2_BF_SAMMODE TFA9872_BF_SAMMODE
+
+/* interrupt bit field names of TFA2 and TFA1 do not match */
+#define TFA1_BF_IEACS TFA1_BF_INTENACS
+#define TFA1_BF_IPOACS TFA1_BF_INTPOLACS
+#define TFA1_BF_ISTACS TFA1_BF_INTOACS
+#define TFA1_BF_ISTVDDS TFA1_BF_INTOVDDS
+#define TFA1_BF_ICLVDDS TFA1_BF_INTIVDDS
+#define TFA1_BF_IPOVDDS TFA1_BF_INTPOLVDDS
+#define TFA1_BF_IENOCLK TFA1_BF_INTENNOCLK
+#define TFA1_BF_ISTNOCLK TFA1_BF_INTONOCLK
+#define TFA1_BF_IPONOCLK TFA1_BF_INTPOLNOCLK
+
+/* interrupt bit fields not available on TFA1 */
+#define TFA1_BF_IECLKOOR -1
+#define TFA1_BF_ISTCLKOOR -1
+#define TFA1_BF_IEMWSRC -1
+#define TFA1_BF_ISTMWSRC -1
+#define TFA1_BF_IPOMWSRC -1
+#define TFA1_BF_IEMWSMU -1
+#define TFA1_BF_ISTMWSMU -1
+#define TFA1_BF_IPOMWSMU -1
+#define TFA1_BF_IEMWCFC -1
+#define TFA1_BF_ISTMWCFC -1
+#define TFA1_BF_IPOMWCFC -1
+#define TFA1_BF_CLKOOR -1
+#define TFA1_BF_MANWAIT1 -1
+#define TFA1_BF_MANWAIT2 -1
+#define TFA1_BF_MANMUTE -1
+#define TFA1_BF_IPCLKOOR -1
+#define TFA1_BF_ICLCLKOOR -1
+#define TFA1_BF_IPOSWS -1
+#define TFA1_BF_IESWS -1
+#define TFA1_BF_ISTSWS -1
+#define TFA1_BF_IESPKS -1
+#define TFA1_BF_ISTSPKS -1
+#define TFA1_BF_IPOSPKS -1
+#define TFA1_BF_IECLKS -1
+#define TFA1_BF_ISTCLKS -1
+#define TFA1_BF_IPOCLKS -1
+#define TFA1_BF_IEAMPS -1
+#define TFA1_BF_ISTAMPS -1
+#define TFA1_BF_IPOAMPS -1
+#define TFA1_BF_IELP0 -1
+#define TFA1_BF_ISTLP0 -1
+#define TFA1_BF_IPOLP0 -1
+#define TFA1_BF_IELP1 -1
+#define TFA1_BF_ISTLP1 -1
+#define TFA1_BF_IPOLP1 -1
+#define TFA1_BF_LP0 -1
+#define TFA1_BF_LP1 -1
+#define TFA1_BF_R25C -1
+#define TFA1_BF_SAMMODE -1
+
+/* TDM STATUS fields not available on TFA1 */
+#define TFA1_BF_TDMLUTER -1
+#define TFA1_BF_TDMERR -1
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9912_device_genregs.h b/sound/soc/codecs/tfa98xx-downstream/tfa9912_device_genregs.h
new file mode 100644
index 00000000000..99bd0de5730
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9912_device_genregs.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9912_device_genregs.h
+ * This file was generated automatically on 04/19/17 at 12:26:46.
+ * Source file: TFA9912_N1A_I2C_regmap_V1.39.xlsx
+ */
+
+#ifndef _TFA9912_DEVICE_GENREGS_H
+#define _TFA9912_DEVICE_GENREGS_H
+
+
+#define TFA99XX_SYS_CONTROL0 0x00
+#define TFA99XX_SYS_CONTROL1 0x01
+#define TFA99XX_SYS_CONTROL2 0x02
+#define TFA99XX_DEVICE_REVISION 0x03
+#define TFA99XX_CLOCK_CONTROL 0x04
+#define TFA99XX_CLOCK_GATING_CONTROL 0x05
+#define TFA99XX_HW_PATH_CFG 0x06
+#define TFA99XX_CLKCHK_TH 0x07
+#define TFA99XX_AMP_CTRL 0x08
+#define TFA99XX_SIDE_TONE_CONFIG 0x0d
+#define TFA99XX_CTRL_DIGTOANA_REG 0x0e
+#define TFA99XX_STATUS_FLAGS0 0x10
+#define TFA99XX_STATUS_FLAGS1 0x11
+#define TFA99XX_STATUS_FLAGS3 0x13
+#define TFA99XX_STATUS_FLAGS4 0x14
+#define TFA99XX_BATTERY_VOLTAGE 0x15
+#define TFA99XX_TEMPERATURE 0x16
+#define TFA99XX_VDDP_VOLTAGE 0x17
+#define TFA99XX_TDM_CONFIG0 0x20
+#define TFA99XX_TDM_CONFIG1 0x21
+#define TFA99XX_TDM_CONFIG2 0x22
+#define TFA99XX_TDM_CONFIG3 0x23
+#define TFA99XX_TDM_CONFIG4 0x24
+#define TFA99XX_TDM_CONFIG5 0x25
+#define TFA99XX_TDM_CONFIG6 0x26
+#define TFA99XX_TDM_CONFIG7 0x27
+#define TFA99XX_TDM_CONFIG8 0x28
+#define TFA99XX_TDM_CONFIG9 0x29
+#define TFA99XX_PDM_CONFIG0 0x31
+#define TFA99XX_PDM_CONFIG1 0x32
+#define TFA99XX_INTERRUPT_OUT_REG1 0x40
+#define TFA99XX_INTERRUPT_OUT_REG2 0x41
+#define TFA99XX_INTERRUPT_OUT_REG3 0x42
+#define TFA99XX_INTERRUPT_IN_REG1 0x44
+#define TFA99XX_INTERRUPT_IN_REG2 0x45
+#define TFA99XX_INTERRUPT_IN_REG3 0x46
+#define TFA99XX_INTERRUPT_ENABLE_REG1 0x48
+#define TFA99XX_INTERRUPT_ENABLE_REG2 0x49
+#define TFA99XX_INTERRUPT_ENABLE_REG3 0x4a
+#define TFA99XX_STATUS_POLARITY_REG1 0x4c
+#define TFA99XX_STATUS_POLARITY_REG2 0x4d
+#define TFA99XX_STATUS_POLARITY_REG3 0x4e
+#define TFA99XX_BAT_PROT_CONFIG 0x50
+#define TFA99XX_AUDIO_CONTROL 0x51
+#define TFA99XX_AMPLIFIER_CONFIG 0x52
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL0 0x53
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL1 0x54
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL2 0x55
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL4 0x57
+#define TFA99XX_KEY1_PROTECTED_PWM_CONFIG 0x58
+#define TFA99XX_CF_TAP_STATUS_0 0x5c
+#define TFA99XX_CF_TAP_STATUS_1 0x5d
+#define TFA99XX_TAP_CONTROL 0x5f
+#define TFA99XX_PGA_CONTROL0 0x60
+#define TFA99XX_GAIN_ATT 0x61
+#define TFA99XX_LOW_NOISE_GAIN1 0x62
+#define TFA99XX_LOW_NOISE_GAIN2 0x63
+#define TFA99XX_MODE1_DETECTOR1 0x64
+#define TFA99XX_MODE1_DETECTOR2 0x65
+#define TFA99XX_BST_PFM_CTRL 0x66
+#define TFA99XX_LOW_POWER_CTRL 0x67
+#define TFA99XX_TDM_SOURCE_CTRL 0x68
+#define TFA99XX_SAM_CTRL 0x69
+#define TFA99XX_RST_MIN_VBAT_CTRL 0x6a
+#define TFA99XX_SYS_CONTROL3 0x6b
+#define TFA99XX_STATUS_FLAGS5 0x6e
+#define TFA99XX_DCDC_CONTROL0 0x70
+#define TFA99XX_KEY1_PROTECTED_DCDC_CONTROL3 0x73
+#define TFA99XX_DCDC_CONTROL4 0x74
+#define TFA99XX_DCDC_CONTROL5 0x75
+#define TFA99XX_DCDC_CONTROL6 0x76
+#define TFA99XX_KEY2_PROTECTED_DCDC_CONTROL7 0x77
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG0 0x80
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG2 0x82
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG3 0x83
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG4 0x84
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG5 0x85
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG7 0x87
+#define TFA99XX_KEY2_PROTECTED_VOLSENSE_CONFIG 0x88
+#define TFA99XX_CURSENSE_CONFIG 0x89
+#define TFA99XX_CF_CONTROLS 0x90
+#define TFA99XX_CF_MAD 0x91
+#define TFA99XX_CF_MEM 0x92
+#define TFA99XX_CF_STATUS 0x93
+#define TFA99XX_MTPKEY1_REG 0xa0
+#define TFA99XX_MTPKEY2_REG 0xa1
+#define TFA99XX_MTP_STATUS 0xa2
+#define TFA99XX_KEY_PROTECTED_MTP_CONTROL 0xa3
+#define TFA99XX_KEY1_PROTECTED_FAIM_CONTROL 0xa4
+#define TFA99XX_MTP_DATA_OUT_MSB 0xa5
+#define TFA99XX_MTP_DATA_OUT_LSB 0xa6
+#define TFA99XX_KEY1_PROTECTED_PROTECTION_CONFIG 0xb0
+#define TFA99XX_TEMP_SENSOR_CONFIG 0xb1
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL0 0xc0
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL1 0xc1
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG0 0xc3
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG1 0xc4
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG2 0xc5
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG3 0xc6
+#define TFA99XX_KEY1_PROTECTED_DIGIMUX_CONTROL1 0xc8
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL0 0xca
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL1 0xcb
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST0 0xcd
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST3 0xd0
+#define TFA99XX_KEY1_PROTECTED_TSIG_CONTROL1 0xd2
+#define TFA99XX_KEY1_PROTECTED_ADC10_CONTROL 0xd3
+#define TFA99XX_KEY1_PROTECTED_ADC10_DATA 0xd4
+#define TFA99XX_KEY2_PROTECTED_CTRL_DIGTOANA 0xd5
+#define TFA99XX_KEY1_PROTECTED_CLKDIV_CONTROL 0xd6
+#define TFA99XX_KEY1_PROTECTED_IO_CONFIG2 0xd7
+#define TFA99XX_KEY1_PROTECTED_TEST_CTRL1 0xd8
+#define TFA99XX_KEY1_PROTECTED_MODE_OVERRULE 0xd9
+#define TFA99XX_KEY1_PROTECTED_FRO8_CALIB_CTRL 0xed
+#define TFA99XX_SOFTWARE_PROFILE 0xee
+#define TFA99XX_SOFTWARE_VSTEP 0xef
+#define TFA99XX_KEY2_PROTECTED_MTP0 0xf0
+#define TFA99XX_KEY1_PROTECTED_MTP2 0xf2
+#define TFA99XX_KEY2_PROTECTED_MTP4 0xf4
+#define TFA99XX_KEY1_PROTECTED_MTP6 0xf6
+#define TFA99XX_KEY1_PROTECTED_MTP7 0xf7
+#define TFA99XX_KEY1_PROTECTED_MTP9 0xf9
+#define TFA99XX_KEY1_PROTECTED_MTPF 0xff
+#define TFA99XX_SYS_CONTROL0_POR
+#define TFA99XX_SYS_CONTROL1_POR
+#define TFA99XX_SYS_CONTROL2_POR
+#define TFA99XX_DEVICE_REVISION_POR
+#define TFA99XX_CLOCK_CONTROL_POR
+#define TFA99XX_CLOCK_GATING_CONTROL_POR
+#define TFA99XX_HW_PATH_CFG_POR
+#define TFA99XX_CLKCHK_TH_POR
+#define TFA99XX_AMP_CTRL_POR
+#define TFA99XX_SIDE_TONE_CONFIG_POR
+#define TFA99XX_CTRL_DIGTOANA_REG_POR
+#define TFA99XX_STATUS_FLAGS0_POR
+#define TFA99XX_STATUS_FLAGS1_POR
+#define TFA99XX_STATUS_FLAGS3_POR
+#define TFA99XX_STATUS_FLAGS4_POR
+#define TFA99XX_BATTERY_VOLTAGE_POR
+#define TFA99XX_TEMPERATURE_POR
+#define TFA99XX_VDDP_VOLTAGE_POR
+#define TFA99XX_TDM_CONFIG0_POR
+#define TFA99XX_TDM_CONFIG1_POR
+#define TFA99XX_TDM_CONFIG2_POR
+#define TFA99XX_TDM_CONFIG3_POR
+#define TFA99XX_TDM_CONFIG4_POR
+#define TFA99XX_TDM_CONFIG5_POR
+#define TFA99XX_TDM_CONFIG6_POR
+#define TFA99XX_TDM_CONFIG7_POR
+#define TFA99XX_TDM_CONFIG8_POR
+#define TFA99XX_TDM_CONFIG9_POR
+#define TFA99XX_PDM_CONFIG0_POR
+#define TFA99XX_PDM_CONFIG1_POR
+#define TFA99XX_INTERRUPT_OUT_REG1_POR
+#define TFA99XX_INTERRUPT_OUT_REG2_POR
+#define TFA99XX_INTERRUPT_OUT_REG3_POR
+#define TFA99XX_INTERRUPT_IN_REG1_POR
+#define TFA99XX_INTERRUPT_IN_REG2_POR
+#define TFA99XX_INTERRUPT_IN_REG3_POR
+#define TFA99XX_INTERRUPT_ENABLE_REG1_POR
+#define TFA99XX_INTERRUPT_ENABLE_REG2_POR
+#define TFA99XX_INTERRUPT_ENABLE_REG3_POR
+#define TFA99XX_STATUS_POLARITY_REG1_POR
+#define TFA99XX_STATUS_POLARITY_REG2_POR
+#define TFA99XX_STATUS_POLARITY_REG3_POR
+#define TFA99XX_BAT_PROT_CONFIG_POR
+#define TFA99XX_AUDIO_CONTROL_POR
+#define TFA99XX_AMPLIFIER_CONFIG_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL2_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL4_POR
+#define TFA99XX_KEY1_PROTECTED_PWM_CONFIG_POR
+#define TFA99XX_CF_TAP_STATUS_0_POR
+#define TFA99XX_CF_TAP_STATUS_1_POR
+#define TFA99XX_TAP_CONTROL_POR
+#define TFA99XX_PGA_CONTROL0_POR
+#define TFA99XX_GAIN_ATT_POR
+#define TFA99XX_LOW_NOISE_GAIN1_POR
+#define TFA99XX_LOW_NOISE_GAIN2_POR
+#define TFA99XX_MODE1_DETECTOR1_POR
+#define TFA99XX_MODE1_DETECTOR2_POR
+#define TFA99XX_BST_PFM_CTRL_POR
+#define TFA99XX_LOW_POWER_CTRL_POR
+#define TFA99XX_TDM_SOURCE_CTRL_POR
+#define TFA99XX_SAM_CTRL_POR
+#define TFA99XX_RST_MIN_VBAT_CTRL_POR
+#define TFA99XX_SYS_CONTROL3_POR
+#define TFA99XX_STATUS_FLAGS5_POR
+#define TFA99XX_DCDC_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_DCDC_CONTROL3_POR
+#define TFA99XX_DCDC_CONTROL4_POR
+#define TFA99XX_DCDC_CONTROL5_POR
+#define TFA99XX_DCDC_CONTROL6_POR
+#define TFA99XX_KEY2_PROTECTED_DCDC_CONTROL7_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG0_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG2_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG3_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG4_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG5_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG7_POR
+#define TFA99XX_KEY2_PROTECTED_VOLSENSE_CONFIG_POR
+#define TFA99XX_CURSENSE_CONFIG_POR
+#define TFA99XX_CF_CONTROLS_POR
+#define TFA99XX_CF_MAD_POR
+#define TFA99XX_CF_MEM_POR
+#define TFA99XX_CF_STATUS_POR
+#define TFA99XX_MTPKEY1_REG_POR
+#define TFA99XX_MTPKEY2_REG_POR
+#define TFA99XX_MTP_STATUS_POR
+#define TFA99XX_KEY_PROTECTED_MTP_CONTROL_POR
+#define TFA99XX_KEY1_PROTECTED_FAIM_CONTROL_POR
+#define TFA99XX_MTP_DATA_OUT_MSB_POR
+#define TFA99XX_MTP_DATA_OUT_LSB_POR
+#define TFA99XX_KEY1_PROTECTED_PROTECTION_CONFIG_POR
+#define TFA99XX_TEMP_SENSOR_CONFIG_POR
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG0_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG1_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG2_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG3_POR
+#define TFA99XX_KEY1_PROTECTED_DIGIMUX_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST0_POR
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST3_POR
+#define TFA99XX_KEY1_PROTECTED_TSIG_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_ADC10_CONTROL_POR
+#define TFA99XX_KEY1_PROTECTED_ADC10_DATA_POR
+#define TFA99XX_KEY2_PROTECTED_CTRL_DIGTOANA_POR
+#define TFA99XX_KEY1_PROTECTED_CLKDIV_CONTROL_POR
+#define TFA99XX_KEY1_PROTECTED_IO_CONFIG2_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CTRL1_POR
+#define TFA99XX_KEY1_PROTECTED_MODE_OVERRULE_POR
+#define TFA99XX_KEY1_PROTECTED_FRO8_CALIB_CTRL_POR
+#define TFA99XX_SOFTWARE_PROFILE_POR
+#define TFA99XX_SOFTWARE_VSTEP_POR
+#define TFA99XX_KEY2_PROTECTED_MTP0_POR
+#define TFA99XX_KEY1_PROTECTED_MTP2_POR
+#define TFA99XX_KEY2_PROTECTED_MTP4_POR
+#define TFA99XX_KEY1_PROTECTED_MTP6_POR
+#define TFA99XX_KEY1_PROTECTED_MTP7_POR
+#define TFA99XX_KEY1_PROTECTED_MTP9_POR
+#define TFA99XX_KEY1_PROTECTED_MTPF_POR
+
+#endif /* _TFA9912_DEVICE_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9912_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9912_tfafieldnames.h
new file mode 100644
index 00000000000..9e5a166ac10
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9912_tfafieldnames.h
@@ -0,0 +1,1776 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9912_tfaFieldnames.h
+ * This file was generated automatically on 09/28/18 at 12:00:21.
+ * Source file: TFA9912_N1A_I2C_regmap_V1.43.xlsx
+ */
+
+#ifndef _TFA9912_TFAFIELDNAMES_H
+#define _TFA9912_TFAFIELDNAMES_H
+
+
+#define TFA9912_I2CVERSION 1.43
+
+typedef enum Tfa9912BfEnumList {
+ TFA9912_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9912_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9912_BF_CFE = 0x0020, /*!< Enable CoolFlux */
+ TFA9912_BF_AMPE = 0x0030, /*!< Enables the Amplifier */
+ TFA9912_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9912_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA9912_BF_AMPC = 0x0060, /*!< CoolFlux controls amplifier */
+ TFA9912_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9912_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9912_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9912_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9912_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9912_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9912_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA9912_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA9912_BF_MANROBOD= 0x0150, /*!< Reaction on BOD */
+ TFA9912_BF_BODE = 0x0160, /*!< BOD Enable */
+ TFA9912_BF_BODHYS= 0x0170, /*!< BOD Hysteresis */
+ TFA9912_BF_BODFILT= 0x0181, /*!< BOD filter */
+ TFA9912_BF_BODTHLVL= 0x01a1, /*!< BOD threshold */
+ TFA9912_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA9912_BF_RCVNS = 0x01e0, /*!< Noise shaper selection */
+ TFA9912_BF_MANWDE= 0x01f0, /*!< Watchdog enable */
+ TFA9912_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9912_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9912_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9912_BF_BYPHVBF= 0x02b0, /*!< Bypass HVBAT filter */
+ TFA9912_BF_TDMC = 0x02c0, /*!< TDM Compatibility with TFA9872 */
+ TFA9912_BF_ENBLADC10= 0x02e0, /*!< ADC10 Enable - I2C direct mode */
+ TFA9912_BF_REV = 0x030f, /*!< Revision info */
+ TFA9912_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9912_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9912_BF_ENCFCKSEL= 0x0430, /*!< Coolflux DSP clock scaling, low power mode */
+ TFA9912_BF_CFCKSEL= 0x0441, /*!< Coolflux DSP clock scaler selection for low power mode */
+ TFA9912_BF_TDMINFSEL= 0x0460, /*!< TDM clock selection */
+ TFA9912_BF_DISBLAUTOCLKSEL= 0x0470, /*!< Disable Automatic dsp clock source selection */
+ TFA9912_BF_SELCLKSRC= 0x0480, /*!< I2C selection of DSP clock when auto select is disabled */
+ TFA9912_BF_SELTIMSRC= 0x0490, /*!< I2C selection of Watchdog and Timer clock */
+ TFA9912_BF_SSLEFTE= 0x0500, /*!< */
+ TFA9912_BF_SPKSSEN= 0x0510, /*!< Enable speaker path */
+ TFA9912_BF_VSLEFTE= 0x0520, /*!< */
+ TFA9912_BF_VSRIGHTE= 0x0530, /*!< Voltage sense */
+ TFA9912_BF_CSLEFTE= 0x0540, /*!< */
+ TFA9912_BF_CSRIGHTE= 0x0550, /*!< Current sense */
+ TFA9912_BF_SSPDME= 0x0560, /*!< Sub-system PDM */
+ TFA9912_BF_PGALE = 0x0570, /*!< Enable PGA chop clock for left channel */
+ TFA9912_BF_PGARE = 0x0580, /*!< Enable PGA chop clock */
+ TFA9912_BF_SSTDME= 0x0590, /*!< Sub-system TDM */
+ TFA9912_BF_SSPBSTE= 0x05a0, /*!< Sub-system boost */
+ TFA9912_BF_SSADCE= 0x05b0, /*!< Sub-system ADC */
+ TFA9912_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9912_BF_SSCFTIME= 0x05d0, /*!< CF Sub-system timer */
+ TFA9912_BF_SSCFWDTE= 0x05e0, /*!< CF Sub-system WDT */
+ TFA9912_BF_FAIMVBGOVRRL= 0x05f0, /*!< Over rule of vbg for FaIM access */
+ TFA9912_BF_SAMSPKSEL= 0x0600, /*!< Input selection for TAP/SAM */
+ TFA9912_BF_PDM2IISEN= 0x0610, /*!< PDM2IIS Bridge enable */
+ TFA9912_BF_TAPRSTBYPASS= 0x0620, /*!< Tap decimator reset bypass - Bypass the decimator reset from tapdec */
+ TFA9912_BF_CARDECISEL0= 0x0631, /*!< Cardec input 0 sel */
+ TFA9912_BF_CARDECISEL1= 0x0651, /*!< Cardec input sel */
+ TFA9912_BF_TAPDECSEL= 0x0670, /*!< Select TAP/Cardec for TAP */
+ TFA9912_BF_COMPCOUNT= 0x0680, /*!< Comparator o/p filter selection */
+ TFA9912_BF_STARTUPMODE= 0x0691, /*!< Startup Mode Selection */
+ TFA9912_BF_AUTOTAP= 0x06b0, /*!< Enable auto tap switching */
+ TFA9912_BF_COMPINITIME= 0x06c1, /*!< Comparator initialization time to be used in Tap Machine */
+ TFA9912_BF_ANAPINITIME= 0x06e1, /*!< Analog initialization time to be used in Tap Machine */
+ TFA9912_BF_CCHKTH= 0x0707, /*!< Clock check Higher Threshold */
+ TFA9912_BF_CCHKTL= 0x0787, /*!< Clock check Higher Threshold */
+ TFA9912_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9912_BF_AMPTCRR= 0x0832, /*!< Amplifier on-off criteria for tap mode entry */
+ TFA9912_BF_STGS = 0x0d00, /*!< PDM side tone gain selector */
+ TFA9912_BF_STGAIN= 0x0d18, /*!< Side tone gain */
+ TFA9912_BF_STSMUTE= 0x0da0, /*!< Side tone soft mute */
+ TFA9912_BF_ST1C = 0x0db0, /*!< side tone one s complement */
+ TFA9912_BF_CMFBEL= 0x0e80, /*!< CMFB enable left */
+ TFA9912_BF_VDDS = 0x1000, /*!< POR */
+ TFA9912_BF_PLLS = 0x1010, /*!< PLL lock */
+ TFA9912_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9912_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9912_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9912_BF_CLKS = 0x1050, /*!< Clocks stable */
+ TFA9912_BF_MTPB = 0x1060, /*!< MTP busy */
+ TFA9912_BF_NOCLK = 0x1070, /*!< Lost clock */
+ TFA9912_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA9912_BF_SWS = 0x10a0, /*!< Amplifier engage */
+ TFA9912_BF_WDS = 0x10b0, /*!< Watchdog */
+ TFA9912_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9912_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9912_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9912_BF_BODNOK= 0x10f0, /*!< BOD */
+ TFA9912_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9912_BF_DCDCA = 0x1110, /*!< DCDC active */
+ TFA9912_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos */
+ TFA9912_BF_DCPEAKCUR= 0x1130, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9912_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9912_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9912_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9912_BF_STMUTEB= 0x1170, /*!< side tone (un)mute busy */
+ TFA9912_BF_STMUTE= 0x1180, /*!< side tone mute state */
+ TFA9912_BF_TDMLUTER= 0x1190, /*!< TDM LUT error */
+ TFA9912_BF_TDMSTAT= 0x11a2, /*!< TDM status bits */
+ TFA9912_BF_TDMERR= 0x11d0, /*!< TDM error */
+ TFA9912_BF_HAPTIC= 0x11e0, /*!< Status haptic driver */
+ TFA9912_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9912_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9912_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9912_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9912_BF_CLIPAH= 0x1340, /*!< Clipping A to Vddp */
+ TFA9912_BF_CLIPAL= 0x1350, /*!< Clipping A to gnd */
+ TFA9912_BF_CLIPBH= 0x1360, /*!< Clipping B to Vddp */
+ TFA9912_BF_CLIPBL= 0x1370, /*!< Clipping B to gnd */
+ TFA9912_BF_OCDS = 0x1380, /*!< OCP amplifier */
+ TFA9912_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9912_BF_TCMPTRG= 0x13a0, /*!< Status Tap comparator triggered */
+ TFA9912_BF_TAPDET= 0x13b0, /*!< Status Tap detected */
+ TFA9912_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9912_BF_MANWAIT2= 0x13d0, /*!< Wait CF config */
+ TFA9912_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9912_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9912_BF_SPKSL = 0x1400, /*!< Left speaker status */
+ TFA9912_BF_SPKS = 0x1410, /*!< Speaker status */
+ TFA9912_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA9912_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9912_BF_DCMODE= 0x1471, /*!< DCDC mode status bits */
+ TFA9912_BF_DSPCLKSRC= 0x1490, /*!< DSP clock source selected by manager */
+ TFA9912_BF_STARTUPMODSTAT= 0x14a1, /*!< Startup Mode Selected by Manager(Read Only) */
+ TFA9912_BF_TSPMSTATE= 0x14c3, /*!< Tap Machine State */
+ TFA9912_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9912_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9912_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9912_BF_DCILCF= 0x17a0, /*!< DCDC current limiting for DSP */
+ TFA9912_BF_TDMUC = 0x2000, /*!< Mode setting */
+ TFA9912_BF_DIO4SEL= 0x2011, /*!< DIO4 Input selection */
+ TFA9912_BF_TDME = 0x2040, /*!< Enable TDM interface */
+ TFA9912_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA9912_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9912_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9912_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9912_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9912_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA9912_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9912_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9912_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9912_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9912_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9912_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9912_BF_TDMTXDFO= 0x2271, /*!< Format unused bits in a slot */
+ TFA9912_BF_TDMTXUS0= 0x2291, /*!< Format unused slots GAINIO */
+ TFA9912_BF_TDMTXUS1= 0x22b1, /*!< Format unused slots DIO1 */
+ TFA9912_BF_TDMTXUS2= 0x22d1, /*!< Format unused slots DIO2 */
+ TFA9912_BF_TDMGIE= 0x2300, /*!< Control gain (channel in 0) */
+ TFA9912_BF_TDMDCE= 0x2310, /*!< Control audio left (channel in 1 ) */
+ TFA9912_BF_TDMSPKE= 0x2320, /*!< Control audio right (channel in 2 ) */
+ TFA9912_BF_TDMCSE= 0x2330, /*!< Current sense */
+ TFA9912_BF_TDMVSE= 0x2340, /*!< Voltage sense */
+ TFA9912_BF_TDMGOE= 0x2350, /*!< DSP Gainout */
+ TFA9912_BF_TDMCF2E= 0x2360, /*!< DSP 2 */
+ TFA9912_BF_TDMCF3E= 0x2370, /*!< DSP 3 */
+ TFA9912_BF_TDMCFE= 0x2380, /*!< DSP */
+ TFA9912_BF_TDMES6= 0x2390, /*!< Loopback of Audio left (channel 1) */
+ TFA9912_BF_TDMES7= 0x23a0, /*!< Loopback of Audio right (channel 2) */
+ TFA9912_BF_TDMCF4E= 0x23b0, /*!< AEC ref right control */
+ TFA9912_BF_TDMPD1E= 0x23c0, /*!< PDM 1 control */
+ TFA9912_BF_TDMPD2E= 0x23d0, /*!< PDM 2 control */
+ TFA9912_BF_TDMGIN= 0x2401, /*!< IO gainin */
+ TFA9912_BF_TDMLIO= 0x2421, /*!< IO audio left */
+ TFA9912_BF_TDMRIO= 0x2441, /*!< IO audio right */
+ TFA9912_BF_TDMCSIO= 0x2461, /*!< IO Current Sense */
+ TFA9912_BF_TDMVSIO= 0x2481, /*!< IO voltage sense */
+ TFA9912_BF_TDMGOIO= 0x24a1, /*!< IO gain out */
+ TFA9912_BF_TDMCFIO2= 0x24c1, /*!< IO DSP 2 */
+ TFA9912_BF_TDMCFIO3= 0x24e1, /*!< IO DSP 3 */
+ TFA9912_BF_TDMCFIO= 0x2501, /*!< IO DSP */
+ TFA9912_BF_TDMLPB6= 0x2521, /*!< IO Source 6 */
+ TFA9912_BF_TDMLPB7= 0x2541, /*!< IO Source 7 */
+ TFA9912_BF_TDMGS = 0x2603, /*!< Control gainin */
+ TFA9912_BF_TDMDCS= 0x2643, /*!< tdm slot for audio left (channel 1) */
+ TFA9912_BF_TDMSPKS= 0x2683, /*!< tdm slot for audio right (channel 2) */
+ TFA9912_BF_TDMCSS= 0x26c3, /*!< Slot Position of Current Sense Out */
+ TFA9912_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense */
+ TFA9912_BF_TDMCGOS= 0x2743, /*!< Slot Position of GAIN out */
+ TFA9912_BF_TDMCF2S= 0x2783, /*!< Slot Position DSPout2 */
+ TFA9912_BF_TDMCF3S= 0x27c3, /*!< Slot Position DSPout3 */
+ TFA9912_BF_TDMCFS= 0x2803, /*!< Slot Position of DSPout */
+ TFA9912_BF_TDMEDAT6S= 0x2843, /*!< Slot Position of loopback channel left */
+ TFA9912_BF_TDMEDAT7S= 0x2883, /*!< Slot Position of loopback channel right */
+ TFA9912_BF_TDMTXUS3= 0x2901, /*!< Format unused slots D3 */
+ TFA9912_BF_PDMSM = 0x3100, /*!< PDM control */
+ TFA9912_BF_PDMSTSEL= 0x3110, /*!< PDM Decimator input selection */
+ TFA9912_BF_PDMSTENBL= 0x3120, /*!< Side tone input enable */
+ TFA9912_BF_PDMLSEL= 0x3130, /*!< PDM data selection for left channel during PDM direct mode */
+ TFA9912_BF_PDMRSEL= 0x3140, /*!< PDM data selection for right channel during PDM direct mode */
+ TFA9912_BF_MICVDDE= 0x3150, /*!< Enable MICVDD */
+ TFA9912_BF_PDMCLRAT= 0x3201, /*!< PDM BCK/Fs ratio */
+ TFA9912_BF_PDMGAIN= 0x3223, /*!< PDM gain */
+ TFA9912_BF_PDMOSEL= 0x3263, /*!< PDM output selection - RE/FE data combination */
+ TFA9912_BF_SELCFHAPD= 0x32a0, /*!< Select the source for haptic data output (not for customer) */
+ TFA9912_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9912_BF_ISTPLLS= 0x4010, /*!< Status PLL lock */
+ TFA9912_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9912_BF_ISTOVDS= 0x4030, /*!< Status OVP alarm */
+ TFA9912_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9912_BF_ISTCLKS= 0x4050, /*!< Status clocks stable */
+ TFA9912_BF_ISTMTPB= 0x4060, /*!< Status MTP busy */
+ TFA9912_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9912_BF_ISTSPKS= 0x4080, /*!< Status speaker error */
+ TFA9912_BF_ISTACS= 0x4090, /*!< Status cold start */
+ TFA9912_BF_ISTSWS= 0x40a0, /*!< Status amplifier engage */
+ TFA9912_BF_ISTWDS= 0x40b0, /*!< Status watchdog */
+ TFA9912_BF_ISTAMPS= 0x40c0, /*!< Status amplifier enable */
+ TFA9912_BF_ISTAREFS= 0x40d0, /*!< Status Ref enable */
+ TFA9912_BF_ISTADCCR= 0x40e0, /*!< Status Control ADC */
+ TFA9912_BF_ISTBODNOK= 0x40f0, /*!< Status BOD */
+ TFA9912_BF_ISTBSTCU= 0x4100, /*!< Status DCDC current limiting */
+ TFA9912_BF_ISTBSTHI= 0x4110, /*!< Status DCDC active */
+ TFA9912_BF_ISTBSTOC= 0x4120, /*!< Status DCDC OCP */
+ TFA9912_BF_ISTBSTPKCUR= 0x4130, /*!< Status bst peakcur */
+ TFA9912_BF_ISTBSTVC= 0x4140, /*!< Status DCDC level 1x */
+ TFA9912_BF_ISTBST86= 0x4150, /*!< Status DCDC level 1.14x */
+ TFA9912_BF_ISTBST93= 0x4160, /*!< Status DCDC level 1.07x */
+ TFA9912_BF_ISTRCVLD= 0x4170, /*!< Status rcvldop ready */
+ TFA9912_BF_ISTOCPL= 0x4180, /*!< Status ocp alarm left */
+ TFA9912_BF_ISTOCPR= 0x4190, /*!< Status ocp alarm */
+ TFA9912_BF_ISTMWSRC= 0x41a0, /*!< Status Waits HW I2C settings */
+ TFA9912_BF_ISTMWCFC= 0x41b0, /*!< Status waits CF config */
+ TFA9912_BF_ISTMWSMU= 0x41c0, /*!< Status Audio mute sequence */
+ TFA9912_BF_ISTCFMER= 0x41d0, /*!< Status cfma error */
+ TFA9912_BF_ISTCFMAC= 0x41e0, /*!< Status cfma ack */
+ TFA9912_BF_ISTCLKOOR= 0x41f0, /*!< Status flag_clk_out_of_range */
+ TFA9912_BF_ISTTDMER= 0x4200, /*!< Status tdm error */
+ TFA9912_BF_ISTCLPL= 0x4210, /*!< Status clip left */
+ TFA9912_BF_ISTCLPR= 0x4220, /*!< Status clip */
+ TFA9912_BF_ISTOCPM= 0x4230, /*!< Status mic ocpok */
+ TFA9912_BF_ISTLP1= 0x4250, /*!< Status low power mode1 */
+ TFA9912_BF_ISTLA = 0x4260, /*!< Status low amplitude detection */
+ TFA9912_BF_ISTVDDP= 0x4270, /*!< Status VDDP greater than VBAT */
+ TFA9912_BF_ISTTAPDET= 0x4280, /*!< Status Tap detected */
+ TFA9912_BF_ISTAUDMOD= 0x4290, /*!< Status Audio Mode activated */
+ TFA9912_BF_ISTSAMMOD= 0x42a0, /*!< Status SAM Mode activated */
+ TFA9912_BF_ISTTAPMOD= 0x42b0, /*!< Status Tap Mode Activated */
+ TFA9912_BF_ISTTAPTRG= 0x42c0, /*!< Status Tap comparator triggered */
+ TFA9912_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9912_BF_ICLPLLS= 0x4410, /*!< Clear PLL lock */
+ TFA9912_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9912_BF_ICLOVDS= 0x4430, /*!< Clear OVP alarm */
+ TFA9912_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9912_BF_ICLCLKS= 0x4450, /*!< Clear clocks stable */
+ TFA9912_BF_ICLMTPB= 0x4460, /*!< Clear mtp busy */
+ TFA9912_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9912_BF_ICLSPKS= 0x4480, /*!< Clear speaker error */
+ TFA9912_BF_ICLACS= 0x4490, /*!< Clear cold started */
+ TFA9912_BF_ICLSWS= 0x44a0, /*!< Clear amplifier engage */
+ TFA9912_BF_ICLWDS= 0x44b0, /*!< Clear watchdog */
+ TFA9912_BF_ICLAMPS= 0x44c0, /*!< Clear enbl amp */
+ TFA9912_BF_ICLAREFS= 0x44d0, /*!< Clear ref enable */
+ TFA9912_BF_ICLADCCR= 0x44e0, /*!< Clear control ADC */
+ TFA9912_BF_ICLBODNOK= 0x44f0, /*!< Clear BOD */
+ TFA9912_BF_ICLBSTCU= 0x4500, /*!< Clear DCDC current limiting */
+ TFA9912_BF_ICLBSTHI= 0x4510, /*!< Clear DCDC active */
+ TFA9912_BF_ICLBSTOC= 0x4520, /*!< Clear DCDC OCP */
+ TFA9912_BF_ICLBSTPC= 0x4530, /*!< Clear bst peakcur */
+ TFA9912_BF_ICLBSTVC= 0x4540, /*!< Clear DCDC level 1x */
+ TFA9912_BF_ICLBST86= 0x4550, /*!< Clear DCDC level 1.14x */
+ TFA9912_BF_ICLBST93= 0x4560, /*!< Clear DCDC level 1.07x */
+ TFA9912_BF_ICLRCVLD= 0x4570, /*!< Clear rcvldop ready */
+ TFA9912_BF_ICLOCPL= 0x4580, /*!< Clear ocp alarm left */
+ TFA9912_BF_ICLOCPR= 0x4590, /*!< Clear ocp alarm */
+ TFA9912_BF_ICLMWSRC= 0x45a0, /*!< Clear wait HW I2C settings */
+ TFA9912_BF_ICLMWCFC= 0x45b0, /*!< Clear wait cf config */
+ TFA9912_BF_ICLMWSMU= 0x45c0, /*!< Clear audio mute sequence */
+ TFA9912_BF_ICLCFMER= 0x45d0, /*!< Clear cfma err */
+ TFA9912_BF_ICLCFMAC= 0x45e0, /*!< Clear cfma ack */
+ TFA9912_BF_ICLCLKOOR= 0x45f0, /*!< Clear flag_clk_out_of_range */
+ TFA9912_BF_ICLTDMER= 0x4600, /*!< Clear tdm error */
+ TFA9912_BF_ICLCLPL= 0x4610, /*!< Clear clip left */
+ TFA9912_BF_ICLCLP= 0x4620, /*!< Clear clip */
+ TFA9912_BF_ICLOCPM= 0x4630, /*!< Clear mic ocpok */
+ TFA9912_BF_ICLLP1= 0x4650, /*!< Clear low power mode1 */
+ TFA9912_BF_ICLLA = 0x4660, /*!< Clear low amplitude detection */
+ TFA9912_BF_ICLVDDP= 0x4670, /*!< Clear VDDP greater then VBAT */
+ TFA9912_BF_ICLTAPDET= 0x4680, /*!< Clear Tap detected */
+ TFA9912_BF_ICLAUDMOD= 0x4690, /*!< Clear Audio Mode activated */
+ TFA9912_BF_ICLSAMMOD= 0x46a0, /*!< Clear SAM Mode activated */
+ TFA9912_BF_ICLTAPMOD= 0x46b0, /*!< Clear Tap Mode Activated */
+ TFA9912_BF_ICLTAPTRG= 0x46c0, /*!< Clear Comparator Interrupt */
+ TFA9912_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9912_BF_IEPLLS= 0x4810, /*!< Enable pll lock */
+ TFA9912_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9912_BF_IEOVDS= 0x4830, /*!< Enable OVP alarm */
+ TFA9912_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9912_BF_IECLKS= 0x4850, /*!< Enable clocks stable */
+ TFA9912_BF_IEMTPB= 0x4860, /*!< Enable mtp busy */
+ TFA9912_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9912_BF_IESPKS= 0x4880, /*!< Enable speaker error */
+ TFA9912_BF_IEACS = 0x4890, /*!< Enable cold started */
+ TFA9912_BF_IESWS = 0x48a0, /*!< Enable amplifier engage */
+ TFA9912_BF_IEWDS = 0x48b0, /*!< Enable watchdog */
+ TFA9912_BF_IEAMPS= 0x48c0, /*!< Enable enbl amp */
+ TFA9912_BF_IEAREFS= 0x48d0, /*!< Enable ref enable */
+ TFA9912_BF_IEADCCR= 0x48e0, /*!< Enable Control ADC */
+ TFA9912_BF_IEBODNOK= 0x48f0, /*!< Enable BOD */
+ TFA9912_BF_IEBSTCU= 0x4900, /*!< Enable DCDC current limiting */
+ TFA9912_BF_IEBSTHI= 0x4910, /*!< Enable DCDC active */
+ TFA9912_BF_IEBSTOC= 0x4920, /*!< Enable DCDC OCP */
+ TFA9912_BF_IEBSTPC= 0x4930, /*!< Enable bst peakcur */
+ TFA9912_BF_IEBSTVC= 0x4940, /*!< Enable DCDC level 1x */
+ TFA9912_BF_IEBST86= 0x4950, /*!< Enable DCDC level 1.14x */
+ TFA9912_BF_IEBST93= 0x4960, /*!< Enable DCDC level 1.07x */
+ TFA9912_BF_IERCVLD= 0x4970, /*!< Enable rcvldop ready */
+ TFA9912_BF_IEOCPL= 0x4980, /*!< Enable ocp alarm left */
+ TFA9912_BF_IEOCPR= 0x4990, /*!< Enable ocp alarm */
+ TFA9912_BF_IEMWSRC= 0x49a0, /*!< Enable waits HW I2C settings */
+ TFA9912_BF_IEMWCFC= 0x49b0, /*!< Enable man wait cf config */
+ TFA9912_BF_IEMWSMU= 0x49c0, /*!< Enable man Audio mute sequence */
+ TFA9912_BF_IECFMER= 0x49d0, /*!< Enable cfma err */
+ TFA9912_BF_IECFMAC= 0x49e0, /*!< Enable cfma ack */
+ TFA9912_BF_IECLKOOR= 0x49f0, /*!< Enable flag_clk_out_of_range */
+ TFA9912_BF_IETDMER= 0x4a00, /*!< Enable tdm error */
+ TFA9912_BF_IECLPL= 0x4a10, /*!< Enable clip left */
+ TFA9912_BF_IECLPR= 0x4a20, /*!< Enable clip */
+ TFA9912_BF_IEOCPM1= 0x4a30, /*!< Enable mic ocpok */
+ TFA9912_BF_IELP1 = 0x4a50, /*!< Enable low power mode1 */
+ TFA9912_BF_IELA = 0x4a60, /*!< Enable low amplitude detection */
+ TFA9912_BF_IEVDDP= 0x4a70, /*!< Enable VDDP greater than VBAT */
+ TFA9912_BF_IETAPDET= 0x4a80, /*!< Enable Tap detected */
+ TFA9912_BF_IEAUDMOD= 0x4a90, /*!< Enable Audio Mode activated */
+ TFA9912_BF_IESAMMOD= 0x4aa0, /*!< Enable SAM Mode activated */
+ TFA9912_BF_IETAPMOD= 0x4ab0, /*!< Enable Tap Mode Activated */
+ TFA9912_BF_IETAPTRG= 0x4ac0, /*!< Enable comparator interrupt */
+ TFA9912_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9912_BF_IPOPLLS= 0x4c10, /*!< Polarity pll lock */
+ TFA9912_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9912_BF_IPOOVDS= 0x4c30, /*!< Polarity OVP alarm */
+ TFA9912_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9912_BF_IPOCLKS= 0x4c50, /*!< Polarity clocks stable */
+ TFA9912_BF_IPOMTPB= 0x4c60, /*!< Polarity mtp busy */
+ TFA9912_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9912_BF_IPOSPKS= 0x4c80, /*!< Polarity speaker error */
+ TFA9912_BF_IPOACS= 0x4c90, /*!< Polarity cold started */
+ TFA9912_BF_IPOSWS= 0x4ca0, /*!< Polarity amplifier engage */
+ TFA9912_BF_IPOWDS= 0x4cb0, /*!< Polarity watchdog */
+ TFA9912_BF_IPOAMPS= 0x4cc0, /*!< Polarity enbl amp */
+ TFA9912_BF_IPOAREFS= 0x4cd0, /*!< Polarity ref enable */
+ TFA9912_BF_IPOADCCR= 0x4ce0, /*!< Polarity Control ADC */
+ TFA9912_BF_IPOBODNOK= 0x4cf0, /*!< Polarity BOD */
+ TFA9912_BF_IPOBSTCU= 0x4d00, /*!< Polarity DCDC current limiting */
+ TFA9912_BF_IPOBSTHI= 0x4d10, /*!< Polarity DCDC active */
+ TFA9912_BF_IPOBSTOC= 0x4d20, /*!< Polarity DCDC OCP */
+ TFA9912_BF_IPOBSTPC= 0x4d30, /*!< Polarity bst peakcur */
+ TFA9912_BF_IPOBSTVC= 0x4d40, /*!< Polarity DCDC level 1x */
+ TFA9912_BF_IPOBST86= 0x4d50, /*!< Polarity DCDC level 1.14x */
+ TFA9912_BF_IPOBST93= 0x4d60, /*!< Polarity DCDC level 1.07x */
+ TFA9912_BF_IPORCVLD= 0x4d70, /*!< Polarity rcvldop ready */
+ TFA9912_BF_IPOOCPL= 0x4d80, /*!< Polarity ocp alarm left */
+ TFA9912_BF_IPOOCPR= 0x4d90, /*!< Polarity ocp alarm */
+ TFA9912_BF_IPOMWSRC= 0x4da0, /*!< Polarity waits HW I2C settings */
+ TFA9912_BF_IPOMWCFC= 0x4db0, /*!< Polarity man wait cf config */
+ TFA9912_BF_IPOMWSMU= 0x4dc0, /*!< Polarity man audio mute sequence */
+ TFA9912_BF_IPOCFMER= 0x4dd0, /*!< Polarity cfma err */
+ TFA9912_BF_IPOCFMAC= 0x4de0, /*!< Polarity cfma ack */
+ TFA9912_BF_IPOCLKOOR= 0x4df0, /*!< Polarity flag_clk_out_of_range */
+ TFA9912_BF_IPOTDMER= 0x4e00, /*!< Polarity tdm error */
+ TFA9912_BF_IPOCLPL= 0x4e10, /*!< Polarity clip left */
+ TFA9912_BF_IPOCLPR= 0x4e20, /*!< Polarity clip */
+ TFA9912_BF_IPOOCPM= 0x4e30, /*!< Polarity mic ocpok */
+ TFA9912_BF_IPOLP1= 0x4e50, /*!< Polarity low power mode1 */
+ TFA9912_BF_IPOLA = 0x4e60, /*!< Polarity low amplitude detection */
+ TFA9912_BF_IPOVDDP= 0x4e70, /*!< Polarity VDDP greater than VBAT */
+ TFA9912_BF_IPOLTAPDET= 0x4e80, /*!< PolarityTap detected */
+ TFA9912_BF_IPOLAUDMOD= 0x4e90, /*!< PolarityAudio Mode activated */
+ TFA9912_BF_IPOLSAMMOD= 0x4ea0, /*!< PolaritySAM Mode activated */
+ TFA9912_BF_IPOLTAPMOD= 0x4eb0, /*!< Polarity Tap Mode Activated */
+ TFA9912_BF_IPOLTAPTRG= 0x4ec0, /*!< PolarityTap Comparator Trigger */
+ TFA9912_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time */
+ TFA9912_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9912_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9912_BF_BSSRR = 0x5082, /*!< Battery Safeguard release time */
+ TFA9912_BF_BSSHY = 0x50b1, /*!< Battery Safeguard hysteresis */
+ TFA9912_BF_BSSAC = 0x50d0, /*!< Reset clipper - Auto clear */
+ TFA9912_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9912_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA9912_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9912_BF_INTSMUTE= 0x5110, /*!< Soft mute HW */
+ TFA9912_BF_CFSML = 0x5120, /*!< Soft mute FW left */
+ TFA9912_BF_CFSM = 0x5130, /*!< Soft mute FW */
+ TFA9912_BF_HPFBYPL= 0x5140, /*!< Bypass HPF left */
+ TFA9912_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9912_BF_DPSAL = 0x5160, /*!< Enable DPSA left */
+ TFA9912_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9912_BF_VOL = 0x5187, /*!< FW volume control for primary audio channel */
+ TFA9912_BF_HNDSFRCV= 0x5200, /*!< Selection receiver */
+ TFA9912_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9912_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9912_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9912_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9912_BF_CFTAPPAT= 0x5c07, /*!< Coolflux tap pattern */
+ TFA9912_BF_TAPDBGINFO= 0x5c83, /*!< Reserved */
+ TFA9912_BF_TATPSTAT1= 0x5d0f, /*!< Tap Status 1 from CF FW */
+ TFA9912_BF_TCOMPTHR= 0x5f03, /*!< Comparator threshold (in uV) */
+ TFA9912_BF_PGAGAIN= 0x6081, /*!< PGA gain selection */
+ TFA9912_BF_TDMSPKG= 0x6123, /*!< System gain (INPLEV 0) */
+ TFA9912_BF_LPM1LVL= 0x6505, /*!< low power mode1 detector ctrl threshold for low_audio_lvl */
+ TFA9912_BF_LPM1HLD= 0x6565, /*!< Low power mode1 detector, ctrl hold time before low audio is reckoned to be low audio */
+ TFA9912_BF_LPM1DIS= 0x65c0, /*!< low power mode1 detector control */
+ TFA9912_BF_DCDIS = 0x6630, /*!< DCDC */
+ TFA9912_BF_TDMSRCMAP= 0x6801, /*!< tdm source mapping */
+ TFA9912_BF_TDMSRCAS= 0x6821, /*!< frame a selection */
+ TFA9912_BF_TDMSRCBS= 0x6841, /*!< frame b selection */
+ TFA9912_BF_ANC1C = 0x68a0, /*!< ANC one s complement */
+ TFA9912_BF_SAMMODE= 0x6901, /*!< Sam mode */
+ TFA9912_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA9912_BF_DCCV = 0x7071, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9912_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA9912_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA9912_BF_DCINSEL= 0x70c1, /*!< DCDC IIR input Selection */
+ TFA9912_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9912_BF_DCTRIP= 0x7504, /*!< Adaptive boost trip levels 1, effective only when boost_intelligent is set to 1 */
+ TFA9912_BF_DCTRIP2= 0x7554, /*!< Adaptive boost trip level 2, effective only when boost_intelligent is set to 1 */
+ TFA9912_BF_DCTRIPT= 0x75a4, /*!< Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9912_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9912_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9912_BF_RST = 0x9000, /*!< Reset */
+ TFA9912_BF_DMEM = 0x9011, /*!< Target memory */
+ TFA9912_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA9912_BF_CFINT = 0x9040, /*!< Interrupt - auto clear */
+ TFA9912_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA9912_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA9912_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA9912_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA9912_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA9912_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA9912_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA9912_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA9912_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA9912_BF_MADD = 0x910f, /*!< Memory address */
+ TFA9912_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA9912_BF_ERR = 0x9307, /*!< Error flags */
+ TFA9912_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA9912_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA9912_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA9912_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA9912_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA9912_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA9912_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA9912_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA9912_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9912_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9912_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9912_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9912_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9912_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9912_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9912_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9912_BF_SWPROFIL= 0xee0f, /*!< Software profile data */
+ TFA9912_BF_SWVSTEP= 0xef0f, /*!< Software vstep information */
+ TFA9912_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9912_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9912_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9912_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9912_BF_DCMCCCL= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9912_BF_USERDEF= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9912_BF_R25C = 0xf40f, /*!< Ron resistance of speaker coil */
+} Tfa9912BfEnumList_t;
+#define TFA9912_NAMETABLE static tfaBfName_t Tfa9912DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux , */\
+ { 0x30, "AMPE"}, /* Enables the Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x150, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x160, "BODE"}, /* BOD Enable , */\
+ { 0x170, "BODHYS"}, /* BOD Hysteresis , */\
+ { 0x181, "BODFILT"}, /* BOD filter , */\
+ { 0x1a1, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "RCVNS"}, /* Noise shaper selection , */\
+ { 0x1f0, "MANWDE"}, /* Watchdog enable , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b0, "BYPHVBF"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "TDMC"}, /* TDM Compatibility with TFA9872 , */\
+ { 0x2e0, "ENBLADC10"}, /* ADC10 Enable - I2C direct mode , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x430, "ENCFCKSEL"}, /* Coolflux DSP clock scaling, low power mode , */\
+ { 0x441, "CFCKSEL"}, /* Coolflux DSP clock scaler selection for low power mode, */\
+ { 0x460, "TDMINFSEL"}, /* TDM clock selection , */\
+ { 0x470, "DISBLAUTOCLKSEL"}, /* Disable Automatic dsp clock source selection , */\
+ { 0x480, "SELCLKSRC"}, /* I2C selection of DSP clock when auto select is disabled, */\
+ { 0x490, "SELTIMSRC"}, /* I2C selection of Watchdog and Timer clock , */\
+ { 0x500, "SSLEFTE"}, /* , */\
+ { 0x510, "SPKSSEN"}, /* Enable speaker path , */\
+ { 0x520, "VSLEFTE"}, /* , */\
+ { 0x530, "VSRIGHTE"}, /* Voltage sense , */\
+ { 0x540, "CSLEFTE"}, /* , */\
+ { 0x550, "CSRIGHTE"}, /* Current sense , */\
+ { 0x560, "SSPDME"}, /* Sub-system PDM , */\
+ { 0x570, "PGALE"}, /* Enable PGA chop clock for left channel , */\
+ { 0x580, "PGARE"}, /* Enable PGA chop clock , */\
+ { 0x590, "SSTDME"}, /* Sub-system TDM , */\
+ { 0x5a0, "SSPBSTE"}, /* Sub-system boost , */\
+ { 0x5b0, "SSADCE"}, /* Sub-system ADC , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x5d0, "SSCFTIME"}, /* CF Sub-system timer , */\
+ { 0x5e0, "SSCFWDTE"}, /* CF Sub-system WDT , */\
+ { 0x5f0, "FAIMVBGOVRRL"}, /* Over rule of vbg for FaIM access , */\
+ { 0x600, "SAMSPKSEL"}, /* Input selection for TAP/SAM , */\
+ { 0x610, "PDM2IISEN"}, /* PDM2IIS Bridge enable , */\
+ { 0x620, "TAPRSTBYPASS"}, /* Tap decimator reset bypass - Bypass the decimator reset from tapdec, */\
+ { 0x631, "CARDECISEL0"}, /* Cardec input 0 sel , */\
+ { 0x651, "CARDECISEL1"}, /* Cardec input sel , */\
+ { 0x670, "TAPDECSEL"}, /* Select TAP/Cardec for TAP , */\
+ { 0x680, "COMPCOUNT"}, /* Comparator o/p filter selection , */\
+ { 0x691, "STARTUPMODE"}, /* Startup Mode Selection , */\
+ { 0x6b0, "AUTOTAP"}, /* Enable auto tap switching , */\
+ { 0x6c1, "COMPINITIME"}, /* Comparator initialization time to be used in Tap Machine, */\
+ { 0x6e1, "ANAPINITIME"}, /* Analog initialization time to be used in Tap Machine, */\
+ { 0x707, "CCHKTH"}, /* Clock check Higher Threshold , */\
+ { 0x787, "CCHKTL"}, /* Clock check Higher Threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x832, "AMPTCRR"}, /* Amplifier on-off criteria for tap mode entry , */\
+ { 0xd00, "STGS"}, /* PDM side tone gain selector , */\
+ { 0xd18, "STGAIN"}, /* Side tone gain , */\
+ { 0xda0, "STSMUTE"}, /* Side tone soft mute , */\
+ { 0xdb0, "ST1C"}, /* side tone one s complement , */\
+ { 0xe80, "CMFBEL"}, /* CMFB enable left , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "CLKS"}, /* Clocks stable , */\
+ { 0x1060, "MTPB"}, /* MTP busy , */\
+ { 0x1070, "NOCLK"}, /* Lost clock , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "SWS"}, /* Amplifier engage , */\
+ { 0x10b0, "WDS"}, /* Watchdog , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos , */\
+ { 0x1130, "DCPEAKCUR"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "STMUTEB"}, /* side tone (un)mute busy , */\
+ { 0x1180, "STMUTE"}, /* side tone mute state , */\
+ { 0x1190, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11a2, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11d0, "TDMERR"}, /* TDM error , */\
+ { 0x11e0, "HAPTIC"}, /* Status haptic driver , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1340, "CLIPAH"}, /* Clipping A to Vddp , */\
+ { 0x1350, "CLIPAL"}, /* Clipping A to gnd , */\
+ { 0x1360, "CLIPBH"}, /* Clipping B to Vddp , */\
+ { 0x1370, "CLIPBL"}, /* Clipping B to gnd , */\
+ { 0x1380, "OCDS"}, /* OCP amplifier , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "TCMPTRG"}, /* Status Tap comparator triggered , */\
+ { 0x13b0, "TAPDET"}, /* Status Tap detected , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "MANWAIT2"}, /* Wait CF config , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1400, "SPKSL"}, /* Left speaker status , */\
+ { 0x1410, "SPKS"}, /* Speaker status , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1471, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1490, "DSPCLKSRC"}, /* DSP clock source selected by manager , */\
+ { 0x14a1, "STARTUPMODSTAT"}, /* Startup Mode Selected by Manager(Read Only) , */\
+ { 0x14c3, "TSPMSTATE"}, /* Tap Machine State , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x17a0, "DCILCF"}, /* DCDC current limiting for DSP , */\
+ { 0x2000, "TDMUC"}, /* Mode setting , */\
+ { 0x2011, "DIO4SEL"}, /* DIO4 Input selection , */\
+ { 0x2040, "TDME"}, /* Enable TDM interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits in a slot , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "TDMTXUS1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "TDMTXUS2"}, /* Format unused slots DIO2 , */\
+ { 0x2300, "TDMGIE"}, /* Control gain (channel in 0) , */\
+ { 0x2310, "TDMDCE"}, /* Control audio left (channel in 1 ) , */\
+ { 0x2320, "TDMSPKE"}, /* Control audio right (channel in 2 ) , */\
+ { 0x2330, "TDMCSE"}, /* Current sense , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense , */\
+ { 0x2350, "TDMGOE"}, /* DSP Gainout , */\
+ { 0x2360, "TDMCF2E"}, /* DSP 2 , */\
+ { 0x2370, "TDMCF3E"}, /* DSP 3 , */\
+ { 0x2380, "TDMCFE"}, /* DSP , */\
+ { 0x2390, "TDMES6"}, /* Loopback of Audio left (channel 1) , */\
+ { 0x23a0, "TDMES7"}, /* Loopback of Audio right (channel 2) , */\
+ { 0x23b0, "TDMCF4E"}, /* AEC ref right control , */\
+ { 0x23c0, "TDMPD1E"}, /* PDM 1 control , */\
+ { 0x23d0, "TDMPD2E"}, /* PDM 2 control , */\
+ { 0x2401, "TDMGIN"}, /* IO gainin , */\
+ { 0x2421, "TDMLIO"}, /* IO audio left , */\
+ { 0x2441, "TDMRIO"}, /* IO audio right , */\
+ { 0x2461, "TDMCSIO"}, /* IO Current Sense , */\
+ { 0x2481, "TDMVSIO"}, /* IO voltage sense , */\
+ { 0x24a1, "TDMGOIO"}, /* IO gain out , */\
+ { 0x24c1, "TDMCFIO2"}, /* IO DSP 2 , */\
+ { 0x24e1, "TDMCFIO3"}, /* IO DSP 3 , */\
+ { 0x2501, "TDMCFIO"}, /* IO DSP , */\
+ { 0x2521, "TDMLPB6"}, /* IO Source 6 , */\
+ { 0x2541, "TDMLPB7"}, /* IO Source 7 , */\
+ { 0x2603, "TDMGS"}, /* Control gainin , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for audio left (channel 1) , */\
+ { 0x2683, "TDMSPKS"}, /* tdm slot for audio right (channel 2) , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of Current Sense Out , */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense , */\
+ { 0x2743, "TDMCGOS"}, /* Slot Position of GAIN out , */\
+ { 0x2783, "TDMCF2S"}, /* Slot Position DSPout2 , */\
+ { 0x27c3, "TDMCF3S"}, /* Slot Position DSPout3 , */\
+ { 0x2803, "TDMCFS"}, /* Slot Position of DSPout , */\
+ { 0x2843, "TDMEDAT6S"}, /* Slot Position of loopback channel left , */\
+ { 0x2883, "TDMEDAT7S"}, /* Slot Position of loopback channel right , */\
+ { 0x2901, "TDMTXUS3"}, /* Format unused slots D3 , */\
+ { 0x3100, "PDMSM"}, /* PDM control , */\
+ { 0x3110, "PDMSTSEL"}, /* PDM Decimator input selection , */\
+ { 0x3120, "PDMSTENBL"}, /* Side tone input enable , */\
+ { 0x3130, "PDMLSEL"}, /* PDM data selection for left channel during PDM direct mode, */\
+ { 0x3140, "PDMRSEL"}, /* PDM data selection for right channel during PDM direct mode, */\
+ { 0x3150, "MICVDDE"}, /* Enable MICVDD , */\
+ { 0x3201, "PDMCLRAT"}, /* PDM BCK/Fs ratio , */\
+ { 0x3223, "PDMGAIN"}, /* PDM gain , */\
+ { 0x3263, "PDMOSEL"}, /* PDM output selection - RE/FE data combination , */\
+ { 0x32a0, "SELCFHAPD"}, /* Select the source for haptic data output (not for customer), */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTPLLS"}, /* Status PLL lock , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOVDS"}, /* Status OVP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTCLKS"}, /* Status clocks stable , */\
+ { 0x4060, "ISTMTPB"}, /* Status MTP busy , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTSPKS"}, /* Status speaker error , */\
+ { 0x4090, "ISTACS"}, /* Status cold start , */\
+ { 0x40a0, "ISTSWS"}, /* Status amplifier engage , */\
+ { 0x40b0, "ISTWDS"}, /* Status watchdog , */\
+ { 0x40c0, "ISTAMPS"}, /* Status amplifier enable , */\
+ { 0x40d0, "ISTAREFS"}, /* Status Ref enable , */\
+ { 0x40e0, "ISTADCCR"}, /* Status Control ADC , */\
+ { 0x40f0, "ISTBODNOK"}, /* Status BOD , */\
+ { 0x4100, "ISTBSTCU"}, /* Status DCDC current limiting , */\
+ { 0x4110, "ISTBSTHI"}, /* Status DCDC active , */\
+ { 0x4120, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4130, "ISTBSTPKCUR"}, /* Status bst peakcur , */\
+ { 0x4140, "ISTBSTVC"}, /* Status DCDC level 1x , */\
+ { 0x4150, "ISTBST86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "ISTBST93"}, /* Status DCDC level 1.07x , */\
+ { 0x4170, "ISTRCVLD"}, /* Status rcvldop ready , */\
+ { 0x4180, "ISTOCPL"}, /* Status ocp alarm left , */\
+ { 0x4190, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x41a0, "ISTMWSRC"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "ISTMWCFC"}, /* Status waits CF config , */\
+ { 0x41c0, "ISTMWSMU"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x41e0, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x41f0, "ISTCLKOOR"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4210, "ISTCLPL"}, /* Status clip left , */\
+ { 0x4220, "ISTCLPR"}, /* Status clip , */\
+ { 0x4230, "ISTOCPM"}, /* Status mic ocpok , */\
+ { 0x4250, "ISTLP1"}, /* Status low power mode1 , */\
+ { 0x4260, "ISTLA"}, /* Status low amplitude detection , */\
+ { 0x4270, "ISTVDDP"}, /* Status VDDP greater than VBAT , */\
+ { 0x4280, "ISTTAPDET"}, /* Status Tap detected , */\
+ { 0x4290, "ISTAUDMOD"}, /* Status Audio Mode activated , */\
+ { 0x42a0, "ISTSAMMOD"}, /* Status SAM Mode activated , */\
+ { 0x42b0, "ISTTAPMOD"}, /* Status Tap Mode Activated , */\
+ { 0x42c0, "ISTTAPTRG"}, /* Status Tap comparator triggered , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLPLLS"}, /* Clear PLL lock , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOVDS"}, /* Clear OVP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLCLKS"}, /* Clear clocks stable , */\
+ { 0x4460, "ICLMTPB"}, /* Clear mtp busy , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLSPKS"}, /* Clear speaker error , */\
+ { 0x4490, "ICLACS"}, /* Clear cold started , */\
+ { 0x44a0, "ICLSWS"}, /* Clear amplifier engage , */\
+ { 0x44b0, "ICLWDS"}, /* Clear watchdog , */\
+ { 0x44c0, "ICLAMPS"}, /* Clear enbl amp , */\
+ { 0x44d0, "ICLAREFS"}, /* Clear ref enable , */\
+ { 0x44e0, "ICLADCCR"}, /* Clear control ADC , */\
+ { 0x44f0, "ICLBODNOK"}, /* Clear BOD , */\
+ { 0x4500, "ICLBSTCU"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "ICLBSTHI"}, /* Clear DCDC active , */\
+ { 0x4520, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4530, "ICLBSTPC"}, /* Clear bst peakcur , */\
+ { 0x4540, "ICLBSTVC"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "ICLBST86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "ICLBST93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4570, "ICLRCVLD"}, /* Clear rcvldop ready , */\
+ { 0x4580, "ICLOCPL"}, /* Clear ocp alarm left , */\
+ { 0x4590, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x45a0, "ICLMWSRC"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "ICLMWCFC"}, /* Clear wait cf config , */\
+ { 0x45c0, "ICLMWSMU"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x45e0, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x45f0, "ICLCLKOOR"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4610, "ICLCLPL"}, /* Clear clip left , */\
+ { 0x4620, "ICLCLP"}, /* Clear clip , */\
+ { 0x4630, "ICLOCPM"}, /* Clear mic ocpok , */\
+ { 0x4650, "ICLLP1"}, /* Clear low power mode1 , */\
+ { 0x4660, "ICLLA"}, /* Clear low amplitude detection , */\
+ { 0x4670, "ICLVDDP"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4680, "ICLTAPDET"}, /* Clear Tap detected , */\
+ { 0x4690, "ICLAUDMOD"}, /* Clear Audio Mode activated , */\
+ { 0x46a0, "ICLSAMMOD"}, /* Clear SAM Mode activated , */\
+ { 0x46b0, "ICLTAPMOD"}, /* Clear Tap Mode Activated , */\
+ { 0x46c0, "ICLTAPTRG"}, /* Clear Comparator Interrupt , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEPLLS"}, /* Enable pll lock , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOVDS"}, /* Enable OVP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IECLKS"}, /* Enable clocks stable , */\
+ { 0x4860, "IEMTPB"}, /* Enable mtp busy , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IESPKS"}, /* Enable speaker error , */\
+ { 0x4890, "IEACS"}, /* Enable cold started , */\
+ { 0x48a0, "IESWS"}, /* Enable amplifier engage , */\
+ { 0x48b0, "IEWDS"}, /* Enable watchdog , */\
+ { 0x48c0, "IEAMPS"}, /* Enable enbl amp , */\
+ { 0x48d0, "IEAREFS"}, /* Enable ref enable , */\
+ { 0x48e0, "IEADCCR"}, /* Enable Control ADC , */\
+ { 0x48f0, "IEBODNOK"}, /* Enable BOD , */\
+ { 0x4900, "IEBSTCU"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "IEBSTHI"}, /* Enable DCDC active , */\
+ { 0x4920, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4930, "IEBSTPC"}, /* Enable bst peakcur , */\
+ { 0x4940, "IEBSTVC"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "IEBST86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "IEBST93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4970, "IERCVLD"}, /* Enable rcvldop ready , */\
+ { 0x4980, "IEOCPL"}, /* Enable ocp alarm left , */\
+ { 0x4990, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x49a0, "IEMWSRC"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "IEMWCFC"}, /* Enable man wait cf config , */\
+ { 0x49c0, "IEMWSMU"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "IECFMER"}, /* Enable cfma err , */\
+ { 0x49e0, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x49f0, "IECLKOOR"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4a10, "IECLPL"}, /* Enable clip left , */\
+ { 0x4a20, "IECLPR"}, /* Enable clip , */\
+ { 0x4a30, "IEOCPM1"}, /* Enable mic ocpok , */\
+ { 0x4a50, "IELP1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "IELA"}, /* Enable low amplitude detection , */\
+ { 0x4a70, "IEVDDP"}, /* Enable VDDP greater than VBAT , */\
+ { 0x4a80, "IETAPDET"}, /* Enable Tap detected , */\
+ { 0x4a90, "IEAUDMOD"}, /* Enable Audio Mode activated , */\
+ { 0x4aa0, "IESAMMOD"}, /* Enable SAM Mode activated , */\
+ { 0x4ab0, "IETAPMOD"}, /* Enable Tap Mode Activated , */\
+ { 0x4ac0, "IETAPTRG"}, /* Enable comparator interrupt , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOPLLS"}, /* Polarity pll lock , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOVDS"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOCLKS"}, /* Polarity clocks stable , */\
+ { 0x4c60, "IPOMTPB"}, /* Polarity mtp busy , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOSPKS"}, /* Polarity speaker error , */\
+ { 0x4c90, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4ca0, "IPOSWS"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "IPOWDS"}, /* Polarity watchdog , */\
+ { 0x4cc0, "IPOAMPS"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "IPOAREFS"}, /* Polarity ref enable , */\
+ { 0x4ce0, "IPOADCCR"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "IPOBODNOK"}, /* Polarity BOD , */\
+ { 0x4d00, "IPOBSTCU"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "IPOBSTHI"}, /* Polarity DCDC active , */\
+ { 0x4d20, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "IPOBSTPC"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "IPOBSTVC"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "IPOBST86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "IPOBST93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d70, "IPORCVLD"}, /* Polarity rcvldop ready , */\
+ { 0x4d80, "IPOOCPL"}, /* Polarity ocp alarm left , */\
+ { 0x4d90, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "IPOMWSRC"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "IPOMWCFC"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "IPOMWSMU"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4de0, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4df0, "IPOCLKOOR"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4e10, "IPOCLPL"}, /* Polarity clip left , */\
+ { 0x4e20, "IPOCLPR"}, /* Polarity clip , */\
+ { 0x4e30, "IPOOCPM"}, /* Polarity mic ocpok , */\
+ { 0x4e50, "IPOLP1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "IPOLA"}, /* Polarity low amplitude detection , */\
+ { 0x4e70, "IPOVDDP"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x4e80, "IPOLTAPDET"}, /* PolarityTap detected , */\
+ { 0x4e90, "IPOLAUDMOD"}, /* PolarityAudio Mode activated , */\
+ { 0x4ea0, "IPOLSAMMOD"}, /* PolaritySAM Mode activated , */\
+ { 0x4eb0, "IPOLTAPMOD"}, /* Polarity Tap Mode Activated , */\
+ { 0x4ec0, "IPOLTAPTRG"}, /* PolarityTap Comparator Trigger , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery Safeguard release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "BSSAC"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5110, "INTSMUTE"}, /* Soft mute HW , */\
+ { 0x5120, "CFSML"}, /* Soft mute FW left , */\
+ { 0x5130, "CFSM"}, /* Soft mute FW , */\
+ { 0x5140, "HPFBYPL"}, /* Bypass HPF left , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5160, "DPSAL"}, /* Enable DPSA left , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5187, "VOL"}, /* FW volume control for primary audio channel , */\
+ { 0x5200, "HNDSFRCV"}, /* Selection receiver , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5c07, "CFTAPPAT"}, /* Coolflux tap pattern , */\
+ { 0x5c83, "TAPDBGINFO"}, /* Reserved , */\
+ { 0x5d0f, "TATPSTAT1"}, /* Tap Status 1 from CF FW , */\
+ { 0x5f03, "TCOMPTHR"}, /* Comparator threshold (in uV) , */\
+ { 0x6081, "PGAGAIN"}, /* PGA gain selection , */\
+ { 0x6123, "TDMSPKG"}, /* System gain (INPLEV 0) , */\
+ { 0x6505, "LPM1LVL"}, /* low power mode1 detector ctrl threshold for low_audio_lvl , */\
+ { 0x6565, "LPM1HLD"}, /* Low power mode1 detector, ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "LPM1DIS"}, /* low power mode1 detector control , */\
+ { 0x6630, "DCDIS"}, /* DCDC , */\
+ { 0x6801, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6821, "TDMSRCAS"}, /* frame a selection , */\
+ { 0x6841, "TDMSRCBS"}, /* frame b selection , */\
+ { 0x68a0, "ANC1C"}, /* ANC one s complement , */\
+ { 0x6901, "SAMMODE"}, /* Sam mode , */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70c1, "DCINSEL"}, /* DCDC IIR input Selection , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7504, "DCTRIP"}, /* Adaptive boost trip levels 1, effective only when boost_intelligent is set to 1, */\
+ { 0x7554, "DCTRIP2"}, /* Adaptive boost trip level 2, effective only when boost_intelligent is set to 1, */\
+ { 0x75a4, "DCTRIPT"}, /* Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0x9000, "RST"}, /* Reset , */\
+ { 0x9011, "DMEM"}, /* Target memory , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* Memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* Error flags , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xee0f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xef0f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "DCMCCCL"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "USERDEF"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf40f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9912_BITNAMETABLE static tfaBfName_t Tfa9912BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x30, "enbl_amplifier"}, /* Enables the Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x101, "vamp_sel"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "enbl_fro8m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x150, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x160, "enbl_bod"}, /* BOD Enable , */\
+ { 0x170, "enbl_bod_hyst"}, /* BOD Hysteresis , */\
+ { 0x181, "bod_delay"}, /* BOD filter , */\
+ { 0x1a1, "bod_lvlsel"}, /* BOD threshold , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "pwm_sel_rcv_ns"}, /* Noise shaper selection , */\
+ { 0x1f0, "man_enbl_watchdog"}, /* Watchdog enable , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b0, "bypass_hvbat_filter"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "tdm_tfa9872_compatible"}, /* TDM Compatibility with TFA9872 , */\
+ { 0x2d0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x2e0, "enbl_adc10"}, /* ADC10 Enable - I2C direct mode , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x430, "cf_clock_scaling"}, /* Coolflux DSP clock scaling, low power mode , */\
+ { 0x441, "sel_cf_clock"}, /* Coolflux DSP clock scaler selection for low power mode, */\
+ { 0x460, "tdm_intf_sel"}, /* TDM clock selection , */\
+ { 0x470, "disable_auto_sel_refclk"}, /* Disable Automatic dsp clock source selection , */\
+ { 0x480, "sel_clk_src"}, /* I2C selection of DSP clock when auto select is disabled, */\
+ { 0x490, "wdt_tim_clk_src"}, /* I2C selection of Watchdog and Timer clock , */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker path , */\
+ { 0x530, "enbl_volsense"}, /* Voltage sense , */\
+ { 0x550, "enbl_cursense"}, /* Current sense , */\
+ { 0x560, "enbl_pdm_ss"}, /* Sub-system PDM , */\
+ { 0x580, "enbl_pga_chop"}, /* Enable PGA chop clock , */\
+ { 0x590, "enbl_tdm_ss"}, /* Sub-system TDM , */\
+ { 0x5a0, "enbl_bst_ss"}, /* Sub-system boost , */\
+ { 0x5b0, "enbl_adc10_ss"}, /* Sub-system ADC , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x5d0, "enbl_tim_clk"}, /* CF Sub-system timer , */\
+ { 0x5e0, "enbl_wdt_clk"}, /* CF Sub-system WDT , */\
+ { 0x5f0, "faim_enable_vbg"}, /* Over rule of vbg for FaIM access , */\
+ { 0x600, "aux_spkr_sel"}, /* Input selection for TAP/SAM , */\
+ { 0x620, "bypass_tapdec_reset"}, /* Tap decimator reset bypass - Bypass the decimator reset from tapdec, */\
+ { 0x631, "car_dec_in_sel0"}, /* Cardec input 0 sel , */\
+ { 0x651, "car_dec_in_sel1"}, /* Cardec input sel , */\
+ { 0x670, "tapdec_sel"}, /* Select TAP/Cardec for TAP , */\
+ { 0x680, "comp_count"}, /* Comparator o/p filter selection , */\
+ { 0x691, "startup_mode"}, /* Startup Mode Selection , */\
+ { 0x6b0, "enable_auto_tap_switching"}, /* Enable auto tap switching , */\
+ { 0x6c1, "comp_init_time"}, /* Comparator initialization time to be used in Tap Machine, */\
+ { 0x6e1, "ana_init_time"}, /* Analog initialization time to be used in Tap Machine, */\
+ { 0x707, "clkchk_th_hi"}, /* Clock check Higher Threshold , */\
+ { 0x787, "clkchk_th_lo"}, /* Clock check Higher Threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x832, "ctrl_on2tap_criterion"}, /* Amplifier on-off criteria for tap mode entry , */\
+ { 0xd00, "side_tone_gain_sel"}, /* PDM side tone gain selector , */\
+ { 0xd18, "side_tone_gain"}, /* Side tone gain , */\
+ { 0xda0, "mute_side_tone"}, /* Side tone soft mute , */\
+ { 0xdb0, "side_tone_1scomplement"}, /* side tone one s complement , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1060, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10b0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_soft_mute_busy"}, /* side tone (un)mute busy , */\
+ { 0x1180, "flag_soft_mute_state"}, /* side tone mute state , */\
+ { 0x1190, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11a2, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11d0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1340, "flag_clipa_high"}, /* Clipping A to Vddp , */\
+ { 0x1350, "flag_clipa_low"}, /* Clipping A to gnd , */\
+ { 0x1360, "flag_clipb_high"}, /* Clipping B to Vddp , */\
+ { 0x1370, "flag_clipb_low"}, /* Clipping B to gnd , */\
+ { 0x1380, "flag_ocp_alarm"}, /* OCP amplifier , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_tap_comp_trig"}, /* Status Tap comparator triggered , */\
+ { 0x13b0, "flag_cf_tapdetected"}, /* Status Tap detected , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "flag_man_wait_cf_config"}, /* Wait CF config , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x1410, "flag_cf_speakererror"}, /* Speaker status , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1471, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1490, "man_dsp_clk_src"}, /* DSP clock source selected by manager , */\
+ { 0x14a1, "man_startup_mode"}, /* Startup Mode Selected by Manager(Read Only) , */\
+ { 0x14c3, "tap_machine_state"}, /* Tap Machine State , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x17a0, "flag_bst_bstcur_cf"}, /* DCDC current limiting for DSP , */\
+ { 0x2000, "tdm_usecase"}, /* Mode setting , */\
+ { 0x2011, "dio4_input_sel"}, /* DIO4 Input selection , */\
+ { 0x2040, "tdm_enable"}, /* Enable TDM interface , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits in a slot , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "tdm_txdata_format_unused_slot_sd1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "tdm_txdata_format_unused_slot_sd2"}, /* Format unused slots DIO2 , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control gain (channel in 0) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio left (channel in 1 ) , */\
+ { 0x2320, "tdm_sink2_enable"}, /* Control audio right (channel in 2 ) , */\
+ { 0x2330, "tdm_source0_enable"}, /* Current sense , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense , */\
+ { 0x2350, "tdm_source2_enable"}, /* DSP Gainout , */\
+ { 0x2360, "tdm_source3_enable"}, /* DSP 2 , */\
+ { 0x2370, "tdm_source4_enable"}, /* DSP 3 , */\
+ { 0x2380, "tdm_source5_enable"}, /* DSP , */\
+ { 0x2390, "tdm_source6_enable"}, /* Loopback of Audio left (channel 1) , */\
+ { 0x23a0, "tdm_source7_enable"}, /* Loopback of Audio right (channel 2) , */\
+ { 0x2401, "tdm_sink0_io"}, /* IO gainin , */\
+ { 0x2421, "tdm_sink1_io"}, /* IO audio left , */\
+ { 0x2441, "tdm_sink2_io"}, /* IO audio right , */\
+ { 0x2461, "tdm_source0_io"}, /* IO Current Sense , */\
+ { 0x2481, "tdm_source1_io"}, /* IO voltage sense , */\
+ { 0x24a1, "tdm_source2_io"}, /* IO gain out , */\
+ { 0x24c1, "tdm_source3_io"}, /* IO DSP 2 , */\
+ { 0x24e1, "tdm_source4_io"}, /* IO DSP 3 , */\
+ { 0x2501, "tdm_source5_io"}, /* IO DSP , */\
+ { 0x2521, "tdm_source6_io"}, /* IO Source 6 , */\
+ { 0x2541, "tdm_source7_io"}, /* IO Source 7 , */\
+ { 0x2603, "tdm_sink0_slot"}, /* Control gainin , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for audio left (channel 1) , */\
+ { 0x2683, "tdm_sink2_slot"}, /* tdm slot for audio right (channel 2) , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of Current Sense Out , */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense , */\
+ { 0x2743, "tdm_source2_slot"}, /* Slot Position of GAIN out , */\
+ { 0x2783, "tdm_source3_slot"}, /* Slot Position DSPout2 , */\
+ { 0x27c3, "tdm_source4_slot"}, /* Slot Position DSPout3 , */\
+ { 0x2803, "tdm_source5_slot"}, /* Slot Position of DSPout , */\
+ { 0x2843, "tdm_source6_slot"}, /* Slot Position of loopback channel left , */\
+ { 0x2883, "tdm_source7_slot"}, /* Slot Position of loopback channel right , */\
+ { 0x2901, "tdm_txdata_format_unused_slot_sd3"}, /* Format unused slots D3 , */\
+ { 0x3100, "pdm_mode"}, /* PDM control , */\
+ { 0x3110, "pdm_input_sel"}, /* PDM Decimator input selection , */\
+ { 0x3120, "enbl_pdm_side_tone"}, /* Side tone input enable , */\
+ { 0x3201, "pdm_nbck"}, /* PDM BCK/Fs ratio , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_pll_lock"}, /* Status PLL lock , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ovpok"}, /* Status OVP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_clocks_stable"}, /* Status clocks stable , */\
+ { 0x4060, "int_out_flag_mtp_busy"}, /* Status MTP busy , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cf_speakererror"}, /* Status speaker error , */\
+ { 0x4090, "int_out_flag_cold_started"}, /* Status cold start , */\
+ { 0x40a0, "int_out_flag_engage"}, /* Status amplifier engage , */\
+ { 0x40b0, "int_out_flag_watchdog_reset"}, /* Status watchdog , */\
+ { 0x40c0, "int_out_flag_enbl_amp"}, /* Status amplifier enable , */\
+ { 0x40d0, "int_out_flag_enbl_ref"}, /* Status Ref enable , */\
+ { 0x40e0, "int_out_flag_adc10_ready"}, /* Status Control ADC , */\
+ { 0x40f0, "int_out_flag_bod_vddd_nok"}, /* Status BOD , */\
+ { 0x4100, "int_out_flag_bst_bstcur"}, /* Status DCDC current limiting , */\
+ { 0x4110, "int_out_flag_bst_hiz"}, /* Status DCDC active , */\
+ { 0x4120, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4130, "int_out_flag_bst_peakcur"}, /* Status bst peakcur , */\
+ { 0x4140, "int_out_flag_bst_voutcomp"}, /* Status DCDC level 1x , */\
+ { 0x4150, "int_out_flag_bst_voutcomp86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "int_out_flag_bst_voutcomp93"}, /* Status DCDC level 1.07x , */\
+ { 0x4190, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x41a0, "int_out_flag_man_wait_src_settings"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "int_out_flag_man_wait_cf_config"}, /* Status waits CF config , */\
+ { 0x41c0, "int_out_flag_man_start_mute_audio"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x41e0, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x41f0, "int_out_flag_clk_out_of_range"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4220, "int_out_flag_clip"}, /* Status clip , */\
+ { 0x4250, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 , */\
+ { 0x4260, "int_out_flag_low_amplitude"}, /* Status low amplitude detection , */\
+ { 0x4270, "int_out_flag_vddp_gt_vbat"}, /* Status VDDP greater than VBAT , */\
+ { 0x4280, "int_out_newtap"}, /* Status Tap detected , */\
+ { 0x4290, "int_out_audiomodeactive"}, /* Status Audio Mode activated , */\
+ { 0x42a0, "int_out_sammodeactive"}, /* Status SAM Mode activated , */\
+ { 0x42b0, "int_out_tapmodeactive"}, /* Status Tap Mode Activated , */\
+ { 0x42c0, "int_out_flag_tap_comp_trig"}, /* Status Tap comparator triggered , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_pll_lock"}, /* Clear PLL lock , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ovpok"}, /* Clear OVP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_clocks_stable"}, /* Clear clocks stable , */\
+ { 0x4460, "int_in_flag_mtp_busy"}, /* Clear mtp busy , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cf_speakererror"}, /* Clear speaker error , */\
+ { 0x4490, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44a0, "int_in_flag_engage"}, /* Clear amplifier engage , */\
+ { 0x44b0, "int_in_flag_watchdog_reset"}, /* Clear watchdog , */\
+ { 0x44c0, "int_in_flag_enbl_amp"}, /* Clear enbl amp , */\
+ { 0x44d0, "int_in_flag_enbl_ref"}, /* Clear ref enable , */\
+ { 0x44e0, "int_in_flag_adc10_ready"}, /* Clear control ADC , */\
+ { 0x44f0, "int_in_flag_bod_vddd_nok"}, /* Clear BOD , */\
+ { 0x4500, "int_in_flag_bst_bstcur"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "int_in_flag_bst_hiz"}, /* Clear DCDC active , */\
+ { 0x4520, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4530, "int_in_flag_bst_peakcur"}, /* Clear bst peakcur , */\
+ { 0x4540, "int_in_flag_bst_voutcomp"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "int_in_flag_bst_voutcomp86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "int_in_flag_bst_voutcomp93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4590, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x45a0, "int_in_flag_man_wait_src_settings"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "int_in_flag_man_wait_cf_config"}, /* Clear wait cf config , */\
+ { 0x45c0, "int_in_flag_man_start_mute_audio"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x45e0, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x45f0, "int_in_flag_clk_out_of_range"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4620, "int_in_flag_clip"}, /* Clear clip , */\
+ { 0x4650, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 , */\
+ { 0x4660, "int_in_flag_low_amplitude"}, /* Clear low amplitude detection , */\
+ { 0x4670, "int_in_flag_vddp_gt_vbat"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4680, "int_in_newtap"}, /* Clear Tap detected , */\
+ { 0x4690, "int_in_audiomodeactive"}, /* Clear Audio Mode activated , */\
+ { 0x46a0, "int_in_sammodeactive"}, /* Clear SAM Mode activated , */\
+ { 0x46b0, "int_in_tapmodeactive"}, /* Clear Tap Mode Activated , */\
+ { 0x46c0, "int_in_flag_tap_comp_trig"}, /* Clear Comparator Interrupt , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_pll_lock"}, /* Enable pll lock , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ovpok"}, /* Enable OVP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_clocks_stable"}, /* Enable clocks stable , */\
+ { 0x4860, "int_enable_flag_mtp_busy"}, /* Enable mtp busy , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cf_speakererror"}, /* Enable speaker error , */\
+ { 0x4890, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48a0, "int_enable_flag_engage"}, /* Enable amplifier engage , */\
+ { 0x48b0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog , */\
+ { 0x48c0, "int_enable_flag_enbl_amp"}, /* Enable enbl amp , */\
+ { 0x48d0, "int_enable_flag_enbl_ref"}, /* Enable ref enable , */\
+ { 0x48e0, "int_enable_flag_adc10_ready"}, /* Enable Control ADC , */\
+ { 0x48f0, "int_enable_flag_bod_vddd_nok"}, /* Enable BOD , */\
+ { 0x4900, "int_enable_flag_bst_bstcur"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "int_enable_flag_bst_hiz"}, /* Enable DCDC active , */\
+ { 0x4920, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4930, "int_enable_flag_bst_peakcur"}, /* Enable bst peakcur , */\
+ { 0x4940, "int_enable_flag_bst_voutcomp"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "int_enable_flag_bst_voutcomp86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "int_enable_flag_bst_voutcomp93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4990, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x49a0, "int_enable_flag_man_wait_src_settings"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "int_enable_flag_man_wait_cf_config"}, /* Enable man wait cf config , */\
+ { 0x49c0, "int_enable_flag_man_start_mute_audio"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x49e0, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x49f0, "int_enable_flag_clk_out_of_range"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4a20, "int_enable_flag_clip"}, /* Enable clip , */\
+ { 0x4a50, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "int_enable_flag_low_amplitude"}, /* Enable low amplitude detection , */\
+ { 0x4a70, "int_enable_flag_vddp_gt_vbat"}, /* Enable VDDP greater than VBAT , */\
+ { 0x4a80, "int_enable_newtap"}, /* Enable Tap detected , */\
+ { 0x4a90, "int_enable_audiomodeactive"}, /* Enable Audio Mode activated , */\
+ { 0x4aa0, "int_enable_sammodeactive"}, /* Enable SAM Mode activated , */\
+ { 0x4ab0, "int_enable_tapmodeactive"}, /* Enable Tap Mode Activated , */\
+ { 0x4ac0, "int_enable_flag_tap_comp_trig"}, /* Enable comparator interrupt , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_pll_lock"}, /* Polarity pll lock , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ovpok"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_clocks_stable"}, /* Polarity clocks stable , */\
+ { 0x4c60, "int_polarity_flag_mtp_busy"}, /* Polarity mtp busy , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cf_speakererror"}, /* Polarity speaker error , */\
+ { 0x4c90, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4ca0, "int_polarity_flag_engage"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog , */\
+ { 0x4cc0, "int_polarity_flag_enbl_amp"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "int_polarity_flag_enbl_ref"}, /* Polarity ref enable , */\
+ { 0x4ce0, "int_polarity_flag_adc10_ready"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity BOD , */\
+ { 0x4d00, "int_polarity_flag_bst_bstcur"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "int_polarity_flag_bst_hiz"}, /* Polarity DCDC active , */\
+ { 0x4d20, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "int_polarity_flag_bst_peakcur"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "int_polarity_flag_bst_voutcomp"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "int_polarity_flag_bst_voutcomp86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "int_polarity_flag_bst_voutcomp93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d90, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "int_polarity_flag_man_wait_src_settings"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "int_polarity_flag_man_wait_cf_config"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "int_polarity_flag_man_start_mute_audio"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4de0, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4df0, "int_polarity_flag_clk_out_of_range"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4e20, "int_polarity_flag_clip"}, /* Polarity clip , */\
+ { 0x4e50, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "int_polarity_flag_low_amplitude"}, /* Polarity low amplitude detection , */\
+ { 0x4e70, "int_polarity_flag_vddp_gt_vbat"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x4e80, "int_polarity_newtap"}, /* PolarityTap detected , */\
+ { 0x4e90, "int_polarity_audiomodeactive"}, /* PolarityAudio Mode activated , */\
+ { 0x4ea0, "int_polarity_sammodeactive"}, /* PolaritySAM Mode activated , */\
+ { 0x4eb0, "int_polarity_tapmodeactive"}, /* Polarity Tap Mode Activated , */\
+ { 0x4ec0, "int_polarity_flag_tap_comp_trig"}, /* PolarityTap Comparator Trigger , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery Safeguard release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5110, "soft_mute"}, /* Soft mute HW , */\
+ { 0x5130, "cf_mute"}, /* Soft mute FW , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5187, "cf_volume"}, /* FW volume control for primary audio channel , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for Battery Safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "enbl_low_latency"}, /* CF low latency outputs for add module , */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5582, "dpsa_drive"}, /* Drive setting (bin. coded) - I2C direct mode , */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually , */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop - I2C direct mode, */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x5c07, "flag_cf_tap_pattern"}, /* Coolflux tap pattern , */\
+ { 0x5c83, "tap_debug_info"}, /* Reserved , */\
+ { 0x5d0f, "tap_status_1"}, /* Tap Status 1 from CF FW , */\
+ { 0x5f03, "tap_comp_threshold"}, /* Comparator threshold (in uV) , */\
+ { 0x6081, "pga_gain_set"}, /* PGA gain selection , */\
+ { 0x60b0, "pga_lowpass_enable"}, /* Lowpass enable , */\
+ { 0x60c0, "pga_pwr_enable"}, /* PGA power enable , */\
+ { 0x60d0, "pga_switch_enable"}, /* PGA switch enable , */\
+ { 0x60e0, "pga_switch_aux_enable"}, /* Switch enable aux , */\
+ { 0x6123, "ctrl_att"}, /* System gain (INPLEV 0) , */\
+ { 0x6265, "zero_lvl"}, /* ctrl threshold for zero X-ing , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* ctrl threshold for low_audio_lvl , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 detector ctrl threshold for zero X-ing , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode1 detector ctrl select mode , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 detector ctrl threshold for low_audio_lvl , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector, ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6630, "dcdcoff_mode"}, /* DCDC , */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage - direct ctrl , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtered vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6801, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6821, "tdm_sourcea_frame_sel"}, /* frame a selection , */\
+ { 0x6841, "tdm_sourceb_frame_sel"}, /* frame b selection , */\
+ { 0x6901, "sam_mode"}, /* Sam mode , */\
+ { 0x6931, "pdmdat_h_sel"}, /* pdm out value when pdm_clk is higth , */\
+ { 0x6951, "pdmdat_l_sel"}, /* pdm out value when pdm_clk is low , */\
+ { 0x6970, "cs_sam_set"}, /* Enable SAM input for current sense - I2C Direct Mode, */\
+ { 0x6980, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x6990, "sam_spkr_sel"}, /* SAM o/p sel during SAM and audio , */\
+ { 0x6b00, "disable_engage"}, /* Disable auto engage , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c60, "sel_clip_pwms"}, /* To select clip-flags , */\
+ { 0x6c72, "pwms_clip_lvl"}, /* To set the amount of pwm pulse that may be skipped before clip-flag is triggered. , */\
+ { 0x6ca5, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70c1, "dcdc_sel"}, /* DCDC IIR input Selection , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current - I2C direct mode, */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller - I2C direct mode, */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator - I2C direct mode , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current - I2C direct mode , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage - I2C direct mode , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac - I2C direct mode , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators - I2C direct mode , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators - I2C direct mode , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators - I2C direct mode , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac - I2C direct mode , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac - I2C direct mode, */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Ignore flag_voutcomp86 , */\
+ { 0x7504, "boost_trip_lvl_1st"}, /* Adaptive boost trip levels 1, effective only when boost_intelligent is set to 1, */\
+ { 0x7554, "boost_trip_lvl_2nd"}, /* Adaptive boost trip level 2, effective only when boost_intelligent is set to 1, */\
+ { 0x75a4, "boost_trip_lvl_track"}, /* Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x7602, "track_decay"}, /* DCDC Boost decay speed after a peak value, effective only when boost_track is set to 1, */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7720, "pga_test_ldo_bypass"}, /* bypass internal PGA LDO , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8200, "enbl_cmfb"}, /* Current sense common mode feedback control , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8222, "cmfb_gain"}, /* Current sense common mode feedback control gain , */\
+ { 0x8256, "cmfb_offset"}, /* Current sense common mode feedback control offset , */\
+ { 0x8305, "cs_ktemp"}, /* First order temperature compensation coefficient , */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC - I2C direct mode , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 - I2C direct mode, */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 - I2C direct mode, */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 - I2C direct mode, */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO - I2C direct mode , */\
+ { 0x8760, "enbl_cs_nofloating_n"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8770, "enbl_cs_nofloating_p"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO -- I2C direct mode , */\
+ { 0x8800, "volsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0x8810, "vol_cur_sense_dc_offset"}, /* voltage and current sense decimator offset control, */\
+ { 0x8902, "cursense_comp_delay"}, /* To align compensation signal with current sense signal, */\
+ { 0x8930, "cursense_comp_sign"}, /* To change polarity of compensation for current sense compensation, */\
+ { 0x8940, "enbl_cursense_comp"}, /* To enable current sense compensation , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset , */\
+ { 0x9011, "cf_dmem"}, /* Target memory , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* Memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* Error flags , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the FaIM controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the FaIM are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the FaIM are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually - - I2C direct mode, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high - I2C direct mode, */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc130, "tap_comp_enable"}, /* Tap Comparator enable control - I2C direct mode , */\
+ { 0xc140, "tap_comp_switch_enable"}, /* Tap Comparator Switch enable control - I2C direct mode, */\
+ { 0xc150, "tap_comp_switch_aux_enable"}, /* Tap Comparator Switch enable control - I2C direct mode, */\
+ { 0xc161, "tap_comp_test_enable"}, /* Comparator threshold - fine value , */\
+ { 0xc180, "curdist_enable"}, /* Enable control - I2C direct mode , */\
+ { 0xc190, "vbg2i_enbl"}, /* Enable control - I2C direct mode , */\
+ { 0xc1a0, "bg_filt_bypass_enbl"}, /* Enable control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* FFT Coolflux , */\
+ { 0xc3e0, "test_pwr_switch"}, /* Test mode for digital power switches core sw/mem sw/micvdd sw, */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc560, "bypass_fro8"}, /* Bypass fro8 with pdm_clk , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc5b0, "pga_test_enable"}, /* Enable PGA test mode , */\
+ { 0xc5c0, "pga_test_offset_enable"}, /* Enable PGA test offset , */\
+ { 0xc5d0, "pga_test_shortinput_enable"}, /* Enable PGA test short input , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc660, "enbl_powerswitch"}, /* Vddd core power switch control - overrules the manager control, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DIO4 (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to DIO3 (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to TDO (see Digimux list for details), */\
+ { 0xc901, "dio1_ehs"}, /* Speed/load setting for DIO1 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc921, "dio2_ehs"}, /* Speed/load setting for DIO2 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc941, "dio3_ehs"}, /* Speed/load setting for DIO3 cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc961, "dio4_ehs"}, /* Speed/load setting for DIO4 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc981, "spdmo_ehs"}, /* Speed/load setting for PDMO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9a1, "tdo_ehs"}, /* Speed/load setting for TDM IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "int_ehs"}, /* Slew Rate INT IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xc9d0, "pdmclk_ehs"}, /* Slew RateBCK2/PDMCLK IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xc9e0, "fs2_ehs"}, /* Slew Rate DS2 IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xc9f0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb54, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba4, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcc05, "pll_seli_lbw"}, /* PLL SELI - Low B/W PLL control mode or I2C direct PLL control mode only, */\
+ { 0xcc64, "pll_selp_lbw"}, /* PLL SELP - Low B/W PLL control mode or I2C direct PLL control mode only, */\
+ { 0xccb3, "pll_selr_lbw"}, /* PLL SELR - Low B/W PLL control mode or I2C direct PLL control mode only, */\
+ { 0xccf0, "sel_user_pll_bw"}, /* PLL Low Bandwidth Mode control , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_fro8"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_range_chk"}, /* Clock out of range , */\
+ { 0xd601, "clkdiv_dsp_sel"}, /* DSP clock divider selection in direct clock control mode, */\
+ { 0xd621, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd641, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd661, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd681, "dsp_tap_clk"}, /* Dsp clock frequency selection in TAP mode; , */\
+ { 0xd6a1, "sel_wdt_clk"}, /* Watch dog clock post divider value , */\
+ { 0xd6c1, "sel_tim_clk"}, /* Timer clock post divider value , */\
+ { 0xd700, "ads1_ehs"}, /* Slew Rate ADS1 IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xd710, "ads2_ehs"}, /* Slew Rate ADS2 IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost - I2C direct mode , */\
+ { 0xd8a1, "force_pga_clock"}, /* force pga clock , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xd900, "overrules_usercase"}, /* Overrule Mode control use , */\
+ { 0xd910, "ovr_switch_ref"}, /* Overrule Value , */\
+ { 0xd920, "ovr_enbl_pll"}, /* Overrule Value , */\
+ { 0xd930, "ovr_switch_amp"}, /* Overrule Value , */\
+ { 0xd940, "ovr_enbl_clk_cs"}, /* Overrule Value , */\
+ { 0xd951, "ovr_sel_clk_cs"}, /* CS clock selection overrule , */\
+ { 0xd970, "ovr_switch_cs"}, /* Overrule Value , */\
+ { 0xd980, "ovr_enbl_csvs_ss"}, /* Overrule Value , */\
+ { 0xd990, "ovr_enbl_comp"}, /* Overrule Value , */\
+ { 0xed00, "enbl_fro8cal"}, /* Enable FRO calibration , */\
+ { 0xed10, "start_fro8_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xed20, "fro8_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xed45, "fro8_auto_trim_val"}, /* Calibration value from Auto Calibration block, to be written into MTP - Read Only, */\
+ { 0xee0f, "sw_profile"}, /* Software profile data , */\
+ { 0xef0f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "spare_mtp1_9_6"}, /* HW gain module - left channel (2's complement) , */\
+ { 0xf1a5, "spare_mtp1_15_10"}, /* Offset for amplifier, HW gain module - left channel (2's complement), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a3, "spare_mtp2_13_10"}, /* Trimming of LDO (2.7V) , */\
+ { 0xf307, "spare_mtp3_7_0"}, /* SPARE , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "calibr_R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xf50f, "spare_mtp5_15_0"}, /* SPARE , */\
+ { 0xf600, "mtp_lock_enbl_coolflux"}, /* Disable function dcdcoff_mode , */\
+ { 0xf610, "mtp_pwm_delay_enbl_clk_auto_gating"}, /* Auto clock gating on pwm_delay , */\
+ { 0xf620, "mtp_ocp_enbl_clk_auto_gating"}, /* Auto clock gating on module ocp , */\
+ { 0xf630, "mtp_disable_clk_a_gating"}, /* Disable clock_a gating , */\
+ { 0xf642, "spare_mtp6_6_3"}, /* SPARE , */\
+ { 0xf686, "spare_mtp6_14_8"}, /* Offset of left amplifier level shifter B , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf910, "disable_sam_mode"}, /* Disable sam mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Disable programming of max dcdc boost voltage , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf987, "type_bits_fw"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro8_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro8_short_nwell_r"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro8_boost_i"}, /* Self bias current selection , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9912_irq {
+ tfa9912_irq_stvdds = 0,
+ tfa9912_irq_stplls = 1,
+ tfa9912_irq_stotds = 2,
+ tfa9912_irq_stovds = 3,
+ tfa9912_irq_stuvds = 4,
+ tfa9912_irq_stclks = 5,
+ tfa9912_irq_stmtpb = 6,
+ tfa9912_irq_stnoclk = 7,
+ tfa9912_irq_stspks = 8,
+ tfa9912_irq_stacs = 9,
+ tfa9912_irq_stsws = 10,
+ tfa9912_irq_stwds = 11,
+ tfa9912_irq_stamps = 12,
+ tfa9912_irq_starefs = 13,
+ tfa9912_irq_stadccr = 14,
+ tfa9912_irq_stbodnok = 15,
+ tfa9912_irq_stbstcu = 16,
+ tfa9912_irq_stbsthi = 17,
+ tfa9912_irq_stbstoc = 18,
+ tfa9912_irq_stbstpkcur = 19,
+ tfa9912_irq_stbstvc = 20,
+ tfa9912_irq_stbst86 = 21,
+ tfa9912_irq_stbst93 = 22,
+ tfa9912_irq_strcvld = 23,
+ tfa9912_irq_stocpl = 24,
+ tfa9912_irq_stocpr = 25,
+ tfa9912_irq_stmwsrc = 26,
+ tfa9912_irq_stmwcfc = 27,
+ tfa9912_irq_stmwsmu = 28,
+ tfa9912_irq_stcfmer = 29,
+ tfa9912_irq_stcfmac = 30,
+ tfa9912_irq_stclkoor = 31,
+ tfa9912_irq_sttdmer = 32,
+ tfa9912_irq_stclpl = 33,
+ tfa9912_irq_stclpr = 34,
+ tfa9912_irq_stocpm = 35,
+ tfa9912_irq_stlp1 = 37,
+ tfa9912_irq_stla = 38,
+ tfa9912_irq_stvddp = 39,
+ tfa9912_irq_sttapdet = 40,
+ tfa9912_irq_staudmod = 41,
+ tfa9912_irq_stsammod = 42,
+ tfa9912_irq_sttapmod = 43,
+ tfa9912_irq_sttaptrg = 44,
+ tfa9912_irq_max = 45,
+ tfa9912_irq_all = -1 /* all irqs */};
+
+#define TFA9912_IRQ_NAMETABLE static tfaIrqName_t Tfa9912IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STPLLS"},\
+ { 2, "STOTDS"},\
+ { 3, "STOVDS"},\
+ { 4, "STUVDS"},\
+ { 5, "STCLKS"},\
+ { 6, "STMTPB"},\
+ { 7, "STNOCLK"},\
+ { 8, "STSPKS"},\
+ { 9, "STACS"},\
+ { 10, "STSWS"},\
+ { 11, "STWDS"},\
+ { 12, "STAMPS"},\
+ { 13, "STAREFS"},\
+ { 14, "STADCCR"},\
+ { 15, "STBODNOK"},\
+ { 16, "STBSTCU"},\
+ { 17, "STBSTHI"},\
+ { 18, "STBSTOC"},\
+ { 19, "STBSTPKCUR"},\
+ { 20, "STBSTVC"},\
+ { 21, "STBST86"},\
+ { 22, "STBST93"},\
+ { 23, "STRCVLD"},\
+ { 24, "STOCPL"},\
+ { 25, "STOCPR"},\
+ { 26, "STMWSRC"},\
+ { 27, "STMWCFC"},\
+ { 28, "STMWSMU"},\
+ { 29, "STCFMER"},\
+ { 30, "STCFMAC"},\
+ { 31, "STCLKOOR"},\
+ { 32, "STTDMER"},\
+ { 33, "STCLPL"},\
+ { 34, "STCLPR"},\
+ { 35, "STOCPM"},\
+ { 36, "36"},\
+ { 37, "STLP1"},\
+ { 38, "STLA"},\
+ { 39, "STVDDP"},\
+ { 40, "STTAPDET"},\
+ { 41, "STAUDMOD"},\
+ { 42, "STSAMMOD"},\
+ { 43, "STTAPMOD"},\
+ { 44, "STTAPTRG"},\
+ { 45, "45"},\
+};
+#endif /* _TFA9912_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_container.c b/sound/soc/codecs/tfa98xx-downstream/tfa_container.c
new file mode 100644
index 00000000000..44ba073d69e
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_container.c
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include "dbgprint.h"
+#include "tfa_container.h"
+#include "tfa.h"
+#include "tfa98xx_tfafieldnames.h"
+#include "tfa_internal.h"
+
+ /* defines */
+#define MODULE_BIQUADFILTERBANK 2
+#define BIQUAD_COEFF_SIZE 6
+
+/* module globals */
+static uint8_t gslave_address = 0; /* This is used to SET the slave with the --slave option */
+
+static int float_to_int(uint32_t x)
+{
+ unsigned e = (0x7F + 31) - ((*(unsigned *)&x & 0x7F800000) >> 23);
+ unsigned m = 0x80000000 | (*(unsigned *)&x << 8);
+ return -(int)((m >> e) & -(e < 32));
+}
+
+/*
+ * check the container file
+*/
+enum tfa_error tfa_load_cnt(void *cnt, int length)
+{
+ TfaContainer_t *cntbuf = (TfaContainer_t *)cnt;
+
+ if (length > TFA_MAX_CNT_LENGTH) {
+ pr_err("incorrect length\n");
+ return tfa_error_container;
+ }
+
+ if (HDR(cntbuf->id[0], cntbuf->id[1]) == 0) {
+ pr_err("header is 0\n");
+ return tfa_error_container;
+ }
+
+ if ((HDR(cntbuf->id[0], cntbuf->id[1])) != paramsHdr) {
+ pr_err("wrong header type: 0x%02x 0x%02x\n", cntbuf->id[0], cntbuf->id[1]);
+ return tfa_error_container;
+ }
+
+ if (cntbuf->size == 0) {
+ pr_err("data size is 0\n");
+ return tfa_error_container;
+ }
+
+ /* check CRC */
+ if (tfaContCrcCheckContainer(cntbuf)) {
+ pr_err("CRC error\n");
+ return tfa_error_container;
+ }
+
+ /* check sub version level */
+ if ((cntbuf->subversion[1] != TFA_PM_SUBVERSION) &&
+ (cntbuf->subversion[0] != '0')) {
+ pr_err("container sub-version not supported: %c%c\n",
+ cntbuf->subversion[0], cntbuf->subversion[1]);
+ return tfa_error_container;
+ }
+
+ return tfa_error_ok;
+}
+
+/*
+ * Dump the contents of the file header
+ */
+void tfaContShowHeader(TfaHeader_t *hdr) {
+ char _id[2];
+
+ pr_debug("File header\n");
+
+ _id[1] = hdr->id >> 8;
+ _id[0] = hdr->id & 0xff;
+ pr_debug("\tid:%.2s version:%.2s subversion:%.2s\n", _id,
+ hdr->version, hdr->subversion);
+ pr_debug("\tsize:%d CRC:0x%08x \n", hdr->size, hdr->CRC);
+ pr_debug("\tcustomer:%.8s application:%.8s type:%.8s\n", hdr->customer,
+ hdr->application, hdr->type);
+}
+
+/*
+ * return device list dsc from index
+ */
+TfaDeviceList_t *tfaContGetDevList(TfaContainer_t *cont, int dev_idx)
+{
+ uint8_t *base = (uint8_t *)cont;
+
+ if (cont == NULL)
+ return NULL;
+
+ if ((dev_idx < 0) || (dev_idx >= cont->ndev))
+ return NULL;
+
+ if (cont->index[dev_idx].type != dscDevice)
+ return NULL;
+
+ base += cont->index[dev_idx].offset;
+ return (TfaDeviceList_t *)base;
+}
+
+/*
+ * get the Nth profile for the Nth device
+ */
+TfaProfileList_t *tfaContGetDevProfList(TfaContainer_t * cont, int devIdx, int profIdx)
+{
+ TfaDeviceList_t *dev;
+ int idx, hit;
+ uint8_t *base = (uint8_t *)cont;
+
+ dev = tfaContGetDevList(cont, devIdx);
+ if (dev) {
+ for (idx = 0, hit = 0; idx < dev->length; idx++) {
+ if (dev->list[idx].type == dscProfile) {
+ if (profIdx == hit++)
+ return (TfaProfileList_t *)(dev->list[idx].offset + base);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * get the number of profiles for the Nth device
+ */
+int tfa_cnt_get_dev_nprof(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev;
+ int idx, nprof = 0;
+
+ if (tfa->cnt == NULL)
+ return 0;
+
+ if ((tfa->dev_idx < 0) || (tfa->dev_idx >= tfa->cnt->ndev))
+ return 0;
+
+ dev = tfaContGetDevList(tfa->cnt, tfa->dev_idx);
+ if (dev) {
+ for (idx = 0; idx < dev->length; idx++) {
+ if (dev->list[idx].type == dscProfile) {
+ nprof++;
+ }
+ }
+ }
+
+ return nprof;
+}
+
+/*
+ * get the Nth lifedata for the Nth device
+ */
+TfaLiveDataList_t *tfaContGetDevLiveDataList(TfaContainer_t * cont, int devIdx,
+ int lifeDataIdx)
+{
+ TfaDeviceList_t *dev;
+ int idx, hit;
+ uint8_t *base = (uint8_t *)cont;
+
+ dev = tfaContGetDevList(cont, devIdx);
+ if (dev) {
+ for (idx = 0, hit = 0; idx < dev->length; idx++) {
+ if (dev->list[idx].type == dscLiveData) {
+ if (lifeDataIdx == hit++)
+ return (TfaLiveDataList_t *)
+ (dev->list[idx].offset + base);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Get the max volume step associated with Nth profile for the Nth device
+ */
+int tfacont_get_max_vstep(struct tfa_device *tfa, int prof_idx) {
+ TfaVolumeStep2File_t *vp;
+ struct TfaVolumeStepMax2File *vp3;
+ int vstep_count = 0;
+ vp = (TfaVolumeStep2File_t *)tfacont_getfiledata(tfa, prof_idx, volstepHdr);
+ if (vp == NULL)
+ return 0;
+ /* check the header type to load different NrOfVStep appropriately */
+ if (tfa->tfa_family == 2) {
+ /* this is actually tfa2, so re-read the buffer*/
+ vp3 = (struct TfaVolumeStepMax2File *)
+ tfacont_getfiledata(tfa, prof_idx, volstepHdr);
+ if (vp3) {
+ vstep_count = vp3->NrOfVsteps;
+ }
+ }
+ else {
+ /* this is max1*/
+ if (vp) {
+ vstep_count = vp->vsteps;
+ }
+ }
+ return vstep_count;
+}
+
+/**
+ * Get the file contents associated with the device or profile
+ * Search within the device tree, if not found, search within the profile
+ * tree. There can only be one type of file within profile or device.
+ */
+TfaFileDsc_t *tfacont_getfiledata(struct tfa_device *tfa, int prof_idx, enum TfaHeaderType type)
+{
+ TfaDeviceList_t *dev;
+ TfaProfileList_t *prof;
+ TfaFileDsc_t *file;
+ TfaHeader_t *hdr;
+ unsigned int i;
+
+ if (tfa->cnt == NULL) {
+ pr_err("invalid pointer to container file\n");
+ return NULL;
+ }
+
+ dev = tfaContGetDevList(tfa->cnt, tfa->dev_idx);
+ if (dev == NULL) {
+ pr_err("invalid pointer to container file device list\n");
+ return NULL;
+ }
+
+ /* process the device list until a file type is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ if (file != NULL) {
+ hdr = (TfaHeader_t *)file->data;
+ /* check for file type */
+ if (hdr->id == type) {
+ return (TfaFileDsc_t *)&file->data;
+ }
+ }
+ }
+ }
+
+ /* File not found in device tree.
+ * So, look in the profile list until the file type is encountered
+ */
+ prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ if (prof == NULL) {
+ pr_err("invalid pointer to container file profile list\n");
+ return NULL;
+ }
+
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (file != NULL) {
+ hdr = (TfaHeader_t *)file->data;
+ if (hdr != NULL) {
+ /* check for file type */
+ if (hdr->id == type) {
+ return (TfaFileDsc_t *)&file->data;
+ }
+ }
+ }
+ }
+ }
+
+ if (tfa->verbose)
+ pr_debug("%s: no file found of type %d\n", __FUNCTION__, type);
+
+ return NULL;
+}
+
+/*
+ * write a parameter file to the device
+ */
+static enum Tfa98xx_Error tfaContWriteVstep(struct tfa_device *tfa, TfaVolumeStep2File_t *vp, int vstep)
+{
+ enum Tfa98xx_Error err;
+ unsigned short vol;
+
+ if (vstep < vp->vsteps) {
+ /* vol = (unsigned short)(voldB / (-0.5f)); */
+ vol = (unsigned short)(-2 * float_to_int(*((uint32_t *)&vp->vstep[vstep].attenuation)));
+ if (vol > 255) /* restricted to 8 bits */
+ vol = 255;
+
+ err = tfa98xx_set_volume_level(tfa, vol);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+
+ err = tfa98xx_dsp_write_preset(tfa, sizeof(vp->vstep[0].preset), vp->vstep[vstep].preset);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+ err = tfa_cont_write_filterbank(tfa, vp->vstep[vstep].filter);
+
+ }
+ else {
+ pr_err("Incorrect volume given. The value vstep[%d] >= %d\n", vstep, vp->vsteps);
+ err = Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose) pr_debug("vstep[%d][%d]\n", tfa->dev_idx, vstep);
+
+ return err;
+}
+
+static struct TfaVolumeStepMessageInfo *
+tfaContGetmsgInfoFromReg(struct TfaVolumeStepRegisterInfo *regInfo)
+{
+ char *p = (char*)regInfo;
+ p += sizeof(regInfo->NrOfRegisters) + (regInfo->NrOfRegisters * sizeof(uint32_t));
+ return (struct TfaVolumeStepMessageInfo*) p;
+}
+
+static int
+tfaContGetmsgLen(struct TfaVolumeStepMessageInfo *msgInfo)
+{
+ return (msgInfo->MessageLength.b[0] << 16) + (msgInfo->MessageLength.b[1] << 8) + msgInfo->MessageLength.b[2];
+}
+
+static struct TfaVolumeStepMessageInfo *
+tfaContGetNextmsgInfo(struct TfaVolumeStepMessageInfo *msgInfo)
+{
+ char *p = (char*)msgInfo;
+ int msgLen = tfaContGetmsgLen(msgInfo);
+ int type = msgInfo->MessageType;
+
+ p += sizeof(msgInfo->MessageType) + sizeof(msgInfo->MessageLength);
+ if (type == 3)
+ p += msgLen;
+ else
+ p += msgLen * 3;
+
+ return (struct TfaVolumeStepMessageInfo*) p;
+}
+
+static struct TfaVolumeStepRegisterInfo*
+tfaContGetNextRegFromEndInfo(struct TfaVolumeStepMessageInfo *msgInfo)
+{
+ char *p = (char*)msgInfo;
+ p += sizeof(msgInfo->NrOfMessages);
+ return (struct TfaVolumeStepRegisterInfo*) p;
+
+}
+
+static struct TfaVolumeStepRegisterInfo*
+tfaContGetRegForVstep(TfaVolumeStepMax2File_t *vp, int idx)
+{
+ int i, j, nrMessage;
+
+ struct TfaVolumeStepRegisterInfo *regInfo
+ = (struct TfaVolumeStepRegisterInfo*) vp->vstepsBin;
+ struct TfaVolumeStepMessageInfo *msgInfo = NULL;
+
+ for (i = 0; i < idx; i++) {
+ msgInfo = tfaContGetmsgInfoFromReg(regInfo);
+ nrMessage = msgInfo->NrOfMessages;
+
+ for (j = 0; j < nrMessage; j++) {
+ msgInfo = tfaContGetNextmsgInfo(msgInfo);
+ }
+ regInfo = tfaContGetNextRegFromEndInfo(msgInfo);
+ }
+
+ return regInfo;
+}
+
+#pragma pack (push, 1)
+struct tfa_partial_msg_block {
+ uint8_t offset;
+ uint16_t change;
+ uint8_t update[16][3];
+};
+#pragma pack (pop)
+
+static enum Tfa98xx_Error tfaContWriteVstepMax2_One(struct tfa_device *tfa, struct TfaVolumeStepMessageInfo *new_msg,
+ struct TfaVolumeStepMessageInfo *old_msg, int enable_partial_update)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int len = (tfaContGetmsgLen(new_msg) - 1) * 3;
+ char *buf = (char*)new_msg->ParameterData;
+ uint8_t *partial = NULL;
+ uint8_t cmdid[3];
+ int use_partial_coeff = 0;
+
+ if (enable_partial_update) {
+ if (new_msg->MessageType != old_msg->MessageType) {
+ pr_debug("Message type differ - Disable Partial Update\n");
+ enable_partial_update = 0;
+ }
+ else if (tfaContGetmsgLen(new_msg) != tfaContGetmsgLen(old_msg)) {
+ pr_debug("Message Length differ - Disable Partial Update\n");
+ enable_partial_update = 0;
+ }
+ }
+
+ if ((enable_partial_update) && (new_msg->MessageType == 1)) {
+ /* No patial updates for message type 1 (Coefficients) */
+ enable_partial_update = 0;
+ if ((tfa->rev & 0xff) == 0x88) {
+ use_partial_coeff = 1;
+ }
+ else if ((tfa->rev & 0xff) == 0x13) {
+ use_partial_coeff = 1;
+ }
+ }
+
+ /* Change Message Len to the actual buffer len */
+ memcpy(cmdid, new_msg->CmdId, sizeof(cmdid));
+
+ /* The algoparams and mbdrc msg id will be changed to the reset type when SBSL=0
+ * if SBSL=1 the msg will remain unchanged. It's up to the tuning engineer to choose the 'without_reset'
+ * types inside the vstep. In other words: the reset msg is applied during SBSL==0 else it remains unchanged.
+ */
+ if (tfa_needs_reset(tfa) == 1) {
+ if (new_msg->MessageType == 0) {
+ cmdid[2] = SB_PARAM_SET_ALGO_PARAMS;
+ if (tfa->verbose)
+ pr_debug("P-ID for SetAlgoParams modified!\n");
+ }
+ else if (new_msg->MessageType == 2) {
+ cmdid[2] = SB_PARAM_SET_MBDRC;
+ if (tfa->verbose)
+ pr_debug("P-ID for SetMBDrc modified!\n");
+ }
+ }
+
+ /*
+ * +sizeof(struct tfa_partial_msg_block) will allow to fit one
+ * additonnal partial block If the partial update goes over the len of
+ * a regular message ,we can safely write our block and check afterward
+ * that we are over the size of a usual update
+ */
+ if (enable_partial_update) {
+ partial = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (!partial)
+ pr_debug("Partial update memory error - Disabling\n");
+ }
+
+ if (partial) {
+ uint8_t offset = 0, i = 0;
+ uint16_t *change;
+ uint8_t *n = new_msg->ParameterData;
+ uint8_t *o = old_msg->ParameterData;
+ uint8_t *p = partial;
+ uint8_t* trim = partial;
+
+ /* set dspFiltersReset */
+ *p++ = 0x02;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ while ((o < (old_msg->ParameterData + len)) &&
+ (p < (partial + len - 3))) {
+ if ((offset == 0xff) ||
+ (memcmp(n, o, 3 * sizeof(uint8_t)))) {
+ *p++ = offset;
+ change = (uint16_t*)p;
+ *change = 0;
+ p += 2;
+
+ for (i = 0;
+ (i < 16) && (o < (old_msg->ParameterData + len));
+ i++, n += 3, o += 3) {
+ if (memcmp(n, o, 3 * sizeof(uint8_t))) {
+ *change |= BIT(i);
+ memcpy(p, n, 3);
+ p += 3;
+ trim = p;
+ }
+ }
+
+ offset = 0;
+ *change = cpu_to_be16(*change);
+ }
+ else {
+ n += 3;
+ o += 3;
+ offset++;
+ }
+ }
+
+ if (trim == partial) {
+ pr_debug("No Change in message - discarding %d bytes\n", len);
+ len = 0;
+
+ }
+ else if (trim < (partial + len - 3)) {
+ pr_debug("Using partial update: %d -> %d bytes\n", len, (int)(trim - partial + 3));
+
+ /* Add the termination marker */
+ memset(trim, 0x00, 3);
+ trim += 3;
+
+ /* Signal This will be a partial update */
+ cmdid[2] |= BIT(6);
+ buf = (char*)partial;
+ len = (int)(trim - partial);
+ }
+ else {
+ pr_debug("Partial too big - use regular update\n");
+ }
+ }
+
+ if (use_partial_coeff) {
+ err = tfa_dsp_partial_coefficients(tfa, old_msg->ParameterData, new_msg->ParameterData);
+ }
+ else if (len) {
+ uint8_t *buffer;
+
+ if (tfa->verbose)
+ pr_debug("Command-ID used: 0x%02x%02x%02x \n", cmdid[0], cmdid[1], cmdid[2]);
+
+ buffer = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (buffer == NULL) {
+ err = Tfa98xx_Error_Fail;
+ }
+ else {
+ memcpy(&buffer[0], cmdid, 3);
+ memcpy(&buffer[3], buf, len);
+ err = tfa_dsp_msg(tfa, 3 + len, (char *)buffer);
+ kmem_cache_free(tfa->cachep, buffer);
+ }
+ }
+
+ if (partial)
+ kmem_cache_free(tfa->cachep, partial);
+
+ return err;
+}
+
+static enum Tfa98xx_Error tfaContWriteVstepMax2(struct tfa_device *tfa, TfaVolumeStepMax2File_t *vp, int vstep_idx, int vstep_msg_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ struct TfaVolumeStepRegisterInfo *regInfo = NULL;
+ struct TfaVolumeStepMessageInfo *msgInfo = NULL, *p_msgInfo = NULL;
+ TfaBitfield_t bitF;
+ int i, nrMessages, enp = tfa->partial_enable;
+
+ if (vstep_idx >= vp->NrOfVsteps) {
+ pr_debug("Volumestep %d is not available \n", vstep_idx);
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->p_regInfo == NULL) {
+ if (tfa->verbose)
+ pr_debug("Inital vstep write\n");
+ enp = 0;
+ }
+
+ regInfo = tfaContGetRegForVstep(vp, vstep_idx);
+
+ msgInfo = tfaContGetmsgInfoFromReg(regInfo);
+ nrMessages = msgInfo->NrOfMessages;
+
+ if (enp) {
+ p_msgInfo = tfaContGetmsgInfoFromReg(tfa->p_regInfo);
+ if (nrMessages != p_msgInfo->NrOfMessages) {
+ pr_debug("Message different - Disable partial update\n");
+ enp = 0;
+ }
+ }
+
+ for (i = 0; i < nrMessages; i++) {
+ /* Messagetype(3) is Smartstudio Info! Dont send this! */
+ if (msgInfo->MessageType == 3) {
+ /* MessageLength is in bytes */
+ msgInfo = tfaContGetNextmsgInfo(msgInfo);
+ if (enp)
+ p_msgInfo = tfaContGetNextmsgInfo(p_msgInfo);
+ continue;
+ }
+
+ /* If no vstepMsgIndex is passed on, all message needs to be send */
+ if ((vstep_msg_idx >= TFA_MAX_VSTEP_MSG_MARKER) || (vstep_msg_idx == i)) {
+ err = tfaContWriteVstepMax2_One(tfa, msgInfo, p_msgInfo, enp);
+ if (err != Tfa98xx_Error_Ok) {
+ /*
+ * Force a full update for the next write
+ * As the current status of the DSP is unknown
+ */
+ tfa->p_regInfo = NULL;
+ return err;
+ }
+ }
+
+ msgInfo = tfaContGetNextmsgInfo(msgInfo);
+ if (enp)
+ p_msgInfo = tfaContGetNextmsgInfo(p_msgInfo);
+ }
+
+ tfa->p_regInfo = regInfo;
+
+ for (i = 0; i < regInfo->NrOfRegisters * 2; i++) {
+ /* Byte swap the datasheetname */
+ bitF.field = (uint16_t)(regInfo->registerInfo[i] >> 8) | (regInfo->registerInfo[i] << 8);
+ i++;
+ bitF.value = (uint16_t)regInfo->registerInfo[i] >> 8;
+ err = tfaRunWriteBitfield(tfa, bitF);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+ }
+
+ /* Save the current vstep */
+ tfa_dev_set_swvstep(tfa, (unsigned short)vstep_idx);
+
+ return err;
+}
+
+/*
+ * Write DRC message to the dsp
+ * If needed modify the cmd-id
+ */
+
+enum Tfa98xx_Error tfaContWriteDrcFile(struct tfa_device *tfa, int size, uint8_t data[])
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ uint8_t *msg = NULL;
+
+ msg = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (msg == NULL)
+ return Tfa98xx_Error_Fail;
+ memcpy(msg, data, size);
+
+ if (TFA_GET_BF(tfa, SBSL) == 0) {
+ /* Only do this when not set already */
+ if (msg[2] != SB_PARAM_SET_MBDRC) {
+ msg[2] = SB_PARAM_SET_MBDRC;
+
+ if (tfa->verbose) {
+ pr_debug("P-ID for SetMBDrc modified!: ");
+ pr_debug("Command-ID used: 0x%02x%02x%02x \n",
+ msg[0], msg[1], msg[2]);
+ }
+ }
+ }
+
+ /* Send cmdId + payload to dsp */
+ err = tfa_dsp_msg(tfa, size, (const char *)msg);
+
+ kmem_cache_free(tfa->cachep, msg);
+
+ return err;
+}
+
+
+/*
+ * write a parameter file to the device
+ * The VstepIndex and VstepMsgIndex are only used to write a specific msg from the vstep file.
+ */
+enum Tfa98xx_Error tfaContWriteFile(struct tfa_device *tfa, TfaFileDsc_t *file, int vstep_idx, int vstep_msg_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaHeader_t *hdr = (TfaHeader_t *)file->data;
+ TfaHeaderType_t type;
+ int size, i;
+ char subVerString[8] = { 0 };
+ int subversion = 0;
+
+ if (tfa->verbose) {
+ tfaContShowHeader(hdr);
+ }
+
+ type = (TfaHeaderType_t)hdr->id;
+ if ((type == msgHdr) || ((type == volstepHdr) && (tfa->tfa_family == 2)))
+ {
+ subVerString[0] = hdr->subversion[0];
+ subVerString[1] = hdr->subversion[1];
+ subVerString[2] = '\0';
+
+ sscanf(subVerString, "%d", &subversion);
+
+ if ((subversion > 0) &&
+ (((hdr->customer[0]) == 'A') && ((hdr->customer[1]) == 'P') &&
+ ((hdr->customer[2]) == 'I') && ((hdr->customer[3]) == 'V')))
+ {
+ /* Temporary workaround (example: For climax --calibrate scenario for probus devices) */
+ err = tfaGetFwApiVersion(tfa, (unsigned char *)&tfa->fw_itf_ver[0]);
+ if (err) {
+ pr_debug("[%s] cannot get FWAPI error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+ for (i = 0; i<4; i++)
+ {
+ if (tfa->fw_itf_ver[i] != hdr->customer[i + 4]) //+4 to skip "?PIV" string part in the .msg file.
+ {
+ ERRORMSG("Error: tfaContWriteFile: Expected FW API version = %d.%d.%d.%d, Msg File version: %d.%d.%d.%d \n",
+ tfa->fw_itf_ver[0],
+ tfa->fw_itf_ver[1],
+ tfa->fw_itf_ver[2],
+ tfa->fw_itf_ver[3],
+ hdr->customer[4],
+ hdr->customer[5],
+ hdr->customer[6],
+ hdr->customer[7]);
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ }
+ }
+
+ switch (type) {
+ case msgHdr: /* generic DSP message */
+ size = hdr->size - sizeof(TfaMsgFile_t);
+ err = tfa_dsp_msg(tfa, size, (const char *)((TfaMsgFile_t *)hdr)->data);
+ break;
+ case volstepHdr:
+ if (tfa->tfa_family == 2) {
+ err = tfaContWriteVstepMax2(tfa, (TfaVolumeStepMax2File_t *)hdr, vstep_idx, vstep_msg_idx);
+ }
+ else {
+ err = tfaContWriteVstep(tfa, (TfaVolumeStep2File_t *)hdr, vstep_idx);
+ }
+ break;
+ case speakerHdr:
+ if (tfa->tfa_family == 2) {
+ /* Remove header and xml_id */
+ size = hdr->size - sizeof(struct TfaSpkHeader) - sizeof(struct TfaFWVer);
+
+ err = tfa_dsp_msg(tfa, size,
+ (const char *)(((TfaSpeakerFile_t *)hdr)->data + (sizeof(struct TfaFWVer))));
+ }
+ else {
+ size = hdr->size - sizeof(TfaSpeakerFile_t);
+ err = tfa98xx_dsp_write_speaker_parameters(tfa, size,
+ (const unsigned char *)((TfaSpeakerFile_t *)hdr)->data);
+ }
+ break;
+ case presetHdr:
+ size = hdr->size - sizeof(TfaPreset_t);
+ err = tfa98xx_dsp_write_preset(tfa, size, (const unsigned char *)((TfaPreset_t *)hdr)->data);
+ break;
+ case equalizerHdr:
+ err = tfa_cont_write_filterbank(tfa, ((TfaEqualizerFile_t *)hdr)->filter);
+ break;
+ case patchHdr:
+ size = hdr->size - sizeof(TfaPatch_t); // size is total length
+ err = tfa_dsp_patch(tfa, size, (const unsigned char *)((TfaPatch_t *)hdr)->data);
+ break;
+ case configHdr:
+ size = hdr->size - sizeof(TfaConfig_t);
+ err = tfa98xx_dsp_write_config(tfa, size, (const unsigned char *)((TfaConfig_t *)hdr)->data);
+ break;
+ case drcHdr:
+ if (hdr->version[0] == TFA_DR3_VERSION) {
+ /* Size is total size - hdrsize(36) - xmlversion(3) */
+ size = hdr->size - sizeof(TfaDrc2_t);
+ err = tfaContWriteDrcFile(tfa, size, ((TfaDrc2_t *)hdr)->data);
+ }
+ else {
+ /*
+ * The DRC file is split as:
+ * 36 bytes for generic header (customer, application, and type)
+ * 127x3 (381) bytes first block contains the device and sample rate
+ * independent settings
+ * 127x3 (381) bytes block the device and sample rate specific values.
+ * The second block can always be recalculated from the first block,
+ * if vlsCal and the sample rate are known.
+ */
+ //size = hdr->size - sizeof(TfaDrc_t);
+ size = 381; /* fixed size for first block */
+
+ //+381 is done to only send the second part of the drc block
+ err = tfa98xx_dsp_write_drc(tfa, size, ((const unsigned char *)((TfaDrc_t *)hdr)->data + 381));
+ }
+ break;
+ case infoHdr:
+ /* Ignore */
+ break;
+ default:
+ pr_err("Header is of unknown type: 0x%x\n", type);
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ return err;
+}
+
+/**
+ * get the 1st of this dsc type this devicelist
+ */
+static TfaDescPtr_t *tfa_cnt_get_dsc(TfaContainer_t *cnt, TfaDescriptorType_t type, int dev_idx)
+{
+ TfaDeviceList_t *dev = tfaContDevice(cnt, dev_idx);
+ TfaDescPtr_t *_this;
+ int i;
+
+ if (!dev) {
+ return NULL;
+ }
+ /* process the list until a the type is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == (uint32_t)type) {
+ _this = (TfaDescPtr_t *)(dev->list[i].offset + (uint8_t *)cnt);
+ return _this;
+ }
+
+ }
+
+ return NULL;
+}
+
+/**
+ * get the device type from the patch in this devicelist
+ * - find the patch file for this devidx
+ * - return the devid from the patch or 0 if not found
+ */
+int tfa_cnt_get_devid(TfaContainer_t *cnt, int dev_idx)
+{
+ TfaPatch_t *patchfile;
+ TfaDescPtr_t *patchdsc;
+ uint8_t *patchheader;
+ unsigned short devid, checkaddress;
+ int checkvalue;
+
+ patchdsc = tfa_cnt_get_dsc(cnt, dscPatch, dev_idx);
+ if (!patchdsc) /* no patch for this device, assume non-i2c */
+ return 0;
+ patchdsc += 2; /* first the filename dsc and filesize, so skip them */
+ patchfile = (TfaPatch_t *)patchdsc;
+
+ patchheader = patchfile->data;
+
+ checkaddress = (patchheader[1] << 8) + patchheader[2];
+ checkvalue =
+ (patchheader[3] << 16) + (patchheader[4] << 8) + patchheader[5];
+
+ devid = patchheader[0];
+
+ if (checkaddress == 0xFFFF && checkvalue != 0xFFFFFF && checkvalue != 0) {
+ devid = patchheader[5] << 8 | patchheader[0]; /* full revid */
+ }
+
+ return devid;
+}
+
+/**
+ * get the firmware version from the patch in this devicelist
+ */
+int tfa_cnt_get_patch_version(struct tfa_device *tfa)
+{
+ TfaPatch_t *patchfile;
+ TfaDescPtr_t *patchdsc;
+ uint8_t *data;
+ int size, version;
+
+ if (tfa->cnt == NULL)
+ return -1;
+
+ patchdsc = tfa_cnt_get_dsc(tfa->cnt, dscPatch, tfa->dev_idx);
+ patchdsc += 2; /* first the filename dsc and filesize, so skip them */
+ patchfile = (TfaPatch_t *)patchdsc;
+
+ size = patchfile->hdr.size - sizeof(TfaPatch_t);
+ data = patchfile->data;
+
+ version = (data[size - 3] << 16) + (data[size - 2] << 8) + data[size - 1];
+
+ return version;
+}
+
+
+/*
+ * get the slave for the device if it exists
+ */
+enum Tfa98xx_Error tfaContGetSlave(struct tfa_device *tfa, uint8_t *slave_addr)
+{
+ TfaDeviceList_t *dev = NULL;
+
+ /* Make sure the cnt file is loaded */
+ if (tfa->cnt != NULL) {
+ dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ }
+
+ if (dev == NULL) {
+ /* Check if slave argument is used! */
+ if (gslave_address == 0) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ else {
+ *slave_addr = gslave_address;
+ return Tfa98xx_Error_Ok;
+ }
+ }
+
+ *slave_addr = dev->dev;
+ return Tfa98xx_Error_Ok;
+}
+
+/* If no container file is given, we can always have used the slave argument */
+void tfaContSetSlave(uint8_t slave_addr)
+{
+ gslave_address = slave_addr;
+}
+
+/*
+ * lookup slave and return device index
+ */
+int tfa_cont_get_idx(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev = NULL;
+ int i;
+
+ for (i = 0; i < tfa->cnt->ndev; i++) {
+ dev = tfaContDevice(tfa->cnt, i);
+ if (dev->dev == tfa->slave_address)
+ break;
+
+ }
+ if (i == tfa->cnt->ndev)
+ return -1;
+
+ return i;
+}
+
+/*
+ * write a bit field
+ */
+enum Tfa98xx_Error tfaRunWriteBitfield(struct tfa_device *tfa, TfaBitfield_t bf)
+{
+ enum Tfa98xx_Error error;
+ uint16_t value;
+ union {
+ uint16_t field;
+ TfaBfEnum_t Enum;
+ } bfUni;
+
+ value = bf.value;
+ bfUni.field = bf.field;
+#ifdef TFA_DEBUG
+ if (tfa->verbose)
+ pr_debug("bitfield: %s=0x%x (0x%x[%d..%d]=0x%x)\n", tfaContBfName(bfUni.field, tfa->rev), value,
+ bfUni.Enum.address, bfUni.Enum.pos, bfUni.Enum.pos + bfUni.Enum.len, value);
+#endif
+ error = tfa->dev_ops.tfa_set_bitfield(tfa, bfUni.field, value);
+
+ return error;
+}
+
+/*
+ * read a bit field
+ */
+enum Tfa98xx_Error tfaRunReadBitfield(struct tfa_device *tfa, TfaBitfield_t *bf)
+{
+ enum Tfa98xx_Error error;
+ union {
+ uint16_t field;
+ TfaBfEnum_t Enum;
+ } bfUni;
+ uint16_t regvalue, msk;
+
+ bfUni.field = bf->field;
+
+ error = tfa_reg_read(tfa, (unsigned char)(bfUni.Enum.address), &regvalue);
+ if (error) return error;
+
+ msk = ((1 << (bfUni.Enum.len + 1)) - 1) << bfUni.Enum.pos;
+
+ regvalue &= msk;
+ bf->value = regvalue >> bfUni.Enum.pos;
+
+ return error;
+}
+
+/*
+ dsp mem direct write
+ */
+static enum Tfa98xx_Error tfaRunWriteDspMem(struct tfa_device *tfa, TfaDspMem_t *cfmem)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int i;
+
+ for (i = 0; i < cfmem->size; i++) {
+ if (tfa->verbose)
+ pr_debug("dsp mem (%d): 0x%02x=0x%04x\n", cfmem->type, cfmem->address, cfmem->words[i]);
+
+ error = tfa_mem_write(tfa, cfmem->address++, cfmem->words[i], cfmem->type);
+ if (error) return error;
+ }
+
+ return error;
+}
+
+/*
+ * write filter payload to DSP
+ * note that the data is in an aligned union for all filter variants
+ * the aa data is used but it's the same for all of them
+ */
+static enum Tfa98xx_Error tfaRunWriteFilter(struct tfa_device *tfa, TfaContBiquad_t *bq)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ enum Tfa98xx_DMEM dmem;
+ uint16_t address;
+ uint8_t data[3 * 3 + sizeof(bq->aa.bytes)];
+ int i, channel = 0, runs = 1;
+ int8_t saved_index = bq->aa.index; /* This is used to set back the index */
+
+ /* Channel=1 is primary, Channel=2 is secondary*/
+ if (bq->aa.index > 100) {
+ bq->aa.index -= 100;
+ channel = 2;
+ }
+ else if (bq->aa.index > 50) {
+ bq->aa.index -= 50;
+ channel = 1;
+ }
+ else if ((tfa->rev & 0xff) == 0x88) {
+ runs = 2;
+ }
+
+ if (tfa->verbose) {
+ if (channel == 2)
+ pr_debug("filter[%d,S]", bq->aa.index);
+ else if (channel == 1)
+ pr_debug("filter[%d,P]", bq->aa.index);
+ else
+ pr_debug("filter[%d]", bq->aa.index);
+ }
+
+ for (i = 0; i < runs; i++) {
+ if (runs == 2)
+ channel++;
+
+ /* get the target address for the filter on this device */
+ dmem = tfa98xx_filter_mem(tfa, bq->aa.index, &address, channel);
+ if (dmem == Tfa98xx_DMEM_ERR) {
+ if (tfa->verbose) {
+ pr_debug("Warning: XFilter settings are applied via msg file (ini filter[x] format is skipped).\n");
+ }
+ /* Dont exit with an error here, We could continue without problems */
+ return Tfa98xx_Error_Ok;
+ }
+
+ /* send a DSP memory message that targets the devices specific memory for the filter
+ * msg params: which_mem, start_offset, num_words
+ */
+ memset(data, 0, 3 * 3);
+ data[2] = dmem; /* output[0] = which_mem */
+ data[4] = address >> 8; /* output[1] = start_offset */
+ data[5] = address & 0xff;
+ data[8] = sizeof(bq->aa.bytes) / 3; /*output[2] = num_words */
+ memcpy(&data[9], bq->aa.bytes, sizeof(bq->aa.bytes)); /* payload */
+
+ if (tfa->tfa_family == 2) {
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, FW_PAR_ID_SET_MEMORY, sizeof(data), data);
+ }
+ else {
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, 4 /* param */, sizeof(data), data);
+ }
+ }
+
+#ifdef TFA_DEBUG
+ if (tfa->verbose) {
+ if (bq->aa.index == 13) {
+ pr_debug("=%d,%.0f,%.2f \n",
+ bq->in.type, bq->in.cutOffFreq, bq->in.leakage);
+ }
+ else if (bq->aa.index >= 10 && bq->aa.index <= 12) {
+ pr_debug("=%d,%.0f,%.1f,%.1f \n", bq->aa.type,
+ bq->aa.cutOffFreq, bq->aa.rippleDb, bq->aa.rolloff);
+ }
+ else {
+ pr_debug("= unsupported filter index \n");
+ }
+ }
+#endif
+
+ /* Because we can load the same filters multiple times
+ * For example: When we switch profile we re-write in operating mode.
+ * We then need to remember the index (primary, secondary or both)
+ */
+ bq->aa.index = saved_index;
+
+ return error;
+}
+
+/*
+ * write the register based on the input address, value and mask
+ * only the part that is masked will be updated
+ */
+static enum Tfa98xx_Error tfaRunWriteRegister(struct tfa_device *tfa, TfaRegpatch_t *reg)
+{
+ enum Tfa98xx_Error error;
+ uint16_t value, newvalue;
+
+ if (tfa->verbose)
+ pr_debug("register: 0x%02x=0x%04x (msk=0x%04x)\n", reg->address, reg->value, reg->mask);
+
+ error = tfa_reg_read(tfa, reg->address, &value);
+ if (error) return error;
+
+ value &= ~reg->mask;
+ newvalue = reg->value & reg->mask;
+
+ value |= newvalue;
+ error = tfa_reg_write(tfa, reg->address, value);
+
+ return error;
+
+}
+
+// write reg and bitfield items in the devicelist to the target
+enum Tfa98xx_Error tfaContWriteRegsDev(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ TfaBitfield_t *bitF;
+ int i;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!dev) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ /* process the list until a patch, file of profile is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscPatch ||
+ dev->list[i].type == dscFile ||
+ dev->list[i].type == dscProfile) break;
+
+ if (dev->list[i].type == dscBitfield) {
+ bitF = (TfaBitfield_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaRunWriteBitfield(tfa, *bitF);
+ }
+ if (dev->list[i].type == dscRegister) {
+ err = tfaRunWriteRegister(tfa, (TfaRegpatch_t *)(dev->list[i].offset + (char*)tfa->cnt));
+ }
+
+ if (err) break;
+ }
+
+ return err;
+}
+
+// write reg and bitfield items in the profilelist the target
+enum Tfa98xx_Error tfaContWriteRegsProf(struct tfa_device *tfa, int prof_idx)
+{
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ TfaBitfield_t *bitf;
+ unsigned int i;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!prof) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose)
+ pr_debug("----- profile: %s (%d) -----\n", tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+
+ /* process the list until the end of the profile or the default section */
+ for (i = 0; i < prof->length; i++) {
+ /* We only want to write the values before the default section when we switch profile */
+ if (prof->list[i].type == dscDefault)
+ break;
+
+ if (prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaRunWriteBitfield(tfa, *bitf);
+ }
+ if (prof->list[i].type == dscRegister) {
+ err = tfaRunWriteRegister(tfa, (TfaRegpatch_t *)(prof->list[i].offset + (char*)tfa->cnt));
+ }
+ if (err) break;
+ }
+ return err;
+}
+
+// write patchfile in the devicelist to the target
+enum Tfa98xx_Error tfaContWritePatch(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ TfaFileDsc_t *file;
+ TfaPatch_t *patchfile;
+ int size, i;
+
+ if (!dev) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ /* process the list until a patch is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscPatch) {
+ file = (TfaFileDsc_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ patchfile = (TfaPatch_t *)&file->data;
+ if (tfa->verbose) tfaContShowHeader(&patchfile->hdr);
+ size = patchfile->hdr.size - sizeof(TfaPatch_t); // size is total length
+ err = tfa_dsp_patch(tfa, size, (const unsigned char *)patchfile->data);
+ if (err) return err;
+ }
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+
+/**
+ * Create a buffer which can be used to send to the dsp.
+ */
+static void create_dsp_buffer_msg(struct tfa_device *tfa, TfaMsg_t *msg, char *buffer, int *size)
+{
+ int i, nr = 0;
+
+ (void)tfa;
+
+ /* Copy cmdId. Remember that the cmdId is reversed */
+ buffer[nr++] = msg->cmdId[2];
+ buffer[nr++] = msg->cmdId[1];
+ buffer[nr++] = msg->cmdId[0];
+
+ /* Copy the data to the buffer */
+ for (i = 0; i < msg->msg_size; i++) {
+ buffer[nr++] = (uint8_t)((msg->data[i] >> 16) & 0xffff);
+ buffer[nr++] = (uint8_t)((msg->data[i] >> 8) & 0xff);
+ buffer[nr++] = (uint8_t)(msg->data[i] & 0xff);
+ }
+
+ *size = nr;
+}
+
+// write all param files in the devicelist to the target
+enum Tfa98xx_Error tfaContWriteFiles(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ TfaFileDsc_t *file;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ char buffer[(MEMTRACK_MAX_WORDS * 3) + 3] = { 0 }; //every word requires 3 and 3 is the msg
+ int i, size = 0;
+
+ if (!dev) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ /* process the list and write all files */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ if (tfaContWriteFile(tfa, file, 0, TFA_MAX_VSTEP_MSG_MARKER)) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ if (dev->list[i].type == dscSetInputSelect ||
+ dev->list[i].type == dscSetOutputSelect ||
+ dev->list[i].type == dscSetProgramConfig ||
+ dev->list[i].type == dscSetLagW ||
+ dev->list[i].type == dscSetGains ||
+ dev->list[i].type == dscSetvBatFactors ||
+ dev->list[i].type == dscSetSensesCal ||
+ dev->list[i].type == dscSetSensesDelay ||
+ dev->list[i].type == dscSetMBDrc ||
+ dev->list[i].type == dscSetFwkUseCase ||
+ dev->list[i].type == dscSetVddpConfig) {
+ create_dsp_buffer_msg(tfa, (TfaMsg_t *)
+ (dev->list[i].offset + (char*)tfa->cnt), buffer, &size);
+ if (tfa->verbose) {
+ pr_debug("command: %s=0x%02x%02x%02x \n",
+ tfaContGetCommandString(dev->list[i].type),
+ (unsigned char)buffer[0], (unsigned char)buffer[1], (unsigned char)buffer[2]);
+ }
+
+ err = tfa_dsp_msg(tfa, size, buffer);
+ }
+
+ if (dev->list[i].type == dscCmd) {
+ size = *(uint16_t *)(dev->list[i].offset + (char*)tfa->cnt);
+
+ err = tfa_dsp_msg(tfa, size, dev->list[i].offset + 2 + (char*)tfa->cnt);
+ if (tfa->verbose) {
+ const char *cmd_id = dev->list[i].offset + 2 + (char*)tfa->cnt;
+ pr_debug("Writing cmd=0x%02x%02x%02x \n", (uint8_t)cmd_id[0], (uint8_t)cmd_id[1], (uint8_t)cmd_id[2]);
+ }
+ }
+ if (err != Tfa98xx_Error_Ok)
+ break;
+
+ if (dev->list[i].type == dscCfMem) {
+ err = tfaRunWriteDspMem(tfa, (TfaDspMem_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt));
+ }
+
+ if (err != Tfa98xx_Error_Ok)
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * write all param files in the profilelist to the target
+ * this is used during startup when maybe ACS is set
+ */
+enum Tfa98xx_Error tfaContWriteFilesProf(struct tfa_device *tfa, int prof_idx, int vstep_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ char buffer[(MEMTRACK_MAX_WORDS * 3) + 3] = { 0 }; //every word requires 3 and 3 is the msg
+ unsigned int i;
+ TfaFileDsc_t *file;
+ TfaPatch_t *patchfile;
+ int size;
+
+ if (!prof) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ /* process the list and write all files */
+ for (i = 0; i < prof->length; i++) {
+ switch (prof->list[i].type) {
+ case dscFile:
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER);
+ break;
+ case dscPatch:
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ patchfile = (TfaPatch_t *)&file->data;
+ if (tfa->verbose) tfaContShowHeader(&patchfile->hdr);
+ size = patchfile->hdr.size - sizeof(TfaPatch_t); // size is total length
+ err = tfa_dsp_patch(tfa, size, (const unsigned char *)patchfile->data);
+ break;
+ case dscCfMem:
+ err = tfaRunWriteDspMem(tfa, (TfaDspMem_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt));
+ break;
+ case dscSetInputSelect:
+ case dscSetOutputSelect:
+ case dscSetProgramConfig:
+ case dscSetLagW:
+ case dscSetGains:
+ case dscSetvBatFactors:
+ case dscSetSensesCal:
+ case dscSetSensesDelay:
+ case dscSetMBDrc:
+ case dscSetFwkUseCase:
+ case dscSetVddpConfig:
+ create_dsp_buffer_msg(tfa, (TfaMsg_t *)
+ (prof->list[i].offset + (uint8_t *)tfa->cnt), buffer, &size);
+ if (tfa->verbose) {
+ pr_debug("command: %s=0x%02x%02x%02x \n",
+ tfaContGetCommandString(prof->list[i].type),
+ (unsigned char)buffer[0], (unsigned char)buffer[1], (unsigned char)buffer[2]);
+ }
+
+ err = tfa_dsp_msg(tfa, size, buffer);
+ break;
+ case dscCmd:
+ size = *(uint16_t *)(prof->list[i].offset + (char*)tfa->cnt);
+
+ err = tfa_dsp_msg(tfa, size, prof->list[i].offset + 2 + (char*)tfa->cnt);
+ if (tfa->verbose) {
+ const char *cmd_id = prof->list[i].offset + 2 + (char*)tfa->cnt;
+ pr_debug("Writing cmd=0x%02x%02x%02x \n", (uint8_t)cmd_id[0], (uint8_t)cmd_id[1], (uint8_t)cmd_id[2]);
+ }
+ break;
+ default:
+ /* ignore any other type */
+ break;
+ }
+ }
+
+ return err;
+}
+
+static enum Tfa98xx_Error tfaContWriteItem(struct tfa_device *tfa, TfaDescPtr_t * dsc)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaRegpatch_t *reg;
+ TfaMode_t *cas;
+ TfaBitfield_t *bitf;
+
+ // When no DSP should only write to HW registers.
+ if (tfa->ext_dsp == 0 && !(dsc->type == dscBitfield || dsc->type == dscRegister)) {
+ return Tfa98xx_Error_Ok;
+ }
+
+ switch (dsc->type) {
+ case dscDefault:
+ case dscDevice: // ignore
+ case dscProfile: // profile list
+ break;
+ case dscRegister: // register patch
+ reg = (TfaRegpatch_t *)(dsc->offset + (uint8_t *)tfa->cnt);
+ return tfaRunWriteRegister(tfa, reg);
+ //pr_debug("$0x%2x=0x%02x,0x%02x\n", reg->address, reg->mask, reg->value);
+ break;
+ case dscString: // ascii: zero terminated string
+ pr_debug(";string: %s\n", tfaContGetString(tfa->cnt, dsc));
+ break;
+ case dscFile: // filename + file contents
+ case dscPatch:
+ break;
+ case dscMode:
+ cas = (TfaMode_t *)(dsc->offset + (uint8_t *)tfa->cnt);
+ if (cas->value == Tfa98xx_Mode_RCV)
+ tfa98xx_select_mode(tfa, Tfa98xx_Mode_RCV);
+ else
+ tfa98xx_select_mode(tfa, Tfa98xx_Mode_Normal);
+ break;
+ case dscCfMem:
+ err = tfaRunWriteDspMem(tfa, (TfaDspMem_t *)(dsc->offset + (uint8_t *)tfa->cnt));
+ break;
+ case dscBitfield:
+ bitf = (TfaBitfield_t *)(dsc->offset + (uint8_t *)tfa->cnt);
+ return tfaRunWriteBitfield(tfa, *bitf);
+ break;
+ case dscFilter:
+ return tfaRunWriteFilter(tfa, (TfaContBiquad_t *)(dsc->offset + (uint8_t *)tfa->cnt));
+ break;
+ }
+
+ return err;
+}
+
+static unsigned int tfa98xx_sr_from_field(unsigned int field)
+{
+ switch (field) {
+ case 0:
+ return 8000;
+ case 1:
+ return 11025;
+ case 2:
+ return 12000;
+ case 3:
+ return 16000;
+ case 4:
+ return 22050;
+ case 5:
+ return 24000;
+ case 6:
+ return 32000;
+ case 7:
+ return 44100;
+ case 8:
+ return 48000;
+ default:
+ return 0;
+ }
+}
+
+enum Tfa98xx_Error tfa_write_filters(struct tfa_device *tfa, int prof_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ unsigned int i;
+ int status;
+
+ if (!prof) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose) {
+ pr_debug("----- profile: %s (%d) -----\n", tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+ pr_debug("Waiting for CLKS... \n");
+ }
+
+ for (i = 10; i > 0; i--) {
+ err = tfa98xx_dsp_system_stable(tfa, &status);
+ if (status)
+ break;
+ else
+ msleep_interruptible(10);
+ }
+
+ if (i == 0) {
+ if (tfa->verbose)
+ pr_err("Unable to write filters, CLKS=0 \n");
+
+ return Tfa98xx_Error_StateTimedOut;
+ }
+
+ /* process the list until the end of the profile or the default section */
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscFilter) {
+ if (tfaContWriteItem(tfa, &prof->list[i]) != Tfa98xx_Error_Ok)
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ return err;
+}
+
+unsigned int tfa98xx_get_profile_sr(struct tfa_device *tfa, unsigned int prof_idx)
+{
+ TfaBitfield_t *bitf;
+ unsigned int i;
+ TfaDeviceList_t *dev;
+ TfaProfileList_t *prof;
+ int fs_profile = -1;
+
+ dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ if (!dev)
+ return 0;
+
+ prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ if (!prof)
+ return 0;
+
+ /* Check profile fields first */
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscDefault)
+ break;
+
+ /* check for profile settingd (AUDFS) */
+ if (prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_profile = bitf->value;
+ break;
+ }
+ }
+ }
+
+ if (tfa->verbose)
+ pr_debug("%s - profile fs: 0x%x = %dHz (%d - %d)\n",
+ __FUNCTION__, fs_profile,
+ tfa98xx_sr_from_field(fs_profile),
+ tfa->dev_idx, prof_idx);
+
+ if (fs_profile != -1)
+ return tfa98xx_sr_from_field(fs_profile);
+
+ /* Check for container default setting */
+ /* process the list until a patch, file of profile is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscPatch ||
+ dev->list[i].type == dscFile ||
+ dev->list[i].type == dscProfile)
+ break;
+
+ if (dev->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_profile = bitf->value;
+ break;
+ }
+ }
+ /* Ignore register case */
+ }
+
+ if (tfa->verbose)
+ pr_debug("%s - default fs: 0x%x = %dHz (%d - %d)\n",
+ __FUNCTION__, fs_profile,
+ tfa98xx_sr_from_field(fs_profile),
+ tfa->dev_idx, prof_idx);
+
+ if (fs_profile != -1)
+ return tfa98xx_sr_from_field(fs_profile);
+
+ return 48000; /* default of HW */
+}
+
+static enum Tfa98xx_Error get_sample_rate_info(struct tfa_device *tfa, TfaProfileList_t *prof, TfaProfileList_t *previous_prof, int fs_previous_profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaBitfield_t *bitf;
+ unsigned int i;
+ int fs_default_profile = 8; /* default is 48kHz */
+ int fs_next_profile = 8; /* default is 48kHz */
+
+
+ /* ---------- default settings previous profile ---------- */
+ for (i = 0; i < previous_prof->length; i++) {
+ /* Search for the default section */
+ if (i == 0) {
+ while (previous_prof->list[i].type != dscDefault && i < previous_prof->length) {
+ i++;
+ }
+ i++;
+ }
+
+ /* Only if we found the default section search for AUDFS */
+ if (i < previous_prof->length) {
+ if (previous_prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(previous_prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_default_profile = bitf->value;
+ break;
+ }
+ }
+ }
+ }
+
+ /* ---------- settings next profile ---------- */
+ for (i = 0; i < prof->length; i++) {
+ /* We only want to write the values before the default section */
+ if (prof->list[i].type == dscDefault)
+ break;
+ /* search for AUDFS */
+ if (prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_next_profile = bitf->value;
+ break;
+ }
+ }
+ }
+
+ /* Enable if needed for debugging!
+ if (tfa->verbose) {
+ pr_debug("sample rate from the previous profile: %d \n", fs_previous_profile);
+ pr_debug("sample rate in the default section: %d \n", fs_default_profile);
+ pr_debug("sample rate for the next profile: %d \n", fs_next_profile);
+ }
+ */
+
+ if (fs_next_profile != fs_default_profile) {
+ if (tfa->verbose)
+ pr_debug("Writing delay tables for AUDFS=%d \n", fs_next_profile);
+
+ /* If the AUDFS from the next profile is not the same as
+ * the AUDFS from the default we need to write new delay tables
+ */
+ err = tfa98xx_dsp_write_tables(tfa, fs_next_profile);
+ }
+ else if (fs_default_profile != fs_previous_profile) {
+ if (tfa->verbose)
+ pr_debug("Writing delay tables for AUDFS=%d \n", fs_default_profile);
+
+ /* But if we do not have a new AUDFS in the next profile and
+ * the AUDFS from the default profile is not the same as the AUDFS
+ * from the previous profile we also need to write new delay tables
+ */
+ err = tfa98xx_dsp_write_tables(tfa, fs_default_profile);
+ }
+
+ return err;
+}
+/*
+ * process all items in the profilelist
+ * NOTE an error return during processing will leave the device muted
+ *
+ */
+enum Tfa98xx_Error tfaContWriteProfile(struct tfa_device *tfa, int prof_idx, int vstep_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ TfaProfileList_t *previous_prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, tfa_dev_get_swprof(tfa));
+ char buffer[(MEMTRACK_MAX_WORDS * 4) + 4] = { 0 }; //every word requires 3 or 4 bytes, and 3 or 4 is the msg
+ unsigned int i, k = 0, j = 0, tries = 0;
+ TfaFileDsc_t *file;
+ int manstate, size = 0, ready, fs_previous_profile = 8; /* default fs is 48kHz*/
+
+ if (!prof || !previous_prof) {
+ pr_err("Error trying to get the (previous) swprofile \n");
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose) {
+ tfa98xx_trace_printk("device:%s profile:%s vstep:%d\n", tfaContDeviceName(tfa->cnt, tfa->dev_idx),
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx), vstep_idx);
+ }
+
+ /* We only make a power cycle when the profiles are not in the same group */
+ if (prof->group == previous_prof->group && prof->group != 0) {
+ if (tfa->verbose) {
+ pr_debug("The new profile (%s) is in the same group as the current profile (%s) \n",
+ tfaContGetString(tfa->cnt, &prof->name), tfaContGetString(tfa->cnt, &previous_prof->name));
+ }
+ }
+ else {
+ /* mute */
+ err = tfaRunMute(tfa);
+ if (err) return err;
+
+ /* Get current sample rate before we start switching */
+ fs_previous_profile = TFA_GET_BF(tfa, AUDFS);
+
+ /* clear SBSL to make sure we stay in initCF state */
+ if (tfa->tfa_family == 2) {
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 0);
+ }
+
+ /* When we switch profile we first power down the subsystem
+ * This should only be done when we are in operating mode
+ */
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ if (((tfa->tfa_family == 2) && (manstate >= 6)) || (tfa->tfa_family != 2)) {
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err) return err;
+
+ /* Wait until we are in PLL powerdown */
+ tries = 0;
+ do {
+ err = tfa98xx_dsp_system_stable(tfa, &ready);
+
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ if (manstate == 6) {
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err) return err;
+ } else if (manstate == 0) {
+ /* Reset SBSL back after powering down */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 0);
+ }
+
+ if (!ready)
+ break;
+ else
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ tries++;
+ } while (tries <= 100);
+
+ if (tries > 100) {
+ pr_debug("Wait for PLL powerdown timed out!\n");
+ return Tfa98xx_Error_StateTimedOut;
+ }
+ }
+ else {
+ pr_debug("No need to go to powerdown now \n");
+ }
+ }
+
+ /* set all bitfield settings */
+ /* First set all default settings */
+ if (tfa->verbose) {
+ pr_debug("---------- default settings profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &previous_prof->name), tfa_dev_get_swprof(tfa));
+ }
+
+ err = tfa_show_current_state(tfa);
+
+ /* Loop profile length */
+ for (i = 0; i < previous_prof->length; i++) {
+ /* Search for the default section */
+ if (i == 0) {
+ while (previous_prof->list[i].type != dscDefault && i < previous_prof->length) {
+ i++;
+ }
+ i++;
+ }
+
+ /* Only if we found the default section try writing the items */
+ if (i < previous_prof->length) {
+ if (tfaContWriteItem(tfa, &previous_prof->list[i]) != Tfa98xx_Error_Ok)
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ if (tfa->verbose)
+ pr_debug("---------- new settings profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+
+ /* set new settings */
+ for (i = 0; i < prof->length; i++) {
+ /* Remember where we currently are with writing items*/
+ j = i;
+
+ /* We only want to write the values before the default section when we switch profile */
+ /* process and write all non-file items */
+ switch (prof->list[i].type) {
+ case dscFile:
+ case dscPatch:
+ case dscSetInputSelect:
+ case dscSetOutputSelect:
+ case dscSetProgramConfig:
+ case dscSetLagW:
+ case dscSetGains:
+ case dscSetvBatFactors:
+ case dscSetSensesCal:
+ case dscSetSensesDelay:
+ case dscSetMBDrc:
+ case dscSetFwkUseCase:
+ case dscSetVddpConfig:
+ case dscCmd:
+ case dscFilter:
+ case dscDefault:
+ /* When one of these files are found, we exit */
+ i = prof->length;
+ break;
+ default:
+ err = tfaContWriteItem(tfa, &prof->list[i]);
+ if (err != Tfa98xx_Error_Ok)
+ return Tfa98xx_Error_Bad_Parameter;
+ break;
+ }
+ }
+
+ if (strstr(tfaContGetString(tfa->cnt, &prof->name), ".standby") != NULL) {
+ pr_info("Keep power down without writing files, in standby profile!\n");
+
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err) return err;
+
+ /* Wait until we are in PLL powerdown */
+ tries = 0;
+ do {
+ err = tfa98xx_dsp_system_stable(tfa, &ready);
+ if (!ready)
+ break;
+ else
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ tries++;
+ } while (tries <= 100);
+
+ if (tries > 100) {
+ pr_debug("Wait for PLL powerdown timed out!\n");
+ return Tfa98xx_Error_StateTimedOut;
+ }
+
+ err = tfa_show_current_state(tfa);
+
+ return err;
+ }
+
+ if (prof->group != previous_prof->group || prof->group == 0) {
+ if (tfa->tfa_family == 2)
+ TFA_SET_BF_VOLATILE(tfa, MANSCONF, 1);
+
+ /* Leave powerdown state */
+ err = tfa_cf_powerup(tfa);
+ if (err) return err;
+
+ err = tfa_show_current_state(tfa);
+
+ if (tfa->tfa_family == 2) {
+ /* Reset SBSL to 0 (workaround of enbl_powerswitch=0) */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 0);
+ /* Sending commands to DSP we need to make sure RST is 0 (otherwise we get no response)*/
+ TFA_SET_BF(tfa, RST, 0);
+ }
+ }
+
+ /* Check if there are sample rate changes */
+ err = get_sample_rate_info(tfa, prof, previous_prof, fs_previous_profile);
+ if (err) return err;
+
+
+ /* Write files from previous profile (default section)
+ * Should only be used for the patch&trap patch (file)
+ */
+ if (tfa->ext_dsp != 0) {
+ if (tfa->tfa_family == 2) {
+ for (i = 0; i < previous_prof->length; i++) {
+ /* Search for the default section */
+ if (i == 0) {
+ while (previous_prof->list[i].type != dscDefault && i < previous_prof->length) {
+ i++;
+ }
+ i++;
+ }
+
+ /* Only if we found the default section try writing the file */
+ if (i < previous_prof->length) {
+ if (previous_prof->list[i].type == dscFile || previous_prof->list[i].type == dscPatch) {
+ /* Only write this once */
+ if (tfa->verbose && k == 0) {
+ pr_debug("---------- files default profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &previous_prof->name), prof_idx);
+ k++;
+ }
+ file = (TfaFileDsc_t *)(previous_prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER);
+ }
+ }
+ }
+ }
+
+ if (tfa->verbose) {
+ pr_debug("---------- files new profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+ }
+ }
+
+ /* write everything until end or the default section starts
+ * Start where we currenly left */
+ for (i = j; i < prof->length; i++) {
+ /* We only want to write the values before the default section when we switch profile */
+
+ if (prof->list[i].type == dscDefault) {
+ break;
+ }
+
+ switch (prof->list[i].type) {
+ case dscFile:
+ case dscPatch:
+ /* For tiberius stereo 1 device does not have a dsp! */
+ if (tfa->ext_dsp != 0) {
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER);
+ }
+ break;
+ case dscSetInputSelect:
+ case dscSetOutputSelect:
+ case dscSetProgramConfig:
+ case dscSetLagW:
+ case dscSetGains:
+ case dscSetvBatFactors:
+ case dscSetSensesCal:
+ case dscSetSensesDelay:
+ case dscSetMBDrc:
+ case dscSetFwkUseCase:
+ case dscSetVddpConfig:
+ /* For tiberius stereo 1 device does not have a dsp! */
+ if (tfa->ext_dsp != 0) {
+ create_dsp_buffer_msg(tfa, (TfaMsg_t *)
+ (prof->list[i].offset + (char*)tfa->cnt), buffer, &size);
+ err = tfa_dsp_msg(tfa, size, buffer);
+
+ if (tfa->verbose) {
+ pr_debug("command: %s=0x%02x%02x%02x \n",
+ tfaContGetCommandString(prof->list[i].type),
+ (unsigned char)buffer[0], (unsigned char)buffer[1], (unsigned char)buffer[2]);
+ }
+ }
+ break;
+ case dscCmd:
+ /* For tiberius stereo 1 device does not have a dsp! */
+ if (tfa->ext_dsp != 0) {
+ size = *(uint16_t *)(prof->list[i].offset + (char*)tfa->cnt);
+ err = tfa_dsp_msg(tfa, size, prof->list[i].offset + 2 + (char*)tfa->cnt);
+ if (tfa->verbose) {
+ const char *cmd_id = prof->list[i].offset + 2 + (char*)tfa->cnt;
+ pr_debug("Writing cmd=0x%02x%02x%02x \n", (uint8_t)cmd_id[0], (uint8_t)cmd_id[1], (uint8_t)cmd_id[2]);
+ }
+ }
+ break;
+ default:
+ /* This allows us to write bitfield, registers or xmem after files */
+ if (tfaContWriteItem(tfa, &prof->list[i]) != Tfa98xx_Error_Ok) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ break;
+ }
+
+ if (err != Tfa98xx_Error_Ok) {
+ return err;
+ }
+ }
+
+ if ((prof->group != previous_prof->group || prof->group == 0) && (tfa->tfa_family == 2)) {
+ if (TFA_GET_BF(tfa, REFCKSEL) == 0) {
+ /* set SBSL to go to operation mode */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+ }
+ }
+
+ return err;
+}
+
+/*
+ * process only vstep in the profilelist
+ *
+ */
+enum Tfa98xx_Error tfaContWriteFilesVstep(struct tfa_device *tfa, int prof_idx, int vstep_idx)
+{
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ unsigned int i;
+ TfaFileDsc_t *file;
+ TfaHeader_t *hdr;
+ TfaHeaderType_t type;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!prof)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ if (tfa->verbose)
+ tfa98xx_trace_printk("device:%s profile:%s vstep:%d\n", tfaContDeviceName(tfa->cnt, tfa->dev_idx),
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx), vstep_idx);
+
+ /* write vstep file only! */
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ hdr = (TfaHeader_t *)file->data;
+ type = (TfaHeaderType_t)hdr->id;
+
+ switch (type) {
+ case volstepHdr:
+ if (tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER))
+ return Tfa98xx_Error_Bad_Parameter;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return err;
+}
+
+char *tfaContGetString(TfaContainer_t *cnt, TfaDescPtr_t *dsc)
+{
+ if (dsc->type != dscString)
+ return "Undefined string";
+
+ return dsc->offset + (char*)cnt;
+}
+
+char *tfaContGetCommandString(uint32_t type)
+{
+ if (type == dscSetInputSelect)
+ return "SetInputSelector";
+ else if (type == dscSetOutputSelect)
+ return "SetOutputSelector";
+ else if (type == dscSetProgramConfig)
+ return "SetProgramConfig";
+ else if (type == dscSetLagW)
+ return "SetLagW";
+ else if (type == dscSetGains)
+ return "SetGains";
+ else if (type == dscSetvBatFactors)
+ return "SetvBatFactors";
+ else if (type == dscSetSensesCal)
+ return "SetSensesCal";
+ else if (type == dscSetSensesDelay)
+ return "SetSensesDelay";
+ else if (type == dscSetMBDrc)
+ return "SetMBDrc";
+ else if (type == dscSetFwkUseCase)
+ return "SetFwkUseCase";
+ else if (type == dscSetVddpConfig)
+ return "SetVddpConfig";
+ else if (type == dscFilter)
+ return "filter";
+ else
+ return "Undefined string";
+}
+
+/*
+ * Get the name of the device at a certain index in the container file
+ * return device name
+ */
+char *tfaContDeviceName(TfaContainer_t *cnt, int dev_idx)
+{
+ TfaDeviceList_t *dev;
+
+ dev = tfaContDevice(cnt, dev_idx);
+ if (dev == NULL)
+ return "!ERROR!";
+
+ return tfaContGetString(cnt, &dev->name);
+}
+
+/*
+ * Get the application name from the container file application field
+ * note that the input stringbuffer should be sizeof(application field)+1
+ *
+ */
+int tfa_cnt_get_app_name(struct tfa_device *tfa, char *name)
+{
+ unsigned int i;
+ int len = 0;
+
+ for (i = 0; i < sizeof(tfa->cnt->application); i++) {
+ if (isalnum(tfa->cnt->application[i])) /* copy char if valid */
+ name[len++] = tfa->cnt->application[i];
+ if (tfa->cnt->application[i] == '\0')
+ break;
+ }
+ name[len++] = '\0';
+
+ return len;
+}
+
+/*
+ * Get profile index of the calibration profile.
+ * Returns: (profile index) if found, (-2) if no
+ * calibration profile is found or (-1) on error
+ */
+int tfaContGetCalProfile(struct tfa_device *tfa)
+{
+ int prof, cal_idx = -2;
+
+ if ((tfa->dev_idx < 0) || (tfa->dev_idx >= tfa->cnt->ndev))
+ return -1;
+
+ /* search for the calibration profile in the list of profiles */
+ for (prof = 0; prof < tfa->cnt->nprof; prof++) {
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, prof), ".cal") != NULL) {
+ cal_idx = prof;
+ pr_debug("Using calibration profile: '%s'\n", tfaContProfileName(tfa->cnt, tfa->dev_idx, prof));
+ break;
+ }
+ }
+
+ return cal_idx;
+}
+
+/**
+ * Is the profile a tap profile
+ */
+int tfaContIsTapProfile(struct tfa_device *tfa, int prof_idx)
+{
+ if ((tfa->dev_idx < 0) || (tfa->dev_idx >= tfa->cnt->ndev))
+ return -1;
+
+ /* Check if next profile is tap profile */
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx), ".tap") != NULL) {
+ pr_debug("Using Tap profile: '%s'\n", tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx));
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the name of the profile at certain index for a device in the container file
+ * return profile name
+ */
+char *tfaContProfileName(TfaContainer_t *cnt, int dev_idx, int prof_idx)
+{
+ TfaProfileList_t *prof = NULL;
+
+ /* the Nth profiles for this device */
+ prof = tfaContGetDevProfList(cnt, dev_idx, prof_idx);
+
+ /* If the index is out of bound */
+ if (prof == NULL)
+ return "NONE";
+
+ return tfaContGetString(cnt, &prof->name);
+}
+
+/*
+ * return 1st profile list
+ */
+TfaProfileList_t *tfaContGet1stProfList(TfaContainer_t * cont)
+{
+ TfaProfileList_t *prof;
+ uint8_t *b = (uint8_t *)cont;
+
+ int maxdev = 0;
+ TfaDeviceList_t *dev;
+
+ // get nr of devlists
+ maxdev = cont->ndev;
+ // get last devlist
+ dev = tfaContGetDevList(cont, maxdev - 1);
+ if (dev == NULL)
+ return NULL;
+ // the 1st profile starts after the last device list
+ b = (uint8_t *)dev + sizeof(TfaDeviceList_t) + dev->length * (sizeof(TfaDescPtr_t));
+ prof = (TfaProfileList_t *)b;
+ return prof;
+}
+
+/*
+ * return 1st livedata list
+ */
+TfaLiveDataList_t *tfaContGet1stLiveDataList(TfaContainer_t * cont)
+{
+ TfaLiveDataList_t *ldata;
+ TfaProfileList_t *prof;
+ TfaDeviceList_t *dev;
+ uint8_t *b = (uint8_t *)cont;
+ int maxdev, maxprof;
+
+ // get nr of devlists+1
+ maxdev = cont->ndev;
+ // get nr of proflists
+ maxprof = cont->nprof;
+
+ // get last devlist
+ dev = tfaContGetDevList(cont, maxdev - 1);
+ // the 1st livedata starts after the last device list
+ b = (uint8_t *)dev + sizeof(TfaDeviceList_t) +
+ dev->length * (sizeof(TfaDescPtr_t));
+
+ while (maxprof != 0) {
+ // get last proflist
+ prof = (TfaProfileList_t *)b;
+ b += sizeof(TfaProfileList_t) +
+ ((prof->length - 1) * (sizeof(TfaDescPtr_t)));
+ maxprof--;
+ }
+
+ /* Else the marker falls off */
+ b += 4; //bytes
+
+ ldata = (TfaLiveDataList_t *)b;
+ return ldata;
+}
+
+/*
+ * return the device list pointer
+ */
+TfaDeviceList_t *tfaContDevice(TfaContainer_t *cnt, int dev_idx)
+{
+ return tfaContGetDevList(cnt, dev_idx);
+}
+
+/*
+ * return the next profile:
+ * - assume that all profiles are adjacent
+ * - calculate the total length of the input
+ * - the input profile + its length is the next profile
+ */
+TfaProfileList_t* tfaContNextProfile(TfaProfileList_t* prof) {
+ uint8_t *this, *next; /* byte pointers for byte pointer arithmetic */
+ TfaProfileList_t* nextprof;
+ int listlength; /* total length of list in bytes */
+
+ if (prof == NULL)
+ return NULL;
+
+ if (prof->ID != TFA_PROFID)
+ return NULL; /* invalid input */
+
+ this = (uint8_t *)prof;
+ /* nr of items in the list, length includes name dsc so - 1*/
+ listlength = (prof->length - 1) * sizeof(TfaDescPtr_t);
+ /* the sizeof(TfaProfileList_t) includes the list[0] length */
+ next = this + listlength + sizeof(TfaProfileList_t);// - sizeof(TfaDescPtr_t);
+ nextprof = (TfaProfileList_t *)next;
+
+ if (nextprof->ID != TFA_PROFID)
+ return NULL;
+
+ return nextprof;
+}
+
+/*
+ * return the next livedata
+ */
+TfaLiveDataList_t* tfaContNextLiveData(TfaLiveDataList_t* livedata) {
+ TfaLiveDataList_t* nextlivedata = (TfaLiveDataList_t *)((char*)livedata + (livedata->length * 4) +
+ sizeof(TfaLiveDataList_t) - 4);
+
+ if (nextlivedata->ID == TFA_LIVEDATAID)
+ return nextlivedata;
+
+ return NULL;
+}
+
+/*
+ * check CRC for container
+ * CRC is calculated over the bytes following the CRC field
+ *
+ * return non zero value on error
+ */
+int tfaContCrcCheckContainer(TfaContainer_t *cont)
+{
+ uint8_t *base;
+ size_t size;
+ uint32_t crc;
+
+ base = (uint8_t *)&cont->CRC + 4; // ptr to bytes following the CRC field
+ size = (size_t)(cont->size - (base - (uint8_t *)cont)); // nr of bytes following the CRC field
+ crc = ~crc32_le(~0u, base, size);
+
+ return crc != cont->CRC;
+}
+
+static void get_all_features_from_cnt(struct tfa_device *tfa, int *hw_feature_register, int sw_feature_register[2])
+{
+ TfaFeatures_t *features;
+ int i;
+
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+
+ /* Init values in case no keyword is defined in cnt file: */
+ *hw_feature_register = -1;
+ sw_feature_register[0] = -1;
+ sw_feature_register[1] = -1;
+
+ if (dev == NULL)
+ return;
+
+ // process the device list
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscFeatures) {
+ features = (TfaFeatures_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ *hw_feature_register = features->value[0];
+ sw_feature_register[0] = features->value[1];
+ sw_feature_register[1] = features->value[2];
+ break;
+ }
+ }
+}
+
+/* wrapper function */
+void tfa_get_hw_features_from_cnt(struct tfa_device *tfa, int *hw_feature_register)
+{
+ int sw_feature_register[2];
+ get_all_features_from_cnt(tfa, hw_feature_register, sw_feature_register);
+}
+
+/* wrapper function */
+void tfa_get_sw_features_from_cnt(struct tfa_device *tfa, int sw_feature_register[2])
+{
+ int hw_feature_register;
+ get_all_features_from_cnt(tfa, &hw_feature_register, sw_feature_register);
+}
+
+enum Tfa98xx_Error tfa98xx_factory_trimmer(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.factory_trimmer)(tfa);
+}
+enum Tfa98xx_Error tfa98xx_set_phase_shift(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.phase_shift)(tfa);
+}
+enum Tfa98xx_Error tfa_set_filters(struct tfa_device *tfa, int prof_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ unsigned int i;
+
+ if (!prof)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ /* If we are in powerdown there is no need to set filters */
+ if (TFA_GET_BF(tfa, PWDN) == 1)
+ return Tfa98xx_Error_Ok;
+
+ /* loop the profile to find filter settings */
+ for (i = 0; i < prof->length; i++) {
+ /* We only want to write the values before the default section */
+ if (prof->list[i].type == dscDefault)
+ break;
+
+ /* write all filter settings */
+ if (prof->list[i].type == dscFilter) {
+ if (tfaContWriteItem(tfa, &prof->list[i]) != Tfa98xx_Error_Ok)
+ return err;
+ }
+ }
+
+ return err;
+}
+
+int tfa_tib_dsp_msgmulti(struct tfa_device *tfa, int length, const char *buffer)
+{
+ uint8_t *buf = (uint8_t *)buffer;
+ static uint8_t *blob = NULL, *blobptr; /* TODO: not multi-thread safe */
+ static int total = 0; /* TODO: not multi-thread safe */
+ int post_len = 0;
+
+ /* checks for 24b_BE or 32_LE */
+ int len_word_in_bytes = (tfa->convert_dsp32) ? 4 : 3;
+ /* TODO: get rid of these magic constants max size should depend on the tfa device type */
+ int tfadsp_max_msg_size = (tfa->convert_dsp32) ? 5336 : 4000;
+
+ /* No data found*/
+ if (length == -1 && blob == NULL) {
+ return -1;
+ }
+
+ if (length == -1) {
+ int i;
+ /* set last length field to zero */
+ for (i = total; i < (total + len_word_in_bytes); i++) {
+ blob[i] = 0;
+ }
+ total += len_word_in_bytes;
+ memcpy(buf, blob, total);
+
+ kfree(blob);
+ blob = NULL; /* Set to NULL pointer, otherwise no new malloc is done! */
+ return total;
+ }
+
+ if (blob == NULL) {
+ if (tfa->verbose)
+ pr_debug("%s, Creating the multi-message \n\n", __FUNCTION__);
+
+ blob = kmalloc(tfadsp_max_msg_size, GFP_KERNEL);
+ /* add command ID for multi-msg = 0x008015 */
+ if (tfa->convert_dsp32) {
+ blob[0] = 0x15;
+ blob[1] = 0x80;
+ blob[2] = 0x0;
+ blob[3] = 0x0;
+ }
+ else {
+ blob[0] = 0x0;
+ blob[1] = 0x80;
+ blob[2] = 0x15;
+ }
+ blobptr = blob;
+ blobptr += len_word_in_bytes;
+ total = len_word_in_bytes;
+ }
+
+ if (tfa->verbose) {
+ pr_debug("%s, id:0x%02x%02x%02x, length:%d \n", __FUNCTION__, buf[0], buf[1], buf[2], length);
+ }
+
+ /* check total message size after concatination */
+ post_len = total + length + (2 * len_word_in_bytes);
+ if (post_len > tfadsp_max_msg_size) {
+ //pr_debug("New multi-message too large! (%d >= %d (max.)), current length: %d\n", post_len, tfadsp_max_msg_size, total);
+ return Tfa98xx_Error_Buffer_too_small;
+ }
+
+ /* add length field (length in words) to the multi message */
+ if (tfa->convert_dsp32) {
+ *blobptr++ = (uint8_t)((length / len_word_in_bytes) & 0xff); /* lsb */
+ *blobptr++ = (uint8_t)(((length / len_word_in_bytes) & 0xff00) >> 8); /* msb */
+ *blobptr++ = 0x0;
+ *blobptr++ = 0x0;
+ }
+ else {
+ *blobptr++ = 0x0;
+ *blobptr++ = (uint8_t)(((length / len_word_in_bytes) & 0xff00) >> 8); /* msb */
+ *blobptr++ = (uint8_t)((length / len_word_in_bytes) & 0xff); /* lsb */
+ }
+ memcpy(blobptr, buf, length);
+ blobptr += length;
+ total += (length + len_word_in_bytes);
+
+ /* SetRe25 message is always the last message of the multi-msg */
+ if (tfa->convert_dsp32) {
+ if (buf[1] == 0x81 && buf[0] == SB_PARAM_SET_RE25C) {
+ return 1; /* 1 means last message is done! */
+ }
+ }
+ else {
+ if (buf[1] == 0x81 && buf[2] == SB_PARAM_SET_RE25C) {
+ return 1; /* 1 means last message is done! */
+ }
+ }
+
+ return 0;
+}
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_container.h b/sound/soc/codecs/tfa98xx-downstream/tfa_container.h
new file mode 100644
index 00000000000..477a9263151
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_container.h
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*
+ * tfaContainer.h
+ *
+ * Created on: Sep 11, 2013
+ * Author: wim
+ */
+
+#ifndef TFACONTAINER_H_
+#define TFACONTAINER_H_
+
+/* static limits */
+#define TFACONT_MAXDEVS (4) /* maximum nr of devices */
+#define TFACONT_MAXPROFS (16) /* maximum nr of profiles */
+
+#include "tfa98xx_parameters.h"
+
+/**
+* Pass the container buffer, initialize and allocate internal memory.
+*
+* @param cnt pointer to the start of the buffer holding the container file
+* @param length of the data in bytes
+* @return
+* - tfa_error_ok if normal
+* - tfa_error_container invalid container data
+* - tfa_error_bad_param invalid parameter
+*
+*/
+enum tfa_error tfa_load_cnt(void *cnt, int length);
+
+/**
+ * Return the descriptor string
+ * @param cnt pointer to the container struct
+ * @param dsc pointer to Tfa descriptor
+ * @return descriptor string
+ */
+char *tfaContGetString(TfaContainer_t *cnt, TfaDescPtr_t *dsc);
+
+/**
+ * Gets the string for the given command type number
+ * @param type number representing a command
+ * @return string of a command
+ */
+char *tfaContGetCommandString(uint32_t type);
+
+/**
+ * get the device type from the patch in this devicelist
+ * - find the patch file for this devidx
+ * - return the devid from the patch or 0 if not found
+ * @param cnt pointer to container file
+ * @param dev_idx device index
+ * @return descriptor string
+ */
+int tfa_cnt_get_devid(TfaContainer_t *cnt, int dev_idx);
+
+/**
+ * Get the slave for the device if it exists.
+ * @param tfa the device struct pointer
+ * @param slave_addr the index of the device
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContGetSlave(struct tfa_device *tfa, uint8_t *slave_addr);
+
+void tfaContSetSlave(uint8_t slave_addr);
+
+/**
+ * Get the index for a skave address.
+ * @param tfa the device struct pointer
+ * @return the device index
+ */
+int tfa_cont_get_idx(struct tfa_device *tfa);
+
+/**
+ * Write reg and bitfield items in the devicelist to the target.
+ * @param tfa the device struct pointer
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteRegsDev(struct tfa_device *tfa);
+
+/**
+ * Write reg and bitfield items in the profilelist to the target.
+ * @param tfa the device struct pointer
+ * @param prof_idx the profile index
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteRegsProf(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Write a patchfile in the devicelist to the target.
+ * @param tfa the device struct pointer
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWritePatch(struct tfa_device *tfa);
+
+/**
+ * Write all param files in the devicelist to the target.
+ * @param tfa the device struct pointer
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteFiles(struct tfa_device *tfa);
+
+/**
+ * Get sample rate from passed profile index
+ * @param tfa the device struct pointer
+ * @param prof_idx the index of the profile
+ * @return sample rate value
+ */
+unsigned int tfa98xx_get_profile_sr(struct tfa_device *tfa, unsigned int prof_idx);
+
+/**
+ * Get the device name string
+ * @param cnt the pointer to the container struct
+ * @param dev_idx the index of the device
+ * @return device name string or error string if not found
+ */
+char *tfaContDeviceName(TfaContainer_t *cnt, int dev_idx);
+
+/**
+ * Get the application name from the container file application field
+ * @param tfa the device struct pointer
+ * @param name the input stringbuffer with size: sizeof(application field)+1
+ * @return actual string length
+ */
+int tfa_cnt_get_app_name(struct tfa_device *tfa, char *name);
+
+/**
+ * Get profile index of the calibration profile
+ * @param tfa the device struct pointer
+ * @return profile index, -2 if no calibration profile is found or -1 on error
+ */
+int tfaContGetCalProfile(struct tfa_device *tfa);
+
+/**
+ * Is the profile a tap profile ?
+ * @param tfa the device struct pointer
+ * @param prof_idx the index of the profile
+ * @return 1 if the profile is a tap profile or 0 if not
+ */
+int tfaContIsTapProfile(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Get the name of the profile at certain index for a device in the container file
+ * @param cnt the pointer to the container struct
+ * @param dev_idx the index of the device
+ * @param prof_idx the index of the profile
+ * @return profile name string or error string if not found
+ */
+char *tfaContProfileName(TfaContainer_t *cnt, int dev_idx, int prof_idx);
+
+/**
+ * Process all items in the profilelist
+ * NOTE an error return during processing will leave the device muted
+ * @param tfa the device struct pointer
+ * @param prof_idx index of the profile
+ * @param vstep_idx index of the vstep
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteProfile(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+
+/**
+ * Specify the speaker configurations (cmd id) (Left, right, both, none)
+ * @param dev_idx index of the device
+ * @param configuration name string of the configuration
+ */
+void tfa98xx_set_spkr_select(int dev_idx, char *configuration);
+
+enum Tfa98xx_Error tfa_cont_write_filterbank(struct tfa_device *tfa, TfaFilter_t *filter);
+
+/**
+ * Write all param files in the profilelist to the target
+ * this is used during startup when maybe ACS is set
+ * @param tfa the device struct pointer
+ * @param prof_idx the index of the profile
+ * @param vstep_idx the index of the vstep
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteFilesProf(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+enum Tfa98xx_Error tfaContWriteFilesVstep(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+enum Tfa98xx_Error tfaContWriteDrcFile(struct tfa_device *tfa, int size, uint8_t data[]);
+
+/**
+ * Get the device list dsc from the tfaContainer
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @return device list pointer
+ */
+TfaDeviceList_t *tfaContGetDevList(TfaContainer_t *cont, int dev_idx);
+
+/**
+ * Get the Nth profile for the Nth device
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @param prof_idx the index of the profile
+ * @return profile list pointer
+ */
+TfaProfileList_t *tfaContGetDevProfList(TfaContainer_t *cont, int dev_idx, int prof_idx);
+
+/**
+ * Get the number of profiles for device from contaienr
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @return device list pointer
+ */
+int tfa_cnt_get_dev_nprof(struct tfa_device *tfa);
+
+
+/**
+ * Get the Nth livedata for the Nth device
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @param livedata_idx the index of the livedata
+ * @return livedata list pointer
+ */
+TfaLiveDataList_t *tfaContGetDevLiveDataList(TfaContainer_t *cont, int dev_idx, int livedata_idx);
+
+/**
+ * Check CRC for container
+ * @param cont pointer to the tfaContainer
+ * @return error value 0 on error
+ */
+int tfaContCrcCheckContainer(TfaContainer_t *cont);
+
+/**
+ * Get the device list pointer
+ * @param cnt pointer to the container struct
+ * @param dev_idx the index of the device
+ * @return pointer to device list
+ */
+TfaDeviceList_t *tfaContDevice(TfaContainer_t *cnt, int dev_idx);
+
+/**
+ * Return the pointer to the first profile in a list from the tfaContainer
+ * @param cont pointer to the tfaContainer
+ * @return pointer to first profile in profile list
+ */
+TfaProfileList_t *tfaContGet1stProfList(TfaContainer_t *cont);
+
+/**
+ * Return the pointer to the next profile in a list
+ * @param prof is the pointer to the profile list
+ * @return profile list pointer
+ */
+TfaProfileList_t* tfaContNextProfile(TfaProfileList_t *prof);
+
+/**
+ * Return the pointer to the first livedata in a list from the tfaContainer
+ * @param cont pointer to the tfaContainer
+ * @return pointer to first livedata in profile list
+ */
+TfaLiveDataList_t *tfaContGet1stLiveDataList(TfaContainer_t *cont);
+
+/**
+ * Return the pointer to the next livedata in a list
+ * @param livedata_idx is the pointer to the livedata list
+ * @return livedata list pointer
+ */
+TfaLiveDataList_t* tfaContNextLiveData(TfaLiveDataList_t *livedata_idx);
+
+/**
+ * Write a bit field
+ * @param tfa the device struct pointer
+ * @param bf bitfield to write
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaRunWriteBitfield(struct tfa_device *tfa, TfaBitfield_t bf);
+
+/**
+ * Write a parameter file to the device
+ * @param tfa the device struct pointer
+ * @param file filedescriptor pointer
+ * @param vstep_idx index to vstep
+ * @param vstep_msg_idx index to vstep message
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteFile(struct tfa_device *tfa, TfaFileDsc_t *file, int vstep_idx, int vstep_msg_idx);
+
+/**
+ * Get the max volume step associated with Nth profile for the Nth device
+ * @param tfa the device struct pointer
+ * @param prof_idx profile index
+ * @return the number of vsteps
+ */
+int tfacont_get_max_vstep(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Get the file contents associated with the device or profile
+ * Search within the device tree, if not found, search within the profile
+ * tree. There can only be one type of file within profile or device.
+ * @param tfa the device struct pointer
+ * @param prof_idx I2C profile index in the device
+ * @param type file type
+ * @return 0 NULL if file type is not found
+ * @return 1 file contents
+ */
+TfaFileDsc_t *tfacont_getfiledata(struct tfa_device *tfa, int prof_idx, enum TfaHeaderType type);
+
+/**
+ * Dump the contents of the file header
+ * @param hdr pointer to file header data
+ */
+void tfaContShowHeader(TfaHeader_t *hdr);
+
+/**
+ * Read a bit field
+ * @param tfa the device struct pointer
+ * @param bf bitfield to read out
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaRunReadBitfield(struct tfa_device *tfa, TfaBitfield_t *bf);
+
+/**
+ * Get hw feature bits from container file
+ * @param tfa the device struct pointer
+ * @param hw_feature_register pointer to where hw features are stored
+ */
+void tfa_get_hw_features_from_cnt(struct tfa_device *tfa, int *hw_feature_register);
+
+/**
+ * Get sw feature bits from container file
+ * @param tfa the device struct pointer
+ * @param sw_feature_register pointer to where sw features are stored
+ */
+void tfa_get_sw_features_from_cnt(struct tfa_device *tfa, int sw_feature_register[2]);
+
+/**
+ * Factory trimming for the Boost converter
+ * check if there is a correction needed
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa98xx_factory_trimmer(struct tfa_device *tfa);
+
+/**
+ * Control for PWM phase shift
+ * @param tfa the device struct pointer
+ */
+ enum Tfa98xx_Error tfa98xx_set_phase_shift(struct tfa_device *tfa);
+
+
+/**
+ * Search for filters settings and if found then write them to the device
+ * @param tfa the device struct pointer
+ * @param prof_idx profile to look in
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfa_set_filters(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Get the firmware version from the patch in the container file
+ * @param tfa the device struct pointer
+ * @return firmware version
+ */
+int tfa_cnt_get_patch_version(struct tfa_device *tfa);
+
+int tfa_tib_dsp_msgmulti(struct tfa_device *tfa, int length, const char *buffer);
+
+#endif /* TFACONTAINER_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_device.h b/sound/soc/codecs/tfa98xx-downstream/tfa_device.h
new file mode 100644
index 00000000000..a529b432d55
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_device.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/**\file
+ *
+ * The tfa_device interface controls a single I2C device instance by
+ * referencing to the device specific context provided by means of the
+ * tfa_device structure pointer.
+ * Multiple instances of tfa_device structures will be created and maintained
+ * by the caller.
+ *
+ * The API is functionally grouped as:
+ * - tfa_dev basic codec interface to probe, start/stop and control the device state
+ * - access to internal MTP storage
+ * - abstraction for interrupt bits and handling
+ * - container reading support
+ */
+#ifndef __TFA_DEVICE_H__
+#define __TFA_DEVICE_H__
+
+#include "config.h"
+
+struct tfa_device;
+
+/*
+ * hw/sw feature bit settings in MTP
+ */
+enum featureSupport {
+ supportNotSet, /**< default means not set yet */
+ supportNo, /**< no support */
+ supportYes /**< supported */
+};
+/*
+ * supported Digital Audio Interfaces bitmap
+ */
+enum Tfa98xx_DAI {
+ Tfa98xx_DAI_I2S = 0x01, /**< I2S only */
+ Tfa98xx_DAI_TDM = 0x02, /**< TDM, I2S */
+ Tfa98xx_DAI_PDM = 0x04, /**< PDM */
+ };
+
+/*
+ * device ops function structure
+ */
+struct tfa_device_ops {
+ enum Tfa98xx_Error(*tfa_dsp_msg)(struct tfa_device *tfa, int length, const char *buf);
+ enum Tfa98xx_Error(*tfa_dsp_msg_read)(struct tfa_device *tfa, int length, unsigned char *bytes);
+ enum Tfa98xx_Error(*tfa_reg_read)(struct tfa_device *tfa, unsigned char subaddress, unsigned short *value);
+ enum Tfa98xx_Error(*tfa_reg_write)(struct tfa_device *tfa, unsigned char subaddress, unsigned short value);
+ enum Tfa98xx_Error(*tfa_mem_read)(struct tfa_device *tfa, unsigned int start_offset, int num_words, int *pValues);
+ enum Tfa98xx_Error(*tfa_mem_write)(struct tfa_device *tfa, unsigned short address, int value, int memtype);
+
+ enum Tfa98xx_Error (*tfa_init)(struct tfa_device *tfa); /**< init typically for loading optimal settings */
+ enum Tfa98xx_Error (*dsp_reset)(struct tfa_device *tfa, int state); /**< reset the coolflux dsp */
+ enum Tfa98xx_Error (*dsp_system_stable)(struct tfa_device *tfa, int *ready); /**< ready when clocks are stable to allow DSP subsystem access */
+ enum Tfa98xx_Error (*dsp_write_tables)(struct tfa_device *tfa, int sample_rate); /**< write the device/type specific delaytables */
+ enum Tfa98xx_Error (*auto_copy_mtp_to_iic)(struct tfa_device *tfa); /**< Set auto_copy_mtp_to_iic */
+ enum Tfa98xx_Error (*factory_trimmer)(struct tfa_device *tfa); /**< Factory trimming for the Boost converter */
+ enum Tfa98xx_Error (*phase_shift)(struct tfa_device *tfa); /**< Control for PWM phase shift */
+ int (*set_swprof)(struct tfa_device *tfa, unsigned short new_value); /**< Set the sw profile in the struct and the hw register */
+ int (*get_swprof)(struct tfa_device *tfa); /**< Get the sw profile from the hw register */
+ int(*set_swvstep)(struct tfa_device *tfa, unsigned short new_value); /**< Set the sw vstep in the struct and the hw register */
+ int(*get_swvstep)(struct tfa_device *tfa); /**< Get the sw vstep from the hw register */
+ int(*get_mtpb)(struct tfa_device *tfa); /**< get status of MTB busy bit*/
+ enum Tfa98xx_Error (*set_mute)(struct tfa_device *tfa, int mute); /**< set mute */
+ enum Tfa98xx_Error (*faim_protect)(struct tfa_device *tfa, int state); /**< Protect FAIM from being corrupted */
+ enum Tfa98xx_Error(*set_osc_powerdown)(struct tfa_device *tfa, int state); /**< Allow to change internal osc. gating settings */
+ enum Tfa98xx_Error(*update_lpm)(struct tfa_device *tfa, int state); /**< Allow to change lowpowermode settings */
+ int (*tfa_set_bitfield)(struct tfa_device* tfa, uint16_t bitfield, uint16_t value);
+ enum Tfa98xx_Error (*tfa_status)(struct tfa_device *tfa);
+};
+
+/**
+ * Device states and modifier flags to allow a device/type independent fine
+ * grained control of the internal state.\n
+ * Values below 0x10 are referred to as base states which can be or-ed with
+ * state modifiers, from 0x10 and higher.
+ *
+ */
+enum tfa_state {
+ TFA_STATE_UNKNOWN, /**< unknown or invalid */
+ TFA_STATE_POWERDOWN, /**< PLL in powerdown, Algo is up/warm */
+ TFA_STATE_INIT_HW, /**< load I2C/PLL hardware setting (~wait2srcsettings) */
+ TFA_STATE_INIT_CF, /**< coolflux HW access possible (~initcf) */
+ TFA_STATE_INIT_FW, /**< DSP framework active (~patch loaded) */
+ TFA_STATE_OPERATING, /**< Amp and Algo running */
+ TFA_STATE_FAULT, /**< An alarm or error occurred */
+ TFA_STATE_RESET, /**< I2C reset and ACS set */
+ /* --sticky state modifiers-- */
+ TFA_STATE_MUTE=0x10, /**< Algo & Amp mute */
+ TFA_STATE_UNMUTE=0x20, /**< Algo & Amp unmute */
+ TFA_STATE_CLOCK_ALWAYS=0x40, /**< PLL connect to internal oscillator */
+ TFA_STATE_CLOCK_AUDIO=0x80, /**< PLL connect to audio clock (BCK/FS) */
+ TFA_STATE_LOW_POWER=0x100, /**< lowest possible power state */
+};
+
+/**
+ * This is the main tfa device context structure, it will carry all information
+ * that is needed to handle a single I2C device instance.
+ * All functions dealing with the device will need access to the fields herein.
+ */
+struct tfa_device {
+ int dev_idx; /**< device container index */
+ int in_use;
+ int buffer_size; /**< lowest level max buffer size */
+ int has_msg; /**< support direct dsp messaging */
+ int dynamicTDMmode; /**tracking dynamic TDM setting from alsa input stream*/
+ int bitwidth; /**bitwdith from alsa input stream*/
+ unsigned char slave_address; /**< I2C slave address (not shifted) */
+ unsigned short rev; /**< full revid of this device */
+ unsigned char tfa_family; /**< tfa1/tfa2 */
+ enum featureSupport supportDrc;
+ enum featureSupport supportFramework;
+ enum featureSupport support_saam;
+ int sw_feature_bits[2]; /**< cached copy of sw feature bits */
+ int hw_feature_bits; /**< cached copy of hw feature bits */
+ int profile; /**< active profile */
+ int vstep; /**< active vstep */
+ unsigned char spkr_count;
+ unsigned char spkr_select;
+ unsigned char support_tcoef;/**< legacy tfa9887, will be removed */
+ enum Tfa98xx_DAI daimap; /**< supported audio interface types */
+ int mohm[3]; /**< speaker calibration values in milli ohms -1 is error */
+ struct tfa_device_ops dev_ops;
+ uint16_t interrupt_enable[3];
+ uint16_t interrupt_status[3];
+ int ext_dsp; /**< respond to external DSP: -1:none, 0:no_dsp, 1:cold, 2:warm */
+ int bus; /* TODO fix ext_dsp and bus handling */
+ int tfadsp_event; /**< enum tfadsp_event_en is for external registry */
+ int verbose; /**< verbosity level for debug print output */
+ enum tfa_state state; /**< last known state or-ed with optional state_modifier */
+ struct TfaContainer *cnt;/**< the loaded container file */
+ struct TfaVolumeStepRegisterInfo *p_regInfo; /**< remember vstep for partial updates */
+ int partial_enable; /**< enable partial updates */
+ void *data; /**< typically pointing to Linux driver structure owning this device */
+ int convert_dsp32; /**< convert 24 bit DSP messages to 32 bit */
+ int sync_iv_delay; /**< synchronize I/V delay at cold start */
+ int is_probus_device; /**< probus device: device without internal DSP */
+ int advance_keys_handling;
+ unsigned int rate;
+ int needs_reset; /**< add the reset trigger for SetAlgoParams and SetMBDrc commands */
+ struct kmem_cache *cachep; /**< Memory allocator handle */
+ char fw_itf_ver[4]; /* Firmware ITF version */
+};
+
+/**
+ * The tfa_dev_probe is called before accessing any device accessing functions.
+ * Access to the tfa device register 3 is attempted and will record the
+ * returned id for further use. If no device responds the function will abort.
+ * The recorded id will by used by the query functions to fill the remaining
+ * relevant data fields of the device structure.
+ * Data such as MTP features that requires device access will only be read when
+ * explicitly called and the result will be then cached in the struct.
+ *
+ * A structure pointer passed to this device needs to refer to existing memory
+ * space allocated by the caller.
+ *
+ * @param slave = I2C slave address of the target device (not shifted)
+ * @param tfa struct = points to memory that holds the context for this device
+ * instance
+ *
+ * @return
+ * - 0 if the I2C device responded to a read of register address 3\n
+ * when the device responds but with an unknown id a warning will be printed
+ * - -1 if no response from the I2C device
+ *
+ */
+int tfa_dev_probe(int slave, struct tfa_device *tfa);
+
+/**
+ * Start this instance at the profile and vstep as provided.
+ * The profile and vstep will be loaded first in case the current value differs
+ * from the requested values.
+ * Note that this call will not change the mute state of the tfa, which means
+ * that of this instance was called in muted state the caller will have to
+ * unmute in order to get audio.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @param profile the selected profile to run
+ * @param vstep the selected vstep to use
+ * @return tfa_error enum
+ */
+enum tfa_error tfa_dev_start(struct tfa_device *tfa, int profile, int vstep);
+
+
+/**
+ * Stop audio for this instance as gracefully as possible.
+ * Audio will be muted and the PLL will be shutdown together with any other
+ * device/type specific settings needed to prevent audio artifacts or
+ * workarounds.
+ *
+ * Note that this call will change state of the tfa to mute and powered down.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @return tfa_error enum
+ */
+enum tfa_error tfa_dev_stop(struct tfa_device *tfa);
+
+/**
+ * This interface allows a device/type independent fine grained control of the
+ * internal state of the instance.
+ * Whenever a base state is requested an attempt is made to actively bring the device
+ * into this state. However this may depend on external conditions beyond control of
+ * this software layer. Therefore in case the state cannot be set an erro will
+ * be returned and the current state remains unchanged.
+ * The base states, lower values below 0x10, are all mutually exclusive, they higher ones
+ * can also function as a sticky modifier which means for example that operating
+ * state could be in either muted or unmuted state. Or in case of init_cf it can be
+ * internal clock (always) or external audio clock.
+ * This function is intended to be used for device mute/unmute synchronization
+ * when called from higher layers. Mostly internal calls will use this to control
+ * the startup and profile transitions in a device/type independent way.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @param state struct = desired device state after function return
+ * @return tfa_error enum
+ */
+enum tfa_error tfa_dev_set_state(struct tfa_device *tfa, enum tfa_state state,int is_calibration);
+
+/**
+ * Retrieve the current state of this instance in an active way.
+ * The state field in tfa structure will reflect the result unless an error is
+ * returned.
+ * Note that the hardware state may change on external events an as such this
+ * field should be treated as volatile.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @return tfa_error enum
+ *
+ */
+enum tfa_state tfa_dev_get_state(struct tfa_device *tfa);
+
+/**
+ * Deduce the width from machine driver and decide TDM setting to be
+ * programmed to the TFA amplifier dynamically
+ * @param tfa struct = pointer to context of this device instance
+ * @param width = parmeters read from top layer to decide the applicable TDM settings
+ * @return tfa_error enum
+ - 0 if the width received is correct (16/32/24)
+ * - others if width received is not correct
+ */
+int tfa_dev_set_tdm_bitwidth(struct tfa_device *tfa, int width);
+/**
+ * Fill TDM setting addresses for current device needed with dynamic TDM switch
+ * @param tfa struct = pointer to context of this device instance
+ * @param tdme = pointer to be filled with TDME address
+ * @param tnbck = pointer to be filled with TDMNBCK address
+ * @param tslln = pointer to be filled with TDMSLLN address
+ * @param tsize = pointer to be filled with TDMSSIZE address
+ */
+void tfa_dev_get_tdm_add(struct tfa_device* tfa,uint16_t *tdme,uint16_t * tnbck,uint16_t *tslln,uint16_t *tsize);
+/**
+ * MTP support functions
+ */
+enum tfa_mtp {
+ TFA_MTP_OTC, /**< */
+ TFA_MTP_EX, /**< */
+ TFA_MTP_RE25, /**< */
+ TFA_MTP_RE25_PRIM, /**< */
+ TFA_MTP_RE25_SEC, /**< */
+ TFA_MTP_LOCK, /**< */
+};
+
+/**
+ *
+ */
+int tfa_dev_mtp_get(struct tfa_device *tfa, enum tfa_mtp item);
+
+/**
+ *
+ */
+enum tfa_error tfa_dev_mtp_set(struct tfa_device *tfa, enum tfa_mtp item, int value);
+
+
+//irq
+/* tfa2 interrupt support
+ * !!! enum tfa9912_irq !!!*/
+/*
+ * interrupt bit function to clear
+ */
+int tfa_irq_clear(struct tfa_device *tfa, int bit);
+/*
+ * return state of irq or -1 if illegal bit
+ */
+int tfa_irq_get(struct tfa_device *tfa, int bit);
+/*
+ * interrupt bit function that operates on the shadow regs in the handle
+ */
+int tfa_irq_ena(struct tfa_device *tfa, int bit, int state);
+/*
+ * interrupt bit function that sets the polarity
+ */
+int tfa_irq_set_pol(struct tfa_device *tfa, int bit, int state);
+
+/*
+ * mask interrupts by disabling them
+ */
+int tfa_irq_mask(struct tfa_device *tfa);
+/*
+ * unmask interrupts by enabling them again
+ */
+int tfa_irq_unmask(struct tfa_device *tfa);
+//cnt read
+//debug?
+
+#endif /* __TFA_DEVICE_H__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_dsp.c b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp.c
new file mode 100644
index 00000000000..894fd049f59
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp.c
@@ -0,0 +1,4376 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include "dbgprint.h"
+#include "tfa_container.h"
+#include "tfa.h"
+#include "tfa98xx_tfafieldnames.h"
+#include "tfa_internal.h"
+
+#define TFA_API_SBFW_8_09_00 (31) /**< Corresponds to SB3.5 PRC2 release */
+ /* handle macro for bitfield */
+#define TFA_MK_BF(reg, pos, len) ((reg<<8)|(pos<<4)|(len-1))
+
+/* abstract family for register */
+#define FAM_TFA98XX_CF_CONTROLS (TFA_FAM(tfa,RST) >> 8)
+#define FAM_TFA98XX_CF_MEM (TFA_FAM(tfa,MEMA)>> 8)
+#define FAM_TFA98XX_MTP0 (TFA_FAM(tfa,MTPOTC) >> 8)
+#define FAM_TFA98xx_INT_EN (TFA_FAM(tfa,INTENVDDS) >> 8)
+
+#define CF_STATUS_I2C_CMD_ACK 0x01
+
+/* Defines below are used for irq function (this removed the genregs include) */
+#define TFA98XX_INTERRUPT_ENABLE_REG1 0x48
+#define TFA98XX_INTERRUPT_IN_REG1 0x44
+#define TFA98XX_INTERRUPT_OUT_REG1 0x40
+#define TFA98XX_STATUS_POLARITY_REG1 0x4c
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK 0x2
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MSK 0x1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_POS 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_POS 0
+#define MIN_BATT_LEVEL 640
+#define MAX_BATT_LEVEL 670
+void tfanone_ops(struct tfa_device_ops *ops);
+void tfa9872_ops(struct tfa_device_ops *ops);
+void tfa9873_ops(struct tfa_device_ops *ops);
+void tfa9874_ops(struct tfa_device_ops *ops);
+void tfa9875_ops(struct tfa_device_ops *ops);
+void tfa9878_ops(struct tfa_device_ops *ops);
+void tfa9912_ops(struct tfa_device_ops *ops);
+void tfa9888_ops(struct tfa_device_ops *ops);
+void tfa9891_ops(struct tfa_device_ops *ops);
+void tfa9897_ops(struct tfa_device_ops *ops);
+void tfa9896_ops(struct tfa_device_ops *ops);
+void tfa9890_ops(struct tfa_device_ops *ops);
+void tfa9895_ops(struct tfa_device_ops *ops);
+void tfa9894_ops(struct tfa_device_ops *ops);
+
+#ifndef MIN
+#define MIN(A,B) (A<B?A:B)
+#endif
+
+/* retry values */
+#define CFSTABLE_TRIES 10
+#define AMPOFFWAIT_TRIES 50
+#define MTPBWAIT_TRIES 50
+#define MTPEX_WAIT_NTRIES 50
+
+/* calibration done executed */
+#define TFA_MTPEX_POS TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_POS /**/
+
+int tfa_get_calibration_info(struct tfa_device *tfa, int channel)
+{
+ return tfa->mohm[channel];
+}
+
+/* return sign extended tap pattern */
+int tfa_get_tap_pattern(struct tfa_device *tfa)
+{
+ int value = tfa_get_bf(tfa, TFA9912_BF_CFTAPPAT);
+ int bitshift;
+ uint8_t field_len = 1 + (TFA9912_BF_CFTAPPAT & 0x0f); /* length of bitfield */
+
+ bitshift = 8 * sizeof(int) - field_len;
+ /* signextend */
+ value = (value << bitshift) >> bitshift;
+
+ return value;
+}
+/*
+ * interrupt bit function to clear
+ */
+int tfa_irq_clear(struct tfa_device *tfa, enum tfa9912_irq bit)
+{
+ unsigned char reg;
+
+ /* make bitfield enum */
+ if (bit == tfa9912_irq_all) {
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_IN_REG1; reg < TFA98XX_INTERRUPT_IN_REG1 + 3; reg++)
+ tfa_reg_write(tfa, reg, 0xffff); /* all bits */
+ }
+ else if (bit < tfa9912_irq_max) {
+ reg = (unsigned char)(TFA98XX_INTERRUPT_IN_REG1 + (bit >> 4));
+ tfa_reg_write(tfa, reg, 1 << (bit & 0x0f)); /* only this bit */
+ }
+ else
+ return -1;
+
+ return 0;
+}
+/*
+ * return state of irq or -1 if illegal bit
+ */
+int tfa_irq_get(struct tfa_device *tfa, enum tfa9912_irq bit)
+{
+ uint16_t value;
+ int reg, mask;
+
+ if (bit < tfa9912_irq_max) {
+ /* only this bit */
+ reg = TFA98XX_INTERRUPT_OUT_REG1 + (bit >> 4);
+ mask = 1 << (bit & 0x0f);
+ tfa_reg_read(tfa, (unsigned char)reg, &value);
+ }
+ else
+ return -1;
+
+ return (value & mask) != 0;
+}
+/*
+ * interrupt bit function that operates on the shadow regs in the handle
+ */
+
+int tfa_irq_ena(struct tfa_device *tfa, enum tfa9912_irq bit, int state)
+{
+ uint16_t value, new_value;
+ int reg = 0, mask;
+ /* */
+ if (bit == tfa9912_irq_all) {
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_ENABLE_REG1; reg <= TFA98XX_INTERRUPT_ENABLE_REG1 + tfa9912_irq_max / 16; reg++) {
+ tfa_reg_write(tfa, (unsigned char)reg, state ? 0xffff : 0); /* all bits */
+ tfa->interrupt_enable[reg - TFA98XX_INTERRUPT_ENABLE_REG1] = state ? 0xffff : 0; /* all bits */
+ }
+ }
+ else if (bit < tfa9912_irq_max) {
+ /* only this bit */
+ reg = TFA98XX_INTERRUPT_ENABLE_REG1 + (bit >> 4);
+ mask = 1 << (bit & 0x0f);
+ tfa_reg_read(tfa, (unsigned char)reg, &value);
+ if (state) //set
+ new_value = (uint16_t)(value | mask);
+ else // clear
+ new_value = value & ~mask;
+ if (new_value != value) {
+ tfa_reg_write(tfa, (unsigned char)reg, new_value); /* only this bit */
+ tfa->interrupt_enable[reg - TFA98XX_INTERRUPT_ENABLE_REG1] = new_value;
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/*
+ * mask interrupts by disabling them
+ */
+int tfa_irq_mask(struct tfa_device *tfa)
+{
+ int reg;
+
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_ENABLE_REG1; reg <= TFA98XX_INTERRUPT_ENABLE_REG1 + tfa9912_irq_max / 16; reg++)
+ tfa_reg_write(tfa, (unsigned char)reg, 0);
+
+ return 0;
+}
+
+/*
+ * unmask interrupts by enabling them again
+ */
+int tfa_irq_unmask(struct tfa_device *tfa)
+{
+ int reg;
+
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_ENABLE_REG1; reg <= TFA98XX_INTERRUPT_ENABLE_REG1 + tfa9912_irq_max / 16; reg++)
+ tfa_reg_write(tfa, (unsigned char)reg, tfa->interrupt_enable[reg - TFA98XX_INTERRUPT_ENABLE_REG1]);
+
+ return 0;
+}
+
+/*
+ * interrupt bit function that sets the polarity
+ */
+
+int tfa_irq_set_pol(struct tfa_device *tfa, enum tfa9912_irq bit, int state)
+{
+ uint16_t value, new_value;
+ int reg = 0, mask;
+
+ if (bit == tfa9912_irq_all) {
+ /* operate on all bits */
+ for (reg = TFA98XX_STATUS_POLARITY_REG1; reg <= TFA98XX_STATUS_POLARITY_REG1 + tfa9912_irq_max / 16; reg++) {
+ tfa_reg_write(tfa, (unsigned char)reg, state ? 0xffff : 0); /* all bits */
+ }
+ }
+ else if (bit < tfa9912_irq_max) {
+ /* only this bit */
+ reg = TFA98XX_STATUS_POLARITY_REG1 + (bit >> 4);
+ mask = 1 << (bit & 0x0f);
+ tfa_reg_read(tfa, (unsigned char)reg, &value);
+ if (state) /* Active High */
+ new_value = (uint16_t)(value | mask);
+ else /* Active Low */
+ new_value = value & ~mask;
+ if (new_value != value) {
+ tfa_reg_write(tfa, (unsigned char)reg, new_value); /* only this bit */
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/*
+ * set device info and register device ops
+ */
+void tfa_set_query_info(struct tfa_device *tfa)
+{
+ /* invalidate device struct cached values */
+ tfa->hw_feature_bits = -1;
+ tfa->sw_feature_bits[0] = -1;
+ tfa->sw_feature_bits[1] = -1;
+ tfa->profile = -1;
+ tfa->vstep = -1;
+ /* defaults */
+ tfa->is_probus_device = 0;
+ tfa->advance_keys_handling = 0; /*artf65038*/
+ tfa->tfa_family = 1;
+ tfa->daimap = Tfa98xx_DAI_I2S; /* all others */
+ tfa->spkr_count = 1;
+ tfa->spkr_select = 0;
+ tfa->support_tcoef = supportYes;
+ tfa->supportDrc = supportNotSet;
+ tfa->support_saam = supportNotSet;
+ tfa->ext_dsp = -1; /* respond to external DSP: -1:none, 0:no_dsp, 1:cold, 2:warm */
+ tfa->bus = 0;
+ tfa->partial_enable = 0;
+ tfa->convert_dsp32 = 0;
+ tfa->sync_iv_delay = 0;
+ tfa->dynamicTDMmode = -1; /**tracking dynamic TDM setting from alsa input stream*/
+ tfa->rate = 0;
+ tfa->bitwidth = -1;/**bitwdith from alsa input stream*/
+
+ /* TODO use the getfeatures() for retrieving the features [artf103523]
+ tfa->supportDrc = supportNotSet;*/
+
+ switch (tfa->rev & 0xff) {
+ case 0: /* tfanone : non-i2c external DSP device */
+ /* e.g. qc adsp */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 0;
+ tfa->spkr_count = 0;
+ tfa->daimap = 0;
+ tfanone_ops(&tfa->dev_ops); /* register device operations via tfa hal*/
+ tfa->bus = 1;
+ break;
+ case 0x72:
+ /* tfa9872 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9872_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x73:
+ /* tfa9873 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->advance_keys_handling = 1; /*artf65038*/
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9873_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x74:
+ /* tfa9874 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9874_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x75:
+ /* tfa9875 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->advance_keys_handling = 1; /*artf65038*/
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9875_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x78:
+ /* tfa9878 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->advance_keys_handling = 1; /*artf65038*/
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9878_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x88:
+ /* tfa9888 */
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 2;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9888_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x97:
+ /* tfa9897 */
+ tfa->supportDrc = supportNo;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9897_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x96:
+ /* tfa9896 */
+ tfa->supportDrc = supportNo;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9896_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x92:
+ /* tfa9891 */
+ tfa->spkr_count = 1;
+ tfa->daimap = (Tfa98xx_DAI_PDM | Tfa98xx_DAI_I2S);
+ tfa9891_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x91:
+ /* tfa9890B */
+ tfa->spkr_count = 1;
+ tfa->daimap = (Tfa98xx_DAI_PDM | Tfa98xx_DAI_I2S);
+ break;
+ case 0x80:
+ case 0x81:
+ /* tfa9890 */
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_I2S;
+ tfa->supportDrc = supportNo;
+ tfa->supportFramework = supportNo;
+ tfa9890_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x12:
+ /* tfa9895 */
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_I2S;
+ tfa9895_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x13:
+ /* tfa9912 */
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9912_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x94:
+ /* tfa9894 */
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9894_ops(&tfa->dev_ops); /* register device operations */
+ break;
+
+ default:
+ pr_err("unknown device type : 0x%02x\n", tfa->rev);
+ _ASSERT(0);
+ break;
+ }
+}
+
+/*
+ * lookup the device type and return the family type
+ */
+int tfa98xx_dev2family(int dev_type)
+{
+ /* only look at the die ID part (lsb byte) */
+ switch (dev_type & 0xff) {
+ case 0x12:
+ case 0x80:
+ case 0x81:
+ case 0x91:
+ case 0x92:
+ case 0x97:
+ case 0x96:
+ return 1;
+ case 0x88:
+ case 0x72:
+ case 0x73:
+ case 0x13:
+ case 0x74:
+ case 0x75:
+ case 0x78:
+ case 0x94:
+ return 2;
+ case 0x50:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * return the target address for the filter on this device
+
+ filter_index:
+ [0..9] reserved for EQ (not deployed, calc. is available)
+ [10..12] anti-alias filter
+ [13] integrator filter
+
+ */
+enum Tfa98xx_DMEM tfa98xx_filter_mem(struct tfa_device *tfa, int filter_index, unsigned short *address, int channel)
+{
+ enum Tfa98xx_DMEM dmem = -1;
+ int idx;
+ unsigned short bq_table[7][4] = {
+ /* index: 10, 11, 12, 13 */
+ {346,351,356,288}, //87 BRA_MAX_MRA4-2_7.00
+ {346,351,356,288}, //90 BRA_MAX_MRA6_9.02
+ {467,472,477,409}, //95 BRA_MAX_MRA7_10.02
+ {406,411,416,348}, //97 BRA_MAX_MRA9_12.01
+ {467,472,477,409}, //91 BRA_MAX_MRAA_13.02
+ {8832, 8837, 8842, 8847}, //88 part1
+ {8853, 8858, 8863, 8868} //88 part2
+ /* Since the 88 is stereo we have 2 parts.
+ * Every index has 5 values except index 13 this one has 6 values
+ */
+ };
+
+ if ((10 <= filter_index) && (filter_index <= 13)) {
+ dmem = Tfa98xx_DMEM_YMEM; /* for all devices */
+ idx = filter_index - 10;
+
+ switch (tfa->rev & 0xff) { // only compare lower byte
+ case 0x12:
+ *address = bq_table[2][idx];
+ break;
+ case 0x97:
+ *address = bq_table[3][idx];
+ break;
+ case 0x96:
+ *address = bq_table[3][idx];
+ break;
+ case 0x80:
+ case 0x81: // for the RAM version
+ case 0x91:
+ *address = bq_table[1][idx];
+ break;
+ case 0x92:
+ *address = bq_table[4][idx];
+ break;
+ case 0x88:
+ /* Channel 1 = primary, 2 = secondary */
+ if (channel == 1)
+ *address = bq_table[5][idx];
+ else
+ *address = bq_table[6][idx];
+ break;
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x78:
+ case 0x13:
+ default:
+ /* unsupported case, possibly intermediate version */
+ return -1;
+ _ASSERT(0);
+ }
+ }
+ return dmem;
+}
+
+/************************ query functions ********************************************************/
+/**
+* return revision
+* Used by the LTT
+*/
+void tfa98xx_rev(int *major, int *minor, int *revision)
+{
+ char version_str[] = TFA98XX_API_REV_STR;
+ sscanf(version_str, "v%d.%d.%d", major, minor, revision);
+}
+
+/**
+ * tfa_supported_speakers
+ * returns the number of the supported speaker count
+ */
+enum Tfa98xx_Error tfa_supported_speakers(struct tfa_device *tfa, int* spkr_count)
+{
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ else
+ *spkr_count = tfa->spkr_count;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/*
+ * tfa98xx_supported_saam
+ * returns the supportedspeaker as microphone feature
+ */
+enum Tfa98xx_Error tfa98xx_supported_saam(struct tfa_device *tfa, enum Tfa98xx_saam *saam)
+{
+ int features;
+ enum Tfa98xx_Error error;
+
+ if (tfa->support_saam == supportNotSet) {
+ error = tfa98xx_dsp_get_hw_feature_bits(tfa, &features);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+ tfa->support_saam =
+ (features & 0x8000) ? supportYes : supportNo; /* SAAM is bit15 */
+ }
+ *saam = tfa->support_saam == supportYes ? Tfa98xx_saam : Tfa98xx_saam_none;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/*
+ * tfa98xx_compare_features
+ * Obtains features_from_MTP and features_from_cnt
+ */
+enum Tfa98xx_Error tfa98xx_compare_features(struct tfa_device *tfa, int features_from_MTP[3], int features_from_cnt[3])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint32_t value;
+ uint16_t mtpbf;
+ unsigned char bytes[3 * 2];
+ int status;
+
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status)
+ return Tfa98xx_Error_NoClock; // Only test when we have a clock.
+
+ /* Set proper MTP location per device: */
+ if (tfa->tfa_family == 1) {
+ mtpbf = 0x850f; /* MTP5 for tfa1,16 bits */
+ }
+ else {
+ mtpbf = 0xf907; /* MTP9 for tfa2, 8 bits */
+ }
+
+ /* Read HW features from MTP: */
+ value = tfa_read_reg(tfa, mtpbf) & 0xffff;
+ features_from_MTP[0] = tfa->hw_feature_bits = value;
+
+ /* Read SW features: */
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK, FW_PAR_ID_GET_FEATURE_INFO, sizeof(bytes), bytes);
+ if (error != Tfa98xx_Error_Ok)
+ return error; /* old ROM code may respond with Tfa98xx_Error_RpcParamId */
+
+ tfa98xx_convert_bytes2data(sizeof(bytes), bytes, &features_from_MTP[1]);
+
+ /* check if feature bits from MTP match feature bits from cnt file: */
+ tfa_get_hw_features_from_cnt(tfa, &features_from_cnt[0]);
+ tfa_get_sw_features_from_cnt(tfa, &features_from_cnt[1]);
+
+ return error;
+}
+
+/********************************* device specific ops ************************************************/
+/* the wrapper for DspReset, in case of full */
+enum Tfa98xx_Error tfa98xx_dsp_reset(struct tfa_device *tfa, int state)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ error = (tfa->dev_ops.dsp_reset)(tfa, state);
+
+ return error;
+}
+
+/* the ops wrapper for tfa98xx_dsp_SystemStable */
+enum Tfa98xx_Error tfa98xx_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ return (tfa->dev_ops.dsp_system_stable)(tfa, ready);
+}
+
+/* the ops wrapper for tfa98xx_dsp_system_stable */
+enum Tfa98xx_Error tfa98xx_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.auto_copy_mtp_to_iic)(tfa);
+}
+
+/* the ops wrapper for tfa98xx_faim_protect */
+enum Tfa98xx_Error tfa98xx_faim_protect(struct tfa_device *tfa, int state)
+{
+ return (tfa->dev_ops.faim_protect)(tfa, state);
+}
+
+/*
+ * bring the device into a state similar to reset
+ */
+enum Tfa98xx_Error tfa98xx_init(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t value = 0;
+
+ /* reset all i2C registers to default
+ * Write the register directly to avoid the read in the bitfield function.
+ * The I2CR bit may overwrite the full register because it is reset anyway.
+ * This will save a reg read transaction.
+ */
+ TFA_SET_BF_VALUE(tfa, I2CR, 1, &value);
+ TFA_WRITE_REG(tfa, I2CR, value);
+
+ /* Put DSP in reset */
+ tfa98xx_dsp_reset(tfa, 1); /* in pair of tfaRunStartDSP() */
+
+ /* some other registers must be set for optimal amplifier behaviour
+ * This is implemented in a file specific for the type number
+ */
+ if (tfa->dev_ops.tfa_init)
+ error = (tfa->dev_ops.tfa_init)(tfa);
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ error = (tfa->dev_ops.dsp_write_tables)(tfa, sample_rate);
+
+ return error;
+}
+
+/** Set internal oscillator into power down mode.
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+enum Tfa98xx_Error tfa98xx_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ if (tfa->dev_ops.set_osc_powerdown) {
+ return tfa->dev_ops.set_osc_powerdown(tfa, state);
+ }
+
+ return Tfa98xx_Error_Not_Implemented;
+}
+
+/** update low power mode of the device.
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - LPMODE is on, 1 LPMODE is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+enum Tfa98xx_Error tfa98xx_update_lpm(struct tfa_device *tfa, int state)
+{
+ if (tfa->dev_ops.update_lpm) {
+ return tfa->dev_ops.update_lpm(tfa, state);
+ }
+
+ return Tfa98xx_Error_Not_Implemented;
+}
+/** Check presence of powerswitch=1 in configuration and optimal setting.
+*
+* @param[in] tfa device description structure
+*
+* @return -1 when error, 0 or 1 depends on switch settings.
+*/
+int tfa98xx_powerswitch_is_enabled(struct tfa_device *tfa)
+{
+ uint16_t value;
+ enum Tfa98xx_Error ret;
+
+ if (((tfa->rev & 0xff) == 0x13) || ((tfa->rev & 0xff) == 0x88)) {
+ ret = tfa_reg_read(tfa, 0xc6, &value);
+ if (ret != Tfa98xx_Error_Ok) {
+ return -1;
+ }
+ /* PLMA5539: Check actual value of powerswitch. TODO: regmap v1.40 should make this bit public. */
+
+ return (int)(value & (1u << 6));
+ }
+
+ return 1;
+}
+
+/********************* new tfa2 *********************************************************************/
+/* newly added messaging for tfa2 tfa1? */
+enum Tfa98xx_Error tfa98xx_dsp_get_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, unsigned char bytes[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ char msg[4 * 3];
+ int nr = 0;
+
+ msg[nr++] = 8;
+ msg[nr++] = MODULE_FRAMEWORK + 128;
+ msg[nr++] = FW_PAR_ID_GET_MEMORY;
+
+ msg[nr++] = 0;
+ msg[nr++] = 0;
+ msg[nr++] = (char)memoryType;
+
+ msg[nr++] = 0;
+ msg[nr++] = (offset >> 8) & 0xff;
+ msg[nr++] = offset & 0xff;
+
+ msg[nr++] = 0;
+ msg[nr++] = (length >> 8) & 0xff;
+ msg[nr++] = length & 0xff;
+
+ /* send msg */
+ error = tfa_dsp_msg(tfa, nr, (char *)msg);
+
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the device (length * 3) */
+ error = tfa_dsp_msg_read(tfa, length * 3, bytes);
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_set_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, int value)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int nr = 0;
+ char msg[5 * 3];
+
+ msg[nr++] = 8;
+ msg[nr++] = MODULE_FRAMEWORK + 128;
+ msg[nr++] = FW_PAR_ID_SET_MEMORY;
+
+ msg[nr++] = 0;
+ msg[nr++] = 0;
+ msg[nr++] = (char)memoryType;
+
+ msg[nr++] = 0;
+ msg[nr++] = (offset >> 8) & 0xff;
+ msg[nr++] = offset & 0xff;
+
+ msg[nr++] = 0;
+ msg[nr++] = (length >> 8) & 0xff;
+ msg[nr++] = length & 0xff;
+
+ msg[nr++] = (value >> 16) & 0xff;
+ msg[nr++] = (value >> 8) & 0xff;
+ msg[nr++] = value & 0xff;
+
+ /* send msg */
+ error = tfa_dsp_msg(tfa, nr, (char *)msg);
+
+ return error;
+}
+/****************************** calibration support **************************/
+/*
+ * get/set the mtp with user controllable values
+ *
+ * check if the relevant clocks are available
+ */
+enum Tfa98xx_Error tfa98xx_get_mtp(struct tfa_device *tfa, uint16_t *value)
+{
+ int status;
+ int result;
+
+ /* not possible if PLL in powerdown */
+ if (TFA_GET_BF(tfa, PWDN)) {
+ pr_debug("PLL in powerdown\n");
+ return Tfa98xx_Error_NoClock;
+ }
+
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (status == 0) {
+ pr_debug("PLL not running\n");
+ return Tfa98xx_Error_NoClock;
+ }
+
+ result = TFA_READ_REG(tfa, MTP0);
+ if (result < 0) {
+ return -result;
+ }
+ *value = (uint16_t)result;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/*
+ * lock or unlock KEY2
+ * lock = 1 will lock
+ * lock = 0 will unlock
+ *
+ * note that on return all the hidden key will be off
+ */
+void tfa98xx_key2(struct tfa_device *tfa, int lock)
+{
+ /* unhide lock registers */
+ tfa_reg_write(tfa, (tfa->tfa_family == 1) ? 0x40 : 0x0F, 0x5A6B);
+ /* lock/unlock key2 MTPK */
+ TFA_WRITE_REG(tfa, MTPKEY2, lock ? 0 : 0x5A);
+ /* unhide lock registers */
+ if (!tfa->advance_keys_handling) /*artf65038*/
+ tfa_reg_write(tfa, (tfa->tfa_family == 1) ? 0x40 : 0x0F, 0);
+}
+void tfa2_manual_mtp_cpy(struct tfa_device *tfa, uint16_t reg_row_to_keep, uint16_t reg_row_to_set, uint8_t row)///MCH_TO_TEST
+{
+ uint16_t value;
+ int loop = 0;
+ enum Tfa98xx_Error error;
+ /* Assure FAIM is enabled (enable it when neccesery) */
+ if (tfa->is_probus_device)
+ {
+ error = tfa98xx_faim_protect(tfa, 1);
+ if (tfa->verbose) {
+ pr_debug("FAIM enabled (err:%d).\n", error);
+ }
+ }
+ tfa_reg_read(tfa, (unsigned char)reg_row_to_keep, &value);
+ if (!row)
+ {
+ tfa_reg_write(tfa, 0xA7, value);
+ tfa_reg_write(tfa, 0xA8, reg_row_to_set);
+ }
+ else
+ {
+ tfa_reg_write(tfa, 0xA7, reg_row_to_set);
+ tfa_reg_write(tfa, 0xA8, value);
+ }
+ tfa_reg_write(tfa, 0xA3, 0x10 | row);
+ if (tfa->is_probus_device)
+ {
+ /* Assure FAIM is enabled (enable it when neccesery) */
+ for (loop = 0; loop < 100 /*x10ms*/; loop++) {
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ if (tfa_dev_get_mtpb(tfa) == 0)
+ break;
+ }
+ error = tfa98xx_faim_protect(tfa, 0);
+ if (tfa->verbose) {
+ pr_debug("FAIM disabled (err:%d).\n", error);
+ }
+ }
+}
+
+enum Tfa98xx_Error tfa98xx_set_mtp(struct tfa_device *tfa, uint16_t value, uint16_t mask)
+{
+ unsigned short mtp_old, mtp_new;
+ int loop, status;
+ enum Tfa98xx_Error error;
+
+ error = tfa98xx_get_mtp(tfa, &mtp_old);
+
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ mtp_new = (value & mask) | (mtp_old & ~mask);
+
+ if (mtp_old == mtp_new) /* no change */ {
+ if (tfa->verbose)
+ pr_info("No change in MTP. Value not written! \n");
+ return Tfa98xx_Error_Ok;
+ }
+ error = tfa98xx_update_lpm(tfa, 1);
+ if (error) {
+ return error;
+ }
+ /* Assure FAIM is enabled (enable it when neccesery) */
+ error = tfa98xx_faim_protect(tfa, 1);
+ if (error) {
+ return error;
+ }
+ if (tfa->verbose) {
+ pr_debug("MTP clock enabled.\n");
+ }
+
+ /* assure that the clock is up, else we can't write MTP */
+ error = tfa98xx_dsp_system_stable(tfa, &status);
+ if (error) {
+ return error;
+ }
+ if (status == 0) {
+ return Tfa98xx_Error_NoClock;
+ }
+
+ tfa98xx_key2(tfa, 0); /* unlock */
+ TFA_WRITE_REG(tfa, MTP0, mtp_new); /* write to i2c shadow reg */
+ /* CIMTP=1 start copying all the data from i2c regs_mtp to mtp*/
+ if (tfa->tfa_family == 2)
+ tfa2_manual_mtp_cpy(tfa, 0xF1, mtp_new, 0);
+ else
+ TFA_SET_BF(tfa, CIMTP, 1);
+ /* wait until MTP write is done */
+ error = Tfa98xx_Error_StateTimedOut;
+ for (loop = 0; loop < 100 /*x10ms*/; loop++) {
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ if (tfa_dev_get_mtpb(tfa) == 0) {
+ error = Tfa98xx_Error_Ok;
+ break;
+ }
+ }
+ tfa98xx_key2(tfa, 1); /* lock */
+ /* MTP setting failed due to timeout ?*/
+ if (error) {
+ tfa98xx_faim_protect(tfa, 0);
+ return error;
+ }
+
+ /* Disable the FAIM, if this is neccessary */
+ error = tfa98xx_faim_protect(tfa, 0);
+ if (error) {
+ return error;
+ }
+ if (tfa->verbose) {
+ pr_debug("MTP clock disabled.\n");
+ }
+ error = tfa98xx_update_lpm(tfa, 0);
+ if (error) {
+ return error;
+ }
+ return error;
+}
+/*
+ * clear mtpex
+ * set ACS
+ * start tfa
+ */
+int tfa_calibrate(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error;
+
+ /* clear mtpex */
+ error = tfa98xx_set_mtp(tfa, 0, TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK);
+ if (error)
+ return error;
+
+ /* set RST=1 to put the DSP in Reset */
+ TFA_SET_BF(tfa, RST, 1);
+
+ /* set ACS/coldboot state */
+ error = tfaRunColdboot(tfa, 1);
+
+ /* start tfa by playing */
+ return error;
+}
+
+static short twos(short x)
+{
+ return (x < 0) ? x + 512 : x;
+}
+
+void tfa98xx_set_exttemp(struct tfa_device *tfa, short ext_temp)
+{
+ if ((-256 <= ext_temp) && (ext_temp <= 255)) {
+ /* make twos complement */
+ pr_debug("Using ext temp %d C\n", twos(ext_temp));
+ TFA_SET_BF(tfa, TROS, 1);
+ TFA_SET_BF(tfa, EXTTS, twos(ext_temp));
+ }
+ else {
+ pr_debug("Clearing ext temp settings\n");
+ TFA_SET_BF(tfa, TROS, 0);
+ }
+}
+short tfa98xx_get_exttemp(struct tfa_device *tfa)
+{
+ short ext_temp = (short)TFA_GET_BF(tfa, EXTTS);
+ return (twos(ext_temp));
+}
+
+/************************** tfa simple bitfield interfacing ***************************************/
+/* convenience functions */
+enum Tfa98xx_Error tfa98xx_set_volume_level(struct tfa_device *tfa, unsigned short vol)
+{
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (vol > 255) /* restricted to 8 bits */
+ vol = 255;
+
+ /* 0x00 -> 0.0 dB
+ * 0x01 -> -0.5 dB
+ * ...
+ * 0xFE -> -127dB
+ * 0xFF -> muted
+ */
+
+ /* volume value is in the top 8 bits of the register */
+ return -TFA_SET_BF(tfa, VOL, (uint16_t)vol);
+}
+
+static enum Tfa98xx_Error
+tfa98xx_set_mute_tfa2(struct tfa_device *tfa, enum Tfa98xx_Mute mute)
+{
+ enum Tfa98xx_Error error;
+
+ if (tfa->dev_ops.set_mute == NULL)
+ return Tfa98xx_Error_Not_Supported;
+
+ switch (mute) {
+ case Tfa98xx_Mute_Off:
+ error = tfa->dev_ops.set_mute(tfa, 0);
+ TFA_SET_BF(tfa, AMPE, 1);
+ break;
+ case Tfa98xx_Mute_Amplifier:
+ case Tfa98xx_Mute_Digital:
+ error = tfa->dev_ops.set_mute(tfa, 1);
+ TFA_SET_BF(tfa, AMPE, 0);
+ break;
+ default:
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ return error;
+}
+
+static enum Tfa98xx_Error
+tfa98xx_set_mute_tfa1(struct tfa_device *tfa, enum Tfa98xx_Mute mute)
+{
+ enum Tfa98xx_Error error;
+ unsigned short audioctrl_value;
+ unsigned short sysctrl_value;
+ int value;
+
+ value = TFA_READ_REG(tfa, CFSM); /* audio control register */
+ if (value < 0)
+ return -value;
+ audioctrl_value = (unsigned short)value;
+ value = TFA_READ_REG(tfa, AMPE); /* system control register */
+ if (value < 0)
+ return -value;
+ sysctrl_value = (unsigned short)value;
+
+ switch (mute) {
+ case Tfa98xx_Mute_Off:
+ /* previous state can be digital or amplifier mute,
+ * clear the cf_mute and set the enbl_amplifier bits
+ *
+ * To reduce PLOP at power on it is needed to switch the
+ * amplifier on with the DCDC in follower mode
+ * (enbl_boost = 0 ?).
+ * This workaround is also needed when toggling the
+ * powerdown bit!
+ */
+ TFA_SET_BF_VALUE(tfa, CFSM, 0, &audioctrl_value);
+ TFA_SET_BF_VALUE(tfa, AMPE, 1, &sysctrl_value);
+ TFA_SET_BF_VALUE(tfa, DCA, 1, &sysctrl_value);
+ break;
+ case Tfa98xx_Mute_Digital:
+ /* expect the amplifier to run */
+ /* set the cf_mute bit */
+ TFA_SET_BF_VALUE(tfa, CFSM, 1, &audioctrl_value);
+ /* set the enbl_amplifier bit */
+ TFA_SET_BF_VALUE(tfa, AMPE, 1, &sysctrl_value);
+ /* clear active mode */
+ TFA_SET_BF_VALUE(tfa, DCA, 0, &sysctrl_value);
+ break;
+ case Tfa98xx_Mute_Amplifier:
+ /* clear the cf_mute bit */
+ TFA_SET_BF_VALUE(tfa, CFSM, 0, &audioctrl_value);
+ /* clear the enbl_amplifier bit and active mode */
+ TFA_SET_BF_VALUE(tfa, AMPE, 0, &sysctrl_value);
+ TFA_SET_BF_VALUE(tfa, DCA, 0, &sysctrl_value);
+ break;
+ default:
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ error = -TFA_WRITE_REG(tfa, CFSM, audioctrl_value);
+ if (error)
+ return error;
+ error = -TFA_WRITE_REG(tfa, AMPE, sysctrl_value);
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_set_mute(struct tfa_device *tfa, enum Tfa98xx_Mute mute)
+{
+ if (tfa->in_use == 0) {
+ pr_err("device is not opened \n");
+ return Tfa98xx_Error_NotOpen;
+ }
+
+ if (tfa->tfa_family == 1)
+ return tfa98xx_set_mute_tfa1(tfa, mute);
+ else
+ return tfa98xx_set_mute_tfa2(tfa, mute);
+}
+
+/****************** patching **********************************************************/
+static enum Tfa98xx_Error
+tfa98xx_process_patch_file(struct tfa_device *tfa, int length,
+ const unsigned char *bytes)
+{
+ unsigned short size;
+ int index = 0;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ while (index < length) {
+ size = bytes[index] + bytes[index + 1] * 256;
+ index += 2;
+ if ((index + size) > length) {
+ /* outside the buffer, error in the input data */
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (size > tfa->buffer_size) {
+ /* too big, must fit buffer */
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ error = tfa98xx_write_raw(tfa, size, &bytes[index]);
+ if (error != Tfa98xx_Error_Ok)
+ break;
+ index += size;
+ }
+ return error;
+}
+
+
+
+/* the patch contains a header with the following
+ * IC revision register: 1 byte, 0xFF means don't care
+ * XMEM address to check: 2 bytes, big endian, 0xFFFF means don't care
+ * XMEM value to expect: 3 bytes, big endian
+ */
+static enum Tfa98xx_Error
+tfa98xx_check_ic_rom_version(struct tfa_device *tfa, const unsigned char patchheader[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short checkrev, revid;
+ unsigned char lsb_revid;
+ unsigned short checkaddress;
+ int checkvalue;
+ int value = 0;
+ int status;
+ checkrev = patchheader[0];
+ lsb_revid = tfa->rev & 0xff; /* only compare lower byte */
+
+ if ((checkrev != 0xFF) && (checkrev != lsb_revid))
+ return Tfa98xx_Error_Not_Supported;
+
+ checkaddress = (patchheader[1] << 8) + patchheader[2];
+ checkvalue =
+ (patchheader[3] << 16) + (patchheader[4] << 8) + patchheader[5];
+ if (checkaddress != 0xFFFF) {
+ /* before reading XMEM, check if we can access the DSP */
+ error = tfa98xx_dsp_system_stable(tfa, &status);
+ if (error == Tfa98xx_Error_Ok) {
+ if (!status) {
+ /* DSP subsys not running */
+ error = Tfa98xx_Error_DSP_not_running;
+ }
+ }
+ /* read register to check the correct ROM version */
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfa_mem_read(tfa, checkaddress, 1, &value);
+ }
+ if (error == Tfa98xx_Error_Ok) {
+ if (value != checkvalue) {
+ pr_err("patch file romid type check failed [0x%04x]: expected 0x%02x, actual 0x%02x\n",
+ checkaddress, value, checkvalue);
+ error = Tfa98xx_Error_Not_Supported;
+ }
+ }
+ }
+ else { /* == 0xffff */
+ /* check if the revid subtype is in there */
+ if (checkvalue != 0xFFFFFF && checkvalue != 0) {
+ revid = patchheader[5] << 8 | patchheader[0]; /* full revid */
+ if (revid != tfa->rev) {
+ pr_err("patch file device type check failed: expected 0x%02x, actual 0x%02x\n",
+ tfa->rev, revid);
+ return Tfa98xx_Error_Not_Supported;
+ }
+ }
+ }
+
+ return error;
+}
+
+
+#define PATCH_HEADER_LENGTH 6
+enum Tfa98xx_Error
+ tfa_dsp_patch(struct tfa_device *tfa, int patchLength,
+ const unsigned char *patchBytes)
+{
+ enum Tfa98xx_Error error;
+ int status;
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (patchLength < PATCH_HEADER_LENGTH)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ error = tfa98xx_check_ic_rom_version(tfa, patchBytes);
+ if (Tfa98xx_Error_Ok != error) {
+ return error;
+ }
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status)
+ return Tfa98xx_Error_NoClock; // Only test when we have a clock.
+ /******MCH_TO_TEST**************/
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfaRunColdboot(tfa, 1);
+ if (error)
+ return Tfa98xx_Error_DSP_not_running;
+ }
+ /**************************/
+ error =
+ tfa98xx_process_patch_file(tfa, patchLength - PATCH_HEADER_LENGTH,
+ patchBytes + PATCH_HEADER_LENGTH);
+
+ return error;
+}
+
+/****************** end patching **********************************************************/
+
+TFA_INTERNAL enum Tfa98xx_Error
+tfa98xx_wait_result(struct tfa_device *tfa, int wait_retry_count)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int cf_status; /* the contents of the CF_STATUS register */
+ int tries = 0;
+ do {
+ cf_status = TFA_GET_BF(tfa, ACK);
+ if (cf_status < 0)
+ error = -cf_status;
+ tries++;
+ }
+ // i2c_cmd_ack
+ /* don't wait forever, DSP is pretty quick to respond (< 1ms) */
+ while ((error == Tfa98xx_Error_Ok) && ((cf_status & CF_STATUS_I2C_CMD_ACK) == 0)
+ && (tries < wait_retry_count));
+ if (tries >= wait_retry_count) {
+ /* something wrong with communication with DSP */
+ error = Tfa98xx_Error_DSP_not_running;
+ }
+ return error;
+}
+
+/*
+ * * support functions for data conversion
+ */
+ /**
+ convert memory bytes to signed 24 bit integers
+ input: bytes contains "num_bytes" byte elements
+ output: data contains "num_bytes/3" int24 elements
+ */
+void tfa98xx_convert_bytes2data(int num_bytes, const unsigned char bytes[],
+ int data[])
+{
+ int i; /* index for data */
+ int k; /* index for bytes */
+ int d;
+ int num_data = num_bytes / 3;
+ _ASSERT((num_bytes % 3) == 0);
+ for (i = 0, k = 0; i < num_data; ++i, k += 3) {
+ d = (bytes[k] << 16) | (bytes[k + 1] << 8) | (bytes[k + 2]);
+ _ASSERT(d >= 0);
+ _ASSERT(d < (1 << 24)); /* max 24 bits in use */
+ if (bytes[k] & 0x80) /* sign bit was set */
+ d = -((1 << 24) - d);
+
+ data[i] = d;
+ }
+}
+
+
+/**
+ convert signed 32 bit integers to 24 bit aligned bytes
+ input: data contains "num_data" int elements
+ output: bytes contains "3 * num_data" byte elements
+*/
+void tfa98xx_convert_data2bytes(int num_data, const int data[],
+ unsigned char bytes[])
+{
+ int i; /* index for data */
+ int k; /* index for bytes */
+ int d;
+ /* note: cannot just take the lowest 3 bytes from the 32 bit
+ * integer, because also need to take care of clipping any
+ * value > 2&23 */
+ for (i = 0, k = 0; i < num_data; ++i, k += 3) {
+ if (data[i] >= 0)
+ d = MIN(data[i], (1 << 23) - 1);
+ else {
+ /* 2's complement */
+ d = (1 << 24) - MIN(-data[i], 1 << 23);
+ }
+ _ASSERT(d >= 0);
+ _ASSERT(d < (1 << 24)); /* max 24 bits in use */
+ bytes[k] = (d >> 16) & 0xFF; /* MSB */
+ bytes[k + 1] = (d >> 8) & 0xFF;
+ bytes[k + 2] = (d) & 0xFF; /* LSB */
+ }
+}
+
+/*
+ * DSP RPC message support functions
+ * depending on framework to be up and running
+ * need base i2c of memaccess (tfa1=0x70/tfa2=0x90)
+ */
+
+
+ /* write dsp messages in function tfa_dsp_msg_rpc() */
+ /* note the 'old' write_parameter() was more efficient because all i2c was in one burst transaction */
+
+ //TODO properly handle bitfields: state should be restored! (now it will change eg dmesg field to xmem)
+enum Tfa98xx_Error tfa_dsp_msg_write(struct tfa_device *tfa, int length, const char *buffer)
+{
+ int offset = 0;
+ int chunk_size = ROUND_DOWN(tfa->buffer_size, 3); /* XMEM word size */
+ int remaining_bytes = length;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t cfctl;
+ int value;
+
+ value = TFA_READ_REG(tfa, DMEM);
+ if (value < 0) {
+ error = -value;
+ return error;
+ }
+ cfctl = (uint16_t)value;
+ /* assume no I2C errors from here */
+
+ TFA_SET_BF_VALUE(tfa, DMEM, (uint16_t)Tfa98xx_DMEM_XMEM, &cfctl); /* set cf ctl to DMEM */
+ TFA_SET_BF_VALUE(tfa, AIF, 0, &cfctl); /* set to autoincrement */
+ TFA_WRITE_REG(tfa, DMEM, cfctl);
+
+ /* xmem[1] is start of message
+ * direct write to register to save cycles avoiding read-modify-write
+ */
+ TFA_WRITE_REG(tfa, MADD, 1);
+
+ /* due to autoincrement in cf_ctrl, next write will happen at
+ * the next address */
+ while ((error == Tfa98xx_Error_Ok) && (remaining_bytes > 0)) {
+ if (remaining_bytes < chunk_size)
+ chunk_size = remaining_bytes;
+ /* else chunk_size remains at initialize value above */
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM,
+ chunk_size, (const unsigned char *)buffer + offset);
+ remaining_bytes -= chunk_size;
+ offset += chunk_size;
+ }
+
+ /* notify the DSP */
+ if (error == Tfa98xx_Error_Ok) {
+ /* cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
+ /* set the cf_req1 and cf_int bit */
+ TFA_SET_BF_VALUE(tfa, REQCMD, 0x01, &cfctl); /* bit 0 */
+ TFA_SET_BF_VALUE(tfa, CFINT, 1, &cfctl);
+ error = -TFA_WRITE_REG(tfa, CFINT, cfctl);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg_write_id(struct tfa_device *tfa, int length, const char *buffer, uint8_t cmdid[3])
+{
+ int offset = 0;
+ int chunk_size = ROUND_DOWN(tfa->buffer_size, 3); /* XMEM word size */
+ int remaining_bytes = length;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t cfctl;
+ int value;
+
+ value = TFA_READ_REG(tfa, DMEM);
+ if (value < 0) {
+ error = -value;
+ return error;
+ }
+ cfctl = (uint16_t)value;
+ /* assume no I2C errors from here */
+
+ TFA_SET_BF_VALUE(tfa, DMEM, (uint16_t)Tfa98xx_DMEM_XMEM, &cfctl); /* set cf ctl to DMEM */
+ TFA_SET_BF_VALUE(tfa, AIF, 0, &cfctl); /* set to autoincrement */
+ TFA_WRITE_REG(tfa, DMEM, cfctl);
+
+ /* xmem[1] is start of message
+ * direct write to register to save cycles avoiding read-modify-write
+ */
+ TFA_WRITE_REG(tfa, MADD, 1);
+
+ /* write cmd-id */
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM, 3, (const unsigned char *)cmdid);
+
+ /* due to autoincrement in cf_ctrl, next write will happen at
+ * the next address */
+ while ((error == Tfa98xx_Error_Ok) && (remaining_bytes > 0)) {
+ if (remaining_bytes < chunk_size)
+ chunk_size = remaining_bytes;
+ /* else chunk_size remains at initialize value above */
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM,
+ chunk_size, (const unsigned char *)buffer + offset);
+ remaining_bytes -= chunk_size;
+ offset += chunk_size;
+ }
+
+ /* notify the DSP */
+ if (error == Tfa98xx_Error_Ok) {
+ /* cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
+ /* set the cf_req1 and cf_int bit */
+ TFA_SET_BF_VALUE(tfa, REQCMD, 0x01, &cfctl); /* bit 0 */
+ TFA_SET_BF_VALUE(tfa, CFINT, 1, &cfctl);
+ error = -TFA_WRITE_REG(tfa, CFINT, cfctl);
+ }
+
+ return error;
+}
+
+/*
+* status function used by tfa_dsp_msg_rpc() to retrieve command/msg status:
+* return a <0 status of the DSP did not ACK.
+*/
+enum Tfa98xx_Error tfa_dsp_msg_status(struct tfa_device *tfa, int *pRpcStatus)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ error = tfa98xx_wait_result(tfa, 2); /* 2 is only one try */
+ if (error == Tfa98xx_Error_DSP_not_running) {
+ *pRpcStatus = -1;
+ return Tfa98xx_Error_Ok;
+ }
+ else if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ error = tfa98xx_check_rpc_status(tfa, pRpcStatus);
+
+ return error;
+}
+
+const char* tfa98xx_get_i2c_status_id_string(int status)
+{
+ const char* p_id_str;
+
+ switch (status)
+ {
+ case Tfa98xx_DSP_Not_Running:
+ p_id_str = "No response from DSP";
+ break;
+ case Tfa98xx_I2C_Req_Done:
+ p_id_str = "Ok";
+ break;
+ case Tfa98xx_I2C_Req_Busy:
+ p_id_str = "Request is being processed";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_M_ID:
+ p_id_str = "Provided M-ID does not fit in valid rang [0..2]";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_P_ID:
+ p_id_str = "Provided P-ID is not valid in the given M-ID context";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_CC:
+ p_id_str = "Invalid channel configuration bits (SC|DS|DP|DC) combination";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_Seq:
+ p_id_str = "Invalid sequence of commands, in case the DSP expects some commands in a specific order";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_Param:
+ p_id_str = "Generic error, invalid parameter";
+ break;
+ case Tfa98xx_I2C_Req_Buffer_Overflow:
+ p_id_str = "I2C buffer has overflowed: host has sent too many parameters, memory integrity is not guaranteed";
+ break;
+ case Tfa98xx_I2C_Req_Calib_Busy:
+ p_id_str = "Calibration not completed";
+ break;
+ case Tfa98xx_I2C_Req_Calib_Failed:
+ p_id_str = "Calibration failed";
+ break;
+
+ default:
+ p_id_str = "Unspecified error";
+ }
+
+ return p_id_str;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg_read_rpc(struct tfa_device *tfa, int length, unsigned char *bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int burst_size; /* number of words per burst size */
+ int bytes_per_word = 3;
+ int num_bytes;
+ int offset = 0;
+ unsigned short start_offset = 2; /* msg starts @xmem[2] ,[1]=cmd */
+
+ if (length > TFA2_MAX_PARAM_SIZE)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ TFA_SET_BF(tfa, DMEM, (uint16_t)Tfa98xx_DMEM_XMEM);
+ error = -TFA_WRITE_REG(tfa, MADD, start_offset);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ num_bytes = length; /* input param */
+ while (num_bytes > 0) {
+ burst_size = ROUND_DOWN(tfa->buffer_size, bytes_per_word);
+ if (num_bytes < burst_size)
+ burst_size = num_bytes;
+ error = tfa98xx_read_data(tfa, FAM_TFA98XX_CF_MEM, burst_size, bytes + offset);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ num_bytes -= burst_size;
+ offset += burst_size;
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg(struct tfa_device *tfa, int length24, const char *buf24)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int lastmessage = 0;
+ uint8_t *blob;
+ int i;
+ int *intbuf = NULL;
+ char* buf = (char *)buf24;
+ int length = length24;
+
+ if (tfa->convert_dsp32) {
+ int idx = 0;
+
+ length = 4 * length24 / 3;
+ intbuf = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ buf = (char *)intbuf;
+
+ /* convert 24 bit DSP messages to a 32 bit integer */
+ for (i = 0; i < length24; i += 3) {
+ int tmp = (buf24[i] << 16) + (buf24[i + 1] << 8) + buf24[i + 2];
+ /* Sign extend to 32-bit from 24-bit */
+ intbuf[idx++] = ((int32_t)tmp << 8) >> 8;
+ }
+ }
+
+ /* Only create multi-msg when the dsp is cold */
+ if (tfa->ext_dsp == 1) {
+ /* Creating the multi-msg */
+ error = tfa_tib_dsp_msgmulti(tfa, length, buf);
+ if (error == Tfa98xx_Error_Fail)
+ return Tfa98xx_Error_Fail;
+
+ /* if the buffer is full we need to send the existing message and add the current message */
+ if (error == Tfa98xx_Error_Buffer_too_small) {
+ int len;
+
+ /* (a) send the existing (full) message */
+ blob = kmalloc(64 * 1024, GFP_KERNEL); // max length is 64k
+ len = tfa_tib_dsp_msgmulti(tfa, -1, (const char*)blob);
+ if (tfa->verbose) {
+ pr_debug("Multi-message buffer full. Sending multi-message, length=%d \n", len);
+ }
+ if (tfa->has_msg == 0) /* via i2c */ {
+ /* Send tot the target selected */
+ error = (tfa->dev_ops.tfa_dsp_msg)(tfa, len, (const char*)blob);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_write_dsp(tfa, len, (const char*)blob);
+ }
+ kfree(blob);
+
+ /* (b) add the current DSP message to a new multi-message */
+ error = tfa_tib_dsp_msgmulti(tfa, length, buf);
+ if (error == Tfa98xx_Error_Fail) {
+ return Tfa98xx_Error_Fail;
+ }
+ }
+
+ lastmessage = error;
+
+ /* When the lastmessage is done we can send the multi-msg to the target */
+ if (lastmessage == 1) {
+
+ /* Get the full multi-msg data */
+ blob = kmalloc(64 * 1024, GFP_KERNEL); //max length is 64k
+ length = tfa_tib_dsp_msgmulti(tfa, -1, (const char*)blob);
+
+ if (tfa->verbose)
+ pr_debug("Last message for the multi-message received. Multi-message length=%d \n", length);
+
+ if (tfa->has_msg == 0) /* via i2c */ {
+ /* Send tot the target selected */
+ error = (tfa->dev_ops.tfa_dsp_msg)(tfa, length, (const char*)blob);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_write_dsp(tfa, length, (const char*)blob);
+ }
+
+ kfree(blob); /* Free the kmalloc blob */
+ lastmessage = 0; /* reset to be able to re-start */
+ }
+ }
+ else {
+ if (tfa->has_msg == 0) /* via i2c */ {
+ error = (tfa->dev_ops.tfa_dsp_msg)(tfa, length, buf);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_write_dsp(tfa, length, (const char*)buf);
+ }
+ }
+
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ /* DSP verbose has argument 0x04 */
+ if ((tfa->verbose & 0x04) != 0) {
+ pr_debug("DSP w [%d]: ", length);
+ for (i = 0; i < length; i++)
+ pr_debug("0x%02x ", (uint8_t)buf[i]);
+ pr_debug("\n");
+ }
+
+ if (tfa->convert_dsp32) {
+ kmem_cache_free(tfa->cachep, intbuf);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg_read(struct tfa_device *tfa, int length24, unsigned char *bytes24)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int i;
+ int length = length24;
+ unsigned char *bytes = bytes24;
+
+ if (tfa->convert_dsp32) {
+ length = 4 * length24 / 3;
+ bytes = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ }
+
+ if (tfa->has_msg == 0) /* via i2c */ {
+ error = (tfa->dev_ops.tfa_dsp_msg_read)(tfa, length, bytes);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_read_dsp(tfa, length, bytes);
+ }
+
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ /* DSP verbose has argument 0x04 */
+ if ((tfa->verbose & 0x04) != 0) {
+ pr_debug("DSP R [%d]: ", length);
+ for (i = 0; i < length; i++)
+ pr_debug("0x%02x ", (uint8_t)bytes[i]);
+ pr_debug("\n");
+ }
+
+ if (tfa->convert_dsp32) {
+ int idx = 0;
+
+ /* convert 32 bit LE to 24 bit BE */
+ for (i = 0; i < length; i += 4) {
+ bytes24[idx++] = bytes[i + 2];
+ bytes24[idx++] = bytes[i + 1];
+ bytes24[idx++] = bytes[i + 0];
+ }
+
+ kmem_cache_free(tfa->cachep, bytes);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_reg_read(struct tfa_device *tfa, unsigned char subaddress, unsigned short *value)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_reg_read)(tfa, subaddress, value);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_reg_write(struct tfa_device *tfa, unsigned char subaddress, unsigned short value)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_reg_write)(tfa, subaddress, value);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_mem_read(struct tfa_device *tfa, unsigned int start_offset, int num_words, int *pValues)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_mem_read)(tfa, start_offset, num_words, pValues);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_mem_write(struct tfa_device *tfa, unsigned short address, int value, int memtype)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_mem_write)(tfa, address, value, memtype);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+
+/*
+ * write/read raw msg functions :
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ */
+#define MAX_WORDS (300)
+enum Tfa98xx_Error tfa_dsp_msg_rpc(struct tfa_device *tfa, int length, const char *buf)
+{
+ enum Tfa98xx_Error error;
+ int tries, rpc_status = Tfa98xx_I2C_Req_Done;
+
+ /* write the message and notify the DSP */
+ error = tfa_dsp_msg_write(tfa, length, buf);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* get the result from the DSP (polling) */
+ for (tries = TFA98XX_WAITRESULT_NTRIES; tries > 0; tries--) {
+ error = tfa_dsp_msg_status(tfa, &rpc_status);
+ if (error == Tfa98xx_Error_Ok && rpc_status == Tfa98xx_I2C_Req_Done)
+ break;
+ /* If the rpc status is a specific error we want to know it.
+ * If it is busy or not running it should retry
+ */
+ if (rpc_status != Tfa98xx_I2C_Req_Busy && rpc_status != Tfa98xx_DSP_Not_Running)
+ break;
+ }
+
+ if (rpc_status != Tfa98xx_I2C_Req_Done) {
+ /* DSP RPC call returned an error */
+ error = (enum Tfa98xx_Error) (rpc_status + Tfa98xx_Error_RpcBase);
+ pr_debug("DSP msg status: %d (%s)\n", rpc_status, tfa98xx_get_i2c_status_id_string(rpc_status));
+ }
+ return error;
+}
+
+/**
+ * write/read raw msg functions:
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ * An ID is added to modify the command-ID
+ */
+enum Tfa98xx_Error tfa_dsp_msg_id(struct tfa_device *tfa, int length, const char *buf, uint8_t cmdid[3])
+{
+ enum Tfa98xx_Error error;
+ int tries, rpc_status = Tfa98xx_I2C_Req_Done;
+
+ /* write the message and notify the DSP */
+ error = tfa_dsp_msg_write_id(tfa, length, buf, cmdid);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* get the result from the DSP (polling) */
+ for (tries = TFA98XX_WAITRESULT_NTRIES; tries > 0; tries--) {
+ error = tfa_dsp_msg_status(tfa, &rpc_status);
+ if (error == Tfa98xx_Error_Ok && rpc_status == Tfa98xx_I2C_Req_Done)
+ break;
+ }
+
+ if (rpc_status != Tfa98xx_I2C_Req_Done) {
+ /* DSP RPC call returned an error */
+ error = (enum Tfa98xx_Error) (rpc_status + Tfa98xx_Error_RpcBase);
+ pr_debug("DSP msg status: %d (%s)\n", rpc_status, tfa98xx_get_i2c_status_id_string(rpc_status));
+ }
+ return error;
+}
+
+/* read the return code for the RPC call */
+TFA_INTERNAL enum Tfa98xx_Error
+tfa98xx_check_rpc_status(struct tfa_device *tfa, int *pRpcStatus)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ /* the value to sent to the * CF_CONTROLS register: cf_req=00000000,
+ * cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
+ unsigned short cf_ctrl = 0x0002;
+ /* memory address to be accessed (0: Status, 1: ID, 2: parameters) */
+ unsigned short cf_mad = 0x0000;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ if (pRpcStatus == NULL)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ /* 1) write DMEM=XMEM to the DSP XMEM */
+ {
+ /* minimize the number of I2C transactions by making use of the autoincrement in I2C */
+ unsigned char buffer[4];
+ /* first the data for CF_CONTROLS */
+ buffer[0] = (unsigned char)((cf_ctrl >> 8) & 0xFF);
+ buffer[1] = (unsigned char)(cf_ctrl & 0xFF);
+ /* write the contents of CF_MAD which is the subaddress following CF_CONTROLS */
+ buffer[2] = (unsigned char)((cf_mad >> 8) & 0xFF);
+ buffer[3] = (unsigned char)(cf_mad & 0xFF);
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_CONTROLS, sizeof(buffer), buffer);
+ }
+ if (error == Tfa98xx_Error_Ok) {
+ /* read 1 word (24 bit) from XMEM */
+ error = tfa98xx_dsp_read_mem(tfa, 0, 1, pRpcStatus);
+ }
+
+ return error;
+}
+
+/***************************** xmem only **********************************/
+enum Tfa98xx_Error
+ tfa98xx_dsp_read_mem(struct tfa_device *tfa,
+ unsigned int start_offset, int num_words, int *pValues)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned char *bytes;
+ int burst_size; /* number of words per burst size */
+ const int bytes_per_word = 3;
+ int dmem;
+ int num_bytes;
+ int *p;
+
+ bytes = (unsigned char *)kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (bytes == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* If no offset is given, assume XMEM! */
+ if (((start_offset >> 16) & 0xf) > 0)
+ dmem = (start_offset >> 16) & 0xf;
+ else
+ dmem = Tfa98xx_DMEM_XMEM;
+
+ /* Remove offset from adress */
+ start_offset = start_offset & 0xffff;
+ num_bytes = num_words * bytes_per_word;
+ p = pValues;
+
+ TFA_SET_BF(tfa, DMEM, (uint16_t)dmem);
+ error = -TFA_WRITE_REG(tfa, MADD, (unsigned short)start_offset);
+ if (error != Tfa98xx_Error_Ok)
+ goto tfa98xx_dsp_read_mem_exit;
+
+ for (; num_bytes > 0;) {
+ burst_size = ROUND_DOWN(tfa->buffer_size, bytes_per_word);
+ if (num_bytes < burst_size)
+ burst_size = num_bytes;
+
+ _ASSERT(burst_size <= sizeof(bytes));
+ error = tfa98xx_read_data(tfa, FAM_TFA98XX_CF_MEM, burst_size, bytes);
+ if (error != Tfa98xx_Error_Ok)
+ goto tfa98xx_dsp_read_mem_exit;
+
+ tfa98xx_convert_bytes2data(burst_size, bytes, p);
+
+ num_bytes -= burst_size;
+ p += burst_size / bytes_per_word;
+ }
+
+tfa98xx_dsp_read_mem_exit:
+ kmem_cache_free(tfa->cachep, bytes);
+
+ return error;
+}
+
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_mem_word(struct tfa_device *tfa, unsigned short address, int value, int memtype)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned char bytes[3];
+
+ TFA_SET_BF(tfa, DMEM, (uint16_t)memtype);
+
+ error = -TFA_WRITE_REG(tfa, MADD, address);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ tfa98xx_convert_data2bytes(1, &value, bytes);
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM, 3, bytes);
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_cont_write_filterbank(struct tfa_device *tfa, TfaFilter_t *filter)
+{
+ unsigned char biquad_index;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ for (biquad_index = 0; biquad_index < 10; biquad_index++) {
+ if (filter[biquad_index].enabled) {
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_BIQUADFILTERBANK,
+ biquad_index + 1, //start @1
+ sizeof(filter[biquad_index].biquad.bytes),
+ filter[biquad_index].biquad.bytes);
+ }
+ else {
+ error = Tfa98xx_DspBiquad_Disable(tfa, biquad_index + 1);
+ }
+ if (error) return error;
+
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ Tfa98xx_DspBiquad_Disable(struct tfa_device *tfa, int biquad_index)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int coeff_buffer[BIQUAD_COEFF_SIZE];
+ unsigned char bytes[3 + BIQUAD_COEFF_SIZE * 3];
+ int nr = 0;
+
+ if (biquad_index > TFA98XX_BIQUAD_NUM)
+ return Tfa98xx_Error_Bad_Parameter;
+ if (biquad_index < 1)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ /* make opcode */
+ bytes[nr++] = 0;
+ bytes[nr++] = MODULE_BIQUADFILTERBANK + 128;
+ bytes[nr++] = (unsigned char)biquad_index;
+
+
+ /* set in correct order and format for the DSP */
+ coeff_buffer[0] = (int)-8388608; /* -1.0f */
+ coeff_buffer[1] = 0;
+ coeff_buffer[2] = 0;
+ coeff_buffer[3] = 0;
+ coeff_buffer[4] = 0;
+ coeff_buffer[5] = 0;
+
+ /* convert to packed 24 */
+ tfa98xx_convert_data2bytes(BIQUAD_COEFF_SIZE, coeff_buffer, &bytes[nr]);
+ nr += BIQUAD_COEFF_SIZE * 3;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)bytes);
+
+ return error;
+}
+
+/* wrapper for tfa_dsp_msg that adds opcode */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ const unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char *buffer;
+ int nr = 0;
+
+ buffer = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (buffer == NULL)
+ return Tfa98xx_Error_Fail;
+
+ buffer[nr++] = tfa->spkr_select;
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ memcpy(&buffer[nr], data, num_bytes);
+ nr += num_bytes;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+
+ kmem_cache_free(tfa->cachep, buffer);
+
+ return error;
+}
+
+/* wrapper for tfa_dsp_msg that adds opcode */
+/* this is as the former tfa98xx_dsp_get_param() */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write_read(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char buffer[3];
+ int nr = 0;
+
+ if (num_bytes <= 0) {
+ pr_debug("Error: The number of READ bytes is smaller or equal to 0! \n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ if ((tfa->is_probus_device) && (tfa->cnt->ndev == 1) &&
+ (param_id == SB_PARAM_GET_RE25C ||
+ param_id == SB_PARAM_GET_LSMODEL ||
+ param_id == SB_PARAM_GET_ALGO_PARAMS)) {
+ /* Modifying the ID for GetRe25C */
+ buffer[nr++] = 4;
+ }
+ else {
+ buffer[nr++] = tfa->spkr_select;
+ }
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the dsp */
+ error = tfa_dsp_msg_read(tfa, num_bytes, data);
+ return error;
+}
+
+/* wrapper for dsp_msg that adds opcode and 3 bytes required for coefs */
+enum Tfa98xx_Error tfa_dsp_cmd_id_coefs(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char buffer[2 * 3];
+ int nr = 0;
+ char api_ver[4] = { 0 };
+
+ //Get rev id
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK, FW_PAR_ID_GET_API_VERSION, 3, api_ver);
+ buffer[nr++] = tfa->spkr_select;
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ if ((api_ver[1] < TFA_API_SBFW_8_09_00) || (api_ver[0] == 2)) { //(api_ver[0] == 2) is for 88 device
+
+ buffer[nr++] = 0;
+ buffer[nr++] = 0;
+ buffer[nr++] = 0;
+ }
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the dsp */
+ error = tfa_dsp_msg_read(tfa, num_bytes, data);
+
+ return error;
+}
+
+/* wrapper for dsp_msg that adds opcode and 3 bytes required for MBDrcDynamics */
+enum Tfa98xx_Error tfa_dsp_cmd_id_MBDrc_dynamics(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int index_subband,
+ int num_bytes, unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char buffer[2 * 3];
+ int nr = 0;
+
+ buffer[nr++] = tfa->spkr_select;
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ buffer[nr++] = 0;
+ buffer[nr++] = 0;
+ buffer[nr++] = (unsigned char)index_subband;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the dsp */
+ error = tfa_dsp_msg_read(tfa, num_bytes, data);
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_preset(struct tfa_device *tfa, int length,
+ const unsigned char *p_preset_bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ if (p_preset_bytes != NULL) {
+ /* by design: keep the data opaque and no
+ * interpreting/calculation */
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_PRESET, length,
+ p_preset_bytes);
+ }
+ else {
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ return error;
+}
+
+/*
+ * get features from MTP
+ */
+enum Tfa98xx_Error
+ tfa98xx_dsp_get_hw_feature_bits(struct tfa_device *tfa, int *features)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint32_t value;
+ uint16_t mtpbf;
+
+ /* return the cache data if it's valid */
+ if (tfa->hw_feature_bits != -1) {
+ *features = tfa->hw_feature_bits;
+ }
+ else {
+ /* for tfa1 check if we have clock */
+ if (tfa->tfa_family == 1) {
+ int status;
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status) {
+ tfa_get_hw_features_from_cnt(tfa, features);
+ /* skip reading MTP: */
+ return (*features == -1) ? Tfa98xx_Error_Fail : Tfa98xx_Error_Ok;
+ }
+ mtpbf = 0x850f; /* MTP5 for tfa1,16 bits */
+ }
+ else
+ mtpbf = 0xf907; /* MTP9 for tfa2, 8 bits */
+ value = tfa_read_reg(tfa, mtpbf) & 0xffff;
+ *features = tfa->hw_feature_bits = value;
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_get_sw_feature_bits(struct tfa_device *tfa, int features[2])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ const int byte_size = 2 * 3;
+ unsigned char bytes[2 * 3];
+
+ /* return the cache data if it's valid */
+ if (tfa->sw_feature_bits[0] != -1) {
+ features[0] = tfa->sw_feature_bits[0];
+ features[1] = tfa->sw_feature_bits[1];
+ }
+ else {
+ /* for tfa1 check if we have clock */
+ if (tfa->tfa_family == 1) {
+ int status;
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status) {
+ tfa_get_sw_features_from_cnt(tfa, features);
+ /* skip reading MTP: */
+ return (features[0] == -1) ? Tfa98xx_Error_Fail : Tfa98xx_Error_Ok;
+ }
+ }
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK,
+ FW_PAR_ID_GET_FEATURE_INFO, byte_size, bytes);
+
+ if (error != Tfa98xx_Error_Ok) {
+ /* old ROM code may respond with Tfa98xx_Error_RpcParamId */
+ return error;
+ }
+
+ tfa98xx_convert_bytes2data(byte_size, bytes, features);
+ }
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_get_state_info(struct tfa_device *tfa, unsigned char bytes[], unsigned int *statesize)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int bSupportFramework = 0;
+ unsigned int stateSize = 9;
+
+ err = tfa98xx_dsp_support_framework(tfa, &bSupportFramework);
+ if (err == Tfa98xx_Error_Ok) {
+ if (bSupportFramework) {
+ err = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK,
+ FW_PARAM_GET_STATE, 3 * stateSize, bytes);
+ }
+ else {
+ /* old ROM code, ask SpeakerBoost and only do first portion */
+ stateSize = 8;
+ err = tfa_dsp_cmd_id_write_read(tfa, MODULE_SPEAKERBOOST,
+ SB_PARAM_GET_STATE, 3 * stateSize, bytes);
+ }
+ }
+
+ *statesize = stateSize;
+
+ return err;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_support_drc(struct tfa_device *tfa, int *pbSupportDrc)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ *pbSupportDrc = 0;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ if (tfa->supportDrc != supportNotSet) {
+ *pbSupportDrc = (tfa->supportDrc == supportYes);
+ }
+ else {
+ int featureBits[2];
+
+ error = tfa98xx_dsp_get_sw_feature_bits(tfa, featureBits);
+ if (error == Tfa98xx_Error_Ok) {
+ /* easy case: new API available */
+ /* bit=0 means DRC enabled */
+ *pbSupportDrc = (featureBits[0] & FEATURE1_DRC) == 0;
+ }
+ else if (error == Tfa98xx_Error_RpcParamId) {
+ /* older ROM code, doesn't support it */
+ *pbSupportDrc = 0;
+ error = Tfa98xx_Error_Ok;
+ }
+ /* else some other error, return transparently */
+ /* pbSupportDrc only changed when error == Tfa98xx_Error_Ok */
+
+ if (error == Tfa98xx_Error_Ok) {
+ tfa->supportDrc = *pbSupportDrc ? supportYes : supportNo;
+ }
+ }
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_support_framework(struct tfa_device *tfa, int *pbSupportFramework)
+{
+ int featureBits[2] = { 0, 0 };
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ _ASSERT(pbSupportFramework != 0);
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (tfa->supportFramework != supportNotSet) {
+ if (tfa->supportFramework == supportNo)
+ *pbSupportFramework = 0;
+ else
+ *pbSupportFramework = 1;
+ }
+ else {
+ error = tfa98xx_dsp_get_sw_feature_bits(tfa, featureBits);
+ if (error == Tfa98xx_Error_Ok) {
+ *pbSupportFramework = 1;
+ tfa->supportFramework = supportYes;
+ }
+ else {
+ *pbSupportFramework = 0;
+ tfa->supportFramework = supportNo;
+ error = Tfa98xx_Error_Ok;
+ }
+ }
+
+ /* *pbSupportFramework only changed when error == Tfa98xx_Error_Ok */
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_speaker_parameters(struct tfa_device *tfa,
+ int length, const unsigned char *p_speaker_bytes)
+{
+ enum Tfa98xx_Error error;
+ int bSupportDrc;
+
+ if (p_speaker_bytes != NULL) {
+ /* by design: keep the data opaque and no
+ * interpreting/calculation */
+ /* Use long WaitResult retry count */
+ error = tfa_dsp_cmd_id_write(
+ tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_LSMODEL, length,
+ p_speaker_bytes);
+ }
+ else {
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ error = tfa98xx_dsp_support_drc(tfa, &bSupportDrc);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ if (bSupportDrc) {
+ /* Need to set AgcGainInsert back to PRE,
+ * as the SetConfig forces it to POST */
+ uint8_t bytes[3] = { 0, 0, 0 };
+
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_AGCINS,
+ 3,
+ bytes);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_config(struct tfa_device *tfa, int length,
+ const unsigned char *p_config_bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int bSupportDrc;
+
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_CONFIG, length,
+ p_config_bytes);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ error = tfa98xx_dsp_support_drc(tfa, &bSupportDrc);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ if (bSupportDrc) {
+ /* Need to set AgcGainInsert back to PRE,
+ * as the SetConfig forces it to POST */
+ uint8_t bytes[3] = { 0, 0, 0 };
+
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_AGCINS,
+ 3,
+ bytes);
+ }
+
+ return error;
+}
+
+/* load all the parameters for the DRC settings from a file */
+enum Tfa98xx_Error tfa98xx_dsp_write_drc(struct tfa_device *tfa,
+ int length, const unsigned char *p_drc_bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ if (p_drc_bytes != NULL) {
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_DRC, length,
+ p_drc_bytes);
+
+ }
+ else {
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_powerdown(struct tfa_device *tfa, int powerdown)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ error = TFA_SET_BF(tfa, PWDN, (uint16_t)powerdown);
+
+ if (powerdown) {
+ /* Workaround for ticket PLMA5337 */
+ if (tfa->tfa_family == 2) {
+ TFA_SET_BF_VOLATILE(tfa, AMPE, 0);
+ }
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_select_mode(struct tfa_device *tfa, enum Tfa98xx_Mode mode)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (error == Tfa98xx_Error_Ok) {
+ switch (mode) {
+
+ default:
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ return error;
+}
+
+int tfa_set_bf(struct tfa_device *tfa, const uint16_t bf, const uint16_t value)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue, msk, oldvalue;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err) {
+ pr_err("Error getting bf :%d \n", -err);
+ return -err;
+ }
+
+ oldvalue = regvalue;
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= ~msk;
+ regvalue |= value << pos;
+
+ /* Only write when the current register value is not the same as the new value */
+ if (oldvalue != regvalue) {
+ err = tfa_reg_write(tfa, address, regvalue);
+ if (err) {
+ pr_err("Error setting bf :%d \n", -err);
+ return -err;
+ }
+ }
+
+ return 0;
+}
+
+int tfa_set_bf_volatile(struct tfa_device *tfa, const uint16_t bf, const uint16_t value)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue, msk;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err) {
+ pr_err("Error getting bf :%d \n", -err);
+ return -err;
+ }
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= ~msk;
+ regvalue |= value << pos;
+
+ err = tfa_reg_write(tfa, address, regvalue);
+ if (err) {
+ pr_err("Error setting bf :%d \n", -err);
+ return -err;
+ }
+
+ return 0;
+}
+
+int tfa_get_bf(struct tfa_device *tfa, const uint16_t bf)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue, msk;
+ uint16_t value;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err) {
+ pr_err("Error getting bf :%d \n", -err);
+ return -err;
+ }
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= msk;
+ value = regvalue >> pos;
+
+ return value;
+}
+
+int tfa_set_bf_value(const uint16_t bf, const uint16_t bf_value, uint16_t *p_reg_value)
+{
+ uint16_t regvalue, msk;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+
+ regvalue = *p_reg_value;
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= ~msk;
+ regvalue |= bf_value << pos;
+
+ *p_reg_value = regvalue;
+
+ return 0;
+}
+
+uint16_t tfa_get_bf_value(const uint16_t bf, const uint16_t reg_value)
+{
+ uint16_t msk, value;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ value = (reg_value & msk) >> pos;
+
+ return value;
+}
+
+
+int tfa_write_reg(struct tfa_device *tfa, const uint16_t bf, const uint16_t reg_value)
+{
+ enum Tfa98xx_Error err;
+
+ /* bitfield enum - 8..15 : address */
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_write(tfa, address, reg_value);
+ if (err)
+ return -err;
+
+ return 0;
+}
+
+int tfa_read_reg(struct tfa_device *tfa, const uint16_t bf)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue;
+
+ /* bitfield enum - 8..15 : address */
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err)
+ return -err;
+
+ return regvalue;
+}
+
+/*
+ * powerup the coolflux subsystem and wait for it
+ */
+enum Tfa98xx_Error tfa_cf_powerup(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int tries, status;
+
+ /* power on the sub system */
+ TFA_SET_BF_VOLATILE(tfa, PWDN, 0);
+
+ // wait until everything is stable, in case clock has been off
+ if (tfa->verbose)
+ pr_info("Waiting for DSP system stable...\n");
+ for (tries = CFSTABLE_TRIES; tries > 0; tries--) {
+ err = tfa98xx_dsp_system_stable(tfa, &status);
+ _ASSERT(err == Tfa98xx_Error_Ok);
+ if (status)
+ break;
+ else
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ }
+ if (tries == 0) {// timedout
+ pr_err("DSP subsystem start timed out\n");
+ return Tfa98xx_Error_StateTimedOut;
+ }
+
+ return err;
+}
+
+/*
+ * Enable/Disable the I2S output for TFA1 devices
+ * without TDM interface
+ */
+static enum Tfa98xx_Error tfa98xx_aec_output(struct tfa_device *tfa, int enable)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if ((tfa->daimap & Tfa98xx_DAI_TDM) == Tfa98xx_DAI_TDM)
+ return err;
+
+ if (tfa->tfa_family == 1)
+ err = -tfa_set_bf(tfa, TFA1_BF_I2SDOE, (enable != 0));
+ else {
+ pr_err("I2SDOE on unsupported family\n");
+ err = Tfa98xx_Error_Not_Supported;
+ }
+
+ return err;
+}
+
+/*
+ * Print the current state of the hardware manager
+ * Device manager status information, man_state from TFA9888_N1B_I2C_regmap_V12
+ */
+int tfa_is_94_N2_device(struct tfa_device *tfa)
+{
+ return ((((tfa->rev) & 0xff) == 0x94) && (((tfa->rev >> 8) & 0xff) > 0x1a));
+}
+enum Tfa98xx_Error tfa_show_current_state(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int manstate = -1;
+
+ if (tfa->tfa_family == 2 && tfa->verbose) {
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ if (manstate < 0)
+ return -manstate;
+
+ pr_debug("Current HW manager state: ");
+
+ switch (manstate) {
+ case 0: pr_debug("power_down_state \n");
+ break;
+ case 1: pr_debug("wait_for_source_settings_state \n");
+ break;
+ case 2: pr_debug("connnect_pll_input_state \n");
+ break;
+ case 3: pr_debug("disconnect_pll_input_state \n");
+ break;
+ case 4: pr_debug("enable_pll_state \n");
+ break;
+ case 5: pr_debug("enable_cgu_state \n");
+ break;
+ case 6: pr_debug("init_cf_state \n");
+ break;
+ case 7: pr_debug("enable_amplifier_state \n");
+ break;
+ case 8: pr_debug("alarm_state \n");
+ break;
+ case 9: pr_debug("operating_state \n");
+ break;
+ case 10: pr_debug("mute_audio_state \n");
+ break;
+ case 11: pr_debug("disable_cgu_pll_state \n");
+ break;
+ default:
+ pr_debug("Unable to find current state \n");
+ break;
+ }
+ }
+
+ return err;
+}
+
+enum Tfa98xx_Error tfaGetFwApiVersion(struct tfa_device *tfa, unsigned char *pFirmwareVersion)
+{
+ enum Tfa98xx_Error err = 0;
+ char cmd_buf[4];
+ int cmd_len, res_len;
+
+ if (tfa == NULL)
+ return Tfa98xx_Error_Bad_Parameter;
+ if (!tfa->is_probus_device)
+ {
+ int buffer;
+ err = tfa_mem_read(tfa, FW_VAR_API_VERSION, 1, (int *)(&buffer));
+ if (err) {
+ pr_debug("%s Error: Unable to get API Version from DSP \n", __FUNCTION__);
+ return err;
+ }
+ pFirmwareVersion[0] = (buffer >> 16) & 0xff;
+ pFirmwareVersion[1] = (buffer >> 8) & 0xff;
+ if ((pFirmwareVersion[0] != 2) && (pFirmwareVersion[1] >= 33)) {
+ pFirmwareVersion[2] = (buffer >> 3) & 0x1F;
+ pFirmwareVersion[3] = (buffer) & 0x07;
+ } else {
+ pFirmwareVersion[2] = (buffer >> 6) & 0x03;
+ pFirmwareVersion[3] = (buffer) & 0x3f;
+ }
+ }
+ else
+ {
+ unsigned char buffer[4 * 3] = { 0 };
+ cmd_len = 0x03;
+
+ /* GetAPI: Command is 0x00 0x80 0xFE */
+ cmd_buf[0] = 0x00;
+ cmd_buf[1] = 0x80;
+ cmd_buf[2] = 0xFE;
+
+ /* Write the command.*/
+
+ err = tfa98xx_write_dsp(tfa, cmd_len, (const char *)cmd_buf);
+
+ /* Read the API Value.*/
+ if (err == 0)
+ {
+ res_len = 3;
+ err = tfa98xx_read_dsp(tfa, res_len, (unsigned char *)buffer);
+
+ }
+
+ /* Split 3rd byte into two seperate ITF version fields (3rd field and 4th field) */
+ pFirmwareVersion[0] = (buffer[0]);
+ pFirmwareVersion[1] = (buffer[1]);
+ if ((pFirmwareVersion[0] != 2) && (pFirmwareVersion[1] >= 33)) {
+ pFirmwareVersion[3] = (buffer[2]) & 0x07;
+ pFirmwareVersion[2] = (buffer[2] >> 3) & 0x1F;
+ } else {
+ pFirmwareVersion[3] = (buffer[2]) & 0x3f;
+ pFirmwareVersion[2] = (buffer[2] >> 6) & 0x03;
+ }
+ }
+
+ if (1 == tfa->cnt->ndev) {
+ /* Mono configuration */
+ /* Workaround for FW 8.9.0 (FW API x.31.y.z) & above.
+ Firmware cannot return the 4th field (mono/stereo) of ITF version correctly, as it requires
+ certain set of messages to be sent before it can detect itself as a mono/stereo configuration.
+ Hence, HostSDK need to handle this at system level */
+ if ((pFirmwareVersion[0] == 8) && (pFirmwareVersion[1] >= 31)) {
+ pFirmwareVersion[3] = 1;
+ }
+ }
+
+
+ return err;
+
+}
+
+
+/*
+ * start the speakerboost algorithm
+ * this implies a full system startup when the system was not already started
+ *
+ */
+enum Tfa98xx_Error tfaRunSpeakerBoost(struct tfa_device *tfa, int force, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int value;
+
+ if (force) {
+ err = tfaRunColdStartup(tfa, profile);
+ if (err) return err;
+ }
+
+ /* Returns 1 when device is "cold" and 0 when device is warm */
+ value = tfa_is_cold(tfa);
+
+ pr_debug("Startup of device [%s] is a %sstart\n", tfaContDeviceName(tfa->cnt, tfa->dev_idx), value ? "cold" : "warm");
+ /* cold start and not tap profile */
+ if (value) {
+ /* Run startup and write all files */
+ err = tfaRunSpeakerStartup(tfa, force, profile);
+ if (err) return err;
+
+ /* Save the current profile and set the vstep to 0 */
+ /* This needs to be overwriten even in CF bypass */
+ tfa_dev_set_swprof(tfa, (unsigned short)profile);
+ tfa_dev_set_swvstep(tfa, 0);
+
+ /* Synchonize I/V delay on 96/97 at cold start */
+ if ((tfa->tfa_family == 1) && (tfa->daimap == Tfa98xx_DAI_TDM))
+ tfa->sync_iv_delay = 1;
+ }
+
+ return err;
+}
+
+enum Tfa98xx_Error tfaRunSpeakerStartup(struct tfa_device *tfa, int force, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!force) { // in case of force CF already runnning
+ err = tfaRunStartup(tfa, profile);
+ PRINT_ASSERT(err);
+ if (err)
+ return err;
+
+ /* Startup with CF in bypass then return here */
+ if (tfa_cf_enabled(tfa) == 0)
+ return err;
+
+ /* respond to external DSP: -1:none, 0:no_dsp, 1:cold, 2:warm */
+ if (tfa->ext_dsp == -1) {
+ err = tfaRunStartDSP(tfa);
+ if (err)
+ return err;
+ }
+ }
+
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1 */
+ tfa98xx_auto_copy_mtp_to_iic(tfa);
+
+ err = tfaGetFwApiVersion(tfa, (unsigned char *)&tfa->fw_itf_ver[0]);
+ if (err) {
+ pr_debug("[%s] cannot get FWAPI error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+ /* write all the files from the device list */
+ err = tfaContWriteFiles(tfa);
+ if (err) {
+ pr_debug("[%s] tfaContWriteFiles error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+
+ /* write all the files from the profile list (use volumstep 0) */
+ err = tfaContWriteFilesProf(tfa, profile, 0);
+ if (err) {
+ pr_debug("[%s] tfaContWriteFilesProf error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+
+ return err;
+}
+
+/*
+ * Run calibration
+ */
+enum Tfa98xx_Error tfaRunSpeakerCalibration(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int calibrateDone;
+
+ /* return if there is no audio running */
+ if ((tfa->tfa_family == 2) && TFA_GET_BF(tfa, NOCLK))
+ return Tfa98xx_Error_NoClock;
+
+ /* When MTPOTC is set (cal=once) unlock key2 */
+ if (TFA_GET_BF(tfa, MTPOTC) == 1) {
+ tfa98xx_key2(tfa, 0);
+ }
+
+ /* await calibration, this should return ok */
+ err = tfaRunWaitCalibration(tfa, &calibrateDone);
+ if (err == Tfa98xx_Error_Ok) {
+ err = tfa_dsp_get_calibration_impedance(tfa);
+ PRINT_ASSERT(err);
+ }
+
+ /* When MTPOTC is set (cal=once) re-lock key2 */
+ if (TFA_GET_BF(tfa, MTPOTC) == 1) {
+ tfa98xx_key2(tfa, 1);
+ }
+
+ return err;
+}
+
+enum Tfa98xx_Error tfaRunColdboot(struct tfa_device *tfa, int state)
+{
+#define CF_CONTROL 0x8100
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int tries = 10;
+
+ /* repeat set ACS bit until set as requested */
+ while (state != TFA_GET_BF(tfa, ACS)) {
+ /* set colstarted in CF_CONTROL to force ACS */
+ err = tfa_mem_write(tfa, CF_CONTROL, state, Tfa98xx_DMEM_IOMEM);
+ PRINT_ASSERT(err);
+
+ if (tries-- == 0) {
+ pr_debug("coldboot (ACS) did not %s\n", state ? "set" : "clear");
+ return Tfa98xx_Error_Other;
+ }
+ }
+
+ return err;
+}
+
+
+
+/*
+ * load the patch if any
+ * else tell no loaded
+ */
+static enum Tfa98xx_Error tfa_run_load_patch(struct tfa_device *tfa)
+{
+ return tfaContWritePatch(tfa);
+}
+
+/*
+ * this will load the patch witch will implicitly start the DSP
+ * if no patch is available the DPS is started immediately
+ */
+enum Tfa98xx_Error tfaRunStartDSP(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ err = tfa_run_load_patch(tfa);
+ if (err) { /* patch load is fatal so return immediately*/
+ return err;
+ }
+
+ /* Clear count_boot, should be reset to 0 before the DSP reset is released */
+ err = tfa_mem_write(tfa, 512, 0, Tfa98xx_DMEM_XMEM);
+ PRINT_ASSERT(err);
+
+ /* Reset DSP once for sure after initializing */
+ if (err == Tfa98xx_Error_Ok) {
+ err = tfa98xx_dsp_reset(tfa, 0);
+ PRINT_ASSERT(err);
+ }
+
+ /* Sample rate is needed to set the correct tables */
+ err = tfa98xx_dsp_write_tables(tfa, TFA_GET_BF(tfa, AUDFS));
+ PRINT_ASSERT(err);
+
+ return err;
+}
+
+/*
+ * start the clocks and wait until the AMP is switching
+ * on return the DSP sub system will be ready for loading
+ */
+enum Tfa98xx_Error tfaRunStartup(struct tfa_device *tfa, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ int i, noinit = 0, audfs = 0, fractdel = 0;
+
+ if (dev == NULL)
+ return Tfa98xx_Error_Fail;
+
+ if (dev->bus) /* no i2c device, do nothing */
+ return Tfa98xx_Error_Ok;
+
+ /* process the device list to see if the user implemented the noinit */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscNoInit) {
+ noinit = 1;
+ break;
+ }
+ }
+
+ if (!noinit) {
+ /* Read AUDFS & FRACTDEL prior to (re)init. */
+ audfs = TFA_GET_BF(tfa, AUDFS);
+ fractdel = TFA_GET_BF(tfa, FRACTDEL);
+ /* load the optimal TFA98XX in HW settings */
+ err = tfa98xx_init(tfa);
+ PRINT_ASSERT(err);
+
+ /* Restore audfs & fractdel after coldboot, so we can calibrate with correct fs setting.
+ * in case something else was given in cnt file, profile below will apply this. */
+ TFA_SET_BF(tfa, AUDFS, audfs);
+ TFA_SET_BF(tfa, FRACTDEL, fractdel);
+#ifdef __KERNEL__
+ if ((tfa->dynamicTDMmode == 3) && tfa_dev_set_tdm_bitwidth(tfa,tfa->bitwidth))
+ return Tfa98xx_Error_Fail;
+#endif//
+ }
+ else {
+ pr_debug("\nWarning: No init keyword found in the cnt file. Init is skipped! \n");
+ }
+
+ /* I2S settings to define the audio input properties
+ * these must be set before the subsys is up */
+ // this will run the list until a non-register item is encountered
+ err = tfaContWriteRegsDev(tfa); // write device register settings
+ PRINT_ASSERT(err);
+ // also write register the settings from the default profile
+ // NOTE we may still have ACS=1 so we can switch sample rate here
+ err = tfaContWriteRegsProf(tfa, profile);
+ PRINT_ASSERT(err);
+
+ /* Factory trimming for the Boost converter */
+ tfa98xx_factory_trimmer(tfa);
+#ifdef __KERNEL__
+#if 0
+ /* Control for PWM phase shift */
+ if (tfa->bitwidth == 24 && tfa->rate == 16)/*TFA9875-240*/
+ tfa98xx_set_phase_shift(tfa);
+#endif
+#endif
+ /* Go to the initCF state */
+ tfa_dev_set_state(tfa, TFA_STATE_INIT_CF, strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, profile), ".cal") != NULL);
+
+ err = tfa_show_current_state(tfa);
+
+ return err;
+}
+
+/*
+ * run the startup/init sequence and set ACS bit
+ */
+enum Tfa98xx_Error tfaRunColdStartup(struct tfa_device *tfa, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ err = tfaRunStartup(tfa, profile);
+ PRINT_ASSERT(err);
+ if (err)
+ return err;
+
+ if (!tfa->is_probus_device) {
+ /* force cold boot */
+ err = tfaRunColdboot(tfa, 1); // set ACS
+ PRINT_ASSERT(err);
+ if (err)
+ return err;
+ }
+
+ /* start */
+ err = tfaRunStartDSP(tfa);
+ PRINT_ASSERT(err);
+
+ return err;
+}
+
+/*
+ *
+ */
+enum Tfa98xx_Error tfaRunMute(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int status;
+ int tries = 0;
+
+ /* signal the TFA98XX to mute */
+ if (tfa->tfa_family == 1) {
+ err = tfa98xx_set_mute(tfa, Tfa98xx_Mute_Amplifier);
+
+ if (err == Tfa98xx_Error_Ok) {
+ /* now wait for the amplifier to turn off */
+ do {
+ status = TFA_GET_BF(tfa, SWS);
+ if (status != 0)
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ else
+ break;
+ tries++;
+ } while (tries < AMPOFFWAIT_TRIES);
+
+
+ if (tfa->verbose)
+ pr_debug("-------------------- muted --------------------\n");
+
+ /*The amplifier is always switching*/
+ if (tries == AMPOFFWAIT_TRIES)
+ return Tfa98xx_Error_Other;
+ }
+ }
+
+ return err;
+}
+/*
+ *
+ */
+enum Tfa98xx_Error tfaRunUnmute(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ /* signal the TFA98XX to mute */
+ err = tfa98xx_set_mute(tfa, Tfa98xx_Mute_Off);
+
+ if (tfa->verbose)
+ pr_debug("-------------------unmuted ------------------\n");
+
+ return err;
+}
+
+static void individual_calibration_results(struct tfa_device *tfa)
+{
+ int value_P, value_S;
+
+ /* Read the calibration result in xmem (529=primary channel) (530=secondary channel) */
+ tfa_mem_read(tfa, 529, 1, &value_P);
+ tfa_mem_read(tfa, 530, 1, &value_S);
+
+ if (value_P != 1 && value_S != 1)
+ pr_debug("Calibration failed on both channels! \n");
+ else if (value_P != 1) {
+ pr_debug("Calibration failed on Primary (Left) channel! \n");
+ TFA_SET_BF_VOLATILE(tfa, SSLEFTE, 0); /* Disable the sound for the left speaker */
+ }
+ else if (value_S != 1) {
+ pr_debug("Calibration failed on Secondary (Right) channel! \n");
+ TFA_SET_BF_VOLATILE(tfa, SSRIGHTE, 0); /* Disable the sound for the right speaker */
+ }
+
+ TFA_SET_BF_VOLATILE(tfa, AMPINSEL, 0); /* Set amplifier input to TDM */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+}
+
+/*
+ * wait for calibrateDone
+ */
+enum Tfa98xx_Error tfaRunWaitCalibration(struct tfa_device *tfa, int *calibrateDone)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int tries = 0, mtp_busy = 1, tries_mtp_busy = 0;
+
+ *calibrateDone = 0;
+
+ /* in case of calibrate once wait for MTPEX */
+ if (TFA_GET_BF(tfa, MTPOTC)) {
+ // Check if MTP_busy is clear!
+ while (tries_mtp_busy < MTPBWAIT_TRIES)
+ {
+ mtp_busy = tfa_dev_get_mtpb(tfa);
+ if (mtp_busy == 1)
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ else
+ break;
+ tries_mtp_busy++;
+ }
+
+ if (tries_mtp_busy < MTPBWAIT_TRIES) {
+ /* Because of the msleep TFA98XX_API_WAITRESULT_NTRIES is way to long!
+ * Setting this to 25 will take it atleast 25*50ms = 1.25 sec
+ */
+ while ((*calibrateDone == 0) && (tries < MTPEX_WAIT_NTRIES)) {
+ *calibrateDone = TFA_GET_BF(tfa, MTPEX);
+ if (*calibrateDone == 1)
+ break;
+ msleep_interruptible(50); /* wait 50ms to avoid busload */
+ tries++;
+ }
+
+ if (tries >= MTPEX_WAIT_NTRIES) {
+ tries = TFA98XX_API_WAITRESULT_NTRIES;
+ }
+ }
+ else {
+ pr_err("MTP bussy after %d tries\n", MTPBWAIT_TRIES);
+ }
+ }
+
+ /* poll xmem for calibrate always
+ * calibrateDone = 0 means "calibrating",
+ * calibrateDone = -1 (or 0xFFFFFF) means "fails"
+ * calibrateDone = 1 means calibration done
+ */
+ while ((*calibrateDone != 1) && (tries < TFA98XX_API_WAITRESULT_NTRIES)) {
+ err = tfa_mem_read(tfa, TFA_FW_XMEM_CALIBRATION_DONE, 1, calibrateDone);
+ if (*calibrateDone == -1)
+ break;
+ tries++;
+ }
+
+ if (*calibrateDone != 1) {
+ pr_err("Calibration failed! \n");
+ err = Tfa98xx_Error_Bad_Parameter;
+ }
+ else if (tries == TFA98XX_API_WAITRESULT_NTRIES) {
+ pr_debug("Calibration has timedout! \n");
+ err = Tfa98xx_Error_StateTimedOut;
+ }
+ else if (tries_mtp_busy == 1000) {
+ pr_err("Calibrate Failed: MTP_busy stays high! \n");
+ err = Tfa98xx_Error_StateTimedOut;
+ }
+
+ /* Give reason why calibration failed! */
+ if (err != Tfa98xx_Error_Ok) {
+ if ((tfa->tfa_family == 2) && (TFA_GET_BF(tfa, REFCKSEL) == 1)) {
+ pr_err("Unable to calibrate the device with the internal clock! \n");
+ }
+ }
+
+ /* Check which speaker calibration failed. Only for 88C */
+ if ((err != Tfa98xx_Error_Ok) && ((tfa->rev & 0x0FFF) == 0xc88)) {
+ individual_calibration_results(tfa);
+ }
+
+ return err;
+}
+
+/*
+ * tfa_dev_start will only do the basics: Going from powerdown to operating or a profile switch.
+ * for calibrating or akoustic shock handling use the tfa98xxCalibration function.
+ */
+enum tfa_error tfa_dev_start(struct tfa_device *tfa, int next_profile, int vstep)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int active_profile = -1;
+
+ /* Get currentprofile */
+ active_profile = tfa_dev_get_swprof(tfa);
+ if (active_profile == 0xff)
+ active_profile = -1;
+
+ /* TfaRun_SpeakerBoost implies un-mute */
+ pr_debug("Active_profile:%s, next_profile:%s\n",
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, active_profile),
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, next_profile));
+
+ err = tfa_show_current_state(tfa);
+
+ if (tfa->tfa_family == 1) { /* TODO move this to ini file */
+ /* Enable I2S output on TFA1 devices without TDM */
+ err = tfa98xx_aec_output(tfa, 1);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+ }
+
+ if (tfa->bus != 0) { /* non i2c */
+#ifndef __KERNEL__
+ tfadsp_fw_start(tfa, next_profile, vstep);
+#endif /* __KERNEL__ */
+ }
+ else {
+ /* Check if we need coldstart or ACS is set */
+ err = tfaRunSpeakerBoost(tfa, 0, next_profile);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, next_profile), ".standby") != NULL) {
+ pr_info("Skip powering on device, in standby profile!\n");
+ } else {
+ /* Make sure internal oscillator is running for DSP devices (non-dsp and max1 this is no-op) */
+ tfa98xx_set_osc_powerdown(tfa, 0);
+
+ /* Go to the Operating state */
+ tfa_dev_set_state(tfa, TFA_STATE_OPERATING | TFA_STATE_MUTE, 0);
+ }
+ }
+ active_profile = tfa_dev_get_swprof(tfa);
+
+ /* Profile switching */
+ if ((next_profile != active_profile && active_profile >= 0)) {
+ err = tfaContWriteProfile(tfa, next_profile, vstep);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+ }
+
+ /* If the profile contains the .standby suffix go to powerdown
+ * else we should be in operating state
+ */
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, next_profile), ".standby") != NULL) {
+ tfa_dev_set_swprof(tfa, (unsigned short)next_profile);
+ tfa_dev_set_swvstep(tfa, (unsigned short)vstep);
+
+ pr_info("Power down device, by force, in standby profile!\n");
+ err = tfa_dev_stop(tfa);
+ goto error_exit;
+ }
+
+ err = tfa_show_current_state(tfa);
+
+ if ((TFA_GET_BF(tfa, CFE) != 0) && (vstep != tfa->vstep) && (vstep != -1)) {
+ err = tfaContWriteFilesVstep(tfa, next_profile, vstep);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+ }
+
+ /* Always search and apply filters after a startup */
+ err = tfa_set_filters(tfa, next_profile);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+
+ tfa_dev_set_swprof(tfa, (unsigned short)next_profile);
+ tfa_dev_set_swvstep(tfa, (unsigned short)vstep);
+
+ /* PLMA5539: Gives information about current setting of powerswitch */
+ if (tfa->verbose) {
+ if (!tfa98xx_powerswitch_is_enabled(tfa))
+ pr_info("Device start without powerswitch enabled!\n");
+ }
+
+error_exit:
+ tfa_show_current_state(tfa);
+
+ return err;
+}
+
+enum tfa_error tfa_dev_stop(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ /* mute */
+ tfaRunMute(tfa);
+
+ /* Make sure internal oscillator is not running for DSP devices (non-dsp and max1 this is no-op) */
+ tfa98xx_set_osc_powerdown(tfa, 1);
+
+ /* powerdown CF */
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+
+ /* disable I2S output on TFA1 devices without TDM */
+ err = tfa98xx_aec_output(tfa, 0);
+
+ return err;
+}
+
+/*
+ * int registers and coldboot dsp
+ */
+int tfa_reset(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int state = -1;
+ int retry_cnt = 0;
+
+ /* Check device state. Print warning if reset is done from other state than powerdown (when verbose) */
+ state = tfa_dev_get_state(tfa);
+ if (tfa->verbose) {
+ if (((tfa->tfa_family == 1) && state != TFA_STATE_RESET) ||
+ ((tfa->tfa_family == 2) && state != TFA_STATE_POWERDOWN)) {
+ pr_info("WARNING: Device reset should be performed in POWERDOWN state\n");
+ }
+ }
+
+ /* Split TFA1 behavior from TFA2*/
+ if (tfa->tfa_family == 1) {
+ err = TFA_SET_BF(tfa, I2CR, 1);
+ if (err)
+ return err;
+ err = tfa98xx_powerdown(tfa, 0);
+ if (err)
+ return err;
+ err = tfa_cf_powerup(tfa);
+ if (err)
+ return err;
+ err = tfaRunColdboot(tfa, 1);
+ if (err)
+ return err;
+ err = TFA_SET_BF(tfa, I2CR, 1);
+ }
+ else {
+ /* Probus devices needs extra protection to ensure proper reset
+ behavior, this step is valid only in state other than powerdown */
+ if (tfa->is_probus_device && state != TFA_STATE_POWERDOWN) {
+ err = TFA_SET_BF_VOLATILE(tfa, AMPE, 0);
+ if (err)
+ return err;
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err)
+ return err;
+ }
+
+ err = TFA_SET_BF_VOLATILE(tfa, I2CR, 1);
+ if (err)
+ return err;
+
+ /* Restore MANSCONF to POR state */
+ err = TFA_SET_BF_VOLATILE(tfa, MANSCONF, 0);
+ if (err)
+ return err;
+
+ /* Probus devices HW are already reseted here,
+ Last step is to send init message to softDSP */
+ if (tfa->is_probus_device) {
+ if (tfa->ext_dsp > 0) {
+ err = tfa98xx_init_dsp(tfa);
+ /* ext_dsp status from warm to cold after reset */
+ if (tfa->ext_dsp == 2) {
+ tfa->ext_dsp = 1;
+ }
+ }
+ }
+ else {
+ /* Restore MANCOLD to POR state */
+ TFA_SET_BF_VOLATILE(tfa, MANCOLD, 1);
+
+ /* Coolflux has to be powered on to ensure proper ACS
+ bit state */
+
+ /* Powerup CF to access CF io */
+ err = tfa98xx_powerdown(tfa, 0);
+ if (err)
+ return err;
+
+ /* For clock */
+ err = tfa_cf_powerup(tfa);
+ if (err)
+ return err;
+
+ /* Force cold boot */
+ err = tfaRunColdboot(tfa, 1); /* Set ACS */
+ if (err)
+ return err;
+
+ /* Set PWDN = 1, this will transfer device into powerdown state */
+ err = TFA_SET_BF_VOLATILE(tfa, PWDN, 1);
+ if (err)
+ return err;
+
+ /* 88 needs SBSL on top of PWDN bit to start transition,
+ for 92 and 94 this doesn't matter */
+ err = TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+ if (err)
+ return err;
+
+ /* Powerdown state should be reached within 1ms */
+ for (retry_cnt = 0; retry_cnt < TFA98XX_WAITRESULT_NTRIES; retry_cnt++) {
+ if (tfa_is_94_N2_device(tfa))
+ state = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ state = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ state = TFA_GET_BF(tfa, MANSTATE);
+ if (state < 0) {
+ return err;
+ }
+
+ /* Check for MANSTATE=Powerdown (0) */
+ if (state == 0)
+ break;
+ msleep_interruptible(2);
+ }
+
+ /* Reset all I2C registers to default values,
+ now device state is consistent, same as after powerup */
+ err = TFA_SET_BF(tfa, I2CR, 1);
+ }
+ }
+
+ return err;
+}
+
+/*
+ * Write all the bytes specified by num_bytes and data
+ */
+enum Tfa98xx_Error
+ tfa98xx_write_data(struct tfa_device *tfa,
+ unsigned char subaddress, int num_bytes,
+ const unsigned char data[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ /* subaddress followed by data */
+ const int bytes2write = num_bytes + 1;
+ unsigned char *write_data;
+
+ if (num_bytes > TFA2_MAX_PARAM_SIZE)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ write_data = (unsigned char *)kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (write_data == NULL)
+ return Tfa98xx_Error_Fail;
+
+ write_data[0] = subaddress;
+ memcpy(&write_data[1], data, num_bytes);
+
+ error = tfa98xx_write_raw(tfa, bytes2write, write_data);
+
+ kmem_cache_free(tfa->cachep, write_data);
+ return error;
+}
+
+/*
+ * fill the calibration value as milli ohms in the struct
+ *
+ * assume that the device has been calibrated
+ */
+enum Tfa98xx_Error tfa_dsp_get_calibration_impedance(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned char bytes[3 * 2] = { 0 };
+ int nr_bytes, i, data[2], calibrateDone, spkr_count = 0, cal_idx = 0;
+ unsigned int scaled_data;
+ int tries = 0;
+
+ error = tfa_supported_speakers(tfa, &spkr_count);
+
+ if (tfa_dev_mtp_get(tfa, TFA_MTP_OTC)) {
+ pr_debug("Getting calibration values from MTP\n");
+
+ if ((tfa->rev & 0xFF) == 0x88) {
+ for (i = 0; i < spkr_count; i++) {
+ if (i == 0)
+ tfa->mohm[i] = tfa_dev_mtp_get(tfa, TFA_MTP_RE25_PRIM);
+ else
+ tfa->mohm[i] = tfa_dev_mtp_get(tfa, TFA_MTP_RE25_SEC);
+ }
+ }
+ else {
+ tfa->mohm[0] = tfa_dev_mtp_get(tfa, TFA_MTP_RE25);
+ }
+ }
+ else {
+ pr_debug("Getting calibration values from Speakerboost\n");
+
+ /* Make sure the calibrateDone bit is set before getting the values from speakerboost!
+ * This does not work for 72 (because the dsp cannot set this bit)
+ */
+ if (!tfa->is_probus_device) {
+ /* poll xmem for calibrate always
+ * calibrateDone = 0 means "calibrating",
+ * calibrateDone = -1 (or 0xFFFFFF) means "fails"
+ * calibrateDone = 1 means calibration done
+ */
+ calibrateDone = 0;
+ while ((calibrateDone != 1) && (tries < TFA98XX_API_WAITRESULT_NTRIES)) {
+ error = tfa_mem_read(tfa, TFA_FW_XMEM_CALIBRATION_DONE, 1, &calibrateDone);
+ if (calibrateDone == 1)
+ break;
+ tries++;
+ }
+
+ if (calibrateDone != 1) {
+ pr_err("Calibration failed! \n");
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ else if (tries == TFA98XX_API_WAITRESULT_NTRIES) {
+ pr_debug("Calibration has timedout! \n");
+ error = Tfa98xx_Error_StateTimedOut;
+ }
+ }
+ /* SoftDSP interface differs from hw-dsp interfaces */
+ if (tfa->is_probus_device && tfa->cnt->ndev > 1) {
+ spkr_count = tfa->cnt->ndev;
+ }
+
+ nr_bytes = spkr_count * 3;
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_SPEAKERBOOST, SB_PARAM_GET_RE25C, nr_bytes, bytes);
+ if (error == Tfa98xx_Error_Ok) {
+ tfa98xx_convert_bytes2data(nr_bytes, bytes, data);
+
+ for (i = 0; i < spkr_count; i++) {
+
+ /* for probus devices, calibration values coming from soft-dsp speakerboost,
+ are ordered in a different way. Re-align to standard representation. */
+ cal_idx = i;
+ if ((tfa->is_probus_device && tfa->dev_idx >= 1)) {
+ cal_idx = 0;
+ }
+
+ /* signed data has a limit of 30 Ohm */
+ scaled_data = data[i];
+
+ if (tfa->tfa_family == 2)
+ tfa->mohm[cal_idx] = (scaled_data * 1000) / TFA2_FW_ReZ_SCALE;
+ else
+ tfa->mohm[cal_idx] = (scaled_data * 1000) / TFA1_FW_ReZ_SCALE;
+ }
+ }
+ }
+
+ return error;
+}
+
+/* start count from 1, 0 is invalid */
+int tfa_dev_get_swprof(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.get_swprof)(tfa);
+}
+
+int tfa_dev_set_swprof(struct tfa_device *tfa, unsigned short new_value)
+{
+ return (tfa->dev_ops.set_swprof)(tfa, new_value + 1);
+}
+
+/* same value for all channels
+ * start count from 1, 0 is invalid */
+int tfa_dev_get_swvstep(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.get_swvstep)(tfa);
+}
+
+int tfa_dev_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ return (tfa->dev_ops.set_swvstep)(tfa, new_value + 1);
+}
+
+/*
+ function overload for MTPB
+ */
+int tfa_dev_get_mtpb(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.get_mtpb)(tfa);
+}
+
+int tfa_is_cold(struct tfa_device *tfa)
+{
+ int value;
+
+ /*
+ * check for cold boot status
+ */
+ if (tfa->is_probus_device) {
+ if (tfa->ext_dsp > 0) {
+ if (tfa->ext_dsp == 2)
+ value = 0; // warm
+ else /* no dsp or cold */
+ value = 1; // cold
+ }
+ else {
+ value = (TFA_GET_BF(tfa, MANSCONF) == 0);
+ }
+ }
+ else {
+ value = TFA_GET_BF(tfa, ACS);
+ }
+
+ return value;
+}
+
+int tfa_needs_reset(struct tfa_device *tfa)
+{
+ int value;
+
+ /* checks if the DSP commands SetAlgoParams and SetMBDrc
+ * need a DSP reset (now: at coldstart or during calibration)
+ */
+ if (tfa_is_cold(tfa) == 1 || tfa->needs_reset == 1)
+ value = 1;
+ else
+ value = 0;
+
+ return value;
+}
+
+int tfa_cf_enabled(struct tfa_device *tfa)
+{
+ int value;
+
+ /* For 72 there is no CF */
+ if (tfa->is_probus_device) {
+ value = (tfa->ext_dsp != 0);
+ }
+ else {
+ value = TFA_GET_BF(tfa, CFE);
+ }
+
+ return value;
+}
+
+#define NR_COEFFS 6
+#define NR_BIQUADS 28
+#define BQ_SIZE (3 * NR_COEFFS)
+#define DSP_MSG_OVERHEAD 27
+
+#pragma pack (push, 1)
+struct dsp_msg_all_coeff {
+ uint8_t select_eq[3];
+ uint8_t biquad[NR_BIQUADS][NR_COEFFS][3];
+};
+#pragma pack (pop)
+
+/* number of biquads for each equalizer */
+static const int eq_biquads[] = {
+ 10, 10, 2, 2, 2, 2
+};
+
+#define NR_EQ (int)(sizeof(eq_biquads) / sizeof(int))
+
+enum Tfa98xx_Error tfa_dsp_partial_coefficients(struct tfa_device *tfa, uint8_t *prev, uint8_t *next)
+{
+ uint8_t bq, eq;
+ int eq_offset;
+ int new_cost, old_cost;
+ uint32_t eq_biquad_mask[NR_EQ];
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ struct dsp_msg_all_coeff *data1 = (struct dsp_msg_all_coeff *)prev;
+ struct dsp_msg_all_coeff *data2 = (struct dsp_msg_all_coeff *)next;
+
+ old_cost = DSP_MSG_OVERHEAD + 3 + sizeof(struct dsp_msg_all_coeff);
+ new_cost = 0;
+
+ eq_offset = 0;
+ for (eq = 0; eq < NR_EQ; eq++) {
+ uint8_t *eq1 = &data1->biquad[eq_offset][0][0];
+ uint8_t *eq2 = &data2->biquad[eq_offset][0][0];
+
+ eq_biquad_mask[eq] = 0;
+
+ if (memcmp(eq1, eq2, BQ_SIZE*eq_biquads[eq]) != 0) {
+ int nr_bq = 0;
+ int bq_sz, eq_sz;
+
+ for (bq = 0; bq < eq_biquads[eq]; bq++) {
+ uint8_t *bq1 = &eq1[bq*BQ_SIZE];
+ uint8_t *bq2 = &eq2[bq*BQ_SIZE];
+
+ if (memcmp(bq1, bq2, BQ_SIZE) != 0) {
+ eq_biquad_mask[eq] |= (1 << bq);
+ nr_bq++;
+ }
+ }
+
+ bq_sz = (2 * 3 + BQ_SIZE) * nr_bq;
+ eq_sz = 2 * 3 + BQ_SIZE * eq_biquads[eq];
+
+ /* dsp message i2c transaction overhead */
+ bq_sz += DSP_MSG_OVERHEAD * nr_bq;
+ eq_sz += DSP_MSG_OVERHEAD;
+
+ if (bq_sz >= eq_sz) {
+ eq_biquad_mask[eq] = 0xffffffff;
+
+ new_cost += eq_sz;
+
+ }
+ else {
+ new_cost += bq_sz;
+ }
+ }
+ pr_debug("eq_biquad_mask[%d] = 0x%.8x\n", eq, eq_biquad_mask[eq]);
+
+ eq_offset += eq_biquads[eq];
+ }
+
+ pr_debug("cost for writing all coefficients = %d\n", old_cost);
+ pr_debug("cost for writing changed coefficients = %d\n", new_cost);
+
+ if (new_cost >= old_cost) {
+ const int buffer_sz = 3 + sizeof(struct dsp_msg_all_coeff);
+ uint8_t *buffer;
+
+ buffer = kmalloc(buffer_sz, GFP_KERNEL);
+ if (buffer == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* cmd id */
+ buffer[0] = 0x00;
+ buffer[1] = 0x82;
+ buffer[2] = 0x00;
+
+ /* parameters */
+ memcpy(&buffer[3], data2, sizeof(struct dsp_msg_all_coeff));
+
+ err = tfa_dsp_msg(tfa, buffer_sz, (const char *)buffer);
+
+ kfree(buffer);
+ if (err)
+ return err;
+
+ }
+ else {
+ eq_offset = 0;
+ for (eq = 0; eq < NR_EQ; eq++) {
+ uint8_t *eq2 = &data2->biquad[eq_offset][0][0];
+
+ if (eq_biquad_mask[eq] == 0xffffffff) {
+ const int msg_sz = 6 + BQ_SIZE * eq_biquads[eq];
+ uint8_t *msg;
+
+ msg = kmalloc(msg_sz, GFP_KERNEL);
+ if (msg == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* cmd id */
+ msg[0] = 0x00;
+ msg[1] = 0x82;
+ msg[2] = 0x00;
+
+ /* select eq and bq */
+ msg[3] = 0x00;
+ msg[4] = eq + 1;
+ msg[5] = 0x00; /* all biquads */
+
+ /* biquad parameters */
+ memcpy(&msg[6], eq2, BQ_SIZE * eq_biquads[eq]);
+
+ err = tfa_dsp_msg(tfa, msg_sz, (const char *)msg);
+
+ kfree(msg);
+ if (err)
+ return err;
+
+ }
+ else if (eq_biquad_mask[eq] != 0) {
+ for (bq = 0; bq < eq_biquads[eq]; bq++) {
+
+ if (eq_biquad_mask[eq] & (1 << bq)) {
+ uint8_t *bq2 = &eq2[bq*BQ_SIZE];
+ const int msg_sz = 6 + BQ_SIZE;
+ uint8_t *msg;
+
+ msg = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (msg == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* cmd id */
+ msg[0] = 0x00;
+ msg[1] = 0x82;
+ msg[2] = 0x00;
+
+ /* select eq and bq*/
+ msg[3] = 0x00;
+ msg[4] = eq + 1;
+ msg[5] = bq + 1;
+
+ /* biquad parameters */
+ memcpy(&msg[6], bq2, BQ_SIZE);
+
+ err = tfa_dsp_msg(tfa, msg_sz, (const char *)msg);
+
+ kmem_cache_free(tfa->cachep, msg);
+ if (err)
+ return err;
+ }
+ }
+ }
+ eq_offset += eq_biquads[eq];
+ }
+ }
+
+ return err;
+}
+
+/* fill context info */
+int tfa_dev_probe(int slave, struct tfa_device *tfa)
+{
+ uint16_t rev;
+
+ tfa->slave_address = (unsigned char)slave;
+
+ /* read revid via low level hal, register 3 */
+ if (tfa98xx_read_register16(tfa, 3, &rev) != Tfa98xx_Error_Ok) {
+ PRINT("\nError: Unable to read revid from slave:0x%02x \n", slave);
+ return -1;
+ }
+
+ tfa->rev = rev;
+ tfa->dev_idx = -1;
+ tfa->state = TFA_STATE_UNKNOWN;
+ tfa->p_regInfo = NULL;
+
+ tfa_set_query_info(tfa);
+
+ tfa->in_use = 1;
+
+ return 0;
+}
+
+enum tfa_error tfa_dev_set_state(struct tfa_device *tfa, enum tfa_state state, int is_calibration)
+{
+ enum tfa_error err = tfa_error_ok;
+ int loop = 50, ready = 0;
+ int count;
+
+ /* Base states */
+ /* Do not change the order of setting bits as this is important! */
+ switch (state & 0x0f) {
+ case TFA_STATE_POWERDOWN: /* PLL in powerdown, Algo up */
+ break;
+ case TFA_STATE_INIT_HW: /* load I2C/PLL hardware setting (~wait2srcsettings) */
+ break;
+ case TFA_STATE_INIT_CF: /* coolflux HW access possible (~initcf) */
+ /* Start with SBSL=0 to stay in initCF state */
+ if (!tfa->is_probus_device)
+ TFA_SET_BF(tfa, SBSL, 0);
+
+ /* We want to leave Wait4SrcSettings state for max2 */
+ if (tfa->tfa_family == 2)
+ TFA_SET_BF(tfa, MANSCONF, 1);
+
+ /* And finally set PWDN to 0 to leave powerdown state */
+ TFA_SET_BF(tfa, PWDN, 0);
+
+ /* Make sure the DSP is running! */
+ do {
+ err = tfa98xx_dsp_system_stable(tfa, &ready);
+ if (err != tfa_error_ok)
+ return err;
+ if (ready)
+ break;
+ } while (loop--);
+ if (((!tfa->is_probus_device) && (is_calibration)) || ((tfa->rev & 0xff) == 0x13))
+ {
+ /* Enable FAIM when clock is stable, to avoid MTP corruption */
+ err = tfa98xx_faim_protect(tfa, 1);
+ if (tfa->verbose) {
+ pr_debug("FAIM enabled (err:%d).\n", err);
+ }
+ }
+ break;
+ case TFA_STATE_INIT_FW: /* DSP framework active (~patch loaded) */
+ break;
+ case TFA_STATE_OPERATING: /* Amp and Algo running */
+ /* Depending on our previous state we need to set 3 bits */
+ TFA_SET_BF(tfa, PWDN, 0); /* Coming from state 0 */
+ TFA_SET_BF(tfa, MANSCONF, 1); /* Coming from state 1 */
+ if (!tfa->is_probus_device)
+ TFA_SET_BF(tfa, SBSL, 1); /* Coming from state 6 */
+ else
+ TFA_SET_BF(tfa, AMPE, 1); /* No SBSL for probus device, we set AMPE to 1 */
+
+ /*
+ * Disable MTP clock to protect memory.
+ * However in case of calibration wait for DSP! (This should be case only during calibration).
+ */
+ if (TFA_GET_BF(tfa, MTPOTC) == 1 && tfa->tfa_family == 2) {
+ count = MTPEX_WAIT_NTRIES * 4; /* Calibration takes a lot of time */
+ while ((TFA_GET_BF(tfa, MTPEX) != 1) && count) {
+ msleep_interruptible(10);
+ count--;
+ }
+ }
+ if (((!tfa->is_probus_device) && (is_calibration)) || ((tfa->rev & 0xff) == 0x13))
+ {
+ err = tfa98xx_faim_protect(tfa, 0);
+ if (tfa->verbose) {
+ pr_debug("FAIM disabled (err:%d).\n", err);
+ }
+ }
+ /* Synchonize I/V delay on 96/97 at cold start */
+ if (tfa->sync_iv_delay) {
+ if (tfa->verbose)
+ pr_debug("syncing I/V delay for %x\n",
+ (tfa->rev & 0xff));
+
+ /* wait for ACS to be cleared */
+ count = 10;
+ while ((TFA_GET_BF(tfa, ACS) == 1) &&
+ (count-- > 0)) {
+ msleep_interruptible(1);
+ }
+
+ tfa98xx_dsp_reset(tfa, 1);
+ tfa98xx_dsp_reset(tfa, 0);
+ tfa->sync_iv_delay = 0;
+ }
+ break;
+ case TFA_STATE_FAULT: /* An alarm or error occurred */
+ break;
+ case TFA_STATE_RESET: /* I2C reset and ACS set */
+ tfa98xx_init(tfa);
+ break;
+ default:
+ if (state & 0x0f)
+ return tfa_error_bad_param;
+ }
+
+ /* state modifiers */
+
+ if (state & TFA_STATE_MUTE)
+ tfa98xx_set_mute(tfa, Tfa98xx_Mute_Amplifier);
+
+ if (state & TFA_STATE_UNMUTE)
+ tfa98xx_set_mute(tfa, Tfa98xx_Mute_Off);
+
+ tfa->state = state;
+
+ return tfa_error_ok;
+}
+
+enum tfa_state tfa_dev_get_state(struct tfa_device *tfa)
+{
+ int cold = 0;
+ int manstate;
+
+ /* different per family type */
+ if (tfa->tfa_family == 1) {
+ cold = TFA_GET_BF(tfa, ACS);
+ if (cold && TFA_GET_BF(tfa, PWDN))
+ tfa->state = TFA_STATE_RESET;
+ else if (!cold && TFA_GET_BF(tfa, SWS))
+ tfa->state = TFA_STATE_OPERATING;
+ }
+ else /* family 2 */ {
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ switch (manstate) {
+ case 0:
+ tfa->state = TFA_STATE_POWERDOWN;
+ break;
+ case 8: /* if dsp reset if off assume framework is running */
+ tfa->state = TFA_GET_BF(tfa, RST) ? TFA_STATE_INIT_CF : TFA_STATE_INIT_FW;
+ break;
+ case 9:
+ tfa->state = TFA_STATE_OPERATING;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return tfa->state;
+}
+
+int tfa_dev_mtp_get(struct tfa_device *tfa, enum tfa_mtp item)
+{
+ int value = 0;
+
+ switch (item) {
+ case TFA_MTP_OTC:
+ value = TFA_GET_BF(tfa, MTPOTC);
+ break;
+ case TFA_MTP_EX:
+ value = TFA_GET_BF(tfa, MTPEX);
+ break;
+ case TFA_MTP_RE25:
+ case TFA_MTP_RE25_PRIM:
+ if (tfa->tfa_family == 2) {
+ if ((tfa->rev & 0xFF) == 0x88)
+ value = TFA_GET_BF(tfa, R25CL);
+ else if ((tfa->rev & 0xFF) == 0x13)
+ value = tfa_get_bf(tfa, TFA9912_BF_R25C);
+ else
+ value = TFA_GET_BF(tfa, R25C);
+ }
+ else {
+ tfa_reg_read(tfa, 0x83, (unsigned short*)&value);
+ }
+ break;
+ case TFA_MTP_RE25_SEC:
+ if ((tfa->rev & 0xFF) == 0x88) {
+ value = TFA_GET_BF(tfa, R25CR);
+ }
+ else {
+ pr_debug("Error: Current device has no secondary Re25 channel \n");
+ }
+ break;
+ case TFA_MTP_LOCK:
+ break;
+ }
+
+ return value;
+}
+
+enum tfa_error tfa_dev_mtp_set(struct tfa_device *tfa, enum tfa_mtp item, int value)
+{
+ enum tfa_error err = tfa_error_ok;
+
+ switch (item) {
+ case TFA_MTP_OTC:
+ err = tfa98xx_set_mtp(tfa, (uint16_t)value, TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MSK);
+ break;
+ case TFA_MTP_EX:
+ err = tfa98xx_set_mtp(tfa, (uint16_t)value, TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK);
+ break;
+ case TFA_MTP_RE25:
+ case TFA_MTP_RE25_PRIM:
+ if (tfa->tfa_family == 2) {
+ tfa98xx_key2(tfa, 0); /* unlock */
+ if ((tfa->rev & 0xFF) == 0x88)
+ TFA_SET_BF(tfa, R25CL, (uint16_t)value);
+ else
+ {
+ if (tfa->is_probus_device == 1 && TFA_GET_BF(tfa, MTPOTC) == 1)
+ tfa2_manual_mtp_cpy(tfa, 0xF4, value, 2);
+ TFA_SET_BF(tfa, R25C, (uint16_t)value);
+ }
+ tfa98xx_key2(tfa, 1); /* lock */
+ }
+ break;
+ case TFA_MTP_RE25_SEC:
+ if ((tfa->rev & 0xFF) == 0x88) {
+ TFA_SET_BF(tfa, R25CR, (uint16_t)value);
+ }
+ else {
+ pr_debug("Error: Current device has no secondary Re25 channel \n");
+ err = tfa_error_bad_param;
+ }
+ break;
+ case TFA_MTP_LOCK:
+ break;
+ }
+
+ return err;
+}
+
+int tfa_get_pga_gain(struct tfa_device *tfa)
+{
+ return TFA_GET_BF(tfa, SAAMGAIN);
+}
+
+int tfa_set_pga_gain(struct tfa_device *tfa, uint16_t value)
+{
+
+ return TFA_SET_BF(tfa, SAAMGAIN, value);
+}
+
+int tfa_get_noclk(struct tfa_device *tfa)
+{
+ return TFA_GET_BF(tfa, NOCLK);
+}
+
+
+enum Tfa98xx_Error tfa_status(struct tfa_device *tfa)
+{
+ int value;
+ uint16_t val;
+
+ if (tfa->dev_ops.tfa_status != NULL)
+ return(tfa->dev_ops.tfa_status(tfa));
+ /*
+ * check IC status bits: cold start
+ * and DSP watch dog bit to re init
+ */
+ value = TFA_READ_REG(tfa, VDDS); /* STATUSREG */
+ if (value < 0)
+ return -value;
+ val = (uint16_t)value;
+
+ /* pr_debug("SYS_STATUS0: 0x%04x\n", val); */
+ if (TFA_GET_BF_VALUE(tfa, ACS, val) ||
+ TFA_GET_BF_VALUE(tfa, WDS, val)) {
+
+ if (TFA_GET_BF_VALUE(tfa, ACS, val))
+ pr_err("ERROR: ACS\n");
+ if (TFA_GET_BF_VALUE(tfa, WDS, val))
+ pr_err("ERROR: WDS\n");
+
+ return Tfa98xx_Error_DSP_not_running;
+ }
+
+ if (TFA_GET_BF_VALUE(tfa, SPKS, val))
+ pr_err("ERROR: SPKS\n");
+ if (!TFA_GET_BF_VALUE(tfa, SWS, val))
+ pr_err("ERROR: SWS\n");
+
+ /* Check secondary errors */
+ if (!TFA_GET_BF_VALUE(tfa, CLKS, val) ||
+ !TFA_GET_BF_VALUE(tfa, UVDS, val) ||
+ !TFA_GET_BF_VALUE(tfa, OVDS, val) ||
+ !TFA_GET_BF_VALUE(tfa, OTDS, val) ||
+ !TFA_GET_BF_VALUE(tfa, PLLS, val) ||
+ (!(tfa->daimap & Tfa98xx_DAI_TDM) &&
+ !TFA_GET_BF_VALUE(tfa, VDDS, val)))
+ pr_err("Misc errors detected: STATUS_FLAG0 = 0x%x\n", val);
+
+ if ((tfa->daimap & Tfa98xx_DAI_TDM) && (tfa->tfa_family == 2)) {
+ value = TFA_READ_REG(tfa, TDMERR); /* STATUS_FLAGS1 */
+ if (value < 0)
+ return -value;
+ val = (uint16_t)value;
+ if (TFA_GET_BF_VALUE(tfa, TDMERR, val) ||
+ TFA_GET_BF_VALUE(tfa, TDMLUTER, val))
+ pr_err("TDM related errors: STATUS_FLAG1 = 0x%x\n", val);
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+#ifdef __KERNEL__
+void tfa_dev_get_tdm_add(struct tfa_device* tfa, uint16_t* tdme, uint16_t* tnbck, uint16_t* tslln, uint16_t* tsize)
+{
+ unsigned short revid = tfa->rev;
+ switch (revid & 0xff) {
+ case 0x72:
+ *tdme = TFA9872_BF_TDME;
+ *tnbck = TFA9872_BF_TDMNBCK;
+ *tslln = TFA9872_BF_TDMSLLN;
+ *tsize = TFA9872_BF_TDMSSIZE;
+ break;
+ case 0x73:
+ *tdme = TFA9873_BF_TDME;
+ *tnbck = TFA9873_BF_TDMNBCK;
+ *tslln = TFA9873_BF_TDMSLLN;
+ *tsize = TFA9873_BF_TDMSSIZE;
+ break;
+ case 0x74:
+ *tdme = TFA9874_BF_TDME;
+ *tnbck = TFA9874_BF_TDMNBCK;
+ *tslln = TFA9874_BF_TDMSLLN;
+ *tsize = TFA9874_BF_TDMSSIZE;
+ break;
+ case 0x78:
+ *tdme = TFA9878_BF_TDME;
+ *tnbck = TFA9878_BF_TDMNBCK;
+ *tslln = TFA9878_BF_TDMSLLN;
+ *tsize = TFA9878_BF_TDMSSIZE;
+ break;
+ case 0x13:
+ *tdme = TFA9912_BF_TDME;
+ *tnbck = TFA9912_BF_TDMNBCK;
+ *tslln = TFA9912_BF_TDMSLLN;
+ *tsize = TFA9912_BF_TDMSSIZE;
+ break;
+ case 0x94:
+ *tdme = TFA9894_BF_TDME;
+ *tnbck = TFA9894_BF_TDMNBCK;
+ *tslln = TFA9894_BF_TDMSLLN;
+ *tsize = TFA9894_BF_TDMSSIZE;
+ break;
+
+ default:
+ pr_err("unsuported device rev:%x\n", revid);
+ break;
+ }
+}
+int tfa_dev_set_tdm_bitwidth(struct tfa_device* tfa, int width)/*SACAS-26*/
+{
+ uint8_t nbck, slotlen, samplesize;
+
+ switch (width) {
+ case 16: /* 16-bit sample in 16-bit slot */
+ nbck = 0;
+ slotlen = 15;
+ samplesize = 15;
+ break;
+ case 24: /* 24-bit sample in 32-bit slot */
+ nbck = 2;
+ slotlen = 31;
+ samplesize = (tfa->tfa_family == 1) ? 23 : (tfa->is_probus_device == 1) ? 31 : 23;
+ break;
+ case 32: /* 32-bit sample in 32-bit slot */
+ nbck = 2;
+ slotlen = 31;
+ samplesize = (tfa->tfa_family == 1) ? 23 : (tfa->is_probus_device == 1) ? 31 : 23;
+ break;
+ default:
+ pr_err("unsupported tdm bitwidth:%d\n", width);
+ return -EINVAL;
+ break;
+ }
+
+ if (tfa->tfa_family == 2)
+ {
+ uint16_t tdme, tdmnbck, tdmslln,tdmssize;
+ tfa_dev_get_tdm_add(tfa,&tdme,&tdmnbck,&tdmslln,&tdmssize); /*SACAS-26*/
+ /* stop tdm */
+ tfa_set_bf(tfa, tdme, 0);
+ tfa_set_bf(tfa, tdmnbck, nbck);
+ tfa_set_bf(tfa, tdmslln, slotlen);
+ tfa_set_bf(tfa, tdmssize, samplesize);
+ /* enable tdm */
+ tfa_set_bf(tfa, tdme, 1);
+ }
+ else if (tfa->daimap == Tfa98xx_DAI_TDM)
+ {
+ /* stop tdm */
+ tfa_set_bf(tfa, TFA1_BF_TDMEN, 0);
+ tfa_set_bf(tfa, TFA1_BF_NBCK, nbck);
+ tfa_set_bf(tfa, TFA1_BF_TDMSLLN, slotlen);
+ tfa_set_bf(tfa, TFA1_BF_TDMSAMSZ, samplesize);
+ /* enable tdm */
+ tfa_set_bf(tfa, TFA1_BF_TDMEN, 1);
+
+ }
+ return 0;
+
+}
+#define NR_OF_BATS 10
+void tfa_adapt_noisemode(struct tfa_device *tfa)
+{
+ int i, avbatt;
+ long total_bats = 0;
+ if ((tfa_get_bf(tfa, 0x5900) == 0) || (tfa_get_bf(tfa, TFA9873_BF_LP1) == 1))
+ {
+ if (tfa->verbose)
+ pr_debug("Adapting low noise mode is not needed, condition not fulfilled!\n");
+ return;
+ }
+ if (tfa->verbose)
+ pr_debug("Adapting low noise mode\n");
+
+ for (i = 0; i < NR_OF_BATS; i++) {
+ int bat = TFA_GET_BF(tfa, BATS);
+ if (tfa->verbose)
+ pr_debug("bats[%d]=%d\n", i, bat);
+ total_bats += bat;
+ msleep_interruptible(5);
+ }
+
+ avbatt = (int)(total_bats / NR_OF_BATS);
+
+ if (avbatt <= MIN_BATT_LEVEL && !tfa_get_bf(tfa, TFA9873_BF_LNMODE))//640 corresponds to 3.4 volt, MCH_TO_TEST
+ {
+ tfa_set_bf(tfa, TFA9873_BF_LNMODE, 1);
+ pr_debug("\navbatt= %d--Applying high noise gain\n", avbatt);
+ }
+ else if (avbatt > MAX_BATT_LEVEL && tfa_get_bf(tfa, TFA9873_BF_LNMODE))
+ {
+ tfa_set_bf(tfa, TFA9873_BF_LNMODE, 0);
+ pr_debug("\navbatt= %d--Applying automatic noise gain\n", avbatt);
+ }
+
+
+}
+int tfa_plop_noise_interrupt(struct tfa_device *tfa, int profile, int vstep)
+{
+ enum Tfa98xx_Error err;
+ int no_clk = 0;
+
+ /* Remove sticky bit by reading it once */
+ TFA_GET_BF(tfa, NOCLK);
+
+ /* No clock detected */
+ if (tfa_irq_get(tfa, tfa9912_irq_stnoclk)) {
+ no_clk = TFA_GET_BF(tfa, NOCLK);
+
+ /* Detect for clock is lost! (clock is not stable) */
+ if (no_clk == 1) {
+ /* Clock is lost. Set I2CR to remove POP noise */
+ pr_info("No clock detected. Resetting the I2CR to avoid pop on 72! \n");
+ err = tfa_dev_start(tfa, profile, vstep);
+ if (err != Tfa98xx_Error_Ok) {
+ pr_err("Error loading i2c registers (tfa_dev_start), err=%d\n", err);
+ }
+ else {
+ pr_info("Setting i2c registers after I2CR succesfull\n");
+ tfa_dev_set_state(tfa, TFA_STATE_UNMUTE, 0);
+ }
+
+ /* Remove sticky bit by reading it once */
+ tfa_get_noclk(tfa);
+
+ /* This is only for SAAM on the 72.
+ Since the NOCLK interrupt is only enabled for 72 this is the place
+ However: Not tested yet! But also does not harm normal flow!
+ */
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, profile), ".saam")) {
+ pr_info("Powering down from a SAAM profile, workaround PLMA4766 used! \n");
+ TFA_SET_BF(tfa, PWDN, 1);
+ TFA_SET_BF(tfa, AMPE, 0);
+ TFA_SET_BF(tfa, SAMMODE, 0);
+ }
+ }
+
+ /* If clk is stable set polarity to check for LOW (no clock)*/
+ tfa_irq_set_pol(tfa, tfa9912_irq_stnoclk, (no_clk == 0));
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa, tfa9912_irq_stnoclk);
+ }
+
+ /* return no_clk to know we called tfa_dev_start */
+ return no_clk;
+}
+
+void tfa_lp_mode_interrupt(struct tfa_device *tfa)
+{
+ const int irq_stclp0 = 36; /* FIXME: this 72 interrupt does not excist for 9912 */
+ int lp0, lp1;
+
+ if (tfa_irq_get(tfa, irq_stclp0)) {
+ lp0 = TFA_GET_BF(tfa, LP0);
+ if (lp0 > 0) {
+ pr_info("lowpower mode 0 detected\n");
+ }
+ else {
+ pr_info("lowpower mode 0 not detected\n");
+ }
+
+ tfa_irq_set_pol(tfa, irq_stclp0, (lp0 == 0));
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa, irq_stclp0);
+ }
+
+ if (tfa_irq_get(tfa, tfa9912_irq_stclpr)) {
+ lp1 = TFA_GET_BF(tfa, LP1);
+ if (lp1 > 0) {
+ pr_info("lowpower mode 1 detected\n");
+ }
+ else {
+ pr_info("lowpower mode 1 not detected\n");
+ }
+
+ tfa_irq_set_pol(tfa, tfa9912_irq_stclpr, (lp1 == 0));
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa, tfa9912_irq_stclpr);
+ }
+}
+#endif//__KERNEL__
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_dsp_fw.h b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp_fw.h
new file mode 100644
index 00000000000..1621bcb8be6
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp_fw.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef TFA98XX_INTERNALS_H
+#define TFA98XX_INTERNALS_H
+
+#include "config.h"
+
+#include "tfa_service.h" //TODO cleanup for enum Tfa98xx_Status_ID
+/*
+ * tfadsp_fw_api.c
+ */
+/**
+ * Return a text version of the firmware status ID code
+ * @param status the given status ID code
+ * @return the firmware status ID string
+ */
+const char *tfadsp_fw_status_string(enum Tfa98xx_Status_ID status);
+int tfadsp_fw_start(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+int tfadsp_fw_get_api_version(struct tfa_device *tfa, uint8_t *buffer);
+#define FW_MAXTAG 150
+int tfadsp_fw_get_tag(struct tfa_device *tfa, uint8_t *buffer);
+int tfadsp_fw_get_status_change(struct tfa_device *tfa, uint8_t *buffer);
+int tfadsp_fw_set_re25(struct tfa_device *tfa, int prim, int sec );
+int tfadsp_fw_get_re25(struct tfa_device *tfa, uint8_t *buffer);
+
+/*
+ * the order matches the ACK bits order in TFA98XX_CF_STATUS
+ */
+enum tfa_fw_event { /* not all available on each device */
+ tfa_fw_i2c_cmd_ack,
+ tfa_fw_reset_start,
+ tfa_fw_short_on_mips,
+ tfa_fw_soft_mute_ready,
+ tfa_fw_volume_ready,
+ tfa_fw_error_damage,
+ tfa_fw_calibrate_done,
+ tfa_fw_max
+};
+
+/* the following type mappings are compiler specific */
+#define subaddress_t unsigned char
+
+/* module Ids */
+#define MODULE_FRAMEWORK 0
+#define MODULE_SPEAKERBOOST 1
+#define MODULE_BIQUADFILTERBANK 2
+#define MODULE_TAPTRIGGER 5
+#define MODULE_SETRE 9
+
+/* RPC commands */
+/* SET */
+#define FW_PAR_ID_SET_MEMORY 0x03
+#define FW_PAR_ID_SET_SENSES_DELAY 0x04
+#define FW_PAR_ID_SETSENSESCAL 0x05
+#define FW_PAR_ID_SET_INPUT_SELECTOR 0x06
+#define FW_PAR_ID_SET_OUTPUT_SELECTOR 0x08
+#define FW_PAR_ID_SET_PROGRAM_CONFIG 0x09
+#define FW_PAR_ID_SET_GAINS 0x0A
+#define FW_PAR_ID_SET_MEMTRACK 0x0B
+#define FW_PAR_ID_SET_FWKUSECASE 0x11
+#define TFA1_FW_PAR_ID_SET_CURRENT_DELAY 0x03
+#define TFA1_FW_PAR_ID_SET_CURFRAC_DELAY 0x06
+/* GET */
+#define FW_PAR_ID_GET_MEMORY 0x83
+#define FW_PAR_ID_GLOBAL_GET_INFO 0x84
+#define FW_PAR_ID_GET_FEATURE_INFO 0x85
+#define FW_PAR_ID_GET_MEMTRACK 0x8B
+#define FW_PAR_ID_GET_TAG 0xFF
+#define FW_PAR_ID_GET_API_VERSION 0xFE
+#define FW_PAR_ID_GET_STATUS_CHANGE 0x8D
+
+/* Load a full model into SpeakerBoost. */
+/* SET */
+#define SB_PARAM_SET_ALGO_PARAMS 0x00
+#define SB_PARAM_SET_LAGW 0x01
+#define SB_PARAM_SET_ALGO_PARAMS_WITHOUT_RESET 0x02
+#define SB_PARAM_SET_RE25C 0x05
+#define SB_PARAM_SET_LSMODEL 0x06
+#define SB_PARAM_SET_MBDRC 0x07
+#define SB_PARAM_SET_MBDRC_WITHOUT_RESET 0x08
+#define SB_PARAM_SET_EXCURSION_FILTERS 0x0A
+#define SB_PARAM_SET_DRC 0x0F
+/* GET */
+#define SB_PARAM_GET_ALGO_PARAMS 0x80
+#define SB_PARAM_GET_LAGW 0x81
+#define SB_PARAM_GET_RE25C 0x85
+#define SB_PARAM_GET_LSMODEL 0x86
+#define SB_PARAM_GET_MBDRC 0x87
+#define SB_PARAM_GET_MBDRC_DYNAMICS 0x89
+#define SB_PARAM_GET_EXCURSION_FILTERS 0x8A
+#define SB_PARAM_GET_TAG 0xFF
+
+#define SB_PARAM_SET_EQ 0x0A /* 2 Equaliser Filters. */
+#define SB_PARAM_SET_PRESET 0x0D /* Load a preset */
+#define SB_PARAM_SET_CONFIG 0x0E /* Load a config */
+#define SB_PARAM_SET_AGCINS 0x10
+#define SB_PARAM_SET_CURRENT_DELAY 0x03
+#define SB_PARAM_GET_STATE 0xC0
+#define SB_PARAM_GET_XMODEL 0xC1 /* Gets current Excursion Model. */
+#define SB_PARAM_GET_XMODEL_COEFFS 0x8C /* Get coefficients for XModel */
+#define SB_PARAM_GET_EXCURSION_FILTERS 0x8A /* Get excursion filters */
+#define SB_PARAM_SET_EXCURSION_FILTERS 0x0A /* Set excursion filters */
+
+/* SET: TAPTRIGGER */
+#define TAP_PARAM_SET_ALGO_PARAMS 0x01
+#define TAP_PARAM_SET_DECIMATION_PARAMS 0x02
+
+/* GET: TAPTRIGGER*/
+#define TAP_PARAM_GET_ALGO_PARAMS 0x81
+#define TAP_PARAM_GET_TAP_RESULTS 0x84
+
+/* sets the speaker calibration impedance (@25 degrees celsius) */
+#define SB_PARAM_SET_RE0 0x89
+
+#define BFB_PAR_ID_SET_COEFS 0x00
+#define BFB_PAR_ID_GET_COEFS 0x80
+#define BFB_PAR_ID_GET_CONFIG 0x81
+
+/* for compatibility */
+#define FW_PARAM_GET_STATE FW_PAR_ID_GLOBAL_GET_INFO
+#define FW_PARAM_GET_FEATURE_BITS FW_PAR_ID_GET_FEATURE_BITS
+
+/* RPC Status results */
+#define STATUS_OK 0
+#define STATUS_INVALID_MODULE_ID 2
+#define STATUS_INVALID_PARAM_ID 3
+#define STATUS_INVALID_INFO_ID 4
+
+/* the maximum message length in the communication with the DSP */
+#define TFA2_MAX_PARAM_SIZE (507*3) /* TFA2 */
+#define TFA1_MAX_PARAM_SIZE (145*3) /* TFA1 */
+
+#define ROUND_DOWN(a,n) (((a)/(n))*(n))
+
+/* feature bits */
+#define FEATURE1_TCOEF 0x100 /* bit8 set means tCoefA expected */
+#define FEATURE1_DRC 0x200 /* bit9 NOT set means DRC expected */
+
+/* DSP firmware xmem defines */
+#define TFA1_FW_XMEM_CALIBRATION_DONE 231
+#define TFA2_FW_XMEM_CALIBRATION_DONE 516
+#define TFA1_FW_XMEM_COUNT_BOOT 0xa1
+#define TFA2_FW_XMEM_COUNT_BOOT 512
+#define TFA2_FW_XMEM_CMD_COUNT 520
+
+/* note that the following defs rely on the handle variable */
+#define TFA_FW_XMEM_CALIBRATION_DONE TFA_FAM_FW(tfa,XMEM_CALIBRATION_DONE)
+#define TFA_FW_XMEM_COUNT_BOOT TFA_FAM_FW(tfa,XMEM_COUNT_BOOT)
+#define TFA_FW_XMEM_CMD_COUNT TFA_FAM_FW(tfa,XMEM_CMD_COUNT)
+
+#define TFA2_FW_ReZ_SCALE 65536
+#define TFA1_FW_ReZ_SCALE 16384
+
+#endif /* TFA98XX_INTERNALS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_ext.h b/sound/soc/codecs/tfa98xx-downstream/tfa_ext.h
new file mode 100644
index 00000000000..72c65594a1c
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_ext.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/*
+ * tfa_ext.h
+ *
+ * Created on: Jun 8, 2016
+ * Author: wim
+ */
+
+#ifndef TFA_SRC_TFA_EXT_H_
+#define TFA_SRC_TFA_EXT_H_
+
+#include "tfa_device.h"
+
+/*
+ * events
+ */
+/** Maximum value for enumerator */
+#define LVM_MAXENUM (0xffff)
+/**
+This enum type specifies the different events that may trigger a callback.
+*/
+enum tfadsp_event_en
+{
+ TFADSP_CMD_ACK = 1, /**< Command handling is completed */
+ TFADSP_SOFT_MUTE_READY = 8, /**< Muting completed */
+ TFADSP_VOLUME_READY = 16, /**< Volume change completed */
+ TFADSP_DAMAGED_SPEAKER = 32, /**< Damaged speaker was detected */
+ TFADSP_CALIBRATE_DONE = 64, /**< Calibration is completed */
+ TFADSP_SPARSESIG_DETECTED = 128, /**< Sparse signal detected */
+ TFADSP_CMD_READY = 256, /**< Ready to receive commands */
+ TFADSP_EXT_PWRUP = 0x8000,/**< DSP API has started, powered up */
+ TFADSP_EXT_PWRDOWN = 0x8001,/**< DSP API stopped, power down */
+ TFADSP_EVENT_DUMMY = LVM_MAXENUM
+} ;
+
+typedef int (*tfa_event_handler_t)(struct tfa_device *tfa, enum tfadsp_event_en tfadsp_event);
+typedef int (*dsp_send_message_t)(struct tfa_device *tfa, int length, const char *buf);
+typedef int (*dsp_read_message_t)(struct tfa_device *tfa, int length, char *buf);
+typedef int (*dsp_write_reg_t)(struct tfa_device *tfa, unsigned char subaddress, unsigned short value);
+
+int tfa_ext_register(dsp_write_reg_t tfa_write_reg, dsp_send_message_t tfa_send_message, dsp_read_message_t tfa_read_message, tfa_event_handler_t *tfa_event_handler);
+
+#endif /* TFA_SRC_TFA_EXT_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_init.c b/sound/soc/codecs/tfa98xx-downstream/tfa_init.c
new file mode 100644
index 00000000000..6dc4e9c0ce9
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_init.c
@@ -0,0 +1,2148 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include "dbgprint.h"
+#include "tfa_service.h"
+#include "tfa_internal.h"
+#include "tfa_container.h"
+#include "tfa98xx_tfafieldnames.h"
+
+ /* The CurrentSense4 registers are not in the datasheet */
+#define TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF (1<<2)
+#define TFA98XX_CURRENTSENSE4 0x49
+
+/***********************************************************************************/
+/* GLOBAL (Defaults) */
+/***********************************************************************************/
+static enum Tfa98xx_Error no_overload_function_available(struct tfa_device *tfa, int not_used)
+{
+ (void)tfa;
+ (void)not_used;
+
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error no_overload_function_available2(struct tfa_device *tfa)
+{
+ (void)tfa;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short status;
+ int value;
+
+ /* check the contents of the STATUS register */
+ value = TFA_READ_REG(tfa, AREFS);
+ if (value < 0) {
+ error = -value;
+ *ready = 0;
+ _ASSERT(error); /* an error here can be fatal */
+ return error;
+ }
+ status = (unsigned short)value;
+
+ /* check AREFS and CLKS: not ready if either is clear */
+ *ready = !((TFA_GET_BF_VALUE(tfa, AREFS, status) == 0)
+ || (TFA_GET_BF_VALUE(tfa, CLKS, status) == 0));
+
+ return error;
+}
+
+/* tfa98xx_toggle_mtp_clock
+ * Allows to stop clock for MTP/FAim needed for PLMA5505 */
+static enum Tfa98xx_Error tfa_faim_protect(struct tfa_device *tfa, int state)
+{
+ (void)tfa;
+ (void)state;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/** Set internal oscillator into power down mode.
+ *
+ * This function is a worker for tfa98xx_set_osc_powerdown().
+ *
+ * @param[in] tfa device description structure
+ * @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+ *
+ * @return Tfa98xx_Error_Ok when successfull, error otherwise.
+ */
+static enum Tfa98xx_Error tfa_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ /* This function has no effect in general case, only for tfa9912 */
+ (void)tfa;
+ (void)state;
+
+ return Tfa98xx_Error_Ok;
+}
+static enum Tfa98xx_Error tfa_update_lpm(struct tfa_device *tfa, int state)
+{
+ /* This function has no effect in general case, only for tfa9912 */
+ (void)tfa;
+ (void)state;
+
+ return Tfa98xx_Error_Ok;
+}
+static enum Tfa98xx_Error tfa_dsp_reset(struct tfa_device *tfa, int state)
+{
+ /* generic function */
+ TFA_SET_BF_VOLATILE(tfa, RST, (uint16_t)state);
+
+ return Tfa98xx_Error_Ok;
+}
+
+int tfa_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int mtpk, active_value = tfa->profile;
+
+ /* Also set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* for TFA1 devices */
+ /* it's in MTP shadow, so unlock if not done already */
+ mtpk = TFA_GET_BF(tfa, MTPK); /* get current key */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, 0x5a);
+ TFA_SET_BF_VOLATILE(tfa, SWPROFIL, new_value); /* set current profile */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, (uint16_t)mtpk); /* restore key */
+
+ return active_value;
+}
+
+static int tfa_get_swprofile(struct tfa_device *tfa)
+{
+ return /*TFA_GET_BF(tfa, SWPROFIL) - 1*/tfa->profile;
+}
+
+static int tfa_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ int mtpk, active_value = tfa->vstep;
+
+ /* Also set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* for TFA1 devices */
+ /* it's in MTP shadow, so unlock if not done already */
+ mtpk = TFA_GET_BF(tfa, MTPK); /* get current key */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, 0x5a);
+ TFA_SET_BF_VOLATILE(tfa, SWVSTEP, new_value); /* set current vstep */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, (uint16_t)mtpk); /* restore key */
+
+ return active_value;
+}
+
+static int tfa_get_swvstep(struct tfa_device *tfa)
+{
+ int value = 0;
+ /* Set the new value in the hw register */
+ value = TFA_GET_BF(tfa, SWVSTEP);
+
+ /* Also set the new value in the struct */
+ tfa->vstep = value - 1;
+
+ return value - 1; /* invalid if 0 */
+}
+
+static int tfa_get_mtpb(struct tfa_device *tfa) {
+
+ int value = 0;
+
+ /* Set the new value in the hw register */
+ value = TFA_GET_BF(tfa, MTPB);
+
+ return value;
+}
+
+static enum Tfa98xx_Error
+tfa_set_mute_nodsp(struct tfa_device *tfa, int mute)
+{
+ (void)tfa;
+ (void)mute;
+
+ return Tfa98xx_Error_Ok;
+}
+
+static int tfa_set_bitfield(struct tfa_device* tfa, uint16_t bitfield, uint16_t value)
+{
+ return tfa_set_bf(tfa, (uint16_t)bitfield, value);
+}
+
+void tfa_set_ops_defaults(struct tfa_device_ops *ops)
+{
+ /* defaults */
+ ops->tfa_reg_read = tfa98xx_read_register16;
+ ops->tfa_reg_write = tfa98xx_write_register16;
+ ops->tfa_mem_read = tfa98xx_dsp_read_mem;
+ ops->tfa_mem_write = tfa98xx_dsp_write_mem_word;
+ ops->tfa_dsp_msg = tfa_dsp_msg_rpc;
+ ops->tfa_dsp_msg_read = tfa_dsp_msg_read_rpc;
+ ops->dsp_write_tables = no_overload_function_available;
+ ops->dsp_reset = tfa_dsp_reset;
+ ops->dsp_system_stable = tfa_dsp_system_stable;
+ ops->auto_copy_mtp_to_iic = no_overload_function_available2;
+ ops->factory_trimmer = no_overload_function_available2;
+ ops->phase_shift = no_overload_function_available2;
+ ops->set_swprof = tfa_set_swprofile;
+ ops->get_swprof = tfa_get_swprofile;
+ ops->set_swvstep = tfa_set_swvstep;
+ ops->get_swvstep = tfa_get_swvstep;
+ ops->get_mtpb = tfa_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+ ops->faim_protect = tfa_faim_protect;
+ ops->set_osc_powerdown = tfa_set_osc_powerdown;
+ ops->update_lpm = tfa_update_lpm;
+ ops->tfa_set_bitfield = tfa_set_bitfield;
+}
+
+/***********************************************************************************/
+/* no TFA
+ * external DSP SB instance */
+ /***********************************************************************************/
+static short tfanone_swvstep, swprof; //TODO emulate in hal plugin
+static enum Tfa98xx_Error tfanone_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ (void)tfa; /* suppress warning */
+ *ready = 1; /* assume always ready */
+
+ return Tfa98xx_Error_Ok;
+}
+
+static int tfanone_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ swprof = new_value;
+
+ return active_value;
+}
+
+static int tfanone_get_swprofile(struct tfa_device *tfa)
+{
+ (void)tfa; /* suppress warning */
+ return swprof;
+}
+
+static int tfanone_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfanone_swvstep = new_value;
+
+ return new_value;
+}
+
+static int tfanone_get_swvstep(struct tfa_device *tfa)
+{
+ (void)tfa; /* suppress warning */
+ return tfanone_swvstep;
+}
+
+void tfanone_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->dsp_system_stable = tfanone_dsp_system_stable;
+ ops->set_swprof = tfanone_set_swprofile;
+ ops->get_swprof = tfanone_get_swprofile;
+ ops->set_swvstep = tfanone_set_swvstep;
+ ops->get_swvstep = tfanone_get_swvstep;
+
+}
+
+/***********************************************************************************/
+/* TFA9912 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9912_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Fail;
+
+ if (tfa) {
+ if (status == 0 || status == 1) {
+ ret = -(tfa_set_bf(tfa, TFA9912_BF_SSFAIME, (uint16_t)status));
+ }
+ }
+
+ return ret;
+}
+
+static enum Tfa98xx_Error tfa9912_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock keys to write settings */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+
+ /* The optimal settings */
+ if (tfa->rev == 0x1a13) {
+
+ /* ----- generated code start ----- */
+ /* ----- version 1.43 ----- */
+ tfa_reg_write(tfa, 0x00, 0x0255); //POR=0x0245
+ tfa_reg_write(tfa, 0x01, 0x838a); //POR=0x83ca
+ tfa_reg_write(tfa, 0x02, 0x2dc8); //POR=0x2828
+ tfa_reg_write(tfa, 0x05, 0x762a); //POR=0x766a
+ tfa_reg_write(tfa, 0x22, 0x543c); //POR=0x545c
+ tfa_reg_write(tfa, 0x26, 0x0100); //POR=0x0010
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x0080
+ tfa_reg_write(tfa, 0x52, 0x551c); //POR=0x1afc
+ tfa_reg_write(tfa, 0x53, 0x003e); //POR=0x001e
+ tfa_reg_write(tfa, 0x61, 0x000c); //POR=0x0018
+ tfa_reg_write(tfa, 0x63, 0x0a96); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0a82); //POR=0x0a8b
+ tfa_reg_write(tfa, 0x66, 0x0701); //POR=0x0700
+ tfa_reg_write(tfa, 0x6c, 0x00d5); //POR=0x02d5
+ tfa_reg_write(tfa, 0x70, 0x26f8); //POR=0x06e0
+ tfa_reg_write(tfa, 0x71, 0x3074); //POR=0x2074
+ tfa_reg_write(tfa, 0x75, 0x4484); //POR=0x4585
+ tfa_reg_write(tfa, 0x76, 0x72ea); //POR=0x54a2
+ tfa_reg_write(tfa, 0x83, 0x0716); //POR=0x0617
+ tfa_reg_write(tfa, 0x89, 0x0013); //POR=0x0014
+ tfa_reg_write(tfa, 0xb0, 0x4c08); //POR=0x4c00
+ tfa_reg_write(tfa, 0xc6, 0x004e); //POR=0x000e /* PLMA5539: Please make sure bit 6 is always on! */
+ /* ----- generated code end ----- */
+
+ /* PLMA5505: MTP key open makes vulanable for MTP corruption */
+ tfa9912_faim_protect(tfa, 0);
+ }
+ else {
+ pr_info("Warning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ }
+
+ return error;
+}
+
+static enum Tfa98xx_Error tfa9912_factory_trimmer(struct tfa_device *tfa)
+{
+ unsigned short currentValue, delta;
+ int result;
+
+ /* Factory trimming for the Boost converter */
+ /* check if there is a correction needed */
+ result = TFA_GET_BF(tfa, DCMCCAPI);
+ if (result) {
+ /* Get currentvalue of DCMCC and the Delta value */
+ currentValue = (unsigned short)TFA_GET_BF(tfa, DCMCC);
+ delta = (unsigned short)TFA_GET_BF(tfa, USERDEF);
+
+ /* check the sign bit (+/-) */
+ result = TFA_GET_BF(tfa, DCMCCSB);
+ if (result == 0) {
+ /* Do not exceed the maximum value of 15 */
+ if (currentValue + delta < 15) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue + delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue + delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 15);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 15 \n");
+ }
+ }
+ else if (result == 1) {
+ /* Do not exceed the minimum value of 0 */
+ if (currentValue - delta > 0) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue - delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue - delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 0);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 0 \n");
+ }
+ }
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error tfa9912_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1. Workaround for 72, 88 and 9912/9892(see PLMA5290) */
+ return tfa_reg_write(tfa, 0xA3, 0x20);
+}
+
+static int tfa9912_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9912_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9912_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9912_BF_SWPROFIL) - 1;
+}
+
+static int tfa9912_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9912_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9912_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9912_BF_SWVSTEP) - 1;
+}
+
+static enum Tfa98xx_Error
+tfa9912_set_mute(struct tfa_device *tfa, int mute)
+{
+ tfa_set_bf(tfa, TFA9912_BF_CFSM, (const uint16_t)mute);
+
+ return Tfa98xx_Error_Ok;
+}
+
+/* Maksimum value for combination of boost_voltage and vout calibration offset (see PLMA5322, PLMA5528). */
+#define TFA9912_VBOOST_MAX 57
+#define TFA9912_CALIBR_BOOST_MAX 63
+#define TFA9912_DCDCCNT6_REG (TFA9912_BF_DCVOF >> 8)
+#define TFA9912_CALIBR_REG 0xf1
+
+static uint16_t tfa9912_vboost_fixup(struct tfa_device *tfa, uint16_t dcdc_cnt6)
+{
+ unsigned short cal_offset;
+ unsigned short boost_v_1st, boost_v_2nd;
+ uint16_t new_dcdc_cnt6;
+
+ /* Get current calibr_vout_offset, this register is not supported by bitfields */
+ tfa_reg_read(tfa, TFA9912_CALIBR_REG, &cal_offset);
+ cal_offset = (cal_offset & 0x001f);
+ new_dcdc_cnt6 = dcdc_cnt6;
+
+ /* Get current boost_volatage values */
+ boost_v_1st = tfa_get_bf_value(TFA9912_BF_DCVOF, new_dcdc_cnt6);
+ boost_v_2nd = tfa_get_bf_value(TFA9912_BF_DCVOS, new_dcdc_cnt6);
+
+ /* Check boost voltages */
+ if (boost_v_1st > TFA9912_VBOOST_MAX)
+ boost_v_1st = TFA9912_VBOOST_MAX;
+
+ if (boost_v_2nd > TFA9912_VBOOST_MAX)
+ boost_v_2nd = TFA9912_VBOOST_MAX;
+
+ /* Recalculate values, max for the sum is TFA9912_CALIBR_BOOST_MAX */
+ if (boost_v_1st + cal_offset > TFA9912_CALIBR_BOOST_MAX)
+ boost_v_1st = TFA9912_CALIBR_BOOST_MAX - cal_offset;
+
+ if (boost_v_2nd + cal_offset > TFA9912_CALIBR_BOOST_MAX)
+ boost_v_2nd = TFA9912_CALIBR_BOOST_MAX - cal_offset;
+
+ tfa_set_bf_value(TFA9912_BF_DCVOF, boost_v_1st, &new_dcdc_cnt6);
+ tfa_set_bf_value(TFA9912_BF_DCVOS, boost_v_2nd, &new_dcdc_cnt6);
+
+ /* Change register value only when it's neccesary */
+ if (new_dcdc_cnt6 != dcdc_cnt6) {
+ if (tfa->verbose)
+ pr_debug("tfa9912: V boost fixup applied. Old 0x%04x, new 0x%04x\n",
+ dcdc_cnt6, new_dcdc_cnt6);
+ dcdc_cnt6 = new_dcdc_cnt6;
+ }
+
+ return dcdc_cnt6;
+}
+
+/* PLMA5322, PLMA5528 - Limit values of DCVOS and DCVOF to range specified in datasheet. */
+enum Tfa98xx_Error tfa9912_reg_write(struct tfa_device *tfa, unsigned char subaddress, unsigned short value)
+{
+ if (subaddress == TFA9912_DCDCCNT6_REG) {
+ /* Correct V boost (first and secondary) to ensure 12V is not exceeded. */
+ value = tfa9912_vboost_fixup(tfa, value);
+ }
+
+ return tfa98xx_write_register16(tfa, subaddress, value);
+}
+
+/** Set internal oscillator into power down mode for TFA9912.
+*
+* This function is a worker for tfa98xx_set_osc_powerdown().
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+static enum Tfa98xx_Error tfa9912_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ if (state == 1 || state == 0) {
+ return -tfa_set_bf(tfa, TFA9912_BF_MANAOOSC, (uint16_t)state);
+ }
+
+ return Tfa98xx_Error_Bad_Parameter;
+}
+/** update low power mode of the device.
+*
+* @param[in] tfa device description structure
+* @param[in] state State of the low power mode1 detector control
+* 0 - low power mode1 detector control enabled,
+* 1 - low power mode1 detector control disabled(low power mode is also disabled).
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+static enum Tfa98xx_Error tfa9912_update_lpm(struct tfa_device *tfa, int state)
+{
+ if (state == 1 || state == 0) {
+ return -tfa_set_bf(tfa, TFA9912_BF_LPM1DIS, (uint16_t)state);
+ }
+ return Tfa98xx_Error_Bad_Parameter;
+}
+
+void tfa9912_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9912_specific;
+ /* PLMA5322, PLMA5528 - Limits values of DCVOS and DCVOF. */
+ ops->tfa_reg_write = tfa9912_reg_write;
+ ops->factory_trimmer = tfa9912_factory_trimmer;
+ ops->auto_copy_mtp_to_iic = tfa9912_auto_copy_mtp_to_iic;
+ ops->set_swprof = tfa9912_set_swprofile;
+ ops->get_swprof = tfa9912_get_swprofile;
+ ops->set_swvstep = tfa9912_set_swvstep;
+ ops->get_swvstep = tfa9912_get_swvstep;
+ ops->set_mute = tfa9912_set_mute;
+ ops->faim_protect = tfa9912_faim_protect;
+ ops->set_osc_powerdown = tfa9912_set_osc_powerdown;
+ ops->update_lpm = tfa9912_update_lpm;
+}
+
+/***********************************************************************************/
+/* TFA9872 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9872_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t MANAOOSC = 0x0140; /* version 17 */
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x1a72:
+ case 0x2a72:
+ /* ----- generated code start ----- */
+ /* ----- version 26 ----- */
+ tfa_reg_write(tfa, 0x00, 0x1801); //POR=0x0001
+ tfa_reg_write(tfa, 0x02, 0x2dc8); //POR=0x2028
+ tfa_reg_write(tfa, 0x20, 0x0890); //POR=0x2890
+ tfa_reg_write(tfa, 0x22, 0x043c); //POR=0x045c
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x0080
+ tfa_reg_write(tfa, 0x52, 0x1a1c); //POR=0x7ae8
+ tfa_reg_write(tfa, 0x58, 0x161c); //POR=0x101c
+ tfa_reg_write(tfa, 0x61, 0x0198); //POR=0x0000
+ tfa_reg_write(tfa, 0x65, 0x0a8b); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x70, 0x07f5); //POR=0x06e6
+ tfa_reg_write(tfa, 0x74, 0xcc84); //POR=0xd823
+ tfa_reg_write(tfa, 0x82, 0x01ed); //POR=0x000d
+ tfa_reg_write(tfa, 0x83, 0x0014); //POR=0x0013
+ tfa_reg_write(tfa, 0x84, 0x0021); //POR=0x0020
+ tfa_reg_write(tfa, 0x85, 0x0001); //POR=0x0003
+ /* ----- generated code end ----- */
+ break;
+ case 0x1b72:
+ case 0x2b72:
+ case 0x3b72:
+ /* ----- generated code start ----- */
+ /* ----- version 25.00 ----- */
+ tfa_reg_write(tfa, 0x02, 0x2dc8); //POR=0x2828
+ tfa_reg_write(tfa, 0x20, 0x0890); //POR=0x2890
+ tfa_reg_write(tfa, 0x22, 0x043c); //POR=0x045c
+ tfa_reg_write(tfa, 0x23, 0x0001); //POR=0x0003
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x0080
+ tfa_reg_write(tfa, 0x52, 0x5a1c); //POR=0x7a08
+ tfa_reg_write(tfa, 0x61, 0x0198); //POR=0x0000
+ tfa_reg_write(tfa, 0x63, 0x0a9a); //POR=0x0a93
+ tfa_reg_write(tfa, 0x65, 0x0a82); //POR=0x0a8d
+ tfa_reg_write(tfa, 0x6f, 0x01e3); //POR=0x02e4
+ tfa_reg_write(tfa, 0x70, 0x06fd); //POR=0x06e6
+ tfa_reg_write(tfa, 0x71, 0x307e); //POR=0x207e
+ tfa_reg_write(tfa, 0x74, 0xcc84); //POR=0xd913
+ tfa_reg_write(tfa, 0x75, 0x1132); //POR=0x118a
+ tfa_reg_write(tfa, 0x82, 0x01ed); //POR=0x000d
+ tfa_reg_write(tfa, 0x83, 0x001a); //POR=0x0013
+ /* ----- generated code end ----- */
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ /* Turn off the osc1m to save power: PLMA4928 */
+ error = tfa_set_bf(tfa, MANAOOSC, 1);
+
+ /* Bypass OVP by setting bit 3 from register 0xB0 (bypass_ovp=1): PLMA5258 */
+ error = tfa_reg_read(tfa, 0xB0, &value);
+ value |= 1 << 3;
+ error = tfa_reg_write(tfa, 0xB0, value);
+
+ return error;
+}
+
+static enum Tfa98xx_Error tfa9872_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1. Workaround for 72 and 88 (see PLMA5290) */
+ return tfa_reg_write(tfa, 0xA3, 0x20);
+}
+
+static int tfa9872_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9872_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9872_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9872_BF_SWPROFIL) - 1;
+}
+
+static int tfa9872_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9872_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9872_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9872_BF_SWVSTEP) - 1;
+}
+
+void tfa9872_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9872_specific;
+ ops->auto_copy_mtp_to_iic = tfa9872_auto_copy_mtp_to_iic;
+ ops->set_swprof = tfa9872_set_swprofile;
+ ops->get_swprof = tfa9872_get_swprofile;
+ ops->set_swvstep = tfa9872_set_swvstep;
+ ops->get_swvstep = tfa9872_get_swvstep;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+
+/***********************************************************************************/
+/* TFA9873 */
+/***********************************************************************************/
+
+static int tfa9873_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9873_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9873_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9873_BF_SWPROFIL) - 1;
+}
+
+static int tfa9873_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9873_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9873_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9873_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9873_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9873_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9873_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9873_BF_MTPB);
+ return value;
+}
+static enum Tfa98xx_Error tfa9873_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9873_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+static enum Tfa98xx_Error tfa9873_specific(struct tfa_device* tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a73:
+ /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 28 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x4c, 0x00e9); //POR=0x00ff
+ tfa_reg_write(tfa, 0x52, 0x17d0); //POR=0x57d0
+ tfa_reg_write(tfa, 0x56, 0x0011); //POR=0x0019
+ tfa_reg_write(tfa, 0x58, 0x0200); //POR=0x0210
+ tfa_reg_write(tfa, 0x59, 0x0001); //POR=0x0000
+ tfa_reg_write(tfa, 0x5f, 0x0180); //POR=0x0100
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0a82
+ tfa_reg_write(tfa, 0x63, 0x055a); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0542); //POR=0x0a82
+ tfa_reg_write(tfa, 0x6f, 0x00a3); //POR=0x0085
+ tfa_reg_write(tfa, 0x70, 0xa3fb); //POR=0x23fb
+ tfa_reg_write(tfa, 0x71, 0x007e); //POR=0x107e
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ tfa_reg_write(tfa, 0x84, 0x0211); //POR=0x0011
+ tfa_reg_write(tfa, 0x85, 0x0382); //POR=0x0380
+ tfa_reg_write(tfa, 0x8c, 0x0210); //POR=0x0010
+ tfa_reg_write(tfa, 0xd5, 0x0000); //POR=0x0100
+ /* ----- generated code end ----- */
+ break;
+ case 0x0b73:
+ /* ----- generated code start ----- */
+ /* ----- version 20 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0182
+ tfa_reg_write(tfa, 0x63, 0x005a); //POR=0x055a
+ tfa_reg_write(tfa, 0x6f, 0x0082); //POR=0x00a5
+ tfa_reg_write(tfa, 0x70, 0xa3eb); //POR=0x23fb
+ tfa_reg_write(tfa, 0x71, 0x107e); //POR=0x007e
+ tfa_reg_write(tfa, 0x73, 0x0187); //POR=0x0107
+ tfa_reg_write(tfa, 0x83, 0x071c); //POR=0x0799
+ tfa_reg_write(tfa, 0x85, 0x0380); //POR=0x0382
+ tfa_reg_write(tfa, 0xd5, 0x004d); //POR=0x014d
+ /* ----- generated code end ----- */
+ break;
+ case 0x1a73:
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+ error = tfa_set_bf_volatile(tfa, TFA9873_BF_FSSYNCEN, 0);
+ pr_info("info : disabled FS synchronisation! \n");
+ return error;
+}
+void tfa9873_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9873_specific;
+ ops->set_swprof = tfa9873_set_swprofile;
+ ops->get_swprof = tfa9873_get_swprofile;
+ ops->set_swvstep = tfa9873_set_swvstep;
+ ops->get_swvstep = tfa9873_get_swvstep;
+ ops->dsp_system_stable = tfa9873_dsp_system_stable;
+ ops->faim_protect = tfa9873_faim_protect;
+ ops->get_mtpb = tfa9873_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+
+/***********************************************************************************/
+/* TFA9874 */
+/***********************************************************************************/
+
+static enum Tfa98xx_Error tfa9874_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9874_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+
+static enum Tfa98xx_Error tfa9874_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a74: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* V25 */
+ tfa_reg_write(tfa, 0x02, 0x22a8); //POR=0x25c8
+ tfa_reg_write(tfa, 0x51, 0x0020); //POR=0x0000
+ tfa_reg_write(tfa, 0x52, 0x57dc); //POR=0x56dc
+ tfa_reg_write(tfa, 0x58, 0x16a4); //POR=0x1614
+ tfa_reg_write(tfa, 0x61, 0x0110); //POR=0x0198
+ tfa_reg_write(tfa, 0x66, 0x0701); //POR=0x0700
+ tfa_reg_write(tfa, 0x6f, 0x00a3); //POR=0x01a3
+ tfa_reg_write(tfa, 0x70, 0x07f8); //POR=0x06f8
+ tfa_reg_write(tfa, 0x73, 0x0007); //POR=0x0005
+ tfa_reg_write(tfa, 0x74, 0x5068); //POR=0xcc80
+ tfa_reg_write(tfa, 0x75, 0x0d28); //POR=0x1138
+ tfa_reg_write(tfa, 0x83, 0x0594); //POR=0x061a
+ tfa_reg_write(tfa, 0x84, 0x0001); //POR=0x0021
+ tfa_reg_write(tfa, 0x85, 0x0001); //POR=0x0003
+ tfa_reg_write(tfa, 0x88, 0x0000); //POR=0x0002
+ tfa_reg_write(tfa, 0xc4, 0x2001); //POR=0x0001
+ /* ----- generated code end ----- */
+ break;
+ case 0x0b74:
+ /* ----- generated code start ----- */
+ /* V1.6 */
+ tfa_reg_write(tfa, 0x02, 0x22a8); //POR=0x25c8
+ tfa_reg_write(tfa, 0x51, 0x0020); //POR=0x0000
+ tfa_reg_write(tfa, 0x52, 0x57dc); //POR=0x56dc
+ tfa_reg_write(tfa, 0x58, 0x16a4); //POR=0x1614
+ tfa_reg_write(tfa, 0x61, 0x0110); //POR=0x0198
+ tfa_reg_write(tfa, 0x66, 0x0701); //POR=0x0700
+ tfa_reg_write(tfa, 0x6f, 0x00a3); //POR=0x01a3
+ tfa_reg_write(tfa, 0x70, 0x07f8); //POR=0x06f8
+ tfa_reg_write(tfa, 0x73, 0x0047); //POR=0x0045
+ tfa_reg_write(tfa, 0x74, 0x5068); //POR=0xcc80
+ tfa_reg_write(tfa, 0x75, 0x0d28); //POR=0x1138
+ tfa_reg_write(tfa, 0x83, 0x0595); //POR=0x061a
+ tfa_reg_write(tfa, 0x84, 0x0001); //POR=0x0021
+ tfa_reg_write(tfa, 0x85, 0x0001); //POR=0x0003
+ tfa_reg_write(tfa, 0x88, 0x0000); //POR=0x0002
+ tfa_reg_write(tfa, 0xc4, 0x2001); //POR=0x0001
+ /* ----- generated code end ----- */
+ break;
+ case 0x0c74:
+ /* ----- generated code start ----- */
+ /* V1.16 */
+ tfa_reg_write(tfa, 0x02, 0x22c8); //POR=0x25c8
+ tfa_reg_write(tfa, 0x52, 0x57dc); //POR=0x56dc
+ tfa_reg_write(tfa, 0x53, 0x003e); //POR=0x001e
+ tfa_reg_write(tfa, 0x56, 0x0400); //POR=0x0600
+ tfa_reg_write(tfa, 0x61, 0x0110); //POR=0x0198
+ tfa_reg_write(tfa, 0x6f, 0x00a5); //POR=0x01a3
+ tfa_reg_write(tfa, 0x70, 0x07f8); //POR=0x06f8
+ tfa_reg_write(tfa, 0x73, 0x0047); //POR=0x0045
+ tfa_reg_write(tfa, 0x74, 0x5098); //POR=0xcc80
+ tfa_reg_write(tfa, 0x75, 0x8d28); //POR=0x1138
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x83, 0x0799); //POR=0x061a
+ tfa_reg_write(tfa, 0x84, 0x0081); //POR=0x0021
+ /* ----- generated code end ----- */
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ return error;
+}
+
+static int tfa9874_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9874_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9874_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9874_BF_SWPROFIL) - 1;
+}
+
+static int tfa9874_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9874_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9874_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9874_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9874_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9874_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9874_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9874_BF_MTPB);
+ return value;
+}
+
+void tfa9874_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9874_specific;
+ ops->set_swprof = tfa9874_set_swprofile;
+ ops->get_swprof = tfa9874_get_swprofile;
+ ops->set_swvstep = tfa9874_set_swvstep;
+ ops->get_swvstep = tfa9874_get_swvstep;
+ ops->dsp_system_stable = tfa9874_dsp_system_stable;
+ ops->faim_protect = tfa9874_faim_protect;
+ ops->get_mtpb = tfa9874_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+/***********************************************************************************/
+/* TFA9875 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9875_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9875_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+
+static enum Tfa98xx_Error tfa9875_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a75: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 26 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x53, 0x0237); //POR=0x0337
+ tfa_reg_write(tfa, 0x58, 0x0210); //POR=0x0200
+ tfa_reg_write(tfa, 0x5f, 0x0080); //POR=0x00c0
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0182
+ tfa_reg_write(tfa, 0x64, 0x4040); //POR=0x0040
+ tfa_reg_write(tfa, 0x6f, 0x0083); //POR=0x00a5
+ tfa_reg_write(tfa, 0x70, 0xdedf); //POR=0xdefb
+ tfa_reg_write(tfa, 0x73, 0x0182); //POR=0x0187
+ tfa_reg_write(tfa, 0x74, 0xd0f8); //POR=0x50f8
+ tfa_reg_write(tfa, 0x75, 0xd57a); //POR=0xd278
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ tfa_reg_write(tfa, 0x85, 0x0380); //POR=0x0382
+ tfa_reg_write(tfa, 0xd5, 0x004d); //POR=0x014d
+ /* ----- generated code end ----- */
+ break;
+ case 0x1a75: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 26 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x51, 0x0020); //POR=0x0000
+ tfa_reg_write(tfa, 0x53, 0x0336); //POR=0x0337
+ tfa_reg_write(tfa, 0x58, 0x0210); //POR=0x0200
+ tfa_reg_write(tfa, 0x5f, 0x0080); //POR=0x00c0
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0182
+ tfa_reg_write(tfa, 0x63, 0x056a); //POR=0x055a
+ tfa_reg_write(tfa, 0x64, 0x4040); //POR=0x0040
+ tfa_reg_write(tfa, 0x6f, 0x0385); //POR=0x00a5
+ tfa_reg_write(tfa, 0x70, 0xde5f); //POR=0xdefb
+ tfa_reg_write(tfa, 0x73, 0x0183); //POR=0x0187
+ tfa_reg_write(tfa, 0x74, 0xd118); //POR=0x50f8
+ tfa_reg_write(tfa, 0x75, 0xd77a); //POR=0xd278
+ tfa_reg_write(tfa, 0x83, 0x06de); //POR=0x0799
+ tfa_reg_write(tfa, 0x85, 0x0380); //POR=0x0382
+ tfa_reg_write(tfa, 0x87, 0x040a); //POR=0x060a
+ /* ----- generated code end ----- */
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ return error;
+}
+
+static int tfa9875_set_bitfield(struct tfa_device* tfa, uint16_t bitfield, uint16_t value)
+{
+ if (((bitfield >> 8) & 0xff) == 0x10 || ((bitfield >> 8) & 0xff) == 0x13)
+ return tfa_set_bf_volatile(tfa, (uint16_t)bitfield, value);
+ else
+ return tfa_set_bf(tfa, (uint16_t)bitfield, value);
+}
+enum Tfa98xx_Error tfa9875_tfa_status(struct tfa_device* tfa)
+{
+ int value;
+ uint16_t val;
+ value = tfa_read_reg(tfa, TFA9875_BF_VDDS); /* STATUSREG */
+ if (value < 0)
+ return -value;
+ val = (uint16_t)value;
+ if (!tfa_get_bf_value(TFA9875_BF_UVDS, val) ||
+ !tfa_get_bf_value(TFA9875_BF_OVDS, val) ||
+ !tfa_get_bf_value(TFA9875_BF_OTDS, val) ||
+ tfa_get_bf_value(TFA9875_BF_OCDS, val) ||
+ tfa_get_bf_value(TFA9875_BF_NOCLK, val))
+ pr_err("Misc errors detected: STATUS_FLAG0 = 0x%x\n", val);
+ if (!tfa_get_bf_value(TFA9875_BF_UVDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_UVDS, 1);
+ if (!tfa_get_bf_value(TFA9875_BF_OVDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_OVDS, 1);
+ if (!tfa_get_bf_value(TFA9875_BF_OTDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_OTDS, 1);
+ if (tfa_get_bf_value(TFA9875_BF_OCDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_OCDS, 1);
+ if (tfa_get_bf_value(TFA9875_BF_NOCLK, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_NOCLK, 1);
+ /*
+ * checking clocking stability.
+ */
+ if (!tfa_get_bf(tfa, TFA9875_BF_CLKS))
+ pr_err("ERROR: CLKS is unstable\n");
+ if (!tfa_get_bf(tfa, TFA9875_BF_PLLS))
+ pr_err("ERROR: PLL not locked\n");
+ if (tfa_get_bf(tfa, TFA9875_BF_TDMERR) ||
+ tfa_get_bf(tfa, TFA9875_BF_TDMLUTER))
+ pr_err("TDM related errors: STATUS_FLAG1 = 0x%x\n", (uint16_t)tfa_read_reg(tfa, TFA9875_BF_TDMERR));
+ if (tfa_get_bf(tfa, TFA9875_BF_BODNOK))
+ {
+ pr_err("BODNOK error detected : STATUS_FLAG3 = 0x%x\n", (uint16_t)tfa_read_reg(tfa, TFA9875_BF_BODNOK));
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_BODNOK, 1);
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+static enum Tfa98xx_Error tfa9875_phase_shift(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 1b = enable phase shift 0b = disable phase shift */
+ ret = tfa_set_bf_volatile(tfa, 0x58c0, (const uint16_t)1);
+ return ret;
+}
+static int tfa9875_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9875_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9875_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9875_BF_SWPROFIL) - 1;
+}
+
+static int tfa9875_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9875_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9875_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9875_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9875_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9875_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9875_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9875_BF_MTPB);
+ return value;
+}
+
+void tfa9875_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9875_specific;
+ ops->set_swprof = tfa9875_set_swprofile;
+ ops->get_swprof = tfa9875_get_swprofile;
+ ops->set_swvstep = tfa9875_set_swvstep;
+ ops->get_swvstep = tfa9875_get_swvstep;
+ ops->dsp_system_stable = tfa9875_dsp_system_stable;
+ ops->faim_protect = tfa9875_faim_protect;
+ ops->get_mtpb = tfa9875_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+ ops->tfa_set_bitfield = tfa9875_set_bitfield;
+ ops->tfa_status = tfa9875_tfa_status;
+ ops->phase_shift = tfa9875_phase_shift;
+}
+/***********************************************************************************/
+/* TFA9878 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9878_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9878_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+
+static enum Tfa98xx_Error tfa9878_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a78: /* Initial revision ID */
+/* ----- generated code start ----- */
+/* ----- version 28 ----- */
+ tfa_reg_write(tfa, 0x01, 0x2e18); //POR=0x2e88
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x04, 0x0240); //POR=0x0340
+ tfa_reg_write(tfa, 0x52, 0x587c); //POR=0x57dc
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0a82
+ tfa_reg_write(tfa, 0x63, 0x055a); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0542); //POR=0x0a82
+ tfa_reg_write(tfa, 0x71, 0x303e); //POR=0x307e
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ /* ----- generated code end ----- */
+
+
+ break;
+ case 0x1a78: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 12 ----- */
+ tfa_reg_write(tfa, 0x01, 0x2e18); //POR=0x2e88
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x04, 0x0241); //POR=0x0340
+ tfa_reg_write(tfa, 0x52, 0x587c); //POR=0x57dc
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0a82
+ tfa_reg_write(tfa, 0x63, 0x055a); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0542); //POR=0x0a82
+ tfa_reg_write(tfa, 0x70, 0xb7ff); //POR=0x37ff
+ tfa_reg_write(tfa, 0x71, 0x303e); //POR=0x307e
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ tfa_reg_write(tfa, 0x84, 0x0211); //POR=0x0011
+ tfa_reg_write(tfa, 0x8c, 0x0210); //POR=0x0010
+ tfa_reg_write(tfa, 0xce, 0x2202); //POR=0xa202
+ tfa_reg_write(tfa, 0xd5, 0x0000); //POR=0x0100
+ /* ----- generated code end ----- */
+
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ return error;
+}
+
+static int tfa9878_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9878_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9878_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9878_BF_SWPROFIL) - 1;
+}
+
+static int tfa9878_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9878_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9878_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9878_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9878_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9878_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9878_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9878_BF_MTPB);
+ return value;
+}
+
+void tfa9878_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9878_specific;
+ ops->set_swprof = tfa9878_set_swprofile;
+ ops->get_swprof = tfa9878_get_swprofile;
+ ops->set_swvstep = tfa9878_set_swvstep;
+ ops->get_swvstep = tfa9878_get_swvstep;
+ ops->dsp_system_stable = tfa9878_dsp_system_stable;
+ ops->faim_protect = tfa9878_faim_protect;
+ ops->get_mtpb = tfa9878_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+/***********************************************************************************/
+/* TFA9888 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9888_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+ int patch_version;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock keys to write settings */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+
+ /* Only N1C2 is supported */
+ /* ----- generated code start ----- */
+ /* --------- Version v1 ---------- */
+ if (tfa->rev == 0x2c88) {
+ tfa_reg_write(tfa, 0x00, 0x164d); //POR=0x064d
+ tfa_reg_write(tfa, 0x01, 0x828b); //POR=0x92cb
+ tfa_reg_write(tfa, 0x02, 0x1dc8); //POR=0x1828
+ tfa_reg_write(tfa, 0x0e, 0x0080); //POR=0x0000
+ tfa_reg_write(tfa, 0x20, 0x089e); //POR=0x0890
+ tfa_reg_write(tfa, 0x22, 0x543c); //POR=0x545c
+ tfa_reg_write(tfa, 0x23, 0x0006); //POR=0x0000
+ tfa_reg_write(tfa, 0x24, 0x0014); //POR=0x0000
+ tfa_reg_write(tfa, 0x25, 0x000a); //POR=0x0000
+ tfa_reg_write(tfa, 0x26, 0x0100); //POR=0x0000
+ tfa_reg_write(tfa, 0x28, 0x1000); //POR=0x0000
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x00c0
+ tfa_reg_write(tfa, 0x52, 0xfafe); //POR=0xbaf6
+ tfa_reg_write(tfa, 0x70, 0x3ee4); //POR=0x3ee6
+ tfa_reg_write(tfa, 0x71, 0x1074); //POR=0x3074
+ tfa_reg_write(tfa, 0x83, 0x0014); //POR=0x0013
+ /* ----- generated code end ----- */
+ }
+ else {
+ pr_info("Warning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ }
+
+ patch_version = tfa_cnt_get_patch_version(tfa);
+ if (patch_version >= 0x060401)
+ tfa->partial_enable = 1;
+
+ return error;
+}
+
+static enum Tfa98xx_Error tfa9888_tfa_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ unsigned char buffer[15] = { 0 };
+ int size = 15 * sizeof(char);
+
+ /* Write the fractional delay in the hardware register 'cs_frac_delay' */
+ switch (sample_rate) {
+ case 0: /* 8kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 40);
+ break;
+ case 1: /* 11.025KHz */
+ TFA_SET_BF(tfa, FRACTDEL, 38);
+ break;
+ case 2: /* 12kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 37);
+ break;
+ case 3: /* 16kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 59);
+ break;
+ case 4: /* 22.05KHz */
+ TFA_SET_BF(tfa, FRACTDEL, 56);
+ break;
+ case 5: /* 24kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 56);
+ break;
+ case 6: /* 32kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 52);
+ break;
+ case 7: /* 44.1kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 48);
+ break;
+ case 8:
+ default:/* 48kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 46);
+ break;
+ }
+
+ /* First copy the msg_id to the buffer */
+ buffer[0] = (uint8_t)0;
+ buffer[1] = (uint8_t)MODULE_FRAMEWORK + 128;
+ buffer[2] = (uint8_t)FW_PAR_ID_SET_SENSES_DELAY;
+
+ /* Required for all FS exept 8kHz (8kHz is all zero) */
+ if (sample_rate != 0) {
+ buffer[5] = 1; /* Vdelay_P */
+ buffer[8] = 0; /* Idelay_P */
+ buffer[11] = 1; /* Vdelay_S */
+ buffer[14] = 0; /* Idelay_S */
+ }
+
+ /* send SetSensesDelay msg */
+ return tfa_dsp_msg(tfa, size, (char *)buffer);
+}
+
+static enum Tfa98xx_Error tfa9888_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1. Workaround for 72 and 88 (see PLMA5290) */
+ return tfa_reg_write(tfa, 0xA3, 0x20);
+}
+
+static enum Tfa98xx_Error tfa9888_factory_trimmer(struct tfa_device *tfa)
+{
+ unsigned short currentValue, delta;
+ int result;
+
+ /* Factory trimming for the Boost converter */
+ /* check if there is a correction needed */
+ result = TFA_GET_BF(tfa, DCMCCAPI);
+ if (result) {
+ /* Get currentvalue of DCMCC and the Delta value */
+ currentValue = (unsigned short)TFA_GET_BF(tfa, DCMCC);
+ delta = (unsigned short)TFA_GET_BF(tfa, USERDEF);
+
+ /* check the sign bit (+/-) */
+ result = TFA_GET_BF(tfa, DCMCCSB);
+ if (result == 0) {
+ /* Do not exceed the maximum value of 15 */
+ if (currentValue + delta < 15) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue + delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue + delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 15);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 15 \n");
+ }
+ }
+ else if (result == 1) {
+ /* Do not exceed the minimum value of 0 */
+ if (currentValue - delta > 0) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue - delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue - delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 0);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 0 \n");
+ }
+ }
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error
+tfa9888_set_mute(struct tfa_device *tfa, int mute)
+{
+ TFA_SET_BF(tfa, CFSMR, (const uint16_t)mute);
+ TFA_SET_BF(tfa, CFSML, (const uint16_t)mute);
+
+ return Tfa98xx_Error_Ok;
+}
+
+void tfa9888_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9888_specific;
+ ops->dsp_write_tables = tfa9888_tfa_dsp_write_tables;
+ ops->auto_copy_mtp_to_iic = tfa9888_auto_copy_mtp_to_iic;
+ ops->factory_trimmer = tfa9888_factory_trimmer;
+ ops->set_mute = tfa9888_set_mute;
+}
+
+/***********************************************************************************/
+/* TFA9896 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9896_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+
+ if ((tfa->rev == 0x2b96) || (tfa->rev == 0x3b96)) {
+ ret = tfa_set_bf_volatile(tfa, TFA9896_BF_OPENMTP, (uint16_t)status);
+ }
+
+ return ret;
+}
+
+/***********************************************************************************/
+/* TFA9896 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9896_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short check_value;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers must already set to default POR value */
+
+ /* $48:[3] - 1 ==> 0; iddqtestbst - default value changed.
+ * When Iddqtestbst is set to "0", the slewrate is reduced.
+ * This will lower the overshoot on IN-B to avoid NMOS damage of booster.
+ */
+ if (tfa->rev == 0x1b96) {
+ /* ----- generated code start v17 ----- */
+ tfa_reg_write(tfa, 0x06, 0x000b); //POR=0x0001
+ tfa_reg_write(tfa, 0x07, 0x3e7f); //POR=0x1e7f
+ tfa_reg_write(tfa, 0x0a, 0x0d8a); //POR=0x0592
+ tfa_reg_write(tfa, 0x48, 0x0300); //POR=0x0308
+ tfa_reg_write(tfa, 0x88, 0x0100); //POR=0x0000
+ /* ----- generated code end ----- */
+ }
+ else if (tfa->rev == 0x2b96) {
+ /* ----- generated code start ----- v1*/
+ tfa_reg_write(tfa, 0x06, 0x000b); //POR=0x0001
+ tfa_reg_write(tfa, 0x07, 0x3e7f); //POR=0x1e7f
+ tfa_reg_write(tfa, 0x0a, 0x0d8a); //POR=0x0592
+ tfa_reg_write(tfa, 0x48, 0x0300); //POR=0x0308
+ tfa_reg_write(tfa, 0x88, 0x0100); //POR=0x0000
+ /* ----- generated code end ----- */
+ }
+ else if (tfa->rev == 0x3b96) {
+ /* ----- generated code start ----- v1*/
+ tfa_reg_write(tfa, 0x06, 0x000b); //POR=0x0001
+ tfa_reg_write(tfa, 0x07, 0x3e7f); //POR=0x1e7f
+ tfa_reg_write(tfa, 0x0a, 0x0d8a); //POR=0x0592
+ tfa_reg_write(tfa, 0x48, 0x0300); //POR=0x0308
+ tfa_reg_write(tfa, 0x88, 0x0100); //POR=0x0000
+ /* ----- generated code end ----- */
+ }
+ /* $49:[0] - 1 ==> 0; CLIP - default value changed. 0 means CLIPPER on */
+ error = tfa_reg_read(tfa, 0x49, &check_value);
+ check_value &= ~0x1;
+ error = tfa_reg_write(tfa, 0x49, check_value);
+ return error;
+}
+
+/*
+* the int24 values for the vsfw delay table
+*/
+static unsigned char tfa9896_vsfwdelay_table[] = {
+ 0,0,2, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0,0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0,0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,2, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,2, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,2, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,2, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,3 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+/*
+* TODO make this tfa98xx
+* Note that the former products write this table via the patch
+* so moving this to the tfa98xx API requires also updating all patches
+*/
+static enum Tfa98xx_Error tfa9896_dsp_write_vsfwdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURRENT_DELAY, sizeof(tfa9896_vsfwdelay_table), tfa9896_vsfwdelay_table);
+}
+
+/*
+* The int24 values for the fracdelay table
+* For now applicable only for 8 and 48 kHz
+*/
+static unsigned char tfa9896_cvfracdelay_table[] = {
+ 0,0,51, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0, 0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0, 0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,38, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,34, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,33, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,11, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,62 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+static enum Tfa98xx_Error tfa9896_dsp_write_cvfracdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURFRAC_DELAY, sizeof(tfa9896_cvfracdelay_table), tfa9896_cvfracdelay_table);;
+}
+
+static enum Tfa98xx_Error tfa9896_tfa_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ enum Tfa98xx_Error error;
+
+ /* Not used for max1! */
+ (void)sample_rate;
+
+ error = tfa9896_dsp_write_vsfwdelay_table(tfa);
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfa9896_dsp_write_cvfracdelay_table(tfa);
+ }
+
+ return error;
+}
+
+void tfa9896_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9896_specific;
+ ops->dsp_write_tables = tfa9896_tfa_dsp_write_tables;
+ ops->faim_protect = tfa9896_faim_protect;
+}
+
+/***********************************************************************************/
+/* TFA9897 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9897_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short check_value;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers must already set to default POR value */
+
+ /* $48:[3] - 1 ==> 0; iddqtestbst - default value changed.
+ * When Iddqtestbst is set to "0", the slewrate is reduced.
+ * This will lower the overshoot on IN-B to avoid NMOS damage of booster */
+ error = tfa_reg_write(tfa, 0x48, 0x0300); /* POR value = 0x308 */
+
+ /* $49:[0] - 1 ==> 0; CLIP - default value changed. 0 means CLIPPER on */
+ error = tfa_reg_read(tfa, 0x49, &check_value);
+ check_value &= ~0x1;
+ error = tfa_reg_write(tfa, 0x49, check_value);
+
+ return error;
+}
+
+/*
+* the int24 values for the vsfw delay table
+*/
+static unsigned char tfa9897_vsfwdelay_table[] = {
+ 0,0,2, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0,0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0,0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,2, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,2, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,2, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,2, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,3 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+/*
+* TODO make this tfa98xx
+* Note that the former products write this table via the patch
+* so moving this to the tfa98xx API requires also updating all patches
+*/
+static enum Tfa98xx_Error tfa9897_dsp_write_vsfwdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURRENT_DELAY, sizeof(tfa9897_vsfwdelay_table), tfa9897_vsfwdelay_table);;
+}
+
+/*
+* The int24 values for the fracdelay table
+* For now applicable only for 8 and 48 kHz
+*/
+static unsigned char tfa9897_cvfracdelay_table[] = {
+ 0,0,51, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0, 0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0, 0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,38, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,34, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,33, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,11, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,62 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+static enum Tfa98xx_Error tfa9897_dsp_write_cvfracdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURFRAC_DELAY, sizeof(tfa9897_cvfracdelay_table), tfa9897_cvfracdelay_table);;
+}
+
+static enum Tfa98xx_Error tfa9897_tfa_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ enum Tfa98xx_Error error;
+
+ /* Not used for max1! */
+ (void)sample_rate;
+
+ error = tfa9897_dsp_write_vsfwdelay_table(tfa);
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfa9897_dsp_write_cvfracdelay_table(tfa);
+ }
+
+ return error;
+}
+
+void tfa9897_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9897_specific;
+ ops->dsp_write_tables = tfa9897_tfa_dsp_write_tables;
+}
+
+/***********************************************************************************/
+/* TFA9895 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9895_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int result;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers are already set to default */
+
+ result = TFA_SET_BF(tfa, AMPE, 1);
+ if (result < 0)
+ return -result;
+
+ /* some other registers must be set for optimal amplifier behaviour */
+ tfa_reg_write(tfa, 0x05, 0x13AB);
+ tfa_reg_write(tfa, 0x06, 0x001F);
+ /* peak voltage protection is always on, but may be written */
+ tfa_reg_write(tfa, 0x08, 0x3C4E);
+ /*TFA98XX_SYSCTRL_DCA=0*/
+ tfa_reg_write(tfa, 0x09, 0x024D);
+ tfa_reg_write(tfa, 0x41, 0x0308);
+ error = tfa_reg_write(tfa, 0x49, 0x0E82);
+
+ return error;
+}
+
+void tfa9895_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9895_specific;
+}
+
+/***********************************************************************************/
+/* TFA9891 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9891_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* ----- generated code start ----- */
+ /* ----- version 18.0 ----- */
+ tfa_reg_write(tfa, 0x09, 0x025d); //POR=0x024d
+ tfa_reg_write(tfa, 0x10, 0x0018); //POR=0x0024
+ tfa_reg_write(tfa, 0x22, 0x0003); //POR=0x0023
+ tfa_reg_write(tfa, 0x25, 0x0001); //POR=0x0000
+ tfa_reg_write(tfa, 0x46, 0x0000); //POR=0x4000
+ tfa_reg_write(tfa, 0x55, 0x3ffb); //POR=0x7fff
+ /* ----- generated code end ----- */
+
+ return error;
+}
+
+void tfa9891_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9891_specific;
+}
+
+/***********************************************************************************/
+/* TFA9890 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9890_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short regRead = 0;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers are already set to default for N1C2 */
+
+ /* some PLL registers must be set optimal for amplifier behaviour */
+ error = tfa_reg_write(tfa, 0x40, 0x5a6b);
+ if (error)
+ return error;
+ tfa_reg_read(tfa, 0x59, &regRead);
+ regRead |= 0x3;
+ tfa_reg_write(tfa, 0x59, regRead);
+ error = tfa_reg_write(tfa, 0x40, 0x0000);
+ error = tfa_reg_write(tfa, 0x47, 0x7BE1);
+
+ return error;
+}
+
+/*
+* Disable clock gating
+*/
+static enum Tfa98xx_Error tfa9890_clockgating(struct tfa_device *tfa, int on)
+{
+ enum Tfa98xx_Error error;
+ unsigned short value;
+
+ /* for TFA9890 temporarily disable clock gating when dsp reset is used */
+ error = tfa_reg_read(tfa, TFA98XX_CURRENTSENSE4, &value);
+ if (error) return error;
+
+ if (Tfa98xx_Error_Ok == error) {
+ if (on) /* clock gating on - clear the bit */
+ value &= ~TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF;
+ else /* clock gating off - set the bit */
+ value |= TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF;
+
+ error = tfa_reg_write(tfa, TFA98XX_CURRENTSENSE4, value);
+ }
+
+ return error;
+}
+
+/*
+* Tfa9890_DspReset will deal with clock gating control in order
+* to reset the DSP for warm state restart
+*/
+static enum Tfa98xx_Error tfa9890_dsp_reset(struct tfa_device *tfa, int state)
+{
+ enum Tfa98xx_Error error;
+
+ /* for TFA9890 temporarily disable clock gating
+ when dsp reset is used */
+ tfa9890_clockgating(tfa, 0);
+
+ TFA_SET_BF(tfa, RST, (uint16_t)state);
+
+ /* clock gating restore */
+ error = tfa9890_clockgating(tfa, 1);
+
+ return error;
+}
+
+/*
+ * Tfa9890_DspSystemStable will compensate for the wrong behavior of CLKS
+ * to determine if the DSP subsystem is ready for patch and config loading.
+ *
+ * A MTP calibration register is checked for non-zero.
+ *
+ * Note: This only works after i2c reset as this will clear the MTP contents.
+ * When we are configured then the DSP communication will synchronize access.
+ *
+ */
+static enum Tfa98xx_Error tfa9890_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short status, mtp0;
+ int result, tries;
+
+ /* check the contents of the STATUS register */
+ result = TFA_READ_REG(tfa, AREFS);
+ if (result < 0) {
+ error = -result;
+ goto errorExit;
+ }
+ status = (unsigned short)result;
+
+ /* if AMPS is set then we were already configured and running
+ * no need to check further
+ */
+ *ready = (TFA_GET_BF_VALUE(tfa, AMPS, status) == 1);
+ if (*ready) /* if ready go back */
+ return error; /* will be Tfa98xx_Error_Ok */
+
+ /* check AREFS and CLKS: not ready if either is clear */
+ *ready = !((TFA_GET_BF_VALUE(tfa, AREFS, status) == 0)
+ || (TFA_GET_BF_VALUE(tfa, CLKS, status) == 0));
+ if (!*ready) /* if not ready go back */
+ return error; /* will be Tfa98xx_Error_Ok */
+
+ /* check MTPB
+ * mtpbusy will be active when the subsys copies MTP to I2C
+ * 2 times retry avoids catching this short mtpbusy active period
+ */
+ for (tries = 2; tries > 0; tries--) {
+ result = TFA_GET_BF(tfa, MTPB);/*TODO_MTPB*/
+ if (result < 0) {
+ error = -result;
+ goto errorExit;
+ }
+ status = (unsigned short)result;
+
+ /* check the contents of the STATUS register */
+ *ready = (result == 0);
+ if (*ready) /* if ready go on */
+ break;
+ }
+ if (tries == 0) /* ready will be 0 if retries exausted */
+ return Tfa98xx_Error_Ok;
+
+ /* check the contents of MTP register for non-zero,
+ * this indicates that the subsys is ready */
+
+ error = tfa_reg_read(tfa, 0x84, &mtp0);
+ if (error)
+ goto errorExit;
+
+ *ready = (mtp0 != 0); /* The MTP register written? */
+
+ return error;
+
+errorExit:
+ *ready = 0;
+ return error;
+}
+
+void tfa9890_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9890_specific;
+ ops->dsp_reset = tfa9890_dsp_reset;
+ ops->dsp_system_stable = tfa9890_dsp_system_stable;
+}
+
+/***********************************************************************************/
+/* TFA9894 */
+/***********************************************************************************/
+static int tfa9894_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+ tfa_set_bf_volatile(tfa, TFA9894_BF_SWPROFIL, new_value);
+ return active_value;
+}
+
+static int tfa9894_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9894_BF_SWPROFIL) - 1;
+}
+
+static int tfa9894_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+ tfa_set_bf_volatile(tfa, TFA9894_BF_SWVSTEP, new_value);
+ return new_value;
+}
+
+static int tfa9894_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9894_BF_SWVSTEP) - 1;
+}
+
+static int tfa9894_get_mtpb(struct tfa_device *tfa)
+{
+ int value = 0;
+ value = tfa_get_bf(tfa, TFA9894_BF_MTPB);
+ return value;
+}
+
+/** Set internal oscillator into power down mode for TFA9894.
+*
+* This function is a worker for tfa98xx_set_osc_powerdown().
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+static enum Tfa98xx_Error tfa9894_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ if (state == 1 || state == 0) {
+ return -tfa_set_bf(tfa, TFA9894_BF_MANAOOSC, (uint16_t)state);
+ }
+
+ return Tfa98xx_Error_Bad_Parameter;
+}
+
+static enum Tfa98xx_Error tfa9894_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9894_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+static enum Tfa98xx_Error tfa9894_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ /* Unlock keys to write settings */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ pr_debug("Device REFID:%x\n", tfa->rev);
+ /* The optimal settings */
+ if (tfa->rev == 0x0a94) {
+ /* V36 */
+ /* ----- generated code start ----- */
+ tfa_reg_write(tfa, 0x00, 0xa245); //POR=0x8245
+ tfa_reg_write(tfa, 0x02, 0x51e8); //POR=0x55c8
+ tfa_reg_write(tfa, 0x52, 0xbe17); //POR=0xb617
+ tfa_reg_write(tfa, 0x57, 0x0344); //POR=0x0366
+ tfa_reg_write(tfa, 0x61, 0x0033); //POR=0x0073
+ tfa_reg_write(tfa, 0x71, 0x00cf); //POR=0x018d
+ tfa_reg_write(tfa, 0x72, 0x34a9); //POR=0x44e8
+ tfa_reg_write(tfa, 0x73, 0x3808); //POR=0x3806
+ tfa_reg_write(tfa, 0x76, 0x0067); //POR=0x0065
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x81, 0x5715); //POR=0x561a
+ tfa_reg_write(tfa, 0x82, 0x0104); //POR=0x0044
+ /* ----- generated code end ----- */
+ }
+ else if (tfa->rev == 0x1a94) {
+ /* V17 */
+ /* ----- generated code start ----- */
+ tfa_reg_write(tfa, 0x00, 0xa245); //POR=0x8245
+ tfa_reg_write(tfa, 0x01, 0x15da); //POR=0x11ca
+ tfa_reg_write(tfa, 0x02, 0x5288); //POR=0x55c8
+ tfa_reg_write(tfa, 0x52, 0xbe17); //POR=0xb617
+ tfa_reg_write(tfa, 0x53, 0x0dbe); //POR=0x0d9e
+ tfa_reg_write(tfa, 0x56, 0x05c3); //POR=0x07c3
+ tfa_reg_write(tfa, 0x57, 0x0344); //POR=0x0366
+ tfa_reg_write(tfa, 0x61, 0x0032); //POR=0x0073
+ tfa_reg_write(tfa, 0x71, 0x00cf); //POR=0x018d
+ tfa_reg_write(tfa, 0x72, 0x34a9); //POR=0x44e8
+ tfa_reg_write(tfa, 0x73, 0x38c8); //POR=0x3806
+ tfa_reg_write(tfa, 0x76, 0x0067); //POR=0x0065
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x81, 0x5799); //POR=0x561a
+ tfa_reg_write(tfa, 0x82, 0x0104); //POR=0x0044
+ /* ----- generated code end ----- */
+
+ }
+ else if (tfa->rev == 0x2a94 || tfa->rev == 0x3a94) {
+ /* ----- generated code start ----- */
+ /* ----- version 25.00 ----- */
+ tfa_reg_write(tfa, 0x01, 0x15da); //POR=0x11ca
+ tfa_reg_write(tfa, 0x02, 0x51e8); //POR=0x55c8
+ tfa_reg_write(tfa, 0x04, 0x0200); //POR=0x0000
+ tfa_reg_write(tfa, 0x52, 0xbe17); //POR=0xb617
+ tfa_reg_write(tfa, 0x53, 0x0dbe); //POR=0x0d9e
+ tfa_reg_write(tfa, 0x57, 0x0344); //POR=0x0366
+ tfa_reg_write(tfa, 0x61, 0x0032); //POR=0x0073
+ tfa_reg_write(tfa, 0x71, 0x6ecf); //POR=0x6f8d
+ tfa_reg_write(tfa, 0x72, 0xb4a9); //POR=0x44e8
+ tfa_reg_write(tfa, 0x73, 0x38c8); //POR=0x3806
+ tfa_reg_write(tfa, 0x76, 0x0067); //POR=0x0065
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x81, 0x5799); //POR=0x561a
+ tfa_reg_write(tfa, 0x82, 0x0104); //POR=0x0044
+ /* ----- generated code end ----- */
+ }
+ return error;
+}
+
+static enum Tfa98xx_Error
+tfa9894_set_mute(struct tfa_device *tfa, int mute)
+{
+ tfa_set_bf(tfa, TFA9894_BF_CFSM, (const uint16_t)mute);
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error tfa9894_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9894_BF_CLKS) == 1;
+
+ return error;
+}
+
+void tfa9894_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9894_specific;
+ ops->dsp_system_stable = tfa9894_dsp_system_stable;
+ ops->set_mute = tfa9894_set_mute;
+ ops->faim_protect = tfa9894_faim_protect;
+ ops->get_mtpb = tfa9894_get_mtpb;
+ ops->set_swprof = tfa9894_set_swprofile;
+ ops->get_swprof = tfa9894_get_swprofile;
+ ops->set_swvstep = tfa9894_set_swvstep;
+ ops->get_swvstep = tfa9894_get_swvstep;
+ //ops->auto_copy_mtp_to_iic = tfa9894_auto_copy_mtp_to_iic;
+ ops->set_osc_powerdown = tfa9894_set_osc_powerdown;
+}
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_internal.h b/sound/soc/codecs/tfa98xx-downstream/tfa_internal.h
new file mode 100644
index 00000000000..39ecacf8c36
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_internal.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/*
+ internal functions for TFA layer (not shared with SRV and HAL layer!)
+*/
+
+#ifndef __TFA_INTERNAL_H__
+#define __TFA_INTERNAL_H__
+
+#include "tfa_dsp_fw.h"
+#include "tfa_ext.h"
+
+#if __GNUC__ >= 4
+ #define TFA_INTERNAL __attribute__ ((visibility ("hidden")))
+#else
+ #define TFA_INTERNAL
+#endif
+
+#define TFA98XX_GENERIC_SLAVE_ADDRESS 0x1C
+
+TFA_INTERNAL enum Tfa98xx_Error tfa98xx_check_rpc_status(struct tfa_device *tfa, int *pRpcStatus);
+TFA_INTERNAL enum Tfa98xx_Error tfa98xx_wait_result(struct tfa_device *tfa, int waitRetryCount);
+
+#endif /* __TFA_INTERNAL_H__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_service.h b/sound/soc/codecs/tfa98xx-downstream/tfa_service.h
new file mode 100644
index 00000000000..0e57893946e
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_service.h
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+
+#ifndef TFA_SERVICE_H
+#define TFA_SERVICE_H
+
+//#include "config.h"
+// workaround for Visual Studio:
+// fatal error C1083: Cannot open include file: 'config.h': No such file or directory
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef __cplusplus
+extern "C" {
+#include "TFA_I2C.h"
+#endif
+
+/* Linux kernel module defines TFA98XX_GIT_VERSIONS in the linux_driver/Makefile */
+#if 0
+#include "versions.h"
+#endif
+#ifdef TFA98XX_GIT_VERSIONS
+ #define TFA98XX_API_REV_STR "v6.7.14"/*TFA98XX_GIT_VERSIONS*/
+#else
+ #define TFA98XX_API_REV_STR "v6.7.14"
+#endif
+
+#include "tfa_device.h"
+
+/*
+ * data previously defined in Tfa9888_dsp.h
+ */
+#define MEMTRACK_MAX_WORDS 150
+#define LSMODEL_MAX_WORDS 150
+#define TFA98XX_MAXTAG (150)
+#define FW_VAR_API_VERSION (521)
+
+/* Indexes and scaling factors of GetLSmodel */
+#define tfa9888_fs_IDX 128
+#define tfa9888_leakageFactor_IDX 130
+#define tfa9888_ReCorrection_IDX 131
+#define tfa9888_Bl_IDX 132
+#define ReZ_IDX 147
+
+#define tfa9872_leakageFactor_IDX 128
+#define tfa9872_ReCorrection_IDX 129
+#define tfa9872_Bl_IDX 130
+
+#define fs_SCALE (double)1
+#define leakageFactor_SCALE (double)8388608
+#define ReCorrection_SCALE (double)8388608
+#define Bl_SCALE (double)2097152
+#define tCoef_SCALE (double)8388608
+
+/* ---------------------------- Max1 ---------------------------- */
+/* Headroom applied to the main input signal */
+#define SPKRBST_HEADROOM 7
+/* Exponent used for AGC Gain related variables */
+#define SPKRBST_AGCGAIN_EXP SPKRBST_HEADROOM
+#define SPKRBST_TEMPERATURE_EXP 9
+/* Exponent used for Gain Corection related variables */
+#define SPKRBST_LIMGAIN_EXP 4
+#define SPKRBST_TIMECTE_EXP 1
+#define DSP_MAX_GAIN_EXP 7
+/* -------------------------------------------------------------- */
+
+/* speaker related parameters */
+#define TFA2_SPEAKERPARAMETER_LENGTH (3*151) /* MAX2=450 */
+#define TFA1_SPEAKERPARAMETER_LENGTH (3*141) /* MAX1=423 */
+
+/* vstep related parameters */
+#define TFA2_ALGOPARAMETER_LENGTH (3*304) /* N1B = (304) 305 is including the cmd-id */
+#define TFA72_ALGOPARAMETER_LENGTH_MONO (3*183)
+#define TFA72_ALGOPARAMETER_LENGTH_STEREO (3*356)
+#define TFA2_MBDRCPARAMETER_LENGTH (3*152) /* 154 is including the cmd-id */
+#define TFA72_MBDRCPARAMETER_LENGTH (3*98)
+#define TFA1_PRESET_LENGTH 87
+#define TFA1_DRC_LENGTH 381 /* 127 words */
+#define TFA2_FILTERCOEFSPARAMETER_LENGTH (3*168) /* 170 is including the cmd-id */
+#define TFA72_FILTERCOEFSPARAMETER_LENGTH (3*156)
+
+/* Maximum number of retries for DSP result
+ * Keep this value low!
+ * If certain calls require longer wait conditions, the
+ * application should poll, not the API
+ * The total wait time depends on device settings. Those
+ * are application specific.
+ */
+#define TFA98XX_WAITRESULT_NTRIES 40
+#define TFA98XX_WAITRESULT_NTRIES_LONG 2000
+
+/* following lengths are in bytes */
+#define TFA98XX_PRESET_LENGTH 87
+#define TFA98XX_CONFIG_LENGTH 201
+#define TFA98XX_DRC_LENGTH 381 /* 127 words */
+
+typedef unsigned char Tfa98xx_Config_t[TFA98XX_CONFIG_LENGTH];
+typedef unsigned char Tfa98xx_Preset_t[TFA98XX_PRESET_LENGTH];
+typedef unsigned char Tfa98xx_DrcParameters_t[TFA98XX_DRC_LENGTH];
+
+/* Type containing all the possible errors that can occur
+ *
+ */
+enum Tfa98xx_Error {
+ Tfa98xx_Error_Ok = 0,
+ Tfa98xx_Error_Device, /* 1. Currently only used to keep in sync with tfa_error */
+ Tfa98xx_Error_Bad_Parameter, /* 2. */
+ Tfa98xx_Error_Fail, /* 3. generic failure, avoid mislead message */
+ Tfa98xx_Error_NoClock, /* 4. no clock detected */
+ Tfa98xx_Error_StateTimedOut, /* 5. */
+ Tfa98xx_Error_DSP_not_running, /* 6. communication with the DSP failed */
+ Tfa98xx_Error_AmpOn, /* 7. amp is still running */
+ Tfa98xx_Error_NotOpen, /* 8. the given handle is not open */
+ Tfa98xx_Error_InUse, /* 9. too many handles */
+ Tfa98xx_Error_Buffer_too_small, /* 10. if a buffer is too small */
+ /* the expected response did not occur within the expected time */
+ Tfa98xx_Error_RpcBase = 100,
+ Tfa98xx_Error_RpcBusy = 101,
+ Tfa98xx_Error_RpcModId = 102,
+ Tfa98xx_Error_RpcParamId = 103,
+ Tfa98xx_Error_RpcInvalidCC = 104,
+ Tfa98xx_Error_RpcInvalidSeq = 105,
+ Tfa98xx_Error_RpcInvalidParam = 106,
+ Tfa98xx_Error_RpcBufferOverflow = 107,
+ Tfa98xx_Error_RpcCalibBusy = 108,
+ Tfa98xx_Error_RpcCalibFailed = 109,
+ Tfa98xx_Error_Not_Implemented,
+ Tfa98xx_Error_Not_Supported,
+ Tfa98xx_Error_I2C_Fatal, /* Fatal I2C error occurred */
+ /* Nonfatal I2C error, and retry count reached */
+ Tfa98xx_Error_I2C_NonFatal,
+ Tfa98xx_Error_Other = 1000
+};
+
+/*
+ * Type containing all the possible msg returns DSP can give
+ * //TODO move to tfa_dsp_fw.h
+ */
+enum Tfa98xx_Status_ID {
+ Tfa98xx_DSP_Not_Running = -1, /* No response from DSP */
+ Tfa98xx_I2C_Req_Done = 0, /* Request executed correctly and result, if any, is available for download */
+ Tfa98xx_I2C_Req_Busy = 1, /* Request is being processed, just wait for result */
+ Tfa98xx_I2C_Req_Invalid_M_ID = 2, /* Provided M-ID does not fit in valid rang [0..2] */
+ Tfa98xx_I2C_Req_Invalid_P_ID = 3, /* Provided P-ID isn<73>t valid in the given M-ID context */
+ Tfa98xx_I2C_Req_Invalid_CC = 4, /* Invalid channel configuration bits (SC|DS|DP|DC) combination */
+ Tfa98xx_I2C_Req_Invalid_Seq = 5, /* Invalid sequence of commands, in case the DSP expects some commands in a specific order */
+ Tfa98xx_I2C_Req_Invalid_Param = 6, /* Generic error */
+ Tfa98xx_I2C_Req_Buffer_Overflow = 7, /* I2C buffer has overflowed: host has sent too many parameters, memory integrity is not guaranteed */
+ Tfa98xx_I2C_Req_Calib_Busy = 8, /* Calibration not finished */
+ Tfa98xx_I2C_Req_Calib_Failed = 9 /* Calibration failed */
+};
+
+/*
+ * speaker as microphone
+ */
+enum Tfa98xx_saam {
+ Tfa98xx_saam_none, /*< SAAM feature not available */
+ Tfa98xx_saam /*< SAAM feature available */
+};
+
+/*
+ * config file subtypes
+ */
+enum Tfa98xx_config_type {
+ Tfa98xx_config_generic,
+ Tfa98xx_config_sub1,
+ Tfa98xx_config_sub2,
+ Tfa98xx_config_sub3,
+};
+
+enum Tfa98xx_AmpInputSel {
+ Tfa98xx_AmpInputSel_I2SLeft,
+ Tfa98xx_AmpInputSel_I2SRight,
+ Tfa98xx_AmpInputSel_DSP
+};
+
+enum Tfa98xx_OutputSel {
+ Tfa98xx_I2SOutputSel_CurrentSense,
+ Tfa98xx_I2SOutputSel_DSP_Gain,
+ Tfa98xx_I2SOutputSel_DSP_AEC,
+ Tfa98xx_I2SOutputSel_Amp,
+ Tfa98xx_I2SOutputSel_DataI3R,
+ Tfa98xx_I2SOutputSel_DataI3L,
+ Tfa98xx_I2SOutputSel_DcdcFFwdCur,
+};
+
+enum Tfa98xx_StereoGainSel {
+ Tfa98xx_StereoGainSel_Left,
+ Tfa98xx_StereoGainSel_Right
+};
+
+#define TFA98XX_MAXPATCH_LENGTH (3*1024)
+
+/* the number of biquads supported */
+#define TFA98XX_BIQUAD_NUM 10
+
+enum Tfa98xx_Channel {
+ Tfa98xx_Channel_L,
+ Tfa98xx_Channel_R,
+ Tfa98xx_Channel_L_R,
+ Tfa98xx_Channel_Stereo
+};
+
+enum Tfa98xx_Mode {
+ Tfa98xx_Mode_Normal = 0,
+ Tfa98xx_Mode_RCV
+};
+
+enum Tfa98xx_Mute {
+ Tfa98xx_Mute_Off,
+ Tfa98xx_Mute_Digital,
+ Tfa98xx_Mute_Amplifier
+};
+
+enum Tfa98xx_SpeakerBoostStatusFlags {
+ Tfa98xx_SpeakerBoost_Activity = 0, /* Input signal activity. */
+ Tfa98xx_SpeakerBoost_S_Ctrl, /* S Control triggers the limiter */
+ Tfa98xx_SpeakerBoost_Muted, /* 1 when signal is muted */
+ Tfa98xx_SpeakerBoost_X_Ctrl, /* X Control triggers the limiter */
+ Tfa98xx_SpeakerBoost_T_Ctrl, /* T Control triggers the limiter */
+ Tfa98xx_SpeakerBoost_NewModel, /* New model is available */
+ Tfa98xx_SpeakerBoost_VolumeRdy, /* 0:stable vol, 1:still smoothing */
+ Tfa98xx_SpeakerBoost_Damaged, /* Speaker Damage detected */
+ Tfa98xx_SpeakerBoost_SignalClipping /* input clipping detected */
+};
+
+struct Tfa98xx_DrcStateInfo {
+ float GRhighDrc1[2];
+ float GRhighDrc2[2];
+ float GRmidDrc1[2];
+ float GRmidDrc2[2];
+ float GRlowDrc1[2];
+ float GRlowDrc2[2];
+ float GRpostDrc1[2];
+ float GRpostDrc2[2];
+ float GRblDrc[2];
+};
+struct Tfa98xx_StateInfo {
+ /* SpeakerBoost State */
+ float agcGain; /* Current AGC Gain value */
+ float limGain; /* Current Limiter Gain value */
+ float sMax; /* Current Clip/Lim threshold */
+ int T; /* Current Speaker Temperature value */
+ int statusFlag; /* Masked bit word */
+ float X1; /* estimated excursion caused by Spkrboost gain ctrl */
+ float X2; /* estimated excursion caused by manual gain setting */
+ float Re; /* Loudspeaker blocked resistance */
+ /* Framework state */
+ /* increments each time a MIPS problem is detected on the DSP */
+ int shortOnMips;
+ struct Tfa98xx_DrcStateInfo drcState; /* DRC state, when enabled */
+};
+
+typedef struct TfaMsg {
+ uint8_t msg_size;
+ unsigned char cmdId[3];
+ int data[9];
+} TfaMsg_t;
+
+typedef struct tfa_vstep_msg {
+ int fw_version;
+ uint8_t no_of_vsteps;
+ uint16_t reg_no;
+ uint8_t *msg_reg;
+ uint8_t msg_no;
+ uint32_t algo_param_length;
+ uint8_t *msg_algo_param;
+ uint32_t filter_coef_length;
+ uint8_t *msg_filter_coef;
+ uint32_t mbdrc_length;
+ uint8_t *msg_mbdrc;
+} tfa_vstep_msg_t;
+
+typedef struct TfaGroup {
+ uint8_t msg_size;
+ uint8_t profileId[64];
+} TfaGroup_t;
+
+
+struct Tfa98xx_Memtrack_data {
+ int length;
+ float mValues[MEMTRACK_MAX_WORDS];
+ int mAdresses[MEMTRACK_MAX_WORDS];
+ int trackers[MEMTRACK_MAX_WORDS];
+ int scalingFactor[MEMTRACK_MAX_WORDS];
+};
+
+/* possible memory values for DMEM in CF_CONTROLs */
+enum Tfa98xx_DMEM {
+ Tfa98xx_DMEM_ERR = -1,
+ Tfa98xx_DMEM_PMEM = 0,
+ Tfa98xx_DMEM_XMEM = 1,
+ Tfa98xx_DMEM_YMEM = 2,
+ Tfa98xx_DMEM_IOMEM = 3,
+};
+
+/**
+ * lookup the device type and return the family type
+ */
+int tfa98xx_dev2family(int dev_type);
+
+/**
+ * register definition structure
+ */
+struct regdef {
+ unsigned char offset; /**< subaddress offset */
+ unsigned short pwronDefault; /**< register contents after poweron */
+ unsigned short pwronTestmask; /**< mask of bits not test */
+ char *name; /**< short register name */
+};
+
+enum Tfa98xx_DMEM tfa98xx_filter_mem(struct tfa_device *tfa, int filter_index, unsigned short *address, int channel);
+
+/**
+ * Load the default HW settings in the device
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa98xx_init(struct tfa_device *tfa);
+
+/**
+ * If needed, this function can be used to get a text version of the status ID code
+ * @param status the given status ID code
+ * @return the I2C status ID string
+ */
+const char *tfa98xx_get_i2c_status_id_string(int status);
+
+/* control the powerdown bit
+ * @param tfa the device struct pointer
+ * @param powerdown must be 1 or 0
+ */
+enum Tfa98xx_Error tfa98xx_powerdown(struct tfa_device *tfa, int powerdown);
+
+/* indicates on which channel of DATAI2 the gain from the IC is set
+ * @param tfa the device struct pointer
+ * @param gain_sel, see Tfa98xx_StereoGainSel_t
+ */
+enum Tfa98xx_Error tfa98xx_select_stereo_gain_channel(struct tfa_device *tfa,
+ enum Tfa98xx_StereoGainSel gain_sel);
+
+/**
+ * set the mtp with user controllable values
+ * @param tfa the device struct pointer
+ * @param value to be written
+ * @param mask to be applied toi the bits affected
+ */
+enum Tfa98xx_Error tfa98xx_set_mtp(struct tfa_device *tfa, uint16_t value, uint16_t mask);
+enum Tfa98xx_Error tfa98xx_get_mtp(struct tfa_device *tfa, uint16_t *value);
+
+/**
+ * lock or unlock KEY2
+ * lock = 1 will lock
+ * lock = 0 will unlock
+ * note that on return all the hidden key will be off
+ */
+void tfa98xx_key2(struct tfa_device *tfa, int lock);
+
+int tfa_calibrate(struct tfa_device *tfa) ;
+void tfa98xx_set_exttemp(struct tfa_device *tfa, short ext_temp);
+short tfa98xx_get_exttemp(struct tfa_device *tfa);
+
+/* control the volume of the DSP
+ * @param vol volume in bit field. It must be between 0 and 255
+ */
+enum Tfa98xx_Error tfa98xx_set_volume_level(struct tfa_device *tfa,
+ unsigned short vol);
+
+/* set the input channel to use
+ * @param channel see Tfa98xx_Channel_t enumeration
+ */
+enum Tfa98xx_Error tfa98xx_select_channel(struct tfa_device *tfa,
+ enum Tfa98xx_Channel channel);
+
+/* set the mode for normal or receiver mode
+ * @param mode see Tfa98xx_Mode enumeration
+ */
+enum Tfa98xx_Error tfa98xx_select_mode(struct tfa_device *tfa, enum Tfa98xx_Mode mode );
+
+/* mute/unmute the audio
+ * @param mute see Tfa98xx_Mute_t enumeration
+ */
+enum Tfa98xx_Error tfa98xx_set_mute(struct tfa_device *tfa,
+ enum Tfa98xx_Mute mute);
+
+/*
+ * tfa_supported_speakers - required for SmartStudio initialization
+ * returns the number of the supported speaker count
+ */
+enum Tfa98xx_Error tfa_supported_speakers(struct tfa_device *tfa, int* spkr_count);
+
+/**
+* Return the tfa revision
+*/
+void tfa98xx_rev(int *major, int *minor, int *revision);
+
+/*
+ * Return the feature bits from MTP and cnt file for comparison
+ */
+enum Tfa98xx_Error
+tfa98xx_compare_features(struct tfa_device *tfa, int features_from_MTP[3], int features_from_cnt[3]);
+
+/*
+ * return feature bits
+ */
+enum Tfa98xx_Error
+tfa98xx_dsp_get_sw_feature_bits(struct tfa_device *tfa, int features[2]);
+enum Tfa98xx_Error
+tfa98xx_dsp_get_hw_feature_bits(struct tfa_device *tfa, int *features);
+
+/*
+ * tfa98xx_supported_saam
+ * returns the speaker as microphone feature
+ * @param saam enum pointer
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_supported_saam(struct tfa_device *tfa, enum Tfa98xx_saam *saam);
+
+/* load the tables to the DSP
+ * called after patch load is done
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_dsp_write_tables(struct tfa_device *tfa, int sample_rate);
+
+
+/* set or clear DSP reset signal
+ * @param new state
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_dsp_reset(struct tfa_device *tfa, int state);
+
+/* check the state of the DSP subsystem
+ * return ready = 1 when clocks are stable to allow safe DSP subsystem access
+ * @param tfa the device struct pointer
+ * @param ready pointer to state flag, non-zero if clocks are not stable
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_dsp_system_stable(struct tfa_device *tfa, int *ready);
+
+enum Tfa98xx_Error tfa98xx_auto_copy_mtp_to_iic(struct tfa_device *tfa);
+
+/**
+ * check the state of the DSP coolflux
+ * @param tfa the device struct pointer
+ * @return the value of CFE
+ */
+int tfa_cf_enabled(struct tfa_device *tfa);
+
+/* The following functions can only be called when the DSP is running
+ * - I2S clock must be active,
+ * - IC must be in operating mode
+ */
+
+/**
+ * patch the ROM code of the DSP
+ * @param tfa the device struct pointer
+ * @param patchLength the number of bytes of patchBytes
+ * @param patchBytes pointer to the bytes to patch
+ */
+enum Tfa98xx_Error tfa_dsp_patch(struct tfa_device *tfa,
+ int patchLength,
+ const unsigned char *patchBytes);
+
+/**
+ * load explicitly the speaker parameters in case of free speaker,
+ * or when using a saved speaker model
+ */
+enum Tfa98xx_Error tfa98xx_dsp_write_speaker_parameters(
+ struct tfa_device *tfa,
+ int length,
+ const unsigned char *pSpeakerBytes);
+
+/**
+ * read the speaker parameters as used by the SpeakerBoost processing
+ */
+enum Tfa98xx_Error tfa98xx_dsp_read_speaker_parameters(
+ struct tfa_device *tfa,
+ int length,
+ unsigned char *pSpeakerBytes);
+
+/**
+ * read the current status of the DSP, typically used for development,
+ * not essential to be used in a product
+ */
+enum Tfa98xx_Error tfa98xx_dsp_get_state_info(
+ struct tfa_device *tfa,
+ unsigned char bytes[],
+ unsigned int *statesize);
+
+/**
+ * Check whether the DSP supports DRC
+ * pbSupportDrc=1 when DSP supports DRC,
+ * pbSupportDrc=0 when DSP doesn't support it
+ */
+enum Tfa98xx_Error tfa98xx_dsp_support_drc(struct tfa_device *tfa,
+ int *pbSupportDrc);
+
+enum Tfa98xx_Error
+tfa98xx_dsp_support_framework(struct tfa_device *tfa, int *pbSupportFramework);
+
+/**
+ * read the speaker excursion model as used by SpeakerBoost processing
+ */
+enum Tfa98xx_Error tfa98xx_dsp_read_excursion_model(
+ struct tfa_device *tfa,
+ int length,
+ unsigned char *pSpeakerBytes);
+
+/**
+ * load all the parameters for a preset from a file
+ */
+enum Tfa98xx_Error tfa98xx_dsp_write_preset(struct tfa_device *tfa,
+ int length, const unsigned char
+ *pPresetBytes);
+
+/**
+ * wrapper for dsp_msg that adds opcode and only writes
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ const unsigned char data[]);
+
+/**
+ * wrapper for dsp_msg that writes opcode and reads back the data
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write_read(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[]);
+
+/**
+ * wrapper for dsp_msg that adds opcode and 3 bytes required for coefs
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_coefs(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[]);
+
+/**
+ * wrapper for dsp_msg that adds opcode and 3 bytes required for MBDrcDynamics
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_MBDrc_dynamics(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int index_subband,
+ int num_bytes, unsigned char data[]);
+
+/**
+ * Disable a certain biquad.
+ * @param tfa the device struct pointer
+ * @param biquad_index: 1-10 of the biquad that needs to be adressed
+*/
+enum Tfa98xx_Error Tfa98xx_DspBiquad_Disable(struct tfa_device *tfa,
+ int biquad_index);
+
+/**
+ * fill the calibration value as milli ohms in the struct
+ * assume that the device has been calibrated
+ */
+enum Tfa98xx_Error
+tfa_dsp_get_calibration_impedance(struct tfa_device *tfa);
+
+/*
+ * return the mohm value
+ */
+int tfa_get_calibration_info(struct tfa_device *tfa, int channel);
+
+/*
+ * return sign extended tap pattern
+ */
+int tfa_get_tap_pattern(struct tfa_device *tfa);
+
+/**
+ * Reads a number of words from dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress write address to set in address register
+ * @param pValue pointer to read data
+*/
+enum Tfa98xx_Error tfa98xx_read_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short *pValue);
+
+/**
+ * Reads a number of words from dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress write address to set in address register
+ * @param value value to write int the memory
+*/
+enum Tfa98xx_Error tfa98xx_write_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short value);
+
+/**
+ * Intialise the dsp
+ * @param tfa the device struct pointer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_init_dsp(struct tfa_device *tfa);
+
+/**
+ * Get the status of the external DSP
+ * @param tfa the device struct pointer
+ * @return status
+*/
+int tfa98xx_get_dsp_status(struct tfa_device *tfa);
+
+/**
+ * Write a command message (RPC) to the dsp
+ * @param tfa the device struct pointer
+ * @param num_bytes command buffer size in bytes
+ * @param command_buffer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_write_dsp(struct tfa_device *tfa, int num_bytes, const char *command_buffer);
+
+/**
+ * Read the result from the last message from the dsp
+ * @param tfa the device struct pointer
+ * @param num_bytes result buffer size in bytes
+ * @param result_buffer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_read_dsp(struct tfa_device *tfa, int num_bytes, unsigned char *result_buffer);
+
+/**
+ * Write a command message (RPC) to the dsp and return the result
+ * @param tfa the device struct pointer
+ * @param command_length command buffer size in bytes
+ * @param command_buffer command buffer
+ * @param result_length result buffer size in bytes
+ * @param result_buffer result buffer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_writeread_dsp(struct tfa_device *tfa, int command_length, void *command_buffer,
+ int result_length, void *result_buffer);
+
+/**
+ * Reads a number of words from dsp memory
+ * @param tfa the device struct pointer
+ * @param start_offset offset from where to start reading
+ * @param num_words number of words to read
+ * @param pValues pointer to read data
+*/
+enum Tfa98xx_Error tfa98xx_dsp_read_mem(struct tfa_device *tfa,
+ unsigned int start_offset,
+ int num_words, int *pValues);
+/**
+ * Write a value to dsp memory
+ * @param tfa the device struct pointer
+ * @param address write address to set in address register
+ * @param value value to write int the memory
+ * @param memtype type of memory to write to
+*/
+enum Tfa98xx_Error tfa98xx_dsp_write_mem_word(struct tfa_device *tfa,
+ unsigned short address, int value, int memtype);
+
+/**
+ * Read data from dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress write address to set in address register
+ * @param num_bytes number of bytes to read from dsp
+ * @param data the unsigned char buffer to read data into
+*/
+enum Tfa98xx_Error tfa98xx_read_data(struct tfa_device *tfa,
+ unsigned char subaddress,
+ int num_bytes, unsigned char data[]);
+
+/**
+ * Write all the bytes specified by num_bytes and data to dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress the subaddress to write to
+ * @param num_bytes number of bytes to write
+ * @param data actual data to write
+*/
+enum Tfa98xx_Error tfa98xx_write_data(struct tfa_device *tfa,
+ unsigned char subaddress,
+ int num_bytes,
+ const unsigned char data[]);
+
+enum Tfa98xx_Error tfa98xx_write_raw(struct tfa_device *tfa,
+ int num_bytes,
+ const unsigned char data[]);
+
+/* support for converting error codes into text */
+const char *tfa98xx_get_error_string(enum Tfa98xx_Error error);
+
+/**
+ * convert signed 24 bit integers to 32bit aligned bytes
+ * input: data contains "num_bytes/3" int24 elements
+ * output: bytes contains "num_bytes" byte elements
+ * @param num_data length of the input data array
+ * @param data input data as integer array
+ * @param bytes output data as unsigned char array
+*/
+void tfa98xx_convert_data2bytes(int num_data, const int data[],
+ unsigned char bytes[]);
+
+/**
+ * convert memory bytes to signed 24 bit integers
+ * input: bytes contains "num_bytes" byte elements
+ * output: data contains "num_bytes/3" int24 elements
+ * @param num_bytes length of the input data array
+ * @param bytes input data as unsigned char array
+ * @param data output data as integer array
+*/
+void tfa98xx_convert_bytes2data(int num_bytes, const unsigned char bytes[],
+ int data[]);
+
+/**
+ * Read a part of the dsp memory
+ * @param tfa the device struct pointer
+ * @param memoryType indicator to the memory type
+ * @param offset from where to start reading
+ * @param length the number of bytes to read
+ * @param bytes output data as unsigned char array
+*/
+enum Tfa98xx_Error tfa98xx_dsp_get_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, unsigned char bytes[]);
+
+/**
+ * Write a value to the dsp memory
+ * @param tfa the device struct pointer
+ * @param memoryType indicator to the memory type
+ * @param offset from where to start writing
+ * @param length the number of bytes to write
+ * @param value the value to write to the dsp
+*/
+enum Tfa98xx_Error tfa98xx_dsp_set_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, int value);
+
+enum Tfa98xx_Error tfa98xx_dsp_write_config(struct tfa_device *tfa, int length, const unsigned char *p_config_bytes);
+enum Tfa98xx_Error tfa98xx_dsp_write_drc(struct tfa_device *tfa, int length, const unsigned char *p_drc_bytes);
+
+/**
+ * write/read raw msg functions :
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buf character buffer to write
+*/
+enum Tfa98xx_Error tfa_dsp_msg_rpc(struct tfa_device *tfa, int length, const char *buf);
+
+
+/**
+ * The wrapper functions to call the dsp msg, register and memory function for tfa or probus
+ */
+enum Tfa98xx_Error tfa_dsp_msg(struct tfa_device *tfa, int length, const char *buf);
+enum Tfa98xx_Error tfa_dsp_msg_read(struct tfa_device *tfa, int length, unsigned char *bytes);
+enum Tfa98xx_Error tfa_reg_write(struct tfa_device *tfa, unsigned char subaddress, unsigned short value);
+enum Tfa98xx_Error tfa_reg_read(struct tfa_device *tfa, unsigned char subaddress, unsigned short *value);
+enum Tfa98xx_Error tfa_mem_write(struct tfa_device *tfa, unsigned short address, int value, int memtype);
+enum Tfa98xx_Error tfa_mem_read(struct tfa_device *tfa, unsigned int start_offset, int num_words, int *pValues);
+
+enum Tfa98xx_Error tfa_dsp_partial_coefficients(struct tfa_device *tfa, uint8_t *prev, uint8_t *next);
+int tfa_is_94_N2_device(struct tfa_device *tfa);
+/**
+ * write/read raw msg functions:
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ * An ID is added to modify the command-ID
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buf character buffer to write
+ * @param cmdid command identifier
+*/
+enum Tfa98xx_Error tfa_dsp_msg_id(struct tfa_device *tfa, int length, const char *buf, uint8_t cmdid[3]);
+
+/**
+ * write raw dsp msg functions
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buffer character buffer to write
+*/
+enum Tfa98xx_Error tfa_dsp_msg_write(struct tfa_device *tfa, int length, const char *buffer);
+
+/**
+ * write raw dsp msg functions
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buffer character buffer to write
+ * @param cmdid command identifier
+*/
+enum Tfa98xx_Error tfa_dsp_msg_write_id(struct tfa_device *tfa, int length, const char *buffer, uint8_t cmdid[3]);
+
+/**
+ * status function used by tfa_dsp_msg() to retrieve command/msg status:
+ * return a <0 status of the DSP did not ACK.
+ * @param tfa the device struct pointer
+ * @param pRpcStatus status for remote processor communication
+*/
+enum Tfa98xx_Error tfa_dsp_msg_status(struct tfa_device *tfa, int *pRpcStatus);
+
+/**
+ * Read a message from dsp
+ * @param tfa the device struct pointer
+ * @param length number of bytes of the message
+ * @param bytes pointer to unsigned char buffer
+*/
+enum Tfa98xx_Error tfa_dsp_msg_read_rpc(struct tfa_device *tfa,int length, unsigned char *bytes);
+
+int tfa_set_bf(struct tfa_device *tfa, const uint16_t bf, const uint16_t value);
+int tfa_set_bf_volatile(struct tfa_device *tfa, const uint16_t bf, const uint16_t value);
+
+/**
+ * Get the value of a given bitfield
+ * @param tfa the device struct pointer
+ * @param bf the value indicating which bitfield
+ */
+int tfa_get_bf(struct tfa_device *tfa, const uint16_t bf);
+
+/**
+ * Set the value of a given bitfield
+ * @param bf the value indicating which bitfield
+ * @param bf_value the value of the bitfield
+ * @param p_reg_value a pointer to the register where to write the bitfield value
+ */
+int tfa_set_bf_value(const uint16_t bf, const uint16_t bf_value, uint16_t *p_reg_value);
+
+uint16_t tfa_get_bf_value(const uint16_t bf, const uint16_t reg_value);
+int tfa_write_reg(struct tfa_device *tfa, const uint16_t bf, const uint16_t reg_value);
+int tfa_read_reg(struct tfa_device *tfa, const uint16_t bf);
+
+/* bitfield */
+/**
+ * get the datasheet or bitfield name corresponding to the bitfield number
+ * @param num is the number for which to get the bitfield name
+ * @param rev is the device type
+ */
+char *tfaContBfName(uint16_t num, unsigned short rev);
+
+/**
+ * get the datasheet name corresponding to the bitfield number
+ * @param num is the number for which to get the bitfield name
+ * @param rev is the device type
+ */
+char *tfaContDsName(uint16_t num, unsigned short rev);
+
+/**
+ * get the bitfield name corresponding to the bitfield number
+ * @param num is the number for which to get the bitfield name
+ * @param rev is the device type
+ */
+char *tfaContBitName(uint16_t num, unsigned short rev);
+
+/**
+ * get the bitfield number corresponding to the bitfield name
+ * @param name is the bitfield name for which to get the bitfield number
+ * @param rev is the device type
+ */
+uint16_t tfaContBfEnum(const char *name, unsigned short rev);
+
+/**
+* get the bitfield number corresponding to the bitfield name, checks for all devices
+* @param name is the bitfield name for which to get the bitfield number
+ */
+uint16_t tfaContBfEnumAny(const char *name);
+
+#define TFA_FAM(tfa, fieldname) ((tfa->tfa_family == 1) ? TFA1_BF_##fieldname : TFA2_BF_##fieldname)
+#define TFA_FAM_FW(tfa, fwname) ((tfa->tfa_family == 1) ? TFA1_FW_##fwname : TFA2_FW_##fwname)
+#define TFA2_FAM_TDM(tfa, fieldname) (((tfa->rev & 0xff) == 0x94) ? TFA9894_BF_##fieldname : TFA2_BF_##fieldname)
+
+/* set/get bit fields to HW register*/
+#define TFA_SET_BF(tfa, fieldname, value) tfa_set_bf(tfa, TFA_FAM(tfa, fieldname), value)
+#define TFA_SET_BF_VOLATILE(tfa, fieldname, value) tfa_set_bf_volatile(tfa, TFA_FAM(tfa, fieldname), value)
+#define TFA_GET_BF(tfa, fieldname) tfa_get_bf(tfa, TFA_FAM(tfa, fieldname))
+
+
+/* set/get bit field in variable */
+#define TFA_SET_BF_VALUE(tfa, fieldname, bf_value, p_reg_value) tfa_set_bf_value(TFA_FAM(tfa, fieldname), bf_value, p_reg_value)
+#define TFA_GET_BF_VALUE(tfa, fieldname, reg_value) tfa_get_bf_value(TFA_FAM(tfa, fieldname), reg_value)
+
+/* write/read registers using a bit field name to determine the register address */
+#define TFA_WRITE_REG(tfa, fieldname, value) tfa_write_reg(tfa, TFA_FAM(tfa, fieldname), value)
+#define TFA_READ_REG(tfa, fieldname) tfa_read_reg(tfa, TFA_FAM(tfa, fieldname))
+
+/* FOR CALIBRATION RETRIES */
+#define TFA98XX_API_WAITRESULT_NTRIES 3000 // defined in API
+
+/**
+ * run the startup/init sequence and set ACS bit
+ * @param tfa the device struct pointer
+ * @param state the cold start state that is requested
+ */
+enum Tfa98xx_Error tfaRunColdboot(struct tfa_device *tfa, int state);
+enum Tfa98xx_Error tfaRunMute(struct tfa_device *tfa);
+enum Tfa98xx_Error tfaRunUnmute(struct tfa_device *tfa);
+
+/**
+ * wait for calibrateDone
+ * @param tfa the device struct pointer
+ * @param calibrateDone pointer to status of calibration
+ */
+enum Tfa98xx_Error tfaRunWaitCalibration(struct tfa_device *tfa, int *calibrateDone);
+
+/**
+ * run the startup/init sequence and set ACS bit
+ * @param tfa the device struct pointer
+ * @param profile the profile that should be loaded
+ */
+enum Tfa98xx_Error tfaRunColdStartup(struct tfa_device *tfa, int profile);
+
+/**
+ * this will load the patch witch will implicitly start the DSP
+ * if no patch is available the DPS is started immediately
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfaRunStartDSP(struct tfa_device *tfa);
+
+/**
+ * start the clocks and wait until the AMP is switching
+ * on return the DSP sub system will be ready for loading
+ * @param tfa the device struct pointer
+ * @param profile the profile that should be loaded on startup
+ */
+enum Tfa98xx_Error tfaRunStartup(struct tfa_device *tfa, int profile);
+
+/**
+ * start the maximus speakerboost algorithm
+ * this implies a full system startup when the system was not already started
+ * @param tfa the device struct pointer
+ * @param force indicates wether a full system startup should be allowed
+ * @param profile the profile that should be loaded
+ */
+enum Tfa98xx_Error tfaRunSpeakerBoost(struct tfa_device *tfa, int force, int profile);
+
+/**
+ * Startup the device and write all files from device and profile section
+ * @param tfa the device struct pointer
+ * @param force indicates wether a full system startup should be allowed
+ * @param profile the profile that should be loaded on speaker startup
+ */
+enum Tfa98xx_Error tfaRunSpeakerStartup(struct tfa_device *tfa, int force, int profile);
+
+/**
+ * Run calibration
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfaRunSpeakerCalibration(struct tfa_device *tfa);
+
+/**
+ * startup all devices. all step until patch loading is handled
+ * @param tfa the device struct pointer
+ */
+int tfaRunStartupAll(struct tfa_device *tfa);
+
+/**
+ * powerup the coolflux subsystem and wait for it
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa_cf_powerup(struct tfa_device *tfa);
+
+/*
+ * print the current device manager state
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa_show_current_state(struct tfa_device *tfa);
+
+/**
+ * Init registers and coldboot dsp
+ * @param tfa the device struct pointer
+ */
+int tfa_reset(struct tfa_device *tfa);
+
+/**
+ * Get profile from a register
+ * @param tfa the device struct pointer
+ */
+int tfa_dev_get_swprof(struct tfa_device *tfa);
+
+/**
+ * Save profile in a register
+ */
+int tfa_dev_set_swprof(struct tfa_device *tfa, unsigned short new_value);
+
+int tfa_dev_get_swvstep(struct tfa_device *tfa);
+
+int tfa_dev_set_swvstep(struct tfa_device *tfa, unsigned short new_value);
+
+int tfa_needs_reset(struct tfa_device *tfa);
+
+int tfa_is_cold(struct tfa_device *tfa);
+
+void tfa_set_query_info(struct tfa_device *tfa);
+
+int tfa_get_pga_gain(struct tfa_device *tfa);
+int tfa_set_pga_gain(struct tfa_device *tfa, uint16_t value);
+int tfa_get_noclk(struct tfa_device *tfa);
+
+/**
+ * Status of used for monitoring
+ * @param tfa the device struct pointer
+ * @return tfa error enum
+ */
+
+enum Tfa98xx_Error tfa_status(struct tfa_device *tfa);
+
+/*
+ * function overload for flag_mtp_busy
+ */
+int tfa_dev_get_mtpb(struct tfa_device *tfa);
+
+enum Tfa98xx_Error tfaGetFwApiVersion(struct tfa_device *tfa, unsigned char *pFirmwareVersion);
+#ifdef __cplusplus
+}
+#endif
+#endif /* TFA_SERVICE_H */
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c
index 5da1934527f..c5b72786178 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -65,6 +65,7 @@ struct wcd_mbhc {
bool extn_cable_hph_rem;
bool force_linein;
bool impedance_detect;
+ bool micbias_enabled;
unsigned long event_state;
unsigned long jiffies_atreport;
/* impedance of hphl and hphr */
@@ -193,7 +194,7 @@ int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
* make sure current source is enabled so as to detect
* button press/release events
*/
- if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) {
+ if (mbhc->mbhc_cb->mbhc_micbias_control && mbhc->micbias_enabled) {
if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN))
wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
}
@@ -273,8 +274,10 @@ static void wcd_micbias_disable(struct wcd_mbhc *mbhc)
{
struct snd_soc_component *component = mbhc->component;
- if (mbhc->mbhc_cb->mbhc_micbias_control)
+ if (mbhc->mbhc_cb->mbhc_micbias_control && mbhc->micbias_enabled) {
mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
+ mbhc->micbias_enabled = false;
+ }
if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(component, MIC_BIAS_2, false);
@@ -502,6 +505,7 @@ static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc)
if (mbhc->mbhc_cb->mbhc_micbias_control) {
mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2,
MICB_ENABLE);
+ mbhc->micbias_enabled = true;
wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
}
}
@@ -1235,8 +1239,10 @@ static void wcd_correct_swch_plug(struct work_struct *work)
wcd_mbhc_adc_update_fsm_source(mbhc, plug_type);
exit:
- if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/)
+ if (mbhc->mbhc_cb->mbhc_micbias_control && mbhc->micbias_enabled) {
mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
+ mbhc->micbias_enabled = false;
+ }
/*
* If plug type is corrected from special headset to headphone,
@@ -1464,6 +1470,7 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
mbhc->mbhc_cb = mbhc_cb;
mbhc->fields = fields;
mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
+ mbhc->micbias_enabled = false;
if (mbhc_cb->compute_impedance)
mbhc->impedance_detect = impedance_det_en;
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 6813268e6a1..aab6fe03858 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -3013,6 +3013,7 @@ static int wcd934x_mbhc_init(struct snd_soc_component *component)
{
struct wcd934x_ddata *data = dev_get_drvdata(component->dev->parent);
struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(component);
+ struct wcd_mbhc_config *cfg = &wcd->mbhc_cfg;
struct wcd_mbhc_intr *intr_ids = &wcd->intr_ids;
intr_ids->mbhc_sw_intr = regmap_irq_get_virq(data->irq_data,
@@ -3036,6 +3037,8 @@ static int wcd934x_mbhc_init(struct snd_soc_component *component)
return -EINVAL;
}
+ cfg->micb_mv = wcd->micb2_mv;
+
snd_soc_add_component_controls(component, impedance_detect_controls,
ARRAY_SIZE(impedance_detect_controls));
snd_soc_add_component_controls(component, hph_type_detect_controls,
@@ -5890,7 +5893,6 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
cfg->anc_micbias = MIC_BIAS_2;
cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
cfg->num_btn = WCD934X_MBHC_MAX_BUTTONS;
- cfg->micb_mv = wcd->micb2_mv;
cfg->linein_th = 5000;
cfg->hs_thr = 1700;
cfg->hph_thr = 50;
diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
index f2653df84e4..ac10eb6cfa1 100644
--- a/sound/soc/codecs/wsa884x.c
+++ b/sound/soc/codecs/wsa884x.c
@@ -1769,6 +1769,12 @@ static int wsa884x_set_stream(struct snd_soc_dai *dai,
void *stream, int direction)
{
struct wsa884x_priv *wsa884x = dev_get_drvdata(dai->dev);
+ struct sdw_stream_runtime *sruntime = stream;
+ struct sdw_slave *sdw = dev_to_sdw_dev(dai->dev);
+
+ /* Check if this belongs to same bus */
+ // if (sdw->bus->dev != sruntime->dev)
+ // return 0;
wsa884x->sruntime = stream;
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index 762491d6f2f..2845a83f712 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -140,6 +140,14 @@ config SND_SOC_QDSP6
audio drivers. This includes q6asm, q6adm,
q6afe interfaces to DSP using apr.
+config SND_SOC_QDSP6_Q6VOICE_DAI
+ tristate
+
+config SND_SOC_QDSP6_Q6VOICE
+ tristate "QDSP6 Q6Voice audio driver"
+ depends on SND_SOC_QDSP6
+ select SND_SOC_QDSP6_Q6VOICE_DAI
+
config SND_SOC_MSM8996
tristate "SoC Machine driver for MSM8996 and APQ8096 boards"
depends on QCOM_APR
diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile
index 3963bf23466..8491440075f 100644
--- a/sound/soc/qcom/qdsp6/Makefile
+++ b/sound/soc/qcom/qdsp6/Makefile
@@ -17,3 +17,6 @@ obj-$(CONFIG_SND_SOC_QDSP6_APM_DAI) += q6apm-dai.o
obj-$(CONFIG_SND_SOC_QDSP6_APM_LPASS_DAI) += q6apm-lpass-dais.o
obj-$(CONFIG_SND_SOC_QDSP6_PRM) += q6prm.o
obj-$(CONFIG_SND_SOC_QDSP6_PRM_LPASS_CLOCKS) += q6prm-clocks.o
+obj-$(CONFIG_SND_SOC_QDSP6_Q6VOICE) += q6cvp.o q6cvs.o q6mvm.o q6voice-common.o
+obj-$(CONFIG_SND_SOC_QDSP6_Q6VOICE) += q6voice.o
+obj-$(CONFIG_SND_SOC_QDSP6_Q6VOICE_DAI) += q6voice-dai.o
diff --git a/sound/soc/qcom/qdsp6/q6cvp.c b/sound/soc/qcom/qdsp6/q6cvp.c
new file mode 100644
index 00000000000..3549d3f14c9
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6cvp.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2020, Stephan Gerhold
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/soc/qcom/apr.h>
+#include "q6cvp.h"
+#include "q6voice-common.h"
+
+#define VSS_IVOCPROC_DIRECTION_RX 0
+#define VSS_IVOCPROC_DIRECTION_TX 1
+#define VSS_IVOCPROC_DIRECTION_RX_TX 2
+
+#define VSS_IVOCPROC_PORT_ID_NONE 0xFFFF
+
+#define VSS_IVOCPROC_TOPOLOGY_ID_NONE 0x00010F70
+#define VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS 0x00010F71
+#define VSS_IVOCPROC_TOPOLOGY_ID_TX_DM_FLUENCE 0x00010F72
+
+#define VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT 0x00010F77
+
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING 0x00010F7C
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING 0x00010F7D
+
+#define VSS_ICOMMON_CAL_NETWORK_ID_NONE 0x0001135E
+
+#define VSS_IVOCPROC_CMD_ENABLE 0x000100C6
+#define VSS_IVOCPROC_CMD_DISABLE 0x000110E1
+
+#define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2 0x000112BF
+
+struct vss_ivocproc_cmd_create_full_control_session_v2_cmd {
+ struct apr_hdr hdr;
+
+ /*
+ * Vocproc direction. The supported values:
+ * VSS_IVOCPROC_DIRECTION_RX
+ * VSS_IVOCPROC_DIRECTION_TX
+ * VSS_IVOCPROC_DIRECTION_RX_TX
+ */
+ u16 direction;
+
+ /*
+ * Tx device port ID to which the vocproc connects. If a port ID is
+ * not being supplied, set this to #VSS_IVOCPROC_PORT_ID_NONE.
+ */
+ u16 tx_port_id;
+
+ /*
+ * Tx path topology ID. If a topology ID is not being supplied, set
+ * this to #VSS_IVOCPROC_TOPOLOGY_ID_NONE.
+ */
+ u32 tx_topology_id;
+
+ /*
+ * Rx device port ID to which the vocproc connects. If a port ID is
+ * not being supplied, set this to #VSS_IVOCPROC_PORT_ID_NONE.
+ */
+ u16 rx_port_id;
+
+ /*
+ * Rx path topology ID. If a topology ID is not being supplied, set
+ * this to #VSS_IVOCPROC_TOPOLOGY_ID_NONE.
+ */
+ u32 rx_topology_id;
+
+ /* Voice calibration profile ID. */
+ u32 profile_id;
+
+ /*
+ * Vocproc mode. The supported values:
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING
+ */
+ u32 vocproc_mode;
+
+ /*
+ * Port ID to which the vocproc connects for receiving echo
+ * cancellation reference signal. If a port ID is not being supplied,
+ * set this to #VSS_IVOCPROC_PORT_ID_NONE. This parameter value is
+ * ignored when the vocproc_mode parameter is set to
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING.
+ */
+ u16 ec_ref_port_id;
+
+ /*
+ * Session name string used to identify a session that can be shared
+ * with passive controllers (optional).
+ */
+ char name[20];
+} __packed;
+
+struct q6voice_session *q6cvp_session_create(enum q6voice_path_type path,
+ u16 tx_port, u16 rx_port)
+{
+ struct vss_ivocproc_cmd_create_full_control_session_v2_cmd cmd;
+
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.opcode = VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2;
+
+ /* TODO: Implement calibration */
+ cmd.tx_topology_id = VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS;
+ cmd.rx_topology_id = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
+
+ cmd.direction = VSS_IVOCPROC_DIRECTION_RX_TX;
+ cmd.tx_port_id = tx_port;
+ cmd.rx_port_id = rx_port;
+ cmd.profile_id = VSS_ICOMMON_CAL_NETWORK_ID_NONE;
+ cmd.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
+ cmd.ec_ref_port_id = VSS_IVOCPROC_PORT_ID_NONE;
+
+ return q6voice_session_create(Q6VOICE_SERVICE_CVP, path, &cmd.hdr);
+}
+EXPORT_SYMBOL_GPL(q6cvp_session_create);
+
+int q6cvp_enable(struct q6voice_session *cvp, bool state)
+{
+ struct apr_pkt cmd;
+
+ cmd.hdr.pkt_size = APR_HDR_SIZE;
+ cmd.hdr.opcode = state ? VSS_IVOCPROC_CMD_ENABLE : VSS_IVOCPROC_CMD_DISABLE;
+
+ return q6voice_common_send(cvp, &cmd.hdr);
+}
+EXPORT_SYMBOL_GPL(q6cvp_enable);
+
+static int q6cvp_probe(struct apr_device *adev)
+{
+ return q6voice_common_probe(adev, Q6VOICE_SERVICE_CVP);
+}
+
+static const struct of_device_id q6cvp_device_id[] = {
+ { .compatible = "qcom,q6cvp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, q6cvp_device_id);
+
+static struct apr_driver qcom_q6cvp_driver = {
+ .probe = q6cvp_probe,
+ .remove = q6voice_common_remove,
+ .callback = q6voice_common_callback,
+ .driver = {
+ .name = "qcom-q6cvp",
+ .of_match_table = of_match_ptr(q6cvp_device_id),
+ },
+};
+
+module_apr_driver(qcom_q6cvp_driver);
+
+MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
+MODULE_DESCRIPTION("Q6 Core Voice Processor");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/qdsp6/q6cvp.h b/sound/soc/qcom/qdsp6/q6cvp.h
new file mode 100644
index 00000000000..2381a3cfe07
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6cvp.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _Q6_CVP_H
+#define _Q6_CVP_H
+
+#include "q6voice.h"
+
+struct q6voice_session;
+
+struct q6voice_session *q6cvp_session_create(enum q6voice_path_type path,
+ u16 tx_port, u16 rx_port);
+int q6cvp_enable(struct q6voice_session *cvp, bool enable);
+
+#endif /*_Q6_CVP_H */
diff --git a/sound/soc/qcom/qdsp6/q6cvs.c b/sound/soc/qcom/qdsp6/q6cvs.c
new file mode 100644
index 00000000000..440715870a0
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6cvs.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2020, Stephan Gerhold
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/soc/qcom/apr.h>
+#include "q6cvs.h"
+#include "q6voice-common.h"
+
+static int q6cvs_probe(struct apr_device *adev)
+{
+ return q6voice_common_probe(adev, Q6VOICE_SERVICE_CVS);
+}
+
+static const struct of_device_id q6cvs_device_id[] = {
+ { .compatible = "qcom,q6cvs" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, q6cvs_device_id);
+
+static struct apr_driver qcom_q6cvs_driver = {
+ .probe = q6cvs_probe,
+ .remove = q6voice_common_remove,
+ .callback = q6voice_common_callback,
+ .driver = {
+ .name = "qcom-q6cvs",
+ .of_match_table = of_match_ptr(q6cvs_device_id),
+ },
+};
+
+module_apr_driver(qcom_q6cvs_driver);
+
+MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
+MODULE_DESCRIPTION("Q6 Core Voice Stream");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/qdsp6/q6cvs.h b/sound/soc/qcom/qdsp6/q6cvs.h
new file mode 100644
index 00000000000..5c204682c76
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6cvs.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _Q6_CVS_H
+#define _Q6_CVS_H
+
+#include "q6voice.h"
+
+struct q6voice_session;
+
+#endif /*_Q6_CVS_H */
diff --git a/sound/soc/qcom/qdsp6/q6mvm.c b/sound/soc/qcom/qdsp6/q6mvm.c
new file mode 100644
index 00000000000..ac8408b3429
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6mvm.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2020, Stephan Gerhold
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/soc/qcom/apr.h>
+#include "q6mvm.h"
+#include "q6voice-common.h"
+
+#define VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION 0x000110FF
+
+struct vss_imvm_cmd_create_control_session_cmd {
+ struct apr_hdr hdr;
+
+ /* A variable-sized stream name. */
+ char name[20];
+} __packed;
+
+#define VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL 0x00011327
+
+/* This command is required to let MVM know who is in control of session. */
+struct vss_imvm_cmd_set_policy_dual_control_cmd {
+ struct apr_hdr hdr;
+
+ /* Set to TRUE to enable modem state machine control */
+ bool enable;
+} __packed;
+
+#define VSS_IMVM_CMD_ATTACH_VOCPROC 0x0001123E
+#define VSS_IMVM_CMD_DETACH_VOCPROC 0x0001123F
+
+/*
+ * Attach/detach a vocproc to the MVM.
+ * The MVM will symmetrically connect/disconnect this vocproc
+ * to/from all the streams currently attached to it.
+ */
+struct vss_imvm_cmd_attach_vocproc_cmd {
+ struct apr_hdr hdr;
+
+ /* Handle of vocproc being attached. */
+ u16 handle;
+} __packed;
+
+#define VSS_IMVM_CMD_START_VOICE 0x00011190
+#define VSS_IMVM_CMD_STOP_VOICE 0x00011192
+
+static inline const char *q6mvm_session_name(enum q6voice_path_type path)
+{
+ switch (path) {
+ case Q6VOICE_PATH_VOICE:
+ return "default modem voice";
+ case Q6VOICE_PATH_VOICEMMODE1:
+ return "11C05000";
+ default:
+ return NULL;
+ }
+}
+
+static int q6mvm_set_dual_control(struct q6voice_session *mvm)
+{
+ struct vss_imvm_cmd_set_policy_dual_control_cmd cmd;
+
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.opcode = VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL;
+
+ cmd.enable = true;
+
+ return q6voice_common_send(mvm, &cmd.hdr);
+}
+
+struct q6voice_session *q6mvm_session_create(enum q6voice_path_type path)
+{
+ struct vss_imvm_cmd_create_control_session_cmd cmd;
+ struct q6voice_session *mvm;
+ const char *session_name;
+ int ret;
+
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.opcode = VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
+
+ session_name = q6mvm_session_name(path);
+ if (session_name)
+ strscpy(cmd.name, session_name, sizeof(cmd.name));
+
+ mvm = q6voice_session_create(Q6VOICE_SERVICE_MVM, path, &cmd.hdr);
+ if (IS_ERR(mvm))
+ return mvm;
+
+ ret = q6mvm_set_dual_control(mvm);
+ if (ret) {
+ dev_err(mvm->dev, "failed to set dual control: %d\n", ret);
+ q6voice_session_release(mvm);
+ return ERR_PTR(ret);
+ }
+
+ return mvm;
+}
+EXPORT_SYMBOL_GPL(q6mvm_session_create);
+
+int q6mvm_attach(struct q6voice_session *mvm, struct q6voice_session *cvp,
+ bool state)
+{
+ struct vss_imvm_cmd_attach_vocproc_cmd cmd;
+
+ cmd.hdr.pkt_size = sizeof(cmd);
+ cmd.hdr.opcode = state ? VSS_IMVM_CMD_ATTACH_VOCPROC : VSS_IMVM_CMD_DETACH_VOCPROC;
+
+ cmd.handle = cvp->handle;
+
+ return q6voice_common_send(mvm, &cmd.hdr);
+}
+EXPORT_SYMBOL_GPL(q6mvm_attach);
+
+int q6mvm_start(struct q6voice_session *mvm, bool state)
+{
+ struct apr_pkt cmd;
+
+ cmd.hdr.pkt_size = APR_HDR_SIZE;
+ cmd.hdr.opcode = state ? VSS_IMVM_CMD_START_VOICE : VSS_IMVM_CMD_STOP_VOICE;
+
+ return q6voice_common_send(mvm, &cmd.hdr);
+}
+EXPORT_SYMBOL_GPL(q6mvm_start);
+
+static int q6mvm_probe(struct apr_device *adev)
+{
+ int ret;
+
+ ret = q6voice_common_probe(adev, Q6VOICE_SERVICE_MVM);
+ if (ret)
+ return ret;
+
+ return of_platform_populate(adev->dev.of_node, NULL, NULL, &adev->dev);
+}
+
+static void q6mvm_remove(struct apr_device *adev)
+{
+ of_platform_depopulate(&adev->dev);
+ return q6voice_common_remove(adev);
+}
+
+static const struct of_device_id q6mvm_device_id[] = {
+ { .compatible = "qcom,q6mvm" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, q6mvm_device_id);
+
+static struct apr_driver qcom_q6mvm_driver = {
+ .probe = q6mvm_probe,
+ .remove = q6mvm_remove,
+ .callback = q6voice_common_callback,
+ .driver = {
+ .name = "qcom-q6mvm",
+ .of_match_table = of_match_ptr(q6mvm_device_id),
+ },
+};
+
+module_apr_driver(qcom_q6mvm_driver);
+MODULE_DESCRIPTION("Q6 Multimode Voice Manager");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/qdsp6/q6mvm.h b/sound/soc/qcom/qdsp6/q6mvm.h
new file mode 100644
index 00000000000..51279eddb89
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6mvm.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _Q6_MVM_H
+#define _Q6_MVM_H
+
+#include "q6voice.h"
+
+struct q6voice_session;
+
+struct q6voice_session *q6mvm_session_create(enum q6voice_path_type path);
+
+int q6mvm_attach(struct q6voice_session *mvm, struct q6voice_session *cvp,
+ bool state);
+int q6mvm_start(struct q6voice_session *mvm, bool state);
+
+#endif /*_Q6_MVM_H */
diff --git a/sound/soc/qcom/qdsp6/q6voice-common.c b/sound/soc/qcom/qdsp6/q6voice-common.c
new file mode 100644
index 00000000000..f821d619e16
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6voice-common.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2020, Stephan Gerhold
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/soc/qcom/apr.h>
+#include "q6voice-common.h"
+
+#define APRV2_IBASIC_CMD_DESTROY_SESSION 0x0001003C
+
+#define TIMEOUT_MS 300
+
+struct q6voice_service {
+ struct apr_device *adev;
+ enum q6voice_service_type type;
+
+ /* Protect sessions array */
+ spinlock_t lock;
+ struct q6voice_session *sessions[Q6VOICE_PATH_COUNT];
+};
+
+/* Protect q6voice_services */
+static DEFINE_SPINLOCK(q6voice_services_lock);
+static struct q6voice_service *q6voice_services[Q6VOICE_SERVICE_COUNT] = {0};
+
+int q6voice_common_probe(struct apr_device *adev, enum q6voice_service_type type)
+{
+ struct device *dev = &adev->dev;
+ struct q6voice_service *svc, *current_svc;
+ unsigned long flags;
+
+ if (type >= Q6VOICE_SERVICE_COUNT)
+ return -EINVAL;
+
+ svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
+ if (!svc)
+ return -ENOMEM;
+
+ svc->adev = adev;
+ svc->type = type;
+ spin_lock_init(&svc->lock);
+
+ dev_set_drvdata(dev, svc);
+
+ spin_lock_irqsave(&q6voice_services_lock, flags);
+ current_svc = q6voice_services[type];
+ if (!current_svc)
+ q6voice_services[type] = svc;
+ spin_unlock_irqrestore(&q6voice_services_lock, flags);
+
+ return current_svc ? -EEXIST : 0;
+}
+EXPORT_SYMBOL_GPL(q6voice_common_probe);
+
+void q6voice_common_remove(struct apr_device *adev)
+{
+ struct q6voice_service *svc = dev_get_drvdata(&adev->dev);
+ enum q6voice_service_type type = svc->type;
+ unsigned long flags;
+
+ spin_lock_irqsave(&q6voice_services_lock, flags);
+ if (q6voice_services[type] == svc)
+ q6voice_services[type] = NULL;
+ spin_unlock_irqrestore(&q6voice_services_lock, flags);
+
+ /* TODO: Should probably free up sessions here??? */
+}
+EXPORT_SYMBOL_GPL(q6voice_common_remove);
+
+static void q6voice_session_free(struct kref *ref)
+{
+ struct q6voice_session *s = container_of(ref, struct q6voice_session,
+ refcount);
+
+ kfree(s);
+}
+
+static int q6voice_session_destroy(struct q6voice_session *s)
+{
+ struct apr_pkt cmd;
+
+ cmd.hdr.pkt_size = APR_HDR_SIZE;
+ cmd.hdr.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION;
+
+ return q6voice_common_send(s, &cmd.hdr);
+}
+
+void q6voice_session_release(struct q6voice_session *s)
+{
+ struct q6voice_service *svc = s->svc;
+ unsigned long flags;
+
+ if (s->handle)
+ q6voice_session_destroy(s);
+
+ spin_lock_irqsave(&svc->lock, flags);
+ if (svc->sessions[s->port] == s)
+ svc->sessions[s->port] = NULL;
+ spin_unlock_irqrestore(&svc->lock, flags);
+
+ kref_put(&s->refcount, q6voice_session_free);
+}
+EXPORT_SYMBOL_GPL(q6voice_session_release);
+
+struct q6voice_session *
+q6voice_session_create(enum q6voice_service_type type,
+ enum q6voice_path_type path, struct apr_hdr *hdr)
+{
+ struct q6voice_service *svc;
+ struct q6voice_session *s;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&q6voice_services_lock, flags);
+ svc = q6voice_services[type];
+ spin_unlock_irqrestore(&q6voice_services_lock, flags);
+ if (!svc)
+ return ERR_PTR(-ENODEV);
+
+ s = kzalloc(sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return ERR_PTR(-ENOMEM);
+
+ s->dev = &svc->adev->dev;
+ s->svc = svc;
+ s->port = path;
+
+ kref_init(&s->refcount);
+ spin_lock_init(&s->lock);
+ init_waitqueue_head(&s->wait);
+
+ spin_lock_irqsave(&svc->lock, flags);
+ if (svc->sessions[path]) {
+ spin_unlock_irqrestore(&svc->lock, flags);
+ kfree(s);
+ return ERR_PTR(-EBUSY);
+ }
+ svc->sessions[path] = s;
+ spin_unlock_irqrestore(&svc->lock, flags);
+
+ dev_dbg(s->dev, "create session\n");
+
+ ret = q6voice_common_send(s, hdr);
+ if (ret)
+ goto err;
+
+ if (!s->handle) {
+ dev_warn(s->dev, "failed to receive handle\n");
+ ret = -EIO;
+ goto err;
+ }
+
+ dev_dbg(s->dev, "handle: %d\n", s->handle);
+
+ return s;
+
+err:
+ q6voice_session_release(s);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(q6voice_session_create);
+
+static void q6voice_session_callback(struct q6voice_session *s,
+ struct apr_resp_pkt *data)
+{
+ struct aprv2_ibasic_rsp_result_t *result = data->payload;
+ unsigned long flags;
+
+ if (data->hdr.opcode != APR_BASIC_RSP_RESULT)
+ return; /* Not handled here */
+
+ dev_dbg(s->dev, "basic result: opcode %#x, status: %#x\n",
+ result->opcode, result->status);
+
+ spin_lock_irqsave(&s->lock, flags);
+ if (result->opcode != s->expected_opcode) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ dev_warn(s->dev, "unexpected reply for opcode %#x (status: %#x)\n",
+ result->opcode, result->status);
+ return;
+ }
+
+ if (!s->handle) {
+ s->handle = data->hdr.src_port;
+ } else if (s->handle != data->hdr.src_port) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ dev_warn(s->dev, "unexpected reply for session %#x (!= %#x)\n",
+ data->hdr.src_port, s->handle);
+ return;
+ }
+
+ s->result = result->status;
+ s->expected_opcode = 0;
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ wake_up(&s->wait);
+}
+
+int q6voice_common_callback(struct apr_device *adev, struct apr_resp_pkt *data)
+{
+ struct device *dev = &adev->dev;
+ struct q6voice_service *v = dev_get_drvdata(dev);
+ struct q6voice_session *s;
+ unsigned long flags;
+
+ dev_dbg(dev, "callback: %#x\n", data->hdr.opcode);
+
+ if (data->hdr.dest_port >= Q6VOICE_PATH_COUNT) {
+ dev_warn(dev, "callback() called for unhandled/invalid path: %d\n",
+ data->hdr.dest_port);
+ return 0;
+ }
+
+ spin_lock_irqsave(&v->lock, flags);
+ s = v->sessions[data->hdr.dest_port];
+ if (s)
+ kref_get(&s->refcount);
+ spin_unlock_irqrestore(&v->lock, flags);
+
+ if (s) {
+ q6voice_session_callback(s, data);
+ kref_put(&s->refcount, q6voice_session_free);
+ } else {
+ dev_warn(dev, "callback() called for inactive path: %d\n",
+ data->hdr.dest_port);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(q6voice_common_callback);
+
+int q6voice_common_send(struct q6voice_session *s, struct apr_hdr *hdr)
+{
+ unsigned long flags;
+ int ret;
+
+ hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ hdr->src_port = s->port;
+ hdr->dest_port = s->handle;
+ hdr->token = 0;
+
+ spin_lock_irqsave(&s->lock, flags);
+ s->expected_opcode = hdr->opcode;
+ s->result = 0;
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ ret = apr_send_pkt(s->svc->adev, (struct apr_pkt *)hdr);
+ if (ret < 0)
+ return ret;
+
+ ret = wait_event_timeout(s->wait, (s->expected_opcode == 0),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ s->expected_opcode = 0;
+ return -ETIMEDOUT;
+ }
+
+ if (s->result > 0) {
+ dev_err(s->dev, "command %#x failed with error %d\n",
+ hdr->opcode, s->result);
+ return -EIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(q6voice_common_send);
+
+MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
+MODULE_DESCRIPTION("Q6Voice common session management");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/qdsp6/q6voice-common.h b/sound/soc/qcom/qdsp6/q6voice-common.h
new file mode 100644
index 00000000000..6fb3c9560b2
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6voice-common.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _Q6_VOICE_COMMON_H
+#define _Q6_VOICE_COMMON_H
+
+#include <linux/soc/qcom/apr.h>
+#include "q6voice.h"
+
+enum q6voice_service_type {
+ Q6VOICE_SERVICE_MVM,
+ Q6VOICE_SERVICE_CVP,
+ Q6VOICE_SERVICE_CVS,
+ Q6VOICE_SERVICE_COUNT
+};
+
+struct q6voice_service;
+
+struct q6voice_session {
+ struct device *dev;
+ struct q6voice_service *svc;
+ struct kref refcount;
+
+ u16 port;
+ u16 handle;
+
+ wait_queue_head_t wait;
+
+ /* Protect expected_opcode and result */
+ spinlock_t lock;
+ u32 expected_opcode;
+ u32 result;
+};
+
+int q6voice_common_probe(struct apr_device *adev, enum q6voice_service_type type);
+void q6voice_common_remove(struct apr_device *adev);
+
+int q6voice_common_callback(struct apr_device *adev, struct apr_resp_pkt *data);
+int q6voice_common_send(struct q6voice_session *s, struct apr_hdr *hdr);
+
+struct q6voice_session *q6voice_session_create(enum q6voice_service_type type,
+ enum q6voice_path_type path,
+ struct apr_hdr *hdr);
+void q6voice_session_release(struct q6voice_session *s);
+
+#endif /*_Q6_VOICE_COMMON_H */
diff --git a/sound/soc/qcom/qdsp6/q6voice-dai.c b/sound/soc/qcom/qdsp6/q6voice-dai.c
new file mode 100644
index 00000000000..bf4906ec256
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6voice-dai.c
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2020, Stephan Gerhold
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
+#include "q6afe.h"
+#include "q6voice.h"
+
+#define DRV_NAME "q6voice-dai"
+
+static int q6voice_dai_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct q6voice *v = snd_soc_dai_get_drvdata(dai);
+ struct device *dev = dai->component->dev;
+ int ret;
+
+ switch (dai->driver->id) {
+ case CS_VOICE:
+ ret = q6voice_start(v, Q6VOICE_PATH_VOICE, substream->stream);
+ break;
+ case VOICEMMODE1:
+ ret = q6voice_start(v, Q6VOICE_PATH_VOICEMMODE1, substream->stream);
+ break;
+ default:
+ dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static void q6voice_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct q6voice *v = snd_soc_dai_get_drvdata(dai);
+ struct device *dev = dai->component->dev;
+
+ switch (dai->driver->id) {
+ case CS_VOICE:
+ q6voice_stop(v, Q6VOICE_PATH_VOICE, substream->stream);
+ break;
+ case VOICEMMODE1:
+ q6voice_stop(v, Q6VOICE_PATH_VOICEMMODE1, substream->stream);
+ break;
+ default:
+ dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
+ }
+}
+
+static struct snd_soc_dai_ops q6voice_dai_ops = {
+ .startup = q6voice_dai_startup,
+ .shutdown = q6voice_dai_shutdown,
+};
+
+static struct snd_soc_dai_driver q6voice_dais[] = {
+ {
+ .id = CS_VOICE,
+ .name = "CS-VOICE",
+ /* The constraints here are not really meaningful... */
+ .playback = {
+ .stream_name = "CS-VOICE Playback",
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 1,
+ .channels_max = 1,
+ },
+ .capture = {
+ .stream_name = "CS-VOICE Capture",
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 1,
+ .channels_max = 1,
+ },
+ .ops = &q6voice_dai_ops,
+ },
+ {
+ .id = VOICEMMODE1,
+ .name = "VoiceMMode1",
+ /* The constraints here are not really meaningful... */
+ .playback = {
+ .stream_name = "VoiceMMode1 Playback",
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 1,
+ .channels_max = 1,
+ },
+ .capture = {
+ .stream_name = "VoiceMMode1 Capture",
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 1,
+ .channels_max = 1,
+ },
+ .ops = &q6voice_dai_ops,
+ },
+};
+
+/* FIXME: Use codec2codec instead */
+static struct snd_pcm_hardware q6voice_dai_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED,
+ .buffer_bytes_max = 4096 * 2,
+ .period_bytes_min = 2048,
+ .period_bytes_max = 4096,
+ .periods_min = 2,
+ .periods_max = 4,
+ .fifo_size = 0,
+};
+
+static int q6voice_dai_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ substream->runtime->hw = q6voice_dai_hardware;
+ return 0;
+}
+
+static int q6voice_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct q6voice *v = snd_soc_component_get_drvdata(c);
+
+ switch (mc->reg) {
+ case PRIMARY_MI2S_TX:
+ case SECONDARY_MI2S_TX:
+ case TERTIARY_MI2S_TX:
+ case QUATERNARY_MI2S_TX:
+ case QUINARY_MI2S_TX:
+ case SLIMBUS_0_TX:
+ case SLIMBUS_1_TX:
+ case SLIMBUS_2_TX:
+ case SLIMBUS_3_TX:
+ case SLIMBUS_4_TX:
+ case SLIMBUS_5_TX:
+ case SLIMBUS_6_TX:
+ if (q6voice_get_port(v, Q6VOICE_PORT_TX) == mc->reg)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ case PRIMARY_MI2S_RX:
+ case SECONDARY_MI2S_RX:
+ case TERTIARY_MI2S_RX:
+ case QUATERNARY_MI2S_RX:
+ case QUINARY_MI2S_RX:
+ case SLIMBUS_0_RX:
+ case SLIMBUS_1_RX:
+ case SLIMBUS_2_RX:
+ case SLIMBUS_3_RX:
+ case SLIMBUS_4_RX:
+ case SLIMBUS_5_RX:
+ case SLIMBUS_6_RX:
+ if (q6voice_get_port(v, Q6VOICE_PORT_RX) == mc->reg)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ default:
+ dev_err(c->dev, "%s: invalid mixer request: %d\n", __func__, mc->reg);
+ }
+
+ return 0;
+}
+
+static int q6voice_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct q6voice *v = snd_soc_component_get_drvdata(c);
+ struct snd_soc_dapm_update *update = NULL;
+
+ switch (mc->reg) {
+ case PRIMARY_MI2S_TX:
+ case SECONDARY_MI2S_TX:
+ case TERTIARY_MI2S_TX:
+ case QUATERNARY_MI2S_TX:
+ case QUINARY_MI2S_TX:
+ case SLIMBUS_0_TX:
+ case SLIMBUS_1_TX:
+ case SLIMBUS_2_TX:
+ case SLIMBUS_3_TX:
+ case SLIMBUS_4_TX:
+ case SLIMBUS_5_TX:
+ case SLIMBUS_6_TX:
+ q6voice_set_port(v, Q6VOICE_PORT_TX, mc->reg);
+ break;
+ case PRIMARY_MI2S_RX:
+ case SECONDARY_MI2S_RX:
+ case TERTIARY_MI2S_RX:
+ case QUATERNARY_MI2S_RX:
+ case QUINARY_MI2S_RX:
+ case SLIMBUS_0_RX:
+ case SLIMBUS_1_RX:
+ case SLIMBUS_2_RX:
+ case SLIMBUS_3_RX:
+ case SLIMBUS_4_RX:
+ case SLIMBUS_5_RX:
+ case SLIMBUS_6_RX:
+ q6voice_set_port(v, Q6VOICE_PORT_RX, mc->reg);
+ break;
+ default:
+ dev_err(c->dev, "%s: invalid mixer setting: %d\n", __func__, mc->reg);
+ }
+
+ if (ucontrol->value.integer.value[0])
+ snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update);
+ else
+ snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update);
+
+ return 1;
+}
+
+static const struct snd_kcontrol_new cs_voice_tx_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("QUIN_MI2S_TX", QUINARY_MI2S_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_0_TX", SLIMBUS_0_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_1_TX", SLIMBUS_1_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_2_TX", SLIMBUS_2_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_3_TX", SLIMBUS_3_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_4_TX", SLIMBUS_4_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_5_TX", SLIMBUS_5_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_6_TX", SLIMBUS_6_TX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+};
+
+static const struct snd_kcontrol_new voicemmode1_tx_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_MI2S_TX", PRIMARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SEC_MI2S_TX", SECONDARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("TERT_MI2S_TX", TERTIARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("QUAT_MI2S_TX", QUATERNARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("QUIN_MI2S_TX", QUINARY_MI2S_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_0_TX", SLIMBUS_0_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_1_TX", SLIMBUS_1_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_2_TX", SLIMBUS_2_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_3_TX", SLIMBUS_3_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_4_TX", SLIMBUS_4_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_5_TX", SLIMBUS_5_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("SLIMBUS_6_TX", SLIMBUS_6_TX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+};
+
+static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", PRIMARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", PRIMARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SECONDARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SECONDARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", TERTIARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", TERTIARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new quaternary_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", QUATERNARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", QUATERNARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new quinary_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", QUINARY_MI2S_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", QUINARY_MI2S_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_0_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_0_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_0_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_1_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_1_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_1_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_2_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_2_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_2_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_3_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_3_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_3_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_4_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_4_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_4_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_5_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_5_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_5_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_kcontrol_new slimbus_6_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("CS-Voice", SLIMBUS_6_RX, CS_VOICE, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", SLIMBUS_6_RX, VOICEMMODE1, 1, 0,
+ q6voice_get_mixer, q6voice_put_mixer)
+};
+
+static const struct snd_soc_dapm_widget q6voice_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VOICEMMODE1_DL", "VoiceMMode1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOICEMMODE1_UL", "VoiceMMode1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_MIXER("CS-Voice Capture Mixer", SND_SOC_NOPM, 0, 0,
+ cs_voice_tx_mixer_controls,
+ ARRAY_SIZE(cs_voice_tx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("VoiceMMode1 Capture Mixer", SND_SOC_NOPM, 0, 0,
+ voicemmode1_tx_mixer_controls,
+ ARRAY_SIZE(voicemmode1_tx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("PRI_MI2S_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ primary_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(primary_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_MI2S_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ secondary_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("TERT_MI2S_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ tertiary_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(tertiary_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ quaternary_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(quaternary_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("QUIN_MI2S_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ quinary_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(quinary_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_0_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_0_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_1_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_1_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_1_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_2_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_2_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_2_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_3_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_3_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_3_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_4_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_4_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_4_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_5_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_5_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_5_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SLIMBUS_6_RX Voice Mixer", SND_SOC_NOPM, 0, 0,
+ slimbus_6_rx_mixer_controls,
+ ARRAY_SIZE(slimbus_6_rx_mixer_controls)),
+};
+
+static const struct snd_soc_dapm_route q6voice_dapm_routes[] = {
+ { "CS-Voice Capture Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX" },
+ { "CS-Voice Capture Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX" },
+ { "CS-Voice Capture Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX" },
+ { "CS-Voice Capture Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX" },
+ { "CS-Voice Capture Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_2_TX", "SLIMBUS_2_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX" },
+ { "CS-Voice Capture Mixer", "SLIMBUS_6_TX", "SLIMBUS_6_TX" },
+ { "CS-VOICE_UL1", NULL, "CS-Voice Capture Mixer" },
+
+ { "PRI_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SEC_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "TERT_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "QUAT_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "QUIN_MI2S_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_0_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_1_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_2_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_3_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_4_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_5_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+ { "SLIMBUS_6_RX Voice Mixer", "CS-Voice", "CS-VOICE_DL1" },
+
+ { "VoiceMMode1 Capture Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_2_TX", "SLIMBUS_2_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX" },
+ { "VoiceMMode1 Capture Mixer", "SLIMBUS_6_TX", "SLIMBUS_6_TX" },
+ { "VOICEMMODE1_UL", NULL, "VoiceMMode1 Capture Mixer" },
+
+ { "PRI_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SEC_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "TERT_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "QUAT_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "QUIN_MI2S_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_0_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_1_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_2_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_3_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_4_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_5_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+ { "SLIMBUS_6_RX Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL" },
+
+ { "PRI_MI2S_RX", NULL, "PRI_MI2S_RX Voice Mixer" },
+ { "SEC_MI2S_RX", NULL, "SEC_MI2S_RX Voice Mixer" },
+ { "TERT_MI2S_RX", NULL, "TERT_MI2S_RX Voice Mixer" },
+ { "QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Voice Mixer" },
+ { "QUIN_MI2S_RX", NULL, "QUIN_MI2S_RX Voice Mixer" },
+ { "SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Voice Mixer" },
+ { "SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Voice Mixer" },
+ { "SLIMBUS_2_RX", NULL, "SLIMBUS_2_RX Voice Mixer" },
+ { "SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX Voice Mixer" },
+ { "SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Voice Mixer" },
+ { "SLIMBUS_5_RX", NULL, "SLIMBUS_5_RX Voice Mixer" },
+ { "SLIMBUS_6_RX", NULL, "SLIMBUS_6_RX Voice Mixer" },
+};
+
+static unsigned int q6voice_reg_read(struct snd_soc_component *component,
+ unsigned int reg)
+{
+ /* default value */
+ return 0;
+}
+
+static int q6voice_reg_write(struct snd_soc_component *component,
+ unsigned int reg, unsigned int val)
+{
+ /* dummy */
+ return 0;
+}
+
+static const struct snd_soc_component_driver q6voice_dai_component = {
+ .name = DRV_NAME,
+ .open = q6voice_dai_open,
+
+ .dapm_widgets = q6voice_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(q6voice_dapm_widgets),
+ .dapm_routes = q6voice_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(q6voice_dapm_routes),
+ .read = q6voice_reg_read,
+ .write = q6voice_reg_write,
+
+ /* Needs to probe after q6afe */
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+};
+
+static int q6voice_dai_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct q6voice *v;
+
+ v = q6voice_create(dev);
+ if (IS_ERR(v))
+ return PTR_ERR(v);
+
+ dev_set_drvdata(dev, v);
+
+ return devm_snd_soc_register_component(dev, &q6voice_dai_component,
+ q6voice_dais,
+ ARRAY_SIZE(q6voice_dais));
+}
+
+static const struct of_device_id q6voice_dai_device_id[] = {
+ { .compatible = "qcom,q6voice-dais" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, q6voice_dai_device_id);
+
+static struct platform_driver q6voice_dai_platform_driver = {
+ .driver = {
+ .name = "q6voice-dai",
+ .of_match_table = of_match_ptr(q6voice_dai_device_id),
+ },
+ .probe = q6voice_dai_probe,
+};
+module_platform_driver(q6voice_dai_platform_driver);
+
+MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
+MODULE_DESCRIPTION("Q6Voice DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/qdsp6/q6voice.c b/sound/soc/qcom/qdsp6/q6voice.c
new file mode 100644
index 00000000000..4666a068ac2
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6voice.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+// Copyright (c) 2020, Stephan Gerhold
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "q6afe.h"
+#include "q6cvp.h"
+#include "q6cvs.h"
+#include "q6mvm.h"
+#include "q6voice-common.h"
+
+struct q6voice_path_runtime {
+ struct q6voice_session *sessions[Q6VOICE_SERVICE_COUNT];
+ unsigned int started;
+};
+
+struct q6voice_path {
+ struct q6voice *v;
+
+ enum q6voice_path_type type;
+ /* Serialize access to voice path session */
+ struct mutex lock;
+ struct q6voice_path_runtime *runtime;
+};
+
+struct q6voice {
+ struct device *dev;
+ struct q6voice_path paths[Q6VOICE_PATH_COUNT];
+ u16 port_rx;
+ u16 port_tx;
+};
+
+static int q6voice_path_start(struct q6voice_path *p)
+{
+ struct device *dev = p->v->dev;
+ struct q6voice_session *mvm, *cvp;
+ int ret;
+
+ dev_dbg(dev, "start path %d\n", p->type);
+
+ mvm = p->runtime->sessions[Q6VOICE_SERVICE_MVM];
+ if (!mvm) {
+ mvm = q6mvm_session_create(p->type);
+ if (IS_ERR(mvm))
+ return PTR_ERR(mvm);
+ p->runtime->sessions[Q6VOICE_SERVICE_MVM] = mvm;
+ }
+
+ cvp = p->runtime->sessions[Q6VOICE_SERVICE_CVP];
+ if (!cvp) {
+ cvp = q6cvp_session_create(p->type,
+ q6afe_get_port_id(p->v->port_tx),
+ q6afe_get_port_id(p->v->port_rx));
+ if (IS_ERR(cvp))
+ return PTR_ERR(cvp);
+ p->runtime->sessions[Q6VOICE_SERVICE_CVP] = cvp;
+ }
+
+ ret = q6cvp_enable(cvp, true);
+ if (ret) {
+ dev_err(dev, "failed to enable cvp: %d\n", ret);
+ goto cvp_err;
+ }
+
+ ret = q6mvm_attach(mvm, cvp, true);
+ if (ret) {
+ dev_err(dev, "failed to attach cvp to mvm: %d\n", ret);
+ goto attach_err;
+ }
+
+ ret = q6mvm_start(mvm, true);
+ if (ret) {
+ dev_err(dev, "failed to start voice: %d\n", ret);
+ goto start_err;
+ }
+
+ return ret;
+
+start_err:
+ q6mvm_start(mvm, false);
+attach_err:
+ q6mvm_attach(mvm, cvp, false);
+cvp_err:
+ q6cvp_enable(cvp, false);
+ return ret;
+}
+
+int q6voice_start(struct q6voice *v, enum q6voice_path_type path, bool capture)
+{
+ struct q6voice_path *p = &v->paths[path];
+ int ret = 0;
+
+ mutex_lock(&p->lock);
+ if (!p->runtime) {
+ p->runtime = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p->runtime) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (p->runtime->started & BIT(capture)) {
+ ret = -EALREADY;
+ goto out;
+ }
+
+ p->runtime->started |= BIT(capture);
+
+ /* FIXME: For now we only start if both RX/TX are active */
+ if (p->runtime->started != 3)
+ goto out;
+
+ ret = q6voice_path_start(p);
+ if (ret) {
+ p->runtime->started &= ~BIT(capture);
+ dev_err(v->dev, "failed to start path %d: %d\n", path, ret);
+ goto out;
+ }
+
+out:
+ mutex_unlock(&p->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(q6voice_start);
+
+static void q6voice_path_stop(struct q6voice_path *p)
+{
+ struct device *dev = p->v->dev;
+ struct q6voice_session *mvm = p->runtime->sessions[Q6VOICE_SERVICE_MVM];
+ struct q6voice_session *cvp = p->runtime->sessions[Q6VOICE_SERVICE_CVP];
+ int ret;
+
+ dev_dbg(dev, "stop path %d\n", p->type);
+
+ ret = q6mvm_start(mvm, false);
+ if (ret)
+ dev_err(dev, "failed to stop voice: %d\n", ret);
+
+ ret = q6mvm_attach(mvm, cvp, false);
+ if (ret)
+ dev_err(dev, "failed to detach cvp from mvm: %d\n", ret);
+
+ ret = q6cvp_enable(cvp, false);
+ if (ret)
+ dev_err(dev, "failed to disable cvp: %d\n", ret);
+}
+
+static void q6voice_path_destroy(struct q6voice_path *p)
+{
+ struct q6voice_path_runtime *runtime = p->runtime;
+ enum q6voice_service_type svc;
+
+ for (svc = 0; svc < Q6VOICE_SERVICE_COUNT; ++svc) {
+ if (runtime->sessions[svc])
+ q6voice_session_release(runtime->sessions[svc]);
+ }
+
+ p->runtime = NULL;
+ kfree(runtime);
+}
+
+int q6voice_stop(struct q6voice *v, enum q6voice_path_type path, bool capture)
+{
+ struct q6voice_path *p = &v->paths[path];
+ int ret = 0;
+
+ mutex_lock(&p->lock);
+ if (!p->runtime || !(p->runtime->started & BIT(capture)))
+ goto out;
+
+ if (p->runtime->started == 3)
+ q6voice_path_stop(p);
+
+ p->runtime->started &= ~BIT(capture);
+
+ if (p->runtime->started == 0)
+ q6voice_path_destroy(p);
+
+out:
+ mutex_unlock(&p->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(q6voice_stop);
+
+static void q6voice_free(void *data)
+{
+ struct q6voice *v = data;
+ enum q6voice_path_type path;
+
+ for (path = 0; path < Q6VOICE_PATH_COUNT; ++path) {
+ struct q6voice_path *p = &v->paths[path];
+
+ mutex_lock(&p->lock);
+ if (p->runtime) {
+ dev_warn(v->dev,
+ "q6voice_remove() called while path %d is active\n",
+ path);
+
+ if (p->runtime->started == 3)
+ q6voice_path_stop(p);
+ q6voice_path_destroy(p);
+ }
+ mutex_unlock(&p->lock);
+ mutex_destroy(&p->lock);
+ }
+}
+
+struct q6voice *q6voice_create(struct device *dev)
+{
+ struct q6voice *v;
+ enum q6voice_path_type path;
+ int ret;
+
+ v = devm_kzalloc(dev, sizeof(*v), GFP_KERNEL);
+ if (!v)
+ return ERR_PTR(-ENOMEM);
+
+ v->dev = dev;
+
+ for (path = 0; path < Q6VOICE_PATH_COUNT; ++path) {
+ struct q6voice_path *p = &v->paths[path];
+
+ p->v = v;
+ p->type = path;
+ mutex_init(&p->lock);
+ }
+
+ ret = devm_add_action(dev, q6voice_free, v);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return v;
+}
+EXPORT_SYMBOL_GPL(q6voice_create);
+
+unsigned int q6voice_get_port(struct q6voice *v, enum q6voice_port_type type)
+{
+ switch (type) {
+ case Q6VOICE_PORT_RX:
+ return v->port_rx;
+ case Q6VOICE_PORT_TX:
+ return v->port_tx;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(q6voice_get_port);
+
+void q6voice_set_port(struct q6voice *v, enum q6voice_port_type type, int index)
+{
+ switch (type) {
+ case Q6VOICE_PORT_RX:
+ v->port_rx = index;
+ break;
+ case Q6VOICE_PORT_TX:
+ v->port_tx = index;
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(q6voice_set_port);
+
+MODULE_AUTHOR("Stephan Gerhold <stephan@gerhold.net>");
+MODULE_DESCRIPTION("Q6Voice driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/qcom/qdsp6/q6voice.h b/sound/soc/qcom/qdsp6/q6voice.h
new file mode 100644
index 00000000000..44274bba474
--- /dev/null
+++ b/sound/soc/qcom/qdsp6/q6voice.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _Q6_VOICE_H
+#define _Q6_VOICE_H
+
+enum q6voice_path_type {
+ Q6VOICE_PATH_VOICE= 0,
+ Q6VOICE_PATH_VOIP,
+ Q6VOICE_PATH_VOLTE,
+ Q6VOICE_PATH_VOICE2,
+ Q6VOICE_PATH_QCHAT,
+ Q6VOICE_PATH_VOWLAN,
+ Q6VOICE_PATH_VOICEMMODE1,
+ Q6VOICE_PATH_VOICEMMODE2,
+ Q6VOICE_PATH_COUNT
+};
+
+enum q6voice_port_type {
+ Q6VOICE_PORT_RX = 0,
+ Q6VOICE_PORT_TX,
+};
+
+struct q6voice;
+
+struct q6voice *q6voice_create(struct device *dev);
+int q6voice_start(struct q6voice *v, enum q6voice_path_type path, bool capture);
+int q6voice_stop(struct q6voice *v, enum q6voice_path_type path, bool capture);
+
+unsigned int q6voice_get_port(struct q6voice *v, enum q6voice_port_type port);
+void q6voice_set_port(struct q6voice *v, enum q6voice_port_type port, int index);
+
+#endif /*_Q6_VOICE_H */
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 75701546b6e..d9494ab41a9 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -366,10 +366,12 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;
case QUATERNARY_MI2S_RX:
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
snd_soc_dai_set_sysclk(cpu_dai,
Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
snd_soc_dai_set_fmt(cpu_dai, fmt);
+ snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
break;