dotfiles/system/hardware/oneplus-enchilada/linux_6_9.patch
2024-06-14 01:25:15 +07:00

88582 lines
3.9 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/lg,sw43408.yaml b/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
new file mode 100644
index 00000000000..1e08648f5bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/lg,sw43408.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LG SW43408 1080x2160 DSI panel
+
+maintainers:
+ - Caleb Connolly <caleb.connolly@linaro.org>
+
+description:
+ This panel is used on the Pixel 3, it is a 60hz OLED panel which
+ required DSC (Display Stream Compression) and has rounded corners.
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: lg,sw43408
+
+ reg: true
+ port: true
+ vddi-supply: true
+ vpnl-supply: true
+ reset-gpios: true
+
+required:
+ - compatible
+ - vddi-supply
+ - vpnl-supply
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "lg,sw43408";
+ reg = <0>;
+
+ vddi-supply = <&vreg_l14a_1p88>;
+ vpnl-supply = <&vreg_l28a_3p0>;
+
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
+
+ port {
+ endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
index f9160d7bac3..5605608cd2f 100644
--- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml
@@ -79,8 +79,12 @@ allOf:
then:
properties:
power-supply: false
+ vci-supply: true
+ poc-supply: true
required:
- vddio-supply
+ - vci-supply
+ - poc-supply
else:
properties:
vddio-supply: false
diff --git a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
index 77239906751..025c346811a 100644
--- a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
+++ b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
@@ -18,7 +18,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 9b3ef4bc373..bc6b67d63c2 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
@@ -139,6 +139,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 28e20975c26..3aaf0eb1b01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6752,6 +6752,14 @@ S: Maintained
F: Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
F: drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
+DRM DRIVER FOR LG SW43408 PANELS
+M: Sumit Semwal <sumit.semwal@linaro.org>
+M: Caleb Connolly <caleb.connolly@linaro.org>
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
+F: drivers/gpu/drm/panel/panel-lg-sw43408.c
+
DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
S: Supported
@@ -6931,6 +6939,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/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 7d40ec5e7d2..e375445d249 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -190,6 +190,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-blueline.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyln.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb
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/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-google-blueline.dts b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
new file mode 100644
index 00000000000..2a4bfd354fa
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
@@ -0,0 +1,689 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "sdm845.dtsi"
+#include "pm8998.dtsi"
+#include "pmi8998.dtsi"
+
+/delete-node/ &mpss_region;
+/delete-node/ &venus_mem;
+/delete-node/ &cdsp_mem;
+/delete-node/ &mba_region;
+/delete-node/ &slpi_mem;
+/delete-node/ &spss_mem;
+/delete-node/ &rmtfs_mem;
+
+/ {
+ model = "Google Pixel 3";
+ compatible = "google,blueline", "qcom,sdm845";
+ qcom,board-id = <0x00021505 0>;
+ qcom,msm-id = <321 0x20001>;
+
+ aliases {
+ serial0 = &uart9;
+ serial1 = &uart6;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ volume-keys {
+ compatible = "gpio-keys";
+ label = "Volume keys";
+ autorepeat;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&volume_up_gpio>;
+
+ vol-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pm8998_gpios 6 GPIO_ACTIVE_LOW>;
+ debounce-interval = <15>;
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ mpss_region: memory@8e000000 {
+ reg = <0 0x8e000000 0 0x9800000>;
+ no-map;
+ };
+
+ venus_mem: venus@97800000 {
+ reg = <0 0x97800000 0 0x500000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp-mem@97D00000 {
+ reg = <0 0x97D00000 0 0x800000>;
+ no-map;
+ };
+
+ mba_region: mba@98500000 {
+ reg = <0 0x98500000 0 0x200000>;
+ no-map;
+ };
+
+ slpi_mem: slpi@98700000 {
+ reg = <0 0x98700000 0 0x1400000>;
+ no-map;
+ };
+
+ spss_mem: spss@99B00000 {
+ reg = <0 0x99B00000 0 0x100000>;
+ no-map;
+ };
+
+ /* rmtfs lower guard */
+ memory@f2700000 {
+ reg = <0 0xf2700000 0 0x1000>;
+ no-map;
+ };
+
+ rmtfs_mem: memory@f2701000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0 0xf2701000 0 0x200000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
+ /* rmtfs upper guard */
+ memory@f2901000 {
+ reg = <0 0xf2901000 0 0x1000>;
+ no-map;
+ };
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+
+ charge-full-design-microamp-hours = <2970000>;
+ voltage-min-design-microvolt = <3600000>;
+ voltage-max-design-microvolt = <4400000>;
+ };
+
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ };
+
+ vreg_s4a_1p8: vreg-s4a-1p8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_s4a_1p8";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ vin-supply = <&vph_pwr>;
+ };
+};
+
+&adsp_pas {
+ status = "okay";
+
+ firmware-name = "qcom/sdm845/pixel3/adsp.mbn";
+};
+
+&apps_rsc {
+ pm8998-rpmh-regulators {
+ compatible = "qcom,pm8998-rpmh-regulators";
+ qcom,pmic-id = "a";
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+ vdd-s11-supply = <&vph_pwr>;
+ vdd-s12-supply = <&vph_pwr>;
+ vdd-s13-supply = <&vph_pwr>;
+ vdd-l1-l27-supply = <&vreg_s7a_1p025>;
+ vdd-l2-l8-l17-supply = <&vreg_s3a_1p35>;
+ vdd-l3-l11-supply = <&vreg_s7a_1p025>;
+ vdd-l4-l5-supply = <&vreg_s7a_1p025>;
+ vdd-l6-supply = <&vph_pwr>;
+ vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p04>;
+ vdd-l9-supply = <&vreg_bob>;
+ vdd-l10-l23-l25-supply = <&vreg_bob>;
+ vdd-l13-l19-l21-supply = <&vreg_bob>;
+ vdd-l16-l28-supply = <&vreg_bob>;
+ vdd-l18-l22-supply = <&vreg_bob>;
+ vdd-l20-l24-supply = <&vreg_bob>;
+ vdd-l26-supply = <&vreg_s3a_1p35>;
+ vin-lvs-1-2-supply = <&vreg_s4a_1p8>;
+
+ vreg_s3a_1p35: smps3 {
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ };
+
+ vreg_s5a_2p04: smps5 {
+ regulator-min-microvolt = <1904000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s7a_1p025: smps7 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1028000>;
+ };
+
+ vdda_mipi_dsi0_pll:
+ vreg_l1a_0p875: ldo1 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ };
+
+ vreg_l5a_0p8: ldo5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l12a_1p8: ldo12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a_1p8: ldo7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13a_2p95: ldo13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14a_1p88: ldo14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ /*
+ * We can't properly bring the panel back if it gets turned off
+ * so keep it's regulators always on for now.
+ */
+ regulator-always-on;
+ };
+
+ vreg_l17a_1p3: ldo17 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l19a_3p3: ldo19 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3312000>;
+ qcom,init-voltage = <3300000>;
+ qcom,initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ /*
+ * The touchscreen needs this to be 3.3v, which is apparently
+ * quite close to the hardware limit for this LDO (3.312v)
+ * It must be kept in high power mode to prevent TS brownouts
+ */
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l20a_2p95: ldo20 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2968000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l21a_2p95: ldo21 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2968000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l24a_3p075: ldo24 {
+ regulator-min-microvolt = <3088000>;
+ regulator-max-microvolt = <3088000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l25a_3p3: ldo25 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdda_mipi_dsi0_1p2:
+ vreg_l26a_1p2: ldo26 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ };
+
+ vreg_l28a_3p0: ldo28 {
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-boot-on;
+ /*
+ * We can't properly bring the panel back if it gets turned off
+ * so keep it's regulators always on for now.
+ */
+ regulator-always-on;
+ };
+ };
+
+ pmi8998-rpmh-regulators {
+ compatible = "qcom,pmi8998-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-bob-supply = <&vph_pwr>;
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ regulator-allow-bypass;
+ };
+ };
+
+ pm8005-rpmh-regulators {
+ compatible = "qcom,pm8005-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+
+ vreg_s3c_0p6: smps3 {
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <600000>;
+ };
+ };
+};
+
+&cdsp_pas {
+ status = "okay";
+ firmware-name = "qcom/sdm845/pixel3/cdsp.mbn";
+};
+
+&mdss_dsi0 {
+ status = "okay";
+ vdda-supply = <&vdda_mipi_dsi0_1p2>;
+
+ panel {
+ compatible = "lg,sw43408";
+ reg = <0>;
+
+ vddi-supply = <&vreg_l14a_1p88>;
+ vpnl-supply = <&vreg_l28a_3p0>;
+
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&panel_reset_pins &panel_te_pin &panel_pmgpio_pins>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lg_sw43408_in_0: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+ };
+ };
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&lg_sw43408_in_0>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+ status = "okay";
+ vdds-supply = <&vdda_mipi_dsi0_pll>;
+};
+
+&gcc {
+ protected-clocks = <GCC_QSPI_CORE_CLK>,
+ <GCC_QSPI_CORE_CLK_SRC>,
+ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>;
+};
+
+&gmu {
+ status = "okay";
+};
+
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ memory-region = <&gpu_mem>;
+ firmware-name = "qcom/sdm845/pixel3/a630_zap.mbn";
+ };
+};
+
+&i2c2 {
+ status = "disabled";
+ #dma-cells = <3>;
+
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+
+ touchscreen@49 {
+ compatible = "st,fts";
+ reg = <0x49>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchscreen_pins &touchscreen_reset>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 IRQ_TYPE_LEVEL_LOW>;
+ avdd-supply = <&vreg_l14a_1p88>;
+ vdd-supply = <&vreg_l19a_3p3>;
+ // touchscreen-size-x = <1080>;
+ // touchscreen-size-y = <2160>;
+
+ st,irq-gpio = <&tlmm 125 0>;
+ st,reset-gpio = <&tlmm 99 0>;
+ st,switch_gpio = <&tlmm 136 0>;
+ st,max-coords = <1079 2159>;
+ st,regulator_dvdd = "vdd";
+ st,regulator_avdd = "avdd";
+ };
+};
+
+&ipa {
+ status = "okay";
+
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sdm845/pixel3/ipa_fws.mbn";
+};
+
+&mss_pil {
+ status = "okay";
+ firmware-name = "qcom/sdm845/pixel3/mba.mbn", "qcom/sdm845/pixel3/modem.mbn";
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_mdp {
+ status = "okay";
+};
+
+&pm8998_gpios {
+ volume_up_gpio: vol-up-active {
+ pins = "gpio6";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ qcom,drive-strength = <0>;
+ };
+
+ panel_pmgpio_pins: panel-pmgpio-active {
+ pins = "gpio2", "gpio5";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <0>;
+ };
+};
+
+&pm8998_pon {
+ resin {
+ compatible = "qcom,pm8941-resin";
+ interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+};
+
+&pmi8998_charger {
+ status = "okay";
+ monitored-battery = <&battery>;
+};
+
+&pmi8998_fg {
+ status = "okay";
+ monitored-battery = <&battery>;
+ power-supplies = <&pmi8998_charger>;
+};
+
+&pmi8998_rradc {
+ status = "okay";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&qup_uart6_default {
+ pinmux {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
+ function = "qup6";
+ };
+
+ cts {
+ pins = "gpio45";
+ bias-disable;
+ };
+
+ rts-tx {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio48";
+ bias-pull-up;
+ };
+};
+
+&qup_uart9_default {
+ pinconf-tx {
+ pins = "gpio4";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pinconf-rx {
+ pins = "gpio5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <81 4>;
+
+ panel_te_pin: panel-te {
+ mux {
+ pins = "gpio12";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
+ };
+
+ panel_reset_pins: panel-active {
+ mux {
+ pins = "gpio6", "gpio52";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable = <0>;
+ };
+ };
+
+ panel_suspend: panel-suspend {
+ mux {
+ pins = "gpio6", "gpio52";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ touchscreen_reset: ts-reset {
+ mux {
+ pins = "gpio99";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ //output-high;
+ };
+ };
+
+ touchscreen_pins: ts-pins {
+ mux {
+ pins = "gpio125";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+};
+
+&uart6 {
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn3990-bt";
+
+ vddio-supply = <&vreg_s4a_1p8>;
+ vddxo-supply = <&vreg_l7a_1p8>;
+ vddrf-supply = <&vreg_l17a_1p3>;
+ vddch0-supply = <&vreg_l25a_3p3>;
+ max-speed = <3200000>;
+ };
+};
+
+&uart9 {
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ status = "okay";
+
+ vdd-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
+
+ qcom,imp-res-offset-value = <8>;
+ qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_21_6_MA>;
+ qcom,preemphasis-level = <QUSB2_V2_PREEMPHASIS_5_PERCENT>;
+ qcom,preemphasis-width = <QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT>;
+};
+
+&usb_1_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l26a_1p2>;
+ vdda-pll-supply = <&vreg_l1a_0p875>;
+};
+
+&usb_2 {
+ status = "okay";
+};
+
+&usb_2_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_2_hsphy {
+ status = "okay";
+
+ vdd-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
+
+ qcom,imp-res-offset-value = <8>;
+ qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_22_8_MA>;
+};
+
+&usb_2_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l26a_1p2>;
+ vdda-pll-supply = <&vreg_l1a_0p875>;
+};
+
+&ufs_mem_hc {
+ status = "okay";
+
+ reset-gpios = <&tlmm 150 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l20a_2p95>;
+ vcc-max-microamp = <800000>;
+};
+
+&ufs_mem_phy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l26a_1p2>;
+};
+
+&venus {
+ status = "okay";
+ firmware-name = "qcom/sdm845/oneplus6/venus.mbn";
+};
+
+&wifi {
+ status = "okay";
+
+ 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>;
+
+ qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "google_blueline";
+};
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..5f4d18aa33f 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;
@@ -156,6 +193,29 @@ ts_1p8_supply: ts-1p8-regulator {
gpio = <&tlmm 88 0>;
enable-active-high;
+ };
+
+ panel_vci_3v3: panel-vci-3v3-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "LCD_VCI_3V";
+
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 26 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-boot-on;
+ };
+
+ panel_vddi_poc_1p8: panel-vddi-poc-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDI_POC";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 25 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
regulator-boot-on;
};
};
@@ -253,7 +313,7 @@ vreg_l14a_1p88: ldo14 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-always-on;
+ regulator-boot-on;
};
vreg_l17a_1p3: ldo17 {
@@ -389,6 +449,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 +459,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>;
};
@@ -429,6 +491,8 @@ display_panel: panel@0 {
reg = <0>;
vddio-supply = <&vreg_l14a_1p88>;
+ vci-supply = <&panel_vci_3v3>;
+ poc-supply = <&panel_vddi_poc_1p8>;
reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
@@ -507,6 +571,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 +708,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 +892,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;
@@ -818,7 +908,7 @@ ts_default_pins: ts-int-state {
};
panel_reset_pins: panel-reset-state {
- pins = "gpio6", "gpio25", "gpio26";
+ pins = "gpio6";
function = "gpio";
drive-strength = <8>;
bias-disable;
@@ -872,4 +962,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 486ce175e6b..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@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..e2ffd4b31b0 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"
@@ -35,9 +38,14 @@ / {
qcom,msm-id = <321 0x20001>;
aliases {
+ serial0 = &uart9;
serial1 = &uart6;
};
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
gpio-keys {
compatible = "gpio-keys";
autorepeat;
@@ -99,12 +107,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 +245,14 @@ &gmu {
status = "okay";
};
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
&gpu {
status = "okay";
@@ -264,7 +274,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 +328,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 +407,13 @@ led-1 {
};
};
+&pmi8998_fg {
+ status = "okay";
+
+ power-supplies = <&pmi8998_charger>;
+ monitored-battery = <&battery>;
+};
+
&pm8998_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -402,12 +439,47 @@ 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";
+};
+
+&qup_uart9_rx {
+ drive-strength = <2>;
+ bias-pull-up;
+};
+
+&qup_uart9_tx {
+ drive-strength = <2>;
+ bias-disable;
+};
+
&sdhc_2 {
status = "okay";
@@ -436,21 +508,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 +571,7 @@ codec {
};
slimcap-dai-link {
- link-name = "SLIM Capture";
+ link-name = "SLIM WCD Capture";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_TX>;
};
@@ -480,7 +581,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 +629,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 {
@@ -531,6 +678,11 @@ bluetooth {
};
};
+&uart9 {
+ label = "LS-UART1";
+ status = "okay";
+};
+
&ufs_mem_hc {
status = "okay";
@@ -601,4 +753,13 @@ &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";
+};
+
+
+&slpi_pas {
+ firmware-name = "qcom/sdm845/beryllium/slpi.mbn";
+ status = "okay";
};
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-xiaomi-polaris.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
index e386b504e97..8df61887e3d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
@@ -711,5 +711,6 @@ &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;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 2f20be99ee7..9842d2d3983 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 {
@@ -2681,6 +2712,11 @@ crypto: crypto@1dfa000 {
<&apps_smmu 0x706 0x1>,
<&apps_smmu 0x714 0x1>,
<&apps_smmu 0x716 0x1>;
+
+ /* FIXME: disabled due to a regression causing
+ * a trap to TZ and a hard reset if this device
+ * is used. */
+ status = "disabled";
};
ipa: ipa@1e40000 {
@@ -4443,6 +4479,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..eb072b1b45a
--- /dev/null
+++ b/arch/arm64/configs/sdm845.config
@@ -0,0 +1,1005 @@
+# 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
+
+# Pixel 3
+CONFIG_DRM_PANEL_LG_SW43408=y
+
+# 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
+
+# debugging
+CONFIG_FTRACE=y
+CONFIG_BOOTTIME_TRACING=y
+CONFIG_DYNAMIC_DEBUG=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_NLS_ASCII=y
+# 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_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_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_IOMMU_IO_PGTABLE_DART=n
+CONFIG_MEMORY_HOTPLUG=n
+CONFIG_MELLANOX_PLATFORM=n
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index cb68adcabe0..67bd8956459 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -59,7 +59,7 @@
*/
efi_signature_nop // special NOP to identity as PE/COFF executable
b primary_entry // branch to kernel start, magic
- .quad 0 // Image load offset from start of RAM, little-endian
+ le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian
le64sym _kernel_size_le // Effective size of kernel image, little-endian
le64sym _kernel_flags_le // Informative flags, little-endian
.quad 0 // reserved
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index 7bc3ba89790..0297e5d3e9a 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -62,6 +62,7 @@
*/
#define HEAD_SYMBOLS \
DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \
+ DEFINE_IMAGE_LE64(_kernel_offset_le, 0x00080000); \
DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS);
#endif /* __ARM64_KERNEL_IMAGE_H */
diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c
index b84fdd17c3d..23beef9a62b 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/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 9874ff6d471..795001bb7ff 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -645,29 +645,56 @@ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
/**
- * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
+ * mipi_dsi_compression_mode_ext() - enable/disable DSC on the peripheral
* @dsi: DSI peripheral device
* @enable: Whether to enable or disable the DSC
+ * @algo: Selected compression algorithm
+ * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries
*
- * Enable or disable Display Stream Compression on the peripheral using the
- * default Picture Parameter Set and VESA DSC 1.1 algorithm.
+ * Enable or disable Display Stream Compression on the peripheral.
*
* Return: 0 on success or a negative error code on failure.
*/
-int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
+int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector)
{
- /* Note: Needs updating for non-default PPS or algorithm */
- u8 tx[2] = { enable << 0, 0 };
+ u8 tx[2] = { };
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.type = MIPI_DSI_COMPRESSION_MODE,
.tx_len = sizeof(tx),
.tx_buf = tx,
};
- int ret = mipi_dsi_device_transfer(dsi, &msg);
+ int ret;
+
+ if (algo > 3 || pps_selector > 3)
+ return -EINVAL;
+
+ tx[0] = (enable << 0) |
+ (algo << 1) |
+ (pps_selector << 4);
+
+ ret = mipi_dsi_device_transfer(dsi, &msg);
return (ret < 0) ? ret : 0;
}
+EXPORT_SYMBOL(mipi_dsi_compression_mode_ext);
+
+/**
+ * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
+ * @dsi: DSI peripheral device
+ * @enable: Whether to enable or disable the DSC
+ *
+ * Enable or disable Display Stream Compression on the peripheral using the
+ * default Picture Parameter Set and VESA DSC 1.1 algorithm.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
+{
+ return mipi_dsi_compression_mode_ext(dsi, enable, MIPI_DSI_COMPRESSION_DSC, 0);
+}
EXPORT_SYMBOL(mipi_dsi_compression_mode);
/**
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index cf0b1de1c07..ff3ff6ab9dd 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2115,12 +2115,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");
@@ -2129,10 +2124,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/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 9a14d2232e4..6cc7dfe0093 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1200,6 +1200,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
phys->cached_mode = crtc_state->adjusted_mode;
+ if (phys->ops.atomic_mode_set)
+ phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
}
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 98d1b64a43e..53b95f66a82 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -69,6 +69,8 @@ struct dpu_encoder_phys;
* @is_master: Whether this phys_enc is the current master
* encoder. Can be switched at enable time. Based
* on split_role and current mode (CMD/VID).
+ * @atomic_mode_set: DRM Call. Set a DRM mode.
+ * This likely caches the mode, for use at enable.
* @enable: DRM Call. Enable a DRM mode.
* @disable: DRM Call. Disable mode.
* @control_vblank_irq Register/Deregister for VBLANK IRQ
@@ -93,6 +95,9 @@ struct dpu_encoder_phys;
struct dpu_encoder_phys_ops {
void (*prepare_commit)(struct dpu_encoder_phys *encoder);
bool (*is_master)(struct dpu_encoder_phys *encoder);
+ void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state);
void (*enable)(struct dpu_encoder_phys *encoder);
void (*disable)(struct dpu_encoder_phys *encoder);
int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index fc1d5736d7f..6b525475ae3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -142,6 +142,23 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg)
dpu_encoder_underrun_callback(phys_enc->parent, phys_enc);
}
+static void dpu_encoder_phys_cmd_atomic_mode_set(
+ struct dpu_encoder_phys *phys_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
+
+ phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
+
+ if (phys_enc->has_intf_te)
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
+ else
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
+
+ phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
+}
+
static int _dpu_encoder_phys_cmd_handle_ppdone_timeout(
struct dpu_encoder_phys *phys_enc)
{
@@ -280,14 +297,6 @@ static void dpu_encoder_phys_cmd_irq_enable(struct dpu_encoder_phys *phys_enc)
phys_enc->hw_pp->idx - PINGPONG_0,
phys_enc->vblank_refcount);
- phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
- phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
-
- if (phys_enc->has_intf_te)
- phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
- else
- phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
-
dpu_core_irq_register_callback(phys_enc->dpu_kms,
phys_enc->irq[INTR_IDX_PINGPONG],
dpu_encoder_phys_cmd_pp_tx_done_irq,
@@ -318,10 +327,6 @@ static void dpu_encoder_phys_cmd_irq_disable(struct dpu_encoder_phys *phys_enc)
dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_UNDERRUN]);
dpu_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
dpu_core_irq_unregister_callback(phys_enc->dpu_kms, phys_enc->irq[INTR_IDX_PINGPONG]);
-
- phys_enc->irq[INTR_IDX_CTL_START] = 0;
- phys_enc->irq[INTR_IDX_PINGPONG] = 0;
- phys_enc->irq[INTR_IDX_RDPTR] = 0;
}
static void dpu_encoder_phys_cmd_tearcheck_config(
@@ -472,6 +477,14 @@ static void dpu_encoder_phys_cmd_enable(struct dpu_encoder_phys *phys_enc)
return;
}
+ phys_enc->irq[INTR_IDX_CTL_START] = phys_enc->hw_ctl->caps->intr_start;
+ phys_enc->irq[INTR_IDX_PINGPONG] = phys_enc->hw_pp->caps->intr_done;
+
+ if (phys_enc->has_intf_te)
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_intf->cap->intr_tear_rd_ptr;
+ else
+ phys_enc->irq[INTR_IDX_RDPTR] = phys_enc->hw_pp->caps->intr_rdptr;
+
dpu_encoder_phys_cmd_enable_helper(phys_enc);
phys_enc->enable_state = DPU_ENC_ENABLED;
}
@@ -563,6 +576,10 @@ static void dpu_encoder_phys_cmd_disable(struct dpu_encoder_phys *phys_enc)
ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx);
}
+ phys_enc->irq[INTR_IDX_CTL_START] = 0;
+ phys_enc->irq[INTR_IDX_PINGPONG] = 0;
+ phys_enc->irq[INTR_IDX_RDPTR] = 0;
+
phys_enc->enable_state = DPU_ENC_DISABLED;
}
@@ -701,6 +718,7 @@ static void dpu_encoder_phys_cmd_init_ops(
struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_cmd_is_master;
+ ops->atomic_mode_set = dpu_encoder_phys_cmd_atomic_mode_set;
ops->enable = dpu_encoder_phys_cmd_enable;
ops->disable = dpu_encoder_phys_cmd_disable;
ops->control_vblank_irq = dpu_encoder_phys_cmd_control_vblank_irq;
@@ -739,8 +757,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
dpu_encoder_phys_cmd_init_ops(&phys_enc->ops);
phys_enc->intf_mode = INTF_MODE_CMD;
- phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
-
cmd_enc->stream_sel = 0;
if (!phys_enc->hw_intf) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index d9e7dbf0499..0fe9d16df2d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -356,6 +356,16 @@ static bool dpu_encoder_phys_vid_needs_single_flush(
return phys_enc->split_role != ENC_ROLE_SOLO;
}
+static void dpu_encoder_phys_vid_atomic_mode_set(
+ struct dpu_encoder_phys *phys_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ phys_enc->irq[INTR_IDX_VSYNC] = phys_enc->hw_intf->cap->intr_vsync;
+
+ phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
+}
+
static int dpu_encoder_phys_vid_control_vblank_irq(
struct dpu_encoder_phys *phys_enc,
bool enable)
@@ -699,6 +709,7 @@ static int dpu_encoder_phys_vid_get_frame_count(
static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_vid_is_master;
+ ops->atomic_mode_set = dpu_encoder_phys_vid_atomic_mode_set;
ops->enable = dpu_encoder_phys_vid_enable;
ops->disable = dpu_encoder_phys_vid_disable;
ops->control_vblank_irq = dpu_encoder_phys_vid_control_vblank_irq;
@@ -737,8 +748,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
dpu_encoder_phys_vid_init_ops(&phys_enc->ops);
phys_enc->intf_mode = INTF_MODE_VIDEO;
- phys_enc->irq[INTR_IDX_VSYNC] = phys_enc->hw_intf->cap->intr_vsync;
- phys_enc->irq[INTR_IDX_UNDERRUN] = phys_enc->hw_intf->cap->intr_underrun;
DPU_DEBUG_VIDENC(phys_enc, "created intf idx:%d\n", p->hw_intf->idx);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 1924a2b28e5..8e84de412c6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -404,6 +404,15 @@ static void dpu_encoder_phys_wb_irq_disable(struct dpu_encoder_phys *phys)
dpu_core_irq_unregister_callback(phys->dpu_kms, phys->irq[INTR_IDX_WB_DONE]);
}
+static void dpu_encoder_phys_wb_atomic_mode_set(
+ struct dpu_encoder_phys *phys_enc,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+
+ phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done;
+}
+
static void _dpu_encoder_phys_wb_handle_wbdone_timeout(
struct dpu_encoder_phys *phys_enc)
{
@@ -640,6 +649,7 @@ static bool dpu_encoder_phys_wb_is_valid_for_commit(struct dpu_encoder_phys *phy
static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops)
{
ops->is_master = dpu_encoder_phys_wb_is_master;
+ ops->atomic_mode_set = dpu_encoder_phys_wb_atomic_mode_set;
ops->enable = dpu_encoder_phys_wb_enable;
ops->disable = dpu_encoder_phys_wb_disable;
ops->wait_for_commit_done = dpu_encoder_phys_wb_wait_for_commit_done;
@@ -685,7 +695,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev,
dpu_encoder_phys_wb_init_ops(&phys_enc->ops);
phys_enc->intf_mode = INTF_MODE_WB_LINE;
- phys_enc->irq[INTR_IDX_WB_DONE] = phys_enc->hw_wb->caps->intr_wb_done;
atomic_set(&wb_enc->wbirq_refcount, 0);
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index fab6ad4e510..c1089d789e0 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -384,6 +384,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 5b15d029483..c635f288d60 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -335,6 +335,17 @@ config DRM_PANEL_LG_LG4573
Say Y here if you want to enable support for LG4573 RGB panel.
To compile this driver as a module, choose M here.
+config DRM_PANEL_LG_SW43408
+ tristate "LG SW43408 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 LG sw43408 panel.
+ The panel has a 1080x2160@60Hz resolution and uses 24 bit RGB per
+ pixel. It provides a MIPI DSI interface to the host and has a
+ built-in LED backlight.
+
config DRM_PANEL_MAGNACHIP_D53E6EA8966
tristate "Magnachip D53E6EA8966 DSI panel"
depends on OF && SPI
@@ -405,6 +416,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
@@ -669,6 +690,18 @@ config DRM_PANEL_SAMSUNG_SOFEF00
The panels are 2280x1080@60Hz and 2340x1080@60Hz respectively
+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 panel found in the OnePlus 6T smartphone.
+
+ The panel is 2340x1080@60Hz
+
config DRM_PANEL_SEIKO_43WVF1G
tristate "Seiko 43WVF1G panel"
depends on OF
@@ -887,6 +920,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 f156d7fa0bc..a568d761e7d 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -34,12 +34,14 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o
obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
+obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o
obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
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
@@ -70,6 +72,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
@@ -89,6 +92,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-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c
new file mode 100644
index 00000000000..2413ecb6ae6
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c
@@ -0,0 +1,355 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-2024 Linaro Ltd
+ * Author: Sumit Semwal <sumit.semwal@linaro.org>
+ * Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ */
+
+#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_panel.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/display/drm_dsc.h>
+#include <drm/display/drm_dsc_helper.h>
+
+#define NUM_SUPPLIES 2
+
+static const char *const regulator_names[] = {
+ "vddi",
+ "vpnl",
+};
+
+static unsigned long const regulator_enable_loads[] = {
+ 62000,
+ 857000,
+};
+
+static unsigned long const regulator_disable_loads[] = {
+ 80,
+ 0,
+};
+
+struct sw43408_panel {
+ struct drm_panel base;
+ struct mipi_dsi_device *link;
+
+ struct regulator_bulk_data supplies[NUM_SUPPLIES];
+
+ struct gpio_desc *reset_gpio;
+
+ struct drm_dsc_config dsc;
+};
+
+static inline struct sw43408_panel *to_panel_info(struct drm_panel *panel)
+{
+ return container_of(panel, struct sw43408_panel, base);
+}
+
+static int sw43408_unprepare(struct drm_panel *panel)
+{
+ struct sw43408_panel *ctx = to_panel_info(panel);
+ int ret, i;
+
+ ret = mipi_dsi_dcs_set_display_off(ctx->link);
+ if (ret < 0)
+ dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(ctx->link);
+ if (ret < 0)
+ dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+
+ msleep(100);
+
+ //gpiod_set_value(ctx->reset_gpio, 1);
+
+ for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
+ ret = regulator_set_load(ctx->supplies[i].consumer,
+ regulator_disable_loads[i]);
+ if (ret) {
+ dev_err(panel->dev,
+ "regulator_set_load failed %d\n", ret);
+ return ret;
+ }
+ }
+
+ return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+}
+
+static int sw43408_program(struct drm_panel *panel)
+{
+ struct sw43408_panel *ctx = to_panel_info(panel);
+ struct drm_dsc_picture_parameter_set pps;
+
+ mipi_dsi_dcs_write_seq(ctx->link, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
+
+ mipi_dsi_dcs_set_tear_on(ctx->link, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+
+ mipi_dsi_dcs_write_seq(ctx->link, 0x53, 0x0c, 0x30);
+ mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x00, 0x70, 0xdf, 0x00, 0x70, 0xdf);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xf7, 0x01, 0x49, 0x0c);
+
+ mipi_dsi_dcs_exit_sleep_mode(ctx->link);
+
+ msleep(135);
+
+ /* COMPRESSION_MODE moved after setting the PPS */
+
+ mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xac);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xe5,
+ 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0e, 0x10);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xb5,
+ 0x75, 0x60, 0x2d, 0x5d, 0x80, 0x00, 0x0a, 0x0b,
+ 0x00, 0x05, 0x0b, 0x00, 0x80, 0x0d, 0x0e, 0x40,
+ 0x00, 0x0c, 0x00, 0x16, 0x00, 0xb8, 0x00, 0x80,
+ 0x0d, 0x0e, 0x40, 0x00, 0x0c, 0x00, 0x16, 0x00,
+ 0xb8, 0x00, 0x81, 0x00, 0x03, 0x03, 0x03, 0x01,
+ 0x01);
+ msleep(85);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xcd,
+ 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0x19, 0x19,
+ 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
+ 0x16, 0x16);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xcb, 0x80, 0x5c, 0x07, 0x03, 0x28);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xc0, 0x02, 0x02, 0x0f);
+ mipi_dsi_dcs_write_seq(ctx->link, 0x55, 0x04, 0x61, 0xdb, 0x04, 0x70, 0xdb);
+ mipi_dsi_dcs_write_seq(ctx->link, 0xb0, 0xca);
+
+ mipi_dsi_dcs_set_display_on(ctx->link);
+
+ msleep(50);
+
+ ctx->link->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ drm_dsc_pps_payload_pack(&pps, ctx->link->dsc);
+ mipi_dsi_picture_parameter_set(ctx->link, &pps);
+
+ ctx->link->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ /*
+ * This panel uses PPS selectors with offset:
+ * PPS 1 if pps_identifier is 0
+ * PPS 2 if pps_identifier is 1
+ */
+ mipi_dsi_compression_mode_ext(ctx->link, true,
+ MIPI_DSI_COMPRESSION_DSC, 1);
+
+
+ return 0;
+}
+
+static int sw43408_prepare(struct drm_panel *panel)
+{
+ struct sw43408_panel *ctx = to_panel_info(panel);
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
+ ret = regulator_set_load(ctx->supplies[i].consumer,
+ regulator_enable_loads[i]);
+ if (ret)
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(5000, 6000);
+
+ gpiod_set_value(ctx->reset_gpio, 0);
+ usleep_range(9000, 10000);
+ gpiod_set_value(ctx->reset_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ctx->reset_gpio, 0);
+ usleep_range(9000, 10000);
+
+ ret = sw43408_program(panel);
+ if (ret)
+ goto poweroff;
+
+ return 0;
+
+poweroff:
+ gpiod_set_value(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ return ret;
+}
+
+static const struct drm_display_mode sw43408_mode = {
+ .clock = (1080 + 20 + 32 + 20) * (2160 + 20 + 4 + 20) * 60 / 1000,
+
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 20,
+ .hsync_end = 1080 + 20 + 32,
+ .htotal = 1080 + 20 + 32 + 20,
+
+ .vdisplay = 2160,
+ .vsync_start = 2160 + 20,
+ .vsync_end = 2160 + 20 + 4,
+ .vtotal = 2160 + 20 + 4 + 20,
+
+ .width_mm = 62,
+ .height_mm = 124,
+
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static int sw43408_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ return drm_connector_helper_get_modes_fixed(connector, &sw43408_mode);
+}
+
+static int sw43408_backlight_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ uint16_t brightness = backlight_get_brightness(bl);
+
+ return mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
+}
+
+const struct backlight_ops sw43408_backlight_ops = {
+ .update_status = sw43408_backlight_update_status,
+};
+
+static int sw43408_backlight_init(struct sw43408_panel *ctx)
+{
+ struct device *dev = &ctx->link->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_PLATFORM,
+ .brightness = 255,
+ .max_brightness = 255,
+ };
+
+ ctx->base.backlight = devm_backlight_device_register(dev, dev_name(dev), dev,
+ ctx->link,
+ &sw43408_backlight_ops,
+ &props);
+
+ if (IS_ERR(ctx->base.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->base.backlight),
+ "Failed to create backlight\n");
+
+ return 0;
+}
+
+static const struct drm_panel_funcs sw43408_funcs = {
+ .unprepare = sw43408_unprepare,
+ .prepare = sw43408_prepare,
+ .get_modes = sw43408_get_modes,
+};
+
+static const struct of_device_id sw43408_of_match[] = {
+ { .compatible = "lg,sw43408", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sw43408_of_match);
+
+static int sw43408_add(struct sw43408_panel *ctx)
+{
+ struct device *dev = &ctx->link->dev;
+ int ret;
+
+ ctx->supplies[0].supply = "vddi"; /* 1.88 V */
+ ctx->supplies[0].init_load_uA = 62000;
+ ctx->supplies[1].supply = "vpnl"; /* 3.0 V */
+ ctx->supplies[1].init_load_uA = 857000;
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+ ctx->supplies);
+ if (ret < 0)
+ return ret;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio)) {
+ dev_err(dev, "cannot get reset gpio %ld\n",
+ PTR_ERR(ctx->reset_gpio));
+ return PTR_ERR(ctx->reset_gpio);
+ }
+
+ ret = sw43408_backlight_init(ctx);
+ if (ret < 0)
+ return ret;
+
+ ctx->base.prepare_prev_first = true;
+
+ drm_panel_init(&ctx->base, dev, &sw43408_funcs, DRM_MODE_CONNECTOR_DSI);
+
+ drm_panel_add(&ctx->base);
+ return ret;
+}
+
+static int sw43408_probe(struct mipi_dsi_device *dsi)
+{
+ struct sw43408_panel *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ dsi->mode_flags = MIPI_DSI_MODE_LPM;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->lanes = 4;
+
+ ctx->link = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ret = sw43408_add(ctx);
+ if (ret < 0)
+ return ret;
+
+ /* The panel works only in the DSC mode. Set DSC params. */
+ ctx->dsc.dsc_version_major = 0x1;
+ ctx->dsc.dsc_version_minor = 0x1;
+
+ /* slice_count * slice_width == width */
+ ctx->dsc.slice_height = 16;
+ ctx->dsc.slice_width = 540;
+ ctx->dsc.slice_count = 2;
+ ctx->dsc.bits_per_component = 8;
+ ctx->dsc.bits_per_pixel = 8 << 4;
+ ctx->dsc.block_pred_enable = true;
+
+ dsi->dsc = &ctx->dsc;
+
+ return mipi_dsi_attach(dsi);
+}
+
+static void sw43408_remove(struct mipi_dsi_device *dsi)
+{
+ struct sw43408_panel *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = sw43408_unprepare(&ctx->base);
+ if (ret < 0)
+ dev_err(&dsi->dev, "failed to unprepare panel: %d\n",
+ 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->base);
+}
+
+static struct mipi_dsi_driver sw43408_driver = {
+ .driver = {
+ .name = "panel-lg-sw43408",
+ .of_match_table = sw43408_of_match,
+ },
+ .probe = sw43408_probe,
+ .remove = sw43408_remove,
+};
+module_mipi_dsi_driver(sw43408_driver);
+
+MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
+MODULE_DESCRIPTION("LG SW436408 MIPI-DSI LED panel");
+MODULE_LICENSE("GPL");
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..e441409c686
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-novatek-nt35596s.c
@@ -0,0 +1,566 @@
+// 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);
+ pinfo->base.prepare_prev_first = true;
+
+ 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..f4a03a2d5fd
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c
@@ -0,0 +1,395 @@
+// 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.
+ */
+
+#define DEBUG
+
+#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;
+ bool first_prepare;
+ struct regulator_bulk_data supplies[3];
+ //struct gpio_desc *reset_gpio;
+};
+
+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_off(struct samsung_s6e3fc2x01 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ 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(&dsi->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(&dsi->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;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ /*
+ * On boot the panel has already been initialised, if the regulators are
+ * already enabled then we can safely assume that the panel is on and we
+ * can skip the prepare.
+ */
+ if (regulator_is_enabled(ctx->supplies[0].consumer) && ctx->first_prepare) {
+ ctx->first_prepare = false;
+ dev_dbg(dev, "First prepare!\n");
+ return 0;
+ }
+
+ // ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ // 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_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_disable(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+
+ dev_dbg(&ctx->dsi->dev, "%s\n", __func__);
+
+ samsung_s6e3fc2x01_off(ctx);
+
+ //gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ //regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+ 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;
+
+ mode = drm_mode_duplicate(connector->dev, &samsung_s6e3fc2x01_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,
+ .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;
+
+ pr_info("samsung_s6e3fc2x01_probe\n");
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->supplies[0].supply = "vddio";
+ ctx->supplies[1].supply = "vci";
+ ctx->supplies[2].supply = "poc";
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get vddio regulator\n");
+
+ /* Regulators are all boot-on, enable them to balance the refcounts so we can disable
+ * them later in the first prepare() call */
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to enable regulators\n");
+
+ ctx->first_prepare = true;
+ // ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ // 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;
+
+ drm_panel_init(&ctx->panel, dev, &samsung_s6e3fc2x01_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ 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");
+ 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 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..f34f515089b 100644
--- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c
+++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c
@@ -20,9 +20,9 @@
struct sofef00_panel {
struct drm_panel panel;
struct mipi_dsi_device *dsi;
- struct regulator *supply;
+ bool first_prepare;
+ struct regulator_bulk_data supplies[3];
struct gpio_desc *reset_gpio;
- const struct drm_display_mode *mode;
};
static inline
@@ -84,21 +84,20 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
static int sofef00_panel_off(struct sofef00_panel *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);
+ 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);
@@ -112,7 +111,20 @@ static int sofef00_panel_prepare(struct drm_panel *panel)
struct device *dev = &ctx->dsi->dev;
int ret;
- ret = regulator_enable(ctx->supply);
+ dev_dbg(dev, "%s\n", __func__);
+
+ /*
+ * On boot the panel has already been initialised, if the regulators are
+ * already enabled then we can safely assume that the panel is on and we
+ * can skip the prepare.
+ */
+ if (regulator_is_enabled(ctx->supplies[0].consumer) && ctx->first_prepare) {
+ ctx->first_prepare = false;
+ dev_dbg(dev, "First prepare!\n");
+ return 0;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
if (ret < 0) {
dev_err(dev, "Failed to enable regulator: %d\n", ret);
return ret;
@@ -124,23 +136,27 @@ static int sofef00_panel_prepare(struct drm_panel *panel)
if (ret < 0) {
dev_err(dev, "Failed to initialize panel: %d\n", ret);
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
return ret;
}
return 0;
}
-static int sofef00_panel_unprepare(struct drm_panel *panel)
+static int sofef00_panel_disable(struct drm_panel *panel)
{
struct sofef00_panel *ctx = to_sofef00_panel(panel);
struct device *dev = &ctx->dsi->dev;
int ret;
+ dev_dbg(dev, "%s\n", __func__);
+
ret = sofef00_panel_off(ctx);
if (ret < 0)
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
- regulator_disable(ctx->supply);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
return 0;
}
@@ -159,26 +175,11 @@ 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;
- struct sofef00_panel *ctx = to_sofef00_panel(panel);
- mode = drm_mode_duplicate(connector->dev, ctx->mode);
+ mode = drm_mode_duplicate(connector->dev, &enchilada_panel_mode);
if (!mode)
return -ENOMEM;
@@ -194,7 +195,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,
- .unprepare = sofef00_panel_unprepare,
+ .disable = sofef00_panel_disable,
.get_modes = sofef00_panel_get_modes,
};
@@ -221,7 +222,7 @@ sofef00_create_backlight(struct mipi_dsi_device *dsi)
struct device *dev = &dsi->dev;
const struct backlight_properties props = {
.type = BACKLIGHT_PLATFORM,
- .brightness = 1023,
+ .brightness = 512,
.max_brightness = 1023,
};
@@ -239,19 +240,25 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi)
if (!ctx)
return -ENOMEM;
- ctx->mode = of_device_get_match_data(dev);
+ ctx->supplies[0].supply = "vddio";
+ ctx->supplies[1].supply = "vci";
+ ctx->supplies[2].supply = "poc";
- 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),
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
"Failed to get vddio regulator\n");
- ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ /* Regulators are all boot-on, enable them to balance the refcounts so we can disable
+ * them later in the first prepare() call */
+ ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to enable regulators\n");
+
+ ctx->first_prepare = true;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ctx->reset_gpio))
return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
"Failed to get reset-gpios\n");
@@ -264,6 +271,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))
@@ -295,14 +303,7 @@ static void sofef00_panel_remove(struct mipi_dsi_device *dsi)
}
static const struct of_device_id sofef00_panel_of_match[] = {
- { // OnePlus 6 / enchilada
- .compatible = "samsung,sofef00",
- .data = &enchilada_panel_mode,
- },
- { // OnePlus 6T / fajita
- .compatible = "samsung,s6e3fc2x01",
- .data = &fajita_panel_mode,
- },
+ { .compatible = "samsung,sofef00" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sofef00_panel_of_match);
@@ -311,7 +312,7 @@ static struct mipi_dsi_driver sofef00_panel_driver = {
.probe = sofef00_panel_probe,
.remove = sofef00_panel_remove,
.driver = {
- .name = "panel-oneplus6",
+ .name = "panel-samsung-sofef00",
.of_match_table = 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 ef9ea295f9e..354960ac544 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/Kconfig b/drivers/input/touchscreen/Kconfig
index c821fe3ee79..4a5a749d226 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,7 @@ menuconfig INPUT_TOUCHSCREEN
If unsure, say Y.
if INPUT_TOUCHSCREEN
+source "drivers/input/touchscreen/stm/Kconfig"
config TOUCHSCREEN_88PM860X
tristate "Marvell 88PM860x touchscreen"
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index a81cb5aa21a..e1f98f921b2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -121,3 +121,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o
obj-$(CONFIG_TOUCHSCREEN_IQS7211) += iqs7211.o
obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o
obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += stm/
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/input/touchscreen/stm-fingertips.c b/drivers/input/touchscreen/stm-fingertips.c
new file mode 100644
index 00000000000..1207423b0b5
--- /dev/null
+++ b/drivers/input/touchscreen/stm-fingertips.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+static int s6sy761_power_on(struct s6sy761_data *sdata)
+{
+ u8 buffer[S6SY761_EVENT_SIZE];
+ u8 event;
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
+ sdata->regulators);
+ if (ret)
+ return ret;
+
+ msleep(140);
+
+ /* double check whether the touch is functional */
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ S6SY761_READ_ONE_EVENT,
+ S6SY761_EVENT_SIZE,
+ buffer);
+ if (ret < 0)
+ return ret;
+
+ event = (buffer[0] >> 2) & 0xf;
+
+ if ((event != S6SY761_EVENT_INFO &&
+ event != S6SY761_EVENT_VENDOR_INFO) ||
+ buffer[1] != S6SY761_INFO_BOOT_COMPLETE) {
+ return -ENODEV;
+ }
+
+ ret = i2c_smbus_read_byte_data(sdata->client, S6SY761_BOOT_STATUS);
+ if (ret < 0)
+ return ret;
+
+ /* for some reasons the device might be stuck in the bootloader */
+ if (ret != S6SY761_BS_APPLICATION)
+ return -ENODEV;
+
+ /* enable touch functionality */
+ ret = i2c_smbus_write_word_data(sdata->client,
+ S6SY761_TOUCH_FUNCTION,
+ S6SY761_MASK_TOUCH);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int s6sy761_hw_init(struct s6sy761_data *sdata,
+ unsigned int *max_x, unsigned int *max_y)
+{
+ u8 buffer[S6SY761_PANEL_ID_SIZE]; /* larger read size */
+ int ret;
+
+ ret = s6sy761_power_on(sdata);
+ if (ret)
+ return ret;
+
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ S6SY761_DEVICE_ID,
+ S6SY761_DEVID_SIZE,
+ buffer);
+ if (ret < 0)
+ return ret;
+
+ sdata->devid = get_unaligned_be16(buffer + 1);
+
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ S6SY761_PANEL_INFO,
+ S6SY761_PANEL_ID_SIZE,
+ buffer);
+ if (ret < 0)
+ return ret;
+
+ *max_x = get_unaligned_be16(buffer);
+ *max_y = get_unaligned_be16(buffer + 2);
+
+ /* if no tx channels defined, at least keep one */
+ sdata->tx_channel = max_t(u8, buffer[8], 1);
+
+ ret = i2c_smbus_read_byte_data(sdata->client,
+ S6SY761_FIRMWARE_INTEGRITY);
+ if (ret < 0)
+ return ret;
+ else if (ret != S6SY761_FW_OK)
+ return -ENODEV;
+
+ return 0;
+}
+
+static void s6sy761_power_off(void *data)
+{
+ struct s6sy761_data *sdata = data;
+
+ disable_irq(sdata->client->irq);
+ regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
+ sdata->regulators);
+}
+
+static int s6sy761_probe(struct i2c_client *client)
+{
+ struct s6sy761_data *sdata;
+ unsigned int max_x, max_y;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENODEV;
+
+ sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL);
+ if (!sdata)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, sdata);
+ sdata->client = client;
+
+ sdata->regulators[S6SY761_REGULATOR_VDD].supply = "vdd";
+ sdata->regulators[S6SY761_REGULATOR_AVDD].supply = "avdd";
+ err = devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(sdata->regulators),
+ sdata->regulators);
+ if (err)
+ return err;
+
+ err = devm_add_action_or_reset(&client->dev, s6sy761_power_off, sdata);
+ if (err)
+ return err;
+
+ err = s6sy761_hw_init(sdata, &max_x, &max_y);
+ if (err)
+ return err;
+
+ sdata->input = devm_input_allocate_device(&client->dev);
+ if (!sdata->input)
+ return -ENOMEM;
+
+ sdata->input->name = S6SY761_DEV_NAME;
+ sdata->input->id.bustype = BUS_I2C;
+ sdata->input->open = s6sy761_input_open;
+ sdata->input->close = s6sy761_input_close;
+
+ input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(sdata->input, true, &sdata->prop);
+
+ if (!input_abs_get_max(sdata->input, ABS_X) ||
+ !input_abs_get_max(sdata->input, ABS_Y)) {
+ dev_warn(&client->dev, "the axis have not been set\n");
+ }
+
+ err = input_mt_init_slots(sdata->input, sdata->tx_channel,
+ INPUT_MT_DIRECT);
+ if (err)
+ return err;
+
+ input_set_drvdata(sdata->input, sdata);
+
+ err = input_register_device(sdata->input);
+ if (err)
+ return err;
+
+ err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ s6sy761_irq_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "s6sy761_irq", sdata);
+ if (err)
+ return err;
+
+ pm_runtime_enable(&client->dev);
+
+ return 0;
+}
+
+static void s6sy761_remove(struct i2c_client *client)
+{
+ pm_runtime_disable(&client->dev);
+}
+
+static int s6sy761_runtime_suspend(struct device *dev)
+{
+ struct s6sy761_data *sdata = dev_get_drvdata(dev);
+
+ return i2c_smbus_write_byte_data(sdata->client,
+ S6SY761_APPLICATION_MODE, S6SY761_APP_SLEEP);
+}
+
+static int s6sy761_runtime_resume(struct device *dev)
+{
+ struct s6sy761_data *sdata = dev_get_drvdata(dev);
+
+ return i2c_smbus_write_byte_data(sdata->client,
+ S6SY761_APPLICATION_MODE, S6SY761_APP_NORMAL);
+}
+
+static int s6sy761_suspend(struct device *dev)
+{
+ struct s6sy761_data *sdata = dev_get_drvdata(dev);
+
+ s6sy761_power_off(sdata);
+
+ return 0;
+}
+
+static int s6sy761_resume(struct device *dev)
+{
+ struct s6sy761_data *sdata = dev_get_drvdata(dev);
+
+ enable_irq(sdata->client->irq);
+
+ return s6sy761_power_on(sdata);
+}
+
+static const struct dev_pm_ops s6sy761_pm_ops = {
+ SYSTEM_SLEEP_PM_OPS(s6sy761_suspend, s6sy761_resume)
+ RUNTIME_PM_OPS(s6sy761_runtime_suspend, s6sy761_runtime_resume, NULL)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id s6sy761_of_match[] = {
+ { .compatible = "samsung,s6sy761", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, s6sy761_of_match);
+#endif
+
+static const struct i2c_device_id s6sy761_id[] = {
+ { "s6sy761", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, s6sy761_id);
+
+static struct i2c_driver s6sy761_driver = {
+ .driver = {
+ .name = S6SY761_DEV_NAME,
+ .dev_groups = s6sy761_sysfs_groups,
+ .of_match_table = of_match_ptr(s6sy761_of_match),
+ .pm = pm_ptr(&s6sy761_pm_ops),
+ },
+ .probe = s6sy761_probe,
+ .remove = s6sy761_remove,
+ .id_table = s6sy761_id,
+};
+
+module_i2c_driver(s6sy761_driver);
+
+MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
+MODULE_DESCRIPTION("Samsung S6SY761 Touch Screen");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/stm/Kconfig b/drivers/input/touchscreen/stm/Kconfig
new file mode 100644
index 00000000000..ce7c581c88b
--- /dev/null
+++ b/drivers/input/touchscreen/stm/Kconfig
@@ -0,0 +1,30 @@
+#
+# STMicroelectronics TOUCH driver configuration
+#
+
+config TOUCHSCREEN_SMT_FTS_DOWNSTREAM
+ tristate "STMicroelectronics i2c multitouch touchscreen - FingerTipS (FTM5)"
+ depends on I2C
+ select TOUCHSCREEN_HEATMAP
+ help
+ Say Y here to enable STMicroelectronics (FTM5) touchscreen support.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the module
+ will be called fts_touch.
+
+
+config TOUCHSCREEN_FTM4
+ tristate "STMicroelectronics i2c multitouch touchscreen - FTM4 with FingerTipS"
+ depends on I2C
+ help
+ Say Y here to enable STMicroelectronics touchscreen support.
+ If unsure, say N.
+ To compile this driver as a module, choose M here: the module
+ will be called fts_touch.
+
+config TOUCHSCREEN_FTM4_SHOW_EVENTS
+ bool "Enable debug of FTM4 events"
+ depends on TOUCHSCREEN_FTM4
+ help
+ Say Y here to enable dumping of touch driver events. This should
+ only be enabled for debugging and not for shipping code.
diff --git a/drivers/input/touchscreen/stm/Makefile b/drivers/input/touchscreen/stm/Makefile
new file mode 100644
index 00000000000..364001fc424
--- /dev/null
+++ b/drivers/input/touchscreen/stm/Makefile
@@ -0,0 +1,11 @@
+# FTM5 support
+obj-$(TOUCHSCREEN_SMT_FTS_DOWNSTREAM) += ftm5.o
+ftm5-objs = fts.o fts_proc.o
+ftm5-objs += \
+ fts_lib/ftsCompensation.o fts_lib/ftsCore.o fts_lib/ftsError.o \
+ fts_lib/ftsFrame.o fts_lib/ftsIO.o fts_lib/ftsTest.o fts_lib/ftsTime.o \
+ fts_lib/ftsTool.o fts_lib/ftsFlash.o fts_lib/ftsGesture.o
+
+# Legacy driver
+obj-$(CONFIG_TOUCHSCREEN_FTM4) += ftm4.o
+ftm4-objs += ftm4_ts.o ftm4_fwu.o ftm4_pdc.o
diff --git a/drivers/input/touchscreen/stm/ftm4_fwu.c b/drivers/input/touchscreen/stm/ftm4_fwu.c
new file mode 100644
index 00000000000..76e8db5be4f
--- /dev/null
+++ b/drivers/input/touchscreen/stm/ftm4_fwu.c
@@ -0,0 +1,960 @@
+/******************** (C) COPYRIGHT 2012 STMicroelectronics ********************
+*
+* File Name : ftm4_fwu.c
+* Authors : AMS(Analog Mems Sensor) Team
+* Description : FTS Capacitive touch screen controller (FingerTipS)
+*
+********************************************************************************
+*
+* 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.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+*******************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include "ftm4_ts.h"
+
+#define FTS64FILE_SIGNATURE 0xaaaa5555
+
+enum {
+ BUILT_IN = 0,
+ UMS,
+ NONE,
+ FFU,
+};
+
+struct fts64_header {
+ unsigned int signature;
+ unsigned short fw_ver;
+ unsigned char fw_id;
+ unsigned char reserved1;
+ unsigned char internal_ver[8];
+ unsigned char released_ver[8];
+ unsigned int reserved2;
+ unsigned int checksum;
+};
+
+bool get_pure_autotune_status(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char addrs[3];
+ unsigned char buf[5];
+ bool ret = false;
+ int doffset = 1;
+
+ if (info->digital_rev == FTS_DIGITAL_REV_1)
+ doffset = 0;
+
+ addrs[0] = 0xd0;
+ addrs[1] = 0x00;
+ addrs[2] = 0x4E;
+
+ rc = info->fts_read_reg(info, addrs, 3, buf, 4);
+ if (rc < 0) {
+ tsp_debug_err(info->dev,
+ "%s: PureAutotune Information Read Fail!!"
+ "[Data : %2X%2X]\n",
+ __func__, buf[0 + doffset],
+ buf[1 + doffset]);
+ } else {
+ if ((buf[0 + doffset] == 0xA5) && (buf[1 + doffset] == 0x96))
+ ret = 1;
+ tsp_debug_info(info->dev,
+ "%s: PureAutotune Information !! "
+ "[Data : %2X%2X]\n", __func__,
+ buf[0 + doffset],
+ buf[1 + doffset]);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(get_pure_autotune_status);
+
+static bool get_afe_status(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char addrs[3];
+ unsigned char buf[5];
+ bool ret = false;
+ int doffset = 1;
+
+ if (info->digital_rev == FTS_DIGITAL_REV_1)
+ doffset = 0;
+
+ addrs[0] = 0xd0;
+ addrs[1] = 0x00;
+ addrs[2] = 0x52;
+
+ rc = info->fts_read_reg(info, addrs, 3, buf, 4);
+ if (rc < 0) {
+ tsp_debug_err(info->dev,
+ "%s: Read Fail - Final AFE [Data :"
+ " %2X] AFE Ver [Data : %2X]\n",
+ __func__,
+ buf[0 + doffset],
+ buf[1 + doffset]);
+ return rc;
+ }
+
+ if (buf[0 + doffset])
+ ret = true;
+
+ tsp_debug_info(info->dev,
+ "%s: Final AFE [Data : %2X] AFE Ver "
+ "[Data : %2X]\n",
+ __func__,
+ buf[0 + doffset],
+ buf[1 + doffset]);
+
+ return ret;
+}
+
+int fts_fw_wait_for_specific_event(struct fts_ts_info *info,
+ unsigned char eid0, unsigned char eid1, unsigned char eid2)
+{
+ int rc = 0;
+ unsigned char addrs;
+ unsigned char data[FTS_EVENT_SIZE];
+ int retry = 0;
+
+ memset(data, 0x0, FTS_EVENT_SIZE);
+
+ addrs = READ_ONE_EVENT;
+
+ while (info->fts_read_reg(info, &addrs, 1, (unsigned char *)data,
+ FTS_EVENT_SIZE)) {
+ if (data[0]) {
+ if ((data[0] == eid0) && (data[1] == eid1) &&
+ (data[2] == eid2)) {
+ rc = 0;
+ break;
+ } else {
+ tsp_debug_dbg(info->dev,
+ "%s: %2X, %2X, %2X, %2X\n",
+ __func__, data[0], data[1],
+ data[2], data[3]);
+ }
+ }
+ if (retry++ > FTS_RETRY_COUNT * 15) {
+ rc = -1;
+ tsp_debug_err(info->dev,
+ "%s: Time Over ( %2X, %2X, %2X, %2X )\n",
+ __func__, data[0], data[1],
+ data[2], data[3]);
+ break;
+ }
+ fts_delay(20);
+ }
+
+ return rc;
+}
+
+int fts_fw_wait_for_event(struct fts_ts_info *info, unsigned char eid0,
+ unsigned char eid1)
+{
+ int rc = 0;
+ unsigned char addrs;
+ unsigned char data[FTS_EVENT_SIZE];
+ int retry = 0;
+
+ memset(data, 0x0, FTS_EVENT_SIZE);
+
+ addrs = READ_ONE_EVENT;
+
+ while (info->fts_read_reg(info, &addrs, 1, (unsigned char *)data,
+ FTS_EVENT_SIZE)) {
+ if ((data[0] == EVENTID_STATUS_EVENT) ||
+ (data[0] == EVENTID_ERROR)) {
+ if ((data[0] == EVENTID_STATUS_EVENT) &&
+ (data[1] == eid0) && (data[2] == eid1)) {
+ break;
+ } else if ((data[0] == EVENTID_STATUS_EVENT) &&
+ (data[1] == STATUS_EVENT_FORCE_CAL_DONE)) {
+ break;
+ } else {
+ tsp_debug_dbg(info->dev,
+ "%s: %2X,%2X,%2X,%2X\n",
+ __func__,
+ data[0],
+ data[1],
+ data[2],
+ data[3]);
+ }
+ }
+
+ if (retry++ > FTS_RETRY_COUNT * 15) {
+ rc = -1;
+ tsp_debug_err(info->dev,
+ "%s: Time Over (%2X,%2X,%2X,%2X)\n",
+ __func__,
+ data[0],
+ data[1],
+ data[2],
+ data[3]);
+ break;
+ }
+ fts_delay(20);
+ }
+
+ return rc;
+}
+
+void fts_execute_autotune(struct fts_ts_info *info)
+{
+ int ret = 0;
+ unsigned char regData[4]; /* {0xC1, 0x0E}; */
+ bool bFinalAFE = false;
+ bool NoNeedAutoTune = false; /* default for factory */
+
+ bFinalAFE = get_afe_status(info);
+
+ /* Check flag and decide cx_tune */
+ NoNeedAutoTune = get_pure_autotune_status(info);
+
+ tsp_debug_info(info->dev,
+ "%s: AFE(%d), NoNeedAutoTune(%d)\n", __func__,
+ bFinalAFE, NoNeedAutoTune);
+
+ if ((!NoNeedAutoTune) || (info->o_afe_ver != info->afe_ver)) {
+ info->fts_command(info, CX_TUNNING);
+ fts_delay(300);
+ fts_fw_wait_for_event(info, STATUS_EVENT_MUTUAL_AUTOTUNE_DONE,
+ 0x00);
+
+ info->fts_command(info, SELF_AUTO_TUNE);
+ fts_delay(300);
+ fts_fw_wait_for_event(info, STATUS_EVENT_SELF_AUTOTUNE_DONE,
+ 0x00);
+
+ if (NoNeedAutoTune) {
+ tsp_debug_info(info->dev,
+ "%s: AFE_status(%d) write ( C8 01 )\n",
+ __func__, bFinalAFE);
+
+ regData[0] = 0xC8;
+ regData[1] = 0x01;
+ ret = info->fts_write_reg(info, regData, 2);
+ if (ret < 0) {
+ tsp_debug_err(info->dev,
+ "%s: Flash Back up PureAutotune"
+ "Fail (Clear)\n", __func__);
+ }
+
+ fts_delay(20);
+ fts_fw_wait_for_event(info,
+ STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH,
+ 0x00);
+ }
+
+ info->fts_command(info, FTS_CMD_SAVE_CX_TUNING);
+ fts_delay(230);
+ fts_fw_wait_for_event(info,
+ STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE, 0x00);
+
+ info->fts_command(info, FTS_CMD_SAVE_FWCONFIG);
+ fts_delay(230);
+ fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CONFIG,
+ 0x00);
+
+ /* Reset FTS */
+ info->fts_systemreset(info);
+ fts_delay(20);
+ /* wait for ready event */
+ info->fts_wait_for_ready(info);
+ }
+}
+
+#define FW_IMAGE_NAME_D2_TB_INTEG "tsp_stm/stm_tb_integ.fw"
+#define FW_IMAGE_NAME_D2_Z2A "tsp_stm/stm_z2a.fw"
+#define FW_IMAGE_NAME_D2_Z2I "tsp_stm/stm_z2i.fw"
+#define CONFIG_ID_D1_S 0x2C
+#define CONFIG_ID_D2_TR 0x2E
+#define CONFIG_ID_D2_TB 0x30
+#define CONFIG_OFFSET_BIN_D1 0xf822
+#define CONFIG_OFFSET_BIN_D2 0x1E822
+#define RX_OFFSET_BIN_D2 0x1E834
+#define TX_OFFSET_BIN_D2 0x1E835
+
+#define FW_IMAGE_SIZE_D3 (256 * 1024)
+#define SIGNEDKEY_SIZE (256)
+
+static int wait_for_flash_ready(struct fts_ts_info *info, uint8_t type)
+{
+ uint8_t cmd[2] = {FLASH_CMD_READ_REGISTER, type};
+ uint8_t readData;
+ int i, res = -1;
+
+ tsp_debug_info(info->dev, "[wait_for_flash_ready"
+ " Waiting for flash ready\n");
+
+ for (i = 0; i < 1000 && res != 0; i++) {
+ info->fts_read_reg(info, cmd, sizeof(cmd), &readData, 1);
+ res = readData & 0x80;
+ fts_delay(50);
+ }
+
+ if (i >= 1000 && res != 0) {
+ tsp_debug_err(info->dev, "[wait_for_flash_ready]"
+ " Wait for flash TIMEOUT! ERROR\n");
+ return 0;
+ }
+
+ tsp_debug_info(info->dev, "[wait_for_flash_ready]"
+ " Flash READY!\n");
+
+ return 1;
+}
+
+static int start_flash_dma(struct fts_ts_info *info)
+{
+ int status;
+ uint8_t cmd[3] = {FLASH_CMD_WRITE_REGISTER,
+ FLASH_DMA_CODE0, FLASH_DMA_CODE1};
+
+ tsp_debug_info(info->dev,
+ "[start_flash_dma] Command flash DMA ...\n");
+ info->fts_write_reg(info, cmd, sizeof(cmd));
+
+ status = wait_for_flash_ready(info, FLASH_DMA_CODE0);
+
+ if (status != true) {
+ tsp_debug_err(info->dev,
+ "[start_flash_dma] start_flash_dma: ERROR\n");
+ return false;
+ }
+ tsp_debug_info(info->dev, "[start_flash_dma] flash DMA DONE!\n");
+
+ return true;
+}
+
+static int fillFlash(struct fts_ts_info *info, uint32_t address, uint8_t *data,
+ int size)
+{
+ int remaining;
+ int toWrite = 0;
+ int byteBlock = 0;
+ int wheel = 0;
+ uint32_t addr = 0;
+ int res;
+ int delta;
+
+ uint8_t buff[DMA_CHUNK + 3] = {0};
+
+ remaining = size;
+ while (remaining > 0) {
+ byteBlock = 0;
+ addr = 0;
+ tsp_debug_info(info->dev,
+ "[fillFlash] [%d] Write data to memory.\n",
+ wheel);
+ while (byteBlock < FLASH_CHUNK && remaining > 0) {
+ buff[0] = FLASH_CMD_WRITE_64K;
+ if (remaining >= DMA_CHUNK) {
+ if ((byteBlock + DMA_CHUNK) <= FLASH_CHUNK) {
+ toWrite = DMA_CHUNK;
+ remaining -= DMA_CHUNK;
+ byteBlock += DMA_CHUNK;
+ } else {
+ delta = FLASH_CHUNK - byteBlock;
+ toWrite = delta;
+ remaining -= delta;
+ byteBlock += delta;
+ }
+ } else {
+ if ((byteBlock + remaining) <= FLASH_CHUNK) {
+ toWrite = remaining;
+ byteBlock += remaining;
+ remaining = 0;
+
+ } else {
+ delta = FLASH_CHUNK - byteBlock;
+ toWrite = delta;
+ remaining -= delta;
+ byteBlock += delta;
+ }
+ }
+
+ buff[1] = (uint8_t) ((addr & 0x0000FF00) >> 8);
+ buff[2] = (uint8_t) (addr & 0x000000FF);
+ memcpy(&buff[3], data, toWrite);
+ info->fts_write_reg(info, buff, 3 + toWrite);
+
+ addr += toWrite;
+ data += toWrite;
+ }
+
+ /* configuring the DMA */
+ tsp_debug_info(info->dev,
+ "[fillFlash] [%d] Configure DMA\n", wheel);
+ byteBlock = byteBlock / 4 - 1;
+
+ buff[0] = FLASH_CMD_WRITE_REGISTER;
+ buff[1] = FLASH_DMA_CONFIG;
+ buff[2] = 0x00;
+ buff[3] = 0x00;
+
+ addr = address + ((wheel * FLASH_CHUNK)/4);
+ buff[4] = (uint8_t) ((addr & 0x000000FF));
+ buff[5] = (uint8_t) ((addr & 0x0000FF00) >> 8);
+ buff[6] = (uint8_t) (byteBlock & 0x000000FF);
+ buff[7] = (uint8_t) ((byteBlock & 0x0000FF00) >> 8);
+ buff[8] = 0x00;
+
+ info->fts_write_reg(info, buff, 9);
+ fts_delay(10);
+
+ tsp_debug_info(info->dev,
+ "[fillFlash] [%d] Start flash DMA\n", wheel);
+ res = start_flash_dma(info);
+ if (res < true) {
+ tsp_debug_err(info->dev,
+ "[fillFlash] Error during flashing DMA! ERROR\n");
+ return false;
+ }
+ tsp_debug_info(info->dev,
+ "[fillFlash] [%d] DMA done\n", wheel);
+
+ wheel++;
+ }
+ return true;
+}
+
+uint32_t convU8toU32(uint8_t *src)
+{
+ uint32_t tmpData;
+
+ tmpData = (uint32_t) (((src[3] & 0xFF) << 24) +
+ ((src[2] & 0xFF) << 16) +
+ ((src[1] & 0xFF) << 8) +
+ (src[0] & 0xFF));
+
+ return tmpData;
+}
+
+static int parseBinFile(struct fts_ts_info *info, uint8_t *data,
+ int fw_size,
+ struct FW_FTB_HEADER *fw_header,
+ int keep_cx)
+{
+ int dimension, index;
+ uint32_t temp;
+ int file_type;
+
+ /* start the parsing */
+ index = 0;
+ fw_header->signature = convU8toU32(&data[index]);
+ if (fw_header->signature == FW_HEADER_FTB_SIGNATURE) {
+ tsp_debug_info(info->dev,
+ "[parseBinFile] FW Signature - ftb file\n");
+ file_type = BIN_FTB;
+ } else {
+ tsp_debug_info(info->dev,
+ "[parseBinFile] FW Signature - ftsxxx file. %08X\n",
+ fw_header->signature);
+ file_type = BIN_FTS256;
+ return file_type;
+ }
+
+ index += FW_BYTES_ALLIGN;
+#ifdef FTS_USE_FTB_1
+ fw_header->ftb_ver = convU8toU32(&data[index]);
+ if (fw_header->ftb_ver != FW_FTB_VER) {
+ tsp_debug_err(info->dev,
+ "[parseBinFile] Wrong" " ftb_version %08X ... ERROR\n",
+ fw_header->ftb_ver);
+ return false;
+ }
+#endif /* FTS_USE_FTB_1 */
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->target = convU8toU32(&data[index]);
+ if (fw_header->target != 0x00007036) {
+ tsp_debug_err(info->dev,
+ "[parseBinFile] Wrong target version %08X ... ERROR\n",
+ fw_header->target);
+ return false;
+ }
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->fw_id = convU8toU32(&data[index]);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->fw_ver = convU8toU32(&data[index]);
+ info->fw_version_of_bin = fw_header->fw_ver;
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->cfg_id = convU8toU32(&data[index]);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->cfg_ver = convU8toU32(&data[index]);
+ info->config_version_of_bin = fw_header->cfg_ver;
+
+ index += FW_BYTES_ALLIGN * 3; /* skip 2 reserved data */
+ fw_header->bl_fw_ver = convU8toU32(&data[index]);
+ index += FW_BYTES_ALLIGN;
+
+ fw_header->ext_ver = convU8toU32(&data[index]);
+
+ tsp_debug_info(info->dev,
+ "[parseBinFile] Version : External"
+ " = %04X, FW = %04X, CFG = %04X\n",
+ fw_header->ext_ver,
+ fw_header->fw_ver,
+ fw_header->cfg_ver);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->sec0_size = convU8toU32(&data[index]);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->sec1_size = convU8toU32(&data[index]);
+
+ tsp_debug_info(info->dev,
+ "[parseBinFile] sec0_size = %08X"
+ " (%d bytes), sec1_size = %08X (%d bytes)\n",
+ fw_header->sec0_size,
+ fw_header->sec0_size,
+ fw_header->sec1_size,
+ fw_header->sec1_size);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->sec2_size = convU8toU32(&data[index]);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->sec3_size = convU8toU32(&data[index]);
+
+ tsp_debug_info(info->dev,
+ "[parseBinFile] sec2_size = %08X"
+ " (%d bytes), sec3_size = %08X (%d bytes)\n",
+ fw_header->sec2_size,
+ fw_header->sec2_size,
+ fw_header->sec3_size,
+ fw_header->sec3_size);
+
+ index += FW_BYTES_ALLIGN;
+ fw_header->hdr_crc = convU8toU32(&data[index]);
+
+ if (!keep_cx) {
+ dimension = fw_header->sec0_size + fw_header->sec1_size
+ + fw_header->sec2_size + fw_header->sec3_size;
+
+ temp = fw_size;
+ } else {
+ /* sec2 may contain cx data (future implementation)
+ * sec3 atm not used */
+ dimension = fw_header->sec0_size + fw_header->sec1_size;
+ temp = fw_size - fw_header->sec2_size - fw_header->sec3_size;
+ }
+
+ if (dimension + FW_HEADER_SIZE + FW_BYTES_ALLIGN != temp) {
+ tsp_debug_info(info->dev,
+ "[parseBinFile] Read only %d"
+ " instead of %d... ERROR\n",
+ fw_size, dimension
+ + FW_HEADER_SIZE
+ + FW_BYTES_ALLIGN);
+
+ return false;
+ }
+
+ return file_type;
+}
+
+static int fts_check_erase_done(struct fts_ts_info *info)
+{
+ int timeout = 60; /* 3 sec timeout */
+ unsigned char addrs[2] = {0xF9, 0x02};
+ unsigned char val[1];
+ int rc = 0;
+
+ do {
+ info->fts_read_reg(info, &addrs[0], 2, (unsigned char *)val, 1);
+
+ if ((val[0] & 0x80) != 0x80)
+ break;
+
+ fts_delay(50);
+ timeout--;
+ } while (timeout != 0);
+
+ if (timeout == 0)
+ rc = -1;
+
+ return rc;
+}
+
+int fw_download(struct fts_ts_info *info, uint8_t *pFilename,
+ struct FW_FTB_HEADER *fw_Header, int8_t block_type)
+{
+ uint32_t FTS_TOTAL_SIZE = (256 * 1024); /* Total 256kB */
+ int HEADER_DATA_SIZE = 32;
+
+ int res = 0, rc = 0, i = 0;
+ uint8_t addrs[8] = {0};
+
+ /* System reset */
+ /* System Reset ==> F7 52 34 */
+
+ addrs[0] = 0xF7;
+ addrs[1] = 0x52;
+ addrs[2] = 0x34;
+ info->fts_write_reg(info, &addrs[0], 3);
+ fts_delay(30);
+
+ /* Unlock Flash */
+ /* Unlock Flash Command ==> F7 74 45 */
+ addrs[0] = 0xF7;
+ addrs[1] = 0x74;
+ addrs[2] = 0x45;
+ info->fts_write_reg(info, &addrs[0], 3);
+ fts_delay(100);
+
+ /* Unlock Erase Operation */
+ addrs[0] = 0xFA;
+ addrs[1] = 0x72;
+ addrs[2] = 0x01;
+ info->fts_write_reg(info, &addrs[0], 3);
+ fts_delay(30);
+
+ /* Erase Partial Flash */
+ for (i = 0; i < 64; i++) {
+ /* skip CX2 area (page 61 and page 62) */
+ if ((i == 61) || (i == 62))
+ continue;
+
+ addrs[0] = 0xFA;
+ addrs[1] = 0x02;
+ addrs[2] = (0x80 + i) & 0xFF;
+ info->fts_write_reg(info, &addrs[0], 3);
+ rc = fts_check_erase_done(info);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Unlock Programming operation */
+ addrs[0] = 0xFA;
+ addrs[1] = 0x72;
+ addrs[2] = 0x02;
+ info->fts_write_reg(info, &addrs[0], 3);
+ fts_delay(100);
+
+ /* Write to FLASH */
+ if (block_type == BIN_FTB) {
+ tsp_debug_info(info->dev,
+ "[fw_download] Start sec0 program\n");
+
+ res = fillFlash(info,
+ FLASH_ADDR_CODE,
+ &pFilename[FW_HEADER_SIZE],
+ fw_Header->sec0_size);
+
+ if (res != true) {
+ tsp_debug_err(info->dev,
+ "[fw_download] Error - load sec0 program\n");
+ return false;
+ }
+ tsp_debug_info(info->dev,
+ "[fw_download] load sec0 program DONE!\n");
+ tsp_debug_info(info->dev,
+ "[fw_download] Start sec1 program\n");
+
+ res = fillFlash(info,
+ FLASH_ADDR_CONFIG,
+ &pFilename[FW_HEADER_SIZE +
+ fw_Header->sec0_size],
+ fw_Header->sec1_size);
+
+ if (res != true) {
+ tsp_debug_err(info->dev,
+ "[fw_download] Error - load sec1 program\n");
+ return false;
+ }
+ tsp_debug_info(info->dev,
+ "[fw_download] load sec1 program DONE!\n");
+
+ tsp_debug_info(info->dev,
+ "[fw_download] Flash burn COMPLETED!\n");
+ } else {
+ tsp_debug_info(info->dev,
+ "[fw_download] Start firmware downloading\n");
+ res = fillFlash(info, FLASH_ADDR_CODE,
+ &pFilename[HEADER_DATA_SIZE], FTS_TOTAL_SIZE);
+ if (res != true) {
+ tsp_debug_err(info->dev,
+ "[fw_download] Error - load sec0 program\n");
+ return false;
+ }
+ }
+
+ /* System reset */
+ addrs[0] = 0xF7;
+ addrs[1] = 0x52;
+ addrs[2] = 0x34;
+ info->fts_write_reg(info, &addrs[0], 3);
+ if (fts_cmd_completion_check(info, 0x10, 0x00, 0x00) < 0) {
+ tsp_debug_err(info->dev,
+ "[fw_download] Error - System Reset FAILED\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int fts_fw_compare(struct fts_ts_info *info, const struct firmware *fw)
+{
+ u32 bin_fw_ver_addr_1 = 0;
+ u32 bin_fw_ver_addr_2 = 0;
+ u32 bin_fw_ver_offset = 24;
+ u8 buf[2] = {0};
+ struct fts_version *binary = NULL;
+ struct fts_version *device = &info->ic_fw_ver;
+ int update = 0;
+
+ if ((u32)fw->size < bin_fw_ver_offset) {
+ tsp_debug_err(info->dev,
+ " fw->size(0x%08X) < bin_fw_ver_offset(0x%08X)\n",
+ (u32)fw->size, bin_fw_ver_offset);
+ update = 0;
+ goto error;
+ }
+
+ bin_fw_ver_addr_1 = (u32)fw->size - bin_fw_ver_offset;
+ bin_fw_ver_addr_2 = bin_fw_ver_addr_1 + 1;
+ tsp_debug_info(info->dev,
+ "%s: bin_fw_ver_addr_1 = 0x%08X , bin_fw_ver_addr_2 = 0x%08X\n",
+ __func__, bin_fw_ver_addr_1, bin_fw_ver_addr_2);
+
+ binary = kzalloc(sizeof(struct fts_version), GFP_KERNEL);
+ if (binary == NULL) {
+ tsp_debug_err(info->dev, "failed to kzalloc binary\n");
+ update = 0;
+ goto error;
+ }
+
+ buf[0] = fw->data[bin_fw_ver_addr_1];
+ buf[1] = fw->data[bin_fw_ver_addr_2];
+
+ binary->build = (buf[0] >> 4) & 0x0F;
+ binary->major = buf[0] & 0x0F;
+ binary->minor = buf[1];
+
+ if (binary->major != device->major) {
+ update = 1;
+ } else {
+ if (binary->minor != device->minor)
+ update = 1;
+ else if (binary->build > device->build)
+ update = 1;
+ }
+
+ tsp_debug_info(info->dev,
+ "%s : binary[%d.%02d.%d] device[%d.%02d.%d]"
+ " -> update: %d\n", __func__,
+ binary->major, binary->minor, binary->build,
+ device->major, device->minor, device->build,
+ update);
+
+error:
+ if (binary)
+ kfree(binary);
+
+ return update;
+}
+
+void fts_fw_init(struct fts_ts_info *info)
+{
+ tsp_debug_info(info->dev, "%s\n", __func__);
+
+ info->fts_command(info, FTS_CMD_TRIM_LOW_POWER_OSCILLATOR);
+ fts_delay(200);
+ info->fts_command(info, FTS_CMD_SAVE_CX_TUNING);
+ fts_delay(230);
+ fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE, 0x00);
+
+ fts_get_afe_info(info);
+
+ fts_execute_autotune(info);
+
+ info->fts_command(info, SENSEON);
+
+ fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE, 0x00);
+
+ info->fts_interrupt_set(info, INT_ENABLE);
+}
+
+static int fts_fw_check(struct fts_ts_info *info)
+{
+ int retval = 0;
+
+ retval = fts_systemreset(info);
+ if (retval < 0)
+ return retval;
+
+ retval = fts_wait_for_ready(info);
+ if (retval < 0)
+ return retval;
+
+ retval = fts_read_chip_id(info);
+ if (retval < 0)
+ return retval;
+
+ return retval;
+}
+
+static int fts_fw_update(struct fts_ts_info *info)
+{
+ const struct firmware *fw_entry = NULL;
+ unsigned char *fw_data = NULL;
+ char fw_path[FTS_MAX_FW_PATH];
+ const struct FW_FTB_HEADER *header;
+ int fw_size;
+ int fw_type;
+ int keep_cx;
+ int retval = 0;
+ struct FW_FTB_HEADER fw_ftbHeader;
+
+ if (info->fts_power_state != FTS_POWER_STATE_ACTIVE) {
+ tsp_debug_err(info->dev,
+ "%s : FTS_POWER_STATE is not ACTIVE\n", __func__);
+ return -EPERM;
+ }
+
+ if (info->test_fwpath[0]) {
+ strlcpy(fw_path, &info->test_fwpath[0], sizeof(fw_path));
+ } else if(info->board->firmware_name) {
+ /* A pointer and size of buffer for binary file */
+ strlcpy(fw_path, &info->board->firmware_name[0], sizeof(fw_path));
+ } else {
+ tsp_debug_err(info->dev, "%s : no firmware file\n", __func__);
+ return -EPERM;
+ }
+
+ tsp_debug_info(info->dev,
+ "%s : firmware name : %s\n", __func__, fw_path);
+
+ retval = request_firmware(&fw_entry, fw_path, info->dev);
+ if (retval) {
+ tsp_debug_err(info->dev,
+ "%s : Firmware image %s not available\n", __func__,
+ fw_path);
+ return retval;
+ }
+
+ if (!fts_fw_compare(info, fw_entry)) {
+ tsp_debug_info(info->dev,
+ "%s : skip fw_upgrade(ic_fw_ver == bin_fw_ver)\n",
+ __func__);
+ goto out;
+ }
+
+ fw_size = fw_entry->size;
+ fw_data = (unsigned char *)fw_entry->data;
+ header = (struct FW_FTB_HEADER *)fw_data;
+
+ info->fw_version_of_bin = header->fw_ver;
+ info->config_version_of_bin = header->cfg_ver;
+ /* saver previous afe version before downloading */
+ info->o_afe_ver = info->afe_ver;
+#ifdef FTS_FTB_STYLE_2
+ info->fw_main_version_of_bin =
+ ((header->ext_ver & 0xff)<<8) +
+ ((header->ext_ver >> 8) & 0xff);
+
+ tsp_debug_info(info->dev,
+ "Bin Firmware Version : 0x%04X "
+ "Bin Config Version : 0x%04X "
+ "Bin Main Firmware Version : 0x%04X ",
+ info->fw_version_of_bin,
+ info->config_version_of_bin,
+ info->fw_main_version_of_bin);
+#else /* FTS_FTB_STYLE_2 */
+ tsp_debug_info(info->dev,
+ "Bin Firmware Version : 0x%04X "
+ "Bin Config Version : 0x%04X ",
+ info->fw_version_of_bin,
+ info->config_version_of_bin);
+#endif
+ memcpy(&fw_ftbHeader, fw_data, sizeof(struct FW_FTB_HEADER));
+
+ tsp_debug_info(info->dev,
+ "[flashProcedure] Firmware size : %d\n", fw_size);
+ keep_cx = 0;
+
+ fw_type = parseBinFile(info, fw_data, fw_size, &fw_ftbHeader, keep_cx);
+ if (fw_type == false) {
+ tsp_debug_err(info->dev,
+ "[flashProcedure] Error - FW is not appreciate\n");
+ retval = -EINVAL;
+ goto out;
+ }
+
+ retval = fw_download(info, fw_data, &fw_ftbHeader, fw_type);
+ if (retval == 0) {
+ tsp_debug_err(info->dev,
+ "[flashProcedure] Error - Firmware update is not completed.\n");
+ retval = -EIO;
+ goto out;
+ }
+
+ fts_fw_init(info);
+ retval = fts_fw_check(info);
+ if (retval < 0 ||
+ info->flash_corruption_info.fw_broken ||
+ info->flash_corruption_info.cfg_broken ||
+ info->flash_corruption_info.cx_broken) {
+ retval = -EIO;
+ goto out;
+ }
+
+ fts_get_version_info(info);
+ if (fts_fw_compare(info, fw_entry)) {
+ tsp_debug_err(info->dev,
+ "[flashProcedure] Firmware update failed\n");
+ retval = -EIO;
+ goto out;
+ }
+
+ tsp_debug_info(info->dev,
+ "[flashProcedure] Firmware update is done successfully.\n");
+ retval = 0;
+out:
+ if (fw_entry)
+ release_firmware(fw_entry);
+ return retval;
+}
+
+int fts_fw_verify_update(struct fts_ts_info *info)
+{
+ int retry = 0;
+
+ info->fts_irq_enable(info, false);
+ while (retry++ < FTS_FW_UPDATE_RETRY) {
+ tsp_debug_info(info->dev,
+ "[fw_update] try:%d\n", retry);
+ if (0 == fts_fw_update(info)) {
+ info->fts_irq_enable(info, true);
+ return 0;
+ }
+ }
+ info->fts_irq_enable(info, true);
+ return -EIO;
+}
+EXPORT_SYMBOL(fts_fw_verify_update);
diff --git a/drivers/input/touchscreen/stm/ftm4_pdc.c b/drivers/input/touchscreen/stm/ftm4_pdc.c
new file mode 100644
index 00000000000..83daa211f09
--- /dev/null
+++ b/drivers/input/touchscreen/stm/ftm4_pdc.c
@@ -0,0 +1,2265 @@
+/******************** (C) COPYRIGHT 2012 STMicroelectronics ********************
+*
+* File Name : ftm4_pdc.c
+* Authors : AMS(Analog Mems Sensor) Team
+* Description : FTS Capacitive touch screen controller (FingerTipS)
+*
+********************************************************************************
+*
+* 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.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+*******************************************************************************/
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include "ftm4_ts.h"
+
+#define TSP_FACTEST_RESULT_PASS 2
+#define TSP_FACTEST_RESULT_FAIL 1
+#define TSP_FACTEST_RESULT_NONE 0
+
+#define BUFFER_MAX ((256 * 1024) - 16)
+#define READ_CHUNK_SIZE 128
+
+#define FTS_F_WIX1_ADDR 0x1FE7
+#define FTS_S_WIX1_ADDR 0x1FE8
+#define FTS_F_WIX2_ADDR 0x18FD
+#define FTS_S_WIX2_ADDR 0x1929
+#define FTS_WATER_SELF_RAW_ADDR 0x1E
+
+#define FTS_MAX_TX_LENGTH 44
+#define FTS_MAX_RX_LENGTH 64
+
+#define FTS_CX2_READ_LENGTH 4
+#define FTS_CX2_ADDR_OFFSET 3
+#define FTS_CX2_TX_START 0
+#define FTS_CX2_BASE_ADDR 0x1000
+#define SEC_CMD_STR_LEN 12
+
+#define DEBUG_MSG 1
+enum {
+ TYPE_RAW_DATA = 0,
+ TYPE_FILTERED_DATA = 2,
+ TYPE_STRENGTH_DATA = 4,
+ TYPE_BASELINE_DATA = 6
+};
+
+enum {
+ BUILT_IN = 0,
+ UMS,
+};
+
+enum CMD_STATUS {
+ CMD_STATUS_WAITING = 0,
+ CMD_STATUS_RUNNING,
+ CMD_STATUS_OK,
+ CMD_STATUS_FAIL,
+ CMD_STATUS_NOT_APPLICABLE,
+};
+
+static void get_fw_ver_bin(void *device_data);
+static void get_fw_ver_ic(void *device_data);
+static void get_config_ver(void *device_data);
+static void get_threshold(void *device_data);
+static void get_x_num(void *device_data);
+static void get_y_num(void *device_data);
+static void run_rawcap_read(void *device_data);
+static void get_rawcap(void *device_data);
+static void run_ix_data_read(void *device_data);
+static void run_ix_data_read_all(void *device_data);
+static void run_self_raw_read(void *device_data);
+static void run_self_raw_read_all(void *device_data);
+static void get_cx_data(void *device_data);
+static void run_cx_data_read(void *device_data);
+static void get_cx_all_data(void *device_data);
+static void get_strength_all_data(void *device_data);
+static void set_tsp_test_result(void *device_data);
+static void get_tsp_test_result(void *device_data);
+static void run_trx_short_test(void *device_data);
+static void report_rate(void *device_data);
+static void delay(void *device_data);
+static void debug(void *device_data);
+static void run_autotune_enable(void *device_data);
+static void run_autotune(void *device_data);
+static void not_support_cmd(void *device_data);
+
+static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count);
+static ssize_t show_cmd_status(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t show_cmd_result(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t cmd_list_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t store_upgrade(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t store_check_fw(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t show_version_info(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+static void tui_mode_cmd(struct fts_ts_info *info);
+#endif
+
+struct fts_cmd fts_commands[] = {
+ {FTS_CMD("get_fw_ver_bin", get_fw_ver_bin),},
+ {FTS_CMD("get_fw_ver_ic", get_fw_ver_ic),},
+ {FTS_CMD("get_config_ver", get_config_ver),},
+ {FTS_CMD("get_threshold", get_threshold),},
+ {FTS_CMD("get_x_num", get_x_num),},
+ {FTS_CMD("get_y_num", get_y_num),},
+ {FTS_CMD("run_rawcap_read", run_rawcap_read),},
+ {FTS_CMD("get_rawcap", get_rawcap),},
+ {FTS_CMD("run_ix_data_read", run_ix_data_read),},
+ {FTS_CMD("run_ix_data_read_all", run_ix_data_read_all),},
+ {FTS_CMD("run_self_raw_read", run_self_raw_read),},
+ {FTS_CMD("run_self_raw_read_all", run_self_raw_read_all),},
+ {FTS_CMD("get_cx_data", get_cx_data),},
+ {FTS_CMD("run_cx_data_read", run_cx_data_read),},
+ {FTS_CMD("get_cx_all_data", get_cx_all_data),},
+ {FTS_CMD("get_strength_all_data", get_strength_all_data),},
+ {FTS_CMD("set_tsp_test_result", set_tsp_test_result),},
+ {FTS_CMD("get_tsp_test_result", get_tsp_test_result),},
+ {FTS_CMD("report_rate", report_rate),},
+ {FTS_CMD("delay", delay),},
+ {FTS_CMD("debug", debug),},
+ {FTS_CMD("run_autotune_enable", run_autotune_enable),},
+ {FTS_CMD("run_autotune", run_autotune),},
+ {FTS_CMD("run_trx_short_test", run_trx_short_test),},
+ {FTS_CMD("not_support_cmd", not_support_cmd),},
+};
+
+static DEVICE_ATTR(cmd, S_IWUSR | S_IWGRP, NULL, store_cmd);
+static DEVICE_ATTR(cmd_status, S_IRUGO, show_cmd_status, NULL);
+static DEVICE_ATTR(cmd_result, S_IRUGO, show_cmd_result, NULL);
+static DEVICE_ATTR(cmd_list, S_IRUGO, cmd_list_show, NULL);
+static DEVICE_ATTR(fw_upgrade, S_IWUSR | S_IWGRP, NULL, store_upgrade);
+static DEVICE_ATTR(check_fw, S_IWUSR | S_IWGRP, NULL, store_check_fw);
+static DEVICE_ATTR(version, S_IRUGO, show_version_info, NULL);
+
+static struct attribute *touch_pdc_attributes[] = {
+ &dev_attr_cmd.attr,
+ &dev_attr_cmd_status.attr,
+ &dev_attr_cmd_result.attr,
+ &dev_attr_cmd_list.attr,
+ &dev_attr_fw_upgrade.attr,
+ &dev_attr_check_fw.attr,
+ &dev_attr_version.attr,
+ NULL,
+};
+
+static struct attribute_group touch_pdc_attr_group = {
+ .attrs = touch_pdc_attributes,
+};
+
+static ssize_t store_check_fw(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ unsigned int input = 0;
+ int ret = 0;
+
+ if (sscanf(buf, "%u", &input) != 1) {
+ tsp_debug_err(&info->client->dev, "%s: Invalid argument\n", __func__);
+ return -EINVAL;
+ }
+
+ if (input) {
+ mutex_lock(&info->device_mutex);
+
+ info->test_fwpath[0] = '\0';
+ ret = fts_fw_verify_update(info);
+
+ mutex_unlock(&info->device_mutex);
+ }
+
+ if (ret)
+ return ret;
+ else
+ return count;
+}
+
+static ssize_t store_upgrade(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ int ret = 0;
+
+ if (strlcpy(&info->test_fwpath[0], buf, count) <= 0) {
+ tsp_debug_err(&info->client->dev, "%s: invalid firmware name\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&info->device_mutex);
+
+ ret = fts_fw_verify_update(info);
+ info->test_fwpath[0] = '\0';
+
+ mutex_unlock(&info->device_mutex);
+
+ if (ret)
+ return ret;
+ else
+ return count;
+}
+
+static ssize_t show_version_info(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ int offset = 0;
+ char str[16] = {0};
+ int ret = 0;
+
+ mutex_lock(&info->device_mutex);
+
+ if (fts_get_version_info(info) < 0) {
+ mutex_unlock(&info->device_mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&info->device_mutex);
+
+ ret += snprintf(str + ret, sizeof(str) - ret,
+ "v%d.%02d", info->ic_fw_ver.major, info->ic_fw_ver.minor);
+
+ if (info->ic_fw_ver.build) {
+ ret += snprintf(str + ret, sizeof(str) - ret,
+ ".%d", info->ic_fw_ver.build);
+ }
+
+ offset += snprintf(buf + offset, PAGE_SIZE - offset, "%s\n", str);
+
+ return offset;
+}
+
+static int fts_check_index(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ int node;
+
+ if (info->cmd_param[0] < 0 ||
+ info->cmd_param[0] >= info->SenseChannelLength ||
+ info->cmd_param[1] < 0 ||
+ info->cmd_param[1] >= info->ForceChannelLength) {
+ snprintf(buff, sizeof(buff), "%s", "NG");
+ strncat(info->cmd_result, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_FAIL;
+ tsp_debug_info(&info->client->dev,
+ "%s: parameter error: %u,%u\n",
+ __func__, info->cmd_param[0], info->cmd_param[1]);
+ node = -1;
+ return node;
+ }
+ node = info->cmd_param[1] * info->SenseChannelLength +
+ info->cmd_param[0];
+ tsp_debug_info(&info->client->dev, "%s: node = %d\n", __func__, node);
+ return node;
+}
+
+static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ char *cur, *start, *end;
+ char buff[CMD_STR_LEN] = { 0 };
+ int len, i;
+ struct fts_cmd *ft_cmd_ptr = NULL;
+ char delim = ',';
+ bool cmd_found = false;
+ int param_cnt = 0;
+
+ if (!info) {
+ tsp_debug_err(&info->client->dev,
+ "%s: No platform data found\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!info->input_dev) {
+ tsp_debug_err(&info->client->dev,
+ "%s: No input_dev data found\n", __func__);
+ return -EINVAL;
+ }
+
+ if (count > CMD_STR_LEN) {
+ tsp_debug_err(&info->client->dev,
+ "%s: overflow command length\n", __func__);
+ return -EINVAL;
+ }
+
+ if (info->cmd_is_running == true) {
+ tsp_debug_err(&info->client->dev,
+ "ft_cmd: other cmd is running.\n");
+ if (strncmp("clear_cover_mode", buf, 16) == 0) {
+ cancel_delayed_work(&info->cover_cmd_work);
+ tsp_debug_err(&info->client->dev,
+ "[cmd is delayed] %d, param = %d, %d\n",
+ __LINE__, buf[17]-'0', buf[19]-'0');
+ info->delayed_cmd_param[0] = buf[17]-'0';
+ if (info->delayed_cmd_param[0] > 1)
+ info->delayed_cmd_param[1] = buf[19]-'0';
+
+ schedule_delayed_work(&info->cover_cmd_work,
+ msecs_to_jiffies(10));
+ }
+ return -EBUSY;
+ } else if (info->reinit_done == false) {
+ tsp_debug_err(&info->client->dev,
+ "ft_cmd: reinit is working\n");
+ if (strncmp("clear_cover_mode", buf, 16) == 0) {
+ cancel_delayed_work(&info->cover_cmd_work);
+ tsp_debug_err(&info->client->dev,
+ "[cmd is delayed] %d, param = %d, %d\n",
+ __LINE__, buf[17]-'0', buf[19]-'0');
+ info->delayed_cmd_param[0] = buf[17]-'0';
+ if (info->delayed_cmd_param[0] > 1)
+ info->delayed_cmd_param[1] = buf[19]-'0';
+
+ if (info->delayed_cmd_param[0] == 0)
+ schedule_delayed_work(&info->cover_cmd_work,
+ msecs_to_jiffies(300));
+ }
+ }
+
+ /* check lock */
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = true;
+ mutex_unlock(&info->cmd_lock);
+ info->cmd_state = 1;
+ memset(info->cmd_param, 0x00, ARRAY_SIZE(info->cmd_param));
+
+ len = (int)count;
+ if (*(buf + len - 1) == '\n')
+ len--;
+ memset(info->cmd, 0x00, ARRAY_SIZE(info->cmd));
+ memcpy(info->cmd, buf, len);
+ cur = strchr(buf, (int)delim);
+ if (cur)
+ memcpy(buff, buf, cur - buf);
+
+ else
+ memcpy(buff, buf, len);
+ tsp_debug_info(&info->client->dev, "COMMAND : %s\n", buff);
+
+ /* find command */
+ list_for_each_entry(ft_cmd_ptr, &info->cmd_list_head, list) {
+ if (!strncmp(buff, ft_cmd_ptr->cmd_name, CMD_STR_LEN)) {
+ cmd_found = true;
+ break;
+ }
+ }
+
+ /* set not_support_cmd */
+ if (!cmd_found) {
+ list_for_each_entry(ft_cmd_ptr, &info->cmd_list_head, list) {
+ if (!strncmp
+ ("not_support_cmd", ft_cmd_ptr->cmd_name,
+ CMD_STR_LEN))
+ break;
+ }
+ }
+
+ /* parsing parameters */
+ if (cur && cmd_found) {
+ cur++;
+ start = cur;
+ memset(buff, 0x00, ARRAY_SIZE(buff));
+
+ do {
+ if (*cur == delim || cur - buf == len) {
+ end = cur;
+ memcpy(buff, start, end - start);
+ *(buff + strnlen(buff, ARRAY_SIZE(buff))) =
+ '\0';
+ if (kstrtoint
+ (buff, 10,
+ info->cmd_param + param_cnt) < 0)
+ goto err_out;
+ start = cur + 1;
+ memset(buff, 0x00, ARRAY_SIZE(buff));
+ param_cnt++;
+ }
+ cur++;
+ } while (cur - buf <= len);
+ }
+ tsp_debug_info(&info->client->dev, "cmd = %s\n", ft_cmd_ptr->cmd_name);
+ for (i = 0; i < param_cnt; i++)
+ tsp_debug_info(&info->client->dev, "cmd param %d= %d\n", i,
+ info->cmd_param[i]);
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode())
+ tui_mode_cmd(info);
+ else
+#endif
+ ft_cmd_ptr->cmd_func(info);
+
+err_out:
+ return count;
+}
+
+static ssize_t show_cmd_status(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ char buff[16] = {0};
+
+ if (!info) {
+ tsp_debug_err(&info->client->dev,
+ "%s: No platform data found\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!info->input_dev) {
+ tsp_debug_err(&info->client->dev,
+ "%s: No input_dev data found\n", __func__);
+ return -EINVAL;
+ }
+
+ tsp_debug_info(&info->client->dev, "tsp cmd: status:%d\n", info->cmd_state);
+ if (info->cmd_state == CMD_STATUS_WAITING)
+ snprintf(buff, sizeof(buff), "WAITING");
+
+ else if (info->cmd_state == CMD_STATUS_RUNNING)
+ snprintf(buff, sizeof(buff), "RUNNING");
+
+ else if (info->cmd_state == CMD_STATUS_OK)
+ snprintf(buff, sizeof(buff), "OK");
+
+ else if (info->cmd_state == CMD_STATUS_FAIL)
+ snprintf(buff, sizeof(buff), "FAIL");
+
+ else if (info->cmd_state == CMD_STATUS_NOT_APPLICABLE)
+ snprintf(buff, sizeof(buff), "NOT_APPLICABLE");
+ return snprintf(buf, TSP_BUF_SIZE, "%s\n", buff);
+}
+
+static ssize_t show_cmd_result(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ if (!info) {
+ tsp_debug_err(&info->client->dev,
+ "%s: No platform data found\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!info->input_dev) {
+ tsp_debug_err(&info->client->dev,
+ "%s: No input_dev data found\n", __func__);
+ return -EINVAL;
+ }
+
+ tsp_debug_info(&info->client->dev, "tsp cmd: result: %s\n",
+ info->cmd_result);
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+ info->cmd_state = 0;
+ return snprintf(buf, TSP_BUF_SIZE, "%s\n", info->cmd_result);
+}
+
+static ssize_t cmd_list_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ int ii = 0;
+ char buffer[info->cmd_buf_size+CMD_STR_LEN];
+ char buffer_name[CMD_STR_LEN];
+
+ snprintf(buffer, CMD_STR_LEN, "++factory command list++\n");
+ while (strncmp(fts_commands[ii].cmd_name, "not_support_cmd", 16) != 0) {
+ snprintf(buffer_name, CMD_STR_LEN,
+ "%s\n", fts_commands[ii].cmd_name);
+ strcat(buffer, buffer_name);
+ ii++;
+ }
+
+ tsp_debug_info(&info->client->dev,
+ "%s: length : %u / %d\n", __func__,
+ (unsigned int)strlen(buffer), info->cmd_buf_size+CMD_STR_LEN);
+
+ return snprintf(buf, TSP_BUF_SIZE, "%s\n", buffer);
+}
+
+static void set_default_result(struct fts_ts_info *info)
+{
+ char delim = ':';
+
+ memset(info->cmd_result, 0x00, ARRAY_SIZE(info->cmd_result));
+ memcpy(info->cmd_result, info->cmd, strnlen(info->cmd, CMD_STR_LEN));
+ strncat(info->cmd_result, &delim, 1);
+}
+
+static void set_cmd_result(struct fts_ts_info *info, char *buff, int len)
+{
+ strncat(info->cmd_result, buff, len);
+}
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+static void tui_mode_cmd(struct fts_ts_info *info)
+{
+ char buff[16] = "TUImode:FAIL";
+
+ set_default_result(info);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+#endif
+
+static void not_support_cmd(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[16] = {0};
+
+ set_default_result(info);
+ snprintf(buff, sizeof(buff), "%s", "NA");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ tsp_debug_info(&info->client->dev, "%s: \"%s\"\n", __func__, buff);
+}
+
+void procedure_cmd_event(struct fts_ts_info *info, unsigned char *data)
+{
+ char buff[16] = {0};
+
+ if ((data[1] == 0x00) && (data[2] == 0x62)) {
+ snprintf(buff, sizeof(buff), "%d",
+ *(unsigned short *)&data[3]);
+ tsp_debug_info(&info->client->dev, "%s: %s\n", "get_threshold", buff);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+
+ } else if ((data[1] == 0x07) && (data[2] == 0xE7)) {
+ if (data[3] <= TSP_FACTEST_RESULT_PASS) {
+ sprintf(buff, "%s",
+ data[3] == TSP_FACTEST_RESULT_PASS ? "PASS" :
+ data[3] == TSP_FACTEST_RESULT_FAIL ? "FAIL" : "NONE");
+ tsp_debug_info(&info->client->dev,
+ "%s: success [%s][%d]", "get_tsp_test_result",
+ data[3] == TSP_FACTEST_RESULT_PASS ? "PASS" :
+ data[3] == TSP_FACTEST_RESULT_FAIL ? "FAIL" :
+ "NONE", data[3]);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ } else {
+ snprintf(buff, sizeof(buff), "%s", "NG");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_FAIL;
+ tsp_debug_info(&info->client->dev, "%s: %s\n",
+ "get_tsp_test_result",
+ buff);
+ }
+ }
+}
+EXPORT_SYMBOL(procedure_cmd_event);
+
+void fts_print_frame(struct fts_ts_info *info, short *min, short *max)
+{
+ int i = 0;
+ int j = 0;
+ unsigned char *pStr = NULL;
+ unsigned char pTmp[16] = {0};
+
+ pStr = kzalloc(6 * (info->SenseChannelLength + 1), GFP_KERNEL);
+ if (pStr == NULL) {
+ tsp_debug_info(&info->client->dev, "FTS pStr kzalloc failed\n");
+ return;
+ }
+
+ memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
+ snprintf(pTmp, sizeof(pTmp), " ");
+ strncat(pStr, pTmp, 6 * info->SenseChannelLength);
+
+ for (i = 0; i < info->SenseChannelLength; i++) {
+ snprintf(pTmp, sizeof(pTmp), "Rx%02d ", i);
+ strncat(pStr, pTmp, 6 * info->SenseChannelLength);
+ }
+
+ tsp_debug_info(&info->client->dev, "FTS %s\n", pStr);
+ memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
+ snprintf(pTmp, sizeof(pTmp), " +");
+ strncat(pStr, pTmp, 6 * info->SenseChannelLength);
+
+ for (i = 0; i < info->SenseChannelLength; i++) {
+ snprintf(pTmp, sizeof(pTmp), "------");
+ strncat(pStr, pTmp, 6 * info->SenseChannelLength);
+ }
+
+ tsp_debug_info(&info->client->dev, "FTS %s\n", pStr);
+
+ for (i = 0; i < info->ForceChannelLength; i++) {
+ memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
+ snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", i);
+ strncat(pStr, pTmp, 6 * info->SenseChannelLength);
+
+ for (j = 0; j < info->SenseChannelLength; j++) {
+ snprintf(pTmp, sizeof(pTmp), "%5d ",
+ info->pFrame[(i * info->SenseChannelLength) + j]);
+
+ if (i > 0) {
+ if (info->pFrame[(i * info->SenseChannelLength) + j] < *min)
+ *min = info->pFrame[(i * info->SenseChannelLength) + j];
+
+ if (info->pFrame[(i * info->SenseChannelLength) + j] > *max)
+ *max = info->pFrame[(i * info->SenseChannelLength) + j];
+ }
+ strncat(pStr, pTmp, 6 * info->SenseChannelLength);
+ }
+ tsp_debug_info(&info->client->dev, "FTS %s\n", pStr);
+ }
+
+ kfree(pStr);
+}
+
+static int fts_panel_ito_test(struct fts_ts_info *info)
+{
+ unsigned char cmd = READ_ONE_EVENT;
+ unsigned char data[FTS_EVENT_SIZE];
+ unsigned char regAdd[4] = {0xB0, 0x03, 0x60, 0xFB};
+ unsigned char wregAdd[3] = {0xA7, 0x01, 0x00};
+ uint8_t *errortypes[16] = {
+ "F open", "S open", "F2G short", "S2G short", "F2V short",
+ "S2V short", "F2F short", "S2S short", "F2S short",
+ "FPC F open", "FPC S open", "Key F open", "Key S open",
+ "Reserved", "Reserved", "Reserved"};
+ int retry = 0;
+ int result = -1;
+
+ info->fts_systemreset(info);
+ info->fts_wait_for_ready(info);
+ info->fts_irq_enable(info, false);
+ info->fts_interrupt_set(info, INT_DISABLE);
+ info->fts_write_reg(info, &regAdd[0], 4);
+ info->fts_command(info, FLUSHBUFFER);
+ info->fts_write_reg(info, &wregAdd[0], 3);
+ fts_delay(200);
+ memset(data, 0x0, FTS_EVENT_SIZE);
+ while (info->fts_read_reg
+ (info, &cmd, 1, (unsigned char *)data, FTS_EVENT_SIZE)) {
+ if ((data[0] == 0x0F) && (data[1] == 0x05)) {
+ switch (data[2]) {
+ case NO_ERROR:
+ if (data[3] == 0x00) {
+ tsp_debug_info(
+ &info->client->dev,
+ "ITO open / short test PASS!!\n");
+ return 1;
+ }
+ break;
+ case ITO_FORCE_OPEN:
+ case ITO_SENSE_OPEN:
+ case ITO_FORCE_SHRT_GND:
+ case ITO_SENSE_SHRT_GND:
+ case ITO_FORCE_SHRT_VCM:
+ case ITO_SENSE_SHRT_VCM:
+ case ITO_FORCE_SHRT_FORCE:
+ case ITO_SENSE_SHRT_SENSE:
+ case ITO_F2E_SENSE:
+ case ITO_FPC_FORCE_OPEN:
+ case ITO_FPC_SENSE_OPEN:
+ case ITO_KEY_FORCE_OPEN:
+ case ITO_KEY_SENSE_OPEN:
+ case ITO_RESERVED0:
+ case ITO_RESERVED1:
+ case ITO_RESERVED2:
+ case ITO_MAX_ERR_REACHED:
+ tsp_debug_info(
+ &info->client->dev,
+ "ITO open / short test FAIL!! Error Type : %s, Channel : %d\n",
+ errortypes[data[2]], data[3]);
+ break;
+ }
+ break;
+ }
+ if (retry++ > 30) {
+ tsp_debug_info(&info->client->dev,
+ "Time over - wait for result of ITO test\n");
+ break;
+ }
+ fts_delay(10);
+ }
+ info->fts_systemreset(info);
+ info->fts_wait_for_ready(info);
+ info->fts_command(info, SENSEON);
+ info->touch_count = 0;
+ info->fts_command(info, FLUSHBUFFER);
+ info->fts_interrupt_set(info, INT_ENABLE);
+ info->fts_irq_enable(info, true);
+ return result;
+}
+int fts_read_frame(struct fts_ts_info *info, unsigned char type, short *min,
+ short *max)
+{
+ unsigned char pFrameAddress[8] = {
+ 0xD0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
+ unsigned int FrameAddress = 0;
+ unsigned int writeAddr = 0;
+ unsigned int start_addr = 0;
+ unsigned int end_addr = 0;
+ unsigned int totalbytes = 0;
+ unsigned int remained = 0;
+ unsigned int readbytes = 0xFF;
+ unsigned int dataposition = 0;
+ unsigned char *pRead = NULL;
+ int rc = 0;
+ int ret = 0;
+ int i = 0;
+
+ tsp_debug_info(&info->client->dev,
+ "===> fts_read_frame digital rev( %d ) sense ( %d ) force (%d)\n",
+ info->digital_rev, info->SenseChannelLength, info->ForceChannelLength);
+
+ pRead = kzalloc(BUFFER_MAX, GFP_KERNEL);
+ if (pRead == NULL) {
+ tsp_debug_info(&info->client->dev,
+ "FTS pRead kzalloc failed\n");
+ rc = 1;
+ goto ErrorExit;
+ }
+
+ pFrameAddress[2] = type;
+ totalbytes = info->SenseChannelLength * info->ForceChannelLength * 2;
+ ret = info->fts_read_reg(info, &pFrameAddress[0], 3, pRead, pFrameAddress[3]);
+
+ if (ret > 0) {
+ if (info->digital_rev == FTS_DIGITAL_REV_1)
+ FrameAddress = pRead[0] + (pRead[1] << 8);
+ else if (info->digital_rev == FTS_DIGITAL_REV_2)
+ FrameAddress = pRead[1] + (pRead[2] << 8);
+
+ start_addr = FrameAddress+info->SenseChannelLength * 2;
+ end_addr = start_addr + totalbytes;
+ } else {
+ tsp_debug_info(&info->client->dev,
+ "FTS read failed rc = %d\n", ret);
+ rc = 2;
+ goto ErrorExit;
+ }
+
+#ifdef DEBUG_MSG
+ tsp_debug_info(&info->client->dev,
+ "FTS FrameAddress = %X\n", FrameAddress);
+ tsp_debug_info(&info->client->dev,
+ "FTS start_addr = %X, end_addr = %X\n",
+ start_addr, end_addr);
+#endif
+
+ remained = totalbytes;
+ for (writeAddr = start_addr; writeAddr < end_addr;
+ writeAddr += READ_CHUNK_SIZE) {
+ pFrameAddress[1] = (writeAddr >> 8) & 0xFF;
+ pFrameAddress[2] = writeAddr & 0xFF;
+
+ if (remained >= READ_CHUNK_SIZE)
+ readbytes = READ_CHUNK_SIZE;
+ else
+ readbytes = remained;
+
+ memset(pRead, 0x0, readbytes);
+
+#ifdef DEBUG_MSG
+ tsp_debug_info(&info->client->dev,
+ "FTS %02X%02X%02X readbytes=%d\n",
+ pFrameAddress[0], pFrameAddress[1],
+ pFrameAddress[2], readbytes);
+
+#endif
+ if (info->digital_rev == FTS_DIGITAL_REV_1) {
+ info->fts_read_reg(info, &pFrameAddress[0],
+ 3, pRead, readbytes);
+ remained -= readbytes;
+
+ for (i = 0; i < readbytes; i += 2) {
+ info->pFrame[dataposition++] =
+ pRead[i] + (pRead[i + 1] << 8);
+ }
+ } else if (info->digital_rev == FTS_DIGITAL_REV_2) {
+ info->fts_read_reg(info, &pFrameAddress[0],
+ 3, pRead, readbytes + 1);
+ remained -= readbytes;
+
+ for (i = 1; i < (readbytes+1); i += 2) {
+ info->pFrame[dataposition++] =
+ pRead[i] + (pRead[i + 1] << 8);
+ }
+ }
+ }
+ kfree(pRead);
+
+#ifdef DEBUG_MSG
+ tsp_debug_info(&info->client->dev,
+ "FTS writeAddr = %X, start_addr = %X, end_addr = %X\n",
+ writeAddr, start_addr, end_addr);
+#endif
+
+ switch (type) {
+ case TYPE_RAW_DATA:
+ tsp_debug_info(&info->client->dev,
+ "FTS [Raw Data : 0x%X%X]\n", pFrameAddress[0],
+ FrameAddress);
+ break;
+ case TYPE_FILTERED_DATA:
+ tsp_debug_info(&info->client->dev,
+ "FTS [Filtered Data : 0x%X%X]\n",
+ pFrameAddress[0], FrameAddress);
+ break;
+ case TYPE_STRENGTH_DATA:
+ tsp_debug_info(&info->client->dev,
+ "FTS [Strength Data : 0x%X%X]\n",
+ pFrameAddress[0], FrameAddress);
+ break;
+ case TYPE_BASELINE_DATA:
+ tsp_debug_info(&info->client->dev,
+ "FTS [Baseline Data : 0x%X%X]\n",
+ pFrameAddress[0], FrameAddress);
+ break;
+ }
+ fts_print_frame(info, min, max);
+
+ErrorExit:
+ return rc;
+}
+
+static void get_fw_ver_bin(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[16] = {0};
+
+ set_default_result(info);
+
+ if (strncmp(info->board->model_name, "G925", 4) == 0) {
+ info->tspid_val = gpio_get_value(info->board->tspid);
+ info->tspid2_val = gpio_get_value(info->board->tspid2);
+
+ sprintf(buff, "ST%01X%01X%04X",
+ info->tspid_val, info->tspid2_val,
+ info->fw_main_version_of_bin);
+ } else {
+ sprintf(buff, "ST%02X%04X",
+ info->panel_revision,
+ info->fw_main_version_of_bin);
+ }
+
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void get_fw_ver_ic(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[16] = {0};
+
+ set_default_result(info);
+
+ if (strncmp(info->board->model_name, "G925", 4) == 0) {
+ info->tspid_val = gpio_get_value(info->board->tspid);
+ info->tspid2_val = gpio_get_value(info->board->tspid2);
+
+ sprintf(buff, "ST%01X%01X%04X",
+ info->tspid_val, info->tspid2_val,
+ info->fw_main_version_of_ic);
+ } else {
+ sprintf(buff, "ST%02X%04X",
+ info->panel_revision,
+ info->fw_main_version_of_ic);
+ }
+
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void get_config_ver(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[20] = {0};
+ const char *name = NULL;
+
+ if (info->board->model_name)
+ name = info->board->model_name;
+ else if (info->board->project_name)
+ name = info->board->project_name;
+
+ snprintf(buff, sizeof(buff), "%s_ST_%04X",
+ name? name : STM_DEVICE_NAME,
+ info->config_version_of_ic);
+
+ set_default_result(info);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void get_threshold(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ unsigned char cmd[4] = {0xB2, 0x00, 0x62, 0x02};
+ char buff[CMD_STR_LEN] = {0};
+ int timeout = 0;
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ info->fts_write_reg(info, &cmd[0], 4);
+ info->cmd_state = CMD_STATUS_RUNNING;
+
+ while (info->cmd_state == CMD_STATUS_RUNNING) {
+ if (timeout++ > 30) {
+ info->cmd_state = CMD_STATUS_FAIL;
+ break;
+ }
+ fts_delay(10);
+ }
+}
+
+static void get_x_num(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[16] = { 0 };
+
+ set_default_result(info);
+ snprintf(buff, sizeof(buff), "%d", info->SenseChannelLength);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = 2;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void get_y_num(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[16] = { 0 };
+
+ set_default_result(info);
+ snprintf(buff, sizeof(buff), "%d", info->ForceChannelLength);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void run_rawcap_read(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ short min = 0x7FFF;
+ short max = 0x8000;
+
+ set_default_result(info);
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max);
+ snprintf(buff, sizeof(buff), "%d,%d", min, max);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+
+}
+
+static void get_rawcap(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ short val = 0;
+ int node = 0;
+
+ set_default_result(info);
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ node = fts_check_index(info);
+ if (node < 0)
+ return;
+
+ val = info->pFrame[node];
+ snprintf(buff, sizeof(buff), "%d", val);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void get_strength_all_data(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ short min = 0x7FFF;
+ short max = 0x8000;
+ const int str_size = info->ForceChannelLength *
+ info->SenseChannelLength * 5;
+ char all_strbuff[str_size];
+ int i, j;
+
+ memset(all_strbuff, 0, sizeof(char)*(str_size)); /* size 5 ex(1125,) */
+
+ set_default_result(info);
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
+
+
+ for (i = 0; i < info->ForceChannelLength; i++) {
+ for (j = 0; j < info->SenseChannelLength; j++) {
+ sprintf(buff, "%d,",
+ info->pFrame[
+ (i * info->SenseChannelLength) + j]);
+ strcat(all_strbuff, buff);
+ }
+ }
+
+ info->cmd_state = CMD_STATUS_OK;
+
+ set_cmd_result(info, all_strbuff,
+ strnlen(all_strbuff, sizeof(all_strbuff)));
+ tsp_debug_info(&info->client->dev,
+ "%ld (%ld)\n", strnlen(all_strbuff,
+ sizeof(all_strbuff)), sizeof(all_strbuff));
+}
+
+void fts_read_self_frame(struct fts_ts_info *info, unsigned short oAddr)
+{
+ char buff[66] = {0, };
+ short *data = 0;
+ char temp[9] = {0, };
+ char temp2[512] = {0, };
+ int i = 0;
+ int rc = 0;
+ unsigned char regAdd[6] = {0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00};
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ regAdd[1] = (oAddr >> 8) & 0xff;
+ regAdd[2] = oAddr & 0xff;
+ rc = info->fts_read_reg(info, &regAdd[0], 3, (unsigned char *)&buff[0], 5);
+ if (rc < 0) {
+ info->cmd_state = CMD_STATUS_FAIL;
+ return;
+ }
+
+ if (info->digital_rev == FTS_DIGITAL_REV_1) {
+ tsp_debug_info(&info->client->dev,
+ "%s: Force Address : %02x%02x\n",
+ __func__, buff[1], buff[0]);
+ tsp_debug_info(&info->client->dev,
+ "%s: Sense Address : %02x%02x\n",
+ __func__, buff[3], buff[2]);
+ regAdd[1] = buff[3];
+ regAdd[2] = buff[2];
+ regAdd[4] = buff[1];
+ regAdd[5] = buff[0];
+ } else if (info->digital_rev == FTS_DIGITAL_REV_2) {
+ tsp_debug_info(&info->client->dev,
+ "%s: Force Address : %02x%02x\n",
+ __func__, buff[2], buff[1]);
+ tsp_debug_info(&info->client->dev,
+ "%s: Sense Address : %02x%02x\n",
+ __func__, buff[4], buff[3]);
+ regAdd[1] = buff[4];
+ regAdd[2] = buff[3];
+ regAdd[4] = buff[2];
+ regAdd[5] = buff[1];
+ }
+
+ rc = info->fts_read_reg(info, &regAdd[0], 3,
+ (unsigned char *)&buff[0],
+ info->SenseChannelLength * 2 + 1);
+ if (rc < 0) {
+ info->cmd_state = CMD_STATUS_FAIL;
+ return;
+ }
+
+ if (info->digital_rev == FTS_DIGITAL_REV_1)
+ data = (short *)&buff[0];
+ else
+ data = (short *)&buff[1];
+
+ memset(temp, 0x00, ARRAY_SIZE(temp));
+ memset(temp2, 0x00, ARRAY_SIZE(temp2));
+
+ for (i = 0; i < info->SenseChannelLength; i++) {
+ tsp_debug_info(&info->client->dev,
+ "%s: Rx [%d] = %d\n", __func__,
+ i,
+ *data);
+ sprintf(temp, "%d,", *data);
+ strncat(temp2, temp, 9);
+ data++;
+ }
+
+ rc = info->fts_read_reg(info, &regAdd[3], 3,
+ (unsigned char *)&buff[0],
+ info->ForceChannelLength * 2 + 1);
+ if (rc < 0) {
+ info->cmd_state = CMD_STATUS_FAIL;
+ return;
+ }
+
+ if (info->digital_rev == FTS_DIGITAL_REV_1)
+ data = (short *)&buff[0];
+ else
+ data = (short *)&buff[1];
+
+ for (i = 0; i < info->ForceChannelLength; i++) {
+ tsp_debug_info(&info->client->dev,
+ "%s: Tx [%d] = %d\n", __func__, i, *data);
+ sprintf(temp, "%d,", *data);
+ strncat(temp2, temp, 9);
+ data++;
+ }
+
+ set_cmd_result(info, temp2, strnlen(temp2, sizeof(temp2)));
+
+ info->cmd_state = CMD_STATUS_OK;
+}
+
+static void fts_read_ix_data(struct fts_ts_info *info, bool allnode)
+{
+ char buff[33] = { 0 };
+
+ unsigned short max_tx_ix_sum = 0;
+ unsigned short min_tx_ix_sum = 0xFFFF;
+
+ unsigned short max_rx_ix_sum = 0;
+ unsigned short min_rx_ix_sum = 0xFFFF;
+
+ unsigned char tx_ix2[info->ForceChannelLength + 4];
+ unsigned char rx_ix2[info->SenseChannelLength + 4];
+
+ unsigned char regAdd[FTS_EVENT_SIZE];
+ unsigned short tx_ix1 = 0, rx_ix1 = 0;
+
+ unsigned short force_ix_data[info->ForceChannelLength * 2 + 1];
+ unsigned short sense_ix_data[info->SenseChannelLength * 2 + 1];
+ int buff_size, j;
+ char *mbuff = NULL;
+ int num, n, a, fzero;
+ char cnum;
+ int i = 0;
+ int comp_header_addr, comp_start_tx_addr, comp_start_rx_addr;
+ unsigned int rx_num, tx_num;
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ info->fts_irq_enable(info, false);
+ info->fts_interrupt_set(info, INT_DISABLE);
+
+ info->fts_command(info, SENSEOFF);
+
+ info->fts_command(info, FLUSHBUFFER); /* Clear FIFO */
+ fts_delay(50);
+
+ info->fts_release_all_finger(info);
+
+ /* Request compensation data */
+ regAdd[0] = 0xB8;
+ regAdd[1] = 0x20; /* SELF IX */
+ regAdd[2] = 0x00;
+ info->fts_write_reg(info, &regAdd[0], 3);
+ fts_fw_wait_for_specific_event(info,
+ EVENTID_STATUS_REQUEST_COMP, 0x20, 0x00);
+
+ /* Read an address of compensation data */
+ regAdd[0] = 0xD0;
+ regAdd[1] = 0x00;
+ regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR;
+ info->fts_read_reg(info, regAdd, 3, &buff[0], 3);
+ comp_header_addr = buff[1] + (buff[2] << 8);
+
+ /* Read header of compensation area */
+ regAdd[0] = 0xD0;
+ regAdd[1] = (comp_header_addr >> 8) & 0xFF;
+ regAdd[2] = comp_header_addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
+ tx_num = buff[5];
+ rx_num = buff[6];
+ tsp_debug_info(&info->client->dev,
+ "%s: [FTS] tx : %d, rx : %d",
+ __func__, tx_num, rx_num);
+
+ tx_ix1 = (short) buff[10];
+ rx_ix1 = (short) buff[11];
+
+ comp_start_tx_addr = comp_header_addr + 0x10;
+ comp_start_rx_addr = comp_start_tx_addr + tx_num;
+
+ memset(tx_ix2, 0x0, tx_num);
+ memset(rx_ix2, 0x0, rx_num);
+
+ /* Read Self TX Ix2 */
+ regAdd[0] = 0xD0;
+ regAdd[1] = (comp_start_tx_addr >> 8) & 0xFF;
+ regAdd[2] = comp_start_tx_addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &tx_ix2[0], tx_num + 1);
+
+ /* Read Self RX Ix2 */
+ regAdd[0] = 0xD0;
+ regAdd[1] = (comp_start_rx_addr >> 8) & 0xFF;
+ regAdd[2] = comp_start_rx_addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &rx_ix2[0], rx_num + 1);
+
+ for (i = 0; i < info->ForceChannelLength; i++) {
+ force_ix_data[i] = tx_ix1 + tx_ix2[i + 1];
+ if (max_tx_ix_sum < force_ix_data[i])
+ max_tx_ix_sum = force_ix_data[i];
+ if (min_tx_ix_sum > force_ix_data[i])
+ min_tx_ix_sum = force_ix_data[i];
+ }
+
+ for (i = 0; i < info->SenseChannelLength; i++) {
+ sense_ix_data[i] = rx_ix1 + rx_ix2[i + 1];
+ if (max_rx_ix_sum < sense_ix_data[i])
+ max_rx_ix_sum = sense_ix_data[i];
+ if (min_rx_ix_sum > sense_ix_data[i])
+ min_rx_ix_sum = sense_ix_data[i];
+ }
+
+ tsp_debug_info(&info->client->dev,
+ "%s: MIN_TX_IX_SUM : %d MAX_TX_IX_SUM : %d\n",
+ __func__, min_tx_ix_sum, max_tx_ix_sum);
+ tsp_debug_info(&info->client->dev,
+ "%s: MIN_RX_IX_SUM : %d MAX_RX_IX_SUM : %d\n",
+ __func__, min_rx_ix_sum, max_rx_ix_sum);
+
+ info->fts_command(info, SENSEON);
+
+ info->fts_irq_enable(info, true);
+ info->fts_interrupt_set(info, INT_ENABLE);
+
+ if (allnode == true) {
+ buff_size = (info->ForceChannelLength +
+ info->SenseChannelLength + 2) * 5;
+ mbuff = kzalloc(buff_size, GFP_KERNEL);
+ }
+ if (mbuff != NULL) {
+ char *pBuf = mbuff;
+
+ for (i = 0; i < info->ForceChannelLength; i++) {
+ num = force_ix_data[i];
+ n = 100000;
+ fzero = 0;
+ for (j = 5; j > 0; j--) {
+ n = n / 10;
+ a = num / n;
+ if (a)
+ fzero = 1;
+ cnum = a + '0';
+ num = num - a*n;
+ if (fzero)
+ *pBuf++ = cnum;
+ }
+ if (!fzero)
+ *pBuf++ = '0';
+ *pBuf++ = ',';
+ tsp_debug_info(&info->client->dev,
+ "Force[%d] %d\n", i, force_ix_data[i]);
+ }
+ for (i = 0; i < info->SenseChannelLength; i++) {
+ num = sense_ix_data[i];
+ n = 100000;
+ fzero = 0;
+ for (j = 5; j > 0; j--) {
+ n = n / 10;
+ a = num / n;
+ if (a)
+ fzero = 1;
+ cnum = a + '0';
+ num = num - a * n;
+ if (fzero)
+ *pBuf++ = cnum;
+ }
+ if (!fzero)
+ *pBuf++ = '0';
+ if (i < (info->SenseChannelLength - 1))
+ *pBuf++ = ',';
+ tsp_debug_info(&info->client->dev,
+ "Sense[%d] %d\n", i, sense_ix_data[i]);
+ }
+
+ set_cmd_result(info, mbuff, buff_size);
+ info->cmd_state = CMD_STATUS_OK;
+ kfree(mbuff);
+ } else {
+ if (allnode == true) {
+ snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
+ info->cmd_state = CMD_STATUS_FAIL;
+ } else{
+ snprintf(buff, sizeof(buff), "%d,%d,%d,%d",
+ min_tx_ix_sum, max_tx_ix_sum,
+ min_rx_ix_sum, max_rx_ix_sum);
+ info->cmd_state = CMD_STATUS_OK;
+ }
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ tsp_debug_info(&info->client->dev,
+ "%s: %s\n", __func__, buff);
+ }
+}
+
+static void run_ix_data_read(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+
+ set_default_result(info);
+ fts_read_ix_data(info, false);
+}
+
+static void run_ix_data_read_all(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+
+ set_default_result(info);
+ fts_read_ix_data(info, true);
+}
+
+static void fts_read_self_raw_frame(struct fts_ts_info *info,
+ unsigned short oAddr, bool allnode)
+{
+ char buff[32 * 2 + 1] = { 0 };
+ unsigned char D0_offset = 1;
+ unsigned char regAdd[3] = {0xD0, 0x00, 0x00};
+ unsigned char ReadData[info->SenseChannelLength * 2 + 1];
+ unsigned short self_force_raw_data[info->ForceChannelLength * 2 + 1];
+ unsigned short self_sense_raw_data[info->SenseChannelLength * 2 + 1];
+ unsigned int FrameAddress = 0;
+ unsigned char count = 0;
+ int buff_size, i, j;
+ char *mbuff = NULL;
+ int num, n, a, fzero;
+ char cnum;
+ unsigned short min_tx_self_raw_data = 0xFFFF;
+ unsigned short max_tx_self_raw_data = 0;
+ unsigned short min_rx_self_raw_data = 0xFFFF;
+ unsigned short max_rx_self_raw_data = 0;
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ info->fts_irq_enable(info, false);
+ info->fts_interrupt_set(info, INT_DISABLE);
+ info->fts_command(info, SENSEOFF);
+
+ fts_delay(50);
+
+ info->fts_command(info, FLUSHBUFFER); /* Clear FIFO */
+ fts_delay(50);
+
+ regAdd[1] = 0x00;
+ regAdd[2] = oAddr;
+ info->fts_read_reg(info, regAdd, 3, &ReadData[0], 4);
+
+ /* D1 : DOFFSET = 0, D2 : DOFFSET : 1 */
+ FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8);
+
+ regAdd[1] = (FrameAddress >> 8) & 0xFF;
+ regAdd[2] = FrameAddress & 0xFF;
+
+ info->fts_read_reg(info, regAdd, 3, &ReadData[0], info->ForceChannelLength * 2 + 1);
+
+ for (count = 0; count < info->ForceChannelLength; count++) {
+ self_force_raw_data[count] = ReadData[count*2+D0_offset] + (ReadData[count*2+D0_offset+1]<<8);
+
+ if (max_tx_self_raw_data < self_force_raw_data[count])
+ max_tx_self_raw_data = self_force_raw_data[count];
+ if (min_tx_self_raw_data > self_force_raw_data[count])
+ min_tx_self_raw_data = self_force_raw_data[count];
+ }
+
+ regAdd[1] = 0x00;
+ regAdd[2] = oAddr + 2;
+ info->fts_read_reg(info, regAdd, 3, &ReadData[0], 4);
+
+ FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); /* D1 : DOFFSET = 0, D2 : DOFFSET : 1 */
+
+ regAdd[1] = (FrameAddress >> 8) & 0xFF;
+ regAdd[2] = FrameAddress & 0xFF;
+
+ info->fts_read_reg(info, regAdd, 3, &ReadData[0],
+ info->SenseChannelLength * 2 + 1);
+
+ for (count = 0; count < info->SenseChannelLength; count++) {
+ self_sense_raw_data[count] = ReadData[count*2+D0_offset] +
+ (ReadData[count*2+D0_offset+1]<<8);
+
+ if (max_rx_self_raw_data < self_sense_raw_data[count])
+ max_rx_self_raw_data = self_sense_raw_data[count];
+ if (min_rx_self_raw_data > self_sense_raw_data[count])
+ min_rx_self_raw_data = self_sense_raw_data[count];
+ }
+
+ tsp_debug_info(&info->client->dev,
+ "%s MIN_TX_SELF_RAW: %d MAX_TX_SELF_RAW : %d\n",
+ __func__, min_tx_self_raw_data, max_tx_self_raw_data);
+ tsp_debug_info(&info->client->dev,
+ "%s MIN_RX_SELF_RAW : %d MIN_RX_SELF_RAW : %d\n",
+ __func__, min_rx_self_raw_data, max_rx_self_raw_data);
+
+ fts_delay(1);
+ info->fts_command(info, SENSEON);
+
+ info->fts_irq_enable(info, true);
+ info->fts_interrupt_set(info, INT_ENABLE);
+
+ if (allnode == true) {
+ buff_size = (info->ForceChannelLength +
+ info->SenseChannelLength + 2)*10;
+ mbuff = kzalloc(buff_size, GFP_KERNEL);
+ }
+ if (mbuff != NULL) {
+ char *pBuf = mbuff;
+
+ for (i = 0; i < info->ForceChannelLength; i++) {
+ num = self_force_raw_data[i];
+ n = 100000;
+ fzero = 0;
+ for (j = 5; j > 0; j--) {
+ n = n/10;
+ a = num/n;
+ if (a)
+ fzero = 1;
+ cnum = a + '0';
+ num = num - a*n;
+ if (fzero)
+ *pBuf++ = cnum;
+ }
+ if (!fzero)
+ *pBuf++ = '0';
+ *pBuf++ = ',';
+ tsp_debug_info(&info->client->dev, "%d ", self_force_raw_data[i]);
+ }
+ for (i = 0; i < info->SenseChannelLength; i++) {
+ num = self_sense_raw_data[i];
+ n = 100000;
+ fzero = 0;
+ for (j = 5; j > 0; j--) {
+ n = n/10;
+ a = num/n;
+ if (a)
+ fzero = 1;
+ cnum = a + '0';
+ num = num - a*n;
+ if (fzero)
+ *pBuf++ = cnum;
+ }
+ if (!fzero)
+ *pBuf++ = '0';
+ if (i < (info->SenseChannelLength-1))
+ *pBuf++ = ',';
+ tsp_debug_info(&info->client->dev, "%d ", self_sense_raw_data[i]);
+ }
+
+
+ set_cmd_result(info, mbuff, buff_size);
+ info->cmd_state = CMD_STATUS_OK;
+ kfree(mbuff);
+ } else {
+ if (allnode == true) {
+ snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ } else{
+ snprintf(buff, sizeof(buff), "%d,%d,%d,%d",
+ min_tx_self_raw_data,
+ max_tx_self_raw_data,
+ min_rx_self_raw_data,
+ max_rx_self_raw_data);
+ info->cmd_state = CMD_STATUS_OK;
+ }
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ tsp_debug_info(&info->client->dev, "%s: %s\n",
+ __func__, buff);
+ }
+}
+
+static void run_self_raw_read(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+
+ set_default_result(info);
+ fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR, false);
+}
+
+static void run_self_raw_read_all(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+
+ set_default_result(info);
+ fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR, true);
+}
+
+static void get_cx_data(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ short val = 0;
+ int node = 0;
+
+ set_default_result(info);
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ node = fts_check_index(info);
+ if (node < 0)
+ return;
+
+ val = info->cx_data[node];
+ snprintf(buff, sizeof(buff), "%d", val);
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_OK;
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+
+}
+
+static void run_cx_data_read(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+
+ char buff[SEC_CMD_STR_LEN] = { 0 };
+ unsigned char ReadData[info->ForceChannelLength]
+ [info->SenseChannelLength + FTS_CX2_READ_LENGTH];
+ int cxdiffData_rx[info->ForceChannelLength *
+ (info->SenseChannelLength + FTS_CX2_READ_LENGTH)];
+ int cxdiffData_tx[info->ForceChannelLength *
+ (info->SenseChannelLength + FTS_CX2_READ_LENGTH)];
+ int Max_cxdiffData_rx = 0;
+ int Low_cxdiffData_rx = 0;
+ int Max_cxdiffData_tx = 0;
+ int Low_cxdiffData_tx = 0;
+ unsigned char regAdd[8];
+ unsigned int addr, rx_num, tx_num;
+ int i, j;
+ unsigned char *pStr = NULL;
+ unsigned char pTmp[16] = { 0 };
+
+ int comp_header_addr, comp_start_addr;
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL);
+ if (pStr == NULL) {
+ tsp_debug_info(&info->client->dev,
+ "%s: pStr kzalloc failed\n", __func__);
+ return;
+ }
+
+ tsp_debug_info(&info->client->dev, "%s: start\n", __func__);
+
+ info->fts_irq_enable(info, false);
+ tsp_debug_info(&info->client->dev, "%s: disable_irq\n", __func__);
+ info->fts_interrupt_set(info, INT_DISABLE);
+ tsp_debug_info(&info->client->dev,
+ "%s: fts_interrupt_set\n", __func__);
+ info->fts_command(info, SENSEOFF);
+ tsp_debug_info(&info->client->dev, "%s: fts_command\n", __func__);
+ fts_delay(50);
+ tsp_debug_info(&info->client->dev, "%s: senseoff\n", __func__);
+
+ info->fts_command(info, FLUSHBUFFER);
+ fts_delay(50);
+
+ info->fts_release_all_finger(info);
+
+ /* Request compensation data */
+ regAdd[0] = 0xB8;
+ regAdd[1] = 0x04; /* MUTUAL CX (LPA) */
+ regAdd[2] = 0x00;
+ info->fts_write_reg(info, &regAdd[0], 3);
+ tsp_debug_info(&info->client->dev,
+ "%s: Writing Request compensation data\n", __func__);
+ fts_cmd_completion_check(info, EVENTID_STATUS_REQUEST_COMP,
+ regAdd[1], regAdd[2]);
+
+ /* Read an address of compensation data */
+ regAdd[0] = 0xD0;
+ regAdd[1] = 0x00;
+ regAdd[2] = 0x50;
+ info->fts_read_reg(info, regAdd, 3, &buff[0], 4);
+ comp_header_addr = buff[1] + (buff[2] << 8);
+ tsp_debug_info(&info->client->dev,
+ "%s:Read an address of compensation data\n", __func__);
+
+ /* Read header of compensation area */
+ regAdd[0] = 0xD0;
+ regAdd[1] = (comp_header_addr >> 8) & 0xFF;
+ regAdd[2] = comp_header_addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
+ tx_num = buff[5];
+ rx_num = buff[6];
+ comp_start_addr = comp_header_addr + 0x10;
+
+ tsp_debug_info(&info->client->dev,
+ "%s:Read header of compensation area data\n", __func__);
+ tsp_debug_info(&info->client->dev,
+ "%s: Tx num ( %d ) Rx num ( %d )\n", __func__,
+ tx_num, rx_num);
+ tsp_debug_info(&info->client->dev,
+ "%s: comp_stat_addr : 0x%x\n", __func__,
+ comp_start_addr);
+ /* Read compensation data */
+ for (j = 0; j < tx_num; j++) {
+ memset(&ReadData[j], 0x0, rx_num);
+ memset(pStr, 0x0, 4 * (rx_num + 1));
+ snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
+ strncat(pStr, pTmp, 4 * rx_num);
+
+ addr = comp_start_addr + (rx_num * j);
+ regAdd[0] = 0xD0;
+ regAdd[1] = (addr >> 8) & 0xFF;
+ regAdd[2] = addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1);
+ for (i = 1; i < rx_num + 1; i++) {
+ snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i]);
+ strncat(pStr, pTmp, 4 * rx_num);
+ }
+ tsp_debug_info(&info->client->dev, "%s\n", pStr);
+ }
+
+ tsp_debug_info(&info->client->dev,
+ "%s:Read compensation data\n", __func__);
+ if (info->cx_data) {
+ for (j = 0; j < tx_num; j++) {
+ for (i = 1; i < rx_num + 1; i++)
+ info->cx_data[(j * rx_num) + i - 1] =
+ ReadData[j][i];
+ }
+ }
+ tsp_debug_err(&info->client->dev,
+ "===================> %s : Rx diff\n", __func__);
+ for (j = 0; j < tx_num; j++) {
+ memset(pStr, 0x0, 4 * (rx_num + 1));
+ snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
+ strncat(pStr, pTmp, 16);
+ for (i = 0; i < (rx_num-1); i++) {
+ cxdiffData_rx[(j*rx_num)+i] =
+ info->cx_data[(j*rx_num)+i] -
+ info->cx_data[(j*rx_num)+i+1];
+ if ((j == 0) && (i == 0)) {
+ Max_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i];
+ Low_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i];
+ }
+ if (cxdiffData_rx[(j*rx_num)+i] > Max_cxdiffData_rx)
+ Max_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i];
+ if (cxdiffData_rx[(j*rx_num)+i] < Low_cxdiffData_rx)
+ Low_cxdiffData_rx = cxdiffData_rx[(j*rx_num)+i];
+ snprintf(pTmp, sizeof(pTmp), "%4d", cxdiffData_rx[(j*rx_num)+i]);
+ strcat(pStr, pTmp);
+ }
+ tsp_debug_info(&info->client->dev, "FTS %s\n", pStr);
+ }
+ tsp_debug_err(&info->client->dev,
+ "======> Max : %d / Low : %d <=========\n",
+ Max_cxdiffData_rx, Low_cxdiffData_rx);
+ tsp_debug_err(&info->client->dev,
+ " %s : Tx diff\n <=======================", __func__);
+ for (j = 0; j < (tx_num - 1); j++) {
+ memset(pStr, 0x0, 4 * (rx_num + 1));
+ snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
+ strncat(pStr, pTmp, 16);
+ for (i = 0; i < rx_num; i++) {
+ cxdiffData_tx[(j*rx_num)+i] =
+ info->cx_data[(j*rx_num)+i] -
+ info->cx_data[((j+1)*rx_num)+i];
+ if ((j == 0) && (i == 0)) {
+ Max_cxdiffData_tx = cxdiffData_rx[(j*rx_num)+i];
+ Low_cxdiffData_tx = cxdiffData_rx[(j*rx_num)+i];
+ }
+ if (cxdiffData_tx[(j*rx_num)+i] > Max_cxdiffData_tx)
+ Max_cxdiffData_tx = cxdiffData_tx[(j*rx_num)+i];
+ if (cxdiffData_tx[(j*rx_num)+i] < Low_cxdiffData_tx)
+ Low_cxdiffData_tx = cxdiffData_tx[(j*rx_num)+i];
+ snprintf(pTmp, sizeof(pTmp), "%4d",
+ cxdiffData_tx[(j*rx_num)+i]);
+ strcat(pStr, pTmp);
+ }
+ tsp_debug_info(&info->client->dev, "FTS %s\n", pStr);
+ }
+ tsp_debug_err(&info->client->dev,
+ "======> Max : %d / Low : %d <=========\n",
+ Max_cxdiffData_tx, Low_cxdiffData_tx);
+
+ kfree(pStr);
+
+ snprintf(buff, sizeof(buff), "%s", "OK");
+ info->fts_irq_enable(info, true);
+ info->fts_interrupt_set(info, INT_ENABLE);
+ info->fts_command(info, SENSEON);
+ info->cmd_state = CMD_STATUS_OK;
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+
+}
+
+static void get_cx_all_data(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[SEC_CMD_STR_LEN] = { 0 };
+ unsigned char ReadData[info->ForceChannelLength]
+ [info->SenseChannelLength + FTS_CX2_READ_LENGTH];
+ unsigned char regAdd[8];
+ unsigned int addr, rx_num, tx_num;
+ int i, j;
+ unsigned char *pStr = NULL;
+ unsigned char pTmp[16] = { 0 };
+ char all_strbuff[(info->ForceChannelLength)*
+ (info->SenseChannelLength)*3];
+
+ int comp_header_addr, comp_start_addr;
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ tsp_debug_info(&info->client->dev, "%s: start\n", __func__);
+
+ info->fts_command(info, SENSEOFF);
+ info->fts_irq_enable(info, false);
+ info->fts_command(info, FLUSHBUFFER);
+ fts_delay(50);
+
+ info->fts_release_all_finger(info);
+
+ tx_num = info->ForceChannelLength;
+ rx_num = info->SenseChannelLength;
+
+ pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL);
+ if (pStr == NULL) {
+ tsp_debug_info(&info->client->dev,
+ "%s: pStr kzalloc failed\n", __func__);
+ goto out;
+ }
+
+ /* size 3 ex(45,) */
+ memset(all_strbuff, 0, sizeof(char) * (tx_num*rx_num*3));
+
+ /* Request compensation data */
+ regAdd[0] = 0xB8;
+ regAdd[1] = 0x04; /* MUTUAL CX (LPA) */
+ regAdd[2] = 0x00;
+ info->fts_write_reg(info, &regAdd[0], 3);
+ fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, 0x04, 0x00);
+
+ /* Read an address of compensation data */
+ regAdd[0] = 0xD0;
+ regAdd[1] = 0x00;
+ regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR;
+ info->fts_read_reg(info, regAdd, 3, &buff[0], 4);
+ comp_header_addr = buff[1] + (buff[2] << 8);
+
+ /* Read header of compensation area */
+ regAdd[0] = 0xD0;
+ regAdd[1] = (comp_header_addr >> 8) & 0xFF;
+ regAdd[2] = comp_header_addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
+ tx_num = buff[5];
+ rx_num = buff[6];
+ comp_start_addr = comp_header_addr + 0x10;
+
+ /* Read compensation data */
+ for (j = 0; j < tx_num; j++) {
+ memset(&ReadData[j], 0x0, rx_num);
+ memset(pStr, 0x0, 4 * (rx_num + 1));
+ snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
+ strlcat(pStr, pTmp, 4 * (rx_num + 1));
+
+ addr = comp_start_addr + (rx_num * j);
+ regAdd[0] = 0xD0;
+ regAdd[1] = (addr >> 8) & 0xFF;
+ regAdd[2] = addr & 0xFF;
+ info->fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1);
+ for (i = 0; i < rx_num; i++) {
+ snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i]);
+ strlcat(pStr, pTmp, 4 * (rx_num + 1));
+ }
+ tsp_debug_info(&info->client->dev, "%s\n", pStr);
+ }
+
+ if (info->cx_data) {
+ for (j = 0; j < tx_num; j++) {
+ for (i = 0; i < rx_num; i++) {
+ info->cx_data[(j * rx_num) + i] =
+ ReadData[j][i];
+ snprintf(buff, sizeof(buff),
+ "%d,", ReadData[j][i]);
+ strlcat(all_strbuff, buff, sizeof(all_strbuff));
+ }
+ }
+ }
+
+ kfree(pStr);
+
+out:
+ info->fts_irq_enable(info, true);
+ info->fts_command(info, SENSEON);
+ info->cmd_state = CMD_STATUS_OK;
+ set_cmd_result(info, all_strbuff,
+ strnlen(all_strbuff, sizeof(all_strbuff)));
+ tsp_debug_info(&info->client->dev,
+ "%s: %ld (%ld)\n", __func__,
+ strnlen(all_strbuff, sizeof(all_strbuff)),
+ sizeof(all_strbuff));
+}
+
+
+static void set_tsp_test_result(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ unsigned char regAdd[4] = {0xB0, 0x07, 0xE7, 0x00};
+
+ set_default_result(info);
+
+ if (info->cmd_param[0] < TSP_FACTEST_RESULT_NONE
+ || info->cmd_param[0] > TSP_FACTEST_RESULT_PASS) {
+ snprintf(buff, sizeof(buff), "%s", "NG");
+ info->cmd_state = CMD_STATUS_FAIL;
+ return;
+ }
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ info->fts_irq_enable(info, false);
+ info->fts_interrupt_set(info, INT_DISABLE);
+
+ regAdd[3] = info->cmd_param[0];
+ info->fts_write_reg(info, &regAdd[0], 4);
+ fts_delay(100);
+ info->fts_command(info, FTS_CMD_SAVE_FWCONFIG);
+
+ fts_delay(230);
+ fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CONFIG, 0x00);
+
+ info->fts_irq_enable(info, true);
+ info->fts_interrupt_set(info, INT_ENABLE);
+
+ snprintf(buff, sizeof(buff), "%s", "OK");
+ info->cmd_state = CMD_STATUS_OK;
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void get_tsp_test_result(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ unsigned char cmd[4] = {0xB2, 0x07, 0xE7, 0x01};
+ char buff[CMD_STR_LEN] = { 0 };
+ int timeout = 0;
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ info->fts_command(info, FLUSHBUFFER);
+ info->fts_write_reg(info, &cmd[0], 4);
+ info->cmd_state = CMD_STATUS_RUNNING;
+
+ while (info->cmd_state == CMD_STATUS_RUNNING) {
+ if (timeout++ > 30) {
+ info->cmd_state = CMD_STATUS_FAIL;
+ break;
+ }
+ fts_delay(10);
+ }
+}
+
+static void run_trx_short_test(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+ int ret = 0;
+
+ set_default_result(info);
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+ info->fts_irq_enable(info, false);
+ ret = fts_panel_ito_test(info);
+ if (ret == 1)
+ snprintf(buff, sizeof(buff), "%s", "OK");
+ else
+ snprintf(buff, sizeof(buff), "%s", "FAIL");
+ info->fts_irq_enable(info, true);
+ info->cmd_state = CMD_STATUS_OK;
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void report_rate(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ goto out;
+ }
+
+ if (info->cmd_param[0] < 0 || info->cmd_param[0] > 2) {
+ snprintf(buff, sizeof(buff), "%s", "NG");
+ info->cmd_state = CMD_STATUS_FAIL;
+ } else {
+ snprintf(buff, sizeof(buff), "%s", "OK");
+ info->cmd_state = CMD_STATUS_OK;
+ }
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_WAITING;
+
+out:
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void delay(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+
+ set_default_result(info);
+
+ info->delay_time = info->cmd_param[0];
+
+ tsp_debug_info(&info->client->dev,
+ "%s: delay time is %d\n", __func__, info->delay_time);
+ snprintf(buff, sizeof(buff), "%d", info->delay_time);
+
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+ info->cmd_state = CMD_STATUS_WAITING;
+
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void debug(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+
+ set_default_result(info);
+
+ info->debug_string = info->cmd_param[0];
+
+ tsp_debug_info(&info->client->dev,
+ "%s: command is %d\n", __func__, info->debug_string);
+
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+ info->cmd_state = CMD_STATUS_WAITING;
+
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void run_autotune_enable(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+
+ set_default_result(info);
+
+ info->run_autotune = info->cmd_param[0];
+
+ tsp_debug_info(&info->client->dev, "%s: command is %s\n",
+ __func__, info->run_autotune ? "ENABLE" : "DISABLE");
+
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+ info->cmd_state = CMD_STATUS_WAITING;
+
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+}
+
+static void run_autotune(void *device_data)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)device_data;
+ char buff[CMD_STR_LEN] = { 0 };
+
+ set_default_result(info);
+
+ if (info->touch_stopped) {
+ dev_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n", __func__);
+ }
+
+ if (info->touch_stopped) {
+ tsp_debug_info(&info->client->dev,
+ "%s: [ERROR] Touch is stopped\n",
+ __func__);
+ snprintf(buff, sizeof(buff), "%s", "TSP turned off");
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
+ return;
+ }
+
+ if (!info->run_autotune) {
+ tsp_debug_info(&info->client->dev,
+ "%s: autotune is disabled, %d\n",
+ __func__, info->run_autotune);
+ goto autotune_fail;
+ }
+
+ info->fts_irq_enable(info, false);
+
+ if (info->digital_rev == FTS_DIGITAL_REV_2) {
+ info->fts_interrupt_set(info, INT_DISABLE);
+
+ info->fts_command(info, SENSEOFF);
+ fts_delay(50);
+
+ info->fts_command(info, FTS_CMD_TRIM_LOW_POWER_OSCILLATOR);
+ fts_delay(200);
+
+ info->fts_command(info, FLUSHBUFFER);
+
+ info->fts_release_all_finger(info);
+ fts_execute_autotune(info);
+
+ info->fts_command(info, SENSEON);
+
+ info->fts_interrupt_set(info, INT_ENABLE);
+ } else {
+ tsp_debug_info(&info->client->dev,
+ "%s: digital_rev not matched, %d\n",
+ __func__, info->digital_rev);
+ goto autotune_fail;
+ }
+
+ info->fts_irq_enable(info, true);
+ snprintf(buff, sizeof(buff), "%s", "OK");
+ info->cmd_state = CMD_STATUS_OK;
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+ return;
+
+autotune_fail:
+ snprintf(buff, sizeof(buff), "%s", "NG");
+ info->cmd_state = CMD_STATUS_FAIL;
+ set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+
+ mutex_lock(&info->cmd_lock);
+ info->cmd_is_running = false;
+ mutex_unlock(&info->cmd_lock);
+
+ tsp_debug_info(&info->client->dev, "%s: %s\n", __func__, buff);
+ return;
+}
+
+void fts_production_init(void *device_info)
+{
+ char pdc_dir_name[20] = {0, };
+ int j = 0;
+ struct fts_ts_info *info = (struct fts_ts_info *)device_info;
+ int retval = 0;
+
+ INIT_LIST_HEAD(&info->cmd_list_head);
+
+ info->cmd_buf_size = 0;
+ for (j = 0; j < ARRAY_SIZE(fts_commands); j++) {
+ list_add_tail(&fts_commands[j].list, &info->cmd_list_head);
+ if (fts_commands[j].cmd_name)
+ info->cmd_buf_size += strlen(fts_commands[j].cmd_name) + 1;
+ }
+
+ mutex_init(&info->cmd_lock);
+ info->cmd_is_running = false;
+
+ sprintf(pdc_dir_name, "ftm4_touch");
+
+ info->pdc_dev_ts = device_create(info->input_dev->dev.class,
+ NULL, 0, NULL, pdc_dir_name);
+ if (IS_ERR(info->pdc_dev_ts)) {
+ tsp_debug_err(&info->client->dev,
+ "FTS Failed to create device for the sysfs\n");
+ retval = -ENOENT;
+ goto err_sysfs;
+ }
+
+ dev_set_drvdata(info->pdc_dev_ts, info);
+
+ retval = sysfs_create_group(&info->pdc_dev_ts->kobj,
+ &touch_pdc_attr_group);
+ if (retval < 0) {
+ tsp_debug_err(&info->client->dev,
+ "FTS Failed to create sysfs group\n");
+ goto err_sysfs;
+ }
+
+
+ if (retval < 0) {
+ tsp_debug_err(&info->client->dev,
+ "%s: Failed to create link\n", __func__);
+ goto err_sysfs;
+ }
+
+ return;
+err_sysfs:
+ mutex_destroy(&info->cmd_lock);
+}
+EXPORT_SYMBOL(fts_production_init);
diff --git a/drivers/input/touchscreen/stm/ftm4_ts.c b/drivers/input/touchscreen/stm/ftm4_ts.c
new file mode 100644
index 00000000000..2d7f244a897
--- /dev/null
+++ b/drivers/input/touchscreen/stm/ftm4_ts.c
@@ -0,0 +1,2277 @@
+/******************** (C) COPYRIGHT 2012 STMicroelectronics ********************
+*
+* File Name : fts.c
+* Authors : AMS(Analog Mems Sensor) Team
+* Description : FTS Capacitive touch screen controller (FingerTipS)
+*
+********************************************************************************
+*
+* 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.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+********************************************************************************
+* REVISON HISTORY
+* DATE | DESCRIPTION
+* 03/09/2012| First Release
+* 08/11/2012| Code migration
+* 09/04/2013| Support Blob Information
+*******************************************************************************/
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/power_supply.h>
+#include <linux/firmware.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+#include <linux/trustedui.h>
+#endif
+
+#ifdef CONFIG_OF
+#ifndef USE_OPEN_CLOSE
+#define USE_OPEN_CLOSE
+#undef CONFIG_PM
+#endif
+#endif
+
+#include <linux/input/mt.h>
+#include "ftm4_ts.h"
+
+static struct i2c_driver fts_i2c_driver;
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+extern int tui_force_close(uint32_t arg);
+struct fts_ts_info *tui_tsp_info;
+#endif
+
+#ifdef USE_OPEN_CLOSE
+static int fts_input_open(struct input_dev *dev);
+static void fts_input_close(struct input_dev *dev);
+#ifdef USE_OPEN_DWORK
+static void fts_open_work(struct work_struct *work);
+#endif
+#endif
+
+static int fts_stop_device(struct fts_ts_info *info);
+static int fts_start_device(struct fts_ts_info *info);
+static void fts_irq_enable(struct fts_ts_info *info, bool enable);
+static void fts_reset_work(struct work_struct *work);
+void fts_recovery_cx(struct fts_ts_info *info);
+void fts_release_all_finger(struct fts_ts_info *info);
+static int fts_suspend(struct i2c_client *client, pm_message_t mesg);
+static int fts_resume(struct i2c_client *client);
+
+#if defined(CONFIG_FB)
+static int touch_fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
+#endif
+
+int fts_write_reg(struct fts_ts_info *info,
+ unsigned char *reg, unsigned short num_com)
+{
+ struct i2c_msg xfer_msg[2];
+ int ret = 0;
+
+ if (info->touch_stopped) {
+ tsp_debug_err(&info->client->dev,
+ "%s: Sensor stopped\n", __func__);
+ goto exit;
+ }
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode()) {
+ tsp_debug_err(&info->client->dev,
+ "%s TSP no accessible from Linux,"
+ "TUI is enabled!\n", __func__);
+ return -EIO;
+ }
+#endif
+
+ mutex_lock(&info->i2c_mutex);
+
+ xfer_msg[0].addr = info->client->addr;
+ xfer_msg[0].len = num_com;
+ xfer_msg[0].flags = 0;
+ xfer_msg[0].buf = reg;
+
+ ret = i2c_transfer(info->client->adapter, xfer_msg, 1);
+
+ mutex_unlock(&info->i2c_mutex);
+ return ret;
+
+ exit:
+ return -EIO;
+}
+
+int fts_read_reg(struct fts_ts_info *info, unsigned char *reg, int cnum,
+ unsigned char *buf, int num)
+{
+ struct i2c_msg xfer_msg[2];
+ int ret = 0;
+
+ if (info->touch_stopped) {
+ tsp_debug_err(&info->client->dev,
+ "%s: Sensor stopped\n", __func__);
+ goto exit;
+ }
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode()) {
+ tsp_debug_err(&info->client->dev,
+ "%s TSP no accessible from Linux,"
+ " TUI is enabled!\n", __func__);
+ return -EIO;
+ }
+#endif
+
+ mutex_lock(&info->i2c_mutex);
+
+ xfer_msg[0].addr = info->client->addr;
+ xfer_msg[0].len = cnum;
+ xfer_msg[0].flags = 0;
+ xfer_msg[0].buf = reg;
+
+ xfer_msg[1].addr = info->client->addr;
+ xfer_msg[1].len = num;
+ xfer_msg[1].flags = I2C_M_RD;
+ xfer_msg[1].buf = buf;
+
+ ret = i2c_transfer(info->client->adapter, xfer_msg, 2);
+
+ mutex_unlock(&info->i2c_mutex);
+
+ return ret;
+
+ exit:
+ return -EIO;
+}
+
+void fts_delay(unsigned int ms)
+{
+ if (ms < 20)
+ usleep_range(ms * 1000, ms * 1000);
+ else
+ msleep(ms);
+}
+
+void fts_command(struct fts_ts_info *info, unsigned char cmd)
+{
+ unsigned char regAdd = 0;
+ int ret = 0;
+
+ regAdd = cmd;
+ ret = fts_write_reg(info, &regAdd, 1);
+ tsp_debug_dbg(&info->client->dev,
+ "FTS Command (%02X) , "
+ "ret = %d\n", cmd, ret);
+}
+
+void fts_change_scan_rate(struct fts_ts_info *info, unsigned char cmd)
+{
+ unsigned char regAdd[2] = {0xC3, 0x00};
+ int ret = 0;
+
+ regAdd[1] = cmd;
+ ret = fts_write_reg(info, &regAdd[0], 2);
+
+ tsp_debug_dbg(&info->client->dev,
+ "FTS %s Scan Rate (%02X %02X) , ret = %d\n",
+ (cmd == FTS_CMD_FAST_SCAN) ? "90Hz" :
+ (cmd == FTS_CMD_SLOW_SCAN) ? "60Hz" : "30Hz",
+ regAdd[0], regAdd[1], ret);
+}
+
+int fts_systemreset(struct fts_ts_info *info)
+{
+ int ret = 0;
+ unsigned char addr[4] = {0xB6, 0x00, 0x28, 0x80};
+ unsigned char addr_wbcrc[4] = {0xB6, 0x00, 0x1E, 0x20};
+
+ tsp_debug_info(&info->client->dev, "FTS Enable WBCRC\n");
+ ret = fts_write_reg(info, &addr_wbcrc[0], 4);
+ fts_delay(10);
+
+ tsp_debug_dbg(&info->client->dev, "FTS SystemReset\n");
+ ret = fts_write_reg(info, &addr[0], 4);
+ fts_delay(10);
+
+ return ret;
+}
+
+static void fts_interrupt_set(struct fts_ts_info *info, int enable)
+{
+ unsigned char regAdd[4] = {0xB6, 0x00, 0x2C, INT_ENABLE};
+
+ if (enable== INT_ENABLE) {
+ tsp_debug_dbg(&info->client->dev, "FTS INT Enable\n");
+ } else {
+ regAdd[3] = INT_DISABLE;
+ tsp_debug_dbg(&info->client->dev, "FTS INT Disable\n");
+ }
+
+ fts_write_reg(info, &regAdd[0], 4);
+}
+
+void fts_get_afe_info(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char regAdd[3];
+ unsigned char data[FTS_EVENT_SIZE];
+
+ /* Reading the final AFE version */
+ regAdd[0] = 0xd0;
+ regAdd[1] = 0x00;
+ regAdd[2] = 0x52;
+
+ rc = fts_read_reg(info, regAdd, 3, (unsigned char *)data, 3);
+ if (rc < 0) {
+ info->afe_ver = 0;
+ tsp_debug_err(info->dev,
+ "%s: Read Fail - Final AFE [Data : "
+ "%2X] AFE Ver [Data : %2X] \n",
+ __func__,
+ data[1],
+ data[2]);
+ } else
+ info->afe_ver = data[2];
+}
+
+static int fts_product_info_read(struct fts_ts_info *info)
+{
+ unsigned char data[FTS_EVENT_SIZE] = {0,};
+ unsigned char prd_info[FTS_LOCKDOWNCODE_SIZE] ={0x0,};
+ static u8 addr[2] = {READ_ONE_EVENT, 0};
+ int retry = (FTS_RETRY_COUNT * 5);
+ int total_length = 0;
+ int offset = 0;
+ int ret = 0;
+ int i = 0;
+
+ memset(&info->prd_info, 0, sizeof(struct fts_prd_info));
+
+ info->fts_interrupt_set(info, INT_DISABLE);
+ info->fts_command(info, SENSEOFF);
+
+ fts_command(info,LOCKDOWN_READ);
+
+ while (retry--) {
+ fts_delay(5);
+
+ ret = fts_read_reg(info, &addr[0], 1, &data[0], FTS_EVENT_SIZE);
+ if (ret < 0) {
+ tsp_debug_err(info->dev, "ftm4_reg_read fail\n");
+ goto error;
+ }
+
+ if (data[0] == EVENTID_LOCKDOWN_CODE) {
+ total_length = data[1];
+ offset = data[2];
+
+ tsp_debug_dbg(info->dev, "Total length : %d | offset : %d\n", total_length, offset);
+
+ if (total_length == FTS_LOCKDOWNCODE_SIZE) {
+ for (i = 0; i < 4; i++) {
+ if (offset+i >= FTS_LOCKDOWNCODE_SIZE) {
+ strncpy(&info->prd_info.product_id[0], &prd_info[0], 3);
+ info->prd_info.chip_rev = (prd_info[3] >> 4) & 0xF;
+ info->prd_info.fpc_rev = prd_info[3] & 0xF;
+ info->prd_info.t_sensor_rev = prd_info[4];
+ info->prd_info.site = prd_info[5];
+ info->prd_info.inspector_no = prd_info[6];
+ strncpy(&info->prd_info.date[0], &prd_info[7], 6);
+
+ info->fts_command(info, SENSEON);
+ info->fts_interrupt_set(info, INT_ENABLE);
+ return 0;
+ }
+ prd_info[offset+i] = data[i+3];
+ tsp_debug_dbg(info->dev, "[fts_lockdown_read] code [0x%02X]\n", prd_info[offset+i]);
+ }
+ }
+ } else if ((data[0] == EVENTID_ERROR) && (data[1] == EVENTID_ERROR_LOCKDOWN)) {
+ switch (data[2] & 0x0F) {
+ case 0x01:
+ tsp_debug_err(info->dev, "[fts_lockdown_read] Error - no lockdown code");
+ goto error;
+ case 0x02:
+ tsp_debug_err(info->dev, "[fts_lockdown_read] Error - Data Corrupted");
+ goto error;
+ case 0x03:
+ tsp_debug_err(info->dev, "[fts_lockdown_read] Error - Command format invalid");
+ goto error;
+ }
+ }
+ }
+
+ tsp_debug_err(info->dev, "[fts_lockdown_read] Error - Time over, retry =%d", retry);
+error:
+ info->fts_command(info, SENSEON);
+ info->fts_interrupt_set(info, INT_ENABLE);
+
+ return -EINVAL;
+}
+
+int fts_get_version_info(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char addr[3] = {0xD0, 0x00, 0x56};
+ unsigned char buff[7] = {0};
+ char str[16] = {0};
+ int str_ret = 0;
+
+ rc = fts_read_reg(info, &addr[0], 3, &buff[0], 7);
+ if (rc < 0) {
+ tsp_debug_err(&info->client->dev, "FTS get version info fail!\n");
+ goto error;
+ }
+
+ info->fw_version_of_ic = buff[1] + (buff[2] << 8);
+ info->config_version_of_ic = buff[3] + (buff[4] << 8);
+ info->fw_main_version_of_ic = buff[6] + (buff[5] << 8);
+ info->ic_fw_ver.build = ((buff[5] >> 4) & 0x0F);
+ info->ic_fw_ver.major = (buff[5] & 0x0F);
+ info->ic_fw_ver.minor = buff[6];
+
+ str_ret += snprintf(str + str_ret, sizeof(str) - str_ret,
+ "v%d.%02d",
+ info->ic_fw_ver.major,
+ info->ic_fw_ver.minor);
+
+ if (info->ic_fw_ver.build) {
+ str_ret += snprintf(str + str_ret, sizeof(str) - str_ret,
+ ".%d",
+ info->ic_fw_ver.build);
+ }
+
+ fts_get_afe_info(info);
+ fts_product_info_read(info);
+
+ tsp_debug_info(&info->client->dev,
+ "IC Firmware Version : 0x%04X [%s] "
+ "IC Config Version : 0x%04X "
+ "IC Main Version : 0x%04X "
+ "AFE Version : 0x%02X\n",
+ info->fw_version_of_ic, str,
+ info->config_version_of_ic,
+ info->fw_main_version_of_ic,
+ info->afe_ver);
+ tsp_debug_info(&info->client->dev,
+ "product id : [%02x %02x %02x]\n",
+ info->prd_info.product_id[0],
+ info->prd_info.product_id[1],
+ info->prd_info.product_id[2]);
+ tsp_debug_info(&info->client->dev,
+ "Chip reveion : %d, fpc : %d, t_sensor: %d site : %d , inspector_no : %d\n",
+ info->prd_info.chip_rev, info->prd_info.fpc_rev, info->prd_info.t_sensor_rev,
+ info->prd_info.site, info->prd_info.inspector_no);
+ tsp_debug_info(&info->client->dev,
+ "date : %02d.%02d.%02d %02d:%02d:%02d\n",
+ info->prd_info.date[0], info->prd_info.date[1], info->prd_info.date[2],
+ info->prd_info.date[3], info->prd_info.date[4], info->prd_info.date[5]);
+
+error:
+ return rc;
+}
+
+int fts_read_chip_id(struct fts_ts_info *info)
+{
+ unsigned char regAdd[3] = {0xB6, 0x00, 0x04};
+ unsigned char val[7] = {0};
+ int ret = 0;
+
+ ret = fts_read_reg(info, regAdd, 3, (unsigned char *)val, 7);
+ if (ret < 0) {
+ tsp_debug_err(&info->client->dev, "%s failed. ret: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ tsp_debug_dbg(&info->client->dev,
+ "FTS %02X%02X%02X = %02X %02X %02X %02X %02X %02X\n",
+ regAdd[0], regAdd[1], regAdd[2],
+ val[1], val[2], val[3], val[4],
+ val[5], val[6]);
+
+ if ((val[1] == FTS_ID0) && (val[2] == FTS_ID1)) {
+ if ((val[5] == 0x00) && (val[6] == 0x00)) {
+ tsp_debug_err(&info->client->dev,
+ "\n\r[fts_read_chip_id] Error - No FW : %02X %02X",
+ val[5], val[6]);
+ info->flash_corruption_info.fw_broken = true;
+ } else {
+ tsp_debug_info(&info->client->dev,
+ "FTS Chip ID : %02X %02X\n",
+ val[1], val[2]);
+ }
+ } else
+ return -FTS_ERROR_INVALID_CHIP_ID;
+
+ return ret;
+}
+
+int fts_wait_for_ready(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char addr;
+ unsigned char data[FTS_EVENT_SIZE];
+ int retry = 0;
+ int err_cnt = 0;
+
+ memset(data, 0x0, FTS_EVENT_SIZE);
+
+ addr = READ_ONE_EVENT;
+
+ while (fts_read_reg(info, &addr, 1,
+ (unsigned char *)data, FTS_EVENT_SIZE)) {
+ if (data[0] == EVENTID_CONTROLLER_READY) {
+ rc = 0;
+ break;
+ }
+
+ if (data[0] == EVENTID_ERROR) {
+ if (data[1] == EVENTID_ERROR_FLASH_CORRUPTION) {
+ rc = -FTS_ERROR_EVENT_ID;
+
+ tsp_debug_err(&info->client->dev,
+ "%s: flash corruption:%02X,%02X,%02X\n",
+ __func__, data[0],
+ data[1], data[2]);
+
+ switch (data[2]) {
+ case EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1:
+ info->flash_corruption_info.cfg_broken = true;
+ break;
+ case EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2:
+ info->flash_corruption_info.cfg_broken = true;
+ break;
+ case EVENTID_ERROR_CX_FLASH_CORRUPTION:
+ info->flash_corruption_info.cx_broken = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (err_cnt++ > 32) {
+ rc = -FTS_ERROR_EVENT_ID;
+ break;
+ }
+ continue;
+ }
+
+ if (retry++ > FTS_RETRY_COUNT) {
+ rc = -FTS_ERROR_TIMEOUT;
+ tsp_debug_err(&info->client->dev, "%s: Time Over\n",
+ __func__);
+
+ if (info->lowpower_mode) {
+ schedule_delayed_work(&info->reset_work,
+ msecs_to_jiffies(10));
+ }
+ break;
+ }
+ fts_delay(20);
+ }
+
+ tsp_debug_dbg(&info->client->dev,
+ "%s: %02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n",
+ __func__, data[0], data[1], data[2], data[3],
+ data[4], data[5], data[6], data[7]);
+
+ return rc;
+}
+
+int fts_get_channel_info(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char cmd[4] = { 0xB2, 0x00, 0x14, 0x02 };
+ unsigned char data[FTS_EVENT_SIZE];
+ int retry = 0;
+
+ memset(data, 0x0, FTS_EVENT_SIZE);
+
+ fts_write_reg(info, &cmd[0], 4);
+ cmd[0] = READ_ONE_EVENT;
+ while (fts_read_reg
+ (info, &cmd[0], 1, (unsigned char *)data, FTS_EVENT_SIZE)) {
+ if (data[0] == EVENTID_RESULT_READ_REGISTER) {
+ if ((data[1] == cmd[1]) && (data[2] == cmd[2])) {
+ info->SenseChannelLength = data[3];
+ info->ForceChannelLength = data[4];
+ rc = 0;
+ break;
+ }
+ }
+ if (retry++ > 30) {
+ rc = -1;
+ tsp_debug_err(&info->client->dev,
+ "Time over - wait for channel info\n");
+ break;
+ }
+ fts_delay(5);
+ }
+ return rc;
+}
+
+#ifdef FTS_SUPPORT_NOISE_PARAM
+int fts_get_noise_param_address(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char regAdd[3];
+ unsigned char rData[3];
+ struct fts_noise_param *noise_param;
+ int i;
+
+ noise_param = (struct fts_noise_param *)&info->noise_param;
+
+ regAdd[0] = 0xd0;
+ regAdd[1] = 0x00;
+ regAdd[2] = 32 * 2;
+
+ if (info->digital_rev == FTS_DIGITAL_REV_1)
+ rc = fts_read_reg(info, regAdd, 3,
+ (unsigned char *)noise_param->pAddr, 2);
+ else {
+ rc = fts_read_reg(info, regAdd, 3, (unsigned char *)rData, 3);
+ noise_param->pAddr[0] = rData[1] + (rData[2]<<8);
+ }
+
+ for (i = 1; i < MAX_NOISE_PARAM; i++)
+ noise_param->pAddr[i] = noise_param->pAddr[0] + i * 2;
+
+ for (i = 0; i < MAX_NOISE_PARAM; i++)
+ tsp_debug_dbg(&info->client->dev,
+ "Get Noise Param%d Address = 0x%4x\n",
+ i, noise_param->pAddr[i]);
+
+ return rc;
+}
+
+static int fts_get_noise_param(struct fts_ts_info *info)
+{
+ int rc = 0;
+ unsigned char regAdd[3];
+ unsigned char data[MAX_NOISE_PARAM * 2];
+ struct fts_noise_param *noise_param;
+ int i;
+ unsigned char buf[3];
+
+ noise_param = (struct fts_noise_param *)&info->noise_param;
+ memset(data, 0x0, MAX_NOISE_PARAM * 2);
+
+ for (i = 0; i < MAX_NOISE_PARAM; i++) {
+ regAdd[0] = 0xb3;
+ regAdd[1] = 0x00;
+ regAdd[2] = 0x10;
+ fts_write_reg(info, regAdd, 3);
+
+ regAdd[0] = 0xb1;
+ regAdd[1] = (noise_param->pAddr[i] >> 8) & 0xff;
+ regAdd[2] = noise_param->pAddr[i] & 0xff;
+ rc = fts_read_reg(info, regAdd, 3, &buf[0], 3);
+
+ noise_param->pData[i] = buf[1]+(buf[2]<<8);
+ }
+
+ for (i = 0; i < MAX_NOISE_PARAM; i++) {
+ tsp_debug_dbg(&info->client->dev,
+ "Get Noise Param%d Address "
+ "[ 0x%04x ] = 0x%04x\n", i,
+ noise_param->pAddr[i],
+ noise_param->pData[i]);
+ }
+
+ return rc;
+}
+
+static int fts_set_noise_param(struct fts_ts_info *info)
+{
+ int i;
+ unsigned char regAdd[5];
+ struct fts_noise_param *noise_param;
+
+ noise_param = (struct fts_noise_param *)&info->noise_param;
+
+ for (i = 0; i < MAX_NOISE_PARAM; i++) {
+ regAdd[0] = 0xb3;
+ regAdd[1] = 0x00;
+ regAdd[2] = 0x10;
+ fts_write_reg(info, regAdd, 3);
+
+ regAdd[0] = 0xb1;
+ regAdd[1] = (noise_param->pAddr[i] >> 8) & 0xff;
+ regAdd[2] = noise_param->pAddr[i] & 0xff;
+ regAdd[3] = noise_param->pData[i] & 0xff;
+ regAdd[4] = (noise_param->pData[i] >> 8) & 0xff;
+ fts_write_reg(info, regAdd, 5);
+ }
+
+ for (i = 0; i < MAX_NOISE_PARAM; i++) {
+ tsp_debug_dbg(&info->client->dev,
+ "Set Noise Param%d Address "
+ "[ 0x%04x ] = 0x%04x\n",
+ i,
+ noise_param->pAddr[i],
+ noise_param->pData[i]);
+ }
+
+ return 0;
+}
+#endif
+
+int fts_cmd_completion_check(struct fts_ts_info *info, uint8_t event1, uint8_t event2, uint8_t event3)
+{
+ unsigned char val[8];
+ unsigned char reg[2] = {0x85, 0};
+ int retry = 100;
+ int rc = 0;
+
+ while (retry--) {
+ fts_delay(10);
+ info->fts_read_reg(info, &reg[0], 1, &val[0], FTS_EVENT_SIZE);
+ if ((val[0] == event1) && (val[1] == event2) && (val[2] == event3)) {
+ tsp_debug_info(&info->client->dev,
+ "\n\r[fts_cmd_completion_check] OK [%02x][%02x][%02x]", val[0], val[1], val[2]);
+ return rc;
+ } else if (val[0] == 0x0F) {
+ tsp_debug_err(&info->client->dev,
+ "\n\r[fts_cmd_completion_check] Error - [%02x][%02x][%02x]", val[0], val[1], val[2]);
+ }
+ }
+
+ rc = -1;
+ if (retry <= 0)
+ tsp_debug_err(&info->client->dev,
+ "\n\r[fts_cmd_completion_check] Error - Time Over [%02x][%02x][%02x]", event1, event2, event3);
+ return rc;
+}
+
+static int fts_init(struct fts_ts_info *info)
+{
+ unsigned char val[16];
+ unsigned char regAdd[8];
+ int rc = 0;
+
+ fts_systemreset(info);
+
+ rc = fts_wait_for_ready(info);
+ if (rc == -FTS_ERROR_EVENT_ID) {
+ info->fw_version_of_ic = 0;
+ info->config_version_of_ic = 0;
+ info->fw_main_version_of_ic = 0;
+ } else {
+ fts_get_version_info(info);
+ }
+
+ rc = fts_read_chip_id(info);
+ if (rc < 0)
+ tsp_debug_err(&info->client->dev, "%s: Failed to fts_read_chip_id\n",
+ __func__);
+
+/*
+ rc = fts_fw_update(info);
+ if (rc < 0)
+ tsp_debug_err(&info->client->dev, "%s: Failed to firmware update\n",
+ __func__);
+*/
+
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+ info->digital_rev = FTS_DIGITAL_REV_2;
+ rc = info->fts_get_channel_info(info);
+ if (rc == 0) {
+ tsp_debug_dbg(&info->client->dev,
+ "FTS Sense(%02d) Force(%02d)\n",
+ info->SenseChannelLength,
+ info->ForceChannelLength);
+ } else {
+ tsp_debug_err(&info->client->dev,
+ "FTS read failed rc = %d\n", rc);
+ tsp_debug_err(&info->client->dev,
+ "FTS Initialise Failed\n");
+ }
+ info->pFrame =
+ kzalloc(info->SenseChannelLength * info->ForceChannelLength * 2,
+ GFP_KERNEL);
+ if (info->pFrame == NULL) {
+ tsp_debug_err(&info->client->dev,
+ "FTS pFrame kzalloc Failed\n");
+ return -ENOMEM;
+ }
+ info->cx_data = kzalloc(info->SenseChannelLength *
+ info->ForceChannelLength, GFP_KERNEL);
+ if (!info->cx_data)
+ tsp_debug_err(&info->client->dev,
+ "%s: cx_data kzalloc Failed\n", __func__);
+#endif
+ fts_command(info, SENSEON);
+
+#ifdef FTS_SUPPORT_NOISE_PARAM
+ fts_get_noise_param_address(info);
+#endif
+ /* fts driver set functional feature */
+ info->touch_count = 0;
+ info->palm_pressed = false;
+ info->flip_enable = false;
+ info->mainscr_disable = false;
+
+ info->deepsleep_mode = false;
+ info->wirelesscharger_mode = false;
+ info->lowpower_mode = false;
+ info->lowpower_flag = 0x00;
+ info->fts_power_state = FTS_POWER_STATE_ACTIVE;
+
+ fts_command(info, FORCECALIBRATION);
+
+ fts_interrupt_set(info, INT_ENABLE);
+
+ memset(val, 0x0, 4);
+ regAdd[0] = READ_STATUS;
+ fts_read_reg(info, regAdd, 1, (unsigned char *)val, 4);
+ tsp_debug_dbg(&info->client->dev,
+ "FTS ReadStatus(0x84) : "
+ "%02X %02X %02X %02X\n",
+ val[0], val[1], val[2], val[3]);
+
+ tsp_debug_info(&info->client->dev,
+ "FTS Initialized\n");
+
+ return 0;
+}
+
+static void fts_debug_msg_event_handler(struct fts_ts_info *info,
+ unsigned char data[])
+{
+ tsp_debug_dbg(&info->client->dev,
+ "%s: %02X %02X %02X %02X "
+ "%02X %02X %02X %02X\n", __func__,
+ data[0], data[1], data[2], data[3],
+ data[4], data[5], data[6], data[7]);
+}
+
+static unsigned char fts_event_handler_type_b(struct fts_ts_info *info,
+ unsigned char data[],
+ unsigned char LeftEvent)
+{
+ unsigned char EventNum = 0;
+ unsigned char NumTouches = 0;
+ unsigned char TouchID = 0, EventID = 0, status = 0;
+ unsigned char LastLeftEvent = 0;
+ int x = 0, y = 0, z = 0;
+ int bw = 0, bh = 0, palm = 0;
+ int orient = 0;
+
+#if defined(CONFIG_INPUT_BOOSTER)
+ bool booster_restart = false;
+#endif
+
+ for (EventNum = 0; EventNum < LeftEvent; EventNum++) {
+#ifdef DEBUG
+ tsp_debug_dbg(&info->client->dev,
+ "%d %2x %2x %2x %2x %2x %2x %2x %2x\n",
+ EventNum,
+ data[EventNum * FTS_EVENT_SIZE],
+ data[EventNum * FTS_EVENT_SIZE+1],
+ data[EventNum * FTS_EVENT_SIZE+2],
+ data[EventNum * FTS_EVENT_SIZE+3],
+ data[EventNum * FTS_EVENT_SIZE+4],
+ data[EventNum * FTS_EVENT_SIZE+5],
+ data[EventNum * FTS_EVENT_SIZE+6],
+ data[EventNum * FTS_EVENT_SIZE+7]);
+ tsp_debug_dbg(&info->client->dev,
+ "fts_power_state (%d)\n",
+ info->fts_power_state );
+#endif
+
+ if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER)
+ EventID = data[EventNum * FTS_EVENT_SIZE] & 0xFF;
+ else
+ EventID = data[EventNum * FTS_EVENT_SIZE] & 0x0F;
+
+ if ((EventID >= 3) && (EventID <= 5)) {
+ LastLeftEvent = 0;
+ NumTouches = 1;
+ TouchID = (data[EventNum * FTS_EVENT_SIZE] >> 4) & 0x0F;
+ } else {
+ LastLeftEvent =
+ data[7 + EventNum * FTS_EVENT_SIZE] & 0x0F;
+ NumTouches =
+ (data[1 + EventNum * FTS_EVENT_SIZE] & 0xF0) >> 4;
+ TouchID = data[1 + EventNum * FTS_EVENT_SIZE] & 0x0F;
+ EventID = data[EventNum * FTS_EVENT_SIZE] & 0xFF;
+ status = data[1 + EventNum * FTS_EVENT_SIZE] & 0xFF;
+ }
+
+ switch (EventID) {
+ case EVENTID_NO_EVENT:
+ break;
+
+ case EVENTID_ERROR:
+ if (data[1 + EventNum *
+ FTS_EVENT_SIZE] == 0x08) {
+ /* Get Auto tune fail event */
+ if (data[2 + EventNum *
+ FTS_EVENT_SIZE] == 0x00) {
+ tsp_debug_err(&info->client->dev,
+ "[FTS] Fail Mutual Auto tune\n");
+ } else if (data[2 + EventNum *
+ FTS_EVENT_SIZE] == 0x01) {
+ tsp_debug_err(&info->client->dev,
+ "[FTS] Fail Self Auto tune\n");
+ }
+ } else if (data[1 + EventNum *
+ FTS_EVENT_SIZE] == 0x09)
+ /* Get detect SYNC fail event */
+ tsp_debug_err(&info->client->dev,
+ "[FTS] Fail detect SYNC\n");
+ break;
+
+ case EVENTID_HOVER_ENTER_POINTER:
+ case EVENTID_HOVER_MOTION_POINTER:
+ x = ((data[4 + EventNum * FTS_EVENT_SIZE] & 0xF0) >> 4)
+ | ((data[2 + EventNum * FTS_EVENT_SIZE]) << 4);
+ y = ((data[4 + EventNum * FTS_EVENT_SIZE] & 0x0F) |
+ ((data[3 + EventNum * FTS_EVENT_SIZE]) << 4));
+
+ z = data[5 + EventNum * FTS_EVENT_SIZE];
+
+ input_mt_slot(info->input_dev, 0);
+ input_mt_report_slot_state(info->input_dev,
+ MT_TOOL_FINGER, 1);
+
+ input_report_key(info->input_dev, BTN_TOUCH, 0);
+ input_report_key(info->input_dev, BTN_TOOL_FINGER, 1);
+
+ input_report_abs(info->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(info->input_dev, ABS_MT_DISTANCE, 255 - z);
+ break;
+
+ case EVENTID_HOVER_LEAVE_POINTER:
+ input_mt_slot(info->input_dev, 0);
+ input_mt_report_slot_state(info->input_dev,
+ MT_TOOL_FINGER, 0);
+ break;
+
+ case EVENTID_ENTER_POINTER:
+ if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER)
+ break;
+
+ info->touch_count++;
+#if defined(CONFIG_INPUT_BOOSTER)
+ booster_restart = true;
+#endif
+ case EVENTID_MOTION_POINTER:
+ if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
+ tsp_debug_info(&info->client->dev,
+ "%s: low power mode\n", __func__);
+ fts_release_all_finger(info);
+ break;
+ }
+
+ if (info->touch_count == 0) {
+ tsp_debug_info(&info->client->dev,
+ "%s: count 0\n", __func__);
+ fts_release_all_finger(info);
+ break;
+ }
+
+ if ((EventID == EVENTID_MOTION_POINTER) &&
+ (info->finger[TouchID].state ==
+ EVENTID_LEAVE_POINTER)) {
+ tsp_debug_info(&info->client->dev,
+ "%s: state leave but point is moved.\n", __func__);
+ break;
+ }
+
+ if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER)
+ break;
+
+ x = ((data[1 + EventNum * FTS_EVENT_SIZE]
+ & 0xFF) << 4) +
+ ((data[3 + EventNum * FTS_EVENT_SIZE]
+ & 0xF0) >> 4);
+ y = ((data[2 + EventNum * FTS_EVENT_SIZE]
+ & 0xFF) << 4) +
+ (data[3 + EventNum * FTS_EVENT_SIZE]
+ & 0xF);
+
+ z = data[4 + EventNum * FTS_EVENT_SIZE];
+
+ bw = data[6 + EventNum * FTS_EVENT_SIZE];
+ bh = data[7 + EventNum * FTS_EVENT_SIZE];
+
+ orient = data[5 + EventNum * FTS_EVENT_SIZE];
+
+ if (z == 255) {
+ tsp_debug_info(&info->client->dev,
+ "%s: Palm Detected\n", __func__);
+ tsp_debug_info(&info->client->dev, "%s: "
+ "[ID:%2d X:%4d Y:%4d Z:%4d "
+ " WM:%4d Wm:%4d Orient:%2d "
+ "tc:%2d]\n", __func__,
+ TouchID, x, y, z,
+ max(bw, bh), min(bw, bh),
+ orient, info->touch_count);
+ info->palm_pressed = true;
+ fts_release_all_finger(info);
+ return 0;
+ }
+
+ input_mt_slot(info->input_dev, TouchID);
+ input_mt_report_slot_state(info->input_dev,
+ MT_TOOL_FINGER,
+ 1 + (palm << 1));
+
+ input_report_key(info->input_dev, BTN_TOUCH, 1);
+ input_report_key(info->input_dev,
+ BTN_TOOL_FINGER, 1);
+ input_report_abs(info->input_dev,
+ ABS_MT_POSITION_X, x);
+ input_report_abs(info->input_dev,
+ ABS_MT_POSITION_Y, y);
+
+ input_report_abs(info->input_dev,
+ ABS_MT_TOUCH_MAJOR, max(bw,
+ bh));
+
+ input_report_abs(info->input_dev,
+ ABS_MT_TOUCH_MINOR, min(bw,
+ bh));
+
+ input_report_abs(info->input_dev,
+ ABS_MT_PRESSURE, z);
+
+ input_report_abs(info->input_dev,
+ ABS_MT_ORIENTATION, orient);
+
+ info->finger[TouchID].lx = x;
+ info->finger[TouchID].ly = y;
+
+ break;
+
+ case EVENTID_LEAVE_POINTER:
+ if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER)
+ break;
+
+ if (info->palm_pressed) {
+ tsp_debug_info(&info->client->dev,
+ "%s: Palm Released\n", __func__);
+ info->palm_pressed = false;
+ return 0;
+ }
+
+ if (info->touch_count <= 0) {
+ tsp_debug_info(&info->client->dev,
+ "%s: count 0\n", __func__);
+ fts_release_all_finger(info);
+ break;
+ }
+
+ info->touch_count--;
+
+ input_mt_slot(info->input_dev, TouchID);
+
+ input_mt_report_slot_state(info->input_dev,
+ MT_TOOL_FINGER, 0);
+
+ if (info->touch_count == 0) {
+ /* Clear BTN_TOUCH when All touch are released */
+ input_report_key(info->input_dev, BTN_TOUCH, 0);
+ input_report_key(info->input_dev, BTN_TOOL_FINGER, 0);
+
+ }
+ break;
+ case EVENTID_STATUS_EVENT:
+ if (status == STATUS_EVENT_GLOVE_MODE) {
+
+ } else if (status == STATUS_EVENT_RAW_DATA_READY) {
+ unsigned char regAdd[4] = {0xB0, 0x01, 0x29, 0x01};
+
+ fts_write_reg(info, &regAdd[0], 4);
+
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received the Raw Data Ready Event\n");
+ } else if (status == STATUS_EVENT_FORCE_CAL_MUTUAL) {
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received Force Calibration Mutual only Event\n");
+ } else if (status == STATUS_EVENT_FORCE_CAL_SELF) {
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received Force Calibration Self only Event\n");
+ } else if (status == STATUS_EVENT_WATERMODE_ON) {
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received Water Mode On Event\n");
+ } else if (status == STATUS_EVENT_WATERMODE_OFF) {
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received Water Mode Off Event\n");
+ } else if (status == STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK) {
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received Mutual Calib Frame Check Event\n");
+ } else if (status == STATUS_EVENT_SELF_CAL_FRAME_CHECK) {
+ tsp_debug_dbg(&info->client->dev, "[FTS] Received Self Calib Frame Check Event\n");
+ } else {
+ fts_debug_msg_event_handler(info,
+ &data[EventNum *
+ FTS_EVENT_SIZE]);
+ }
+ break;
+
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+ case EVENTID_RESULT_READ_REGISTER:
+ procedure_cmd_event(info, &data[EventNum * FTS_EVENT_SIZE]);
+ break;
+#endif /* FEATURE_FTS_PRODUCTION_CODE */
+
+ default:
+ fts_debug_msg_event_handler(info,
+ &data[EventNum *
+ FTS_EVENT_SIZE]);
+ continue;
+ }
+
+ if (EventID == EVENTID_ENTER_POINTER)
+ tsp_debug_event(&info->client->dev,
+ "[P] tID:%d x:%d y:%d w:%d "
+ "h:%d z:%d p:%d tc:%d tm:%d\n",
+ TouchID, x, y, bw,
+ bh, z, palm, info->touch_count, info->touch_mode);
+ else if (EventID == EVENTID_HOVER_ENTER_POINTER)
+ tsp_debug_event(&info->client->dev,
+ "[HP] tID:%d x:%d y:%d z:%d\n",
+ TouchID, x, y, z);
+
+ else if (EventID == EVENTID_LEAVE_POINTER) {
+ tsp_debug_event(&info->client->dev,
+ "[R] tID:%d mc: %d tc:%d lx: %d ly: %d "
+ "Ver[%02X%04X%01X%01X]\n",
+ TouchID, info->finger[TouchID].mcount, info->touch_count,
+ info->finger[TouchID].lx,
+ info->finger[TouchID].ly,
+ info->panel_revision,
+ info->fw_main_version_of_ic,
+ info->flip_enable,
+ info->mainscr_disable);
+
+ info->finger[TouchID].mcount = 0;
+ } else if (EventID == EVENTID_HOVER_LEAVE_POINTER) {
+ tsp_debug_event(&info->client->dev,
+ "[HR] tID:%d Ver[%02X%04X%01X]\n",
+ TouchID,
+ info->panel_revision,
+ info->fw_main_version_of_ic,
+ info->flip_enable);
+ info->finger[TouchID].mcount = 0;
+ } else if (EventID == EVENTID_MOTION_POINTER)
+ info->finger[TouchID].mcount++;
+
+ if ((EventID == EVENTID_ENTER_POINTER) ||
+ (EventID == EVENTID_MOTION_POINTER) ||
+ (EventID == EVENTID_LEAVE_POINTER))
+ info->finger[TouchID].state = EventID;
+ }
+
+ input_sync(info->input_dev);
+
+#if defined(CONFIG_INPUT_BOOSTER)
+ if ((EventID == EVENTID_ENTER_POINTER)
+ || (EventID == EVENTID_LEAVE_POINTER)) {
+ if (booster_restart)
+ input_booster_send_event(BOOSTER_DEVICE_TOUCH, BOOSTER_MODE_ON);
+ if (!info->touch_count)
+ input_booster_send_event(BOOSTER_DEVICE_TOUCH, BOOSTER_MODE_OFF);
+ }
+#endif
+
+ return LastLeftEvent;
+}
+
+#ifdef FTS_SUPPORT_TA_MODE
+static void fts_ta_cb(struct fts_callbacks *cb, int ta_status)
+{
+ struct fts_ts_info *info =
+ container_of(cb, struct fts_ts_info, callbacks);
+
+ if (ta_status == 0x01 || ta_status == 0x03) {
+ fts_command(info, FTS_CMD_CHARGER_PLUGGED);
+ info->TA_Pluged = true;
+ tsp_debug_dbg(&info->client->dev,
+ "%s: device_control : CHARGER CONNECTED, ta_status : %x\n",
+ __func__, ta_status);
+ } else {
+ fts_command(info, FTS_CMD_CHARGER_UNPLUGGED);
+ info->TA_Pluged = false;
+ tsp_debug_dbg(&info->client->dev,
+ "%s: device_control : CHARGER DISCONNECTED, ta_status : %x\n",
+ __func__, ta_status);
+ }
+}
+#endif
+
+/**
+ * fts_interrupt_handler()
+ *
+ * Called by the kernel when an interrupt occurs (when the sensor
+ * asserts the attention irq).
+ *
+ * This function is the ISR thread and handles the acquisition
+ * and the reporting of finger data when the presence of fingers
+ * is detected.
+ */
+static irqreturn_t fts_interrupt_handler(int irq, void *handle)
+{
+ struct fts_ts_info *info = handle;
+ unsigned char regAdd[4] = {0xB6, 0x00, 0x23, READ_ALL_EVENT};
+ unsigned short evtcount = 0;
+
+ evtcount = 0;
+
+ fts_read_reg(info, &regAdd[0], 3, (unsigned char *)&evtcount, 2);
+ evtcount = evtcount >> 8;
+ evtcount = evtcount / 2;
+
+ if (evtcount > FTS_FIFO_MAX)
+ evtcount = FTS_FIFO_MAX;
+
+ if (evtcount > 0) {
+ memset(info->data, 0x0, FTS_EVENT_SIZE * evtcount);
+ fts_read_reg(info, &regAdd[3], 1, (unsigned char *)info->data,
+ FTS_EVENT_SIZE * evtcount);
+ fts_event_handler_type_b(info, info->data, evtcount);
+ }
+ return IRQ_HANDLED;
+}
+
+static void fts_irq_enable(struct fts_ts_info *info,
+ bool enable)
+{
+ spin_lock(&info->lock);
+
+ if (enable) {
+ if (atomic_cmpxchg(&info->irq_enabled, 0, 1) == 0) {
+ tsp_debug_dbg(info->dev, "enable_irq\n");
+ enable_irq(info->irq);
+ }
+ } else {
+ if (atomic_cmpxchg(&info->irq_enabled, 1, 0) == 1) {
+ tsp_debug_dbg(info->dev, "disable_irq\n");
+ disable_irq_nosync(info->irq);
+ }
+ }
+
+ spin_unlock(&info->lock);
+}
+
+#ifdef CONFIG_OF
+#ifdef FTS_SUPPORT_TA_MODE
+struct fts_callbacks *fts_charger_callbacks;
+void tsp_charger_infom(bool en)
+{
+ pr_err("[TSP]%s: ta:%d\n", __func__, en);
+
+ if (fts_charger_callbacks && fts_charger_callbacks->inform_charger)
+ fts_charger_callbacks->inform_charger(fts_charger_callbacks, en);
+}
+static void fts_tsp_register_callback(void *cb)
+{
+ fts_charger_callbacks = cb;
+}
+#endif
+static int fts_power_ctrl(void *data, bool on)
+{
+ struct fts_ts_info *info = (struct fts_ts_info *)data;
+ const struct fts_i2c_platform_data *pdata = info->board;
+ struct device *dev = &info->client->dev;
+ struct regulator *regulator_dvdd = NULL;
+ struct regulator *regulator_avdd = NULL;
+ static bool enabled;
+ int retval = 0;
+
+ if (enabled == on)
+ return retval;
+
+ /* touch power init */
+ if (gpio_is_valid(pdata->vdd_gpio)) {
+ gpio_request(pdata->vdd_gpio, "touch-vdd");
+ } else {
+ regulator_avdd = regulator_get(NULL, pdata->regulator_avdd);
+ if (IS_ERR_OR_NULL(regulator_avdd)) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to get %s regulator.\n",
+ __func__, pdata->regulator_avdd);
+ goto out;
+ }
+ }
+ if (gpio_is_valid(pdata->vio_gpio)) {
+ gpio_request(pdata->vio_gpio, "touch-vio");
+ } else {
+ regulator_dvdd = regulator_get(NULL, pdata->regulator_dvdd);
+ if (IS_ERR_OR_NULL(regulator_dvdd)) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to get %s regulator.\n",
+ __func__, pdata->regulator_dvdd);
+ goto out;
+ }
+ }
+
+ tsp_debug_info(dev, "%s: %s\n", __func__, on ? "on" : "off");
+
+ if (on) {
+ if (gpio_is_valid(pdata->vdd_gpio)) {
+ retval = gpio_direction_output(pdata->vdd_gpio, 1);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable vdd: %d\n",
+ __func__, retval);
+ }
+ } else if (!IS_ERR_OR_NULL(regulator_avdd)) {
+ retval = regulator_enable(regulator_avdd);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable avdd: %d\n",
+ __func__, retval);
+ goto out;
+ }
+ }
+
+ if (gpio_is_valid(pdata->vio_gpio)) {
+ retval = gpio_direction_output(pdata->vio_gpio, 1);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable vio: %d\n",
+ __func__, retval);
+ }
+ } else if (!IS_ERR_OR_NULL(regulator_dvdd)) {
+ retval = regulator_enable(regulator_dvdd);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable dvdd: %d\n",
+ __func__, retval);
+ goto out;
+ }
+ }
+
+ retval = pinctrl_select_state(pdata->pinctrl, pdata->pins_default);
+ if (retval < 0)
+ tsp_debug_err(dev, "%s: "
+ "Failed to configure tsp_attn pin\n",
+ __func__);
+
+ fts_delay(5);
+ } else {
+ if (gpio_is_valid(pdata->vio_gpio)) {
+ retval = gpio_direction_output(pdata->vio_gpio, 0);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable vio: %d\n",
+ __func__, retval);
+ }
+ } else if (!IS_ERR_OR_NULL(regulator_dvdd)) {
+ retval = regulator_disable(regulator_dvdd);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable dvdd: %d\n",
+ __func__, retval);
+ goto out;
+ }
+ }
+
+ if (gpio_is_valid(pdata->vdd_gpio)) {
+ retval = gpio_direction_output(pdata->vdd_gpio, 0);
+ if (retval)
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable vdd: %d\n",
+ __func__, retval);
+ } else if (!IS_ERR_OR_NULL(regulator_avdd)) {
+ retval = regulator_disable(regulator_avdd);
+ if (retval) {
+ tsp_debug_err(dev, "%s: "
+ "Failed to enable avdd: %d\n",
+ __func__, retval);
+ goto out;
+ }
+ }
+
+ retval = pinctrl_select_state(pdata->pinctrl, pdata->pins_sleep);
+ if (retval < 0)
+ tsp_debug_err(dev, "%s: Failed to "
+ "configure tsp_attn pin\n", __func__);
+ }
+
+ enabled = on;
+
+out:
+ regulator_put(regulator_dvdd);
+ regulator_put(regulator_avdd);
+
+ return retval;
+}
+
+static int fts_parse_dt(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct fts_i2c_platform_data *pdata = dev->platform_data;
+ struct device_node *np = dev->of_node;
+ u32 coords[2], lines[2];
+ int retval = 0;
+
+ pdata->tspid = of_get_named_gpio(np, "stm,tspid_gpio", 0);
+ if (gpio_is_valid(pdata->tspid))
+ tsp_debug_dbg(dev,
+ "TSP_ID : %d\n",
+ gpio_get_value(pdata->tspid));
+ else
+ tsp_debug_err(dev,
+ "Failed to get tspid gpio\n");
+
+ pdata->tspid2 = of_get_named_gpio(np, "stm,tspid2_gpio", 0);
+ if (gpio_is_valid(pdata->tspid2))
+ tsp_debug_dbg(dev,
+ "TSP_ID2 : %d\n",
+ gpio_get_value(pdata->tspid2));
+ else
+ tsp_debug_err(dev,
+ "Failed to get tspid2 gpio\n");
+
+ pdata->gpio = of_get_named_gpio(np, "stm,irq_gpio", 0);
+ if (gpio_is_valid(pdata->gpio)) {
+ retval = gpio_request_one(pdata->gpio,
+ GPIOF_DIR_IN, "stm,tsp_int");
+ if (retval) {
+ tsp_debug_err(dev,
+ "Unable to request tsp_int [%d]\n",
+ pdata->gpio);
+ return -EINVAL;
+ }
+ } else {
+ tsp_debug_err(dev,
+ "Failed to get irq gpio\n");
+ return -EINVAL;
+ }
+ client->irq = gpio_to_irq(pdata->gpio);
+
+ if (of_property_read_u32(np, "stm,irq_type", &pdata->irq_type)) {
+ tsp_debug_err(dev, "Failed to get irq_type property\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(np, "stm,grip_area", &pdata->grip_area))
+ tsp_debug_err(dev, "Failed to get grip_area property\n");
+
+ if (of_property_read_u32_array(np, "stm,max_coords", coords, 2)) {
+ tsp_debug_err(dev, "Failed to get max_coords property\n");
+ return -EINVAL;
+ }
+ pdata->max_x = coords[0];
+ pdata->max_y = coords[1];
+
+ if (of_property_read_u32_array(np, "stm,num_lines", lines, 2))
+ tsp_debug_dbg(dev, "skipped to get num_lines property\n");
+ else {
+ pdata->SenseChannelLength = lines[0];
+ pdata->ForceChannelLength = lines[1];
+ tsp_debug_dbg(dev, "num_of[rx,tx]: [%d,%d]\n",
+ pdata->SenseChannelLength, pdata->ForceChannelLength);
+ }
+
+ if (of_property_read_string(np, "stm,regulator_dvdd", &pdata->regulator_dvdd)) {
+ tsp_debug_err(dev,
+ "Failed to get regulator_dvdd name property\n");
+ }
+ if (of_property_read_string(np, "stm,regulator_avdd", &pdata->regulator_avdd)) {
+ tsp_debug_err(dev,
+ "Failed to get regulator_avdd name property\n");
+ }
+
+ pdata->vdd_gpio = of_get_named_gpio(np, "stm,vdd-gpio", 0);
+ if (gpio_is_valid(pdata->vdd_gpio))
+ tsp_debug_dbg(dev, "vdd_gpio : %d\n",
+ gpio_get_value(pdata->vdd_gpio));
+ else
+ tsp_debug_err(dev, "Failed to get vdd_gpio gpio\n");
+
+ pdata->vio_gpio = of_get_named_gpio(np, "stm,vio-gpio", 0);
+ if (gpio_is_valid(pdata->vio_gpio))
+ tsp_debug_dbg(dev, "vio_gpio :"
+ "%d\n", gpio_get_value(pdata->vio_gpio));
+ else
+ tsp_debug_err(dev, "Failed to get vio_gpio gpio\n");
+
+ pdata->power = fts_power_ctrl;
+
+ /* Optional parmeters(those values are not mandatory)
+ * do not return error value even if fail to get the value
+ */
+ of_property_read_string(np, "stm,firmware_name", &pdata->firmware_name);
+
+ if (of_property_read_string_index(np, "stm,project_name", 0, &pdata->project_name))
+ tsp_debug_dbg(dev,
+ "skipped to get project_name property\n");
+ if (of_property_read_string_index(np, "stm,project_name", 1, &pdata->model_name))
+ tsp_debug_dbg(dev,
+ "skipped to get model_name property\n");
+
+ pdata->max_width = 28;
+ pdata->support_hover = true;
+ pdata->support_mshover = true;
+#ifdef FTS_SUPPORT_TA_MODE
+ pdata->register_cb = fts_tsp_register_callback;
+#endif
+
+ return retval;
+}
+#endif
+
+static int fts_setup_drv_data(struct i2c_client *client)
+{
+ int retval = 0;
+ struct fts_i2c_platform_data *pdata;
+ struct fts_ts_info *info = NULL;
+
+ /* parse dt */
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct fts_i2c_platform_data), GFP_KERNEL);
+
+ if (!pdata) {
+ tsp_debug_err(&client->dev, "Failed to allocate platform data\n");
+ return -ENOMEM;
+ }
+
+ client->dev.platform_data = pdata;
+ retval = fts_parse_dt(client);
+ if (retval) {
+ tsp_debug_err(&client->dev, "Failed to parse dt\n");
+ goto error;
+ }
+ } else {
+ pdata = client->dev.platform_data;
+ }
+
+ if (!pdata) {
+ tsp_debug_err(&client->dev, "No platform data found\n");
+ return -EINVAL;
+ }
+ if (!pdata->power) {
+ tsp_debug_err(&client->dev, "No power contorl found\n");
+ retval = -EINVAL;
+ goto error;
+ }
+
+ pdata->pinctrl = devm_pinctrl_get(&client->dev);
+ if (IS_ERR(pdata->pinctrl)) {
+ tsp_debug_err(&client->dev, "could not get pinctrl\n");
+ retval = PTR_ERR(pdata->pinctrl);
+ goto error;
+ }
+
+ pdata->pins_default = pinctrl_lookup_state(pdata->pinctrl, "on_state");
+ if (IS_ERR(pdata->pins_default))
+ tsp_debug_err(&client->dev, "could not get default pinstate\n");
+
+ pdata->pins_sleep = pinctrl_lookup_state(pdata->pinctrl, "off_state");
+ if (IS_ERR(pdata->pins_sleep))
+ tsp_debug_err(&client->dev, "could not get sleep pinstate\n");
+
+ info = kzalloc(sizeof(struct fts_ts_info), GFP_KERNEL);
+ if (!info) {
+ tsp_debug_err(&client->dev,
+ "%s: Failed to alloc mem for info\n",
+ __func__);
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ info->client = client;
+ info->board = pdata;
+ info->irq = client->irq;
+ info->irq_type = info->board->irq_type;
+ atomic_set(&info->irq_enabled, 0);
+ info->touch_stopped = false;
+ info->panel_revision = info->board->panel_revision;
+ info->stop_device = fts_stop_device;
+ info->start_device = fts_start_device;
+ info->fts_command = fts_command;
+ info->fts_read_reg = fts_read_reg;
+ info->fts_write_reg = fts_write_reg;
+ info->fts_systemreset = fts_systemreset;
+ info->fts_get_version_info = fts_get_version_info;
+ info->fts_wait_for_ready = fts_wait_for_ready;
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+ info->fts_get_channel_info = fts_get_channel_info;
+ info->fts_interrupt_set = fts_interrupt_set;
+ info->fts_irq_enable = fts_irq_enable;
+ info->fts_release_all_finger = fts_release_all_finger;
+#endif
+
+#ifdef FTS_SUPPORT_NOISE_PARAM
+ info->fts_get_noise_param_address = fts_get_noise_param_address;
+#endif
+
+#ifdef USE_OPEN_DWORK
+ INIT_DELAYED_WORK(&info->open_work, fts_open_work);
+#endif
+ info->delay_time = 300;
+ INIT_DELAYED_WORK(&info->reset_work, fts_reset_work);
+
+ if (info->board->support_hover)
+ tsp_debug_info(&info->client->dev, "FTS Support Hover Event\n");
+ else
+ tsp_debug_info(&info->client->dev, "FTS Not support Hover Event\n");
+
+ i2c_set_clientdata(client, info);
+
+ if (pdata->get_ddi_type) {
+ info->ddi_type = pdata->get_ddi_type();
+ tsp_debug_info(&client->dev,
+ "%s: DDI Type is %s[%d]\n",
+ __func__, info->ddi_type ?
+ "MAGNA" : "SDC", info->ddi_type);
+ }
+
+ pdata->switch_gpio = of_get_named_gpio(client->dev.of_node,
+ "stm,switch_gpio", 0);
+
+ if (gpio_is_valid(pdata->switch_gpio)) {
+ retval = gpio_request_one(pdata->switch_gpio,
+ GPIOF_OUT_INIT_LOW,
+ "stm,tsp_i2c_switch");
+ if (retval) {
+ tsp_debug_err(&client->dev,
+ "Can't req GPIO%d: rev %d\n",
+ pdata->switch_gpio, retval);
+ goto error;
+ }
+ } else {
+ tsp_debug_info(&client->dev, "Didn't find switch_gpio = %d\n",
+ pdata->switch_gpio);
+ }
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ tui_tsp_info = info;
+#endif
+ return 0;
+error:
+ kfree(info);
+ if (client->dev.of_node) {
+ kfree(pdata);
+ client->dev.platform_data = NULL;
+ }
+ return retval;
+}
+
+static int fts_probe(struct i2c_client *client, const struct i2c_device_id *idp)
+{
+ int retval = 0;
+ struct fts_ts_info *info = NULL;
+ static char fts_ts_phys[64] = { 0 };
+ int i = 0;
+
+/*
+ tsp_debug_info(&client->dev, "FTS Driver [12%s] %s %s\n",
+ FTS_TS_DRV_VERSION, __DATE__, __TIME__);
+*/
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ tsp_debug_err(&client->dev, "FTS err = EIO!\n");
+ return -EIO;
+ }
+
+ /* Build up driver data */
+ retval = fts_setup_drv_data(client);
+ if (retval < 0) {
+ tsp_debug_err(&client->dev,
+ "%s: Failed to set up driver data\n",
+ __func__);
+ goto err_setup_drv_data;
+ }
+
+ info = (struct fts_ts_info *)i2c_get_clientdata(client);
+ if (!info) {
+ tsp_debug_err(&client->dev,
+ "%s: Failed to get driver data\n", __func__);
+ retval = -ENODEV;
+ goto err_get_drv_data;
+ }
+
+ if (info->board->power)
+ info->board->power(info, true);
+
+ info->dev = &info->client->dev;
+ info->input_dev = input_allocate_device();
+ if (!info->input_dev) {
+ tsp_debug_err(&info->client->dev, "FTS err = ENOMEM!\n");
+ retval = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+
+ info->input_dev->dev.parent = &client->dev;
+ info->input_dev->name = "touchscreen";
+ snprintf(fts_ts_phys, sizeof(fts_ts_phys), "%s/input1",
+ info->input_dev->name);
+ info->input_dev->phys = fts_ts_phys;
+ info->input_dev->id.bustype = BUS_I2C;
+
+#ifdef USE_OPEN_CLOSE
+ info->input_dev->open = fts_input_open;
+ info->input_dev->close = fts_input_close;
+#endif
+
+ set_bit(EV_SYN, info->input_dev->evbit);
+ set_bit(EV_KEY, info->input_dev->evbit);
+ set_bit(EV_ABS, info->input_dev->evbit);
+#ifdef INPUT_PROP_DIRECT
+ set_bit(INPUT_PROP_DIRECT, info->input_dev->propbit);
+#endif
+ set_bit(BTN_TOUCH, info->input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, info->input_dev->keybit);
+
+ input_mt_init_slots(info->input_dev, FINGER_MAX, INPUT_MT_DIRECT);
+ input_set_abs_params(info->input_dev, ABS_MT_POSITION_X,
+ 0, info->board->max_x, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_POSITION_Y,
+ 0, info->board->max_y, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_PRESSURE,
+ 0, 255, 0, 0);
+
+ mutex_init(&info->device_mutex);
+ mutex_init(&info->i2c_mutex);
+ spin_lock_init(&info->lock);
+
+ info->enabled = false;
+ mutex_lock(&info->device_mutex);
+ retval = fts_init(info);
+ info->reinit_done = true;
+ mutex_unlock(&info->device_mutex);
+ if (retval < 0) {
+ tsp_debug_err(&info->client->dev, "FTS fts_init fail!\n");
+ goto err_fts_init;
+ }
+
+ input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, 255, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MINOR,
+ 0, 255, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_DISTANCE,
+ 0, 255, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_ORIENTATION,
+ 0, 255, 0, 0);
+
+ input_set_drvdata(info->input_dev, info);
+ i2c_set_clientdata(client, info);
+
+ retval = input_register_device(info->input_dev);
+ if (retval) {
+ tsp_debug_err(&info->client->dev, "FTS input_register_device fail!\n");
+ goto err_register_input;
+ }
+
+ for (i = 0; i < FINGER_MAX; i++) {
+ info->finger[i].state = EVENTID_LEAVE_POINTER;
+ info->finger[i].mcount = 0;
+ }
+
+ info->enabled = true;
+
+ retval = request_threaded_irq(info->irq, NULL,
+ fts_interrupt_handler, info->board->irq_type,
+ FTS_TS_DRV_NAME, info);
+
+ if (retval < 0) {
+ tsp_debug_err(&info->client->dev,
+ "%s: Failed to enable attention interrupt\n",
+ __func__);
+ goto err_enable_irq;
+ }
+ atomic_set(&info->irq_enabled, 1);
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ trustedui_set_tsp_irq(info->irq);
+ tsp_debug_info(&client->dev, "%s[%d] called!\n",
+ __func__, info->irq);
+#endif
+
+#if defined(CONFIG_FB)
+ info->fb_notif.notifier_call = touch_fb_notifier_callback;
+ retval = fb_register_client(&info->fb_notif);
+#endif
+
+
+#ifdef FTS_SUPPORT_TA_MODE
+ info->register_cb = info->board->register_cb;
+
+ info->callbacks.inform_charger = fts_ta_cb;
+ if (info->register_cb)
+ info->register_cb(&info->callbacks);
+#endif
+
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+ fts_production_init(info);
+#endif /* FEATURE_FTS_PRODUCTION_CODE */
+ device_init_wakeup(&client->dev, true);
+ if (device_may_wakeup(&info->client->dev))
+ enable_irq_wake(info->irq);
+ info->lowpower_mode = true;
+
+ return 0;
+
+err_enable_irq:
+ input_unregister_device(info->input_dev);
+ info->input_dev = NULL;
+
+err_register_input:
+ if (info->input_dev)
+ input_free_device(info->input_dev);
+
+err_fts_init:
+ mutex_destroy(&info->device_mutex);
+ mutex_destroy(&info->i2c_mutex);
+err_input_allocate_device:
+ info->board->power(info, false);
+ kfree(info);
+err_get_drv_data:
+err_setup_drv_data:
+ return retval;
+}
+
+static int fts_remove(struct i2c_client *client)
+{
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ tsp_debug_info(&info->client->dev, "FTS removed\n");
+
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&info->fb_notif))
+ tsp_debug_err(&info->client->dev,
+ "%s: Error occured while unregistering fb_notifier.\n", __func__);
+#endif
+
+ fts_interrupt_set(info, INT_DISABLE);
+ fts_command(info, FLUSHBUFFER);
+
+ fts_irq_enable(info, false);
+ free_irq(info->irq, info);
+
+ input_mt_destroy_slots(info->input_dev);
+
+ input_unregister_device(info->input_dev);
+ info->input_dev = NULL;
+
+ info->board->power(info, false);
+
+ kfree(info);
+
+ return 0;
+}
+
+#ifdef USE_OPEN_CLOSE
+#ifdef USE_OPEN_DWORK
+static void fts_open_work(struct work_struct *work)
+{
+ int retval = 0;
+ struct fts_ts_info *info = container_of(work, struct fts_ts_info,
+ open_work.work);
+
+ tsp_debug_info(&info->client->dev, "%s\n", __func__);
+
+ retval = fts_start_device(info);
+ if (retval < 0)
+ tsp_debug_err(&info->client->dev,
+ "%s: Failed to start device\n", __func__);
+}
+#endif
+static int fts_input_open(struct input_dev *dev)
+{
+ struct fts_ts_info *info = input_get_drvdata(dev);
+ unsigned char regAdd[4] = {0xB0, 0x01, 0x29, 0x41};
+ int retval = 0;
+
+ tsp_debug_info(&info->client->dev, "%s\n", __func__);
+
+#ifdef USE_OPEN_DWORK
+ schedule_delayed_work(&info->open_work,
+ msecs_to_jiffies(TOUCH_OPEN_DWORK_TIME));
+#else
+ retval = fts_start_device(info);
+ if (retval < 0) {
+ tsp_debug_err(&info->client->dev,
+ "%s: Failed to start device\n", __func__);
+ goto out;
+ }
+#endif
+
+ tsp_debug_info(&info->client->dev,
+ "FTS cmd after wakeup : h%d\n",
+ info->retry_hover_enable_after_wakeup);
+
+ if (info->retry_hover_enable_after_wakeup == 1) {
+ fts_write_reg(info, &regAdd[0], 4);
+ fts_command(info, FTS_CMD_HOVER_ON);
+ }
+
+out:
+ return 0;
+}
+
+static void fts_input_close(struct input_dev *dev)
+{
+ struct fts_ts_info *info = input_get_drvdata(dev);
+
+ tsp_debug_info(&info->client->dev, "%s\n", __func__);
+
+#ifdef USE_OPEN_DWORK
+ cancel_delayed_work(&info->open_work);
+#endif
+
+ fts_stop_device(info);
+
+ info->retry_hover_enable_after_wakeup = 0;
+}
+#endif
+
+static void fts_reinit(struct fts_ts_info *info)
+{
+ fts_systemreset(info);
+
+ fts_wait_for_ready(info);
+
+#ifdef FTS_SUPPORT_NOISE_PARAM
+ fts_set_noise_param(info);
+#endif
+
+ fts_command(info, SENSEON);
+ fts_delay(50);
+
+#ifdef FTS_SUPPORT_TA_MODE
+ if (info->TA_Pluged)
+ fts_command(info, FTS_CMD_CHARGER_PLUGGED);
+#endif
+
+ info->touch_count = 0;
+ info->palm_pressed = false;
+
+ fts_command(info, FLUSHBUFFER);
+ fts_interrupt_set(info, INT_ENABLE);
+}
+
+void fts_release_all_finger(struct fts_ts_info *info)
+{
+ int i;
+
+ for (i = 0; i < FINGER_MAX; i++) {
+ input_mt_slot(info->input_dev, i);
+ input_mt_report_slot_state(info->input_dev, MT_TOOL_FINGER, 0);
+
+ if ((info->finger[i].state == EVENTID_ENTER_POINTER) ||
+ (info->finger[i].state == EVENTID_MOTION_POINTER)) {
+ info->touch_count--;
+ if (info->touch_count < 0)
+ info->touch_count = 0;
+
+ tsp_debug_info(&info->client->dev,
+ "[RA] tID:%d mc: %d tc:%d Ver[%02X%04X%01X%01X]\n",
+ i, info->finger[i].mcount, info->touch_count,
+ info->panel_revision, info->fw_main_version_of_ic,
+ info->flip_enable, info->mainscr_disable);
+ }
+
+ info->finger[i].state = EVENTID_LEAVE_POINTER;
+ info->finger[i].mcount = 0;
+ }
+
+ input_report_key(info->input_dev, BTN_TOUCH, 0);
+ input_report_key(info->input_dev, BTN_TOOL_FINGER, 0);
+
+#ifdef CONFIG_INPUT_BOOSTER
+ input_booster_send_event(BOOSTER_DEVICE_TOUCH, BOOSTER_MODE_FORCE_OFF);
+#endif
+
+ input_sync(info->input_dev);
+}
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+void trustedui_mode_on(void)
+{
+ tsp_debug_info(&tui_tsp_info->client->dev,
+ "%s, release all finger..", __func__);
+ fts_release_all_finger(tui_tsp_info);
+}
+#endif
+
+static void fts_reset_work(struct work_struct *work)
+{
+ struct fts_ts_info *info = container_of(work, struct fts_ts_info,
+ reset_work.work);
+ bool temp_lpm;
+
+ temp_lpm = info->lowpower_mode;
+ /* Reset-routine must go to power off state */
+ info->lowpower_mode = 0;
+
+ tsp_debug_info(&info->client->dev, "%s, Call Power-Off to recover IC, lpm:%d\n", __func__, temp_lpm);
+ fts_stop_device(info);
+
+ fts_delay(100); /* Delay to discharge the IC from ESD or On-state.*/
+ if (fts_start_device(info) < 0)
+ tsp_debug_err(&info->client->dev, "%s: Failed to start device\n", __func__);
+
+ info->lowpower_mode = temp_lpm;
+}
+
+
+static int fts_stop_device(struct fts_ts_info *info)
+{
+ tsp_debug_dbg(&info->client->dev, "%s\n", __func__);
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) {
+ tsp_debug_err(&info->client->dev,
+ "%s TUI cancel event call!\n", __func__);
+ fts_delay(100);
+ tui_force_close(1);
+ fts_delay(200);
+ if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) {
+ tsp_debug_err(&info->client->dev,
+ "%s TUI flag force clear!\n", __func__);
+ trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED|
+ TRUSTEDUI_MODE_INPUT_SECURED);
+ trustedui_set_mode(TRUSTEDUI_MODE_OFF);
+ }
+ }
+#endif
+
+ mutex_lock(&info->device_mutex);
+
+ if (info->touch_stopped) {
+ tsp_debug_err(&info->client->dev,
+ "%s already power off\n", __func__);
+ goto out;
+ }
+
+ if (info->lowpower_mode) {
+ tsp_debug_info(&info->client->dev,
+ "%s lowpower flag:%d\n",
+ __func__, info->lowpower_flag);
+
+ info->fts_power_state = FTS_POWER_STATE_LOWPOWER;
+
+ fts_command(info, FLUSHBUFFER);
+
+ fts_command(info, FTS_CMD_LOWPOWER_MODE);
+
+ if (device_may_wakeup(&info->client->dev))
+ enable_irq_wake(info->irq);
+
+ fts_command(info, FLUSHBUFFER);
+
+ fts_release_all_finger(info);
+#ifdef FTS_SUPPORT_NOISE_PARAM
+ fts_get_noise_param(info);
+#endif
+
+ } else {
+ fts_interrupt_set(info, INT_DISABLE);
+ fts_irq_enable(info, false);
+
+ fts_command(info, FLUSHBUFFER);
+ fts_release_all_finger(info);
+#ifdef FTS_SUPPORT_NOISE_PARAM
+ fts_get_noise_param(info);
+#endif
+ info->touch_stopped = true;
+
+ if (info->board->power)
+ info->board->power(info, false);
+
+ info->fts_power_state = FTS_POWER_STATE_POWERDOWN;
+ }
+ out:
+ mutex_unlock(&info->device_mutex);
+ return 0;
+}
+
+static int fts_start_device(struct fts_ts_info *info)
+{
+ tsp_debug_dbg(&info->client->dev, "%s %s\n",
+ __func__,
+ info->lowpower_mode ?
+ "exit low power mode" : "");
+
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+ if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) {
+ tsp_debug_err(&info->client->dev,
+ "%s TUI cancel event call!\n", __func__);
+ fts_delay(100);
+ tui_force_close(1);
+ fts_delay(200);
+ if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) {
+ tsp_debug_err(&info->client->dev,
+ "%s TUI flag force clear!\n", __func__);
+ trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED|
+ TRUSTEDUI_MODE_INPUT_SECURED);
+ trustedui_set_mode(TRUSTEDUI_MODE_OFF);
+ }
+ }
+#endif
+
+ mutex_lock(&info->device_mutex);
+
+ if (!info->touch_stopped && !info->lowpower_mode) {
+ tsp_debug_err(&info->client->dev,
+ "%s already power on\n", __func__);
+ goto out;
+ }
+
+ fts_release_all_finger(info);
+ if (info->lowpower_mode) {
+ /* low power mode command is sent after LCD OFF. */
+ /* turn on touch power @ LCD ON */
+ if (info->touch_stopped)
+ goto tsp_power_on;
+
+ disable_irq(info->irq);
+
+ info->reinit_done = false;
+ fts_reinit(info);
+ info->reinit_done = true;
+
+ fts_irq_enable(info, true);
+
+ if (device_may_wakeup(&info->client->dev))
+ disable_irq_wake(info->irq);
+ } else {
+tsp_power_on:
+ if (info->board->power)
+ info->board->power(info, true);
+ info->touch_stopped = false;
+ info->reinit_done = false;
+
+ fts_reinit(info);
+ info->reinit_done = true;
+
+ fts_irq_enable(info, true);
+ }
+
+ out:
+ mutex_unlock(&info->device_mutex);
+
+ info->fts_power_state = FTS_POWER_STATE_ACTIVE;
+
+ return 0;
+}
+
+static void fts_shutdown(struct i2c_client *client)
+{
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ tsp_debug_info(&info->client->dev, "FTS %s called!\n", __func__);
+
+ if (info->lowpower_mode) {
+ info->lowpower_mode = 0;
+ tsp_debug_info(&info->client->dev, "FTS lowpower_mode off!\n");
+ }
+
+ fts_stop_device(info);
+}
+
+void fts_recovery_cx(struct fts_ts_info *info)
+{
+ unsigned char regAdd[4] = {0};
+ unsigned char buf[8] = {0};
+ unsigned char cnt = 100;
+ int ret = 0;
+
+ regAdd[0] = 0xB6;
+ regAdd[1] = 0x00;
+ regAdd[2] = 0x1E;
+ regAdd[3] = 0x08;
+ fts_write_reg(info, &regAdd[0], 4); /* Loading FW to PRAM without CRC Check */
+ fts_delay(30);
+
+
+ fts_command(info, CX_TUNNING);
+ fts_delay(300);
+
+ fts_command(info, FTS_CMD_SAVE_CX_TUNING);
+ fts_delay(200);
+
+ do {
+ regAdd[0] = READ_ONE_EVENT;
+ ret = fts_read_reg(info, regAdd, 1, &buf[0], FTS_EVENT_SIZE);
+
+ fts_delay(10);
+
+ if (cnt-- == 0)
+ break;
+ } while (buf[0] != 0x16 || buf[1] != 0x04);
+
+ fts_command(info, SENSEON);
+ fts_delay(50);
+
+ fts_command(info, FLUSHBUFFER);
+}
+
+#ifdef CONFIG_PM
+static int fts_pm_suspend(struct device *dev)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ tsp_debug_info(&info->client->dev, "%s\n", __func__);
+
+ mutex_lock(&info->input_dev->mutex);
+
+ if (info->input_dev->users)
+ fts_stop_device(info);
+
+ mutex_unlock(&info->input_dev->mutex);
+
+ return 0;
+}
+
+static int fts_pm_resume(struct device *dev)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ tsp_debug_info(&info->client->dev, "%s\n", __func__);
+
+ mutex_lock(&info->input_dev->mutex);
+
+ if (info->input_dev->users)
+ fts_start_device(info);
+
+ mutex_unlock(&info->input_dev->mutex);
+
+ return 0;
+}
+#endif
+
+static int fts_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ tsp_debug_info(&info->client->dev, "%s power state : %d\n",
+ __func__, info->fts_power_state);
+
+ fts_stop_device(info);
+
+ return 0;
+}
+
+static int fts_resume(struct i2c_client *client)
+{
+ struct fts_ts_info *info = i2c_get_clientdata(client);
+
+ tsp_debug_info(&info->client->dev, "%s power state : %d\n",
+ __func__, info->fts_power_state);
+ /* if resume is called from active state, the i2c bus is not
+ * switched to AP, skipping resume routine */
+ if (info->fts_power_state == FTS_POWER_STATE_ACTIVE) {
+ tsp_debug_info(&info->client->dev,
+ "%s: calling resume from active state, "
+ "skipping\n", __func__);
+ return 0;
+ }
+
+ fts_start_device(info);
+
+ return 0;
+}
+
+#if defined(CONFIG_FB)
+static int touch_fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fts_ts_info *info =
+ container_of(self, struct fts_ts_info, fb_notif);
+ struct fb_event *ev = (struct fb_event *)data;
+
+ if (ev && ev->data && event == FB_EVENT_BLANK) {
+ int *blank = (int *)ev->data;
+
+ if (*blank == FB_BLANK_UNBLANK)
+ fts_resume(info->client);
+ else if (*blank == FB_BLANK_POWERDOWN)
+ fts_suspend(info->client, PMSG_SUSPEND);
+ }
+
+ return 0;
+}
+#endif
+
+static const struct i2c_device_id fts_device_id[] = {
+ {FTS_TS_DRV_NAME, 0},
+ {}
+};
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops fts_dev_pm_ops = {
+ .suspend = fts_pm_suspend,
+ .resume = fts_pm_resume,
+};
+#endif
+
+#ifdef CONFIG_OF
+static struct of_device_id fts_match_table[] = {
+ { .compatible = "stm,ftm4_fts",},
+ { },
+};
+#else
+#define fts_match_table NULL
+#endif
+
+static struct i2c_driver fts_i2c_driver = {
+ .driver = {
+ .name = FTS_TS_DRV_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+ .of_match_table = fts_match_table,
+#endif
+#ifdef CONFIG_PM
+ .pm = &fts_dev_pm_ops,
+#endif
+ },
+ .probe = fts_probe,
+ .remove = fts_remove,
+ .shutdown = fts_shutdown,
+#if 0 // (!defined(CONFIG_FB))
+ .suspend = fts_suspend,
+ .resume = fts_resume,
+#endif
+ .id_table = fts_device_id,
+};
+
+static int __init fts_driver_init(void)
+{
+ return i2c_add_driver(&fts_i2c_driver);
+}
+
+static void __exit fts_driver_exit(void)
+{
+ i2c_del_driver(&fts_i2c_driver);
+}
+
+MODULE_DESCRIPTION("STMicroelectronics MultiTouch IC Driver");
+MODULE_AUTHOR("STMicroelectronics, Inc.");
+MODULE_LICENSE("GPL v2");
+
+module_init(fts_driver_init);
+module_exit(fts_driver_exit);
diff --git a/drivers/input/touchscreen/stm/ftm4_ts.h b/drivers/input/touchscreen/stm/ftm4_ts.h
new file mode 100644
index 00000000000..90b7d088ba1
--- /dev/null
+++ b/drivers/input/touchscreen/stm/ftm4_ts.h
@@ -0,0 +1,571 @@
+#ifndef _LINUX_FTM4_TS_H_
+#define _LINUX_FTM4_TS_H_
+
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#endif
+#ifdef CONFIG_INPUT_BOOSTER
+#include <linux/input/input_booster.h>
+#endif
+#include <linux/atomic.h>
+
+#include <linux/printk.h>
+
+#include "i2c_fts.h"
+
+#define tsp_debug_dbg(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
+#define tsp_debug_info(dev, fmt, ...) dev_info(dev, fmt, ## __VA_ARGS__)
+#define tsp_debug_err(dev, fmt, ...) dev_err(dev, fmt, ## __VA_ARGS__)
+#ifdef CONFIG_TOUCHSCREEN_FTM4_SHOW_EVENTS
+#define tsp_debug_event(dev, fmt, ...) dev_dbg(dev, fmt, ## __VA_ARGS__)
+#else
+#define tsp_debug_event(dev, fmt, ...)
+#endif
+
+#define USE_OPEN_CLOSE
+#define FEATURE_FTS_PRODUCTION_CODE 1
+
+#ifdef USE_OPEN_DWORK
+#define TOUCH_OPEN_DWORK_TIME 10
+#endif
+
+#define FIRMWARE_IC "fts_ic"
+
+#define FTS_MAX_FW_PATH 64
+
+#define FTS_TS_DRV_NAME "fts_touch"
+#define FTS_TS_DRV_VERSION "0132"
+
+#define STM_DEVICE_NAME "STM"
+
+#define FTS_ID0 0x36
+#define FTS_ID1 0x70
+
+#define FTS_SEC_IX1_TX_MULTIPLIER (4)
+#define FTS_SEC_IX1_RX_MULTIPLIER (2)
+
+#define FTS_DIGITAL_REV_1 0x01
+#define FTS_DIGITAL_REV_2 0x02
+#define FTS_FIFO_MAX 32
+#define FTS_EVENT_SIZE 8
+#define FTS_FW_UPDATE_RETRY 3
+#define FTS_LOCKDOWNCODE_SIZE 13
+
+#define PRESSURE_MIN 0
+#define PRESSURE_MAX 127
+#define P70_PATCH_ADDR_START 0x00420000
+#define FINGER_MAX 10
+#define AREA_MIN PRESSURE_MIN
+#define AREA_MAX PRESSURE_MAX
+
+#define EVENTID_NO_EVENT 0x00
+#define EVENTID_ENTER_POINTER 0x03
+#define EVENTID_LEAVE_POINTER 0x04
+#define EVENTID_MOTION_POINTER 0x05
+#define EVENTID_HOVER_ENTER_POINTER 0x07
+#define EVENTID_HOVER_LEAVE_POINTER 0x08
+#define EVENTID_HOVER_MOTION_POINTER 0x09
+#define EVENTID_PROXIMITY_IN 0x0B
+#define EVENTID_PROXIMITY_OUT 0x0C
+#define EVENTID_MSKEY 0x0E
+#define EVENTID_ERROR 0x0F
+#define EVENTID_CONTROLLER_READY 0x10
+#define EVENTID_SLEEPOUT_CONTROLLER_READY 0x11
+#define EVENTID_RESULT_READ_REGISTER 0x12
+#define EVENTID_STATUS_REQUEST_COMP 0x13
+
+#define EVENTID_STATUS_EVENT 0x16
+#define EVENTID_INTERNAL_RELEASE_INFO 0x14
+#define EVENTID_EXTERNAL_RELEASE_INFO 0x15
+
+#define EVENTID_FROM_STRING 0x80
+#define EVENTID_GESTURE 0x20
+
+#define EVENTID_SIDE_SCROLL 0x40
+/* side touch event-id for debug, remove after f/w fixed */
+#define EVENTID_SIDE_TOUCH_DEBUG 0xDB
+#define EVENTID_SIDE_TOUCH 0x0B
+
+#define EVENTID_ERROR_FLASH_CORRUPTION 0x03
+
+/* define flash corruption type */
+#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_1 0x01
+#define EVENTID_ERROR_CONFIG_FLASH_CORRUPTION_2 0x02
+#define EVENTID_ERROR_CX_FLASH_CORRUPTION 0x03
+
+#define EVENTID_LOCKDOWN_CODE 0x1E
+#define EVENTID_ERROR_LOCKDOWN 0x0B
+
+#define STATUS_EVENT_MUTUAL_AUTOTUNE_DONE 0x01
+#define STATUS_EVENT_SELF_AUTOTUNE_DONE 0x02
+#define STATUS_EVENT_WATER_SELF_AUTOTUNE_DONE 0x4E
+#ifdef FTS_SUPPORT_WATER_MODE
+#define STATUS_EVENT_WATER_SELF_DONE 0x17
+#endif
+#define STATUS_EVENT_FLASH_WRITE_CONFIG 0x03
+#define STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE 0x04
+#define STATUS_EVENT_FORCE_CAL_MUTUAL_SELF 0x05
+#define STATUS_EVENT_FORCE_CAL_DONE 0x06
+
+#define STATUS_EVENT_FORCE_CAL_MUTUAL 0x15
+#define STATUS_EVENT_FORCE_CAL_SELF 0x06
+#define STATUS_EVENT_PARAM1_FCAL_MS_SS_DONE 0x23
+#define STATUS_EVENT_WATERMODE_ON 0x07
+#define STATUS_EVENT_WATERMODE_OFF 0x08
+#define STATUS_EVENT_RTUNE_MUTUAL 0x09
+#define STATUS_EVENT_RTUNE_SELF 0x0A
+#define STATUS_EVENT_PANEL_TEST_RESULT 0x0B
+#define STATUS_EVENT_GLOVE_MODE 0x0C
+#define STATUS_EVENT_RAW_DATA_READY 0x0D
+#define STATUS_EVENT_MUTUAL_CAL_FRAME_CHECK 0xC1
+#define STATUS_EVENT_SELF_CAL_FRAME_CHECK 0xC2
+#define STATUS_EVENT_CHARGER_CONNECTED 0xCC
+#define STATUS_EVENT_CHARGER_DISCONNECTED 0xCD
+#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_WRITE_FINISH 0x10
+#define STATUS_EVENT_PURE_AUTOTUNE_FLAG_CLEAR_FINISH 0x11
+
+#define INT_ENABLE 0x48
+#define INT_DISABLE 0x08
+
+#define READ_STATUS 0x84
+#define READ_ONE_EVENT 0x85
+#define READ_ALL_EVENT 0x86
+
+#define SENSEOFF 0x92
+#define SENSEON 0x93
+#define FTS_CMD_HOVER_OFF 0x94
+#define FTS_CMD_HOVER_ON 0x95
+
+#define FTS_CMD_MSKEY_AUTOTUNE 0x96
+#define FTS_CMD_TRIM_LOW_POWER_OSCILLATOR 0x97
+
+#define FTS_CMD_KEY_SENSE_OFF 0x9A
+#define FTS_CMD_KEY_SENSE_ON 0x9B
+#define FTS_CMD_SET_FAST_GLOVE_MODE 0x9D
+
+#define FTS_CMD_MSHOVER_OFF 0x9E
+#define FTS_CMD_MSHOVER_ON 0x9F
+#define FTS_CMD_SET_NOR_GLOVE_MODE 0x9F
+
+#define FLUSHBUFFER 0xA1
+#define FORCECALIBRATION 0xA2
+#define CX_TUNNING 0xA3
+#define SELF_AUTO_TUNE 0xA4
+
+#define FTS_CMD_CHARGER_PLUGGED 0xA8
+#define FTS_CMD_CHARGER_UNPLUGGED 0xAB
+
+#define FTS_CMD_RELEASEINFO 0xAA
+#define FTS_CMD_STYLUS_OFF 0xAB
+#define FTS_CMD_STYLUS_ON 0xAC
+#define FTS_CMD_LOWPOWER_MODE 0xAD
+
+#define FTS_CMS_ENABLE_FEATURE 0xC1
+#define FTS_CMS_DISABLE_FEATURE 0xC2
+
+#define LOCKDOWN_READ 0xC4
+
+#define FTS_CMD_WRITE_PRAM 0xF0
+#define FTS_CMD_BURN_PROG_FLASH 0xF2
+#define FTS_CMD_ERASE_PROG_FLASH 0xF3
+#define FTS_CMD_READ_FLASH_STAT 0xF4
+#define FTS_CMD_UNLOCK_FLASH 0xF7
+#define FTS_CMD_SAVE_FWCONFIG 0xFB
+#define FTS_CMD_SAVE_CX_TUNING 0xFC
+
+#define FTS_CMD_FAST_SCAN 0x01
+#define FTS_CMD_SLOW_SCAN 0x02
+#define FTS_CMD_USLOW_SCAN 0x03
+
+#define REPORT_RATE_90HZ 0
+#define REPORT_RATE_60HZ 1
+#define REPORT_RATE_30HZ 2
+
+#define FTS_CMD_STRING_ACCESS 0xEC00
+#define FTS_CMD_NOTIFY 0xC0
+
+#define FTS_RETRY_COUNT 10
+
+/* QUICK SHOT : Quick Camera Launching */
+#define FTS_STRING_EVENT_REAR_CAM (1 << 0)
+#define FTS_STRING_EVENT_FRONT_CAM (1 << 1)
+
+/* SCRUB : Display Watch, Event Status / Fast Access Event */
+#define FTS_STRING_EVENT_WATCH_STATUS (1 << 2)
+#define FTS_STRING_EVENT_FAST_ACCESS (1 << 3)
+#define FTS_STRING_EVENT_DIRECT_INDICATOR ((1 << 3) | (1 << 2))
+#define FTS_STRING_EVENT_SPAY (1 << 4)
+#define FTS_STRING_EVENT_SPAY1 (1 << 5)
+#define FTS_STRING_EVENT_SPAY2 ((1 << 4) | (1 << 5))
+
+#define FTS_SIDEGESTURE_EVENT_SINGLE_STROKE 0xE0
+#define FTS_SIDEGESTURE_EVENT_DOUBLE_STROKE 0xE1
+#define FTS_SIDEGESTURE_EVENT_INNER_STROKE 0xE3
+
+#define FTS_SIDETOUCH_EVENT_LONG_PRESS 0xBB
+#define FTS_SIDETOUCH_EVENT_REBOOT_BY_ESD 0xED
+
+#define FTS_ENABLE 1
+#define FTS_DISABLE 0
+
+#define FTS_MODE_QUICK_SHOT (1 << 0)
+#define FTS_MODE_SCRUB (1 << 1)
+#define FTS_MODE_SPAY (1 << 1)
+#define FTS_MODE_QUICK_APP_ACCESS (1 << 2)
+#define FTS_MODE_DIRECT_INDICATOR (1 << 3)
+
+#define TSP_BUF_SIZE 2048
+#define CMD_STR_LEN 32
+#define CMD_RESULT_STR_LEN 2048
+#define CMD_PARAM_NUM 8
+
+#define FTS_LOWP_FLAG_QUICK_CAM (1 << 0)
+#define FTS_LOWP_FLAG_2ND_SCREEN (1 << 1)
+#define FTS_LOWP_FLAG_BLACK_UI (1 << 2)
+#define FTS_LOWP_FLAG_QUICK_APP_ACCESS (1 << 3)
+#define FTS_LOWP_FLAG_DIRECT_INDICATOR (1 << 4)
+#define FTS_LOWP_FLAG_SPAY (1 << 5)
+#define FTS_LOWP_FLAG_TEMP_CMD (1 << 6)
+
+enum fts_error_return {
+ FTS_NOT_ERROR = 0,
+ FTS_ERROR_INVALID_CHIP_ID,
+ FTS_ERROR_INVALID_CHIP_VERSION_ID,
+ FTS_ERROR_INVALID_SW_VERSION,
+ FTS_ERROR_EVENT_ID,
+ FTS_ERROR_TIMEOUT,
+ FTS_ERROR_FW_UPDATE_FAIL,
+};
+#define RAW_MAX 3750
+/**
+ * struct fts_finger - Represents fingers.
+ * @ state: finger status (Event ID).
+ * @ mcount: moving counter for debug.
+ */
+struct fts_finger {
+ unsigned char state;
+ unsigned short mcount;
+ int lx;
+ int ly;
+};
+
+enum tsp_power_mode {
+ FTS_POWER_STATE_ACTIVE = 0,
+ FTS_POWER_STATE_LOWPOWER,
+ FTS_POWER_STATE_POWERDOWN,
+ FTS_POWER_STATE_DEEPSLEEP,
+};
+
+enum fts_cover_id {
+ FTS_FLIP_WALLET = 0,
+ FTS_VIEW_COVER,
+ FTS_COVER_NOTHING1,
+ FTS_VIEW_WIRELESS,
+ FTS_COVER_NOTHING2,
+ FTS_CHARGER_COVER,
+ FTS_VIEW_WALLET,
+ FTS_LED_COVER,
+ FTS_CLEAR_FLIP_COVER,
+ FTS_QWERTY_KEYBOARD_EUR,
+ FTS_QWERTY_KEYBOARD_KOR,
+ FTS_MONTBLANC_COVER = 100,
+};
+
+enum fts_customer_feature {
+ FTS_FEATURE_ORIENTATION_GESTURE = 1,
+ FTS_FEATURE_STYLUS,
+ FTS_FEATURE_QUICK_SHORT_CAMERA_ACCESS,
+ FTS_FEATURE_SIDE_GUSTURE,
+ FTS_FEATURE_COVER_GLASS,
+ FTS_FEATURE_COVER_WALLET,
+ FTS_FEATURE_COVER_LED,
+ FTS_FEATURE_COVER_CLEAR_FLIP,
+ FTS_FEATURE_DUAL_SIDE_GUSTURE,
+ FTS_FEATURE_CUSTOM_COVER_GLASS_ON,
+};
+
+enum ftsito_error_type {
+ NO_ERROR = 0,
+ ITO_FORCE_OPEN,
+ ITO_SENSE_OPEN,
+ ITO_FORCE_SHRT_GND,
+ ITO_SENSE_SHRT_GND,
+ ITO_FORCE_SHRT_VCM,
+ ITO_SENSE_SHRT_VCM,
+ ITO_FORCE_SHRT_FORCE,
+ ITO_SENSE_SHRT_SENSE,
+ ITO_F2E_SENSE,
+ ITO_FPC_FORCE_OPEN,
+ ITO_FPC_SENSE_OPEN,
+ ITO_KEY_FORCE_OPEN,
+ ITO_KEY_SENSE_OPEN,
+ ITO_RESERVED0,
+ ITO_RESERVED1,
+ ITO_RESERVED2,
+ ITO_MAX_ERR_REACHED = 0xFF
+};
+
+struct fts_version {
+ u8 build: 4;
+ u8 major: 4;
+ u8 minor;
+};
+
+struct fts_prd_info {
+ u8 product_id[3];
+ u8 chip_rev:4;
+ u8 fpc_rev:4;
+ u8 t_sensor_rev;
+ u8 site;
+ u8 inspector_no;
+ u8 date[6];
+};
+
+struct fts_flash_corruption_info {
+ bool fw_broken;
+ bool cfg_broken;
+ bool cx_broken;
+};
+
+struct fts_ts_info {
+ struct device *dev;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct hrtimer timer;
+ struct timer_list timer_charger;
+ struct timer_list timer_firmware;
+ struct work_struct work;
+
+ int irq;
+ int irq_type;
+ atomic_t irq_enabled;
+ struct fts_i2c_platform_data *board;
+ void (*register_cb)(void *);
+ struct fts_callbacks callbacks;
+ bool enabled;
+#if defined(CONFIG_FB)
+ struct notifier_block fb_notif;
+#endif
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+ struct device *pdc_dev_ts;
+ struct list_head cmd_list_head;
+ u8 cmd_state;
+ char cmd[CMD_STR_LEN];
+ int cmd_param[CMD_PARAM_NUM];
+ char cmd_result[CMD_RESULT_STR_LEN];
+ int cmd_buf_size;
+ struct mutex cmd_lock;
+ bool cmd_is_running;
+ int SenseChannelLength;
+ int ForceChannelLength;
+ short *pFrame;
+ unsigned char *cx_data;
+ struct delayed_work cover_cmd_work;
+ int delayed_cmd_param[2];
+#endif /* FEATURE_FTS_PRODUCTION_CODE */
+ bool flip_enable;
+ bool run_autotune;
+ bool mainscr_disable;
+ unsigned int cover_type;
+
+ unsigned char lowpower_flag;
+ bool lowpower_mode;
+ bool deepsleep_mode;
+ bool wirelesscharger_mode;
+ int fts_power_state;
+#ifdef FTS_SUPPORT_TA_MODE
+ bool TA_Pluged;
+#endif
+ int digital_rev;
+ int touch_count;
+ struct fts_finger finger[FINGER_MAX];
+ bool palm_pressed;
+
+ int touch_mode;
+ int retry_hover_enable_after_wakeup;
+
+ struct fts_prd_info prd_info;
+ int fw_version_of_ic; /* firmware version of IC */
+ int fw_version_of_bin; /* firmware version of binary */
+ int config_version_of_ic; /* Config release data from IC */
+ int config_version_of_bin; /* Config release data from IC */
+ unsigned short fw_main_version_of_ic; /* firmware main version of IC */
+ unsigned short fw_main_version_of_bin; /* firmware main version of binary */
+ int panel_revision; /* Octa panel revision */
+ int tspid_val;
+ int tspid2_val;
+
+#ifdef USE_OPEN_DWORK
+ struct delayed_work open_work;
+#endif
+
+#ifdef FTS_SUPPORT_NOISE_PARAM
+ struct fts_noise_param noise_param;
+ int (*fts_get_noise_param_address)(struct fts_ts_info *info);
+#endif
+ unsigned int delay_time;
+ unsigned int debug_string;
+ struct delayed_work reset_work;
+
+ unsigned int scrub_id;
+ unsigned int scrub_x;
+ unsigned int scrub_y;
+
+ struct mutex i2c_mutex;
+ struct mutex device_mutex;
+ spinlock_t lock;
+ bool touch_stopped;
+ bool reinit_done;
+
+ unsigned char data[FTS_EVENT_SIZE * FTS_FIFO_MAX];
+ unsigned char ddi_type;
+
+ char test_fwpath[256];
+ struct fts_version ic_fw_ver;
+
+ unsigned char o_afe_ver;
+ unsigned char afe_ver;
+
+ struct fts_flash_corruption_info flash_corruption_info;
+
+ unsigned int checksum_error;
+
+ int (*stop_device)(struct fts_ts_info *info);
+ int (*start_device)(struct fts_ts_info *info);
+
+ int (*fts_write_reg)(struct fts_ts_info *info, unsigned char *reg,
+ unsigned short num_com);
+ int (*fts_read_reg)(struct fts_ts_info *info, unsigned char *reg,
+ int cnum, unsigned char *buf, int num);
+ int (*fts_systemreset)(struct fts_ts_info *info);
+ int (*fts_wait_for_ready)(struct fts_ts_info *info);
+ void (*fts_command)(struct fts_ts_info *info, unsigned char cmd);
+ void (*fts_enable_feature)(struct fts_ts_info *info, unsigned char cmd,
+ int enable);
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+ int (*fts_get_channel_info)(struct fts_ts_info *info);
+ int (*fts_get_version_info)(struct fts_ts_info *info);
+ void (*fts_interrupt_set)(struct fts_ts_info *info, int enable);
+ void (*fts_irq_enable)(struct fts_ts_info *info, bool enable);
+ void (*fts_release_all_finger)(struct fts_ts_info *info);
+#endif /* FEATURE_FTS_PRODUCTION_CODE */
+};
+
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+#define FTS_CMD(name, func) .cmd_name = name, .cmd_func = func
+struct fts_cmd {
+ struct list_head list;
+ const char *cmd_name;
+ void (*cmd_func)(void *device_data);
+};
+
+extern struct fts_cmd fts_commands[];
+#endif /* FEATURE_FTS_PRODUCTION_CODE */
+
+#define WRITE_CHUNK_SIZE 32
+#define FLASH_CHUNK (64 * 1024)
+#define DMA_CHUNK 32
+
+#define FW_HEADER_SIZE 64
+#define FW_HEADER_FTB_SIGNATURE 0xAA55AA55
+#define FW_FTB_VER 0x00000001
+#define FW_BYTES_ALLIGN 4
+#define FW_BIN_VER_OFFSET 16
+#define FW_BIN_CONFIG_VER_OFFSET 20
+
+/* Command for flash */
+#define FLASH_CMD_UNLOCK 0xF7
+#define FLASH_CMD_WRITE_64K 0xF8
+#define FLASH_CMD_READ_REGISTER 0xF9
+#define FLASH_CMD_WRITE_REGISTER 0xFA
+
+/* Parameters for commands */
+#define ADDR_WARM_BOOT 0x001E
+#define WARM_BOOT_VALUE 0x38
+#define FLASH_ADDR_CODE 0x00000000
+#define FLASH_ADDR_CONFIG 0x0000FC00
+
+#define FLASH_UNLOCK_CODE0 0x74
+#define FLASH_UNLOCK_CODE1 0x45
+
+#define FLASH_ERASE_UNLOCK_CODE0 0x72
+#define FLASH_ERASE_UNLOCK_CODE1 0x03
+#define FLASH_ERASE_UNLOCK_CODE2 0x02
+#define FLASH_ERASE_CODE0 0x02
+#define FLASH_ERASE_CODE1 0xC0
+#define FLASH_DMA_CODE0 0x05
+#define FLASH_DMA_CODE1 0xC0
+#define FLASH_DMA_CONFIG 0x06
+
+enum binfile_type {
+ BIN_FTS128 = 1,
+ BIN_FTS256 = 2,
+ BIN_FTB = 3
+};
+
+struct FW_FTB_HEADER {
+ uint32_t signature;
+ uint32_t ftb_ver;
+ uint32_t target;
+ uint32_t fw_id;
+ uint32_t fw_ver;
+ uint32_t cfg_id;
+ uint32_t cfg_ver;
+ uint32_t reserved[2];
+ uint32_t bl_fw_ver;
+ uint32_t ext_ver;
+ uint32_t sec0_size;
+ uint32_t sec1_size;
+ uint32_t sec2_size;
+ uint32_t sec3_size;
+ uint32_t hdr_crc;
+};
+
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+enum fts_system_information_address {
+ FTS_SI_FILTERED_RAW_ADDR = 0x02,
+ FTS_SI_STRENGTH_ADDR = 0x04,
+ FTS_SI_SELF_FILTERED_FORCE_RAW_ADDR = 0x1E,
+ FTS_SI_SELF_FILTERED_SENSE_RAW_ADDR = 0x20,
+ FTS_SI_NOISE_PARAM_ADDR = 0x40,
+ FTS_SI_PURE_AUTOTUNE_FLAG = 0x4E,
+ FTS_SI_COMPENSATION_OFFSET_ADDR = 0x50,
+ FTS_SI_PURE_AUTOTUNE_CONFIG = 0x52,
+ FTS_SI_FACTORY_RESULT_FLAG = 0x56,
+ FTS_SI_AUTOTUNE_CNT = 0x58,
+ FTS_SI_SENSE_CH_LENGTH = 0x5A, /* 2 bytes */
+ FTS_SI_FORCE_CH_LENGTH = 0x5C, /* 2 bytes */
+ FTS_SI_FINGER_THRESHOLD = 0x60, /* 2 bytes */
+ FTS_SI_AUTOTUNE_PROTECTION_CONFIG = 0x62, /* 2 bytes */
+ FTS_SI_REPORT_PRESSURE_RAW_DATA = 0x64, /* 2 bytes */
+ FTS_SI_SS_KEY_THRESHOLD = 0x66, /* 2 bytes */
+ FTS_SI_MS_TUNE_VERSION = 0x68, /* 2 bytes */
+ FTS_SI_CONFIG_CHECKSUM = 0x6A, /* 4 bytes */
+ FTS_SI_PRESSURE_FILTERED_RAW_ADDR = 0x70,
+ FTS_SI_PRESSURE_STRENGTH_ADDR = 0x72,
+ FTS_SI_PRESSURE_THRESHOLD = 0x76,
+};
+#endif
+
+void fts_delay(unsigned int ms);
+int fts_cmd_completion_check(struct fts_ts_info *info, uint8_t event1, uint8_t event2, uint8_t event3);
+int fts_fw_verify_update(struct fts_ts_info *info);
+int fts_get_version_info(struct fts_ts_info *info);
+void fts_get_afe_info(struct fts_ts_info *info);
+void fts_execute_autotune(struct fts_ts_info *info);
+int fts_fw_wait_for_event(struct fts_ts_info *info, unsigned char eid1, unsigned char eid2);
+int fts_systemreset(struct fts_ts_info *info);
+int fts_wait_for_ready(struct fts_ts_info *info);
+int fts_read_chip_id(struct fts_ts_info *info);
+
+#ifdef FEATURE_FTS_PRODUCTION_CODE
+int fts_fw_wait_for_specific_event(struct fts_ts_info *info,
+ unsigned char eid0, unsigned char eid1, unsigned char eid2);
+void procedure_cmd_event(struct fts_ts_info *info, unsigned char *data);
+void fts_production_init(void *device_info);
+#endif
+#endif /* _LINUX_FTM4_TS_H_ */
diff --git a/drivers/input/touchscreen/stm/fts.c b/drivers/input/touchscreen/stm/fts.c
new file mode 100644
index 00000000000..7fa1b5e7620
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts.c
@@ -0,0 +1,4784 @@
+/**
+ * fts.c
+ *
+ * FTS Capacitive touch screen controller (FingerTipS)
+ *
+ * Copyright (C) 2016, STMicroelectronics Limited.
+ * Authors: AMG(Analog Mems Group)
+ *
+ * marco.cali@st.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+ * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+ * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM
+ * THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+ */
+
+
+/*!
+ * \file fts.c
+ * \brief It is the main file which contains all the most important functions
+ * generally used by a device driver the driver
+ */
+#include <linux/device.h>
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/spi/spi.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/notifier.h>
+
+#ifdef KERNEL_ABOVE_2_6_38
+#include <linux/input/mt.h>
+#endif
+
+
+#include "fts.h"
+#include "fts_lib/ftsCompensation.h"
+#include "fts_lib/ftsCore.h"
+#include "fts_lib/ftsIO.h"
+#include "fts_lib/ftsError.h"
+#include "fts_lib/ftsFlash.h"
+#include "fts_lib/ftsFrame.h"
+#include "fts_lib/ftsGesture.h"
+#include "fts_lib/ftsTest.h"
+#include "fts_lib/ftsTime.h"
+#include "fts_lib/ftsTool.h"
+
+/* Touch simulation MT slot */
+#define TOUCHSIM_SLOT_ID 0
+#define TOUCHSIM_TIMER_INTERVAL_NS 8333333
+
+/* Switch GPIO values */
+#define FTS_SWITCH_GPIO_VALUE_SLPI_MASTER 0
+#define FTS_SWITCH_GPIO_VALUE_AP_MASTER 1
+
+/**
+ * Event handler installer helpers
+ */
+#define event_id(_e) (EVT_ID_##_e >> 4)
+#define handler_name(_h) fts_##_h##_event_handler
+
+#define install_handler(_i, _evt, _hnd) \
+ do { \
+ _i->event_dispatch_table[event_id(_evt)] = handler_name(_hnd); \
+ } while (0)
+
+
+/* Use decimal-formatted raw data */
+#define RAW_DATA_FORMAT_DEC
+
+#ifdef KERNEL_ABOVE_2_6_38
+#define TYPE_B_PROTOCOL
+#endif
+
+extern SysInfo systemInfo;
+extern TestToDo tests;
+#ifdef GESTURE_MODE
+extern struct mutex gestureMask_mutex;
+#endif
+
+char fts_ts_phys[64]; /* /< buffer which store the input device name
+ * assigned by the kernel */
+
+static u8 typeOfCommand[CMD_STR_LEN]; /* /< buffer used to store the
+ * command sent from the MP
+ * device file node */
+static int numberParameters; /* /< number of parameter passed through the MP
+ * device file node */
+#ifdef USE_ONE_FILE_NODE
+static int feature_feasibility = ERROR_OP_NOT_ALLOW;
+#endif
+#ifdef GESTURE_MODE
+static u8 mask[GESTURE_MASK_SIZE + 2];
+extern u16 gesture_coordinates_x[GESTURE_MAX_COORDS_PAIRS_REPORT];
+extern u16 gesture_coordinates_y[GESTURE_MAX_COORDS_PAIRS_REPORT];
+extern int gesture_coords_reported;
+extern struct mutex gestureMask_mutex;
+#endif
+
+#ifdef PHONE_KEY
+static u8 key_mask; /* /< store the last update of the key mask
+ * published by the IC */
+#endif
+
+extern spinlock_t fts_int;
+
+static int fts_init_sensing(struct fts_ts_info *info);
+static int fts_mode_handler(struct fts_ts_info *info, int force);
+
+static int fts_chip_initialization(struct fts_ts_info *info, int init_type);
+
+/**
+ * Release all the touches in the linux input subsystem
+ * @param info pointer to fts_ts_info which contains info about device/hw setup
+ */
+void release_all_touches(struct fts_ts_info *info)
+{
+ unsigned int type = MT_TOOL_FINGER;
+ int i;
+
+ for (i = 0; i < TOUCH_ID_MAX; i++) {
+#ifdef STYLUS_MODE
+ if (test_bit(i, &info->stylus_id))
+ type = MT_TOOL_PEN;
+ else
+ type = MT_TOOL_FINGER;
+#endif
+ input_mt_slot(info->input_dev, i);
+ input_report_abs(info->input_dev, ABS_MT_PRESSURE, 0);
+ input_mt_report_slot_state(info->input_dev, type, 0);
+ input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, -1);
+ }
+ input_report_key(info->input_dev, BTN_TOUCH, 0);
+ input_sync(info->input_dev);
+ info->touch_id = 0;
+#ifdef STYLUS_MODE
+ info->stylus_id = 0;
+#endif
+}
+
+
+/**
+ * @defgroup file_nodes Driver File Nodes
+ * Driver publish a series of file nodes used to provide several utilities
+ * to the host and give him access to different API.
+ * @{
+ */
+
+/**
+ * @defgroup device_file_nodes Device File Nodes
+ * @ingroup file_nodes
+ * Device File Nodes \n
+ * There are several file nodes that are associated to the device and which
+ * are designed to be used by the host to enable/disable features or trigger
+ * some system specific actions \n
+ * Usually their final path depend on the definition of device tree node of
+ * the IC (e.g /sys/devices/soc.0/f9928000.i2c/i2c-6/6-0049)
+ * @{
+ */
+/***************************************** FW UPGGRADE
+ * ***************************************************/
+
+/**
+ * File node function to Update firmware from shell \n
+ * echo path_to_fw X Y > fwupdate perform a fw update \n
+ * where: \n
+ * path_to_fw = file name or path of the the FW to burn, if "NULL" the default
+ * approach selected in the driver will be used\n
+ * X = 0/1 to force the FW update whichever fw_version and config_id;
+ * 0=perform a fw update only if the fw in the file is newer than the fw in the
+ * chip \n
+ * Y = 0/1 keep the initialization data; 0 = will erase the initialization data
+ * from flash, 1 = will keep the initialization data
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 no
+ * error) \n
+ * } = end byte
+ */
+static ssize_t fts_fwupdate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, mode[2];
+ char path[100 + 1]; /* extra byte to hold '\0'*/
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ /* default(if not specified by user) set force = 0 and keep_cx to 1 */
+ mode[0] = 0;
+ mode[1] = 1;
+
+ /* reading out firmware upgrade parameters */
+ sscanf(buf, "%100s %d %d", path, &mode[0], &mode[1]);
+ pr_debug("fts_fwupdate_store: path = %s\n", path);
+
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true);
+
+ if (info->sensor_sleep)
+ ret = ERROR_BUS_WR;
+ else
+ ret = flashProcedure(path, mode[0], mode[1]);
+
+ info->fwupdate_stat = ret;
+
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+
+ if (ret == ERROR_BUS_WR)
+ pr_err("%s: bus is not accessible. ERROR %08X\n",
+ __func__, ret);
+ else if (ret < OK)
+ pr_err("%s Unable to upgrade firmware! ERROR %08X\n",
+ __func__, ret);
+
+ return count;
+}
+
+static ssize_t fts_fwupdate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ /* fwupdate_stat: ERROR code Returned by flashProcedure. */
+ return scnprintf(buf, PAGE_SIZE, "{ %08X }\n", info->fwupdate_stat);
+}
+
+
+/***************************************** UTILITIES
+ * (current fw_ver/conf_id, active mode, file fw_ver/conf_id)
+ ***************************************************/
+/**
+ * File node to show on terminal external release version in Little Endian \n
+ * (first the less significant byte) \n
+ * cat appid show the external release version of the FW running in the IC
+ */
+static ssize_t fts_appid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int error;
+ char temp[100];
+
+ error = scnprintf(buf,
+ PAGE_SIZE,
+ "%s\n",
+ printHex("ST-V",
+ systemInfo.u8_releaseInfo,
+ EXTERNAL_RELEASE_INFO_SIZE,
+ temp,
+ sizeof(temp)));
+
+ return error;
+}
+
+/**
+ * File node to show on terminal the mode that is active on the IC \n
+ * cat mode_active to show the bitmask which indicate
+ * the modes/features which are running on the IC in a specific instant of time
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1 = 1 byte in HEX format which represent the actual running scan mode
+ * (@link scan_opt Scan Mode Options @endlink) \n
+ * X2 = 1 byte in HEX format which represent the bitmask on which is running
+ * the actual scan mode \n
+ * X3X4 = 2 bytes in HEX format which represent a bitmask of the features that
+ * are enabled at this moment (@link feat_opt Feature Selection Options
+ * @endlink) \n
+ * } = end byte
+ * @see fts_mode_handler()
+ */
+static ssize_t fts_mode_active_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("Current mode active = %08X\n", info->mode);
+ return scnprintf(buf, PAGE_SIZE, "{ %08X }\n", info->mode);
+}
+
+/**
+ * File node to show the fw_ver and config_id of the FW file
+ * cat fw_file_test show on the kernel log external release
+ * of the FW stored in the fw file/header file
+ */
+static ssize_t fts_fw_test_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ Firmware fw;
+ int ret;
+ char temp[100] = { 0 };
+
+ fw.data = NULL;
+ ret = readFwFile(info->board->fw_name, &fw, 0);
+
+ if (ret < OK)
+ pr_err("Error during reading FW file! ERROR %08X\n", ret);
+ else
+ pr_debug("%s, size = %d bytes\n",
+ printHex("EXT Release = ",
+ systemInfo.u8_releaseInfo,
+ EXTERNAL_RELEASE_INFO_SIZE,
+ temp,
+ sizeof(temp)),
+ fw.data_size);
+ kfree(fw.data);
+ return 0;
+}
+
+static ssize_t fts_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ u8 *dump = NULL;
+ int dumpSize = ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE;
+ u8 reg;
+ int written = 0;
+ int res;
+ int i;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ pr_err("%s: bus is not accessible.\n", __func__);
+ written += scnprintf(buf, PAGE_SIZE,
+ "Bus is not accessible.\n");
+ goto exit;
+ }
+
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "Mode: 0x%08X\n", info->mode);
+
+ res = fts_writeReadU8UX(FTS_CMD_HW_REG_R, ADDR_SIZE_HW_REG, ADDR_ICR,
+ &reg, 1, DUMMY_HW_REG);
+ if (res < 0)
+ pr_err("%s: failed to read ICR.\n", __func__);
+ else
+ written += scnprintf(buf + written, PAGE_SIZE - written,
+ "ICR: 0x%02X\n", reg);
+
+ dump = kzalloc(dumpSize, GFP_KERNEL);
+ if (!dump) {
+ written += strlcat(buf + written, "Buffer allocation failed!\n",
+ PAGE_SIZE - written);
+ goto exit;
+ }
+
+ res = dumpErrorInfo(dump, ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE);
+ if (res >= 0) {
+ written += strlcat(buf + written, "Error dump:",
+ PAGE_SIZE - written);
+ for (i = 0; i < dumpSize; i++) {
+ if (i % 8 == 0)
+ written += scnprintf(buf + written,
+ PAGE_SIZE - written,
+ "\n%02X: ", i);
+ written += scnprintf(buf + written,
+ PAGE_SIZE - written,
+ "%02X ", dump[i]);
+ }
+ written += strlcat(buf + written, "\n", PAGE_SIZE - written);
+ }
+
+exit:
+ kfree(dump);
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return written;
+}
+
+#if 0
+/**
+ * File node to obtain and show strength frame
+ * cat strength_frame to obtain strength data \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 no
+ *error) \n
+ * **** if error code is all 0s **** \n
+ * FF = 1 byte in HEX format number of rows \n
+ * SS = 1 byte in HEX format number of columns \n
+ * N1, ... = the decimal value of each node separated by a coma \n
+ * ********************************* \n
+ * } = end byte
+ */
+static ssize_t fts_strength_frame_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ MutualSenseFrame frame;
+ int res, count, j, size = (6 * 2) + 1, index = 0;
+ char *all_strbuff = NULL;
+ /* char buff[CMD_STR_LEN] = {0}; */
+ /* struct i2c_client *client = to_i2c_client(dev); */
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ frame.node_data = NULL;
+
+ res = fts_disableInterrupt();
+ if (res < OK)
+ goto END;
+
+ res = senseOn();
+ if (res < OK) {
+ pr_err("%s: could not start scanning! ERROR %08X\n",
+ __func__, res);
+ goto END;
+ }
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ res = senseOff();
+ if (res < OK) {
+ pr_err("%s: could not finish scanning! ERROR %08X\n",
+ __func__, res);
+ goto END;
+ }
+
+ mdelay(WAIT_AFTER_SENSEOFF);
+ flushFIFO();
+
+ res = getMSFrame3(MS_STRENGTH, &frame);
+ if (res < OK) {
+ pr_err("%s: could not get the frame! ERROR %08X\n",
+ __func__, res);
+ goto END;
+ } else {
+ size += (res * 6);
+ pr_debug("The frame size is %d words\n", res);
+ res = OK;
+ print_frame_short("MS Strength frame =", array1dTo2d_short(
+ frame.node_data, frame.node_data_size,
+ frame.header.sense_node),
+ frame.header.force_node,
+ frame.header.sense_node);
+ }
+
+END:
+ flushFIFO();
+ release_all_touches(info);
+ fts_mode_handler(info, 1);
+
+ all_strbuff = (char *)kzalloc(size * sizeof(char), GFP_KERNEL);
+
+ if (all_strbuff != NULL) {
+ snprintf(&all_strbuff[index], 11, "{ %08X", res);
+
+ index += 10;
+
+ if (res >= OK) {
+ snprintf(&all_strbuff[index], 3, "%02X",
+ (u8)frame.header.force_node);
+ index += 2;
+ snprintf(&all_strbuff[index], 3, "%02X",
+ (u8)frame.header.sense_node);
+
+ index += 2;
+
+ for (j = 0; j < frame.node_data_size; j++) {
+ snprintf(&all_strbuff[index], 10, "%d,%n",
+ frame.node_data[j], &count);
+ index += count;
+ }
+
+ kfree(frame.node_data);
+ }
+
+ snprintf(&all_strbuff[index], 3, " }");
+ index += 2;
+
+ count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff);
+ kfree(all_strbuff);
+ } else
+ pr_err("%s: Unable to allocate all_strbuff! ERROR %08X\n",
+ __func__, ERROR_ALLOC);
+
+ fts_enableInterrupt();
+ return count;
+}
+#endif
+
+/***************************************** FEATURES
+ ***************************************************/
+
+/* TODO: edit this function according to the features policy to allow during
+ * the screen on/off, following is shown an example but check always with ST
+ * for more details */
+/**
+ * Check if there is any conflict in enable/disable a particular feature
+ * considering the features already enabled and running
+ * @param info pointer to fts_ts_info which contains info about the device
+ * and its hw setup
+ * @param feature code of the feature that want to be tested
+ * @return OK if is possible to enable/disable feature, ERROR_OP_NOT_ALLOW
+ * in case of any other conflict
+ */
+int check_feature_feasibility(struct fts_ts_info *info, unsigned int feature)
+{
+ int res = OK;
+
+/* Example based on the status of the screen and on the feature
+ * that is trying to enable */
+ /*res=ERROR_OP_NOT_ALLOW;
+ * if(info->resume_bit ==0){
+ * switch(feature){
+ #ifdef GESTURE_MODE
+ * case FEAT_SEL_GESTURE:
+ * res = OK;
+ * break;
+ #endif
+ * default:
+ * pr_err("%s: Feature not allowed in this
+ * operating mode! ERROR %08X\n", __func__, res);
+ * break;
+ *
+ * }
+ * }else{
+ * switch(feature){
+ #ifdef GESTURE_MODE
+ * case FEAT_SEL_GESTURE:
+ #endif
+ * case FEAT__SEL_GLOVE: // glove mode can only activate
+ *during sense on
+ * res = OK;
+ * break;
+ *
+ * default:
+ * pr_err("%s: Feature not allowed in this
+ * operating mode! ERROR %08X\n", __func__, res);
+ * break;
+ *
+ * }
+ * }*/
+
+
+/* Example based only on the feature that is going to be activated */
+ switch (feature) {
+ case FEAT_SEL_GESTURE:
+ if (info->cover_enabled == 1) {
+ res = ERROR_OP_NOT_ALLOW;
+ pr_err("%s: Feature not allowed when in Cover mode! ERROR %08X\n",
+ __func__, res);
+ /* for example here can be placed a code for disabling
+ * the cover mode when gesture is activated */
+ }
+ break;
+
+ case FEAT_SEL_GLOVE:
+ if (info->gesture_enabled == 1) {
+ res = ERROR_OP_NOT_ALLOW;
+ pr_err("%s: Feature not allowed when Gestures enabled! ERROR %08X\n",
+ __func__, res);
+ /* for example here can be placed a code for disabling
+ * the gesture mode when cover is activated
+ * (that means that cover mode has
+ * an higher priority on gesture mode) */
+ }
+ break;
+
+ default:
+ pr_debug("%s: Feature Allowed!\n", __func__);
+ }
+
+ return res;
+}
+
+#ifdef USE_ONE_FILE_NODE
+/**
+ * File node to enable some feature
+ * echo XX 00/01 > feature_enable to enable/disable XX
+ * (possible values @link feat_opt Feature Selection Options @endlink) feature
+ * cat feature_enable to show the result of enabling/disabling process
+ * echo 01/00 > feature_enable; cat feature_enable to perform
+ * both actions stated before in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 =
+ * no error) \n
+ * } = end byte
+ */
+static ssize_t fts_feature_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ char *p = (char *)buf;
+ unsigned int temp;
+ int res = OK;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ res = ERROR_BUS_WR;
+ pr_err("%s: bus is not accessible.", __func__);
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return count;
+ }
+
+ if ((count - 2 + 1) / 3 != 1)
+ pr_err("fts_feature_enable: Number of parameter wrong! %d > %d\n",
+ (count - 2 + 1) / 3, 1);
+ else {
+ sscanf(p, "%02X ", &temp);
+ p += 3;
+ res = check_feature_feasibility(info, temp);
+ if (res >= OK) {
+ switch (temp) {
+ #ifdef GESTURE_MODE
+ case FEAT_SEL_GESTURE:
+ sscanf(p, "%02X ", &info->gesture_enabled);
+ pr_debug("fts_feature_enable: Gesture Enabled = %d\n",
+ info->gesture_enabled);
+ break;
+ #endif
+
+ #ifdef GLOVE_MODE
+ case FEAT_SEL_GLOVE:
+ sscanf(p, "%02X ", &info->glove_enabled);
+ pr_debug("fts_feature_enable: Glove Enabled = %d\n",
+ info->glove_enabled);
+ break;
+ #endif
+
+ #ifdef STYLUS_MODE
+ case FEAT_SEL_STYLUS:
+ sscanf(p, "%02X ", &info->stylus_enabled);
+ pr_debug("fts_feature_enable: Stylus Enabled = %d\n",
+ info->stylus_enabled);
+ break;
+ #endif
+
+ #ifdef COVER_MODE
+ case FEAT_SEL_COVER:
+ sscanf(p, "%02X ", &info->cover_enabled);
+ pr_debug("fts_feature_enable: Cover Enabled = %d\n",
+ info->cover_enabled);
+ break;
+ #endif
+
+ #ifdef CHARGER_MODE
+ case FEAT_SEL_CHARGER:
+ sscanf(p, "%02X ", &info->charger_enabled);
+ pr_debug("fts_feature_enable: Charger Enabled = %d\n",
+ info->charger_enabled);
+ break;
+ #endif
+
+ #ifdef GRIP_MODE
+ case FEAT_SEL_GRIP:
+ sscanf(p, "%02X ", &info->grip_enabled);
+ pr_debug("fts_feature_enable: Grip Enabled = %d\n",
+ info->grip_enabled);
+ break;
+ #endif
+
+
+
+ default:
+ pr_err("fts_feature_enable: Feature %08X not valid! ERROR %08X\n",
+ temp, ERROR_OP_NOT_ALLOW);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ feature_feasibility = res;
+ }
+ if (feature_feasibility >= OK)
+ feature_feasibility = fts_mode_handler(info, 1);
+ else
+ pr_err("%s: Call echo XX 00/01 > feature_enable with a correct feature value (XX)! ERROR %08X\n",
+ __func__, res);
+ }
+
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return count;
+}
+
+
+
+static ssize_t fts_feature_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+
+ if (feature_feasibility < OK)
+ pr_err("%s: Call before echo XX 00/01 > feature_enable with a correct feature value (XX)! ERROR %08X\n",
+ __func__, feature_feasibility);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ feature_feasibility);
+
+ feature_feasibility = ERROR_OP_NOT_ALLOW;
+ return count;
+}
+
+#else
+
+
+#ifdef GRIP_MODE
+/**
+ * File node to set the grip mode
+ * echo 01/00 > grip_mode to enable/disable glove mode \n
+ * cat grip_mode to show the status of the grip_enabled switch \n
+ * echo 01/00 > grip_mode; cat grip_mode to enable/disable grip
+ *mode
+ * and see the switch status in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent the value
+ * info->grip_enabled (1 = enabled; 0= disabled) \n
+ * } = end byte
+ */
+static ssize_t fts_grip_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("%s: grip_enabled = %d\n", __func__,
+ info->grip_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ info->grip_enabled);
+
+ return count;
+}
+
+
+static ssize_t fts_grip_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char *p = (char *)buf;
+ unsigned int temp = FEAT_DISABLE;
+ int res;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ pr_err("%s: bus is not accessible.", __func__);
+ goto exit;
+ }
+
+ /* in case of a different elaboration of the input, just modify
+ * this initial part of the code according to customer needs */
+ if ((count + 1) / 3 != 1)
+ pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n",
+ __func__, (count + 1) / 3);
+ else {
+ res = sscanf(p, "%02X ", &temp);
+ if ((res != 1) || (temp > FEAT_ENABLE)) {
+ pr_err("%s: Missing or invalid grip mode(%u)\n",
+ __func__, temp);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+/* standard code that should be always used when a feature is enabled! */
+/* first step : check if the wanted feature can be enabled */
+/* second step: call fts_mode_handler to actually enable it */
+/* NOTE: Disabling a feature is always allowed by default */
+ res = check_feature_feasibility(info, FEAT_SEL_GRIP);
+ if (res >= OK || temp == FEAT_DISABLE) {
+ info->grip_enabled = temp;
+ res = fts_mode_handler(info, 1);
+ if (res < OK)
+ pr_err("%s: Error during fts_mode_handler! ERROR %08X\n",
+ __func__, res);
+ }
+ }
+
+exit:
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return retval;
+}
+#endif
+
+#ifdef CHARGER_MODE
+/**
+ * File node to set the glove mode
+ * echo XX/00 > charger_mode to value >0 to enable
+ * (possible values: @link charger_opt Charger Options @endlink),
+ * 00 to disable charger mode \n
+ * cat charger_mode to show the status of the charger_enabled switch \n
+ * echo 01/00 > charger_mode; cat charger_mode to enable/disable
+ * charger mode and see the switch status in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent the value
+ * info->charger_enabled (>0 = enabled; 0= disabled) \n
+ * } = end byte
+ */
+static ssize_t fts_charger_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("%s: charger_enabled = %d\n", __func__,
+ info->charger_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ info->charger_enabled);
+ return count;
+}
+
+
+static ssize_t fts_charger_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char *p = (char *)buf;
+ unsigned int temp = FEAT_DISABLE;
+ int res;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ pr_err("%s: bus is not accessible.\n", __func__);
+ goto exit;
+ }
+
+/* in case of a different elaboration of the input, just modify this
+ * initial part of the code according to customer needs */
+ if ((count + 1) / 3 != 1) {
+ pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n",
+ __func__, (count + 1) / 3);
+ retval = -EINVAL;
+ } else {
+ res = sscanf(p, "%02X ", &temp);
+ if ((res != 1) || (temp > FEAT_ENABLE)) {
+ pr_err("%s: Missing or invalid charger mode (%u)\n",
+ __func__, temp);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+/** standard code that should be always used when a feature is enabled!
+ * first step : check if the wanted feature can be enabled
+ * second step: call fts_mode_handler to actually enable it
+ * NOTE: Disabling a feature is always allowed by default
+ */
+ res = check_feature_feasibility(info, FEAT_SEL_CHARGER);
+ if (res >= OK || temp == FEAT_DISABLE) {
+ info->charger_enabled = temp;
+ res = fts_mode_handler(info, 1);
+ if (res < OK)
+ pr_err("%s: Error during fts_mode_handler! ERROR %08X\n",
+ __func__, res);
+ }
+ }
+
+exit:
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return retval;
+}
+#endif
+
+#ifdef GLOVE_MODE
+/**
+ * File node to set the glove mode
+ * echo 01/00 > glove_mode to enable/disable glove mode \n
+ * cat glove_mode to show the status of the glove_enabled switch \n
+ * echo 01/00 > glove_mode; cat glove_mode to enable/disable glove mode and
+ * see the switch status in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent the of value
+ * info->glove_enabled (1 = enabled; 0= disabled) \n
+ * } = end byte
+ */
+static ssize_t fts_glove_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("%s: glove_enabled = %d\n", __func__, info->glove_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ info->glove_enabled);
+
+ return count;
+}
+
+
+static ssize_t fts_glove_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ unsigned int temp = FEAT_DISABLE;
+ int res;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ pr_err("%s: bus is not accessible.\n", __func__);
+ goto exit;
+ }
+
+/* in case of a different elaboration of the input, just modify this
+ * initial part of the code according to customer needs */
+ if ((count + 1) / 3 != 1) {
+ pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n",
+ __func__, (count + 1) / 3);
+ retval = -EINVAL;
+ } else {
+ res = sscanf(p, "%02X ", &temp);
+ if ((res != 1) || (temp > FEAT_ENABLE)) {
+ pr_err("%s: Missing or invalid glove mode(%u)\n",
+ __func__, temp);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+/* standard code that should be always used when a feature is enabled! */
+/* first step : check if the wanted feature can be enabled */
+/* second step: call fts_mode_handler to actually enable it */
+/* NOTE: Disabling a feature is always allowed by default */
+ res = check_feature_feasibility(info, FEAT_SEL_GLOVE);
+ if (res >= OK || temp == FEAT_DISABLE) {
+ info->glove_enabled = temp;
+ res = fts_mode_handler(info, 1);
+ if (res < OK)
+ pr_err("%s: Error during fts_mode_handler! ERROR %08X\n",
+ __func__, res);
+ }
+ }
+
+exit:
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return retval;
+}
+#endif
+
+
+#ifdef COVER_MODE
+/* echo 01/00 > cover_mode to enable/disable cover mode */
+/* cat cover_mode to show the status of the cover_enabled switch
+ * (example output in the terminal = "AA00000001BB" if the switch is enabled) */
+/* echo 01/00 > cover_mode; cat cover_mode to enable/disable cover mode and
+ * see the switch status in just one call */
+/* NOTE: the cover can be handled also using a notifier, in this case the body
+ * of these functions should be copied in the notifier callback */
+/**
+ * File node to set the cover mode
+ * echo 01/00 > cover_mode to enable/disable cover mode \n
+ * cat cover_mode to show the status of the cover_enabled switch \n
+ * echo 01/00 > cover_mode; cat cover_mode to enable/disable cover mode
+ * and see the switch status in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which is the value of info->cover_enabled
+ * (1 = enabled; 0= disabled)\n
+ * } = end byte \n
+ * NOTE: \n
+ * the cover can be handled also using a notifier, in this case the body of
+ * these functions should be copied in the notifier callback
+ */
+static ssize_t fts_cover_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("%s: cover_enabled = %d\n", __func__, info->cover_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ info->cover_enabled);
+
+ return count;
+}
+
+
+static ssize_t fts_cover_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ unsigned int temp = FEAT_DISABLE;
+ int res;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ pr_err("%s: bus is not accessible.\n", __func__);
+ goto exit;
+ }
+
+/* in case of a different elaboration of the input, just modify this
+ * initial part of the code according to customer needs */
+ if ((count + 1) / 3 != 1)
+ pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n",
+ __func__, (count + 1) / 3);
+ else {
+ res = sscanf(p, "%02X ", &temp);
+ if ((res != 1) || (temp > FEAT_ENABLE)) {
+ pr_err("%s: Missing or invalid cover mode(%u)\n",
+ __func__, temp);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ p += 3;
+
+/* standard code that should be always used when a feature is enabled! */
+/* first step : check if the wanted feature can be enabled */
+/* second step: call fts_mode_handler to actually enable it */
+/* NOTE: Disabling a feature is always allowed by default */
+ res = check_feature_feasibility(info, FEAT_SEL_COVER);
+ if (res >= OK || temp == FEAT_DISABLE) {
+ info->cover_enabled = temp;
+ res = fts_mode_handler(info, 1);
+ if (res < OK)
+ pr_err("%s: Error during fts_mode_handler! ERROR %08X\n",
+ __func__, res);
+ }
+ }
+
+exit:
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return retval;
+}
+#endif
+
+#ifdef STYLUS_MODE
+/**
+ * File node to enable the stylus report
+ * echo 01/00 > stylus_mode to enable/disable stylus mode \n
+ * cat stylus_mode to show the status of the stylus_enabled switch \n
+ * echo 01/00 > stylus_mode; cat stylus_mode to enable/disable stylus mode
+ * and see the switch status in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which is the value of info->stylus_enabled
+ * (1 = enabled; 0= disabled)\n
+ * } = end byte
+ */
+static ssize_t fts_stylus_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("%s: stylus_enabled = %d\n", __func__, info->stylus_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ info->stylus_enabled);
+
+ return count;
+}
+
+
+static ssize_t fts_stylus_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ unsigned int temp = FEAT_DISABLE;
+ int res;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+
+
+/* in case of a different elaboration of the input, just modify this
+ * initial part of the code according to customer needs */
+ if ((count + 1) / 3 != 1)
+ pr_err("%s: Number of bytes of parameter wrong! %zu != 1 byte\n",
+ __func__, (count + 1) / 3);
+ else {
+ res = sscanf(p, "%02X ", &temp);
+ if ((res != 1) || (temp > FEAT_ENABLE)) {
+ pr_err("%s: Missing or invalid stylus mode(%u)\n",
+ __func__, temp);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ info->stylus_enabled = temp;
+ }
+
+exit:
+ return retval;
+}
+#endif
+
+#endif
+
+/***************************************** GESTURES
+ ***************************************************/
+#ifdef GESTURE_MODE
+#ifdef USE_GESTURE_MASK /* if this define is used, a gesture bit mask
+ * is used as method to select the gestures to
+ * enable/disable */
+
+/**
+ * File node used by the host to set the gesture mask to enable or disable
+ * echo EE X1 X2 ~~ > gesture_mask set the gesture to disable/enable;
+ * EE = 00(disable) or 01(enable) \n
+ * X1 ~~ = gesture mask (example 06 00 ~~ 00 this gesture mask represents
+ * the gestures with ID = 1 and 2) can be specified
+ * from 1 to GESTURE_MASK_SIZE bytes, \n
+ * if less than GESTURE_MASK_SIZE bytes are passed as arguments,
+ * the omit bytes of the mask maintain the previous settings \n
+ * if one or more gestures is enabled the driver will automatically
+ * enable the gesture mode, If all the gestures are disabled the driver
+ * automatically will disable the gesture mode \n
+ * cat gesture_mask set inside the specified mask and return an error code
+ * for the operation \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent an error code for enabling
+ * the mask (00000000 = no error)\n
+ * } = end byte \n\n
+ * if USE_GESTURE_MASK is not define the usage of the function become: \n\n
+ * echo EE X1 X2 ~~ > gesture_mask set the gesture to disable/enable;
+ * EE = 00(disable) or 01(enable) \n
+ * X1 ~~ = gesture IDs (example 01 02 05 represent the gestures with ID = 1, 2
+ * and 5)
+ * there is no limit of the IDs passed as arguments, (@link gesture_opt Gesture
+ * IDs @endlink) \n
+ * if one or more gestures is enabled the driver will automatically enable
+ * the gesture mode. If all the gestures are disabled the driver automatically
+ * will disable the gesture mode. \n
+ * cat gesture_mask to show the status of the gesture enabled switch \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which is the value of info->gesture_enabled
+ * (1 = enabled; 0= disabled)\n
+ * } = end byte
+ */
+static ssize_t fts_gesture_mask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0, res, temp;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ res = ERROR_BUS_WR;
+ pr_err("%s: bus is not accessible.\n", __func__);
+ scnprintf(buf, PAGE_SIZE, "{ %08X }\n", res);
+ goto exit;
+ }
+
+ if (mask[0] == 0) {
+ res = ERROR_OP_NOT_ALLOW;
+ pr_err("%s: Call before echo enable/disable xx xx .... > gesture_mask with a correct number of parameters! ERROR %08X\n",
+ __func__, res);
+ } else {
+ if (mask[1] == FEAT_ENABLE || mask[1] == FEAT_DISABLE)
+ res = updateGestureMask(&mask[2], mask[0], mask[1]);
+ else
+ res = ERROR_OP_NOT_ALLOW;
+
+ if (res < OK)
+ pr_err("fts_gesture_mask_store: ERROR %08X\n", res);
+ }
+ res |= check_feature_feasibility(info, FEAT_SEL_GESTURE);
+ temp = isAnyGestureActive();
+ if (res >= OK || temp == FEAT_DISABLE)
+ info->gesture_enabled = temp;
+
+ pr_debug("fts_gesture_mask_store: Gesture Enabled = %d\n",
+ info->gesture_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n", res);
+ mask[0] = 0;
+
+exit:
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return count;
+}
+
+
+static ssize_t fts_gesture_mask_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ int n, res;
+ unsigned int temp = 0;
+ ssize_t retval = count;
+
+ if ((count + 1) / 3 > GESTURE_MASK_SIZE + 1) {
+ pr_err("fts_gesture_mask_store: Number of bytes of parameter wrong! %zu > (enable/disable + %d )\n",
+ (count + 1) / 3, GESTURE_MASK_SIZE);
+ mask[0] = 0;
+ } else {
+ mask[0] = ((count + 1) / 3) - 1;
+ for (n = 1; n <= (count + 1) / 3; n++) {
+ res = sscanf(p, "%02X ", &temp);
+ if (res != 1) {
+ pr_err("%s: Invalid input\n", __func__);
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ p += 3;
+ mask[n] = (u8)temp;
+ pr_debug("mask[%d] = %02X\n", n, mask[n]);
+ }
+ }
+exit:
+ return retval;
+}
+
+#else /* if this define is not used, to select the gestures to enable/disable
+ * are used the IDs of the gestures */
+/* echo EE X1 X2 ... > gesture_mask set the gesture to disable/enable;
+ * EE = 00(disable) or 01(enable); X1 ... = gesture IDs
+ * (example 01 02 05... represent the gestures with ID = 1, 2 and 5)
+ * there is no limit of the parameters that can be passed,
+ * of course the gesture IDs should be valid (all the valid IDs are listed in
+ * ftsGesture.h) */
+/* cat gesture_mask enable/disable the given gestures, if one or more
+ * gestures is enabled the driver will automatically enable the gesture mode.
+ * If all the gestures are disabled the driver automatically will disable the
+ * gesture mode.
+ * At the end an error code will be printed
+ * (example output in the terminal = "AA00000000BB" if there are no errors) */
+/* echo EE X1 X2 ... > gesture_mask; cat gesture_mask perform in one command
+ * both actions stated before */
+/**
+ * File node used by the host to set the gesture mask to enable or disable
+ * echo EE X1 X2 ~~ > gesture_mask set the gesture to disable/enable;
+ * EE = 00(disable) or 01(enable) \n
+ * X1 ~ = gesture IDs (example 01 02 05 represent the gestures with ID = 1, 2
+ * and 5)
+ * there is no limit of the IDs passed as arguments, (@link gesture_opt Gesture
+ * IDs @endlink) \n
+ * if one or more gestures is enabled the driver will automatically enable
+ * the gesture mode, If all the gestures are disabled the driver automatically
+ * will disable the gesture mode \n
+ * cat gesture_mask to show the status of the gesture enabled switch \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which is the value of info->gesture_enabled
+ * (1 = enabled; 0= disabled)\n
+ * } = end byte
+ */
+static ssize_t fts_gesture_mask_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int count = 0;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ pr_debug("fts_gesture_mask_show: gesture_enabled = %d\n",
+ info->gesture_enabled);
+
+ count += scnprintf(buf + count,
+ PAGE_SIZE - count, "{ %08X }\n",
+ info->gesture_enabled);
+
+
+ return count;
+}
+
+
+static ssize_t fts_gesture_mask_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ char *p = (char *)buf;
+ int n;
+ unsigned int temp = 0;
+ int res;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ pr_err("%s: bus is not accessible.\n", __func__);
+ goto exit;
+ }
+
+ if ((count + 1) / 3 < 2 || (count + 1) / 3 > GESTURE_MASK_SIZE + 1) {
+ pr_err("fts_gesture_mask_store: Number of bytes of parameter wrong! %d < or > (enable/disable + at least one gestureID or max %d bytes)\n",
+ (count + 1) / 3, GESTURE_MASK_SIZE);
+ mask[0] = 0;
+ retval = -EINVAL;
+ } else {
+ memset(mask, 0, GESTURE_MASK_SIZE + 2);
+ mask[0] = ((count + 1) / 3) - 1;
+ res = sscanf(p, "%02X ", &temp);
+ if (res != 1) {
+ pr_err("%s: Invalid input(%u)\n",__func__, temp);
+ mask[0] = 0;
+ retval = -EINVAL;
+ goto bad_param;
+ }
+
+ p += 3;
+ mask[1] = (u8)temp;
+ for (n = 1; n < (count + 1) / 3; n++) {
+ res = sscanf(p, "%02X ", &temp);
+ if (res != 1) {
+ pr_err("%s: Invalid input\n", __func__);
+ mask[0] = 0;
+ retval = -EINVAL;
+ goto bad_param;
+ }
+
+ p += 3;
+ fromIDtoMask((u8)temp, &mask[2], GESTURE_MASK_SIZE);
+ }
+
+ for (n = 0; n < GESTURE_MASK_SIZE + 2; n++)
+ pr_debug("mask[%d] = %02X\n", n, mask[n]);
+ }
+
+bad_param;
+ if (mask[0] == 0) {
+ res = ERROR_OP_NOT_ALLOW;
+ pr_err("%s: Call before echo enable/disable xx xx .... > gesture_mask with a correct number of parameters! ERROR %08X\n",
+ __func__, res);
+
+ goto exit;
+ }
+
+ if (mask[1] == FEAT_ENABLE || mask[1] == FEAT_DISABLE)
+ res = updateGestureMask(&mask[2], mask[0], mask[1]);
+ else
+ res = ERROR_OP_NOT_ALLOW;
+
+ if (res < OK)
+ pr_err("fts_gesture_mask_store: ERROR %08X\n", res);
+
+ res = check_feature_feasibility(info, FEAT_SEL_GESTURE);
+ temp = isAnyGestureActive();
+ if (res >= OK || temp == FEAT_DISABLE)
+ info->gesture_enabled = temp;
+ res = fts_mode_handler(info, 0);
+
+exit:
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ return retval;
+}
+
+
+#endif
+
+
+/**
+ * File node to read the coordinates of the last gesture drawn by the user \n
+ * cat gesture_coordinates to obtain the gesture coordinates \n
+ * the string returned in the shell follow this up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent an error code (00000000 =
+ *OK) \n
+ * \n if error code = 00000000 \n
+ * CC = 1 byte in HEX format number of coords (pair of x,y) returned \n
+ * XXiYYi ... = XXi 2 bytes in HEX format for x[i] and
+ * YYi 2 bytes in HEX format for y[i] (big endian) \n
+ * \n
+ * } = end byte
+ */
+static ssize_t fts_gesture_coordinates_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int size = PAGE_SIZE;
+ int count = 0, res, i = 0;
+
+ pr_debug("%s: Getting gestures coordinates...\n", __func__);
+
+ if (gesture_coords_reported < OK) {
+ pr_err("%s: invalid coordinates! ERROR %08X\n",
+ __func__, gesture_coords_reported);
+ res = gesture_coords_reported;
+ } else {
+ size += gesture_coords_reported * 2 * 4 + 2;
+ /* coords are pairs of x,y (*2) where each coord is
+ * short(2bytes=4char)(*4) + 1 byte(2char) num of coords (+2)
+ **/
+ res = OK; /* set error code to OK */
+ }
+
+
+ count += scnprintf(buf + count,
+ size - count, "{ %08X", res);
+
+ if (res >= OK) {
+ count += scnprintf(buf + count,
+ size - count, "%02X",
+ gesture_coords_reported);
+
+ for (i = 0; i < gesture_coords_reported; i++) {
+ count += scnprintf(buf + count,
+ size - count,
+ "%04X",
+ gesture_coordinates_x[i]);
+ count += scnprintf(buf + count,
+ size - count,
+ "%04X",
+ gesture_coordinates_y[i]);
+ }
+ }
+
+ count += scnprintf(buf + count, size - count, " }\n");
+ pr_debug("%s: Getting gestures coordinates FINISHED!\n", __func__);
+
+ return count;
+}
+#endif
+
+/* Touch simulation hr timer expiry callback */
+static enum hrtimer_restart touchsim_timer_cb(struct hrtimer *timer)
+{
+ struct fts_touchsim *touchsim = container_of(timer,
+ struct fts_touchsim,
+ hr_timer);
+ enum hrtimer_restart retval = HRTIMER_NORESTART;
+
+ if (touchsim->is_running) {
+ hrtimer_forward_now(timer,
+ ns_to_ktime(TOUCHSIM_TIMER_INTERVAL_NS));
+ retval = HRTIMER_RESTART;
+ }
+
+ /* schedule the task to report touch coordinates to kernel
+ * input subsystem
+ */
+ queue_work(touchsim->wq, &touchsim->work);
+
+ return retval;
+}
+
+/* Compute the next touch coordinate(x,y) */
+static void touchsim_refresh_coordinates(struct fts_touchsim *touchsim)
+{
+ struct fts_ts_info *info = container_of(touchsim,
+ struct fts_ts_info,
+ touchsim);
+
+ const int x_start = info->board->x_axis_max / 10;
+ const int x_max = (info->board->x_axis_max * 9) / 10;
+ const int y_start = info->board->y_axis_max / 4;
+ const int y_max = info->board->y_axis_max / 2;
+
+ touchsim->x += touchsim->x_step;
+ touchsim->y += touchsim->y_step;
+
+ if (touchsim->x < x_start || touchsim->x > x_max)
+ touchsim->x_step *= -1;
+
+ if (touchsim->y < y_start || touchsim->y > y_max)
+ touchsim->y_step *= -1;
+}
+
+/* Report touch contact */
+static void touchsim_report_contact_event(struct input_dev *dev, int slot_id,
+ int x, int y, int z)
+{
+ /* report the cordinates to the input subsystem */
+ input_mt_slot(dev, slot_id);
+ input_report_key(dev, BTN_TOUCH, true);
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
+ input_report_abs(dev, ABS_MT_POSITION_X, x);
+ input_report_abs(dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(dev, ABS_MT_PRESSURE, z);
+}
+
+/* Work callback to report the touch co-ordinates to input subsystem */
+static void touchsim_work(struct work_struct *work)
+{
+ struct fts_touchsim *touchsim = container_of(work,
+ struct fts_touchsim,
+ work);
+ struct fts_ts_info *info = container_of(touchsim,
+ struct fts_ts_info,
+ touchsim);
+
+ /* prevent CPU from entering deep sleep */
+ cpu_latency_qos_update_request(&info->pm_qos_req, 100);
+
+ /* Notify the PM core that the wakeup event will take 1 sec */
+ __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ));
+
+ /* get the next touch coordinates */
+ touchsim_refresh_coordinates(touchsim);
+
+ /* send the touch co-ordinates */
+ touchsim_report_contact_event(info->input_dev, TOUCHSIM_SLOT_ID,
+ touchsim->x, touchsim->y, 1);
+
+ input_sync(info->input_dev);
+
+ cpu_latency_qos_update_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE);
+}
+
+/* Start the touch simulation */
+static int touchsim_start(struct fts_touchsim *touchsim)
+{
+ struct fts_ts_info *info = container_of(touchsim,
+ struct fts_ts_info,
+ touchsim);
+ if (!touchsim->wq) {
+ pr_err("%s: touch simulation test wq is not available!\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ if (touchsim->is_running) {
+ pr_err("%s: test in progress!\n", __func__);
+ return -EBUSY;
+ }
+
+ /* setup the initial touch coordinates*/
+ touchsim->x = info->board->x_axis_max / 10;
+ touchsim->y = info->board->y_axis_max / 4;
+
+ touchsim->is_running = true;
+
+ touchsim->x_step = 2;
+ touchsim->y_step = 2;
+
+ /* Disable touch interrupts from hw */
+ fts_disableInterrupt();
+
+ /* Release all touches in the linux input subsystem */
+ release_all_touches(info);
+
+ /* setup and start a hr timer to be fired every 120Hz(~8.333333ms) */
+ hrtimer_init(&touchsim->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ touchsim->hr_timer.function = touchsim_timer_cb;
+ hrtimer_start(&touchsim->hr_timer,
+ ns_to_ktime(TOUCHSIM_TIMER_INTERVAL_NS),
+ HRTIMER_MODE_ABS);
+
+ return OK;
+}
+
+/* Stop the touch simulation test */
+static int touchsim_stop(struct fts_touchsim *touchsim)
+{
+ struct fts_ts_info *info = container_of(touchsim,
+ struct fts_ts_info,
+ touchsim);
+ if (!touchsim->is_running) {
+ pr_err("%s: test is not in progress!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Set the flag here to make sure flushed work doesn't
+ * re-start the timer
+ */
+ touchsim->is_running = false;
+
+ hrtimer_cancel(&touchsim->hr_timer);
+
+ /* flush any pending work */
+ flush_workqueue(touchsim->wq);
+
+ /* Release all touches in the linux input subsystem */
+ release_all_touches(info);
+
+ /* re enable the hw touch interrupt */
+ fts_enableInterrupt();
+
+ return OK;
+}
+
+/** sysfs file node to handle the touch simulation test request.
+ * "cat touchsim" shows if the test is running
+ * Possible outputs:
+ * 1 = test running.
+ * 0 = test not running.
+ */
+static ssize_t fts_touch_simulation_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ info->touchsim.is_running ? 1 : 0);
+}
+
+/** sysfs file node to handle the touch simulation test request.
+ * "echo <cmd> > touchsim" to execute a command
+ * Possible commands (cmd):
+ * 1 = start the test if not already running.
+ * 0 = stop the test if its running.
+ */
+static ssize_t fts_touch_simulation_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ ssize_t retval = count;
+ u8 result;
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ retval = -EBUSY;
+ goto out;
+ }
+
+ if (kstrtou8(buf, 16, &result)) {
+ pr_err("%s:bad input. valid inputs are either 0 or 1!\n",
+ __func__);
+ retval = -EINVAL;
+ goto unlock;
+ }
+
+ if (result == 1)
+ touchsim_start(&info->touchsim);
+ else if (result == 0)
+ touchsim_stop(&info->touchsim);
+ else
+ pr_err("%s:Invalid cmd(%u). valid cmds are either 0 or 1!\n",
+ __func__, result);
+unlock:
+ mutex_unlock(&info->diag_cmd_lock);
+out:
+ return retval;
+}
+
+/***************************************** PRODUCTION TEST
+ ***************************************************/
+
+/**
+ * File node to execute the Mass Production Test or to get data from the IC
+ * (raw or ms/ss init data)
+ * echo cmd > stm_fts_cmd to execute a command \n
+ * cat stm_fts_cmd to show the result of the command \n
+ * echo cmd > stm_fts_cmd; cat stm_fts_cmd to execute and show the result
+ * in just one call \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * X1X2X3X4 = 4 bytes in HEX format which represent an error_code (00000000 =
+ * OK)\n
+ * (optional) data = data coming from the command executed represented as HEX
+ * string \n
+ * Not all the command return additional data \n
+ * } = end byte \n
+ * \n
+ * Possible commands (cmd): \n
+ * - 00 = MP Test -> return error_code \n
+ * - 01 = ITO Test -> return error_code \n
+ * - 03 = MS Raw Test -> return error_code \n
+ * - 04 = MS Init Data Test -> return error_code \n
+ * - 05 = SS Raw Test -> return error_code \n
+ * - 06 = SS Init Data Test -> return error_code \n
+ * - 13 = Read 1 MS Raw Frame -> return additional data: MS frame row after row
+ * \n
+ * - 14 = Read MS Init Data -> return additional data: MS init data row after
+ * row \n
+ * - 15 = Read 1 SS Raw Frame -> return additional data: SS frame,
+ * force channels followed by sense channels \n
+ * - 16 = Read SS Init Data -> return additional data: SS Init data,
+ * first IX for force and sense channels and then CX for force and sense
+ * channels \n
+ * - F0 = Perform a system reset -> return error_code \n
+ * - F1 = Perform a system reset and reenable the sensing and the interrupt
+ */
+static ssize_t stm_fts_cmd_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ u8 result, n = 0;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+ char *p, *temp_buf, *token;
+ ssize_t buf_len;
+ ssize_t retval = count;
+
+ if (!count) {
+ pr_err("%s: Invalid input buffer length!\n", __func__);
+ retval = -EINVAL;
+ goto out;
+ }
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ retval = -EINVAL;
+ goto out;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ retval = -EBUSY;
+ goto out;
+ }
+
+ memset(typeOfCommand, 0, sizeof(typeOfCommand));
+
+ buf_len = strlen(buf) + 1;
+ temp_buf = kmalloc(buf_len, GFP_KERNEL);
+ if (!temp_buf) {
+ pr_err("%s: memory allocation failed for length(%zu)!",
+ __func__, buf_len);
+ retval = -ENOMEM;
+ goto unlock;
+ }
+
+ strlcpy(temp_buf, buf, buf_len);
+ p = temp_buf;
+
+ /* Parse the input string to retrieve 2 hex-digit width cmds/args
+ * separated by one or more spaces.
+ * Any input not equal to 2 hex-digit width are ignored.
+ * A single 2 hex-digit width command w/ or w/o space is allowed.
+ * Inputs not in the valid hex range are also ignored.
+ * In case of encountering any of the above failure, the entire input
+ * buffer is discarded.
+ */
+ while (p && (n < CMD_STR_LEN)) {
+
+ while (isspace(*p)) {
+ p++;
+ }
+
+ token = strsep(&p, " ");
+
+ if (!token || *token == '\0') {
+ break;
+ }
+
+ if (strlen(token) != 2 ) {
+ pr_debug("%s: bad len. len=%zu\n",
+ __func__, strlen(token));
+ n = 0;
+ break;
+ }
+
+ if (kstrtou8(token, 16, &result)) {
+ /* Conversion failed due to bad input.
+ * Discard the entire buffer.
+ */
+ pr_debug("%s: bad input\n", __func__);
+ n = 0;
+ break;
+ }
+
+ /* found a valid cmd/args */
+ typeOfCommand[n] = result;
+ pr_debug("%s: typeOfCommand[%d]=%02X\n",
+ __func__, n, typeOfCommand[n]);
+
+ n++;
+ }
+
+ if (n == 0) {
+ pr_err("%s: Found invalid cmd/arg\n", __func__);
+ retval = -EINVAL;
+ }
+
+ numberParameters = n;
+ pr_debug("%s: Number of Parameters = %d\n", __func__, numberParameters);
+
+ kfree(temp_buf);
+
+unlock:
+ mutex_unlock(&info->diag_cmd_lock);
+out:
+ return retval;
+}
+
+static ssize_t stm_fts_cmd_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int res, j, doClean = 0, index = 0;
+ int size = (6 * 2) + 1;
+ int nodes = 0;
+ int init_type = SPECIAL_PANEL_INIT;
+ u8 *all_strbuff = buf;
+ struct fts_ts_info *info = dev_get_drvdata(dev);
+
+ MutualSenseData compData;
+ SelfSenseData comData;
+ MutualSenseFrame frameMS;
+ SelfSenseFrame frameSS;
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ return -EBUSY;
+ }
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ res = ERROR_BUS_WR;
+ pr_err("%s: bus is not accessible.\n", __func__);
+ scnprintf(buf, PAGE_SIZE, "{ %08X }\n", res);
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ mutex_unlock(&info->diag_cmd_lock);
+ return 0;
+ }
+
+ if (numberParameters >= 1) {
+ res = fts_disableInterrupt();
+ if (res < 0) {
+ pr_err("fts_disableInterrupt: ERROR %08X\n", res);
+ res = (res | ERROR_DISABLE_INTER);
+ goto END;
+ }
+
+ switch (typeOfCommand[0]) {
+ /*ITO TEST*/
+ case 0x01:
+ res = production_test_ito(LIMITS_FILE, &tests);
+ break;
+
+ /*PRODUCTION TEST*/
+ case 0x02:
+ if (systemInfo.u8_cfgAfeVer != systemInfo.u8_cxAfeVer) {
+ res = ERROR_OP_NOT_ALLOW;
+ pr_err("Miss match in CX version! MP test not allowed with wrong CX memory! ERROR %08X\n",
+ res);
+ break;
+ }
+ res = production_test_initialization(init_type);
+ break;
+
+ case 0x00:
+ if (systemInfo.u8_cfgAfeVer != systemInfo.u8_cxAfeVer) {
+ res = ERROR_OP_NOT_ALLOW;
+ pr_err("Miss match in CX version! MP test not allowed with wrong CX memory! ERROR %08X\n",
+ res);
+ break;
+ }
+
+ res = production_test_main(LIMITS_FILE, 1, init_type,
+ &tests);
+ break;
+
+ /*read mutual raw*/
+ case 0x13:
+ if (numberParameters > 1) {
+ pr_debug("Get 1 MS Frame\n");
+ setScanMode(SCAN_MODE_LOCKED, typeOfCommand[1]);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ /* Delete the events related to some touch
+ * (allow to call this function while touching
+ * the screen without having a flooding of the
+ * FIFO)
+ */
+ flushFIFO();
+ res = getMSFrame3(MS_RAW, &frameMS);
+ if (res < 0) {
+ pr_err("Error while taking the MS frame... ERROR %08X\n",
+ res);
+ } else {
+ pr_debug("The frame size is %d words\n",
+ res);
+#ifdef RAW_DATA_FORMAT_DEC
+ size += 3 * 2 +
+ (7 * frameMS.header.sense_node + 1)
+ * frameMS.header.force_node;
+#else
+ size += (res * sizeof(short) + 2) * 2;
+#endif
+ /* set res to OK because if getMSFrame
+ * is successful res = number of words
+ * read
+ */
+ res = OK;
+ print_frame_short(
+ "MS frame =",
+ array1dTo2d_short(
+ frameMS.node_data,
+ frameMS.node_data_size,
+ frameMS.header.
+ sense_node),
+ frameMS.header.force_node,
+ frameMS.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+ /*read self raw*/
+ case 0x15:
+ if (numberParameters > 1) {
+ pr_debug("Get 1 SS Frame\n");
+ setScanMode(SCAN_MODE_LOCKED, typeOfCommand[1]);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ flushFIFO();
+ /* delete the events related to some touch
+ * (allow to call this function while touching
+ * the screen without having a flooding of the
+ * FIFO) */
+ res = getSSFrame3(SS_RAW, &frameSS);
+
+ if (res < OK) {
+ pr_err("Error while taking the SS frame... ERROR %08X\n",
+ res);
+ } else {
+ pr_debug("The frame size is %d words\n",
+ res);
+#ifdef RAW_DATA_FORMAT_DEC
+ size += 3 * 2 + 5 +
+ (frameSS.header.sense_node +
+ frameSS.header.force_node) * 7;
+#else
+ size += (res * sizeof(short) + 2) * 2;
+#endif
+ /* set res to OK because if getMSFrame
+ * is successful res = number of words
+ * read
+ */
+ res = OK;
+ print_frame_short(
+ "SS force frame =",
+ array1dTo2d_short(
+ frameSS.force_data,
+ frameSS.header.
+ force_node, 1),
+ frameSS.header.force_node, 1);
+ print_frame_short(
+ "SS sense frame =",
+ array1dTo2d_short(
+ frameSS.sense_data,
+ frameSS.header.
+ sense_node,
+ frameSS.header.
+ sense_node),
+ 1, frameSS.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case 0x14: /* read mutual comp data */
+ pr_debug("Get MS Compensation Data\n");
+ res = readMutualSenseCompensationData(LOAD_CX_MS_TOUCH,
+ &compData);
+
+ if (res < 0)
+ pr_err("Error reading MS compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_debug("MS Compensation Data Reading Finished!\n");
+ size += ((compData.node_data_size + 3) *
+ sizeof(u8)) * 2;
+ print_frame_i8("MS Data (Cx2) =",
+ array1dTo2d_i8(
+ compData.node_data,
+ compData.
+ node_data_size,
+ compData.header.
+ sense_node),
+ compData.header.force_node,
+ compData.header.sense_node);
+ }
+ break;
+
+ case 0x16: /* read self comp data */
+ pr_debug("Get SS Compensation Data...\n");
+ res = readSelfSenseCompensationData(LOAD_CX_SS_TOUCH,
+ &comData);
+ if (res < 0)
+ pr_err("Error reading SS compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_debug("SS Compensation Data Reading Finished!\n");
+ size += ((comData.header.force_node +
+ comData.header.sense_node) * 2 + 6) *
+ sizeof(u8) * 2;
+ print_frame_u8("SS Data Ix2_fm = ",
+ array1dTo2d_u8(comData.ix2_fm,
+ comData.header.
+ force_node, 1),
+ comData.header.force_node, 1);
+ print_frame_i8("SS Data Cx2_fm = ",
+ array1dTo2d_i8(comData.cx2_fm,
+ comData.header.
+ force_node, 1),
+ comData.header.force_node, 1);
+ print_frame_u8("SS Data Ix2_sn = ",
+ array1dTo2d_u8(comData.ix2_sn,
+ comData.header.
+ sense_node,
+ comData.header.
+ sense_node), 1,
+ comData.header.sense_node);
+ print_frame_i8("SS Data Cx2_sn = ",
+ array1dTo2d_i8(comData.cx2_sn,
+ comData.header.
+ sense_node,
+ comData.header.
+ sense_node), 1,
+ comData.header.sense_node);
+ }
+ break;
+ case 0x17: /* Read mutual strength */
+ pr_debug("Get 1 MS Strength\n");
+ setScanMode(SCAN_MODE_ACTIVE, 0xFF);
+ msleep(WAIT_FOR_FRESH_FRAMES);
+ setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ msleep(WAIT_AFTER_SENSEOFF);
+ /* Flush outstanding touch events */
+ flushFIFO();
+ nodes = getMSFrame3(MS_STRENGTH, &frameMS);
+ if (nodes < 0) {
+ res = nodes;
+ pr_err("Error while taking the MS strength... ERROR %08X\n",
+ res);
+ } else {
+ pr_debug("The frame size is %d words\n", nodes);
+#ifdef RAW_DATA_FORMAT_DEC
+ size += 3 * 2 +
+ (7 * frameMS.header.sense_node + 1)
+ * frameMS.header.force_node;
+#else
+ size += (nodes * sizeof(short) + 2) * 2;
+#endif
+ print_frame_short("MS strength =",
+ array1dTo2d_short(frameMS.node_data,
+ frameMS.node_data_size,
+ frameMS.header.sense_node),
+ frameMS.header.force_node,
+ frameMS.header.sense_node);
+ res = OK;
+ }
+ break;
+ case 0x03: /* MS Raw DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ms_raw(LIMITS_FILE, 1,
+ &tests);
+ break;
+
+ case 0x04: /* MS CX DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ms_cx(LIMITS_FILE, 1,
+ &tests);
+ break;
+
+ case 0x05: /* SS RAW DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ss_raw(LIMITS_FILE, 1,
+ &tests);
+ break;
+
+ case 0x06: /* SS IX CX DATA TEST */
+ res = fts_system_reset();
+ if (res >= OK)
+ res = production_test_ss_ix_cx(LIMITS_FILE, 1,
+ &tests);
+ break;
+
+
+ case 0xF0:
+ case 0xF1: /* TOUCH ENABLE/DISABLE */
+ doClean = (int)(typeOfCommand[0] & 0x01);
+ res = cleanUp(doClean);
+ break;
+
+ default:
+ pr_err("CMD(%02X) NOT VALID!! Insert a proper value\n",
+ typeOfCommand[0]);
+ res = ERROR_OP_NOT_ALLOW;
+ break;
+ }
+
+ doClean = fts_mode_handler(info, 1);
+ if (typeOfCommand[0] != 0xF0)
+ doClean |= fts_enableInterrupt();
+ if (doClean < 0)
+ pr_err("%s: ERROR %08X\n", __func__,
+ (doClean | ERROR_ENABLE_INTER));
+ } else {
+ pr_err("NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+END:
+ /* here start the reporting phase, assembling the data
+ * to send in the file node */
+ size = PAGE_SIZE;
+ index = 0;
+ index += scnprintf(all_strbuff + index, size - index, "{ %08X", res);
+
+ if (res >= OK) {
+ /*all the other cases are already fine printing only the res.*/
+ switch (typeOfCommand[0]) {
+ case 0x13:
+ case 0x17:
+#ifdef RAW_DATA_FORMAT_DEC
+ index += scnprintf(all_strbuff + index, size - index,
+ "%3d",
+ (u8)frameMS.header.force_node);
+ index += scnprintf(all_strbuff + index, size - index,
+ "%3d",
+ (u8)frameMS.header.sense_node);
+#else
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (u8)frameMS.header.force_node);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (u8)frameMS.header.sense_node);
+#endif
+
+ for (j = 0; j < frameMS.node_data_size; j++) {
+#ifdef RAW_DATA_FORMAT_DEC
+ if (j % frameMS.header.sense_node == 0)
+ index += scnprintf(all_strbuff + index,
+ size - index, "\n");
+ index += scnprintf(all_strbuff + index,
+ size - index, "%7d",
+ frameMS.node_data[j]);
+#else
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X%02X",
+ (frameMS.node_data[j] & 0xFF00) >> 8,
+ frameMS.node_data[j] & 0xFF);
+#endif
+ }
+
+ kfree(frameMS.node_data);
+ break;
+
+ case 0x15:
+#ifdef RAW_DATA_FORMAT_DEC
+ index += scnprintf(all_strbuff + index, size - index,
+ "%3d",
+ (u8)frameSS.header.force_node);
+ index += scnprintf(all_strbuff + index, size - index,
+ "%3d",
+ (u8)frameSS.header.sense_node);
+ index += scnprintf(all_strbuff + index, size - index,
+ "\n");
+#else
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (u8)frameSS.header.force_node);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (u8)frameSS.header.sense_node);
+#endif
+
+ /* Copying self raw data Force */
+ for (j = 0; j < frameSS.header.force_node; j++) {
+#ifdef RAW_DATA_FORMAT_DEC
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%7d",
+ frameSS.force_data[j]);
+#else
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X%02X",
+ (frameSS.force_data[j] & 0xFF00) >> 8,
+ frameSS.force_data[j] & 0xFF);
+#endif
+ }
+
+
+
+#ifdef RAW_DATA_FORMAT_DEC
+ index += scnprintf(all_strbuff + index, size - index,
+ "\n");
+#endif
+
+ /* Copying self raw data Sense */
+ for (j = 0; j < frameSS.header.sense_node; j++) {
+#ifdef RAW_DATA_FORMAT_DEC
+ index += scnprintf(all_strbuff + index,
+ size - index, "%7d",
+ frameSS.sense_data[j]);
+#else
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X%02X",
+ (frameSS.sense_data[j] & 0xFF00) >> 8,
+ frameSS.sense_data[j] & 0xFF);
+#endif
+ }
+
+ kfree(frameSS.force_data);
+ kfree(frameSS.sense_data);
+ break;
+
+ case 0x14:
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (u8)compData.header.force_node);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (u8)compData.header.sense_node);
+
+ /* Cpying CX1 value */
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (compData.cx1) & 0xFF);
+
+ /* Copying CX2 values */
+ for (j = 0; j < compData.node_data_size; j++) {
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X",
+ (compData.node_data[j]) & 0xFF);
+ }
+
+ kfree(compData.node_data);
+ break;
+
+ case 0x16:
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ comData.header.force_node);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ comData.header.sense_node);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (comData.f_ix1) & 0xFF);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (comData.s_ix1) & 0xFF);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (comData.f_cx1) & 0xFF);
+
+ index += scnprintf(all_strbuff + index,
+ size - index, "%02X",
+ (comData.s_cx1) & 0xFF);
+
+ /* Copying IX2 Force */
+ for (j = 0; j < comData.header.force_node; j++) {
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X",
+ comData.ix2_fm[j] & 0xFF);
+ }
+
+ /* Copying IX2 Sense */
+ for (j = 0; j < comData.header.sense_node; j++) {
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X",
+ comData.ix2_sn[j] & 0xFF);
+ }
+
+ /* Copying CX2 Force */
+ for (j = 0; j < comData.header.force_node; j++) {
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X",
+ comData.cx2_fm[j] & 0xFF);
+ }
+
+ /* Copying CX2 Sense */
+ for (j = 0; j < comData.header.sense_node; j++) {
+ index += scnprintf(all_strbuff + index,
+ size - index,
+ "%02X",
+ comData.cx2_sn[j] & 0xFF);
+ }
+
+ kfree(comData.ix2_fm);
+ kfree(comData.ix2_sn);
+ kfree(comData.cx2_fm);
+ kfree(comData.cx2_sn);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ index += scnprintf(all_strbuff + index, size - index, " }\n");
+ numberParameters = 0;
+ /* need to reset the number of parameters in order to wait the
+ * next command, comment if you want to repeat the last command sent
+ * just doing a cat */
+ /* pr_err("numberParameters = %d\n", numberParameters); */
+
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+ mutex_unlock(&info->diag_cmd_lock);
+
+ return index;
+}
+
+static DEVICE_ATTR(fwupdate, 0664, fts_fwupdate_show,
+ fts_fwupdate_store);
+static DEVICE_ATTR(appid, 0444, fts_appid_show, NULL);
+static DEVICE_ATTR(mode_active, 0444, fts_mode_active_show, NULL);
+static DEVICE_ATTR(fw_file_test, 0444, fts_fw_test_show, NULL);
+static DEVICE_ATTR(status, 0444, fts_status_show, NULL);
+static DEVICE_ATTR(stm_fts_cmd, 0664, stm_fts_cmd_show,
+ stm_fts_cmd_store);
+#ifdef USE_ONE_FILE_NODE
+static DEVICE_ATTR(feature_enable, 0664,
+ fts_feature_enable_show, fts_feature_enable_store);
+#else
+
+
+#ifdef GRIP_MODE
+static DEVICE_ATTR(grip_mode, 0664, fts_grip_mode_show,
+ fts_grip_mode_store);
+#endif
+
+#ifdef CHARGER_MODE
+static DEVICE_ATTR(charger_mode, 0664,
+ fts_charger_mode_show, fts_charger_mode_store);
+#endif
+
+#ifdef GLOVE_MODE
+static DEVICE_ATTR(glove_mode, 0664,
+ fts_glove_mode_show, fts_glove_mode_store);
+#endif
+
+#ifdef COVER_MODE
+static DEVICE_ATTR(cover_mode, 0664,
+ fts_cover_mode_show, fts_cover_mode_store);
+#endif
+
+#ifdef STYLUS_MODE
+static DEVICE_ATTR(stylus_mode, 0664,
+ fts_stylus_mode_show, fts_stylus_mode_store);
+#endif
+
+#endif
+
+#ifdef GESTURE_MODE
+static DEVICE_ATTR(gesture_mask, 0664,
+ fts_gesture_mask_show, fts_gesture_mask_store);
+static DEVICE_ATTR(gesture_coordinates, 0664,
+ fts_gesture_coordinates_show, NULL);
+#endif
+
+static DEVICE_ATTR(touchsim, 0664,
+ fts_touch_simulation_show,
+ fts_touch_simulation_store);
+
+/* /sys/devices/soc.0/f9928000.i2c/i2c-6/6-0049 */
+static struct attribute *fts_attr_group[] = {
+ &dev_attr_fwupdate.attr,
+ &dev_attr_appid.attr,
+ &dev_attr_mode_active.attr,
+ &dev_attr_fw_file_test.attr,
+ &dev_attr_status.attr,
+ &dev_attr_stm_fts_cmd.attr,
+#ifdef USE_ONE_FILE_NODE
+ &dev_attr_feature_enable.attr,
+#else
+
+#ifdef GRIP_MODE
+ &dev_attr_grip_mode.attr,
+#endif
+#ifdef CHARGER_MODE
+ &dev_attr_charger_mode.attr,
+#endif
+#ifdef GLOVE_MODE
+ &dev_attr_glove_mode.attr,
+#endif
+#ifdef COVER_MODE
+ &dev_attr_cover_mode.attr,
+#endif
+#ifdef STYLUS_MODE
+ &dev_attr_stylus_mode.attr,
+#endif
+
+#endif
+
+#ifdef GESTURE_MODE
+ &dev_attr_gesture_mask.attr,
+ &dev_attr_gesture_coordinates.attr,
+#endif
+ &dev_attr_touchsim.attr,
+ NULL,
+};
+
+/** @}*/
+/** @}*/
+
+
+/**
+ * @defgroup isr Interrupt Service Routine (Event Handler)
+ * The most important part of the driver is the ISR (Interrupt Service Routine)
+ * called also as Event Handler \n
+ * As soon as the interrupt pin goes low, fts_interrupt_handler() is called and
+ * the chain to read and parse the event read from the FIFO start.\n
+ * For any different kind of EVT_ID there is a specific event handler
+ * which will take the correct action to report the proper info to the host. \n
+ * The most important events are the one related to touch information, status
+ * update or user report.
+ * @{
+ */
+
+/**
+ * Report to the linux input system the pressure and release of a button
+ * handling concurrency
+ * @param info pointer to fts_ts_info which contains info about the device
+ * and its hw setup
+ * @param key_code button value
+ */
+void fts_input_report_key(struct fts_ts_info *info, int key_code)
+{
+ mutex_lock(&info->input_report_mutex);
+ input_report_key(info->input_dev, key_code, 1);
+ input_sync(info->input_dev);
+ input_report_key(info->input_dev, key_code, 0);
+ input_sync(info->input_dev);
+ mutex_unlock(&info->input_report_mutex);
+}
+
+
+
+/**
+ * Event Handler for no events (EVT_ID_NOEVENT)
+ */
+static bool fts_nop_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ pr_debug("%s: Doing nothing for event = %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[0], event[1], event[2], event[3],
+ event[4],
+ event[5], event[6], event[7]);
+ return false;
+}
+
+/**
+ * Event handler for enter and motion events (EVT_ID_ENTER_POINT,
+ * EVT_ID_MOTION_POINT )
+ * report touch coordinates and additional information
+ * to the linux input system
+ */
+static bool fts_enter_pointer_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ unsigned char touchId;
+ unsigned int touch_condition = 1, tool = MT_TOOL_FINGER;
+ int x, y, z, major, minor, distance;
+ u8 touchType;
+ if (!info->resume_bit)
+ goto no_report;
+
+ touchType = event[1] & 0x0F;
+ touchId = (event[1] & 0xF0) >> 4;
+
+ x = (((int)event[3] & 0x0F) << 8) | (event[2]);
+ y = ((int)event[4] << 4) | ((event[3] & 0xF0) >> 4);
+ z = (int)event[5];
+ if (z <= 0) {
+ /* Should not happen, because zero pressure implies contact has
+ * left, so this function should not be invoked. For safety, to
+ * prevent this touch from being dropped, set to smallest
+ * pressure value instead
+ */
+ pr_err("%s: Pressure is %i, but pointer is not leaving\n",
+ __func__, z);
+ z = 1; /* smallest non-zero pressure value */
+ }
+ major = (int)(((event[0] & 0x0C) << 2) | ((event[6] & 0xF0) >> 4));
+ minor = (int)(((event[7] & 0xC0) >> 2) | (event[6] & 0x0F));
+ /* TODO: check with fw how they will report distance */
+ distance = 0; /* if the tool is touching the display
+ * the distance should be 0 */
+
+ if (x == info->board->x_axis_max)
+ x--;
+
+ if (y == info->board->y_axis_max)
+ y--;
+
+ input_mt_slot(info->input_dev, touchId);
+ switch (touchType) {
+#ifdef STYLUS_MODE
+ case TOUCH_TYPE_STYLUS:
+ pr_debug("%s : It is a stylus!\n", __func__);
+ if (info->stylus_enabled == 1) {
+ /* if stylus_enabled is not ==1
+ * it will be reported as normal touch */
+ tool = MT_TOOL_PEN;
+ touch_condition = 1;
+ __set_bit(touchId, &info->stylus_id);
+ break;
+ }
+#endif
+ /* TODO: customer can implement a different strategy for each kind of
+ * touch */
+ case TOUCH_TYPE_FINGER:
+ case TOUCH_TYPE_GLOVE:
+ case TOUCH_TYPE_PALM:
+ pr_debug("%s : It is a touch type %d!\n", __func__, touchType);
+ tool = MT_TOOL_FINGER;
+ touch_condition = 1;
+ __set_bit(touchId, &info->touch_id);
+ break;
+
+
+ case TOUCH_TYPE_HOVER:
+ tool = MT_TOOL_FINGER;
+ touch_condition = 0; /* need to hover */
+ z = 0; /* no pressure */
+ __set_bit(touchId, &info->touch_id);
+ distance = DISTANCE_MAX;/* check with fw report the hovering
+ * distance */
+ break;
+
+ case TOUCH_TYPE_INVALID:
+ default:
+ pr_err("%s : Invalid touch type = %d ! No Report...\n",
+ __func__, touchType);
+ goto no_report;
+ }
+
+ input_report_key(info->input_dev, BTN_TOUCH, touch_condition);
+ input_mt_report_slot_state(info->input_dev, tool, 1);
+
+ input_report_abs(info->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(info->input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(info->input_dev, ABS_MT_TOUCH_MAJOR, major);
+ input_report_abs(info->input_dev, ABS_MT_TOUCH_MINOR, minor);
+ input_report_abs(info->input_dev, ABS_MT_PRESSURE, z);
+
+#ifndef SKIP_DISTANCE
+ input_report_abs(info->input_dev, ABS_MT_DISTANCE, distance);
+#endif
+ /* pr_debug("%s : Event 0x%02x - ID[%d], (x, y) = (%3d, %3d)
+ * Size = %d\n",
+ * __func__, *event, touchId, x, y, touchType); */
+
+ return true;
+no_report:
+ return false;
+}
+
+/**
+ * Event handler for leave event (EVT_ID_LEAVE_POINT )
+ * Report to the linux input system that one touch left the display
+ */
+static bool fts_leave_pointer_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ unsigned char touchId;
+ unsigned int tool = MT_TOOL_FINGER;
+ u8 touchType;
+
+ touchType = event[1] & 0x0F;
+ touchId = (event[1] & 0xF0) >> 4;
+
+ input_mt_slot(info->input_dev, touchId);
+
+ input_report_abs(info->input_dev, ABS_MT_PRESSURE, 0);
+ switch (touchType) {
+#ifdef STYLUS_MODE
+ case TOUCH_TYPE_STYLUS:
+ pr_debug("%s : It is a stylus!\n", __func__);
+ if (info->stylus_enabled == 1) {
+ /* if stylus_enabled is not ==1 it will be reported as
+ * normal touch */
+ tool = MT_TOOL_PEN;
+ __clear_bit(touchId, &info->stylus_id);
+ break;
+ }
+#endif
+
+ case TOUCH_TYPE_FINGER:
+ /* pr_debug("%s : It is a finger!\n", __func__); */
+ case TOUCH_TYPE_GLOVE:
+ /* pr_debug("%s : It is a glove!\n", __func__); */
+ case TOUCH_TYPE_PALM:
+ /* pr_debug("%s : It is a palm!\n", __func__); */
+ case TOUCH_TYPE_HOVER:
+ tool = MT_TOOL_FINGER;
+ __clear_bit(touchId, &info->touch_id);
+ break;
+
+ case TOUCH_TYPE_INVALID:
+ default:
+ pr_err("%s : Invalid touch type = %d ! No Report...\n",
+ __func__, touchType);
+ return false;
+ }
+
+ input_mt_report_slot_state(info->input_dev, tool, 0);
+
+ /* pr_debug("%s : TouchID = %d, Touchcount = %d\n", __func__,
+ * touchId,touchcount); */
+
+
+ input_report_abs(info->input_dev, ABS_MT_TRACKING_ID, -1);
+ /* pr_debug("%s : Event 0x%02x - release ID[%d]\n", __func__,
+ * event[0], touchId); */
+ return true;
+}
+
+/* EventId : EVT_ID_MOTION_POINT */
+#define fts_motion_pointer_event_handler fts_enter_pointer_event_handler
+/* remap the motion event handler to the same function which handle the enter
+ * event */
+
+/**
+ * Event handler for error events (EVT_ID_ERROR)
+ * Handle unexpected error events implementing recovery strategy and
+ * restoring the sensing status that the IC had before the error occurred
+ */
+static bool fts_error_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ int error = 0;
+
+ pr_debug("%s: Received event %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[0], event[1], event[2], event[3], event[4],
+ event[5],
+ event[6], event[7]);
+
+ switch (event[1]) {
+ case EVT_TYPE_ERROR_ESD:/* esd */
+ {/* before reset clear all slot */
+ release_all_touches(info);
+
+ fts_chip_powercycle(info);
+
+ error = fts_system_reset();
+ error |= fts_mode_handler(info, 0);
+ error |= fts_enableInterrupt();
+ if (error < OK)
+ pr_err("%s Cannot restore the device ERROR %08X\n",
+ __func__, error);
+ }
+ break;
+ case EVT_TYPE_ERROR_WATCHDOG: /* watch dog timer */
+ {
+ dumpErrorInfo(NULL, 0);
+ /* before reset clear all slots */
+ release_all_touches(info);
+ error = fts_system_reset();
+ error |= fts_mode_handler(info, 0);
+ error |= fts_enableInterrupt();
+ if (error < OK)
+ pr_err("%s Cannot reset the device ERROR %08X\n",
+ __func__, error);
+ }
+ break;
+ }
+ return false;
+}
+
+/**
+ * Event handler for controller ready event (EVT_ID_CONTROLLER_READY)
+ * Handle controller events received after unexpected reset of the IC updating
+ * the resets flag and restoring the proper sensing status
+ */
+static bool fts_controller_ready_event_handler(struct fts_ts_info *info,
+ unsigned char *event)
+{
+ int error;
+
+ pr_debug("%s: Received event %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[0], event[1], event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ release_all_touches(info);
+ setSystemResetedUp(1);
+ setSystemResetedDown(1);
+ error = fts_mode_handler(info, 0);
+ if (error < OK)
+ pr_err("%s Cannot restore the device status ERROR %08X\n",
+ __func__, error);
+ return false;
+}
+
+/**
+ * Event handler for status events (EVT_ID_STATUS_UPDATE)
+ * Handle status update events
+ */
+static bool fts_status_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ switch (event[1]) {
+ case EVT_TYPE_STATUS_ECHO:
+ pr_debug("%s: Echo event of command = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4], event[5],
+ event[6], event[7]);
+ break;
+
+ case EVT_TYPE_STATUS_FORCE_CAL:
+ switch (event[2]) {
+ case 0x00:
+ pr_debug("%s: Continuous frame drop Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x01:
+ pr_debug("%s: Mutual negative detect Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x02:
+ pr_debug("%s: Mutual calib deviation Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x11:
+ pr_debug("%s: SS negative detect Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x12:
+ pr_debug("%s: SS negative detect Force cal in Low Power mode = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x13:
+ pr_debug("%s: SS negative detect Force cal in Idle mode = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x20:
+ pr_debug("%s: SS invalid Mutual Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x21:
+ pr_debug("%s: SS invalid Self Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x22:
+ pr_debug("%s: SS invalid Self Island soft Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x30:
+ pr_debug("%s: MS invalid Mutual Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x31:
+ pr_debug("%s: MS invalid Self Strength soft Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ default:
+ pr_debug("%s: Force cal = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ }
+ break;
+
+ case EVT_TYPE_STATUS_FRAME_DROP:
+ switch (event[2]) {
+ case 0x01:
+ pr_debug("%s: Frame drop noisy frame = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x02:
+ pr_debug("%s: Frame drop bad R = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case 0x03:
+ pr_debug("%s: Frame drop invalid processing state = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ default:
+ pr_debug("%s: Frame drop = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ }
+ break;
+
+ case EVT_TYPE_STATUS_SS_RAW_SAT:
+ if (event[2] == 1)
+ pr_debug("%s: SS Raw Saturated = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ else
+ pr_debug("%s: SS Raw No more Saturated = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ case EVT_TYPE_STATUS_WATER:
+ if (event[2] == 1)
+ pr_debug("%s: Enter Water mode = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ else
+ pr_debug("%s: Exit Water mode = %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+ break;
+
+ default:
+ pr_err("%s: Received unhandled status event = %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[0], event[1], event[2], event[3],
+ event[4], event[5], event[6], event[7]);
+ break;
+ }
+ return false;
+}
+
+
+/* key events reported in the user report */
+#ifdef PHONE_KEY
+/* TODO: the customer should handle the events coming from the keys according
+ * his needs
+ * (this is just an sample code that report the click of a button after a
+ * press->release action) */
+/**
+ * Event handler for status events (EVT_TYPE_USER_KEY)
+ * Handle keys update events, the third byte of the event is a bitmask,
+ * if the bit set means that the corresponding key is pressed.
+ */
+static void fts_key_event_handler(struct fts_ts_info *info,
+ unsigned char *event)
+{
+ /* int value; */
+ pr_debug("%s: Received event %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[0], event[1], event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+
+ if (event[0] == EVT_ID_USER_REPORT && event[1] == EVT_TYPE_USER_KEY) {
+ /* event[2] contain the bitmask of the keys that are actually
+ * pressed */
+
+ if ((event[2] & FTS_KEY_0) == 0 && (key_mask & FTS_KEY_0) > 0) {
+ pr_debug("%s: Button HOME pressed and released!\n",
+ __func__);
+ fts_input_report_key(info, KEY_HOMEPAGE);
+ }
+
+ if ((event[2] & FTS_KEY_1) == 0 && (key_mask & FTS_KEY_1) > 0) {
+ pr_debug("%s: Button Back pressed and released!\n",
+ __func__);
+ fts_input_report_key(info, KEY_BACK);
+ }
+
+ if ((event[2] & FTS_KEY_2) == 0 && (key_mask & FTS_KEY_2) > 0) {
+ pr_debug("%s: Button Menu pressed!\n", __func__);
+ fts_input_report_key(info, KEY_MENU);
+ }
+
+ key_mask = event[2];
+ } else
+ pr_err("%s: Invalid event passed as argument!\n", __func__);
+}
+#endif
+
+/* gesture event must be handled in the user event handler */
+#ifdef GESTURE_MODE
+/* TODO: Customer should implement their own actions in respond of a gesture
+ * event.
+ * This is an example that simply print the gesture received and simulate
+ * the click on a different button for each gesture. */
+/**
+ * Event handler for gesture events (EVT_TYPE_USER_GESTURE)
+ * Handle gesture events and simulate the click on a different button
+ * for any gesture detected (@link gesture_opt Gesture IDs @endlink)
+ */
+static void fts_gesture_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ int value;
+ int needCoords = 0;
+
+ pr_debug("gesture event data: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ event[0], event[1], event[2], event[3], event[4],
+ event[5], event[6], event[7]);
+
+ if (event[0] == EVT_ID_USER_REPORT && event[1] ==
+ EVT_TYPE_USER_GESTURE) {
+ needCoords = 1;
+ /* default read the coordinates for all gestures excluding
+ * double tap */
+
+ switch (event[2]) {
+ case GEST_ID_DBLTAP:
+ value = KEY_WAKEUP;
+ pr_debug("%s: double tap !\n", __func__);
+ needCoords = 0;
+ break;
+
+ case GEST_ID_AT:
+ value = KEY_WWW;
+ pr_debug("%s: @ !\n", __func__);
+ break;
+
+ case GEST_ID_C:
+ value = KEY_C;
+ pr_debug("%s: C !\n", __func__);
+ break;
+
+ case GEST_ID_E:
+ value = KEY_E;
+ pr_debug("%s: e !\n", __func__);
+ break;
+
+ case GEST_ID_F:
+ value = KEY_F;
+ pr_debug("%s: F !\n", __func__);
+ break;
+
+ case GEST_ID_L:
+ value = KEY_L;
+ pr_debug("%s: L !\n", __func__);
+ break;
+
+ case GEST_ID_M:
+ value = KEY_M;
+ pr_debug("%s: M !\n", __func__);
+ break;
+
+ case GEST_ID_O:
+ value = KEY_O;
+ pr_debug("%s: O !\n", __func__);
+ break;
+
+ case GEST_ID_S:
+ value = KEY_S;
+ pr_debug("%s: S !\n", __func__);
+ break;
+
+ case GEST_ID_V:
+ value = KEY_V;
+ pr_debug("%s: V !\n", __func__);
+ break;
+
+ case GEST_ID_W:
+ value = KEY_W;
+ pr_debug("%s: W !\n", __func__);
+ break;
+
+ case GEST_ID_Z:
+ value = KEY_Z;
+ pr_debug("%s: Z !\n", __func__);
+ break;
+
+ case GEST_ID_RIGHT_1F:
+ value = KEY_RIGHT;
+ pr_debug("%s: -> !\n", __func__);
+ break;
+
+ case GEST_ID_LEFT_1F:
+ value = KEY_LEFT;
+ pr_debug("%s: <- !\n", __func__);
+ break;
+
+ case GEST_ID_UP_1F:
+ value = KEY_UP;
+ pr_debug("%s: UP !\n", __func__);
+ break;
+
+ case GEST_ID_DOWN_1F:
+ value = KEY_DOWN;
+ pr_debug("%s: DOWN !\n", __func__);
+ break;
+
+ case GEST_ID_CARET:
+ value = KEY_APOSTROPHE;
+ pr_debug("%s: ^ !\n", __func__);
+ break;
+
+ case GEST_ID_LEFTBRACE:
+ value = KEY_LEFTBRACE;
+ pr_debug("%s: < !\n", __func__);
+ break;
+
+ case GEST_ID_RIGHTBRACE:
+ value = KEY_RIGHTBRACE;
+ pr_debug("%s: > !\n", __func__);
+ break;
+
+ default:
+ pr_err("%s: No valid GestureID!\n", __func__);
+ goto gesture_done;
+ }
+
+ if (needCoords == 1)
+ readGestureCoords(event);
+
+ fts_input_report_key(info, value);
+
+gesture_done:
+ return;
+ } else
+ pr_err("%s: Invalid event passed as argument!\n", __func__);
+}
+#endif
+
+
+/**
+ * Event handler for user report events (EVT_ID_USER_REPORT)
+ * Handle user events reported by the FW due to some interaction triggered
+ * by an external user (press keys, perform gestures, etc.)
+ */
+static bool fts_user_report_event_handler(struct fts_ts_info *info, unsigned
+ char *event)
+{
+ switch (event[1]) {
+#ifdef PHONE_KEY
+ case EVT_TYPE_USER_KEY:
+ fts_key_event_handler(info, event);
+ break;
+#endif
+
+ case EVT_TYPE_USER_PROXIMITY:
+ if (event[2] == 0)
+ pr_err("%s No proximity!\n", __func__);
+ else
+ pr_err("%s Proximity Detected!\n", __func__);
+ break;
+
+#ifdef GESTURE_MODE
+ case EVT_TYPE_USER_GESTURE:
+ fts_gesture_event_handler(info, event);
+ break;
+#endif
+ default:
+ pr_err("%s: Received unhandled user report event = %02X %02X %02X %02X %02X %02X %02X %02X\n",
+ __func__, event[0], event[1], event[2], event[3],
+ event[4], event[5], event[6], event[7]);
+ break;
+ }
+ return false;
+}
+
+#if 0 // no heatmap support
+
+static void heatmap_enable(void)
+{
+ unsigned char command[] = {0xA4, 0x06, LOCAL_HEATMAP_MODE};
+ fts_write(command, 3);
+}
+
+static bool read_heatmap_raw(struct v4l2_heatmap *v4l2, strength_t *data)
+{
+ unsigned char heatmap_read_command[] = {0xA6, 0x00, 0x00};
+
+ unsigned int num_elements;
+ /* index for looping through the heatmap buffer read over the bus */
+ unsigned int local_i;
+
+ int result;
+
+ /* old value of the counter, for comparison */
+ static uint16_t counter;
+
+ strength_t heatmap_value;
+ /* final position of the heatmap value in the full heatmap frame */
+ unsigned int frame_i;
+
+ int heatmap_x, heatmap_y;
+ int max_x = v4l2->format.width;
+ int max_y = v4l2->format.height;
+
+ struct heatmap_report report = {0};
+
+ result = fts_writeRead(heatmap_read_command, 3,
+ (uint8_t *) &report, sizeof(report));
+ if (result != OK) {
+ pr_err("%s: i2c read failed, fts_writeRead returned %i",
+ __func__, result);
+ return false;
+ }
+ if (report.mode != LOCAL_HEATMAP_MODE) {
+ pr_err("Touch IC not in local heatmap mode: %X %X %i",
+ report.prefix, report.mode, report.counter);
+ return false;
+ }
+
+ le16_to_cpus(&report.counter); /* enforce little-endian order */
+ if (report.counter == counter && counter != 0) {
+ /*
+ * We shouldn't make ordered comparisons because of
+ * potential overflow, but at least the value
+ * should have changed. If the value remains the same,
+ * but we are processing a new interrupt,
+ * this could indicate slowness in the interrupt handler.
+ */
+ pr_warn("Heatmap frame has stale counter value %i",
+ counter);
+ }
+ counter = report.counter;
+ num_elements = report.size_x * report.size_y;
+ if (num_elements > LOCAL_HEATMAP_WIDTH * LOCAL_HEATMAP_HEIGHT) {
+ pr_err("Unexpected heatmap size: %i x %i",
+ report.size_x, report.size_y);
+ return false;
+ }
+
+ /* set all to zero, will only write to non-zero locations in the loop */
+ memset(data, 0, max_x * max_y * sizeof(data[0]));
+ /* populate the data buffer, rearranging into final locations */
+ for (local_i = 0; local_i < num_elements; local_i++) {
+ /* enforce little-endian order */
+ le16_to_cpus(&report.data[local_i]);
+ heatmap_value = report.data[local_i];
+
+ if (heatmap_value == 0) {
+ /* Already set to zero. Nothing to do */
+ continue;
+ }
+
+ heatmap_x = report.offset_x + (local_i % report.size_x);
+ heatmap_y = report.offset_y + (local_i / report.size_x);
+
+ if (heatmap_x < 0 || heatmap_x >= max_x ||
+ heatmap_y < 0 || heatmap_y >= max_y) {
+ pr_err("Invalid x or y: (%i, %i), value=%i, ending loop\n",
+ heatmap_x, heatmap_y, heatmap_value);
+ return false;
+ }
+ frame_i = heatmap_y * max_x + heatmap_x;
+ data[frame_i] = heatmap_value;
+ }
+ return true;
+}
+#endif // no heat map
+
+/**
+ * Bottom Half Interrupt Handler function
+ * This handler is called each time there is at least one new event in the FIFO
+ * and the interrupt pin of the IC goes low. It will read all the events from
+ * the FIFO and dispatch them to the proper event handler according the event
+ * ID
+ */
+static irqreturn_t fts_interrupt_handler(int irq, void *handle)
+{
+ struct fts_ts_info *info = handle;
+ int error = 0, count = 0;
+ unsigned char regAdd = FIFO_CMD_READALL;
+ unsigned char data[FIFO_EVENT_SIZE * FIFO_DEPTH];
+ unsigned char eventId;
+ const unsigned char EVENTS_REMAINING_POS = 7;
+ const unsigned char EVENTS_REMAINING_MASK = 0x1F;
+ unsigned char events_remaining = 0;
+ unsigned char *evt_data;
+
+ /* It is possible that interrupts were disabled while the handler is
+ * executing, before acquiring the mutex. If so, simply return.
+ */
+ if (fts_set_bus_ref(info, FTS_BUS_REF_IRQ, true) < 0) {
+ fts_set_bus_ref(info, FTS_BUS_REF_IRQ, false);
+ return IRQ_HANDLED;
+ }
+
+ /* prevent CPU from entering deep sleep */
+ cpu_latency_qos_update_request(&info->pm_qos_req, 100);
+
+ __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ));
+
+ /* Read the first FIFO event and the number of events remaining */
+ error = fts_writeReadU8UX(regAdd, 0, 0, data, FIFO_EVENT_SIZE,
+ DUMMY_FIFO);
+ events_remaining = data[EVENTS_REMAINING_POS] & EVENTS_REMAINING_MASK;
+ events_remaining = (events_remaining > FIFO_DEPTH - 1) ?
+ FIFO_DEPTH - 1 : events_remaining;
+
+ /* Drain the rest of the FIFO, up to 31 events */
+ if (error == OK && events_remaining > 0) {
+ error = fts_writeReadU8UX(regAdd, 0, 0, &data[FIFO_EVENT_SIZE],
+ FIFO_EVENT_SIZE * events_remaining,
+ DUMMY_FIFO);
+ }
+ if (error != OK) {
+ pr_err("Error (%08X) while reading from FIFO in fts_event_handler\n",
+ error);
+ } else {
+ for (count = 0; count < events_remaining + 1; count++) {
+ evt_data = &data[count * FIFO_EVENT_SIZE];
+
+ if (evt_data[0] == EVT_ID_NOEVENT)
+ break;
+
+ eventId = evt_data[0] >> 4;
+
+ /* Ensure event ID is within bounds */
+ if (eventId < NUM_EVT_ID)
+ info->event_dispatch_table[eventId](info,
+ evt_data);
+ }
+ }
+
+ if (info->touch_id == 0)
+ input_report_key(info->input_dev, BTN_TOUCH, 0);
+
+ input_sync(info->input_dev);
+
+ cpu_latency_qos_update_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE);
+ fts_set_bus_ref(info, FTS_BUS_REF_IRQ, false);
+ return IRQ_HANDLED;
+}
+/** @}*/
+
+
+
+/**
+ * Implement the fw update and initialization flow of the IC that should
+ * be executed at every boot up. The function perform a fw update of the
+ * IC in case of crc error or a new fw version and then understand if the
+ * IC need to be re-initialized again.
+ *
+ * @return OK if success or an error code which specify the type of error
+ * encountered
+ */
+static int fts_fw_update(struct fts_ts_info *info)
+{
+ u8 error_to_search[4] = { EVT_TYPE_ERROR_CRC_CX_HEAD,
+ EVT_TYPE_ERROR_CRC_CX,
+ EVT_TYPE_ERROR_CRC_CX_SUB_HEAD,
+ EVT_TYPE_ERROR_CRC_CX_SUB };
+ int ret = 0;
+ int init_type = NO_INIT;
+
+#ifdef PRE_SAVED_METHOD
+ int keep_cx = 1;
+#else
+ int keep_cx = 0;
+#endif
+
+
+ pr_debug("Fw Auto Update is starting...\n");
+
+ /* Check CRC status */
+ ret = fts_crc_check();
+ if (ret > OK) {
+ pr_err("%s: CRC Error or NO FW!\n", __func__);
+ info->reflash_fw = 1;
+ } else {
+ pr_debug("%s: NO CRC Error or Impossible to read CRC register!\n",
+ __func__);
+ }
+ ret = flashProcedure(info->board->fw_name, info->reflash_fw, keep_cx);
+ if ((ret & 0xF000000F) == ERROR_FILE_NOT_FOUND) {
+ pr_err("%s: firmware file not found. Bypassing update.\n",
+ __func__);
+ ret = 0;
+ goto out;
+ } else if ((ret & 0xFF000000) == ERROR_FLASH_PROCEDURE) {
+ pr_err("%s: firmware update failed; retrying. ERROR %08X\n",
+ __func__, ret);
+ /* Power cycle the touch IC */
+ fts_chip_powercycle(info);
+ ret = flashProcedure(info->board->fw_name, info->reflash_fw,
+ keep_cx);
+ if ((ret & 0xFF000000) == ERROR_FLASH_PROCEDURE) {
+ pr_err("%s: firmware update failed again! ERROR %08X\n",
+ __func__, ret);
+ pr_err("Fw Auto Update Failed!\n");
+ return ret;
+ }
+ }
+ info->reflash_fw = 0;
+
+ pr_debug("%s: Verifying if CX CRC Error...\n", __func__);
+ ret = fts_system_reset();
+ if (ret >= OK) {
+ ret = pollForErrorType(error_to_search, 4);
+ if (ret < OK) {
+ pr_debug("%s: No Cx CRC Error Found!\n", __func__);
+ pr_debug("%s: Verifying if Panel CRC Error...\n",
+ __func__);
+ error_to_search[0] = EVT_TYPE_ERROR_CRC_PANEL_HEAD;
+ error_to_search[1] = EVT_TYPE_ERROR_CRC_PANEL;
+ ret = pollForErrorType(error_to_search, 2);
+ if (ret < OK) {
+ pr_debug("%s: No Panel CRC Error Found!\n",
+ __func__);
+ init_type = NO_INIT;
+ } else {
+ pr_err("%s: Panel CRC Error FOUND! CRC ERROR = %02X\n",
+ __func__, ret);
+ init_type = SPECIAL_PANEL_INIT;
+ }
+ } else {
+ pr_err("%s: Cx CRC Error FOUND! CRC ERROR = %02X\n",
+ __func__, ret);
+
+ /** This path of the code is used only in case there is
+ * a CRC error in code or config which not allow the fw
+ * to compute the CRC in the CX before
+ */
+ pr_debug("%s: Try to recovery with CX in fw file...\n",
+ __func__);
+ ret = flashProcedure(info->board->fw_name, CRC_CX, 0);
+ pr_debug("%s: Refresh panel init data", __func__);
+ }
+ } else {
+ /* Skip initialization because the real state is unknown */
+ pr_err("%s: Error while executing system reset! ERROR %08X\n",
+ __func__, ret);
+ }
+
+ if (init_type == NO_INIT) {
+#ifdef PRE_SAVED_METHOD
+ if (systemInfo.u8_cfgAfeVer != systemInfo.u8_cxAfeVer) {
+ init_type = SPECIAL_FULL_PANEL_INIT;
+ pr_err("%s: Different CX AFE Ver: %02X != %02X... Execute FULL Panel Init!\n",
+ __func__, systemInfo.u8_cfgAfeVer,
+ systemInfo.u8_cxAfeVer);
+ } else
+#endif
+ if (systemInfo.u8_cfgAfeVer != systemInfo.u8_panelCfgAfeVer) {
+ init_type = SPECIAL_PANEL_INIT;
+ pr_err("%s: Different Panel AFE Ver: %02X != %02X... Execute Panel Init!\n",
+ __func__, systemInfo.u8_cfgAfeVer,
+ systemInfo.u8_panelCfgAfeVer);
+ } else
+ init_type = NO_INIT;
+ }
+
+out:
+ /** Reinitialize after a complete FW update or if the initialization
+ * status is not correct.
+ */
+ if (init_type != NO_INIT) {
+ ret = fts_chip_initialization(info, init_type);
+ if (ret < OK) {
+ pr_err("%s: Cannot initialize the chip ERROR %08X\n",
+ __func__, ret);
+ }
+
+ /* Reset after initialization */
+ ret = fts_system_reset();
+ if (ret < OK) {
+ pr_err("%s: Reset failed, ERROR %08X\n", __func__,
+ ret);
+ }
+ }
+
+ ret = fts_init_sensing(info);
+ if (ret < OK) {
+ pr_err("Cannot initialize the hardware device ERROR %08X\n",
+ ret);
+ }
+
+ pr_err("Fw Update Finished! error = %08X\n", ret);
+ return ret;
+}
+
+#ifndef FW_UPDATE_ON_PROBE
+/**
+ * Function called by the delayed workthread executed after the probe in
+ * order to perform the fw update flow
+ * @see fts_fw_update()
+ */
+static void fts_fw_update_auto(struct work_struct *work)
+{
+ struct delayed_work *fwu_work = container_of(work, struct delayed_work,
+ work);
+ struct fts_ts_info *info = container_of(fwu_work, struct fts_ts_info,
+ fwu_work);
+
+ fts_set_bus_ref(info, FTS_BUS_REF_FW_UPDATE, true);
+ fts_fw_update(info);
+ fts_set_bus_ref(info, FTS_BUS_REF_FW_UPDATE, false);
+}
+#endif
+
+/* TODO: define if need to do the full mp at the boot */
+/**
+ * Execute the initialization of the IC (supporting a retry mechanism),
+ * checking also the resulting data
+ * @see production_test_main()
+ */
+static int fts_chip_initialization(struct fts_ts_info *info, int init_type)
+{
+ int ret2 = 0;
+ int retry;
+ int initretrycnt = 0;
+
+ /* initialization error, retry initialization */
+ for (retry = 0; retry <= RETRY_INIT_BOOT; retry++) {
+ ret2 = production_test_initialization(init_type);
+ if (ret2 == OK)
+ break;
+ initretrycnt++;
+ pr_err("initialization cycle count = %04d - ERROR %08X\n",
+ initretrycnt, ret2);
+ fts_chip_powercycle(info);
+ }
+
+ if (ret2 < OK) /* initialization error */
+ pr_err("fts initialization failed 3 times\n");
+
+
+ return ret2;
+}
+
+
+static irqreturn_t fts_isr(int irq, void *handle)
+{
+ struct fts_ts_info *info = handle;
+
+ info->timestamp = ktime_get();
+ input_set_timestamp(info->input_dev, info->timestamp);
+
+ return IRQ_WAKE_THREAD;
+}
+
+/**
+ * Initialize the dispatch table with the event handlers for any possible event
+ * ID
+ * Set IRQ pin behavior (level triggered low)
+ * Register top half interrupt handler function.
+ * @see fts_interrupt_handler()
+ */
+static int fts_interrupt_install(struct fts_ts_info *info)
+{
+ int i, error = 0;
+
+ info->event_dispatch_table = kzalloc(sizeof(event_dispatch_handler_t) *
+ NUM_EVT_ID, GFP_KERNEL);
+
+ if (!info->event_dispatch_table) {
+ pr_err("OOM allocating event dispatch table\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < NUM_EVT_ID; i++)
+ info->event_dispatch_table[i] = fts_nop_event_handler;
+
+ install_handler(info, ENTER_POINT, enter_pointer);
+ install_handler(info, LEAVE_POINT, leave_pointer);
+ install_handler(info, MOTION_POINT, motion_pointer);
+ install_handler(info, ERROR, error);
+ install_handler(info, CONTROLLER_READY, controller_ready);
+ install_handler(info, STATUS_UPDATE, status);
+ install_handler(info, USER_REPORT, user_report);
+
+ /* disable interrupts in any case */
+ error = fts_disableInterrupt();
+ if (error) {
+ return error;
+ }
+
+ error = request_threaded_irq(info->client->irq, fts_isr,
+ fts_interrupt_handler, IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+ FTS_TS_DRV_NAME, info);
+
+ if (error) {
+ pr_err("Request irq failed\n");
+ kfree(info->event_dispatch_table);
+ }
+
+ return error;
+}
+
+/**
+ * Clean the dispatch table and the free the IRQ.
+ * This function is called when the driver need to be removed
+ */
+static void fts_interrupt_uninstall(struct fts_ts_info *info)
+{
+ fts_disableInterrupt();
+
+ kfree(info->event_dispatch_table);
+
+ free_irq(info->client->irq, info);
+}
+
+/**@}*/
+
+/**
+ * This function try to attempt to communicate with the IC for the first time
+ * during the boot up process in order to read the necessary info for the
+ * following stages.
+ * The function execute a system reset, read fundamental info (system info)
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_init(struct fts_ts_info *info)
+{
+ int error;
+
+
+ error = fts_system_reset();
+ if (error < OK && isI2cError(error)) {
+ pr_err("Cannot reset the device! ERROR %08X\n", error);
+ return error;
+ } else {
+ if (error == (ERROR_TIMEOUT | ERROR_SYSTEM_RESET_FAIL)) {
+ pr_err("Setting default Sys INFO!\n");
+ error = defaultSysInfo(0);
+ } else {
+ error = readSysInfo(0); /* system reset OK */
+ if (error < OK) {
+ if (!isI2cError(error))
+ error = OK;
+ pr_err("Cannot read Sys Info! ERROR %08X\n",
+ error);
+ }
+ }
+ }
+
+ return error;
+}
+
+/**
+ * Execute a power cycle in the IC, toggling the power lines (AVDD and DVDD)
+ * @param info pointer to fts_ts_info struct which contain information of the
+ * regulators
+ * @return 0 if success or another value if fail
+ */
+int fts_chip_powercycle(struct fts_ts_info *info)
+{
+ int error = 0;
+
+ pr_debug("%s: Power Cycle Starting...\n", __func__);
+ pr_debug("%s: Disabling IRQ...\n", __func__);
+ /** if IRQ pin is short with DVDD a call to the ISR will triggered when
+ * the regulator is turned off if IRQ not disabled */
+ fts_disableInterrupt();
+
+ if (info->vdd_reg) {
+ error = regulator_disable(info->vdd_reg);
+ if (error < 0)
+ pr_err("%s: Failed to disable DVDD regulator\n",
+ __func__);
+ }
+
+ if (info->avdd_reg) {
+ error = regulator_disable(info->avdd_reg);
+ if (error < 0)
+ pr_err("%s: Failed to disable AVDD regulator\n",
+ __func__);
+ }
+
+ if (info->board->reset_gpio != GPIO_NOT_DEFINED)
+ gpio_set_value(info->board->reset_gpio, 0);
+ else
+ mdelay(300);
+
+ /* in FTI power up first the digital and then the analog */
+ if (info->vdd_reg) {
+ error = regulator_enable(info->vdd_reg);
+ if (error < 0)
+ pr_err("%s: Failed to enable DVDD regulator\n",
+ __func__);
+ }
+
+ mdelay(1);
+
+ if (info->avdd_reg) {
+ error = regulator_enable(info->avdd_reg);
+ if (error < 0)
+ pr_err("%s: Failed to enable AVDD regulator\n",
+ __func__);
+ }
+
+ mdelay(5); /* time needed by the regulators for reaching the regime
+ * values */
+
+
+ if (info->board->reset_gpio != GPIO_NOT_DEFINED) {
+ mdelay(10); /* time to wait before bring up the reset
+ * gpio after the power up of the regulators */
+ gpio_set_value(info->board->reset_gpio, 1);
+ }
+
+ release_all_touches(info);
+
+ pr_debug("%s: Power Cycle Finished! ERROR CODE = %08x\n",
+ __func__, error);
+ setSystemResetedUp(1);
+ setSystemResetedDown(1);
+ return error;
+}
+
+
+/**
+ * Complete the boot up process, initializing the sensing of the IC according
+ * to the current setting chosen by the host
+ * Register the notifier for the suspend/resume actions and the event handler
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_init_sensing(struct fts_ts_info *info)
+{
+ int error = 0;
+
+ error |= fts_mode_handler(info, 0); /* enable the features and
+ * sensing */
+ /* error |= fts_enableInterrupt(); */ /* enable the interrupt */
+ error |= fts_resetDisableIrqCount();
+
+ if (error < OK)
+ pr_err("%s Init after Probe error (ERROR = %08X)\n",
+ __func__, error);
+
+ return error;
+}
+
+/* TODO: change this function according with the needs of customer in terms
+ * of feature to enable/disable */
+
+/**
+ * @ingroup mode_section
+ * @{
+ */
+/**
+ * The function handle the switching of the mode in the IC enabling/disabling
+ * the sensing and the features set from the host
+ * @param info pointer to fts_ts_info which contains info about the device and
+ * its hw setup
+ * @param force if 1, the enabling/disabling command will be send even
+ * if the feature was already enabled/disabled otherwise it will judge if
+ * the feature changed status or the IC had a system reset
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_mode_handler(struct fts_ts_info *info, int force)
+{
+ int res = OK;
+ int ret = OK;
+ u8 settings[4] = { 0 };
+
+ /* disable irq wake because resuming from gesture mode */
+ if (IS_POWER_MODE(info->mode, SCAN_MODE_LOW_POWER) &&
+ (info->resume_bit == 1))
+ disable_irq_wake(info->client->irq);
+
+ info->mode = MODE_NOTHING; /* initialize the mode to nothing
+ * in order to be updated depending
+ * on the features enabled */
+
+ pr_debug("%s: Mode Handler starting...\n", __func__);
+ switch (info->resume_bit) {
+ case 0: /* screen down */
+ pr_debug("%s: Screen OFF...\n", __func__);
+ /* do sense off in order to avoid the flooding of the fifo with
+ * touch events if someone is touching the panel during suspend
+ **/
+ pr_debug("%s: Sense OFF!\n", __func__);
+ /* for speed reason (no need to check echo in this case and
+ * interrupt can be enabled) */
+ ret = setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ res |= ret; /* to avoid warning unsused ret variable when a
+ * ll the features are disabled */
+
+#ifdef GESTURE_MODE
+ if (info->gesture_enabled == 1) {
+ pr_debug("%s: enter in gesture mode !\n",
+ __func__);
+ res = enterGestureMode(isSystemResettedDown());
+ if (res >= OK) {
+ enable_irq_wake(info->client->irq);
+ fromIDtoMask(FEAT_SEL_GESTURE,
+ (u8 *)&info->mode,
+ sizeof(info->mode));
+ MODE_LOW_POWER(info->mode, 0);
+ } else
+ pr_err("%s: enterGestureMode failed! ERROR %08X recovery in senseOff...\n",
+ __func__, res);
+ }
+#endif
+
+ setSystemResetedDown(0);
+ break;
+
+ case 1: /* screen up */
+ pr_debug("%s: Screen ON...\n", __func__);
+
+#ifdef GLOVE_MODE
+ if ((info->glove_enabled == FEAT_ENABLE &&
+ isSystemResettedUp()) || force == 1) {
+ pr_debug("%s: Glove Mode setting...\n", __func__);
+ settings[0] = info->glove_enabled;
+ /* required to satisfy also the disable case */
+ ret = setFeatures(FEAT_SEL_GLOVE, settings, 1);
+ if (ret < OK)
+ pr_err("%s: error during setting GLOVE_MODE! ERROR %08X\n",
+ __func__, ret);
+ res |= ret;
+
+ if (ret >= OK && info->glove_enabled == FEAT_ENABLE) {
+ fromIDtoMask(FEAT_SEL_GLOVE, (u8 *)&info->mode,
+ sizeof(info->mode));
+ pr_debug("%s: GLOVE_MODE Enabled!\n", __func__);
+ } else
+ pr_debug("%s: GLOVE_MODE Disabled!\n", __func__);
+ }
+
+#endif
+
+#ifdef COVER_MODE
+ if ((info->cover_enabled == FEAT_ENABLE &&
+ isSystemResettedUp()) || force == 1) {
+ pr_debug("%s: Cover Mode setting...\n", __func__);
+ settings[0] = info->cover_enabled;
+ ret = setFeatures(FEAT_SEL_COVER, settings, 1);
+ if (ret < OK)
+ pr_err("%s: error during setting COVER_MODE! ERROR %08X\n",
+ __func__, ret);
+ res |= ret;
+
+ if (ret >= OK && info->cover_enabled == FEAT_ENABLE) {
+ fromIDtoMask(FEAT_SEL_COVER, (u8 *)&info->mode,
+ sizeof(info->mode));
+ pr_debug("%s: COVER_MODE Enabled!\n", __func__);
+ } else
+ pr_debug("%s: COVER_MODE Disabled!\n", __func__);
+ }
+#endif
+#ifdef CHARGER_MODE
+ if ((info->charger_enabled > 0 && isSystemResettedUp()) ||
+ force == 1) {
+ pr_debug("%s: Charger Mode setting...\n", __func__);
+
+ settings[0] = info->charger_enabled;
+ ret = setFeatures(FEAT_SEL_CHARGER, settings, 1);
+ if (ret < OK)
+ pr_err("%s: error during setting CHARGER_MODE! ERROR %08X\n",
+ __func__, ret);
+ res |= ret;
+
+ if (ret >= OK && info->charger_enabled == FEAT_ENABLE) {
+ fromIDtoMask(FEAT_SEL_CHARGER,
+ (u8 *)&info->mode,
+ sizeof(info->mode));
+ pr_debug("%s: CHARGER_MODE Enabled!\n",
+ __func__);
+ } else
+ pr_debug("%s: CHARGER_MODE Disabled!\n",
+ __func__);
+ }
+#endif
+
+
+#ifdef GRIP_MODE
+ if ((info->grip_enabled == FEAT_ENABLE &&
+ isSystemResettedUp()) || force == 1) {
+ pr_debug("%s: Grip Mode setting...\n", __func__);
+ settings[0] = info->grip_enabled;
+ ret = setFeatures(FEAT_SEL_GRIP, settings, 1);
+ if (ret < OK)
+ pr_err("%s: error during setting GRIP_MODE! ERROR %08X\n",
+ __func__, ret);
+ res |= ret;
+
+ if (ret >= OK && info->grip_enabled == FEAT_ENABLE) {
+ fromIDtoMask(FEAT_SEL_GRIP, (u8 *)&info->mode,
+ sizeof(info->mode));
+ pr_debug("%s: GRIP_MODE Enabled!\n", __func__);
+ } else
+ pr_debug("%s: GRIP_MODE Disabled!\n", __func__);
+ }
+#endif
+ /* If some selective scan want to be enabled can be done
+ * an or of the following options
+ */
+ /* settings[0] = ACTIVE_MULTI_TOUCH | ACTIVE_KEY | */
+ /* ACTIVE_HOVER | ACTIVE_PROXIMITY | */
+ /* ACTIVE_FORCE; */
+ settings[0] = 0xFF; /* enable all the possible scans mode
+ * supported by the config */
+ pr_debug("%s: Sense ON!\n", __func__);
+ res |= setScanMode(SCAN_MODE_ACTIVE, settings[0]);
+ info->mode |= (SCAN_MODE_ACTIVE << 24);
+ MODE_ACTIVE(info->mode, settings[0]);
+
+
+ setSystemResetedUp(0);
+ break;
+
+ default:
+ pr_err("%s: invalid resume_bit value = %d! ERROR %08X\n",
+ __func__, info->resume_bit, ERROR_OP_NOT_ALLOW);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+
+ pr_debug("%s: Mode Handler finished! res = %08X mode = %08X\n",
+ __func__, res, info->mode);
+ return res;
+}
+
+/**
+ * Configure the switch GPIO to toggle bus master between AP and SLPI.
+ * gpio_value takes one of
+ * { FTS_SWITCH_GPIO_VALUE_SLPI_MASTER, FTS_SWITCH_GPIO_VALUE_AP_MASTER }
+ */
+static void fts_set_switch_gpio(struct fts_ts_info *info, int gpio_value)
+{
+ int retval;
+ unsigned int gpio = info->board->switch_gpio;
+
+ if (!gpio_is_valid(gpio))
+ return;
+
+ pr_debug("%s: toggling i2c switch to %s\n", __func__,
+ gpio_value == FTS_SWITCH_GPIO_VALUE_AP_MASTER ? "AP" : "SLPI");
+
+ retval = gpio_direction_output(gpio, gpio_value);
+ if (retval < 0)
+ pr_err("%s: Failed to toggle switch_gpio, err = %d\n",
+ __func__, retval);
+}
+
+/**
+ * Resume work function which perform a system reset, clean all the touches
+ * from the linux input system and prepare the ground for enabling the sensing
+ */
+static void fts_resume_work(struct work_struct *work)
+{
+ struct fts_ts_info *info;
+
+ info = container_of(work, struct fts_ts_info, resume_work);
+
+ if (!info->sensor_sleep)
+ return;
+
+#ifdef CONFIG_TOUCHSCREEN_TBN
+ if (info->tbn)
+ tbn_request_bus(info->tbn);
+#endif
+
+ fts_set_switch_gpio(info, FTS_SWITCH_GPIO_VALUE_AP_MASTER);
+
+ __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ));
+
+ info->resume_bit = 1;
+
+ fts_system_reset();
+
+ release_all_touches(info);
+
+ fts_mode_handler(info, 0);
+
+ info->sensor_sleep = false;
+
+ fts_enableInterrupt();
+
+ complete_all(&info->bus_resumed);
+}
+
+/**
+ * Suspend work function which clean all the touches from Linux input system
+ * and prepare the ground to disabling the sensing or enter in gesture mode
+ */
+static void fts_suspend_work(struct work_struct *work)
+{
+ struct fts_ts_info *info;
+
+ info = container_of(work, struct fts_ts_info, suspend_work);
+
+ if (info->sensor_sleep)
+ return;
+
+ reinit_completion(&info->bus_resumed);
+
+ __pm_wakeup_event(info->wakesrc, jiffies_to_msecs(HZ));
+
+ info->resume_bit = 0;
+
+ fts_mode_handler(info, 0);
+
+ release_all_touches(info);
+
+ info->sensor_sleep = true;
+
+ fts_disableInterrupt();
+
+ fts_set_switch_gpio(info, FTS_SWITCH_GPIO_VALUE_SLPI_MASTER);
+
+#ifdef CONFIG_TOUCHSCREEN_TBN
+ if (info->tbn)
+ tbn_release_bus(info->tbn);
+#endif
+}
+/** @}*/
+
+
+static void fts_aggregate_bus_state(struct fts_ts_info *info)
+{
+ pr_debug("%s: bus_refmask = 0x%02X.\n", __func__,
+ info->bus_refmask);
+
+ /* Complete or cancel any outstanding transitions */
+ cancel_work_sync(&info->suspend_work);
+ cancel_work_sync(&info->resume_work);
+
+ if ((info->bus_refmask == 0 && info->sensor_sleep) ||
+ (info->bus_refmask != 0 && !info->sensor_sleep))
+ return;
+
+ if (info->bus_refmask == 0)
+ queue_work(info->event_wq, &info->suspend_work);
+ else
+ queue_work(info->event_wq, &info->resume_work);
+}
+
+int fts_set_bus_ref(struct fts_ts_info *info, u16 ref, bool enable)
+{
+ int result = OK;
+
+ mutex_lock(&info->bus_mutex);
+
+ if ((enable && (info->bus_refmask & ref)) ||
+ (!enable && !(info->bus_refmask & ref))) {
+ pr_err("%s: reference is unexpectedly set: mask=0x%04X, ref=0x%04X, enable=%d.\n",
+ __func__, info->bus_refmask, ref, enable);
+ mutex_unlock(&info->bus_mutex);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ if (enable) {
+ /* IRQs can only keep the bus active. IRQs received while the
+ * bus is transferred to SLPI should be ignored.
+ */
+ if (ref == FTS_BUS_REF_IRQ && info->bus_refmask == 0)
+ result = ERROR_OP_NOT_ALLOW;
+ else
+ info->bus_refmask |= ref;
+ } else
+ info->bus_refmask &= ~ref;
+ fts_aggregate_bus_state(info);
+
+ mutex_unlock(&info->bus_mutex);
+
+ /* When triggering a wake, wait up to one second to resume. SCREEN_ON
+ * and IRQ references do not need to wait.
+ */
+ if (enable && ref != FTS_BUS_REF_SCREEN_ON && ref != FTS_BUS_REF_IRQ) {
+ wait_for_completion_timeout(&info->bus_resumed, HZ);
+ if (info->sensor_sleep) {
+ pr_err("%s: Failed to wake the touch bus: mask=0x%04X, ref=0x%04X, enable=%d.\n",
+ __func__, info->bus_refmask, ref, enable);
+ result = ERROR_TIMEOUT;
+ }
+ }
+
+ return result;
+}
+
+#if 0
+/**
+ * Callback function used to detect the suspend/resume events generated by
+ * clicking the power button.
+ * This function schedule a suspend or resume work according to the event
+ * received.
+ */
+static int fts_screen_state_chg_callback(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct fts_ts_info *info = container_of(nb, struct fts_ts_info,
+ notifier);
+ struct msm_drm_notifier *evdata = data;
+ unsigned int blank;
+
+ if (val != MSM_DRM_EVENT_BLANK && val != MSM_DRM_EARLY_EVENT_BLANK)
+ return NOTIFY_DONE;
+
+ if (!info || !evdata || !evdata->data) {
+ pr_debug("%s: Bad fts notifier call!\n", __func__);
+ return NOTIFY_DONE;
+ }
+
+ pr_debug("%s: fts notifier begin!\n", __func__);
+
+ /* finish processing any events on queue */
+ flush_workqueue(info->event_wq);
+
+ blank = *(int *) (evdata->data);
+ switch (blank) {
+ case MSM_DRM_BLANK_POWERDOWN:
+ case MSM_DRM_BLANK_LP:
+ if (val == MSM_DRM_EARLY_EVENT_BLANK) {
+ pr_debug("%s: BLANK\n", __func__);
+ fts_set_bus_ref(info, FTS_BUS_REF_SCREEN_ON, false);
+ }
+ break;
+ case MSM_DRM_BLANK_UNBLANK:
+ if (val == MSM_DRM_EVENT_BLANK) {
+ pr_debug("%s: UNBLANK\n", __func__);
+ fts_set_bus_ref(info, FTS_BUS_REF_SCREEN_ON, true);
+ }
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block fts_noti_block = {
+ .notifier_call = fts_screen_state_chg_callback,
+};
+#endif
+
+/**
+ * From the name of the power regulator get/put the actual regulator structs
+ * (copying their references into fts_ts_info variable)
+ * @param info pointer to fts_ts_info which contains info about the device and
+ * its hw setup
+ * @param get if 1, the regulators are get otherwise they are put (released)
+ * back to the system
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_get_reg(struct fts_ts_info *info, bool get)
+{
+ int retval;
+ const struct fts_hw_platform_data *bdata = info->board;
+
+ if (!get) {
+ retval = 0;
+ goto regulator_put;
+ }
+
+ if ((bdata->vdd_reg_name != NULL) && (*bdata->vdd_reg_name != 0)) {
+ info->vdd_reg = regulator_get(info->dev, bdata->vdd_reg_name);
+ if (IS_ERR(info->vdd_reg)) {
+ pr_err("%s: Failed to get power regulator\n", __func__);
+ retval = PTR_ERR(info->vdd_reg);
+ goto regulator_put;
+ }
+ }
+
+ if ((bdata->avdd_reg_name != NULL) && (*bdata->avdd_reg_name != 0)) {
+ info->avdd_reg = regulator_get(info->dev, bdata->avdd_reg_name);
+ if (IS_ERR(info->avdd_reg)) {
+ pr_err("%s: Failed to get bus pullup regulator\n",
+ __func__);
+ retval = PTR_ERR(info->avdd_reg);
+ goto regulator_put;
+ }
+ }
+
+ return OK;
+
+regulator_put:
+ if (info->vdd_reg) {
+ regulator_put(info->vdd_reg);
+ info->vdd_reg = NULL;
+ }
+
+ if (info->avdd_reg) {
+ regulator_put(info->avdd_reg);
+ info->avdd_reg = NULL;
+ }
+
+ return retval;
+}
+
+
+/**
+ * Enable or disable the power regulators
+ * @param info pointer to fts_ts_info which contains info about the device and
+ * its hw setup
+ * @param enable if 1, the power regulators are turned on otherwise they are
+ * turned off
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_enable_reg(struct fts_ts_info *info, bool enable)
+{
+ int retval;
+
+ if (!enable) {
+ retval = 0;
+ goto disable_pwr_reg;
+ }
+
+ if (info->vdd_reg) {
+ retval = regulator_enable(info->vdd_reg);
+ if (retval < 0) {
+ pr_err("%s: Failed to enable bus regulator\n",
+ __func__);
+ goto exit;
+ }
+ }
+
+ if (info->avdd_reg) {
+ retval = regulator_enable(info->avdd_reg);
+ if (retval < 0) {
+ pr_err("%s: Failed to enable power regulator\n",
+ __func__);
+ goto disable_bus_reg;
+ }
+ }
+
+ return OK;
+
+disable_pwr_reg:
+ if (info->avdd_reg)
+ regulator_disable(info->avdd_reg);
+
+disable_bus_reg:
+ if (info->vdd_reg)
+ regulator_disable(info->vdd_reg);
+
+exit:
+ return retval;
+}
+
+/**
+ * Configure a GPIO according to the parameters
+ * @param gpio gpio number
+ * @param config if true, the gpio is set up otherwise it is free
+ * @param dir direction of the gpio, 0 = in, 1 = out
+ * @param state initial value (if the direction is in, this parameter is
+ * ignored)
+ * return error code
+ */
+static int fts_gpio_setup(int gpio, bool config, int dir, int state)
+{
+ int retval = 0;
+ unsigned char buf[16];
+
+ if (config) {
+ scnprintf(buf, sizeof(buf), "fts_gpio_%u\n", gpio);
+
+ retval = gpio_request(gpio, buf);
+ if (retval) {
+ pr_err("%s: Failed to get gpio %d (code: %d)",
+ __func__, gpio, retval);
+ return retval;
+ }
+
+ if (dir == 0)
+ retval = gpio_direction_input(gpio);
+ else
+ retval = gpio_direction_output(gpio, state);
+ if (retval) {
+ pr_err("%s: Failed to set gpio %d direction",
+ __func__, gpio);
+ return retval;
+ }
+ } else
+ gpio_free(gpio);
+
+ return retval;
+}
+
+/**
+ * Setup the IRQ and RESET (if present) gpios.
+ * If the Reset Gpio is present it will perform a cycle HIGH-LOW-HIGH in order
+ * to assure that the IC has been reset properly
+ */
+static int fts_set_gpio(struct fts_ts_info *info)
+{
+ int retval;
+ struct fts_hw_platform_data *bdata =
+ info->board;
+
+ retval = fts_gpio_setup(bdata->irq_gpio, true, 0, 0);
+ if (retval < 0) {
+ pr_err("%s: Failed to configure irq GPIO\n", __func__);
+ goto err_gpio_irq;
+ }
+
+ if (gpio_is_valid(bdata->switch_gpio)) {
+ retval = fts_gpio_setup(bdata->switch_gpio, true, 1, 1);
+ if (retval < 0)
+ pr_err("%s: Failed to configure I2C switch\n",
+ __func__);
+ }
+
+ if (bdata->reset_gpio >= 0) {
+ retval = fts_gpio_setup(bdata->reset_gpio, true, 1, 0);
+ if (retval < 0) {
+ pr_err("%s: Failed to configure reset GPIO\n",
+ __func__);
+ goto err_gpio_reset;
+ }
+ }
+ if (bdata->reset_gpio >= 0) {
+ gpio_set_value(bdata->reset_gpio, 0);
+ mdelay(10);
+ gpio_set_value(bdata->reset_gpio, 1);
+ }
+
+ return OK;
+
+err_gpio_reset:
+ fts_gpio_setup(bdata->irq_gpio, false, 0, 0);
+ bdata->reset_gpio = GPIO_NOT_DEFINED;
+err_gpio_irq:
+ return retval;
+}
+
+/**
+ * Retrieve and parse the hw information from the device tree node defined in
+ * the system.
+ * the most important information to obtain are: IRQ and RESET gpio numbers,
+ * power regulator names
+ * In the device file node is possible to define additional optional
+ * information
+ * that can be parsed here.
+ */
+static int parse_dt(struct device *dev, struct fts_hw_platform_data *bdata)
+{
+ int retval;
+ const char *name;
+ struct device_node *np = dev->of_node;
+ u32 coords[2];
+
+ bdata->switch_gpio = of_get_named_gpio(np, "st,switch_gpio", 0);
+ pr_debug("switch_gpio = %d\n", bdata->switch_gpio);
+
+ bdata->irq_gpio = of_get_named_gpio(np, "st,irq-gpio", 0);
+
+ pr_debug("irq_gpio = %d\n", bdata->irq_gpio);
+
+
+ retval = of_property_read_string(np, "st,regulator_dvdd", &name);
+ if (retval == -EINVAL)
+ bdata->vdd_reg_name = NULL;
+ else if (retval < 0)
+ return retval;
+ else {
+ bdata->vdd_reg_name = name;
+ pr_debug("pwr_reg_name = %s\n", name);
+ }
+
+ retval = of_property_read_string(np, "st,regulator_avdd", &name);
+ if (retval == -EINVAL)
+ bdata->avdd_reg_name = NULL;
+ else if (retval < 0)
+ return retval;
+ else {
+ bdata->avdd_reg_name = name;
+ pr_debug("bus_reg_name = %s\n", name);
+ }
+
+ if (of_property_read_bool(np, "st,reset-gpio")) {
+ bdata->reset_gpio = of_get_named_gpio(np,
+ "st,reset-gpio", 0
+ );
+ pr_debug("reset_gpio =%d\n", bdata->reset_gpio);
+ } else
+ bdata->reset_gpio = GPIO_NOT_DEFINED;
+
+ retval = of_property_read_string(np, "st,firmware_name", &name);
+ if (retval == -EINVAL)
+ bdata->fw_name = PATH_FILE_FW;
+ else if (retval >= 0)
+ bdata->fw_name = name;
+ pr_debug("firmware name = %s\n", bdata->fw_name);
+
+ if (of_property_read_u32_array(np, "st,max-coords", coords, 2)) {
+ pr_err("st,max-coords not found, using 1440x2560\n");
+ coords[0] = 1440;
+ coords[1] = 2560;
+ }
+ bdata->x_axis_max = coords[0];
+ bdata->y_axis_max = coords[1];
+
+ return OK;
+}
+
+/**
+ * Probe function, called when the driver it is matched with a device
+ * with the same name compatible name
+ * This function allocate, initialize all the most important functions and flow
+ * those are used by the driver to operate with the IC.
+ * It allocates device variables, initialize queues and schedule works,
+ * registers the IRQ handler, suspend/resume callbacks, registers the device
+ * to the linux input subsystem etc.
+ */
+#ifdef I2C_INTERFACE
+static int fts_probe(struct i2c_client *client)
+{
+#else
+static int fts_probe(struct spi_device *client)
+{
+#endif
+
+ struct fts_ts_info *info = NULL;
+ int error = 0;
+ struct device_node *dp = client->dev.of_node;
+ int retval;
+ int skip_5_1 = 0;
+ u16 bus_type;
+
+ pr_debug("%s: driver probe begin!\n", __func__);
+ pr_debug("driver ver. %s\n", FTS_TS_DRV_VERSION);
+
+ pr_debug("SET Bus Functionality :\n");
+#ifdef I2C_INTERFACE
+ pr_debug("I2C interface...\n");
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("Unsupported I2C functionality\n");
+ error = -EIO;
+ goto ProbeErrorExit_0;
+ }
+
+ pr_debug("i2c address: %x\n", client->addr);
+ bus_type = BUS_I2C;
+#else
+ pr_debug("SPI interface...\n");
+ client->mode = SPI_MODE_0;
+#ifndef SPI4_WIRE
+ client->mode |= SPI_3WIRE;
+#endif
+
+ client->max_speed_hz = SPI_CLOCK_FREQ;
+ client->bits_per_word = 8;
+ if (spi_setup(client) < 0) {
+ pr_err("Unsupported SPI functionality\n");
+ error = -EIO;
+ goto ProbeErrorExit_0;
+ }
+ bus_type = BUS_SPI;
+#endif
+
+
+ pr_debug("SET Device driver INFO:\n");
+
+
+ info = kzalloc(sizeof(struct fts_ts_info), GFP_KERNEL);
+ if (!info) {
+ pr_err("Out of memory... Impossible to allocate struct info!\n");
+ error = -ENOMEM;
+ goto ProbeErrorExit_0;
+ }
+
+ info->client = client;
+ info->dev = &info->client->dev;
+
+ dev_set_drvdata(info->dev, info);
+
+#ifdef CONFIG_TOUCHSCREEN_TBN
+ info->tbn = tbn_init(info->dev);
+ if (!info->tbn) {
+ pr_err("ERROR: failed to init tbn context\n");
+ error = -ENODEV;
+ goto ProbeErrorExit_1;
+ }
+#endif
+
+ if (dp) {
+ info->board = devm_kzalloc(&client->dev,
+ sizeof(struct fts_hw_platform_data),
+ GFP_KERNEL);
+ if (!info->board) {
+ pr_err("ERROR:info.board kzalloc failed\n");
+ goto ProbeErrorExit_1;
+ }
+ parse_dt(&client->dev, info->board);
+ }
+
+ pr_debug("SET Regulators:\n");
+ retval = fts_get_reg(info, true);
+ if (retval < 0) {
+ pr_err("ERROR: %s: Failed to get regulators\n", __func__);
+ goto ProbeErrorExit_1;
+ }
+
+ retval = fts_enable_reg(info, true);
+ if (retval < 0) {
+ pr_err("%s: ERROR Failed to enable regulators\n", __func__);
+ goto ProbeErrorExit_2;
+ }
+
+ pr_debug("SET GPIOS:\n");
+ retval = fts_set_gpio(info);
+ if (retval < 0) {
+ pr_err("%s: ERROR Failed to set up GPIO's\n", __func__);
+ goto ProbeErrorExit_2;
+ }
+ info->client->irq = gpio_to_irq(info->board->irq_gpio);
+
+ pr_debug("SET Event Handler:\n");
+
+ info->wakesrc = wakeup_source_register(info->dev, "fts_tp");
+ info->event_wq = alloc_workqueue("fts-event-queue", WQ_UNBOUND |
+ WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
+ if (!info->event_wq) {
+ pr_err("ERROR: Cannot create work thread\n");
+ error = -ENOMEM;
+ goto ProbeErrorExit_4;
+ }
+
+ INIT_WORK(&info->resume_work, fts_resume_work);
+ INIT_WORK(&info->suspend_work, fts_suspend_work);
+
+ init_completion(&info->bus_resumed);
+ complete_all(&info->bus_resumed);
+
+ pr_debug("SET Input Device Property:\n");
+ info->dev = &info->client->dev;
+ info->input_dev = input_allocate_device();
+ if (!info->input_dev) {
+ pr_err("ERROR: No such input device defined!\n");
+ error = -ENODEV;
+ goto ProbeErrorExit_5;
+ }
+ info->input_dev->dev.parent = &client->dev;
+ info->input_dev->name = FTS_TS_DRV_NAME;
+ scnprintf(fts_ts_phys, sizeof(fts_ts_phys), "%s/input0",
+ info->input_dev->name);
+ info->input_dev->phys = fts_ts_phys;
+ info->input_dev->id.bustype = bus_type;
+ info->input_dev->id.vendor = 0x0001;
+ info->input_dev->id.product = 0x0002;
+ info->input_dev->id.version = 0x0100;
+
+ __set_bit(EV_SYN, info->input_dev->evbit);
+ __set_bit(EV_KEY, info->input_dev->evbit);
+ __set_bit(EV_ABS, info->input_dev->evbit);
+ __set_bit(BTN_TOUCH, info->input_dev->keybit);
+ /* __set_bit(BTN_TOOL_FINGER, info->input_dev->keybit); */
+ /* __set_bit(BTN_TOOL_PEN, info->input_dev->keybit); */
+
+ input_mt_init_slots(info->input_dev, TOUCH_ID_MAX, INPUT_MT_DIRECT);
+
+ /* input_mt_init_slots(info->input_dev, TOUCH_ID_MAX); */
+
+ input_set_abs_params(info->input_dev, ABS_MT_POSITION_X, X_AXIS_MIN,
+ info->board->x_axis_max, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_POSITION_Y, Y_AXIS_MIN,
+ info->board->y_axis_max, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MAJOR, AREA_MIN,
+ AREA_MAX, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_TOUCH_MINOR, AREA_MIN,
+ AREA_MAX, 0, 0);
+ input_set_abs_params(info->input_dev, ABS_MT_PRESSURE, PRESSURE_MIN,
+ PRESSURE_MAX, 0, 0);
+#ifndef SKIP_DISTANCE
+ input_set_abs_params(info->input_dev, ABS_MT_DISTANCE, DISTANCE_MIN,
+ DISTANCE_MAX, 0, 0);
+#endif
+
+#ifdef GESTURE_MODE
+ input_set_capability(info->input_dev, EV_KEY, KEY_WAKEUP);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_M);
+ input_set_capability(info->input_dev, EV_KEY, KEY_O);
+ input_set_capability(info->input_dev, EV_KEY, KEY_E);
+ input_set_capability(info->input_dev, EV_KEY, KEY_W);
+ input_set_capability(info->input_dev, EV_KEY, KEY_C);
+ input_set_capability(info->input_dev, EV_KEY, KEY_L);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F);
+ input_set_capability(info->input_dev, EV_KEY, KEY_V);
+ input_set_capability(info->input_dev, EV_KEY, KEY_S);
+ input_set_capability(info->input_dev, EV_KEY, KEY_Z);
+ input_set_capability(info->input_dev, EV_KEY, KEY_WWW);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_LEFT);
+ input_set_capability(info->input_dev, EV_KEY, KEY_RIGHT);
+ input_set_capability(info->input_dev, EV_KEY, KEY_UP);
+ input_set_capability(info->input_dev, EV_KEY, KEY_DOWN);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_F1);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F2);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F3);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F4);
+ input_set_capability(info->input_dev, EV_KEY, KEY_F5);
+
+ input_set_capability(info->input_dev, EV_KEY, KEY_LEFTBRACE);
+ input_set_capability(info->input_dev, EV_KEY, KEY_RIGHTBRACE);
+#endif
+
+#ifdef PHONE_KEY
+ /* KEY associated to the touch screen buttons */
+ input_set_capability(info->input_dev, EV_KEY, KEY_HOMEPAGE);
+ input_set_capability(info->input_dev, EV_KEY, KEY_BACK);
+ input_set_capability(info->input_dev, EV_KEY, KEY_MENU);
+#endif
+
+ mutex_init(&info->diag_cmd_lock);
+
+ mutex_init(&(info->input_report_mutex));
+ mutex_init(&info->bus_mutex);
+
+ /* Assume screen is on throughout probe */
+ info->bus_refmask = FTS_BUS_REF_SCREEN_ON;
+
+#ifdef GESTURE_MODE
+ mutex_init(&gestureMask_mutex);
+#endif
+
+ spin_lock_init(&fts_int);
+
+ /* register the multi-touch input device */
+ error = input_register_device(info->input_dev);
+ if (error) {
+ pr_err("ERROR: No such input device\n");
+ error = -ENODEV;
+ goto ProbeErrorExit_5_1;
+ }
+
+ skip_5_1 = 1;
+ /* track slots */
+ info->touch_id = 0;
+#ifdef STYLUS_MODE
+ info->stylus_id = 0;
+#endif
+
+
+ /* init feature switches (by default all the features are disable,
+ * if one feature want to be enabled from the start,
+ * set the corresponding value to 1)*/
+ info->gesture_enabled = 0;
+ info->glove_enabled = 0;
+ info->charger_enabled = 0;
+ info->cover_enabled = 0;
+ info->grip_enabled = 0;
+
+ info->resume_bit = 1;
+
+ /*
+ * This *must* be done before request_threaded_irq is called.
+ * Otherwise, if an interrupt is received before request is added,
+ * but after the interrupt has been subscribed to, pm_qos_req
+ * may be accessed before initialization in the interrupt handler.
+ */
+ cpu_latency_qos_add_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE);
+
+ pr_debug("Init Core Lib:\n");
+ initCore(info);
+ /* init hardware device */
+ pr_debug("Device Initialization:\n");
+ error = fts_init(info);
+ if (error < OK) {
+ pr_err("Cannot initialize the device ERROR %08X\n", error);
+ error = -ENODEV;
+ goto ProbeErrorExit_6;
+ }
+
+#if defined(FW_UPDATE_ON_PROBE) && defined(FW_H_FILE)
+ pr_debug("FW Update and Sensing Initialization:\n");
+ error = fts_fw_update(info);
+ if (error < OK) {
+ pr_err("Cannot execute fw upgrade the device ERROR %08X\n",
+ error);
+ error = -ENODEV;
+ goto ProbeErrorExit_7;
+ }
+
+#else
+ pr_debug("SET Auto Fw Update:\n");
+ info->fwu_workqueue = alloc_workqueue("fts-fwu-queue", WQ_UNBOUND |
+ WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
+ if (!info->fwu_workqueue) {
+ pr_err("ERROR: Cannot create fwu work thread\n");
+ goto ProbeErrorExit_7;
+ }
+ INIT_DELAYED_WORK(&info->fwu_work, fts_fw_update_auto);
+#endif
+
+ pr_debug("SET Device File Nodes:\n");
+ /* sysfs stuff */
+ info->attrs.attrs = fts_attr_group;
+ error = sysfs_create_group(&client->dev.kobj, &info->attrs);
+ if (error) {
+ pr_err("ERROR: Cannot create sysfs structure!\n");
+ error = -ENODEV;
+ goto ProbeErrorExit_7;
+ }
+
+ error = fts_proc_init();
+ if (error < OK)
+ pr_err("Error: can not create /proc file!\n");
+
+#ifndef FW_UPDATE_ON_PROBE
+ queue_delayed_work(info->fwu_workqueue, &info->fwu_work,
+ msecs_to_jiffies(EXP_FN_WORK_DELAY_MS));
+#endif
+
+fts_interrupt_install(info);
+ info->touchsim.wq = alloc_workqueue("fts-heatmap_test-queue",
+ WQ_UNBOUND | WQ_HIGHPRI |
+ WQ_CPU_INTENSIVE, 1);
+
+ if (info->touchsim.wq)
+ INIT_WORK(&(info->touchsim.work), touchsim_work);
+ else
+ pr_err("ERROR: Cannot create touch sim. test work queue\n");
+
+ pr_debug("Probe Finished!\n");
+
+ return OK;
+
+
+ProbeErrorExit_7:
+ if(info->touchsim.wq)
+ destroy_workqueue(info->touchsim.wq);
+
+ProbeErrorExit_6:
+ cpu_latency_qos_remove_request(&info->pm_qos_req);
+ input_unregister_device(info->input_dev);
+
+ProbeErrorExit_5_1:
+ if (skip_5_1 != 1)
+ input_free_device(info->input_dev);
+
+ProbeErrorExit_5:
+ destroy_workqueue(info->event_wq);
+
+ProbeErrorExit_4:
+ /* destroy_workqueue(info->fwu_workqueue); */
+ wakeup_source_unregister(info->wakesrc);
+
+ fts_enable_reg(info, false);
+
+ProbeErrorExit_2:
+ fts_get_reg(info, false);
+
+ProbeErrorExit_1:
+ kfree(info);
+
+ProbeErrorExit_0:
+ pr_err("Probe Failed!\n");
+
+ return error;
+}
+
+
+/**
+ * Clear and free all the resources associated to the driver.
+ * This function is called when the driver need to be removed.
+ */
+#ifdef I2C_INTERFACE
+static int fts_remove(struct i2c_client *client)
+{
+#else
+static int fts_remove(struct spi_device *client)
+{
+#endif
+
+ struct fts_ts_info *info = dev_get_drvdata(&(client->dev));
+
+ /* Force the bus active throughout removal of the client */
+ fts_set_bus_ref(info, FTS_BUS_REF_FORCE_ACTIVE, true);
+
+ pr_debug("%s\n", __func__);
+
+#ifdef CONFIG_TOUCHSCREEN_TBN
+ tbn_cleanup(info->tbn);
+#endif
+
+ fts_proc_remove();
+
+ /* sysfs stuff */
+ sysfs_remove_group(&client->dev.kobj, &info->attrs);
+
+ /* remove interrupt and event handlers */
+ fts_interrupt_uninstall(info);
+
+ cpu_latency_qos_remove_request(&info->pm_qos_req);
+
+ /* unregister the device */
+ input_unregister_device(info->input_dev);
+
+ /* input_free_device(info->input_dev ); */
+
+ /* Remove the work thread */
+ destroy_workqueue(info->event_wq);
+ wakeup_source_unregister(info->wakesrc);
+
+ if(info->touchsim.wq)
+ destroy_workqueue(info->touchsim.wq);
+
+#ifndef FW_UPDATE_ON_PROBE
+ destroy_workqueue(info->fwu_workqueue);
+#endif
+
+ fts_enable_reg(info, false);
+ fts_get_reg(info, false);
+
+ /* free gpio */
+ if (gpio_is_valid(info->board->irq_gpio))
+ gpio_free(info->board->irq_gpio);
+ if (gpio_is_valid(info->board->switch_gpio))
+ gpio_free(info->board->switch_gpio);
+ if (gpio_is_valid(info->board->reset_gpio))
+ gpio_free(info->board->reset_gpio);
+
+ /* free all */
+ kfree(info);
+
+ return OK;
+}
+
+/**
+ * Struct which contains the compatible names that need to match with
+ * the definition of the device in the device tree node
+ */
+static struct of_device_id fts_of_match_table[] = {
+ {
+ .compatible = "st,fts",
+ },
+ {},
+};
+
+#ifdef I2C_INTERFACE
+static const struct i2c_device_id fts_device_id[] = {
+ { FTS_TS_DRV_NAME, 0 },
+ {}
+};
+
+static struct i2c_driver fts_i2c_driver = {
+ .driver = {
+ .name = FTS_TS_DRV_NAME,
+ .of_match_table = fts_of_match_table,
+ },
+ .probe = fts_probe,
+ .remove = fts_remove,
+ .id_table = fts_device_id,
+};
+#else
+static struct spi_driver fts_spi_driver = {
+ .driver = {
+ .name = FTS_TS_DRV_NAME,
+ .of_match_table = fts_of_match_table,
+ .owner = THIS_MODULE,
+ },
+ .probe = fts_probe,
+ .remove = fts_remove,
+};
+#endif
+
+
+
+
+static int __init fts_driver_init(void)
+{
+#ifdef I2C_INTERFACE
+ return i2c_add_driver(&fts_i2c_driver);
+#else
+ return spi_register_driver(&fts_spi_driver);
+#endif
+}
+
+static void __exit fts_driver_exit(void)
+{
+ pr_debug("%s\n", __func__);
+#ifdef I2C_INTERFACE
+ i2c_del_driver(&fts_i2c_driver);
+#else
+ spi_unregister_driver(&fts_spi_driver);
+#endif
+}
+
+
+MODULE_DESCRIPTION("STMicroelectronics MultiTouch IC Driver");
+MODULE_AUTHOR("STMicroelectronics");
+MODULE_LICENSE("GPL");
+
+late_initcall(fts_driver_init);
+module_exit(fts_driver_exit);
diff --git a/drivers/input/touchscreen/stm/fts.h b/drivers/input/touchscreen/stm/fts.h
new file mode 100644
index 00000000000..ca434c1cc9b
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts.h
@@ -0,0 +1,429 @@
+/*
+ * fts.h
+ *
+ * FTS Capacitive touch screen controller (FingerTipS)
+ *
+ * Copyright (C) 2017, STMicroelectronics
+ * Authors: AMG(Analog Mems Group)
+ *
+ * marco.cali@st.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+ * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+ * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM
+ * THE
+ * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+ * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+ */
+
+/*!
+ * \file fts.h
+ * \brief Contains all the definitions and structs used generally by the driver
+ */
+
+#ifndef _LINUX_FTS_I2C_H_
+#define _LINUX_FTS_I2C_H_
+
+#include <linux/device.h>
+#include <linux/pm_qos.h>
+#include "fts_lib/ftsSoftware.h"
+#include "fts_lib/ftsHardware.h"
+
+#ifdef CONFIG_TOUCHSCREEN_TBN
+#include "../touch_bus_negotiator.h"
+#endif
+
+
+/****************** CONFIGURATION SECTION ******************/
+/** @defgroup conf_section Driver Configuration Section
+ * Settings of the driver code in order to suit the HW set up and the
+ *application behavior
+ * @{
+ */
+/* **** CODE CONFIGURATION **** */
+#define FTS_TS_DRV_NAME "fts" /* driver name */
+#define FTS_TS_DRV_VERSION "5.2.10_Google_B1" /* driver version string
+ * */
+#define FTS_TS_DRV_VER 0x05020A00 /* driver version u32 format */
+
+/* #define DEBUG */ /* /< define to print more logs in the kernel log
+ * and better follow the code flow */
+#ifdef pr_fmt
+#undef pr_fmt
+#define pr_fmt(fmt) "[ FTS ] " fmt
+#endif
+
+#define DRIVER_TEST /* /< if defined allow to use and test special functions
+ * of the driver and fts_lib from command shell
+ * (useful for enginering/debug operations) */
+
+/* Comment 2 flags to disable auto-tune in MP test and device boot-up */
+/* if defined allow to have some procedures at the boot or from file node to
+ * assure that touch works under any condition that usually are disabled in the
+ * MP stage of the project
+ */
+/* #define ENGINEERING_CODE */
+/* Initialization of CX memory allowed on the phone */
+/* #define COMPUTE_CX_ON_PHONE */
+/* #define PRE_SAVED_METHOD */
+
+/*#define FW_H_FILE*/ /* include the FW data as header file */
+#ifdef FW_H_FILE
+#define FW_SIZE_NAME myArray_size /* FW data array size */
+#define FW_ARRAY_NAME myArray /* FW data array name */
+/*#define FW_UPDATE_ON_PROBE*/ /* No delay updating FW */
+#endif
+
+#ifndef FW_UPDATE_ON_PROBE
+/* Include the Production Limit File as header file, can be commented to use a
+ * .csv file instead */
+/* #define LIMITS_H_FILE */
+#ifdef LIMITS_H_FILE
+ #define LIMITS_SIZE_NAME myArray2_size /* /< name of the
+ * variable
+ * in the limits header
+ *file which
+ * specified the
+ *dimension of
+ * the limits data
+ *array */
+ #define LIMITS_ARRAY_NAME myArray2 /* /< name of the
+ * variable in
+ * the limits header
+ *file which
+ * specified the limits
+ *data array */
+#endif
+#else
+/* if execute fw update in the probe the limit file must be a .h */
+#define LIMITS_H_FILE /* /< include the Production Limit File as header file,
+ * DO NOT COMMENT! */
+#define LIMITS_SIZE_NAME myArray2_size /* /< name of the
+ * variable
+ * in the limits header
+ *file
+ * which specified the
+ *dimension
+ * of the limits data
+ *array */
+#define LIMITS_ARRAY_NAME myArray2 /* /< name of the
+ * variable in the
+ * limits header file
+ *which specified
+ * the limits data
+ *array */
+#endif
+
+/* #define USE_ONE_FILE_NODE */ /* /< allow to enable/disable all the features
+ * just using one file node */
+
+#ifndef FW_UPDATE_ON_PROBE
+#define EXP_FN_WORK_DELAY_MS 1000 /* /< time in ms elapsed after the probe
+ * to start the work which execute FW
+ *update
+ * and the Initialization of the IC */
+#endif
+
+/* **** END **** */
+
+
+/* **** FEATURES USED IN THE IC **** */
+/* Enable the support of keys */
+/* #define PHONE_KEY */
+
+#define GESTURE_MODE /* /< enable the support of the gestures */
+#ifdef GESTURE_MODE
+ #define USE_GESTURE_MASK /* /< the gestures to select are
+ * referred using
+ * a gesture bitmask instead of their
+ *gesture IDs */
+#endif
+
+
+#define CHARGER_MODE /* /< enable the support to charger mode feature
+ * (comment to disable) */
+
+#define GLOVE_MODE /* /< enable the support to glove mode feature (comment
+ * to disable) */
+
+#define COVER_MODE /* /< enable the support to cover mode feature (comment
+ * to disable) */
+
+#define STYLUS_MODE /* /< enable the support to stylus mode feature (comment
+ * to disable) */
+
+#define GRIP_MODE /* /< enable the support to grip mode feature (comment
+ * to disable) */
+
+
+/* **** END **** */
+
+
+/* **** PANEL SPECIFICATION **** */
+#define X_AXIS_MIN 0 /* /< min X coordinate of the display */
+#define Y_AXIS_MIN 0 /* /< min Y coordinate of the display */
+#define Y_AXIS_MAX 2959 /* /< Max Y coordinate of the display */
+#define X_AXIS_MAX 1440 /* /< Max X coordinate of the display */
+
+#define PRESSURE_MIN 0 /* /< min value of pressure reported */
+#define PRESSURE_MAX 127 /* /< Max value of pressure reported */
+
+#define DISTANCE_MIN 0 /* /< min distance between the tool and the
+ * display */
+#define DISTANCE_MAX 127 /* /< Max distance between the tool and the
+ * display */
+
+#define TOUCH_ID_MAX 10 /* /< Max number of simoultaneous touches
+ * reported */
+
+#define AREA_MIN PRESSURE_MIN /* /< min value of Major/minor axis
+ * reported */
+#define AREA_MAX PRESSURE_MAX /* /< Man value of Major/minor axis
+ * reported */
+/* **** END **** */
+
+/**@}*/
+/*********************************************************/
+
+#if 0 // no heat map
+/* **** LOCAL HEATMAP FEATURE *** */
+#define LOCAL_HEATMAP_WIDTH 7
+#define LOCAL_HEATMAP_HEIGHT 7
+#define LOCAL_HEATMAP_MODE 0xC1
+
+struct heatmap_report {
+ uint8_t prefix; /* always should be 0xA0 */
+ uint8_t mode; /* mode should be 0xC1 for heatmap */
+
+ uint16_t counter; /* LE order, should increment on each heatmap read */
+ int8_t offset_x;
+ uint8_t size_x;
+ int8_t offset_y;
+ uint8_t size_y;
+ /* data is in LE order; order should be enforced after data is read */
+ strength_t data[LOCAL_HEATMAP_WIDTH * LOCAL_HEATMAP_HEIGHT];
+} __attribute__((packed));
+/* **** END **** */
+#endif
+
+/*
+ * Configuration mode
+ *
+ * bitmask which can assume the value defined as features in ftsSoftware.h or
+ * the following values
+ */
+
+/** @defgroup mode_section IC Status Mode
+ * Bitmask which keeps track of the features and working mode enabled in the
+ * IC.
+ * The meaning of the the LSB of the bitmask must be interpreted considering
+ * that the value defined in @link feat_opt Feature Selection Option @endlink
+ * correspond to the position of the corresponding bit in the mask
+ * @{
+ */
+#define MODE_NOTHING 0x00000000 /* /< nothing enabled (sense off) */
+#define MODE_ACTIVE(_mask, _sett) \
+ (_mask |= (SCAN_MODE_ACTIVE << 24) | (_sett << 16))
+/* /< store the status of scan mode active and its setting */
+#define MODE_LOW_POWER(_mask, _sett) \
+ (_mask |= (SCAN_MODE_LOW_POWER << 24) | (_sett << 16))
+/* /< store the status of scan mode low power and its setting */
+#define IS_POWER_MODE(_mask, _mode) ((_mask&(_mode<<24)) != 0x00)
+/* /< check the current mode of the IC */
+
+/** @}*/
+
+#define CMD_STR_LEN 32 /* /< max number of parameters that can accept
+ * the
+ * MP file node (stm_fts_cmd) */
+
+#define TSP_BUF_SIZE PAGE_SIZE /* /< max number of bytes printable on
+ * the shell in the normal file nodes
+ **/
+
+
+/**
+ * Struct which contains information about the HW platform and set up
+ */
+struct fts_hw_platform_data {
+ int (*power) (bool on);
+ int switch_gpio;/* (optional) I2C switch */
+ int irq_gpio; /* /< number of the gpio associated to the interrupt pin
+ * */
+ int reset_gpio; /* /< number of the gpio associated to the reset pin */
+ const char *vdd_reg_name; /* /< name of the VDD regulator */
+ const char *avdd_reg_name; /* /< name of the AVDD regulator */
+ const char *fw_name;
+ int x_axis_max;
+ int y_axis_max;
+};
+
+/* Bits for the bus reference mask */
+enum {
+ FTS_BUS_REF_SCREEN_ON = 0x01,
+ FTS_BUS_REF_IRQ = 0x02,
+ FTS_BUS_REF_FW_UPDATE = 0x04,
+ FTS_BUS_REF_SYSFS = 0x08,
+ FTS_BUS_REF_FORCE_ACTIVE = 0x10
+};
+
+/*
+ * Forward declaration
+ */
+struct fts_ts_info;
+
+/*
+ * Dispatch event handler
+ * Return true if the handler has processed a pointer event
+ */
+typedef bool (*event_dispatch_handler_t)
+ (struct fts_ts_info *info, unsigned char *data);
+
+/**
+ * Driver touch simulation details
+ */
+struct fts_touchsim{
+ /* touch simulation coordinates */
+ int x, y, x_step, y_step;
+
+ /* timer to run the touch simulation code */
+ struct hrtimer hr_timer;
+
+ struct work_struct work;
+ struct workqueue_struct *wq;
+
+ /* True if the touch simulation is currently running */
+ bool is_running;
+};
+
+/**
+ * FTS capacitive touch screen device information
+ * - dev Pointer to the structure device \n
+ * - client client structure \n
+ * - input_dev Input device structure \n
+ * - work Work thread \n
+ * - event_wq Event queue for work thread \n
+ * - event_dispatch_table Event dispatch table handlers \n
+ * - attrs SysFS attributes \n
+ * - mode Device operating mode (bitmask) \n
+ * - touch_id Bitmask for touch id (mapped to input slots) \n
+ * - stylus_id Bitmask for tracking the stylus touches (mapped using the
+ * touchId) \n
+ * - timer Timer when operating in polling mode \n
+ * - power Power on/off routine \n
+ * - board HW info retrieved from device tree \n
+ * - vdd_reg DVDD power regulator \n
+ * - avdd_reg AVDD power regulator \n
+ * - resume_bit Indicate if screen off/on \n
+ * - fwupdate_stat Store the result of a fw update triggered by the host \n
+ * - notifier Used for be notified from a suspend/resume event \n
+ * - sensor_sleep true suspend was called, false resume was called \n
+ * - wakesrc Wakeup Source struct \n
+ * - input_report_mutex mutex for handling the pressure of keys \n
+ * - series_of_switches to store the enabling status of a particular feature
+ * from the host \n
+ * - tbn Touch Bus Negotiator context
+ */
+struct fts_ts_info {
+ struct device *dev; /* Pointer to the device */
+#ifdef I2C_INTERFACE
+ struct i2c_client *client; /* I2C client structure */
+#else
+ struct spi_device *client; /* SPI client structure */
+#endif
+ struct input_dev *input_dev; /* Input device structure */
+
+ struct work_struct suspend_work; /* Suspend work thread */
+ struct work_struct resume_work; /* Resume work thread */
+ struct workqueue_struct *event_wq; /* Used for event handler, */
+ /* suspend, resume threads */
+
+ struct completion bus_resumed; /* resume_work complete */
+
+ struct pm_qos_request pm_qos_req;
+
+#ifndef FW_UPDATE_ON_PROBE
+ struct delayed_work fwu_work; /* Work for fw update */
+ struct workqueue_struct *fwu_workqueue; /* Fw update work queue */
+#endif
+ event_dispatch_handler_t *event_dispatch_table; /* Dispatch table */
+
+ struct attribute_group attrs; /* SysFS attributes */
+
+ unsigned int mode; /* Device operating mode */
+ /* MSB - active or lpm */
+ unsigned long touch_id; /* Bitmask for touch id */
+#ifdef STYLUS_MODE
+ unsigned long stylus_id; /* Bitmask for the stylus */
+#endif
+
+ ktime_t timestamp; /* time that the event was first received from the
+ touch IC, acquired during hard interrupt, in CLOCK_MONOTONIC */
+
+ struct fts_hw_platform_data *board; /* HW info from device tree */
+ struct regulator *vdd_reg; /* DVDD power regulator */
+ struct regulator *avdd_reg; /* AVDD power regulator */
+
+ struct mutex bus_mutex; /* Protect access to the bus */
+ unsigned int bus_refmask; /* References to the bus */
+
+ int resume_bit; /* Indicate if screen off/on */
+ int fwupdate_stat; /* Result of a fw update */
+ int reflash_fw; /* Attempt to reflash fw */
+
+ struct notifier_block notifier; /* Notify on suspend/resume */
+ bool sensor_sleep; /* True if suspend called */
+ struct wakeup_source *wakesrc; /* Wake Lock struct */
+
+ /* input lock */
+ struct mutex input_report_mutex; /* Mutex for pressure report */
+
+ /* switches for features */
+ int gesture_enabled; /* Gesture during suspend */
+ int glove_enabled; /* Glove mode */
+ int charger_enabled; /* Charger mode */
+ int stylus_enabled; /* Stylus mode */
+ int cover_enabled; /* Cover mode */
+ int grip_enabled; /* Grip mode */
+
+#ifdef CONFIG_TOUCHSCREEN_TBN
+ struct tbn_context *tbn;
+#endif
+
+ /* Allow only one thread to execute diag command code*/
+ struct mutex diag_cmd_lock;
+ /* Allow one process to open procfs node */
+ bool diag_node_open;
+
+ /* Touch simulation details */
+ struct fts_touchsim touchsim;
+
+ /* Preallocated i/o read buffer */
+ u8 io_read_buf[READ_CHUNK + DUMMY_FIFO];
+ /* Preallocated i/o write buffer */
+ u8 io_write_buf[WRITE_CHUNK + BITS_64 + DUMMY_FIFO];
+ /* Preallocated i/o extra write buffer */
+ u8 io_extra_write_buf[WRITE_CHUNK + BITS_64 + DUMMY_FIFO];
+
+};
+
+int fts_chip_powercycle(struct fts_ts_info *info);
+extern int input_register_notifier_client(struct notifier_block *nb);
+extern int input_unregister_notifier_client(struct notifier_block *nb);
+
+/* export declaration of functions in fts_proc.c */
+extern int fts_proc_init(void);
+extern int fts_proc_remove(void);
+
+/* Bus reference tracking */
+int fts_set_bus_ref(struct fts_ts_info *info, u16 ref, bool enable);
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_fw.h b/drivers/input/touchscreen/stm/fts_fw.h
new file mode 100644
index 00000000000..b1d7c8d5717
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_fw.h
@@ -0,0 +1,6146 @@
+#ifndef FTS_FW_V5_H
+#define FTS_FW_V5_H
+//This is an auto generated header file
+//--->Remember to change the name of the two variables!<---
+const uint32_t myArray_size = 98168;
+
+const uint8_t myArray[] = {
+ 0x55, 0xAA, 0x55, 0xAA, 0x01, 0x00, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x74, 0x01, 0x00,
+ 0x60, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x13, 0x78, 0xF8,
+ 0x65, 0xFF, 0xBA, 0x4A, 0x34, 0x5D, 0x00, 0x00, 0x9A, 0x00, 0x45, 0xB5, 0xCB, 0xA2, 0xFF, 0xFF,
+ 0x00, 0x04, 0x10, 0x00, 0xE1, 0x01, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x53, 0x02, 0x00, 0x00,
+ 0x6D, 0x02, 0x00, 0x00, 0x87, 0x02, 0x00, 0x00, 0xA1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x43, 0x01, 0x00,
+ 0xFF, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x02, 0x00, 0x00, 0x07, 0x44, 0x01, 0x00,
+ 0x0F, 0x44, 0x01, 0x00, 0x1D, 0x44, 0x01, 0x00, 0x2B, 0x44, 0x01, 0x00, 0x39, 0x44, 0x01, 0x00,
+ 0x47, 0x44, 0x01, 0x00, 0x55, 0x44, 0x01, 0x00, 0x63, 0x44, 0x01, 0x00, 0x71, 0x44, 0x01, 0x00,
+ 0x7F, 0x44, 0x01, 0x00, 0xC9, 0x02, 0x00, 0x00, 0x8D, 0x44, 0x01, 0x00, 0x9B, 0x44, 0x01, 0x00,
+ 0xA9, 0x44, 0x01, 0x00, 0xB7, 0x44, 0x01, 0x00, 0xC5, 0x44, 0x01, 0x00, 0xCD, 0x44, 0x01, 0x00,
+ 0xDB, 0x44, 0x01, 0x00, 0xE3, 0x44, 0x01, 0x00, 0xEB, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x44, 0x01, 0x00,
+ 0xFB, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x32, 0x02, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xF0, 0x02, 0xF8, 0x00, 0xF0, 0x68, 0xF8, 0x0A, 0xA0, 0x90, 0xE8, 0x00, 0x0C, 0x82, 0x44,
+ 0x83, 0x44, 0xAA, 0xF1, 0x01, 0x07, 0xDA, 0x45, 0x01, 0xD1, 0x00, 0xF0, 0x5D, 0xF8, 0xAF, 0xF2,
+ 0x09, 0x0E, 0xBA, 0xE8, 0x0F, 0x00, 0x13, 0xF0, 0x01, 0x0F, 0x18, 0xBF, 0xFB, 0x1A, 0x43, 0xF0,
+ 0x01, 0x03, 0x18, 0x47, 0x08, 0x73, 0x01, 0x00, 0x38, 0x73, 0x01, 0x00, 0x0A, 0x44, 0x4F, 0xF0,
+ 0x00, 0x0C, 0x10, 0xF8, 0x01, 0x3B, 0x13, 0xF0, 0x07, 0x04, 0x08, 0xBF, 0x10, 0xF8, 0x01, 0x4B,
+ 0x1D, 0x11, 0x08, 0xBF, 0x10, 0xF8, 0x01, 0x5B, 0x64, 0x1E, 0x05, 0xD0, 0x10, 0xF8, 0x01, 0x6B,
+ 0x64, 0x1E, 0x01, 0xF8, 0x01, 0x6B, 0xF9, 0xD1, 0x13, 0xF0, 0x08, 0x0F, 0x1E, 0xBF, 0x10, 0xF8,
+ 0x01, 0x4B, 0xAD, 0x1C, 0x0C, 0x1B, 0x09, 0xD1, 0x6D, 0x1E, 0x58, 0xBF, 0x01, 0xF8, 0x01, 0xCB,
+ 0xFA, 0xD5, 0x05, 0xE0, 0x14, 0xF8, 0x01, 0x6B, 0x01, 0xF8, 0x01, 0x6B, 0x6D, 0x1E, 0xF9, 0xD5,
+ 0x91, 0x42, 0xD6, 0xD3, 0x70, 0x47, 0x00, 0x00, 0x10, 0x3A, 0x24, 0xBF, 0x78, 0xC8, 0x78, 0xC1,
+ 0xFA, 0xD8, 0x52, 0x07, 0x24, 0xBF, 0x30, 0xC8, 0x30, 0xC1, 0x44, 0xBF, 0x04, 0x68, 0x0C, 0x60,
+ 0x70, 0x47, 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x10, 0x3A, 0x28, 0xBF,
+ 0x78, 0xC1, 0xFB, 0xD8, 0x52, 0x07, 0x28, 0xBF, 0x30, 0xC1, 0x48, 0xBF, 0x0B, 0x60, 0x70, 0x47,
+ 0x1F, 0xB5, 0x1F, 0xBD, 0x10, 0xB5, 0x10, 0xBD, 0xDF, 0xF8, 0x0C, 0xD0, 0xFF, 0xF7, 0xF8, 0xFF,
+ 0x14, 0xF0, 0xA2, 0xF9, 0x16, 0xF0, 0xC6, 0xFB, 0x00, 0x04, 0x10, 0x00, 0x03, 0xB4, 0xFF, 0xF7,
+ 0xF1, 0xFF, 0x03, 0xBC, 0x16, 0xF0, 0xC4, 0xFB, 0x40, 0xBA, 0x70, 0x47, 0xC0, 0xBA, 0x70, 0x47,
+ 0x12, 0x48, 0x13, 0x49, 0xA1, 0xEB, 0x00, 0x01, 0x4F, 0xF0, 0x20, 0x03, 0x91, 0xFB, 0xF3, 0xF2,
+ 0x02, 0xFB, 0x13, 0x11, 0x4F, 0xF0, 0xCC, 0x33, 0x4F, 0xF0, 0xCC, 0x34, 0x4F, 0xF0, 0xCC, 0x35,
+ 0x4F, 0xF0, 0xCC, 0x36, 0x4F, 0xF0, 0xCC, 0x37, 0x4F, 0xF0, 0xCC, 0x38, 0x4F, 0xF0, 0xCC, 0x39,
+ 0x4F, 0xF0, 0xCC, 0x3A, 0xA0, 0xE8, 0xF8, 0x07, 0x01, 0x3A, 0xFB, 0xD1, 0x19, 0xB1, 0x40, 0xF8,
+ 0x04, 0xAB, 0x04, 0x39, 0xFB, 0xD1, 0x03, 0x48, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x04, 0x10, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3,
+ 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x01, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x10, 0xF0,
+ 0x0B, 0xB8, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80,
+ 0x4F, 0xF0, 0x02, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, 0xFE, 0xBF, 0x1E, 0xF0, 0x04, 0x0F,
+ 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x03, 0x01, 0x4F, 0xF0,
+ 0x00, 0x02, 0x0F, 0xF0, 0xF1, 0xBF, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80,
+ 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x04, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, 0xE4, 0xBF,
+ 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3, 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0,
+ 0x05, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0, 0xD7, 0xBF, 0x00, 0xB5, 0x14, 0xF0, 0x94, 0xF8,
+ 0x5D, 0xF8, 0x04, 0xEB, 0x00, 0xF0, 0x32, 0xB8, 0x1E, 0xF0, 0x04, 0x0F, 0x0C, 0xBF, 0xEF, 0xF3,
+ 0x08, 0x80, 0xEF, 0xF3, 0x09, 0x80, 0x4F, 0xF0, 0x06, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0x0F, 0xF0,
+ 0xC3, 0xBF, 0x00, 0x00, 0x0A, 0x48, 0x4F, 0xF0, 0xFF, 0x01, 0x01, 0x70, 0x4F, 0xF0, 0x00, 0x00,
+ 0x80, 0xF3, 0x11, 0x88, 0x4F, 0xF0, 0x00, 0x00, 0x80, 0xF3, 0x09, 0x88, 0x05, 0x48, 0x4F, 0xF0,
+ 0x02, 0x01, 0x01, 0x70, 0x62, 0xB6, 0x04, 0x48, 0x4F, 0xF0, 0x80, 0x51, 0x01, 0x60, 0x70, 0x47,
+ 0x22, 0xED, 0x00, 0xE0, 0x18, 0x08, 0x10, 0x00, 0x04, 0xED, 0x00, 0xE0, 0x02, 0x48, 0x4F, 0xF0,
+ 0x80, 0x51, 0x01, 0x60, 0x70, 0x47, 0x00, 0x00, 0x04, 0xED, 0x00, 0xE0, 0x4F, 0xF0, 0x20, 0x00,
+ 0x80, 0xF3, 0x11, 0x88, 0xEF, 0xF3, 0x09, 0x80, 0x98, 0xB1, 0x12, 0x48, 0x00, 0x68, 0x12, 0x49,
+ 0x09, 0x68, 0x88, 0x42, 0x17, 0xD0, 0xEF, 0xF3, 0x09, 0x80, 0x0E, 0x49, 0x09, 0x68, 0x20, 0xE9,
+ 0xF0, 0x0F, 0x88, 0x60, 0x00, 0xB5, 0x0B, 0x48, 0x00, 0x68, 0x14, 0xF0, 0x6B, 0xF9, 0x5D, 0xF8,
+ 0x04, 0xEB, 0x08, 0x48, 0x08, 0x49, 0x0A, 0x68, 0x02, 0x60, 0x00, 0x68, 0x81, 0x68, 0xB1, 0xE8,
+ 0xF0, 0x0F, 0x81, 0xF3, 0x09, 0x88, 0x4E, 0xF0, 0x04, 0x0E, 0x4F, 0xF0, 0x00, 0x00, 0x80, 0xF3,
+ 0x11, 0x88, 0x70, 0x47, 0x1C, 0x08, 0x10, 0x00, 0x20, 0x08, 0x10, 0x00, 0xEF, 0xF3, 0x11, 0x80,
+ 0x4F, 0xF0, 0x20, 0x01, 0x81, 0xF3, 0x11, 0x88, 0x70, 0x47, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x00,
+ 0x80, 0xF3, 0x11, 0x88, 0x70, 0x47, 0x00, 0x00, 0x62, 0xB6, 0x70, 0x47, 0x72, 0xB6, 0x70, 0x47,
+ 0x40, 0x1E, 0xFD, 0xD1, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFD, 0x48,
+ 0x16, 0xF0, 0x45, 0xFA, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x14, 0xF0, 0x6B, 0xB9,
+ 0x38, 0xB5, 0x04, 0x46, 0xF8, 0x48, 0xF7, 0x4D, 0x20, 0x60, 0x20, 0x46, 0x13, 0xF0, 0xD3, 0xFC,
+ 0x00, 0x22, 0x6B, 0x46, 0x01, 0x21, 0x10, 0x46, 0x14, 0xF0, 0xA6, 0xF9, 0x01, 0x21, 0x00, 0x20,
+ 0x14, 0xF0, 0x85, 0xF9, 0x28, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x0F, 0xF0, 0x8C, 0xFF, 0xEC, 0xE7,
+ 0x38, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0xB4, 0x83, 0x82, 0x46, 0x01, 0x27, 0xD8, 0xF8,
+ 0x00, 0x00, 0xEB, 0x4D, 0x46, 0x46, 0x90, 0xF8, 0x31, 0x40, 0x10, 0xF8, 0x30, 0x1F, 0x90, 0xF8,
+ 0x31, 0x00, 0x4C, 0x43, 0x00, 0xF0, 0x03, 0x00, 0x87, 0x40, 0xA1, 0x00, 0x28, 0x46, 0x16, 0xF0,
+ 0x6A, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0xE5, 0xF9,
+ 0x00, 0x26, 0xDF, 0xF8, 0x70, 0x93, 0x12, 0xE0, 0xDA, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0xC0, 0xFF,
+ 0x00, 0x20, 0xD9, 0xF8, 0x08, 0x10, 0x07, 0xE0, 0x55, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30,
+ 0x1A, 0x44, 0x45, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0xA0, 0x42, 0xF5, 0xDB, 0x76, 0x1C, 0xBE, 0x42,
+ 0xEA, 0xDB, 0x40, 0x46, 0x0A, 0xE0, 0x00, 0xBF, 0x02, 0x68, 0x55, 0xF8, 0x24, 0x10, 0x92, 0xF8,
+ 0x61, 0x20, 0x02, 0xF0, 0x03, 0x02, 0x11, 0x41, 0x2A, 0xF8, 0x14, 0x10, 0x64, 0x1E, 0xF3, 0xD2,
+ 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x20, 0xB3, 0x4F, 0xF0, 0x01, 0x09,
+ 0xC7, 0x4E, 0xDB, 0xF8, 0x00, 0x00, 0x9F, 0xB0, 0x90, 0xF8, 0x61, 0x10, 0x90, 0xF8, 0x31, 0x40,
+ 0xC1, 0xF3, 0x81, 0x08, 0x90, 0xF8, 0x30, 0x50, 0x09, 0xFA, 0x08, 0xFA, 0x60, 0x19, 0x81, 0x00,
+ 0x06, 0xEB, 0x84, 0x07, 0x30, 0x46, 0x16, 0xF0, 0x1E, 0xFA, 0xBA, 0x48, 0x34, 0x30, 0x13, 0xF0,
+ 0x35, 0xFC, 0xB8, 0x49, 0x34, 0x31, 0x81, 0xF8, 0x06, 0x90, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8,
+ 0x60, 0x20, 0x92, 0x07, 0x01, 0xD5, 0x81, 0xF8, 0x04, 0x90, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07,
+ 0x01, 0xD0, 0x00, 0xF0, 0x8A, 0xF9, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x60, 0x00, 0xC0, 0x07,
+ 0x03, 0xD0, 0xAC, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0x63, 0xFF, 0x00, 0x20, 0x2B, 0xE0, 0xA9, 0x48,
+ 0x34, 0x30, 0xFF, 0xF7, 0x5D, 0xFF, 0xDF, 0xF8, 0x9C, 0xB2, 0x62, 0x00, 0x13, 0xA8, 0xDB, 0xF8,
+ 0x18, 0x10, 0x16, 0xF0, 0x4F, 0xF9, 0x6A, 0x00, 0x68, 0x46, 0xDB, 0xF8, 0x1C, 0x10, 0x16, 0xF0,
+ 0x49, 0xF9, 0x20, 0x46, 0x13, 0xAA, 0x06, 0xE0, 0x56, 0xF8, 0x20, 0x10, 0x32, 0xF9, 0x10, 0x30,
+ 0x19, 0x44, 0x46, 0xF8, 0x20, 0x10, 0x40, 0x1E, 0xF6, 0xD2, 0x28, 0x46, 0x69, 0x46, 0x06, 0xE0,
+ 0x57, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, 0x1A, 0x44, 0x47, 0xF8, 0x20, 0x20, 0x40, 0x1E,
+ 0xF6, 0xD2, 0x09, 0xF1, 0x01, 0x00, 0x81, 0x46, 0x50, 0x45, 0xD0, 0xDB, 0x95, 0x49, 0x05, 0xE0,
+ 0x56, 0xF8, 0x24, 0x00, 0x40, 0xFA, 0x08, 0xF0, 0x21, 0xF8, 0x14, 0x00, 0x64, 0x1E, 0xF7, 0xD2,
+ 0x91, 0x49, 0x05, 0xE0, 0x57, 0xF8, 0x25, 0x00, 0x40, 0xFA, 0x08, 0xF0, 0x21, 0xF8, 0x15, 0x00,
+ 0x6D, 0x1E, 0xF7, 0xD2, 0x1F, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xFF, 0x5F, 0xDF, 0xF8,
+ 0x1C, 0x82, 0x87, 0x4F, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x31, 0x40, 0x90, 0xF8, 0x30, 0x50,
+ 0x07, 0xEB, 0x84, 0x0A, 0x60, 0x19, 0x81, 0x00, 0x04, 0xFB, 0x05, 0xFB, 0x0A, 0xEB, 0x85, 0x06,
+ 0x38, 0x46, 0x16, 0xF0, 0xA0, 0xF9, 0x4F, 0xEA, 0x8B, 0x01, 0x30, 0x46, 0x16, 0xF0, 0x9B, 0xF9,
+ 0x78, 0x48, 0x34, 0x30, 0x13, 0xF0, 0xB2, 0xFB, 0x76, 0x48, 0x4F, 0xF0, 0x01, 0x09, 0x34, 0x30,
+ 0x80, 0xF8, 0x06, 0x90, 0x80, 0xF8, 0x04, 0x90, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xB0, 0x00,
+ 0xC0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0x09, 0xF9, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x60, 0x00,
+ 0xC0, 0x07, 0x03, 0xD0, 0x6B, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0xE2, 0xFE, 0xD8, 0xF8, 0x00, 0x00,
+ 0x90, 0xF8, 0x61, 0x00, 0xC0, 0xF3, 0x81, 0x01, 0x02, 0x91, 0x00, 0xF0, 0x03, 0x01, 0x03, 0x91,
+ 0x02, 0x99, 0x48, 0x46, 0x09, 0xFA, 0x01, 0xF9, 0x03, 0x99, 0x88, 0x40, 0x01, 0x90, 0x00, 0x20,
+ 0x31, 0xE0, 0x60, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0xCB, 0xFE, 0x5E, 0x48, 0xD0, 0xE9, 0x06, 0x32,
+ 0x81, 0x68, 0x20, 0x46, 0x07, 0xE0, 0x00, 0xBF, 0x57, 0xF8, 0x20, 0xC0, 0x33, 0xF9, 0x10, 0x80,
+ 0xC4, 0x44, 0x47, 0xF8, 0x20, 0xC0, 0x40, 0x1E, 0xF6, 0xD2, 0x28, 0x46, 0x07, 0xE0, 0x00, 0xBF,
+ 0x5A, 0xF8, 0x20, 0x30, 0x32, 0xF9, 0x10, 0xC0, 0x9C, 0x44, 0x4A, 0xF8, 0x20, 0xC0, 0x40, 0x1E,
+ 0xF6, 0xD2, 0xDD, 0xE9, 0x00, 0x02, 0x90, 0x42, 0x0B, 0xDA, 0x58, 0x46, 0x07, 0xE0, 0x00, 0xBF,
+ 0x56, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, 0x1A, 0x44, 0x46, 0xF8, 0x20, 0x20, 0x40, 0x1E,
+ 0xF6, 0xD2, 0x00, 0x98, 0x40, 0x1C, 0x00, 0x90, 0x48, 0x45, 0xCA, 0xDB, 0x01, 0x98, 0x48, 0x45,
+ 0x1D, 0xDD, 0x44, 0x48, 0x00, 0x21, 0x34, 0x30, 0x88, 0x46, 0x81, 0x71, 0x01, 0x99, 0xA1, 0xEB,
+ 0x09, 0x09, 0x12, 0xE0, 0x3F, 0x48, 0x34, 0x30, 0xFF, 0xF7, 0x8A, 0xFE, 0x3D, 0x48, 0x81, 0x68,
+ 0x58, 0x46, 0x06, 0xE0, 0x56, 0xF8, 0x20, 0x20, 0x31, 0xF9, 0x10, 0x30, 0x1A, 0x44, 0x46, 0xF8,
+ 0x20, 0x20, 0x40, 0x1E, 0xF6, 0xD2, 0x08, 0xF1, 0x01, 0x08, 0xC1, 0x45, 0xEA, 0xDC, 0x39, 0x49,
+ 0x06, 0xE0, 0x00, 0xBF, 0x57, 0xF8, 0x24, 0x00, 0x02, 0x9A, 0x10, 0x41, 0x21, 0xF8, 0x14, 0x00,
+ 0x64, 0x1E, 0xF7, 0xD2, 0x34, 0x49, 0x05, 0xE0, 0x5A, 0xF8, 0x25, 0x00, 0x02, 0x9A, 0x10, 0x41,
+ 0x21, 0xF8, 0x15, 0x00, 0x6D, 0x1E, 0xF7, 0xD2, 0x58, 0x46, 0x30, 0x4A, 0x06, 0xE0, 0x00, 0xBF,
+ 0x56, 0xF8, 0x20, 0x10, 0x03, 0x9B, 0x19, 0x41, 0x22, 0xF8, 0x10, 0x10, 0x40, 0x1E, 0xF7, 0xD2,
+ 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x00, 0x20, 0x14, 0xF0, 0x5B, 0xF8,
+ 0x02, 0x20, 0x14, 0xF0, 0x58, 0xF8, 0x03, 0x20, 0x14, 0xF0, 0x55, 0xF8, 0x24, 0x4E, 0x00, 0x20,
+ 0x30, 0x70, 0x1C, 0x48, 0x34, 0x30, 0x13, 0xF0, 0xF9, 0xFA, 0x1C, 0x48, 0x21, 0x4F, 0xDF, 0xF8,
+ 0x88, 0x80, 0x00, 0x68, 0x4F, 0xF0, 0x01, 0x04, 0x90, 0xF8, 0x60, 0x00, 0x80, 0x07, 0x4F, 0xEA,
+ 0x05, 0x70, 0x0A, 0xD5, 0x00, 0x28, 0x0F, 0xDA, 0xA8, 0x07, 0x08, 0xD5, 0x34, 0x70, 0xFF, 0xF7,
+ 0x14, 0xFF, 0x3C, 0x70, 0x88, 0xF8, 0x00, 0x40, 0x01, 0xE0, 0x00, 0x28, 0x04, 0xDA, 0x30, 0x78,
+ 0x10, 0xB9, 0xFF, 0xF7, 0x87, 0xFE, 0x3C, 0x70, 0x0A, 0x4F, 0xA8, 0x07, 0x07, 0xF1, 0x34, 0x07,
+ 0x26, 0xD5, 0x30, 0x78, 0x70, 0xBB, 0x38, 0x46, 0x13, 0xF0, 0xD0, 0xFA, 0x3C, 0x71, 0x0B, 0x48,
+ 0xFF, 0xF7, 0x2F, 0xFE, 0x09, 0x48, 0x00, 0xF0, 0x3C, 0xF8, 0x0C, 0x49, 0x08, 0x70, 0x88, 0xF8,
+ 0x00, 0x40, 0x1F, 0xE0, 0x38, 0x08, 0x10, 0x00, 0xB9, 0x03, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x84, 0x5A, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, 0x2E, 0x44, 0x01, 0x20,
+ 0x00, 0x04, 0x10, 0x00, 0x51, 0x07, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, 0x52, 0x07, 0x10, 0x00,
+ 0x68, 0x07, 0x07, 0xD5, 0x38, 0x48, 0x13, 0xF0, 0xA9, 0xFA, 0x04, 0x20, 0x38, 0x71, 0x37, 0x48,
+ 0xFF, 0xF7, 0x07, 0xFE, 0x03, 0x20, 0x14, 0xF0, 0x11, 0xF8, 0x02, 0x20, 0x14, 0xF0, 0x0E, 0xF8,
+ 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0x20, 0x14, 0xF0, 0x09, 0xB8, 0x31, 0x48, 0x00, 0x68, 0x90, 0xF8,
+ 0xB0, 0x00, 0x81, 0x07, 0x2C, 0x48, 0x01, 0xD5, 0x02, 0x21, 0x00, 0xE0, 0x01, 0x21, 0xC1, 0x72,
+ 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x43, 0x2A, 0x49, 0x4F, 0xF0, 0x00, 0x09, 0xCC, 0x46, 0x0F, 0x68,
+ 0x4B, 0x46, 0x97, 0xF8, 0x31, 0x20, 0x97, 0xF8, 0x30, 0x60, 0x97, 0xF8, 0x60, 0x40, 0x02, 0xFB,
+ 0x06, 0xF1, 0x09, 0xB2, 0x64, 0x07, 0x37, 0xD5, 0x22, 0x4C, 0x24, 0x68, 0x25, 0x8E, 0x8D, 0x42,
+ 0x32, 0xD1, 0x32, 0x34, 0x28, 0xE0, 0x35, 0x46, 0x20, 0xE0, 0x00, 0xBF, 0x34, 0xF8, 0x15, 0x10,
+ 0x30, 0xF8, 0x15, 0x80, 0xA1, 0xEB, 0x08, 0x01, 0x09, 0xB2, 0x00, 0x29, 0x01, 0xDB, 0x88, 0x46,
+ 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x08, 0xE0, 0x45, 0x07, 0xDD, 0x00, 0x29, 0x01, 0xDB, 0x8C, 0x46,
+ 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42,
+ 0xB7, 0xF8, 0x63, 0x80, 0x41, 0x45, 0x01, 0xDD, 0x5B, 0x1C, 0x9B, 0xB2, 0x6D, 0x1E, 0xDD, 0xD1,
+ 0x04, 0xEB, 0x46, 0x04, 0x00, 0xEB, 0x46, 0x00, 0x52, 0x1E, 0xD4, 0xD2, 0x97, 0xF8, 0x65, 0x00,
+ 0x98, 0x42, 0x01, 0xD2, 0x4F, 0xF0, 0x01, 0x09, 0x07, 0x48, 0xA0, 0xF8, 0x00, 0xC0, 0x07, 0x48,
+ 0x03, 0x80, 0x48, 0x46, 0xBD, 0xE8, 0xF0, 0x83, 0x6C, 0x08, 0x10, 0x00, 0x2E, 0x44, 0x01, 0x20,
+ 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0x54, 0x07, 0x10, 0x00, 0x56, 0x07, 0x10, 0x00,
+ 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFE, 0x48, 0x15, 0xF0, 0xB1, 0xFF, 0x01, 0x21, 0xBD, 0xE8,
+ 0x10, 0x40, 0x00, 0x20, 0x13, 0xF0, 0xD7, 0xBE, 0x38, 0xB5, 0x04, 0x46, 0xF9, 0x48, 0x20, 0x60,
+ 0xF9, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x01, 0xD0, 0x01, 0x20, 0xE0, 0x72,
+ 0xF3, 0x4D, 0x20, 0x46, 0x13, 0xF0, 0x37, 0xFA, 0x00, 0x22, 0x6B, 0x46, 0x01, 0x21, 0x10, 0x46,
+ 0x13, 0xF0, 0x0A, 0xFF, 0x01, 0x21, 0x00, 0x20, 0x13, 0xF0, 0xE9, 0xFE, 0x28, 0x78, 0x00, 0x28,
+ 0x02, 0xD0, 0x0F, 0xF0, 0xF0, 0xFC, 0xEC, 0xE7, 0x38, 0xBD, 0x2D, 0xE9, 0xFF, 0x41, 0x00, 0x24,
+ 0xDD, 0xE9, 0x0A, 0x76, 0x08, 0x21, 0x68, 0x46, 0x14, 0xF0, 0x7C, 0xFC, 0x05, 0x46, 0x08, 0x21,
+ 0x02, 0xA8, 0x14, 0xF0, 0x77, 0xFC, 0x02, 0x46, 0x00, 0x20, 0x6F, 0xF0, 0x7E, 0x0E, 0x14, 0xE0,
+ 0x00, 0x21, 0x00, 0xFB, 0x02, 0xF3, 0x0D, 0xE0, 0x07, 0xEB, 0x01, 0x0C, 0x13, 0xF9, 0x0C, 0xC0,
+ 0xB4, 0x44, 0xF4, 0x45, 0x01, 0xDA, 0x01, 0x24, 0x03, 0xE0, 0xBC, 0xF1, 0x7F, 0x0F, 0x00, 0xDD,
+ 0x02, 0x24, 0x49, 0x1C, 0x91, 0x42, 0xEF, 0xDB, 0x40, 0x1C, 0xA8, 0x42, 0xE8, 0xDB, 0x20, 0x46,
+ 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFF, 0x41, 0x0A, 0xAC, 0x08, 0x21, 0x94, 0xE8,
+ 0xC0, 0x01, 0x00, 0x24, 0x68, 0x46, 0x14, 0xF0, 0x4D, 0xFC, 0x05, 0x46, 0x08, 0x21, 0x02, 0xA8,
+ 0x14, 0xF0, 0x48, 0xFC, 0x01, 0x46, 0x00, 0x20, 0x08, 0xE0, 0x32, 0x56, 0xD2, 0x19, 0x01, 0xD5,
+ 0x01, 0x24, 0x02, 0xE0, 0xFF, 0x2A, 0x00, 0xDD, 0x02, 0x24, 0x40, 0x1C, 0xA8, 0x42, 0xF4, 0xDB,
+ 0x00, 0x20, 0x0A, 0xE0, 0x2A, 0x18, 0xB2, 0x56, 0x12, 0xEB, 0x08, 0x02, 0x01, 0xD5, 0x01, 0x24,
+ 0x02, 0xE0, 0xFF, 0x2A, 0x00, 0xDD, 0x02, 0x24, 0x40, 0x1C, 0x88, 0x42, 0xF2, 0xDB, 0x20, 0x46,
+ 0xCE, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x13, 0xF0, 0x3F, 0xFA, 0x04, 0x46, 0x0D, 0x46,
+ 0x13, 0xF0, 0x3D, 0xFA, 0xDF, 0xF8, 0xE0, 0x82, 0x06, 0x46, 0x0F, 0x46, 0xD8, 0xF8, 0x00, 0x00,
+ 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0,
+ 0x79, 0xFD, 0x04, 0x46, 0x0D, 0x46, 0xB0, 0x48, 0x01, 0x68, 0x91, 0xF8, 0x31, 0x80, 0x91, 0xF8,
+ 0x30, 0xA0, 0x01, 0x21, 0x08, 0xFB, 0x0A, 0xF0, 0x05, 0x90, 0x06, 0xA8, 0x0D, 0xF0, 0x4A, 0xFF,
+ 0xDF, 0xF8, 0xA8, 0x92, 0x00, 0x20, 0xDF, 0xF8, 0xA8, 0xB2, 0xD9, 0xF8, 0x00, 0x10, 0x06, 0x9B,
+ 0x32, 0x46, 0x91, 0xF9, 0x1B, 0x10, 0x03, 0x90, 0xCD, 0xF8, 0x00, 0xB0, 0xCD, 0xE9, 0x01, 0x31,
+ 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0xD4, 0xFD, 0x01, 0x20, 0x03, 0x90, 0x00, 0x21,
+ 0x06, 0x9B, 0xCD, 0xF8, 0x00, 0xB0, 0xCD, 0xE9, 0x01, 0x31, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46,
+ 0x29, 0x46, 0x10, 0xF0, 0xC6, 0xFD, 0x96, 0x48, 0x34, 0x30, 0x13, 0xF0, 0x57, 0xF9, 0x94, 0x49,
+ 0x05, 0x20, 0x34, 0x31, 0x08, 0x71, 0x08, 0x46, 0xFF, 0xF7, 0x2E, 0xFF, 0x90, 0x48, 0x02, 0x21,
+ 0x80, 0x68, 0x00, 0x90, 0x04, 0xA8, 0x0D, 0xF0, 0x15, 0xFF, 0x8F, 0x48, 0x00, 0x68, 0xB0, 0xF9,
+ 0xC2, 0x11, 0x01, 0x91, 0xB0, 0xF9, 0xC4, 0xB1, 0x59, 0x44, 0x49, 0x10, 0x02, 0x91, 0x90, 0xF8,
+ 0xE8, 0x00, 0x80, 0x07, 0x0A, 0xD4, 0xAA, 0xF1, 0x01, 0x01, 0x08, 0xFB, 0x01, 0xF0, 0x05, 0x90,
+ 0x00, 0x99, 0x53, 0x46, 0x42, 0x46, 0x08, 0x46, 0x00, 0xF0, 0xF2, 0xFA, 0xDD, 0xE9, 0x04, 0x12,
+ 0x00, 0x98, 0x11, 0xF0, 0x90, 0xFA, 0x82, 0x46, 0x02, 0x21, 0x04, 0xA8, 0x0D, 0xF0, 0x55, 0xFF,
+ 0x01, 0x99, 0x4F, 0xF0, 0x00, 0x08, 0x8A, 0x45, 0x01, 0xDC, 0xDA, 0x45, 0x0A, 0xDA, 0x7A, 0x48,
+ 0x02, 0x99, 0x00, 0x68, 0xAA, 0xEB, 0x01, 0x01, 0xB0, 0xF8, 0xC6, 0x01, 0x91, 0xFB, 0xF0, 0xF0,
+ 0x4F, 0xFA, 0x80, 0xF8, 0x06, 0x99, 0xCD, 0xE9, 0x00, 0x18, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46,
+ 0x29, 0x46, 0xFF, 0xF7, 0x0A, 0xFF, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, 0x21, 0xD0, 0xD9, 0xF8,
+ 0x00, 0x10, 0x01, 0x20, 0x6E, 0x4A, 0x81, 0xF8, 0x1B, 0x80, 0x03, 0x90, 0x06, 0x9B, 0x8D, 0xE8,
+ 0x0C, 0x01, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0x62, 0xFD, 0xD9, 0xF8,
+ 0x00, 0x00, 0xA5, 0x21, 0x81, 0x76, 0x01, 0x21, 0x06, 0xA8, 0x0D, 0xF0, 0x1E, 0xFF, 0x07, 0xB0,
+ 0xBD, 0xE8, 0xF0, 0x8F, 0xD9, 0xF8, 0x00, 0x10, 0x00, 0x20, 0xC8, 0x76, 0x01, 0x21, 0xB0, 0x20,
+ 0x05, 0xE0, 0xD9, 0xF8, 0x00, 0x10, 0x00, 0x20, 0xC8, 0x76, 0x01, 0x21, 0xB1, 0x20, 0x0F, 0xF0,
+ 0xBB, 0xFB, 0xE4, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x5C, 0x91, 0x8D, 0xB0, 0xD9, 0xF8,
+ 0x00, 0x00, 0x90, 0xF8, 0x31, 0x80, 0x90, 0xF8, 0x30, 0xA0, 0x13, 0xF0, 0x6E, 0xF9, 0x04, 0x46,
+ 0x0D, 0x46, 0x13, 0xF0, 0x6C, 0xF9, 0x06, 0x46, 0xD9, 0xF8, 0x00, 0x00, 0x0F, 0x46, 0x90, 0xF8,
+ 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0xAA, 0xFC,
+ 0x04, 0x46, 0x0D, 0x46, 0x01, 0x21, 0x04, 0xA8, 0x0D, 0xF0, 0x84, 0xFE, 0xDF, 0xF8, 0x1C, 0x91,
+ 0x00, 0x21, 0x04, 0x9B, 0xD9, 0xF8, 0x00, 0x00, 0xDF, 0xF8, 0x18, 0xB1, 0x90, 0xF9, 0x1D, 0x20,
+ 0xCD, 0xE9, 0x02, 0x21, 0xCD, 0xE9, 0x00, 0xB3, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46,
+ 0x10, 0xF0, 0x0F, 0xFD, 0x01, 0x21, 0x00, 0x22, 0x04, 0x9B, 0xCD, 0xE9, 0x02, 0x21, 0xCD, 0xE9,
+ 0x00, 0xB3, 0x32, 0x46, 0x3B, 0x46, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0x02, 0xFD, 0x34, 0x48,
+ 0x34, 0x30, 0x13, 0xF0, 0x93, 0xF8, 0x32, 0x49, 0x06, 0x20, 0x34, 0x31, 0x08, 0x71, 0x08, 0x46,
+ 0xFF, 0xF7, 0x6A, 0xFE, 0x2E, 0x48, 0x02, 0x21, 0x80, 0x68, 0x00, 0x90, 0x0C, 0xA8, 0x0D, 0xF0,
+ 0x51, 0xFE, 0x2D, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0xC8, 0x11, 0xB0, 0xF9, 0xCA, 0x21, 0x11, 0x44,
+ 0x49, 0x10, 0x03, 0x91, 0x08, 0xFB, 0x0A, 0xF1, 0x01, 0x91, 0x90, 0xF8, 0xE8, 0x00, 0x80, 0x07,
+ 0x0A, 0xD4, 0xAA, 0xF1, 0x01, 0x01, 0x08, 0xFB, 0x01, 0xF0, 0x00, 0x99, 0x01, 0x90, 0x53, 0x46,
+ 0x42, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x2C, 0xFA, 0xDD, 0xE9, 0x00, 0x02, 0x0C, 0x99, 0x11, 0xF0,
+ 0xCA, 0xF9, 0x82, 0x46, 0x02, 0x21, 0x0C, 0xA8, 0x0D, 0xF0, 0x8F, 0xFE, 0x1A, 0x48, 0x4F, 0xF0,
+ 0x00, 0x08, 0x00, 0x68, 0xB0, 0xF9, 0xC8, 0x21, 0x52, 0x45, 0x03, 0xDB, 0xB0, 0xF9, 0xCA, 0x21,
+ 0x52, 0x45, 0x08, 0xDD, 0x03, 0x9A, 0xB0, 0xF8, 0xCC, 0x01, 0xAA, 0xEB, 0x02, 0x01, 0x91, 0xFB,
+ 0xF0, 0xF0, 0x4F, 0xFA, 0x80, 0xF8, 0x04, 0x99, 0xCD, 0xE9, 0x00, 0x18, 0x32, 0x46, 0x3B, 0x46,
+ 0x20, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0x41, 0xFE, 0x4F, 0xF4, 0x80, 0x71, 0x01, 0x28, 0x29, 0xD0,
+ 0x02, 0x28, 0x2D, 0xD0, 0xD9, 0xF8, 0x00, 0x10, 0x32, 0x46, 0x81, 0xF8, 0x1D, 0x80, 0x01, 0x21,
+ 0x04, 0x9B, 0xCD, 0xF8, 0x00, 0xB0, 0x03, 0x91, 0xCD, 0xE9, 0x01, 0x38, 0x3B, 0x46, 0x0B, 0xE0,
+ 0x7C, 0x08, 0x10, 0x00, 0xE1, 0x08, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00,
+ 0xFC, 0x4C, 0x01, 0x20, 0x24, 0x52, 0x01, 0x20, 0x20, 0x46, 0x29, 0x46, 0x10, 0xF0, 0x89, 0xFC,
+ 0xD9, 0xF8, 0x00, 0x00, 0xA5, 0x21, 0x01, 0x77, 0x01, 0x21, 0x04, 0xA8, 0x0D, 0xF0, 0x45, 0xFE,
+ 0x0D, 0xB0, 0x25, 0xE7, 0xD9, 0xF8, 0x00, 0x20, 0x00, 0x20, 0x50, 0x77, 0xB0, 0x20, 0x04, 0xE0,
+ 0xD9, 0xF8, 0x00, 0x20, 0x00, 0x20, 0x50, 0x77, 0xB1, 0x20, 0x0F, 0xF0, 0xE5, 0xFA, 0xE7, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x4F, 0xF3, 0x48, 0x8F, 0xB0, 0x00, 0x68, 0x90, 0xF8, 0x31, 0x60, 0x90, 0xF8,
+ 0x30, 0x00, 0x06, 0x90, 0x13, 0xF0, 0x99, 0xF8, 0x80, 0x46, 0x89, 0x46, 0x13, 0xF0, 0x97, 0xF8,
+ 0x04, 0x46, 0x0D, 0x46, 0x01, 0x21, 0x08, 0xA8, 0x0D, 0xF0, 0xBC, 0xFD, 0xEA, 0x48, 0x02, 0xAB,
+ 0x00, 0x27, 0x00, 0x68, 0x08, 0x9A, 0x90, 0xF9, 0x20, 0x10, 0x90, 0xF9, 0x1F, 0x00, 0x83, 0xE8,
+ 0x83, 0x00, 0xE6, 0x48, 0xCD, 0xE9, 0x00, 0x02, 0x0E, 0x90, 0x22, 0x46, 0x2B, 0x46, 0x40, 0x46,
+ 0x49, 0x46, 0x10, 0xF0, 0x97, 0xFC, 0x08, 0x99, 0xCD, 0xE9, 0x01, 0x17, 0x01, 0x20, 0xCD, 0xE9,
+ 0x03, 0x70, 0x0E, 0x98, 0x00, 0x90, 0x22, 0x46, 0x2B, 0x46, 0x40, 0x46, 0x49, 0x46, 0x10, 0xF0,
+ 0x89, 0xFC, 0xDB, 0x48, 0x12, 0xF0, 0xCA, 0xFF, 0xD9, 0x49, 0x03, 0x20, 0x88, 0x71, 0x08, 0x46,
+ 0xFF, 0xF7, 0xA2, 0xFD, 0xD6, 0x48, 0x02, 0x21, 0x34, 0x38, 0xD0, 0xE9, 0x06, 0x70, 0x00, 0x90,
+ 0xD0, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0xCE, 0xA1, 0xB0, 0xF9, 0xD0, 0xB1, 0x05, 0xA8, 0x0D, 0xF0,
+ 0x81, 0xFD, 0x0A, 0xEB, 0x0B, 0x00, 0x40, 0x10, 0x0D, 0x90, 0xCA, 0x48, 0x00, 0x68, 0x90, 0xF8,
+ 0x34, 0x01, 0x80, 0x07, 0x05, 0xD4, 0x39, 0x46, 0x32, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x7C, 0xF9,
+ 0x76, 0x1E, 0x32, 0x46, 0x38, 0x46, 0x05, 0x99, 0x11, 0xF0, 0x05, 0xF9, 0x00, 0x27, 0x50, 0x45,
+ 0x01, 0xDC, 0x58, 0x45, 0x08, 0xDA, 0x0D, 0x99, 0x09, 0x1A, 0xBE, 0x48, 0x00, 0x68, 0xB0, 0xF8,
+ 0xD2, 0x01, 0x91, 0xFB, 0xF0, 0xF0, 0x47, 0xB2, 0xBA, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x34, 0x01,
+ 0x80, 0x07, 0x07, 0xD4, 0x00, 0x99, 0x06, 0x9A, 0x08, 0x46, 0x00, 0xF0, 0x5D, 0xF9, 0x06, 0x98,
+ 0x40, 0x1E, 0x06, 0x90, 0xDD, 0xE9, 0x05, 0x12, 0x00, 0x98, 0x11, 0xF0, 0xE4, 0xF8, 0x00, 0x26,
+ 0x50, 0x45, 0x01, 0xDC, 0x58, 0x45, 0x08, 0xDA, 0x0D, 0x99, 0x09, 0x1A, 0xAD, 0x48, 0x00, 0x68,
+ 0xB0, 0xF8, 0xD4, 0x01, 0x91, 0xFB, 0xF0, 0xF0, 0x46, 0xB2, 0x02, 0x21, 0x05, 0xA8, 0x0D, 0xF0,
+ 0x9C, 0xFD, 0x08, 0x98, 0xCD, 0xE9, 0x00, 0x07, 0x22, 0x46, 0x2B, 0x46, 0x02, 0x96, 0x40, 0x46,
+ 0x49, 0x46, 0xFF, 0xF7, 0x90, 0xFD, 0x01, 0x28, 0x1E, 0xD0, 0x02, 0x28, 0x25, 0xD0, 0xA2, 0x48,
+ 0x22, 0x46, 0x2B, 0x46, 0x00, 0x68, 0xC7, 0x77, 0x80, 0xF8, 0x20, 0x60, 0x01, 0x20, 0x08, 0x99,
+ 0xCD, 0xE9, 0x03, 0x60, 0xCD, 0xE9, 0x01, 0x17, 0x0E, 0x98, 0x00, 0x90, 0x40, 0x46, 0x49, 0x46,
+ 0x10, 0xF0, 0x08, 0xFC, 0x98, 0x48, 0xA5, 0x21, 0x00, 0x68, 0x81, 0x77, 0x01, 0x21, 0x08, 0xA8,
+ 0x0D, 0xF0, 0x73, 0xFD, 0x0F, 0xB0, 0x53, 0xE6, 0x93, 0x49, 0x00, 0x20, 0x09, 0x68, 0xC8, 0x77,
+ 0x81, 0xF8, 0x20, 0x00, 0x10, 0x21, 0xB2, 0x20, 0x07, 0xE0, 0x8F, 0x49, 0x00, 0x20, 0x09, 0x68,
+ 0xC8, 0x77, 0x81, 0xF8, 0x20, 0x00, 0x10, 0x21, 0xB3, 0x20, 0x0F, 0xF0, 0x0D, 0xFA, 0xE1, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x12, 0xF0, 0xC8, 0xFF, 0x06, 0x46, 0x0F, 0x46, 0x12, 0xF0,
+ 0xC6, 0xFF, 0xDF, 0xF8, 0x10, 0xB2, 0x01, 0x21, 0xDA, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8,
+ 0x31, 0x50, 0x05, 0xA8, 0x0D, 0xF0, 0xE6, 0xFC, 0x7F, 0x4C, 0x02, 0xA9, 0x4F, 0xF0, 0x00, 0x08,
+ 0x20, 0x68, 0x05, 0x9B, 0xDF, 0xF8, 0xF4, 0x91, 0x90, 0xF9, 0x23, 0x20, 0x90, 0xF9, 0x22, 0x00,
+ 0x09, 0xF1, 0x98, 0x09, 0x81, 0xE8, 0x05, 0x01, 0xCD, 0xE9, 0x00, 0x93, 0x42, 0x46, 0x43, 0x46,
+ 0x30, 0x46, 0x39, 0x46, 0x10, 0xF0, 0xBE, 0xFB, 0x05, 0x9A, 0xCD, 0xE9, 0x01, 0x28, 0x01, 0x21,
+ 0xCD, 0xF8, 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x81, 0x00, 0x22, 0x13, 0x46, 0x30, 0x46, 0x39, 0x46,
+ 0x10, 0xF0, 0xB0, 0xFB, 0x6E, 0x48, 0x12, 0xF0, 0xF1, 0xFE, 0x6D, 0x49, 0x03, 0x20, 0x08, 0x72,
+ 0x08, 0x46, 0xFF, 0xF7, 0xC9, 0xFC, 0x6A, 0x48, 0x02, 0x21, 0x34, 0x38, 0xD0, 0xF8, 0x28, 0x90,
+ 0x06, 0xA8, 0x0D, 0xF0, 0xAF, 0xFC, 0xDA, 0xF8, 0x00, 0x00, 0xB0, 0xF9, 0xD6, 0x11, 0xB0, 0xF9,
+ 0xD8, 0x21, 0x90, 0xF8, 0x84, 0x09, 0x11, 0x44, 0x01, 0xEB, 0xD1, 0x71, 0x4F, 0xEA, 0x61, 0x0A,
+ 0x80, 0x07, 0x05, 0xD4, 0x6D, 0x1E, 0x49, 0x46, 0x2A, 0x46, 0x08, 0x46, 0x00, 0xF0, 0xA4, 0xF8,
+ 0x2A, 0x46, 0x48, 0x46, 0x06, 0x99, 0x11, 0xF0, 0x2E, 0xF8, 0xDB, 0xF8, 0x00, 0x10, 0x00, 0x25,
+ 0xA9, 0x46, 0xB1, 0xF9, 0xD6, 0x21, 0x82, 0x42, 0x03, 0xDB, 0xB1, 0xF9, 0xD8, 0x21, 0x82, 0x42,
+ 0x06, 0xDD, 0xB1, 0xF8, 0xDA, 0x11, 0xAA, 0xEB, 0x00, 0x00, 0x90, 0xFB, 0xF1, 0xF0, 0x45, 0xB2,
+ 0x02, 0x21, 0x06, 0xA8, 0x0D, 0xF0, 0xE1, 0xFC, 0x05, 0x99, 0x00, 0x22, 0x8D, 0xE8, 0x22, 0x02,
+ 0x13, 0x46, 0x30, 0x46, 0x39, 0x46, 0xFF, 0xF7, 0xD6, 0xFC, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28,
+ 0x22, 0xD0, 0x21, 0x68, 0x45, 0x48, 0x01, 0xF8, 0x22, 0x5F, 0x81, 0xF8, 0x01, 0x80, 0x01, 0x21,
+ 0x05, 0x9A, 0xCD, 0xE9, 0x03, 0x81, 0x8D, 0xE8, 0x25, 0x00, 0x00, 0x22, 0x13, 0x46, 0x30, 0x46,
+ 0x39, 0x46, 0x10, 0xF0, 0x4F, 0xFB, 0x21, 0x68, 0xA5, 0x20, 0x81, 0xF8, 0x21, 0x00, 0x01, 0x21,
+ 0x05, 0xA8, 0x0D, 0xF0, 0xBA, 0xFC, 0x9A, 0xE5, 0x21, 0x68, 0x01, 0xF8, 0x22, 0x8F, 0x81, 0xF8,
+ 0x01, 0x80, 0x40, 0x21, 0xB2, 0x20, 0x06, 0xE0, 0x21, 0x68, 0xB3, 0x20, 0x01, 0xF8, 0x22, 0x8F,
+ 0x81, 0xF8, 0x01, 0x80, 0x40, 0x21, 0x0F, 0xF0, 0x57, 0xF9, 0xE4, 0xE7, 0x70, 0xB5, 0x04, 0x46,
+ 0x00, 0x20, 0x13, 0xF0, 0xC8, 0xFB, 0x02, 0x20, 0x13, 0xF0, 0xC5, 0xFB, 0x29, 0x4D, 0x28, 0x68,
+ 0x90, 0xF8, 0xC0, 0x01, 0x20, 0x40, 0xC0, 0x07, 0x01, 0xD0, 0xFF, 0xF7, 0xC2, 0xFC, 0x28, 0x68,
+ 0x90, 0xF8, 0xC0, 0x01, 0x80, 0x07, 0x03, 0xD5, 0xA0, 0x07, 0x01, 0xD5, 0xFF, 0xF7, 0x82, 0xFD,
+ 0x28, 0x68, 0x90, 0xF8, 0xC0, 0x01, 0x40, 0x07, 0x03, 0xD5, 0x60, 0x07, 0x01, 0xD5, 0xFF, 0xF7,
+ 0x4F, 0xFE, 0x28, 0x68, 0x90, 0xF8, 0xC0, 0x01, 0x00, 0x07, 0x03, 0xD5, 0x20, 0x07, 0x01, 0xD5,
+ 0xFF, 0xF7, 0x1E, 0xFF, 0x02, 0x20, 0x13, 0xF0, 0xB9, 0xFB, 0x00, 0x20, 0x13, 0xF0, 0xB6, 0xFB,
+ 0xE0, 0x07, 0x04, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0x01, 0xF0, 0xC9, 0xB9, 0x70, 0xBD,
+ 0xF0, 0xB5, 0x00, 0x26, 0x35, 0x46, 0x0C, 0xE0, 0x01, 0x24, 0x07, 0xE0, 0x05, 0xFB, 0x03, 0x47,
+ 0x64, 0x1C, 0x31, 0xF8, 0x17, 0x70, 0x20, 0xF8, 0x16, 0x70, 0x76, 0x1C, 0x9C, 0x42, 0xF5, 0xDB,
+ 0x6D, 0x1C, 0x95, 0x42, 0xF0, 0xDB, 0xF0, 0xBD, 0x30, 0xB5, 0x00, 0x24, 0x01, 0x23, 0x05, 0xE0,
+ 0x31, 0xF8, 0x13, 0x50, 0x20, 0xF8, 0x14, 0x50, 0x5B, 0x1C, 0x64, 0x1C, 0x93, 0x42, 0xF7, 0xDB,
+ 0x30, 0xBD, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0xEC, 0x57, 0x01, 0x20,
+ 0xB0, 0x08, 0x10, 0x00, 0x70, 0xB5, 0x6D, 0x4D, 0x4F, 0xF4, 0x26, 0x74, 0x21, 0x46, 0x28, 0x68,
+ 0x14, 0xF0, 0xCA, 0xF8, 0x00, 0x21, 0x1F, 0x20, 0x0E, 0xF1, 0x6A, 0xFD, 0x22, 0x46, 0x29, 0x68,
+ 0xBD, 0xE8, 0x70, 0x40, 0x1F, 0x23, 0x66, 0x48, 0x14, 0xF0, 0xE5, 0xB8, 0x63, 0x48, 0x10, 0xB5,
+ 0x00, 0x68, 0x64, 0x4C, 0x90, 0xF8, 0x3F, 0x10, 0x20, 0x68, 0x01, 0x76, 0x4F, 0xF4, 0x8C, 0x61,
+ 0x14, 0xF0, 0xB2, 0xF8, 0x00, 0x21, 0x1A, 0x20, 0x0E, 0xF1, 0x52, 0xFD, 0x00, 0x21, 0x1B, 0x20,
+ 0x0E, 0xF1, 0x4E, 0xFD, 0x1A, 0x23, 0x4F, 0xF4, 0x80, 0x62, 0x5B, 0x48, 0x21, 0x68, 0x14, 0xF0,
+ 0xCA, 0xF8, 0x21, 0x68, 0x1B, 0x23, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x22, 0x57, 0x48, 0x01, 0xF5,
+ 0x80, 0x51, 0x14, 0xF0, 0xC0, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x55, 0x4D, 0x04, 0x1D, 0x0E, 0x46,
+ 0x21, 0x46, 0x28, 0x46, 0x14, 0xF0, 0x90, 0xF8, 0x30, 0x68, 0x52, 0x49, 0x00, 0xEB, 0x84, 0x03,
+ 0x8B, 0x42, 0x01, 0xD2, 0x1C, 0x23, 0x12, 0xE0, 0x4F, 0x4A, 0x93, 0x42, 0x12, 0xD2, 0x88, 0x42,
+ 0x0C, 0xD2, 0x88, 0x46, 0x09, 0x1A, 0x8F, 0x08, 0x1C, 0x23, 0x3A, 0x46, 0x29, 0x46, 0x14, 0xF0,
+ 0xA2, 0xF8, 0xE2, 0x1B, 0x05, 0xEB, 0x87, 0x01, 0x1D, 0x23, 0x11, 0xE0, 0x1D, 0x23, 0x22, 0x46,
+ 0x29, 0x46, 0x0E, 0xE0, 0x90, 0x42, 0x14, 0xD2, 0x11, 0x1A, 0x8F, 0x08, 0x90, 0x46, 0x1D, 0x23,
+ 0x3A, 0x46, 0x29, 0x46, 0x14, 0xF0, 0x8F, 0xF8, 0xE2, 0x1B, 0x05, 0xEB, 0x87, 0x01, 0x1E, 0x23,
+ 0x40, 0x46, 0x14, 0xF0, 0x88, 0xF8, 0x30, 0x68, 0x00, 0xEB, 0x84, 0x00, 0x30, 0x60, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x1E, 0x23, 0xE3, 0xE7, 0xF8, 0xB5, 0x35, 0x4C, 0x38, 0x48, 0x00, 0x90, 0x10, 0x34,
+ 0x02, 0x20, 0x13, 0xF0, 0xE8, 0xFA, 0x00, 0x21, 0x1C, 0x20, 0x0E, 0xF1, 0xF1, 0xFC, 0x00, 0x21,
+ 0x1D, 0x20, 0x0E, 0xF1, 0xED, 0xFC, 0x00, 0x21, 0x1E, 0x20, 0x0E, 0xF1, 0xE9, 0xFC, 0x10, 0x21,
+ 0x20, 0x46, 0x15, 0xF0, 0x46, 0xFB, 0x00, 0x20, 0x20, 0x80, 0xA0, 0x70, 0x23, 0x4D, 0x01, 0x20,
+ 0xE0, 0x70, 0x28, 0x68, 0xC1, 0x8A, 0xA1, 0x80, 0x81, 0x8A, 0xE1, 0x80, 0x28, 0x49, 0xC2, 0x8A,
+ 0xA1, 0xF8, 0xFA, 0x2E, 0x80, 0x8A, 0xA1, 0xF8, 0xF8, 0x0E, 0x04, 0x20, 0x69, 0x46, 0xFF, 0xF7,
+ 0x92, 0xFF, 0x01, 0x23, 0x00, 0x22, 0x21, 0x46, 0x10, 0x20, 0x10, 0xF0, 0x46, 0xFC, 0x06, 0x46,
+ 0x69, 0x46, 0xFF, 0xF7, 0x88, 0xFF, 0x01, 0x23, 0x00, 0x22, 0x21, 0x46, 0x11, 0x20, 0x10, 0xF0,
+ 0x3C, 0xFC, 0x69, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x7E, 0xFF, 0x29, 0x68, 0x91, 0xF8, 0x50, 0x02,
+ 0xC0, 0x07, 0x03, 0xD1, 0x91, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x09, 0xD0, 0x01, 0x23, 0x00, 0x22,
+ 0x21, 0x46, 0x12, 0x20, 0x10, 0xF0, 0x29, 0xFC, 0x69, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x6B, 0xFF,
+ 0x01, 0x23, 0x00, 0x22, 0x21, 0x46, 0x13, 0x20, 0x10, 0xF0, 0x1F, 0xFC, 0x69, 0x46, 0x30, 0x46,
+ 0xFF, 0xF7, 0x61, 0xFF, 0x02, 0x20, 0x13, 0xF0, 0xA9, 0xFA, 0xF8, 0xBD, 0x20, 0x07, 0x10, 0x00,
+ 0xF0, 0xEF, 0x01, 0x00, 0x24, 0x07, 0x10, 0x00, 0xF0, 0x9F, 0x01, 0x00, 0xF0, 0xAF, 0x01, 0x00,
+ 0x84, 0x5A, 0x10, 0x00, 0xF0, 0xCF, 0x01, 0x00, 0xF0, 0xDF, 0x01, 0x00, 0xF0, 0xBF, 0x01, 0x00,
+ 0xFC, 0x4C, 0x01, 0x20, 0x0B, 0x48, 0x01, 0x78, 0x5A, 0x29, 0x11, 0xD1, 0x81, 0x88, 0xB1, 0xF5,
+ 0x7C, 0x7F, 0x0D, 0xD8, 0x41, 0x88, 0x00, 0x29, 0x0A, 0xD1, 0x06, 0x49, 0x40, 0x78, 0x10, 0x31,
+ 0x02, 0x28, 0x05, 0xD0, 0xA0, 0xF1, 0x70, 0x02, 0x07, 0x2A, 0x01, 0xD8, 0x0F, 0xF0, 0xBF, 0xB9,
+ 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFE, 0x48,
+ 0x15, 0xF0, 0x8D, 0xFA, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x13, 0xF0, 0xB3, 0xB9,
+ 0x2D, 0xE9, 0xF0, 0x41, 0xF9, 0x4C, 0xA0, 0xF1, 0x60, 0x06, 0x09, 0x2E, 0xD4, 0xE9, 0x12, 0x05,
+ 0xD4, 0xE9, 0x14, 0x23, 0x16, 0xD2, 0xDF, 0xE8, 0x06, 0xF0, 0x05, 0x16, 0x26, 0x37, 0x46, 0x58,
+ 0x67, 0x78, 0x87, 0x00, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x9D, 0xF9, 0x02, 0x46,
+ 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xEF, 0xF9, 0xD4, 0xE9, 0x02, 0x23, 0x10, 0x43, 0x19, 0x43,
+ 0xC4, 0xE9, 0x02, 0x01, 0x75, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x8E, 0xF9, 0x01, 0x23, 0x02, 0x46,
+ 0x00, 0x21, 0x18, 0x46, 0x15, 0xF0, 0xDF, 0xF9, 0xD4, 0xE9, 0x0A, 0x23, 0x10, 0x43, 0x19, 0x43,
+ 0xC4, 0xE9, 0x0A, 0x01, 0x65, 0xE0, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x7C, 0xF9,
+ 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xCE, 0xF9, 0xD4, 0xE9, 0x06, 0x23, 0x10, 0x43,
+ 0x19, 0x43, 0xC4, 0xE9, 0x06, 0x01, 0x54, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x6D, 0xF9, 0x02, 0x46,
+ 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xBF, 0xF9, 0xD4, 0xE9, 0x0E, 0x23, 0x10, 0x43, 0x19, 0x43,
+ 0xC4, 0xE9, 0x0E, 0x01, 0x45, 0xE0, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x5C, 0xF9,
+ 0x01, 0x23, 0x02, 0x46, 0x00, 0x21, 0x18, 0x46, 0x15, 0xF0, 0xAD, 0xF9, 0xD4, 0xE9, 0x04, 0x23,
+ 0x10, 0x43, 0x19, 0x43, 0xC4, 0xE9, 0x04, 0x01, 0x33, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x4C, 0xF9,
+ 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0x9E, 0xF9, 0xD4, 0xE9, 0x0C, 0x23, 0x10, 0x43,
+ 0x19, 0x43, 0xC4, 0xE9, 0x0C, 0x01, 0x24, 0xE0, 0x02, 0x46, 0x2B, 0x46, 0x08, 0x46, 0x00, 0xF0,
+ 0x3B, 0xF9, 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0x8D, 0xF9, 0xD4, 0xE9, 0x08, 0x23,
+ 0x10, 0x43, 0x19, 0x43, 0xC4, 0xE9, 0x08, 0x01, 0x13, 0xE0, 0x08, 0x46, 0x00, 0xF0, 0x2C, 0xF9,
+ 0x02, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0x7E, 0xF9, 0xD4, 0xE9, 0x10, 0x23, 0x10, 0x43,
+ 0x19, 0x43, 0xC4, 0xE9, 0x10, 0x01, 0x04, 0xE0, 0x01, 0x20, 0x88, 0x40, 0x61, 0x68, 0x08, 0x43,
+ 0x60, 0x60, 0x20, 0x68, 0x40, 0x1C, 0x20, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x41,
+ 0x17, 0x46, 0x04, 0x46, 0x0D, 0x46, 0x00, 0x26, 0x09, 0xE0, 0xE0, 0x07, 0x03, 0xD0, 0x31, 0x46,
+ 0x38, 0x46, 0x0E, 0xF0, 0x31, 0xFF, 0x76, 0x1C, 0x6D, 0x08, 0x4F, 0xEA, 0x34, 0x04, 0x54, 0xEA,
+ 0x05, 0x00, 0xF2, 0xD1, 0xE8, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0xA0, 0x4C, 0xD4, 0xE9, 0x02, 0x23,
+ 0xD4, 0xE9, 0x06, 0x56, 0x10, 0x46, 0x19, 0x46, 0x2A, 0x43, 0x33, 0x43, 0xD4, 0xE9, 0x0A, 0x56,
+ 0xD4, 0xE9, 0x0E, 0xC7, 0x45, 0xEA, 0x0C, 0x05, 0x3E, 0x43, 0xD4, 0xE9, 0x08, 0x7C, 0x97, 0x43,
+ 0x2C, 0xEA, 0x03, 0x0C, 0xC4, 0xE9, 0x08, 0x7C, 0xD4, 0xE9, 0x10, 0x23, 0xAA, 0x43, 0xB3, 0x43,
+ 0xC4, 0xE9, 0x10, 0x23, 0x22, 0x68, 0x00, 0x2A, 0xC6, 0xD0, 0x60, 0x22, 0xFF, 0xF7, 0xC6, 0xFF,
+ 0xD4, 0xE9, 0x0A, 0x01, 0x61, 0x22, 0xFF, 0xF7, 0xC1, 0xFF, 0xD4, 0xE9, 0x06, 0x01, 0x62, 0x22,
+ 0xFF, 0xF7, 0xBC, 0xFF, 0xD4, 0xE9, 0x0E, 0x01, 0x63, 0x22, 0xFF, 0xF7, 0xB7, 0xFF, 0xD4, 0xE9,
+ 0x04, 0x01, 0x64, 0x22, 0xFF, 0xF7, 0xB2, 0xFF, 0xD4, 0xE9, 0x0C, 0x01, 0x65, 0x22, 0xFF, 0xF7,
+ 0xAD, 0xFF, 0xD4, 0xE9, 0x08, 0x01, 0x66, 0x22, 0xFF, 0xF7, 0xA8, 0xFF, 0xD4, 0xE9, 0x10, 0x01,
+ 0x67, 0x22, 0xFF, 0xF7, 0xA3, 0xFF, 0x60, 0x68, 0xBD, 0xE8, 0xF0, 0x41, 0x68, 0x22, 0x00, 0x21,
+ 0x9C, 0xE7, 0x99, 0xE7, 0x2D, 0xE9, 0xF1, 0x4F, 0x4F, 0xF0, 0x00, 0x09, 0x12, 0xF0, 0x95, 0xFC,
+ 0x06, 0x46, 0x88, 0x46, 0x12, 0xF0, 0x93, 0xFC, 0x74, 0x4A, 0x04, 0x46, 0x0D, 0x46, 0xC2, 0xE9,
+ 0x14, 0x01, 0xC2, 0xE9, 0x12, 0x68, 0x4F, 0xF0, 0x1D, 0x0A, 0x4F, 0xF0, 0x26, 0x0B, 0x13, 0xF0,
+ 0x8C, 0xFB, 0x00, 0x27, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0, 0xEC, 0xF8, 0x30, 0x40,
+ 0x01, 0xEA, 0x08, 0x01, 0x08, 0x43, 0x22, 0xD0, 0xF8, 0xB2, 0x00, 0x21, 0x13, 0xF0, 0x85, 0xFB,
+ 0x41, 0x07, 0x05, 0xD5, 0x00, 0x99, 0xC9, 0x06, 0x02, 0xD5, 0x49, 0x46, 0x62, 0x20, 0x10, 0xE0,
+ 0xC1, 0x07, 0x05, 0xD0, 0x00, 0x99, 0x49, 0x07, 0x02, 0xD5, 0x49, 0x46, 0x60, 0x20, 0x08, 0xE0,
+ 0x00, 0x99, 0x11, 0xF0, 0xC0, 0x0F, 0x06, 0xD0, 0x10, 0xF0, 0x0A, 0x0F, 0x03, 0xD0, 0x49, 0x46,
+ 0x64, 0x20, 0xFF, 0xF7, 0xBD, 0xFE, 0x09, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x09, 0x7F, 0x1C,
+ 0x57, 0x45, 0xCF, 0xDB, 0x13, 0xF0, 0x59, 0xFB, 0x00, 0x27, 0x3E, 0x46, 0x32, 0x46, 0x01, 0x20,
+ 0x00, 0x21, 0x15, 0xF0, 0xB8, 0xF8, 0x20, 0x40, 0x29, 0x40, 0x08, 0x43, 0x20, 0xD0, 0xF0, 0xB2,
+ 0x01, 0x21, 0x13, 0xF0, 0x52, 0xFB, 0x41, 0x07, 0x05, 0xD5, 0x00, 0x99, 0x89, 0x06, 0x02, 0xD5,
+ 0x39, 0x46, 0x63, 0x20, 0x10, 0xE0, 0xC1, 0x07, 0x05, 0xD0, 0x00, 0x99, 0x09, 0x07, 0x02, 0xD5,
+ 0x39, 0x46, 0x61, 0x20, 0x08, 0xE0, 0x00, 0x99, 0x11, 0xF4, 0xC0, 0x7F, 0x06, 0xD0, 0x10, 0xF0,
+ 0x0A, 0x0F, 0x03, 0xD0, 0x39, 0x46, 0x65, 0x20, 0xFF, 0xF7, 0x8A, 0xFE, 0x7F, 0x1C, 0xFF, 0xB2,
+ 0x76, 0x1C, 0x5E, 0x45, 0xD2, 0xDD, 0xBD, 0xE8, 0xF8, 0x4F, 0x13, 0xF0, 0x26, 0xBB, 0x10, 0xB5,
+ 0x04, 0x46, 0x00, 0x20, 0x13, 0xF0, 0xCF, 0xF8, 0x38, 0x49, 0x00, 0x20, 0x14, 0xF0, 0x0C, 0x0F,
+ 0xC1, 0xE9, 0x08, 0x00, 0xC1, 0xE9, 0x02, 0x00, 0xC1, 0xE9, 0x04, 0x00, 0xC1, 0xE9, 0x06, 0x00,
+ 0xC1, 0xE9, 0x10, 0x00, 0xC1, 0xE9, 0x0A, 0x00, 0xC1, 0xE9, 0x0C, 0x00, 0xC1, 0xE9, 0x0E, 0x00,
+ 0x48, 0x60, 0x08, 0x60, 0x09, 0xD1, 0xE0, 0x06, 0x07, 0xD4, 0xA0, 0x06, 0x05, 0xD4, 0x60, 0x06,
+ 0x03, 0xD4, 0xE0, 0x05, 0x01, 0xD4, 0x20, 0x06, 0x02, 0xD5, 0x20, 0x46, 0xFF, 0xF7, 0x5A, 0xFF,
+ 0xA0, 0x07, 0x02, 0xD0, 0x20, 0x46, 0x00, 0xF0, 0x22, 0xF8, 0xFF, 0xF7, 0x04, 0xFF, 0xBD, 0xE8,
+ 0x10, 0x40, 0x00, 0x20, 0x13, 0xF0, 0xBA, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x16, 0x46, 0x1F, 0x46,
+ 0x80, 0x46, 0x4F, 0xF0, 0xFF, 0x35, 0x00, 0x24, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x15, 0xF0,
+ 0x4A, 0xF8, 0x30, 0x40, 0x39, 0x40, 0x08, 0x43, 0x04, 0xD0, 0x6D, 0x1C, 0x45, 0x45, 0x01, 0xD1,
+ 0x20, 0x46, 0xD1, 0xE6, 0x64, 0x1C, 0x40, 0x2C, 0xEE, 0xD3, 0x00, 0x20, 0xCC, 0xE6, 0x2D, 0xE9,
+ 0xFF, 0x41, 0x04, 0x46, 0x01, 0x20, 0x00, 0xF0, 0x31, 0xF8, 0x80, 0x46, 0x12, 0xF0, 0xC5, 0xFB,
+ 0xCD, 0xE9, 0x00, 0x01, 0x12, 0xF0, 0xC3, 0xFB, 0xCD, 0xE9, 0x02, 0x01, 0x08, 0x21, 0x68, 0x46,
+ 0x13, 0xF0, 0xA0, 0xFD, 0x07, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x13, 0xF0, 0x9B, 0xFD, 0x05, 0x46,
+ 0x07, 0x4E, 0xE0, 0x07, 0x07, 0xD0, 0x30, 0x68, 0x42, 0x46, 0x29, 0x46, 0xB0, 0xF8, 0xDE, 0x30,
+ 0x38, 0x46, 0x00, 0xF0, 0x4C, 0xF8, 0x05, 0xE0, 0xC0, 0x08, 0x10, 0x00, 0x08, 0x04, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xA0, 0x07, 0x07, 0xD5, 0x30, 0x68, 0x42, 0x46, 0x29, 0x46, 0xB0, 0xF8,
+ 0xDE, 0x30, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF8, 0xBD, 0xE8, 0xFF, 0x81, 0x30, 0xB5, 0x85, 0xB0,
+ 0x04, 0x46, 0x68, 0x46, 0x12, 0xF0, 0xF2, 0xFA, 0x67, 0x48, 0x00, 0x90, 0x67, 0x48, 0x00, 0x68,
+ 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x02, 0xD0, 0x01, 0x20, 0x8D, 0xF8, 0x0B, 0x00, 0x02, 0x2C,
+ 0x15, 0xD0, 0x07, 0x20, 0x8D, 0xF8, 0x04, 0x00, 0x61, 0x4C, 0x68, 0x46, 0x12, 0xF0, 0x03, 0xFB,
+ 0x00, 0x22, 0x04, 0xAB, 0x01, 0x21, 0x10, 0x46, 0x12, 0xF0, 0xD6, 0xFF, 0x01, 0x21, 0x00, 0x20,
+ 0x12, 0xF0, 0xB5, 0xFF, 0x20, 0x78, 0x30, 0xB1, 0x0E, 0xF0, 0xBD, 0xFD, 0xED, 0xE7, 0x03, 0x20,
+ 0x8D, 0xF8, 0x09, 0x00, 0xE8, 0xE7, 0x12, 0xF0, 0x68, 0xFB, 0x56, 0x4D, 0xC5, 0xE9, 0x12, 0x01,
+ 0x12, 0xF0, 0x65, 0xFB, 0xC5, 0xE9, 0x14, 0x01, 0xA0, 0x68, 0x05, 0xB0, 0x30, 0xBD, 0x2D, 0xE9,
+ 0xFF, 0x5F, 0x9B, 0x46, 0x92, 0x46, 0x0F, 0x46, 0x00, 0x25, 0x44, 0xE0, 0x00, 0x98, 0x4F, 0xF0,
+ 0x00, 0x09, 0x4C, 0x46, 0xA0, 0xF1, 0x01, 0x08, 0x3A, 0xE0, 0x00, 0xBF, 0x04, 0xFB, 0x07, 0x50,
+ 0x81, 0xB2, 0x60, 0x1C, 0x00, 0xFB, 0x07, 0x50, 0x80, 0xB2, 0x3A, 0xF8, 0x11, 0x20, 0x3A, 0xF8,
+ 0x10, 0x00, 0x10, 0x1A, 0x00, 0xB2, 0x58, 0x45, 0x02, 0xDD, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0,
+ 0xCB, 0xF1, 0x00, 0x01, 0x88, 0x42, 0x13, 0xDA, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xD0, 0x4F, 0xF0,
+ 0x00, 0x09, 0x21, 0x46, 0x18, 0xE0, 0x4F, 0xF0, 0x01, 0x09, 0x14, 0xE0, 0x00, 0x26, 0x04, 0xE0,
+ 0x31, 0x46, 0x66, 0x20, 0xFF, 0xF7, 0x8C, 0xFD, 0x76, 0x1C, 0xA6, 0x42, 0xF8, 0xD9, 0x0E, 0xE0,
+ 0xB9, 0xF1, 0x00, 0x0F, 0x0B, 0xD0, 0x21, 0x46, 0x66, 0x20, 0xFF, 0xF7, 0x81, 0xFD, 0x00, 0x98,
+ 0x80, 0x1E, 0x84, 0x42, 0x03, 0xD1, 0x61, 0x1C, 0x66, 0x20, 0xFF, 0xF7, 0x79, 0xFD, 0x64, 0x1C,
+ 0x44, 0x45, 0xC3, 0xD3, 0x6D, 0x1C, 0xBD, 0x42, 0xB8, 0xD3, 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9,
+ 0xFF, 0x5F, 0x9B, 0x46, 0x92, 0x46, 0x0D, 0x46, 0x00, 0x26, 0x41, 0xE0, 0x4F, 0xF0, 0x00, 0x09,
+ 0x4C, 0x46, 0xA5, 0xF1, 0x01, 0x08, 0x38, 0xE0, 0x06, 0xFB, 0x05, 0x40, 0x61, 0x1C, 0x06, 0xFB,
+ 0x05, 0x11, 0x80, 0xB2, 0x89, 0xB2, 0x3A, 0xF8, 0x10, 0x20, 0x3A, 0xF8, 0x11, 0x00, 0x10, 0x1A,
+ 0x00, 0xB2, 0x58, 0x45, 0x02, 0xDD, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0xCB, 0xF1, 0x00, 0x01,
+ 0x88, 0x42, 0x13, 0xDA, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xD0, 0x4F, 0xF0, 0x00, 0x09, 0x21, 0x46,
+ 0x17, 0xE0, 0x4F, 0xF0, 0x01, 0x09, 0x13, 0xE0, 0x00, 0x27, 0x04, 0xE0, 0x39, 0x46, 0x67, 0x20,
+ 0xFF, 0xF7, 0x3E, 0xFD, 0x7F, 0x1C, 0xA7, 0x42, 0xF8, 0xD9, 0x0D, 0xE0, 0xB9, 0xF1, 0x00, 0x0F,
+ 0x0A, 0xD0, 0x21, 0x46, 0x67, 0x20, 0xFF, 0xF7, 0x33, 0xFD, 0xA8, 0x1E, 0x84, 0x42, 0x03, 0xD1,
+ 0x61, 0x1C, 0x67, 0x20, 0xFF, 0xF7, 0x2C, 0xFD, 0x64, 0x1C, 0x44, 0x45, 0xC4, 0xD3, 0x76, 0x1C,
+ 0x00, 0x98, 0x86, 0x42, 0xBA, 0xD3, 0xB0, 0xE7, 0x29, 0x13, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xC0, 0x08, 0x10, 0x00, 0x08, 0x04, 0x10, 0x00, 0x11, 0x49, 0x08, 0x60, 0x4F, 0xF4, 0x00, 0x51,
+ 0x00, 0x20, 0x12, 0xF0, 0xC8, 0xBE, 0x38, 0xB5, 0xAF, 0xF2, 0x13, 0x00, 0x14, 0xF0, 0xC2, 0xFD,
+ 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x54, 0x6B, 0x46, 0x21, 0x46, 0x10, 0x46, 0x12, 0xF0, 0x04, 0xFF,
+ 0x21, 0x46, 0x00, 0x20, 0x12, 0xF0, 0xE3, 0xFE, 0x06, 0x48, 0xA5, 0x22, 0x01, 0x68, 0x04, 0x48,
+ 0x0A, 0x74, 0x00, 0x68, 0x20, 0xF0, 0x7F, 0x42, 0x4A, 0x61, 0x14, 0xF0, 0xC9, 0xFD, 0x38, 0xBD,
+ 0x60, 0x04, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0x02, 0x00, 0x04, 0xD0, 0x01, 0x2A, 0x04, 0xD0,
+ 0x02, 0x28, 0x03, 0xD1, 0x04, 0xE0, 0x01, 0x20, 0x00, 0xE0, 0x04, 0x20, 0x12, 0xF0, 0x8F, 0xB9,
+ 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x01, 0x46, 0x34, 0x22, 0xFE, 0x48, 0x14, 0xF0, 0x67, 0xFF,
+ 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x12, 0xF0, 0x8D, 0xBE, 0x30, 0xB5, 0x85, 0xB0,
+ 0x04, 0x46, 0x68, 0x46, 0x12, 0xF0, 0xD2, 0xF9, 0xF7, 0x48, 0x00, 0x90, 0x02, 0x20, 0x6C, 0xB3,
+ 0x01, 0x2C, 0x2D, 0xD0, 0x02, 0x2C, 0x2D, 0xD0, 0x03, 0x2C, 0x25, 0xD1, 0x5F, 0xF0, 0x08, 0x01,
+ 0x8D, 0xF8, 0x04, 0x10, 0xF1, 0x49, 0x09, 0x68, 0x91, 0xF8, 0xB0, 0x10, 0xCA, 0x07, 0x04, 0xD0,
+ 0x89, 0x07, 0x00, 0xD4, 0x01, 0x20, 0x8D, 0xF8, 0x0B, 0x00, 0xEA, 0x4D, 0x03, 0x24, 0x68, 0x46,
+ 0x12, 0xF0, 0xD9, 0xF9, 0x00, 0x22, 0x04, 0xAB, 0x01, 0x21, 0x10, 0x46, 0x12, 0xF0, 0xAC, 0xFE,
+ 0x01, 0x21, 0x00, 0x20, 0x12, 0xF0, 0x8B, 0xFE, 0x28, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x0E, 0xF0,
+ 0x92, 0xFC, 0x64, 0x1E, 0x00, 0x2C, 0xEA, 0xDC, 0x05, 0xB0, 0x30, 0xBD, 0x05, 0x21, 0xD7, 0xE7,
+ 0x06, 0x21, 0xD5, 0xE7, 0x8D, 0xF8, 0x09, 0x00, 0xD4, 0xE7, 0x2D, 0xE9, 0xF1, 0x4F, 0x88, 0xB0,
+ 0x12, 0xF0, 0x33, 0xFA, 0x83, 0x46, 0x02, 0x91, 0x12, 0xF0, 0x31, 0xFA, 0x81, 0x46, 0xD7, 0x4C,
+ 0x08, 0x98, 0x8A, 0x46, 0x00, 0x28, 0x20, 0x68, 0x07, 0xD0, 0xB0, 0xF8, 0x7A, 0x11, 0x08, 0x98,
+ 0xFF, 0xF7, 0x92, 0xFF, 0x04, 0x90, 0xD2, 0x48, 0x12, 0xE0, 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0,
+ 0x60, 0x0F, 0x05, 0xD0, 0x58, 0x46, 0x02, 0x99, 0x0F, 0xF0, 0x64, 0xFD, 0x83, 0x46, 0x02, 0x91,
+ 0x20, 0x68, 0xB0, 0xF8, 0x72, 0x11, 0x08, 0x98, 0xFF, 0xF7, 0x7E, 0xFF, 0x04, 0x90, 0xC9, 0x48,
+ 0x03, 0x90, 0x40, 0x20, 0x07, 0x90, 0x06, 0x90, 0xC2, 0x48, 0xB8, 0x21, 0xB8, 0x38, 0x14, 0xF0,
+ 0x4A, 0xFF, 0x00, 0x20, 0x00, 0x90, 0x08, 0x98, 0xFF, 0xF7, 0x88, 0xFF, 0xBD, 0x48, 0x00, 0x27,
+ 0x3E, 0x46, 0x80, 0x68, 0x05, 0x90, 0x01, 0x20, 0x3D, 0x46, 0x01, 0x90, 0x2A, 0x46, 0x01, 0x20,
+ 0x00, 0x21, 0x14, 0xF0, 0x60, 0xFE, 0x02, 0x9A, 0x00, 0xEA, 0x0B, 0x00, 0x11, 0x40, 0x08, 0x43,
+ 0x41, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x54, 0xFE, 0x02, 0x46,
+ 0x0B, 0x46, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0A, 0x01, 0x08, 0x43, 0x20, 0xD0, 0xAD, 0x48,
+ 0xB8, 0x38, 0x00, 0xEB, 0xC6, 0x01, 0x8E, 0x46, 0x03, 0xC9, 0x00, 0xEA, 0x02, 0x0C, 0x01, 0xEA,
+ 0x03, 0x08, 0x5C, 0xEA, 0x08, 0x0C, 0x12, 0xD1, 0xDD, 0xF8, 0x14, 0xC0, 0x3C, 0xF9, 0x17, 0x80,
+ 0xDD, 0xF8, 0x10, 0xC0, 0xE0, 0x45, 0x04, 0xDC, 0x10, 0x43, 0x19, 0x43, 0xCE, 0xE9, 0x00, 0x01,
+ 0x05, 0xE0, 0x22, 0x46, 0x31, 0x46, 0x00, 0x9B, 0x03, 0x98, 0x13, 0xF0, 0x1E, 0xF8, 0x7F, 0x1C,
+ 0x06, 0x98, 0x64, 0x1C, 0x84, 0x42, 0xCD, 0xDB, 0x9A, 0x48, 0xB8, 0x38, 0x00, 0xEB, 0xC6, 0x01,
+ 0xD1, 0xE9, 0x00, 0x02, 0x80, 0xEA, 0x09, 0x00, 0x82, 0xEA, 0x0A, 0x02, 0x10, 0x43, 0x01, 0xD0,
+ 0x00, 0x20, 0x01, 0x90, 0x76, 0x1C, 0x07, 0x98, 0x6D, 0x1C, 0x85, 0x42, 0xAE, 0xDB, 0x01, 0x98,
+ 0x01, 0x28, 0x04, 0xD0, 0x00, 0x98, 0x40, 0x1C, 0x00, 0x90, 0x7F, 0x28, 0x9B, 0xDD, 0x01, 0x98,
+ 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xF1, 0x4F, 0x98, 0xB0, 0x12, 0xF0, 0x95, 0xF9,
+ 0xCD, 0xE9, 0x0C, 0x01, 0x12, 0xF0, 0x93, 0xF9, 0xCD, 0xE9, 0x10, 0x01, 0x18, 0x98, 0x87, 0x4C,
+ 0x00, 0x28, 0x5C, 0xD0, 0x20, 0x68, 0xB0, 0xF8, 0x7A, 0x11, 0x18, 0x98, 0xFF, 0xF7, 0xF4, 0xFE,
+ 0x0F, 0x90, 0x83, 0x48, 0x06, 0x90, 0x40, 0x20, 0x82, 0x46, 0x0E, 0x90, 0x08, 0x21, 0x0C, 0xA8,
+ 0x13, 0xF0, 0x60, 0xFB, 0x04, 0x46, 0x08, 0x21, 0x10, 0xA8, 0x13, 0xF0, 0x5B, 0xFB, 0x44, 0x43,
+ 0x7D, 0x48, 0x01, 0x90, 0x00, 0xF5, 0xE6, 0x60, 0x21, 0x46, 0x02, 0x90, 0x14, 0xF0, 0x91, 0xFE,
+ 0x61, 0x00, 0x01, 0x98, 0x14, 0xF0, 0x8D, 0xFE, 0x72, 0x48, 0xB8, 0x21, 0xB8, 0x38, 0x14, 0xF0,
+ 0xAA, 0xFE, 0x4F, 0xF0, 0x00, 0x09, 0x18, 0x98, 0xFF, 0xF7, 0xE8, 0xFE, 0x6D, 0x48, 0x00, 0x27,
+ 0x3C, 0x46, 0x80, 0x68, 0x0A, 0x90, 0xC9, 0xF1, 0x00, 0x00, 0x4F, 0xF0, 0x01, 0x0B, 0x3E, 0x46,
+ 0x13, 0x90, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0xBD, 0xFD, 0xDD, 0xE9, 0x0C, 0x23,
+ 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x6E, 0xD0, 0x00, 0x25, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x14, 0xF0, 0xB1, 0xFD, 0xDD, 0xE9, 0x10, 0x8C, 0x02, 0x46, 0x0B, 0x46, 0x00, 0xEA, 0x08, 0x00,
+ 0x01, 0xEA, 0x0C, 0x01, 0x08, 0x43, 0x73, 0xD0, 0x5A, 0x48, 0xB8, 0x38, 0x00, 0xEB, 0xC7, 0x0C,
+ 0xDC, 0xE9, 0x00, 0x01, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x0F, 0xD0, 0x93, 0xE0, 0xDD, 0xE9,
+ 0x0C, 0x01, 0x0F, 0xF0, 0x77, 0xFC, 0xCD, 0xE9, 0x0C, 0x01, 0x20, 0x68, 0xB0, 0xF8, 0x72, 0x11,
+ 0x18, 0x98, 0xFF, 0xF7, 0x91, 0xFE, 0x0F, 0x90, 0x52, 0x48, 0x9B, 0xE7, 0xB9, 0xF1, 0x00, 0x0F,
+ 0x0A, 0xDA, 0x0A, 0x98, 0x30, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x81, 0x42, 0x01, 0xDB, 0x00, 0x21,
+ 0x00, 0xE0, 0x01, 0x21, 0x02, 0x98, 0x01, 0x55, 0x0A, 0x98, 0x0F, 0x99, 0x30, 0xF9, 0x14, 0x00,
+ 0x88, 0x42, 0x31, 0xDD, 0x02, 0x99, 0x09, 0x5D, 0x11, 0xB1, 0x01, 0x29, 0x09, 0xD0, 0x6A, 0xE0,
+ 0xB9, 0xF1, 0x7F, 0x0F, 0x67, 0xDA, 0x01, 0x99, 0x09, 0xF1, 0x01, 0x03, 0x21, 0xF8, 0x14, 0x00,
+ 0x51, 0xE0, 0xDC, 0xE9, 0x00, 0x10, 0x11, 0x43, 0x18, 0x43, 0xCC, 0xE9, 0x00, 0x10, 0x01, 0x98,
+ 0x30, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x09, 0x1A, 0x0A, 0x98, 0x30, 0xF9, 0x14, 0x20, 0x0F, 0x98,
+ 0xA2, 0xEB, 0x00, 0x00, 0x00, 0xD5, 0x49, 0x42, 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x81, 0x42,
+ 0x05, 0xDC, 0x13, 0x9B, 0x2A, 0x46, 0x39, 0x46, 0x5B, 0x1C, 0x06, 0x98, 0x36, 0xE0, 0x01, 0x98,
+ 0x20, 0xF8, 0x14, 0x20, 0x3F, 0xE0, 0x52, 0xE0, 0x37, 0xDA, 0x02, 0x99, 0x09, 0x5D, 0x01, 0x29,
+ 0x01, 0xD0, 0x71, 0xB1, 0x37, 0xE0, 0x13, 0x99, 0x11, 0xF1, 0x7F, 0x0F, 0x33, 0xDD, 0x01, 0x99,
+ 0x2A, 0x46, 0x21, 0xF8, 0x14, 0x00, 0x13, 0x9B, 0x39, 0x46, 0x5B, 0x1E, 0x06, 0x98, 0x1D, 0xE0,
+ 0x2A, 0xE0, 0xDC, 0xE9, 0x00, 0x10, 0x11, 0x43, 0x18, 0x43, 0xCC, 0xE9, 0x00, 0x10, 0x01, 0x98,
+ 0x0F, 0x9A, 0x30, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x08, 0x1A, 0x0A, 0x99, 0x31, 0xF9, 0x14, 0x10,
+ 0xA1, 0xEB, 0x02, 0x02, 0x00, 0xD5, 0x40, 0x42, 0x00, 0x2A, 0x00, 0xDA, 0x52, 0x42, 0x90, 0x42,
+ 0x07, 0xDC, 0xA9, 0xF1, 0x01, 0x03, 0x2A, 0x46, 0x39, 0x46, 0x06, 0x98, 0x12, 0xF0, 0x05, 0xFF,
+ 0x09, 0xE0, 0x01, 0x98, 0x20, 0xF8, 0x14, 0x10, 0x05, 0xE0, 0xDC, 0xE9, 0x00, 0x10, 0x11, 0x43,
+ 0x18, 0x43, 0xCC, 0xE9, 0x00, 0x10, 0x64, 0x1C, 0x6D, 0x1C, 0x55, 0x45, 0xFF, 0xF6, 0x4D, 0xAF,
+ 0x08, 0x48, 0xB8, 0x38, 0x00, 0xEB, 0xC7, 0x01, 0xD1, 0xE9, 0x00, 0x01, 0xDD, 0xE9, 0x10, 0x23,
+ 0x50, 0x40, 0x59, 0x40, 0x08, 0x43, 0x01, 0xD0, 0x4F, 0xF0, 0x00, 0x0B, 0x7F, 0x1C, 0x76, 0x1C,
+ 0x0E, 0x98, 0x0B, 0xE0, 0xB0, 0x09, 0x10, 0x00, 0x75, 0x19, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x24, 0x52, 0x01, 0x20, 0xFC, 0x4C, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0x86, 0x42, 0xFF, 0xF6,
+ 0x20, 0xAF, 0xBB, 0xF1, 0x01, 0x0F, 0x05, 0xD0, 0x09, 0xF1, 0x01, 0x09, 0xB9, 0xF1, 0x7F, 0x0F,
+ 0x7F, 0xF7, 0x09, 0xAF, 0x58, 0x46, 0x19, 0xB0, 0xCB, 0xE6, 0x2D, 0xE9, 0xF1, 0x4F, 0x98, 0xB0,
+ 0x4F, 0xF0, 0x00, 0x0A, 0x12, 0xF0, 0x61, 0xF8, 0xCD, 0xE9, 0x0E, 0x01, 0x12, 0xF0, 0x5F, 0xF8,
+ 0xCD, 0xE9, 0x10, 0x01, 0x18, 0x98, 0x48, 0xB1, 0xFD, 0x48, 0x00, 0x68, 0xB0, 0xF8, 0x7A, 0x11,
+ 0x18, 0x98, 0xFF, 0xF7, 0xC1, 0xFD, 0x13, 0x90, 0xFA, 0x48, 0x14, 0xE0, 0xF8, 0x4C, 0x20, 0x68,
+ 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0xDD, 0xE9, 0x0E, 0x01, 0x0F, 0xF0,
+ 0x91, 0xFB, 0xCD, 0xE9, 0x0E, 0x01, 0x20, 0x68, 0xB0, 0xF8, 0x72, 0x11, 0x18, 0x98, 0xFF, 0xF7,
+ 0xAB, 0xFD, 0x13, 0x90, 0xF0, 0x48, 0x40, 0x25, 0xCD, 0xE9, 0x04, 0x05, 0x08, 0x21, 0x0E, 0xA8,
+ 0x13, 0xF0, 0x18, 0xFA, 0x03, 0x90, 0x08, 0x21, 0x10, 0xA8, 0x13, 0xF0, 0x13, 0xFA, 0x0A, 0x90,
+ 0xB8, 0x21, 0xEA, 0x48, 0x14, 0xF0, 0x6F, 0xFD, 0x01, 0x20, 0x12, 0x90, 0x00, 0x20, 0x04, 0x46,
+ 0x08, 0x90, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x8D, 0xFC, 0xDD, 0xE9, 0x10, 0x23,
+ 0x81, 0x46, 0x8B, 0x46, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x7D, 0xD0, 0xDC, 0x48, 0x00, 0x68,
+ 0x90, 0xF8, 0x70, 0x01, 0x80, 0x07, 0x13, 0xD5, 0x08, 0x98, 0x80, 0xB1, 0x00, 0x26, 0x0B, 0xE0,
+ 0x31, 0x46, 0x02, 0x9A, 0x04, 0x98, 0x12, 0xF0, 0x5D, 0xFE, 0x03, 0x46, 0x22, 0x46, 0x31, 0x46,
+ 0x04, 0x98, 0x12, 0xF0, 0x62, 0xFE, 0x76, 0x1C, 0x03, 0x98, 0x86, 0x42, 0xF0, 0xDB, 0x02, 0x94,
+ 0x18, 0x98, 0xFF, 0xF7, 0x83, 0xFD, 0xD1, 0x48, 0x4F, 0xF0, 0x01, 0x08, 0xB8, 0x30, 0x00, 0x27,
+ 0x80, 0x68, 0x3E, 0x46, 0x16, 0x90, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x5B, 0xFC,
+ 0xDD, 0xE9, 0x0E, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x45, 0xD0, 0xC7, 0x48, 0x00, 0xEB,
+ 0xC7, 0x01, 0x0D, 0x91, 0xD1, 0xE9, 0x00, 0x01, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0B, 0x01,
+ 0x08, 0x43, 0x2E, 0xD1, 0x22, 0x46, 0x39, 0x46, 0x04, 0x98, 0x12, 0xF0, 0x2B, 0xFE, 0x0A, 0x9A,
+ 0x08, 0x99, 0x07, 0xFB, 0x02, 0x12, 0x16, 0x99, 0x31, 0xF9, 0x12, 0x20, 0x13, 0x99, 0x8A, 0x42,
+ 0x0A, 0xDA, 0x0D, 0x98, 0x0D, 0x99, 0xD0, 0xE9, 0x00, 0x30, 0x43, 0xEA, 0x09, 0x03, 0x40, 0xEA,
+ 0x0B, 0x00, 0xC1, 0xE9, 0x00, 0x30, 0x14, 0xE0, 0x7F, 0x28, 0x06, 0xDA, 0x43, 0x1C, 0x22, 0x46,
+ 0x39, 0x46, 0x04, 0x98, 0x12, 0xF0, 0x19, 0xFE, 0x0B, 0xE0, 0x0D, 0x98, 0x0D, 0x9A, 0xD0, 0xE9,
+ 0x00, 0x10, 0x41, 0xEA, 0x09, 0x01, 0x40, 0xEA, 0x0B, 0x00, 0xC2, 0xE9, 0x00, 0x10, 0x00, 0x20,
+ 0x12, 0x90, 0x0D, 0x99, 0xD1, 0xE9, 0x00, 0x01, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0B, 0x01,
+ 0x08, 0x43, 0x00, 0xD1, 0x80, 0x46, 0x7F, 0x1C, 0x76, 0x1C, 0xAE, 0x42, 0xAB, 0xDB, 0xB8, 0xF1,
+ 0x00, 0x0F, 0x9D, 0xD0, 0x08, 0x98, 0x00, 0xE0, 0x01, 0xE0, 0x40, 0x1C, 0x08, 0x90, 0x05, 0x98,
+ 0x64, 0x1C, 0x84, 0x42, 0xFF, 0xF6, 0x6D, 0xAF, 0x00, 0x20, 0xB9, 0xE0, 0x4F, 0xF0, 0x00, 0x08,
+ 0x46, 0x46, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0xF5, 0xFB, 0xDD, 0xE9, 0x10, 0x23,
+ 0x83, 0x46, 0x03, 0x91, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x76, 0xD0, 0xB8, 0xF1, 0x00, 0x0F,
+ 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0x18, 0x98, 0xFF, 0xF7, 0x00, 0xFD, 0x8F, 0x48, 0x4F, 0xF0,
+ 0x01, 0x09, 0xB8, 0x30, 0x00, 0x24, 0x80, 0x68, 0x27, 0x46, 0x16, 0x90, 0x3A, 0x46, 0x01, 0x20,
+ 0x00, 0x21, 0x14, 0xF0, 0xD8, 0xFB, 0xDD, 0xE9, 0x0E, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43,
+ 0x78, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0x0E, 0xDD, 0x32, 0x46, 0x21, 0x46, 0x04, 0x98, 0x12, 0xF0,
+ 0xB1, 0xFD, 0x82, 0x49, 0x32, 0x46, 0xEC, 0x31, 0x09, 0x57, 0x0B, 0x18, 0x21, 0x46, 0x04, 0x98,
+ 0x12, 0xF0, 0xB3, 0xFD, 0x65, 0xE0, 0xBA, 0xF1, 0x01, 0x0F, 0x12, 0xD1, 0x32, 0x46, 0x21, 0x46,
+ 0x04, 0x98, 0x12, 0xF0, 0x9F, 0xFD, 0x79, 0x49, 0xEC, 0x31, 0x08, 0x55, 0x77, 0x48, 0x00, 0xEB,
+ 0xC4, 0x02, 0xD2, 0xE9, 0x00, 0x01, 0x03, 0x9B, 0x20, 0xEA, 0x0B, 0x00, 0x99, 0x43, 0xC2, 0xE9,
+ 0x00, 0x01, 0x72, 0x48, 0x00, 0xEB, 0xC4, 0x01, 0x0B, 0x91, 0xD1, 0xE9, 0x00, 0x01, 0x03, 0x9A,
+ 0x00, 0xEA, 0x0B, 0x00, 0x11, 0x40, 0x08, 0x43, 0x39, 0xD1, 0x32, 0x46, 0x21, 0x46, 0x04, 0x98,
+ 0x12, 0xF0, 0x80, 0xFD, 0x0A, 0x9A, 0x16, 0x99, 0x04, 0xFB, 0x02, 0x82, 0x31, 0xF9, 0x12, 0x20,
+ 0x13, 0x99, 0x8A, 0x42, 0x10, 0xDA, 0x0B, 0x9A, 0xDD, 0xF8, 0x0C, 0xC0, 0xD2, 0xE9, 0x00, 0x13,
+ 0x41, 0xEA, 0x0B, 0x01, 0x43, 0xEA, 0x0C, 0x03, 0xC2, 0xE9, 0x00, 0x13, 0x5F, 0x49, 0xEC, 0x31,
+ 0x0A, 0x5D, 0x80, 0x1A, 0x08, 0x55, 0x1A, 0xE0, 0x7F, 0x28, 0x07, 0xDA, 0x43, 0x1C, 0x32, 0x46,
+ 0x21, 0x46, 0x04, 0x98, 0x12, 0xF0, 0x69, 0xFD, 0x11, 0xE0, 0x27, 0xE0, 0x0B, 0x99, 0xD1, 0xE9,
+ 0x00, 0x32, 0x03, 0x99, 0x43, 0xEA, 0x0B, 0x03, 0x0A, 0x43, 0x0B, 0x99, 0xC1, 0xE9, 0x00, 0x32,
+ 0x52, 0x49, 0xEC, 0x31, 0x0A, 0x5D, 0x80, 0x1A, 0x08, 0x55, 0x00, 0x20, 0x12, 0x90, 0x0B, 0x98,
+ 0x03, 0x9A, 0xD0, 0xE9, 0x00, 0x10, 0x01, 0xEA, 0x0B, 0x01, 0x10, 0x40, 0x01, 0x43, 0x00, 0xD1,
+ 0x89, 0x46, 0x64, 0x1C, 0x7F, 0x1C, 0xAF, 0x42, 0xFF, 0xF6, 0x78, 0xAF, 0x4F, 0xF0, 0x00, 0x0A,
+ 0xB9, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x67, 0xAF, 0x08, 0xF1, 0x01, 0x08, 0x05, 0x98, 0x76, 0x1C,
+ 0x86, 0x42, 0xFF, 0xF6, 0x4E, 0xAF, 0x18, 0x98, 0xFF, 0xF7, 0x60, 0xFC, 0x0C, 0x98, 0x40, 0x1C,
+ 0x0C, 0x90, 0x3B, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x70, 0x11, 0x0C, 0x98, 0xB0, 0xEB, 0x11, 0x1F,
+ 0xFF, 0xF6, 0x3C, 0xAF, 0x12, 0x98, 0x5E, 0xE6, 0x2D, 0xE9, 0xF0, 0x4F, 0x04, 0x46, 0x85, 0xB0,
+ 0x00, 0x20, 0x12, 0xF0, 0x78, 0xFB, 0x02, 0x20, 0x12, 0xF0, 0x75, 0xFB, 0x11, 0xF0, 0xBF, 0xFE,
+ 0xCD, 0xE9, 0x02, 0x01, 0x32, 0x48, 0x04, 0x90, 0x40, 0x27, 0x08, 0x21, 0x02, 0xA8, 0x13, 0xF0,
+ 0x99, 0xF8, 0x80, 0x46, 0x01, 0x2C, 0x7F, 0xD1, 0xDD, 0xE9, 0x02, 0x01, 0xCD, 0xE9, 0x00, 0x01,
+ 0x01, 0x22, 0x00, 0x23, 0x04, 0x98, 0x12, 0xF0, 0x17, 0xFD, 0xDF, 0xF8, 0xA8, 0x90, 0x00, 0x20,
+ 0x6F, 0xF0, 0x7E, 0x05, 0x09, 0xEB, 0x48, 0x0B, 0x69, 0x0C, 0x04, 0xE0, 0x29, 0xF8, 0x10, 0x10,
+ 0x0B, 0xF8, 0x00, 0x50, 0x40, 0x1C, 0x40, 0x45, 0xF8, 0xDB, 0x03, 0x20, 0xFF, 0xF7, 0x1E, 0xFC,
+ 0x1E, 0x48, 0xB8, 0x30, 0x00, 0x24, 0xD0, 0xF8, 0x08, 0xA0, 0x26, 0x46, 0x32, 0x46, 0x01, 0x20,
+ 0x00, 0x21, 0x14, 0xF0, 0xF8, 0xFA, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43,
+ 0x1D, 0xD0, 0x3A, 0xF9, 0x14, 0x10, 0x39, 0xF9, 0x14, 0x00, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42,
+ 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x81, 0x42, 0x0A, 0xDA, 0x32, 0x46, 0x00, 0x21, 0x04, 0x98,
+ 0x12, 0xF0, 0xC8, 0xFC, 0x0B, 0xF8, 0x04, 0x00, 0x3A, 0xF8, 0x14, 0x10, 0x29, 0xF8, 0x14, 0x10,
+ 0x2B, 0x46, 0x32, 0x46, 0x00, 0x21, 0x04, 0x98, 0x12, 0xF0, 0xC7, 0xFC, 0x64, 0x1C, 0x76, 0x1C,
+ 0xBE, 0x42, 0xD3, 0xDB, 0x6D, 0x1C, 0x7F, 0x2D, 0xC7, 0xDD, 0x00, 0x25, 0x2C, 0x46, 0x0B, 0xE0,
+ 0x20, 0x07, 0x10, 0x00, 0x24, 0x52, 0x01, 0x20, 0xFC, 0x4C, 0x01, 0x20, 0xF8, 0x08, 0x10, 0x00,
+ 0xF8, 0x5B, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0,
+ 0xBA, 0xFA, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x07, 0xD0, 0x1B, 0xF9,
+ 0x05, 0x30, 0x22, 0x46, 0x00, 0x21, 0x04, 0x98, 0x12, 0xF0, 0x9F, 0xFC, 0x6D, 0x1C, 0x64, 0x1C,
+ 0xBC, 0x42, 0xDC, 0xDB, 0x76, 0x48, 0x26, 0x22, 0x04, 0x99, 0x00, 0x68, 0x00, 0xF5, 0x86, 0x50,
+ 0x00, 0xE0, 0x01, 0xE0, 0x14, 0xF0, 0xD6, 0xFA, 0x00, 0x26, 0x72, 0x4D, 0x34, 0x46, 0x22, 0x46,
+ 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x97, 0xFA, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40,
+ 0x08, 0x43, 0x07, 0xD0, 0x22, 0x46, 0x00, 0x21, 0x04, 0x98, 0x12, 0xF0, 0x73, 0xFC, 0x25, 0xF8,
+ 0x16, 0x00, 0x76, 0x1C, 0x64, 0x1C, 0xBC, 0x42, 0xE9, 0xDB, 0x03, 0x20, 0xFF, 0xF7, 0x9E, 0xFB,
+ 0x65, 0x48, 0x81, 0x68, 0x00, 0x20, 0x06, 0xE0, 0x31, 0xF8, 0x10, 0x30, 0x08, 0xEB, 0x00, 0x02,
+ 0x40, 0x1C, 0x25, 0xF8, 0x12, 0x30, 0x40, 0x45, 0xF6, 0xDB, 0x02, 0x20, 0x12, 0xF0, 0xD6, 0xFA,
+ 0x00, 0x20, 0x12, 0xF0, 0xD3, 0xFA, 0x05, 0xB0, 0x63, 0xE4, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46,
+ 0x01, 0x24, 0x00, 0x20, 0x12, 0xF0, 0xAF, 0xFA, 0x02, 0x20, 0x12, 0xF0, 0xAC, 0xFA, 0x54, 0x4E,
+ 0xE8, 0x07, 0x4F, 0xF0, 0x00, 0x07, 0x4F, 0xF0, 0xA5, 0x08, 0x08, 0xD0, 0x00, 0xF0, 0x20, 0xF8,
+ 0x10, 0xF0, 0x01, 0x04, 0x03, 0xD0, 0x30, 0x68, 0xC7, 0x76, 0x80, 0xF8, 0x1A, 0x80, 0xA8, 0x07,
+ 0x08, 0xD5, 0x00, 0xF0, 0x63, 0xF8, 0x20, 0x40, 0x04, 0x00, 0x03, 0xD0, 0x30, 0x68, 0x47, 0x77,
+ 0x80, 0xF8, 0x1C, 0x80, 0x00, 0x20, 0x12, 0xF0, 0xA9, 0xFA, 0x02, 0x20, 0x12, 0xF0, 0xA6, 0xFA,
+ 0xE8, 0x07, 0x02, 0xD0, 0x01, 0x20, 0x00, 0xF0, 0xBB, 0xF8, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81,
+ 0x2D, 0xE9, 0xFC, 0x47, 0x01, 0x26, 0x11, 0xF0, 0xC8, 0xFD, 0x04, 0x46, 0x0D, 0x46, 0x11, 0xF0,
+ 0xC6, 0xFD, 0xDF, 0xF8, 0xF8, 0x90, 0x07, 0x46, 0x88, 0x46, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8,
+ 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x05, 0xD0, 0x20, 0x46, 0x29, 0x46, 0x0F, 0xF0, 0x02, 0xF9,
+ 0x04, 0x46, 0x0D, 0x46, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x70, 0x01, 0xC0, 0x07, 0x27, 0xD0,
+ 0xCD, 0xE9, 0x00, 0x78, 0x22, 0x46, 0x2B, 0x46, 0x31, 0x48, 0x12, 0xF0, 0x15, 0xFC, 0xD9, 0xF8,
+ 0x00, 0x00, 0x90, 0xF8, 0x70, 0x11, 0xC9, 0x07, 0x1A, 0xD0, 0x90, 0xF8, 0xE8, 0x10, 0x89, 0x07,
+ 0x03, 0xD4, 0x00, 0x20, 0xFF, 0xF7, 0x31, 0xFD, 0x0C, 0xE0, 0x90, 0xF8, 0xE7, 0x00, 0xC0, 0xF3,
+ 0x41, 0x10, 0x02, 0x28, 0x4F, 0xF0, 0x00, 0x00, 0x02, 0xD3, 0xFF, 0xF7, 0xF4, 0xFB, 0x01, 0xE0,
+ 0xFF, 0xF7, 0x53, 0xFB, 0x06, 0x00, 0x03, 0xD1, 0x01, 0x21, 0x74, 0x20, 0x0D, 0xF0, 0xC4, 0xFF,
+ 0x00, 0x20, 0xFF, 0xF7, 0x0B, 0xFB, 0x30, 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x2D, 0xE9, 0xFC, 0x41,
+ 0x01, 0x24, 0x11, 0xF0, 0x7A, 0xFD, 0x05, 0x46, 0x0E, 0x46, 0x11, 0xF0, 0x78, 0xFD, 0x17, 0x4F,
+ 0x3A, 0x68, 0x92, 0xF8, 0x78, 0x21, 0xD2, 0x07, 0x1C, 0xD0, 0xCD, 0xE9, 0x00, 0x01, 0x2A, 0x46,
+ 0x33, 0x46, 0x14, 0x48, 0x12, 0xF0, 0xD8, 0xFB, 0x38, 0x68, 0x90, 0xF8, 0x78, 0x11, 0xC9, 0x07,
+ 0x10, 0xD0, 0x90, 0xF8, 0xE8, 0x00, 0x80, 0x07, 0x20, 0x46, 0x02, 0xD4, 0xFF, 0xF7, 0xF5, 0xFC,
+ 0x01, 0xE0, 0xFF, 0xF7, 0x22, 0xFB, 0x04, 0x00, 0x04, 0xD1, 0x4F, 0xF4, 0x80, 0x71, 0x74, 0x20,
+ 0x0D, 0xF0, 0x92, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0xD9, 0xFA, 0x20, 0x46, 0xBD, 0xE8, 0xFC, 0x81,
+ 0x24, 0x07, 0x10, 0x00, 0xE0, 0x4A, 0x01, 0x20, 0xB0, 0x09, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xFC, 0x4C, 0x01, 0x20, 0x24, 0x52, 0x01, 0x20, 0x10, 0xB5, 0xFF, 0xF7, 0x8C, 0xFA, 0x01, 0x20,
+ 0xFF, 0xF7, 0x72, 0xFE, 0x01, 0x20, 0x00, 0xF0, 0xA4, 0xF9, 0x53, 0x20, 0xFF, 0xF7, 0x35, 0xFF,
+ 0x00, 0x28, 0x0B, 0xD0, 0x4F, 0xF4, 0xD6, 0x70, 0x00, 0xF0, 0xF7, 0xFF, 0x00, 0x28, 0x05, 0xD0,
+ 0xFE, 0xF7, 0xF1, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0x88, 0xBE, 0x10, 0xBD, 0x10, 0xB5,
+ 0xFF, 0xF7, 0x71, 0xFA, 0x01, 0x20, 0xFF, 0xF7, 0x57, 0xFE, 0x01, 0x20, 0x00, 0xF0, 0x89, 0xF9,
+ 0x40, 0xF2, 0xFF, 0x10, 0xFE, 0xF7, 0x02, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0x76, 0xBE,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x12, 0x49, 0x09, 0x68, 0x91, 0xF8, 0xC1, 0x21, 0xD2, 0x07, 0x1D, 0xD0,
+ 0x01, 0x28, 0x1B, 0xD1, 0x10, 0x4F, 0x91, 0xF8, 0x31, 0x20, 0x91, 0xF8, 0x30, 0x10, 0x3D, 0x68,
+ 0x4A, 0x43, 0x02, 0x20, 0x0B, 0x4E, 0x14, 0xB2, 0x32, 0x35, 0xFE, 0xF7, 0x53, 0xF9, 0x03, 0x20,
+ 0x12, 0xF0, 0xB1, 0xF9, 0x38, 0x68, 0x62, 0x00, 0x31, 0x46, 0x04, 0x86, 0x28, 0x46, 0x14, 0xF0,
+ 0x99, 0xF9, 0xBD, 0xE8, 0xF0, 0x41, 0x03, 0x20, 0x12, 0xF0, 0xC0, 0xB9, 0xBD, 0xE8, 0xF0, 0x81,
+ 0x20, 0x07, 0x10, 0x00, 0x2E, 0x44, 0x01, 0x20, 0x24, 0x07, 0x10, 0x00, 0x10, 0xB5, 0x01, 0x46,
+ 0x34, 0x22, 0xFE, 0x48, 0x14, 0xF0, 0xCB, 0xF9, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20,
+ 0x12, 0xF0, 0xF1, 0xB8, 0x30, 0xB5, 0x85, 0xB0, 0x01, 0x24, 0x68, 0x46, 0x11, 0xF0, 0x36, 0xFC,
+ 0xF7, 0x4B, 0x02, 0x22, 0x03, 0x21, 0x18, 0x78, 0xE0, 0xB1, 0x01, 0x28, 0x0D, 0xD0, 0x03, 0x28,
+ 0x0E, 0xD0, 0x02, 0x28, 0x19, 0xD0, 0x04, 0x22, 0x05, 0x28, 0x0C, 0xD0, 0x04, 0x28, 0x0D, 0xD0,
+ 0x06, 0x28, 0x0F, 0xD0, 0x07, 0x28, 0x10, 0xD0, 0x11, 0xE0, 0x8D, 0xF8, 0x06, 0x10, 0x0E, 0xE0,
+ 0x8D, 0xF8, 0x08, 0x10, 0x0B, 0xE0, 0x8D, 0xF8, 0x0A, 0x20, 0x01, 0xE0, 0x8D, 0xF8, 0x0A, 0x10,
+ 0x00, 0x24, 0x04, 0xE0, 0x8D, 0xF8, 0x06, 0x20, 0x01, 0xE0, 0x8D, 0xF8, 0x08, 0x20, 0xE5, 0x48,
+ 0x00, 0x90, 0xE5, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0x07, 0x21, 0xD0, 0x04, 0xB3,
+ 0xD8, 0x79, 0x10, 0xB1, 0x8D, 0xF8, 0x0B, 0x10, 0x02, 0xE0, 0x01, 0x20, 0x8D, 0xF8, 0x0B, 0x00,
+ 0xDA, 0x4D, 0x03, 0x24, 0x68, 0x46, 0x11, 0xF0, 0x1E, 0xFC, 0x00, 0x22, 0x04, 0xAB, 0x01, 0x21,
+ 0x10, 0x46, 0x12, 0xF0, 0xF1, 0xF8, 0x01, 0x21, 0x00, 0x20, 0x12, 0xF0, 0xD0, 0xF8, 0x28, 0x78,
+ 0x00, 0x28, 0x04, 0xD0, 0x0D, 0xF0, 0xD7, 0xFE, 0x64, 0x1E, 0x00, 0x2C, 0xEA, 0xDC, 0x05, 0xB0,
+ 0x30, 0xBD, 0x00, 0x20, 0xE2, 0xE7, 0x2D, 0xE9, 0xF3, 0x4F, 0xCD, 0x4D, 0x87, 0xB0, 0x06, 0x20,
+ 0x0E, 0x46, 0x28, 0x70, 0x11, 0xF0, 0x79, 0xFC, 0xCD, 0xE9, 0x04, 0x01, 0x36, 0x20, 0x02, 0x90,
+ 0xCA, 0x4C, 0x07, 0x98, 0x4F, 0xF0, 0x40, 0x0A, 0xC0, 0xB1, 0x01, 0x28, 0x21, 0xD0, 0x02, 0x28,
+ 0x7E, 0xD1, 0x07, 0x20, 0x28, 0x70, 0xC6, 0x48, 0xDF, 0xF8, 0x00, 0x83, 0x00, 0x90, 0x20, 0x68,
+ 0x08, 0xF1, 0x28, 0x08, 0x41, 0xF2, 0x42, 0x11, 0x08, 0x44, 0x01, 0x90, 0x08, 0x21, 0x04, 0xA8,
+ 0x12, 0xF0, 0x40, 0xFE, 0x04, 0x46, 0x01, 0x2E, 0x1E, 0xD0, 0x8A, 0xE0, 0xBC, 0x48, 0xDF, 0xF8,
+ 0xDC, 0x82, 0x48, 0x38, 0x00, 0x90, 0x08, 0xF1, 0x18, 0x08, 0x41, 0xF2, 0xE6, 0x01, 0x20, 0x68,
+ 0xEA, 0xE7, 0x11, 0xF0, 0x4C, 0xFC, 0xCD, 0xE9, 0x04, 0x01, 0xB5, 0x48, 0x41, 0xF2, 0x1C, 0x11,
+ 0x28, 0x38, 0x00, 0x90, 0x20, 0x68, 0xDF, 0xF8, 0xB4, 0x82, 0x08, 0x44, 0x01, 0x90, 0x26, 0x20,
+ 0x08, 0xF1, 0x1C, 0x08, 0x02, 0x90, 0xD9, 0xE7, 0x02, 0x46, 0x04, 0xA9, 0x00, 0x98, 0x12, 0xF0,
+ 0xE3, 0xFA, 0xDF, 0xF8, 0xB0, 0x92, 0x6F, 0xF0, 0x7E, 0x06, 0x09, 0xEB, 0x44, 0x00, 0x03, 0x90,
+ 0x00, 0x20, 0x71, 0x0C, 0x05, 0xE0, 0x00, 0xBF, 0x29, 0xF8, 0x10, 0x10, 0x03, 0x9A, 0x16, 0x54,
+ 0x40, 0x1C, 0xA0, 0x42, 0xF8, 0xDB, 0x00, 0xBF, 0xFF, 0xF7, 0x44, 0xFF, 0x00, 0x25, 0xD8, 0xF8,
+ 0x00, 0xB0, 0x2F, 0x46, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x84, 0xF8, 0xDD, 0xE9,
+ 0x04, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x1B, 0xD0, 0x3B, 0xF9, 0x15, 0x10, 0x39, 0xF9,
+ 0x15, 0x00, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x81, 0x42,
+ 0x09, 0xDA, 0x39, 0x46, 0x00, 0x98, 0x12, 0xF0, 0x9D, 0xFA, 0x03, 0x99, 0x48, 0x55, 0x3B, 0xF8,
+ 0x15, 0x10, 0x29, 0xF8, 0x15, 0x10, 0x32, 0x46, 0x39, 0x46, 0x00, 0x98, 0x12, 0xF0, 0x99, 0xFA,
+ 0x6D, 0x1C, 0xA5, 0x42, 0x02, 0xD0, 0x7F, 0x1C, 0x57, 0x45, 0xD3, 0xDB, 0x76, 0x1C, 0x00, 0xE0,
+ 0x54, 0xE0, 0x7F, 0x2E, 0xC8, 0xDD, 0x00, 0x26, 0x35, 0x46, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x14, 0xF0, 0x51, 0xF8, 0xDD, 0xE9, 0x04, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x06, 0xD0,
+ 0x03, 0x98, 0x29, 0x46, 0x82, 0x57, 0x00, 0x98, 0x12, 0xF0, 0x7B, 0xFA, 0x76, 0x1C, 0xA6, 0x42,
+ 0x02, 0xD0, 0x6D, 0x1C, 0x55, 0x45, 0xE8, 0xDB, 0xDD, 0xE9, 0x00, 0x10, 0x02, 0x9A, 0x14, 0xF0,
+ 0x71, 0xF8, 0x07, 0x98, 0x30, 0xB1, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x06, 0xD0, 0x03, 0x28,
+ 0x05, 0xD1, 0x03, 0xE0, 0x74, 0x4E, 0x02, 0xE0, 0x74, 0x4E, 0x00, 0xE0, 0x74, 0x4E, 0x00, 0x27,
+ 0x3D, 0x46, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x14, 0xF0, 0x25, 0xF8, 0xDD, 0xE9, 0x04, 0x23,
+ 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x06, 0xD0, 0x29, 0x46, 0x00, 0x98, 0x12, 0xF0, 0x4A, 0xFA,
+ 0x26, 0xF8, 0x17, 0x00, 0x7F, 0x1C, 0xA7, 0x42, 0x02, 0xD0, 0x6D, 0x1C, 0x55, 0x45, 0xE8, 0xDB,
+ 0xFF, 0xF7, 0xC8, 0xFE, 0x00, 0x20, 0xD8, 0xF8, 0x00, 0x10, 0x05, 0xE0, 0x31, 0xF8, 0x10, 0x20,
+ 0x23, 0x18, 0x40, 0x1C, 0x26, 0xF8, 0x13, 0x20, 0xA0, 0x42, 0xF7, 0xDB, 0x09, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x12, 0xF0, 0x45, 0xF8, 0x02, 0x20, 0x12, 0xF0,
+ 0x42, 0xF8, 0x21, 0x46, 0x00, 0x20, 0xFF, 0xF7, 0x06, 0xFF, 0x21, 0x46, 0x01, 0x20, 0xFF, 0xF7,
+ 0x02, 0xFF, 0x21, 0x46, 0x02, 0x20, 0xFF, 0xF7, 0xFE, 0xFE, 0x02, 0x20, 0x12, 0xF0, 0x4E, 0xF8,
+ 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x12, 0xF0, 0x49, 0xB8, 0x2D, 0xE9, 0xF0, 0x47, 0x48, 0x48,
+ 0x00, 0x25, 0x2C, 0x46, 0xD0, 0xE9, 0x14, 0x78, 0xD0, 0xF8, 0x38, 0x90, 0x2E, 0x46, 0x82, 0x46,
+ 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x13, 0xF0, 0xD6, 0xFF, 0x38, 0x40, 0x01, 0xEA, 0x08, 0x01,
+ 0x08, 0x43, 0x04, 0xD0, 0x19, 0xF8, 0x06, 0x00, 0xA8, 0x42, 0x00, 0xD9, 0x05, 0x46, 0x76, 0x1C,
+ 0x40, 0x2E, 0xED, 0xD3, 0xDA, 0xE9, 0x16, 0x78, 0xDA, 0xF8, 0x3C, 0x90, 0x00, 0x26, 0x32, 0x46,
+ 0x01, 0x20, 0x00, 0x21, 0x13, 0xF0, 0xBF, 0xFF, 0x38, 0x40, 0x01, 0xEA, 0x08, 0x01, 0x08, 0x43,
+ 0x04, 0xD0, 0x19, 0xF8, 0x06, 0x00, 0xA0, 0x42, 0x00, 0xD9, 0x04, 0x46, 0x76, 0x1C, 0x40, 0x2E,
+ 0xED, 0xD3, 0xDA, 0xF8, 0x48, 0x20, 0x50, 0x46, 0x15, 0x70, 0xDA, 0xF8, 0x4C, 0x10, 0x0C, 0x70,
+ 0xDA, 0xF8, 0x30, 0x30, 0xDA, 0xF8, 0x28, 0x70, 0xDA, 0xF8, 0x34, 0x60, 0x1B, 0x78, 0x3F, 0x78,
+ 0x2B, 0x44, 0x3B, 0x44, 0xDA, 0xF8, 0x2C, 0x70, 0x36, 0x78, 0x3F, 0x78, 0x26, 0x44, 0x3E, 0x44,
+ 0xD0, 0xE9, 0x14, 0x7C, 0x57, 0xEA, 0x0C, 0x07, 0x0D, 0xD0, 0xD0, 0xE9, 0x16, 0x7C, 0x57, 0xEA,
+ 0x0C, 0x07, 0x0A, 0xD0, 0xFF, 0x27, 0xB3, 0x42, 0x13, 0xD2, 0xF3, 0x1A, 0x2B, 0x44, 0xFF, 0x2B,
+ 0x07, 0xD8, 0x13, 0x70, 0x0B, 0xE0, 0x14, 0x70, 0x09, 0xE0, 0x15, 0x70, 0x0D, 0x70, 0xBD, 0xE8,
+ 0xF0, 0x87, 0x17, 0x70, 0xC2, 0x69, 0x42, 0xF4, 0x00, 0x72, 0xCA, 0xF8, 0x1C, 0x20, 0x0C, 0x70,
+ 0xF5, 0xE7, 0x9E, 0x42, 0x0D, 0xD2, 0x9B, 0x1B, 0x23, 0x44, 0xFF, 0x2B, 0x01, 0xD8, 0x0B, 0x70,
+ 0x05, 0xE0, 0x0F, 0x70, 0xC1, 0x69, 0x41, 0xF4, 0x00, 0x71, 0xCA, 0xF8, 0x1C, 0x10, 0x15, 0x70,
+ 0xE5, 0xE7, 0x15, 0x70, 0xEB, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x1F, 0x46, 0x0D, 0x46, 0x00, 0x2A,
+ 0x34, 0xDD, 0x07, 0x4C, 0x1F, 0xB3, 0xB4, 0xF9, 0x0C, 0x60, 0x11, 0x46, 0x0F, 0xF0, 0x01, 0xFC,
+ 0xB0, 0x42, 0x28, 0x78, 0x27, 0xDA, 0xFF, 0x28, 0x1C, 0xD2, 0x13, 0xE0, 0xFC, 0x09, 0x10, 0x00,
+ 0x68, 0x04, 0x10, 0x00, 0xAD, 0x24, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00,
+ 0x68, 0x5C, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0x78, 0x4B, 0x01, 0x20, 0xCC, 0x4B, 0x01, 0x20,
+ 0x64, 0x4C, 0x01, 0x20, 0x40, 0x1C, 0x28, 0x70, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0xB4, 0xF9,
+ 0x0A, 0x60, 0xDA, 0xE7, 0xE0, 0x69, 0x1F, 0xB1, 0x40, 0xF0, 0x02, 0x00, 0xE0, 0x61, 0x05, 0xE0,
+ 0x40, 0xF4, 0x00, 0x60, 0xFA, 0xE7, 0x08, 0xB1, 0x40, 0x1E, 0x28, 0x70, 0x01, 0x20, 0xEC, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x1E, 0x46, 0x0D, 0x46, 0x00, 0x2A, 0x1A, 0xDD, 0xFE, 0x4C, 0x66, 0xB1,
+ 0xB4, 0xF9, 0x0C, 0x70, 0x11, 0x46, 0x0F, 0xF0, 0xC4, 0xFB, 0xB8, 0x42, 0x11, 0xDD, 0x28, 0x78,
+ 0x50, 0xB1, 0x10, 0x28, 0x04, 0xD3, 0x10, 0x38, 0x03, 0xE0, 0xB4, 0xF9, 0x0A, 0x70, 0xF1, 0xE7,
+ 0x00, 0x20, 0x28, 0x70, 0x00, 0x20, 0xD0, 0xE7, 0xE0, 0x69, 0x26, 0xB1, 0x40, 0xF0, 0x01, 0x00,
+ 0xE0, 0x61, 0x01, 0x20, 0xC9, 0xE7, 0x40, 0xF4, 0x80, 0x60, 0xF9, 0xE7, 0x2D, 0xE9, 0xF1, 0x4F,
+ 0x82, 0xB0, 0x00, 0x25, 0xEC, 0x48, 0x02, 0x9A, 0x2C, 0x46, 0xFF, 0x21, 0x02, 0xB3, 0xD0, 0xF8,
+ 0x30, 0x90, 0x02, 0x26, 0x4F, 0xF0, 0x18, 0x0B, 0x89, 0xF8, 0x00, 0x10, 0xD0, 0xF8, 0x34, 0x80,
+ 0x88, 0xF8, 0x00, 0x10, 0xB0, 0xF9, 0x0C, 0x70, 0x31, 0x02, 0x00, 0x91, 0x41, 0x69, 0x00, 0x29,
+ 0x00, 0xDC, 0x01, 0x25, 0xE0, 0x48, 0x80, 0x69, 0x00, 0x28, 0x00, 0xDC, 0x01, 0x24, 0xFF, 0xF7,
+ 0xFC, 0xFE, 0xFF, 0xF7, 0x97, 0xFD, 0x00, 0x98, 0x0D, 0xF0, 0x49, 0xFC, 0x85, 0xB1, 0x21, 0xE0,
+ 0xD0, 0xF8, 0x28, 0x90, 0x4F, 0xF4, 0x00, 0x66, 0x4F, 0xF0, 0x18, 0x0B, 0x89, 0xF8, 0x00, 0x10,
+ 0xD0, 0xF8, 0x2C, 0x80, 0x88, 0xF8, 0x00, 0x10, 0xB0, 0xF9, 0x0A, 0x70, 0xF1, 0x10, 0xDC, 0xE7,
+ 0xDF, 0xF8, 0x44, 0xA3, 0x3A, 0x46, 0xDA, 0xF8, 0x20, 0x00, 0xDA, 0xF8, 0x14, 0x10, 0x00, 0x68,
+ 0x00, 0xF0, 0x54, 0xFD, 0x01, 0x28, 0x05, 0xD1, 0xDA, 0xF8, 0x1C, 0x10, 0x31, 0x43, 0x01, 0x25,
+ 0xCA, 0xF8, 0x1C, 0x10, 0x8C, 0xB9, 0xDF, 0xF8, 0x20, 0xA3, 0x3A, 0x46, 0xDA, 0xF8, 0x24, 0x00,
+ 0xDA, 0xF8, 0x18, 0x10, 0x00, 0x68, 0x00, 0xF0, 0x41, 0xFD, 0x01, 0x28, 0x05, 0xD1, 0xDA, 0xF8,
+ 0x1C, 0x10, 0x31, 0x43, 0x01, 0x24, 0xCA, 0xF8, 0x1C, 0x10, 0x0D, 0xB1, 0x00, 0x2C, 0x4E, 0xD1,
+ 0x2F, 0x46, 0x26, 0x46, 0x4F, 0xF0, 0x17, 0x0A, 0x4F, 0xB9, 0xBB, 0x48, 0x02, 0x9B, 0x01, 0x6A,
+ 0x42, 0x69, 0x0F, 0x68, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x6A, 0xFF, 0x07, 0x46, 0x4E, 0xB9,
+ 0xB5, 0x48, 0x02, 0x9B, 0x41, 0x6A, 0x82, 0x69, 0x0E, 0x68, 0x41, 0x46, 0x30, 0x46, 0xFF, 0xF7,
+ 0x5F, 0xFF, 0x06, 0x46, 0xFF, 0xF7, 0xA1, 0xFE, 0xFF, 0xF7, 0x3C, 0xFD, 0x00, 0x98, 0x0D, 0xF0,
+ 0xEE, 0xFB, 0x07, 0xB1, 0x16, 0xB9, 0xBA, 0xF1, 0x01, 0x0A, 0xDD, 0xD2, 0x2F, 0x46, 0xAA, 0x4D,
+ 0xAB, 0xF1, 0x01, 0x06, 0x3F, 0xB9, 0x28, 0x6A, 0x02, 0x9B, 0x49, 0x46, 0x00, 0x68, 0x6A, 0x69,
+ 0xFF, 0xF7, 0x09, 0xFF, 0x07, 0x46, 0x3C, 0xB9, 0x68, 0x6A, 0x02, 0x9B, 0x41, 0x46, 0x00, 0x68,
+ 0xAA, 0x69, 0xFF, 0xF7, 0x00, 0xFF, 0x04, 0x46, 0xFF, 0xF7, 0x7F, 0xFE, 0xFF, 0xF7, 0x1A, 0xFD,
+ 0x00, 0x98, 0x0D, 0xF0, 0xCC, 0xFB, 0x07, 0xB1, 0x0C, 0xB9, 0x76, 0x1E, 0xE2, 0xD2, 0x01, 0x2F,
+ 0x05, 0xD1, 0x01, 0x2C, 0x03, 0xD1, 0xE8, 0x69, 0x20, 0xF4, 0x00, 0x70, 0xE8, 0x61, 0xBD, 0xE8,
+ 0xFE, 0x8F, 0x2D, 0xE9, 0xF0, 0x4F, 0x9A, 0x46, 0x91, 0x46, 0x00, 0x22, 0x92, 0x4B, 0x83, 0x46,
+ 0x14, 0x46, 0xB3, 0xF9, 0x0E, 0x70, 0x10, 0x46, 0x01, 0x23, 0x90, 0x46, 0x15, 0xE0, 0x00, 0xBF,
+ 0x09, 0xEB, 0xE4, 0x05, 0x04, 0xF0, 0x07, 0x0C, 0x2E, 0x78, 0x03, 0xFA, 0x0C, 0xF5, 0x35, 0x42,
+ 0x0A, 0xD0, 0x3B, 0xF9, 0x12, 0x50, 0xBD, 0x42, 0x03, 0xDC, 0x0A, 0xF8, 0x02, 0x30, 0x01, 0x20,
+ 0x01, 0xE0, 0x0A, 0xF8, 0x02, 0x80, 0x52, 0x1C, 0x64, 0x1C, 0x8A, 0x42, 0xE8, 0xDB, 0x26, 0xE6,
+ 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0x9A, 0x46, 0x17, 0x46, 0x25, 0x46,
+ 0xDF, 0xF8, 0xF4, 0x91, 0x46, 0x46, 0xDD, 0xF8, 0x3C, 0xB0, 0x4E, 0xE0, 0x0A, 0xEB, 0xE5, 0x00,
+ 0x05, 0xF0, 0x07, 0x01, 0x00, 0x78, 0x06, 0xFA, 0x01, 0xF2, 0x02, 0x42, 0x44, 0xD0, 0x1B, 0xF8,
+ 0x04, 0x00, 0x01, 0x28, 0x3F, 0xD0, 0x00, 0x98, 0xB9, 0xF9, 0x0E, 0x10, 0x30, 0xF9, 0x14, 0x20,
+ 0x8A, 0x42, 0x1D, 0xDA, 0x29, 0x46, 0x01, 0x98, 0x12, 0xF0, 0x61, 0xF8, 0xFF, 0x28, 0x0E, 0xDA,
+ 0x40, 0x1C, 0xC2, 0xB2, 0x4F, 0xF0, 0x00, 0x08, 0x29, 0x46, 0x01, 0x98, 0x12, 0xF0, 0x59, 0xF8,
+ 0x00, 0x98, 0x30, 0xF8, 0x14, 0x10, 0x0E, 0x98, 0x20, 0xF8, 0x14, 0x10, 0x23, 0xE0, 0x0B, 0xF8,
+ 0x04, 0x60, 0xD9, 0xF8, 0x1C, 0x10, 0x41, 0xF0, 0x08, 0x01, 0xC9, 0xF8, 0x1C, 0x10, 0x1A, 0xE0,
+ 0x0E, 0x98, 0x30, 0xF9, 0x14, 0x00, 0x00, 0x28, 0x13, 0xDD, 0x40, 0x1A, 0xA2, 0xEB, 0x01, 0x01,
+ 0x00, 0xD5, 0x40, 0x42, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42, 0x88, 0x42, 0x09, 0xDC, 0x29, 0x46,
+ 0x01, 0x98, 0x12, 0xF0, 0x34, 0xF8, 0x40, 0x1E, 0xC2, 0xB2, 0x29, 0x46, 0x01, 0x98, 0x12, 0xF0,
+ 0x30, 0xF8, 0x0B, 0xF8, 0x04, 0x60, 0x64, 0x1C, 0x6D, 0x1C, 0xBC, 0x42, 0xAE, 0xDB, 0x40, 0x46,
+ 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08,
+ 0x9A, 0x46, 0x17, 0x46, 0x25, 0x46, 0x46, 0x46, 0xDF, 0xF8, 0x2C, 0x91, 0xDD, 0xF8, 0x38, 0xB0,
+ 0x31, 0xE0, 0x00, 0xBF, 0x0A, 0xEB, 0xE5, 0x00, 0x05, 0xF0, 0x07, 0x02, 0x01, 0x78, 0x06, 0xFA,
+ 0x02, 0xF0, 0x08, 0x42, 0x26, 0xD0, 0x1B, 0xF8, 0x04, 0x00, 0x01, 0x28, 0x21, 0xD0, 0x00, 0x98,
+ 0x30, 0xF9, 0x14, 0x10, 0xB9, 0xF9, 0x0E, 0x00, 0x81, 0x42, 0x1A, 0xDD, 0x29, 0x46, 0x01, 0x98,
+ 0x11, 0xF0, 0xFD, 0xFF, 0x00, 0x28, 0x0C, 0xDD, 0x4F, 0xF0, 0x00, 0x08, 0x04, 0x28, 0x01, 0xDB,
+ 0x00, 0x1F, 0x00, 0xE0, 0x00, 0x20, 0xC2, 0xB2, 0x29, 0x46, 0x01, 0x98, 0x11, 0xF0, 0xF1, 0xFF,
+ 0x07, 0xE0, 0x0B, 0xF8, 0x04, 0x60, 0xD9, 0xF8, 0x1C, 0x10, 0x41, 0xF0, 0x04, 0x01, 0xC9, 0xF8,
+ 0x1C, 0x10, 0x64, 0x1C, 0x6D, 0x1C, 0xBC, 0x42, 0xCC, 0xDB, 0x40, 0x46, 0xB8, 0xE7, 0x2D, 0xE9,
+ 0xF0, 0x4F, 0x93, 0xB0, 0x00, 0x24, 0x25, 0x46, 0x18, 0x21, 0x0C, 0xA8, 0x13, 0xF0, 0x53, 0xFE,
+ 0x28, 0x21, 0x02, 0xA8, 0x13, 0xF0, 0x4F, 0xFE, 0x27, 0x48, 0x41, 0x69, 0x00, 0x29, 0x00, 0xDC,
+ 0x01, 0x24, 0x82, 0x69, 0x00, 0x2A, 0x00, 0xDC, 0x01, 0x25, 0x23, 0x4A, 0x81, 0x46, 0x06, 0x46,
+ 0xFF, 0x23, 0x50, 0x32, 0x80, 0x6B, 0x00, 0xF0, 0x03, 0xFC, 0x1F, 0x4A, 0xFF, 0x23, 0x58, 0x32,
+ 0xB1, 0x69, 0xF0, 0x6B, 0x00, 0xF0, 0xFC, 0xFB, 0xFF, 0xF7, 0x77, 0xFD, 0xFF, 0xF7, 0x12, 0xFC,
+ 0x4F, 0xF4, 0x80, 0x6A, 0x50, 0x46, 0x0D, 0xF0, 0xC2, 0xFA, 0x8C, 0xB1, 0xD9, 0xF8, 0x20, 0x00,
+ 0x15, 0x4A, 0x4E, 0x46, 0x00, 0x68, 0x0C, 0xAB, 0x50, 0x32, 0xD9, 0xF8, 0x14, 0x10, 0xFF, 0xF7,
+ 0xF8, 0xFE, 0x01, 0x28, 0x04, 0xD1, 0xF0, 0x69, 0x01, 0x24, 0x40, 0xF0, 0x08, 0x00, 0xF0, 0x61,
+ 0x8D, 0xB1, 0xD9, 0xF8, 0x24, 0x00, 0x0C, 0x4A, 0x4E, 0x46, 0x00, 0x68, 0x02, 0xAB, 0x58, 0x32,
+ 0xD9, 0xF8, 0x18, 0x10, 0xFF, 0xF7, 0xE5, 0xFE, 0x01, 0x28, 0x04, 0xD1, 0xF0, 0x69, 0x01, 0x25,
+ 0x40, 0xF0, 0x08, 0x00, 0xF0, 0x61, 0x0C, 0xB1, 0x00, 0x2D, 0x79, 0xD1, 0x26, 0x46, 0xA8, 0x46,
+ 0x00, 0x27, 0x7E, 0xB9, 0x0C, 0xA8, 0x01, 0xE0, 0x68, 0x04, 0x10, 0x00, 0x00, 0x90, 0xD9, 0xF8,
+ 0x20, 0x00, 0xFD, 0x4B, 0xD9, 0xF8, 0x14, 0x20, 0x00, 0x68, 0xD9, 0xF8, 0x38, 0x10, 0xFF, 0xF7,
+ 0x52, 0xFF, 0x06, 0x46, 0xB8, 0xF1, 0x00, 0x0F, 0x0D, 0xD1, 0x02, 0xA8, 0x00, 0x90, 0xD9, 0xF8,
+ 0x24, 0x10, 0xF5, 0x4B, 0xD9, 0xF8, 0x18, 0x20, 0x08, 0x68, 0x08, 0x33, 0xD9, 0xF8, 0x3C, 0x10,
+ 0xFF, 0xF7, 0x41, 0xFF, 0x80, 0x46, 0xFF, 0xF7, 0x20, 0xFD, 0xFF, 0xF7, 0xBB, 0xFB, 0x50, 0x46,
+ 0x0D, 0xF0, 0x6D, 0xFA, 0x16, 0xB1, 0xB8, 0xF1, 0x00, 0x0F, 0x02, 0xD1, 0x7F, 0x1C, 0x60, 0x2F,
+ 0xCF, 0xDB, 0xDF, 0xF8, 0xA8, 0xB3, 0xD9, 0xF8, 0x14, 0x00, 0x26, 0x46, 0x41, 0x00, 0x0B, 0xF5,
+ 0xE6, 0x68, 0x4C, 0x46, 0x58, 0x46, 0x13, 0xF0, 0xA4, 0xFD, 0xA0, 0x69, 0x41, 0x00, 0x40, 0x46,
+ 0x13, 0xF0, 0x9F, 0xFD, 0x00, 0x27, 0xD1, 0x46, 0xFF, 0xF7, 0x9C, 0xFB, 0x48, 0x46, 0x0D, 0xF0,
+ 0x4E, 0xFA, 0x56, 0xB9, 0x0C, 0xA8, 0xCD, 0xE9, 0x00, 0xB0, 0x20, 0x6A, 0xDA, 0x4B, 0x62, 0x69,
+ 0x00, 0x68, 0xA1, 0x6B, 0xFF, 0xF7, 0xAC, 0xFE, 0x06, 0x46, 0x5D, 0xB9, 0x02, 0xA9, 0xCD, 0xE9,
+ 0x00, 0x81, 0x60, 0x6A, 0xD4, 0x4B, 0xA2, 0x69, 0x00, 0x68, 0x08, 0x33, 0xE1, 0x6B, 0xFF, 0xF7,
+ 0x9F, 0xFE, 0x05, 0x46, 0xFF, 0xF7, 0xE1, 0xFC, 0xFF, 0xF7, 0x7C, 0xFB, 0x48, 0x46, 0x0D, 0xF0,
+ 0x2E, 0xFA, 0x06, 0xB1, 0x15, 0xB9, 0x7F, 0x1C, 0x60, 0x2F, 0xD5, 0xDB, 0x01, 0x2E, 0x07, 0xD1,
+ 0x01, 0x2D, 0x05, 0xD1, 0xE0, 0x69, 0x81, 0x05, 0x02, 0xD5, 0x20, 0xF4, 0x00, 0x70, 0xE0, 0x61,
+ 0x13, 0xB0, 0xAC, 0xE4, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x46, 0xC3, 0x49, 0x16, 0x46, 0x02, 0x46,
+ 0x50, 0x39, 0xDD, 0xE9, 0x06, 0x05, 0xB1, 0xF9, 0x10, 0xC0, 0x01, 0x24, 0x62, 0x45, 0x11, 0xDD,
+ 0x1D, 0x68, 0xA0, 0xF1, 0x7F, 0x02, 0x95, 0x42, 0x07, 0xDD, 0x2A, 0x1A, 0x31, 0x46, 0x38, 0x46,
+ 0x1A, 0x60, 0x11, 0xF0, 0xCE, 0xFE, 0x00, 0x24, 0x11, 0xE0, 0xC8, 0x69, 0x40, 0xF0, 0x40, 0x00,
+ 0xC8, 0x61, 0x0C, 0xE0, 0x01, 0x21, 0x29, 0x70, 0x19, 0x68, 0xC0, 0xF1, 0x7F, 0x02, 0x91, 0x42,
+ 0x05, 0xDA, 0x0A, 0x18, 0x31, 0x46, 0x38, 0x46, 0x1A, 0x60, 0x11, 0xF0, 0xBA, 0xFE, 0x20, 0x46,
+ 0x43, 0xE5, 0x2D, 0xE9, 0xFF, 0x4F, 0x00, 0x24, 0x85, 0xB0, 0x15, 0x46, 0x06, 0x46, 0xA0, 0x46,
+ 0xA3, 0x46, 0x8B, 0xE0, 0x08, 0x98, 0x08, 0xF0, 0x07, 0x01, 0x00, 0xEB, 0xE8, 0x00, 0x7F, 0x22,
+ 0x03, 0x78, 0x01, 0x20, 0x88, 0x40, 0x18, 0x42, 0x03, 0x92, 0x7D, 0xD0, 0x41, 0x46, 0x06, 0x98,
+ 0x11, 0xF0, 0x9F, 0xFE, 0x00, 0x20, 0xDF, 0xF8, 0x80, 0xA2, 0x8D, 0xF8, 0x08, 0x00, 0x81, 0x46,
+ 0xAA, 0xF1, 0x50, 0x0A, 0xFF, 0xF7, 0x16, 0xFB, 0xDA, 0xF8, 0x14, 0x00, 0x85, 0x42, 0x03, 0xD1,
+ 0x4F, 0xF4, 0x00, 0x60, 0x0D, 0xF0, 0xC3, 0xF9, 0x02, 0xAF, 0x10, 0x20, 0xCD, 0xE9, 0x00, 0x07,
+ 0x36, 0xF9, 0x14, 0x00, 0x03, 0xAB, 0x42, 0x46, 0x06, 0x99, 0xFF, 0xF7, 0x9B, 0xFF, 0x20, 0xB9,
+ 0x09, 0xF1, 0x01, 0x09, 0xB9, 0xF1, 0x18, 0x0F, 0xE4, 0xDB, 0x9D, 0xF8, 0x08, 0x00, 0xE8, 0xB3,
+ 0x00, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x81, 0x46, 0xFF, 0xF7, 0xF4, 0xFA, 0xDA, 0xF8, 0x14, 0x00,
+ 0x85, 0x42, 0x03, 0xD1, 0x4F, 0xF4, 0x00, 0x60, 0x0D, 0xF0, 0xA1, 0xF9, 0x04, 0x20, 0xCD, 0xE9,
+ 0x00, 0x07, 0x36, 0xF9, 0x14, 0x00, 0x03, 0xAB, 0x42, 0x46, 0x06, 0x99, 0xFF, 0xF7, 0x7A, 0xFF,
+ 0x20, 0xB9, 0x09, 0xF1, 0x01, 0x09, 0xB9, 0xF1, 0x18, 0x0F, 0xE5, 0xDB, 0x9D, 0xF8, 0x08, 0x00,
+ 0xE0, 0xB1, 0x00, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x81, 0x46, 0x4F, 0xF0, 0x01, 0x0A, 0x00, 0xBF,
+ 0xFF, 0xF7, 0xD0, 0xFA, 0x78, 0x48, 0x50, 0x38, 0x40, 0x69, 0x85, 0x42, 0x03, 0xD1, 0x4F, 0xF4,
+ 0x00, 0x60, 0x0D, 0xF0, 0x7C, 0xF9, 0xCD, 0xE9, 0x00, 0xA7, 0x36, 0xF9, 0x14, 0x00, 0x03, 0xAB,
+ 0x42, 0x46, 0x06, 0x99, 0xFF, 0xF7, 0x56, 0xFF, 0x80, 0xB1, 0x01, 0xE0, 0x0D, 0xE0, 0x13, 0xE0,
+ 0x9D, 0xF8, 0x08, 0x00, 0x01, 0x28, 0x0E, 0xD0, 0x03, 0x9A, 0x41, 0x46, 0x52, 0x1E, 0x03, 0x92,
+ 0x06, 0x98, 0x11, 0xF0, 0x2E, 0xFE, 0x0B, 0xF1, 0x01, 0x0B, 0x04, 0xE0, 0x09, 0xF1, 0x01, 0x09,
+ 0xB9, 0xF1, 0x18, 0x0F, 0xD4, 0xDB, 0x64, 0x1C, 0x08, 0xF1, 0x01, 0x08, 0xAC, 0x42, 0xFF, 0xF6,
+ 0x71, 0xAF, 0xAB, 0x45, 0x02, 0xD0, 0x00, 0x20, 0x09, 0xB0, 0xB8, 0xE5, 0x01, 0x20, 0xFB, 0xE7,
+ 0x2D, 0xE9, 0xFF, 0x5F, 0xDF, 0xF8, 0x70, 0x91, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0x25, 0x9A, 0x46,
+ 0x17, 0x46, 0x2C, 0x46, 0xA9, 0xF1, 0x50, 0x09, 0x46, 0x46, 0xDD, 0xF8, 0x3C, 0xB0, 0x39, 0xE0,
+ 0x0A, 0xEB, 0xE4, 0x00, 0x04, 0xF0, 0x07, 0x02, 0x01, 0x78, 0x06, 0xFA, 0x02, 0xF0, 0x08, 0x42,
+ 0x2F, 0xD0, 0x1B, 0xF8, 0x04, 0x00, 0x58, 0xBB, 0x21, 0x46, 0x01, 0x98, 0x11, 0xF0, 0xF2, 0xFD,
+ 0x00, 0x99, 0xB9, 0xF9, 0x10, 0x20, 0x31, 0xF9, 0x15, 0x30, 0x49, 0x46, 0x93, 0x42, 0x12, 0xDD,
+ 0x0E, 0x9A, 0x7F, 0x3A, 0x90, 0x42, 0x08, 0xDD, 0x0E, 0x99, 0x42, 0x1A, 0x21, 0x46, 0x01, 0x98,
+ 0x11, 0xF0, 0xE7, 0xFD, 0x4F, 0xF0, 0x00, 0x08, 0x12, 0xE0, 0xC8, 0x69, 0x40, 0xF0, 0x40, 0x00,
+ 0xC9, 0xF8, 0x1C, 0x00, 0x0C, 0xE0, 0x0B, 0xF8, 0x04, 0x60, 0x0E, 0x99, 0xC1, 0xF1, 0x7F, 0x01,
+ 0x81, 0x42, 0x05, 0xDD, 0x0E, 0x99, 0x42, 0x18, 0x21, 0x46, 0x01, 0x98, 0x11, 0xF0, 0xD1, 0xFD,
+ 0x6D, 0x1C, 0x64, 0x1C, 0xBD, 0x42, 0xC3, 0xDB, 0x40, 0x46, 0xC9, 0xE5, 0x2D, 0xE9, 0xF0, 0x4F,
+ 0x35, 0x4C, 0x9D, 0xB0, 0x50, 0x3C, 0x61, 0x69, 0xB1, 0xB3, 0x00, 0x20, 0x83, 0x46, 0xA0, 0x69,
+ 0x98, 0xB3, 0x00, 0x20, 0x82, 0x46, 0xBB, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0xBA, 0xF1, 0x00, 0x0F,
+ 0x58, 0xD1, 0x2F, 0x4B, 0x04, 0xAD, 0x0D, 0xCB, 0x85, 0xE8, 0x0D, 0x00, 0x7F, 0x23, 0x2A, 0x4A,
+ 0x20, 0x6C, 0x00, 0xF0, 0x15, 0xFA, 0x28, 0x4A, 0x7F, 0x23, 0x08, 0x32, 0xA1, 0x69, 0x60, 0x6C,
+ 0x00, 0xF0, 0x0E, 0xFA, 0x00, 0x26, 0xA1, 0x46, 0x04, 0xA8, 0x5C, 0x46, 0x50, 0xF8, 0x26, 0x80,
+ 0x55, 0x46, 0x18, 0x21, 0x11, 0xA8, 0x13, 0xF0, 0x3E, 0xFC, 0x28, 0x21, 0x07, 0xA8, 0x13, 0xF0,
+ 0x3A, 0xFC, 0xD9, 0xF8, 0x1C, 0x10, 0x00, 0x27, 0x21, 0xF0, 0x40, 0x01, 0xC9, 0xF8, 0x1C, 0x10,
+ 0xFF, 0xF7, 0x10, 0xFA, 0x34, 0xB1, 0x13, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0x20, 0xC5, 0xE7,
+ 0x01, 0x20, 0xC7, 0xE7, 0x11, 0xA9, 0xCD, 0xE9, 0x00, 0x81, 0xD9, 0xF8, 0x20, 0x10, 0x12, 0x4B,
+ 0xD9, 0xF8, 0x14, 0x20, 0x08, 0x68, 0xD9, 0xF8, 0x40, 0x10, 0xFF, 0xF7, 0x61, 0xFF, 0x04, 0x46,
+ 0x75, 0xB9, 0x07, 0xA9, 0xCD, 0xE9, 0x00, 0x81, 0xD9, 0xF8, 0x24, 0x10, 0x0A, 0x4B, 0xD9, 0xF8,
+ 0x18, 0x20, 0x08, 0x68, 0x08, 0x33, 0xD9, 0xF8, 0x44, 0x10, 0xFF, 0xF7, 0x51, 0xFF, 0x05, 0x46,
+ 0xFF, 0xF7, 0x4B, 0xFB, 0x04, 0xB1, 0x15, 0xB9, 0x7F, 0x1C, 0x18, 0x2F, 0xD0, 0xDB, 0x76, 0x1C,
+ 0x03, 0x2E, 0xB9, 0xD3, 0x1D, 0xB0, 0xFA, 0xE4, 0xB8, 0x04, 0x10, 0x00, 0x84, 0x5A, 0x10, 0x00,
+ 0x0C, 0x6B, 0x01, 0x00, 0x70, 0xB5, 0xFF, 0x4C, 0x00, 0x26, 0x05, 0x46, 0xE6, 0x61, 0x01, 0x28,
+ 0x5E, 0xD0, 0x02, 0x2D, 0x5E, 0xD0, 0x01, 0x20, 0x20, 0x70, 0x60, 0x79, 0x68, 0xB1, 0xF9, 0x4A,
+ 0x00, 0x23, 0x50, 0x32, 0x61, 0x69, 0xA0, 0x6B, 0x00, 0xF0, 0xAA, 0xF9, 0xF5, 0x4A, 0x00, 0x23,
+ 0x58, 0x32, 0xA1, 0x69, 0xE0, 0x6B, 0x00, 0xF0, 0xA3, 0xF9, 0xA0, 0x79, 0x58, 0xB1, 0xF1, 0x49,
+ 0x62, 0x69, 0x50, 0x31, 0x20, 0x6C, 0x11, 0xF0, 0x3F, 0xFD, 0xEE, 0x49, 0xA2, 0x69, 0x58, 0x31,
+ 0x60, 0x6C, 0x11, 0xF0, 0x39, 0xFD, 0xE0, 0x78, 0x10, 0xB1, 0x00, 0x20, 0xFF, 0xF7, 0xEE, 0xFB,
+ 0x20, 0x79, 0x60, 0xB1, 0xE0, 0x78, 0x38, 0xB1, 0x61, 0x78, 0xA0, 0x6A, 0x00, 0xF0, 0x76, 0xF9,
+ 0x61, 0x78, 0xE0, 0x6A, 0x00, 0xF0, 0x72, 0xF9, 0x01, 0x20, 0xFF, 0xF7, 0xDF, 0xFB, 0x60, 0x79,
+ 0x08, 0xB1, 0xFF, 0xF7, 0x5C, 0xFD, 0x01, 0x2D, 0x26, 0xD0, 0x02, 0x2D, 0x26, 0xD0, 0x26, 0x70,
+ 0xFF, 0xF7, 0x90, 0xF9, 0xA0, 0x79, 0x68, 0xB1, 0x20, 0x79, 0x38, 0xB1, 0xA1, 0x78, 0x20, 0x6B,
+ 0x00, 0xF0, 0x5C, 0xF9, 0xA1, 0x78, 0x60, 0x6B, 0x00, 0xF0, 0x58, 0xF9, 0x20, 0x7A, 0xC0, 0xB1,
+ 0xFF, 0xF7, 0x34, 0xFF, 0xFF, 0xF7, 0x7E, 0xF9, 0x01, 0x2D, 0x27, 0xD0, 0x02, 0x2D, 0x27, 0xD0,
+ 0x10, 0x21, 0xE0, 0x69, 0x00, 0xF0, 0x72, 0xF9, 0xE0, 0x69, 0x20, 0xB3, 0x00, 0x20, 0x70, 0xBD,
+ 0x03, 0x20, 0xA1, 0xE7, 0x05, 0x20, 0x9F, 0xE7, 0x02, 0x20, 0x00, 0xE0, 0x04, 0x20, 0x20, 0x70,
+ 0xD6, 0xE7, 0xA2, 0x69, 0x00, 0x2A, 0x06, 0xDD, 0x60, 0x6A, 0xC6, 0x4B, 0x61, 0x6C, 0x00, 0x68,
+ 0x58, 0x33, 0xFF, 0xF7, 0x26, 0xFE, 0x62, 0x69, 0x00, 0x2A, 0xDB, 0xDD, 0x20, 0x6A, 0xC1, 0x4B,
+ 0x21, 0x6C, 0x00, 0x68, 0x50, 0x33, 0xFF, 0xF7, 0x1C, 0xFE, 0xD3, 0xE7, 0x40, 0x21, 0xD8, 0xE7,
+ 0x4F, 0xF4, 0x00, 0x71, 0xD5, 0xE7, 0x01, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0xB9, 0x4D, 0x0C, 0x46,
+ 0x02, 0x28, 0x28, 0xD0, 0x10, 0xF0, 0x21, 0xFE, 0xC5, 0xE9, 0x14, 0x01, 0x10, 0xF0, 0x1F, 0xFE,
+ 0xC5, 0xE9, 0x16, 0x01, 0xB3, 0x48, 0x08, 0x21, 0x50, 0x30, 0x11, 0xF0, 0xFB, 0xFF, 0x68, 0x61,
+ 0xB0, 0x48, 0x08, 0x21, 0x58, 0x30, 0x11, 0xF0, 0xF5, 0xFF, 0xA8, 0x61, 0x04, 0xF1, 0x90, 0x00,
+ 0xA8, 0x62, 0x40, 0x1C, 0xE8, 0x62, 0x40, 0x1C, 0x28, 0x63, 0x40, 0x1C, 0x68, 0x63, 0x4B, 0x38,
+ 0xA8, 0x63, 0x20, 0x30, 0xC5, 0xE9, 0x0F, 0x04, 0x48, 0x38, 0x68, 0x64, 0x74, 0x30, 0x95, 0x34,
+ 0xC5, 0xE9, 0x12, 0x04, 0x70, 0xBD, 0x10, 0xF0, 0xFC, 0xFD, 0xC5, 0xE9, 0x14, 0x01, 0x10, 0xF0,
+ 0xFA, 0xFD, 0xD5, 0xE7, 0x10, 0xB5, 0xA0, 0x49, 0x00, 0x20, 0xFF, 0xF7, 0xC6, 0xFF, 0x9D, 0x48,
+ 0x9E, 0x49, 0x01, 0x62, 0x09, 0x1D, 0x41, 0x62, 0x9D, 0x49, 0x0B, 0x68, 0x93, 0xF8, 0x88, 0x21,
+ 0x12, 0xF0, 0x01, 0x04, 0xC4, 0x70, 0x4F, 0xF0, 0x00, 0x02, 0x04, 0xD0, 0x83, 0x6A, 0x1A, 0x70,
+ 0xC3, 0x6A, 0x1A, 0x70, 0x08, 0xE0, 0x84, 0x6A, 0x93, 0xF8, 0x92, 0x31, 0x23, 0x70, 0x0B, 0x68,
+ 0xC4, 0x6A, 0x93, 0xF8, 0x93, 0x31, 0x23, 0x70, 0x0C, 0x68, 0x94, 0xF8, 0x88, 0x31, 0xC3, 0xF3,
+ 0x40, 0x03, 0x03, 0x71, 0x13, 0xB1, 0x03, 0x6B, 0x1A, 0x70, 0x06, 0xE0, 0x03, 0x6B, 0x94, 0xF8,
+ 0x94, 0x21, 0x1A, 0x70, 0x0A, 0x68, 0x92, 0xF8, 0x95, 0x21, 0x43, 0x6B, 0x1A, 0x70, 0x09, 0x68,
+ 0x91, 0xF8, 0x88, 0x21, 0xC2, 0xF3, 0x80, 0x03, 0x43, 0x71, 0xC2, 0xF3, 0xC0, 0x03, 0x83, 0x71,
+ 0xB1, 0xF8, 0x8A, 0x31, 0x43, 0x81, 0xB1, 0xF8, 0x8C, 0x31, 0x83, 0x81, 0xB1, 0xF8, 0x8E, 0x31,
+ 0xC3, 0x81, 0xB1, 0xF8, 0x90, 0x31, 0x03, 0x82, 0x91, 0xF8, 0x96, 0x31, 0x43, 0x70, 0x91, 0xF8,
+ 0x97, 0x31, 0x83, 0x70, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0x71, 0x91, 0xF8, 0x34, 0x11, 0xC1, 0xF3,
+ 0x40, 0x01, 0x01, 0x72, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0xE3, 0xE6, 0x72, 0x49, 0x10, 0xB5,
+ 0x98, 0x31, 0x01, 0x20, 0xFF, 0xF7, 0x69, 0xFF, 0x70, 0x49, 0x6E, 0x48, 0x10, 0x31, 0x01, 0x62,
+ 0x00, 0x21, 0xC0, 0xE9, 0x16, 0x11, 0x0A, 0x46, 0x81, 0x61, 0x6D, 0x49, 0x0B, 0x68, 0x93, 0xF8,
+ 0xA0, 0x41, 0x14, 0xF0, 0x01, 0x04, 0xC4, 0x70, 0x04, 0xD0, 0x83, 0x6A, 0x1A, 0x70, 0xC3, 0x6A,
+ 0x1A, 0x70, 0x08, 0xE0, 0x84, 0x6A, 0x93, 0xF8, 0xAA, 0x31, 0x23, 0x70, 0x0B, 0x68, 0xC4, 0x6A,
+ 0x93, 0xF8, 0xAB, 0x31, 0x23, 0x70, 0x0B, 0x68, 0x93, 0xF8, 0xA0, 0x41, 0xC4, 0xF3, 0x40, 0x04,
+ 0x04, 0x71, 0x14, 0xB1, 0x03, 0x6B, 0x1A, 0x70, 0x06, 0xE0, 0x93, 0xF8, 0xAC, 0x21, 0x03, 0x6B,
+ 0x1A, 0x70, 0x0A, 0x68, 0x92, 0xF8, 0xAD, 0x21, 0x43, 0x6B, 0x1A, 0x70, 0x09, 0x68, 0x91, 0xF8,
+ 0xA0, 0x21, 0xC2, 0xF3, 0x80, 0x03, 0x43, 0x71, 0xC2, 0xF3, 0xC0, 0x03, 0x83, 0x71, 0xB1, 0xF8,
+ 0xA2, 0x31, 0x43, 0x81, 0xB1, 0xF8, 0xA4, 0x31, 0x83, 0x81, 0xB1, 0xF8, 0xA6, 0x31, 0xC3, 0x81,
+ 0xB1, 0xF8, 0xA8, 0x31, 0x03, 0x82, 0x91, 0xF8, 0xAE, 0x31, 0x43, 0x70, 0x91, 0xF8, 0xAF, 0x31,
+ 0x83, 0x70, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0x71, 0x91, 0xF8, 0x84, 0x19, 0xC1, 0xF3, 0x40, 0x01,
+ 0x01, 0x72, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0x84, 0xE6, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46,
+ 0x01, 0x24, 0x00, 0x20, 0x11, 0xF0, 0xE7, 0xF9, 0x02, 0x20, 0x11, 0xF0, 0xE4, 0xF9, 0x41, 0x4E,
+ 0x78, 0x07, 0x4F, 0xF0, 0x00, 0x05, 0x4F, 0xF0, 0xA5, 0x08, 0x0A, 0xD5, 0xFF, 0xF7, 0x32, 0xFF,
+ 0x10, 0xF0, 0x01, 0x04, 0x05, 0xD0, 0x30, 0x68, 0xC5, 0x77, 0x80, 0xF8, 0x20, 0x50, 0x80, 0xF8,
+ 0x1E, 0x80, 0x38, 0x07, 0x0A, 0xD5, 0xFF, 0xF7, 0x81, 0xFF, 0x20, 0x40, 0x04, 0x00, 0x05, 0xD0,
+ 0x30, 0x68, 0x00, 0xF8, 0x22, 0x5F, 0x45, 0x70, 0x00, 0xF8, 0x01, 0x8C, 0x02, 0x20, 0x11, 0xF0,
+ 0xDD, 0xF9, 0x00, 0x20, 0x11, 0xF0, 0xDA, 0xF9, 0x20, 0x46, 0xF1, 0xE4, 0x02, 0x78, 0x8A, 0x42,
+ 0x01, 0xD9, 0x51, 0x1A, 0x00, 0xE0, 0x00, 0x21, 0x01, 0x70, 0x70, 0x47, 0x10, 0xB5, 0x14, 0x46,
+ 0x0E, 0xF0, 0x0F, 0xFE, 0xA0, 0x42, 0x01, 0xDC, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD,
+ 0xF0, 0xB5, 0x00, 0x25, 0x2C, 0x46, 0x01, 0x26, 0x0D, 0xE0, 0x00, 0xBF, 0x02, 0xEB, 0xE4, 0x07,
+ 0x04, 0xF0, 0x07, 0x0C, 0x3F, 0x78, 0x06, 0xFA, 0x0C, 0xFE, 0x1E, 0xEA, 0x07, 0x0F, 0x01, 0xD0,
+ 0x03, 0x55, 0x6D, 0x1C, 0x64, 0x1C, 0x8D, 0x42, 0xF0, 0xDB, 0xF0, 0xBD, 0x70, 0xB5, 0x04, 0x46,
+ 0x0D, 0x46, 0xC0, 0x07, 0x02, 0xD0, 0x83, 0x20, 0x0C, 0xF0, 0x16, 0xFF, 0xA0, 0x07, 0x03, 0xD5,
+ 0x29, 0x46, 0x84, 0x20, 0x0C, 0xF0, 0x10, 0xFF, 0x60, 0x07, 0x03, 0xD5, 0x29, 0x46, 0x85, 0x20,
+ 0x0C, 0xF0, 0x0A, 0xFF, 0x20, 0x07, 0x03, 0xD5, 0x29, 0x46, 0x86, 0x20, 0x0C, 0xF0, 0x04, 0xFF,
+ 0x60, 0x06, 0x03, 0xD5, 0x29, 0x46, 0x8B, 0x20, 0x0C, 0xF0, 0xFE, 0xFE, 0x20, 0x06, 0x03, 0xD5,
+ 0x29, 0x46, 0x8C, 0x20, 0x0C, 0xF0, 0xF8, 0xFE, 0xE0, 0x05, 0x0F, 0xD5, 0x29, 0x46, 0x87, 0x20,
+ 0x0A, 0xE0, 0x00, 0x00, 0x68, 0x04, 0x10, 0x00, 0xEC, 0x57, 0x01, 0x20, 0x14, 0x0A, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0x0C, 0xF0, 0xE6, 0xFE, 0xA0, 0x05, 0x05, 0xD5,
+ 0x29, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x88, 0x20, 0x0C, 0xF0, 0xDE, 0xBE, 0x70, 0xBD, 0x00, 0x00,
+ 0x5C, 0x4E, 0x08, 0xB5, 0x5C, 0x4D, 0x00, 0x24, 0xDF, 0xF8, 0x70, 0x91, 0x34, 0x60, 0xDF, 0xF8,
+ 0x70, 0x81, 0x2C, 0x60, 0xDF, 0xF8, 0x6C, 0xB1, 0xC9, 0xF8, 0x00, 0x40, 0xDF, 0xF8, 0x68, 0xA1,
+ 0xC8, 0xF8, 0x00, 0x40, 0xCB, 0xF8, 0x00, 0x40, 0xCA, 0xF8, 0x00, 0x40, 0x00, 0x22, 0x6B, 0x46,
+ 0x56, 0x49, 0x10, 0x46, 0x11, 0xF0, 0xE0, 0xF8, 0x00, 0x98, 0x81, 0x07, 0x13, 0xD5, 0xFC, 0xF7,
+ 0x15, 0xFF, 0x2F, 0x68, 0x2C, 0x60, 0xFC, 0xF7, 0x0F, 0xFF, 0x17, 0xF0, 0x53, 0x0F, 0x02, 0xD0,
+ 0x38, 0x46, 0xFE, 0xF7, 0x72, 0xFE, 0x17, 0xF4, 0xD6, 0x7F, 0x02, 0xD0, 0x38, 0x46, 0xFF, 0xF7,
+ 0x34, 0xFF, 0x02, 0x21, 0x82, 0xE0, 0xC1, 0x05, 0x0B, 0xD5, 0xFC, 0xF7, 0xFF, 0xFE, 0x37, 0x68,
+ 0x34, 0x60, 0xFC, 0xF7, 0xF9, 0xFE, 0x38, 0x46, 0xFD, 0xF7, 0xB4, 0xF8, 0x4F, 0xF4, 0x80, 0x71,
+ 0x74, 0xE0, 0x81, 0x05, 0x04, 0xD5, 0xFE, 0xF7, 0xA6, 0xF9, 0x4F, 0xF4, 0x00, 0x71, 0x6D, 0xE0,
+ 0x41, 0x05, 0x16, 0xD5, 0xFC, 0xF7, 0xEA, 0xFE, 0xD8, 0xF8, 0x00, 0x70, 0xC8, 0xF8, 0x00, 0x40,
+ 0xFC, 0xF7, 0xE2, 0xFE, 0xF8, 0x07, 0x01, 0xD0, 0xFD, 0xF7, 0x94, 0xFD, 0xB8, 0x07, 0x01, 0xD5,
+ 0xFD, 0xF7, 0x09, 0xFE, 0x78, 0x07, 0x01, 0xD5, 0xFD, 0xF7, 0xA0, 0xFD, 0x4F, 0xF4, 0x80, 0x61,
+ 0x54, 0xE0, 0x01, 0x06, 0x0C, 0xD5, 0xFC, 0xF7, 0xD1, 0xFE, 0xDB, 0xF8, 0x00, 0x70, 0xCB, 0xF8,
+ 0x00, 0x40, 0xFC, 0xF7, 0xC9, 0xFE, 0x38, 0x46, 0xFE, 0xF7, 0x11, 0xF8, 0x80, 0x21, 0x45, 0xE0,
+ 0x81, 0x02, 0x0D, 0xD5, 0xFC, 0xF7, 0xC2, 0xFE, 0xD9, 0xF8, 0x00, 0x70, 0xC9, 0xF8, 0x00, 0x40,
+ 0xFC, 0xF7, 0xBA, 0xFE, 0x38, 0x46, 0xFD, 0xF7, 0x09, 0xFD, 0x4F, 0xF4, 0x00, 0x11, 0x35, 0xE0,
+ 0xC1, 0x04, 0x04, 0xD5, 0xFE, 0xF7, 0xD8, 0xFE, 0x4F, 0xF4, 0x80, 0x51, 0x2E, 0xE0, 0x01, 0x02,
+ 0x04, 0xD5, 0xFD, 0xF7, 0x4F, 0xFE, 0x4F, 0xF4, 0x00, 0x01, 0x27, 0xE0, 0x01, 0x05, 0x04, 0xD5,
+ 0xFE, 0xF7, 0xE5, 0xFE, 0x4F, 0xF4, 0x00, 0x61, 0x20, 0xE0, 0x40, 0x02, 0x7F, 0xF5, 0x7E, 0xAF,
+ 0xFC, 0xF7, 0x9C, 0xFE, 0xDA, 0xF8, 0x00, 0x70, 0xCA, 0xF8, 0x00, 0x40, 0xFC, 0xF7, 0x94, 0xFE,
+ 0xF8, 0x07, 0x01, 0xD0, 0xFE, 0xF7, 0x47, 0xF9, 0xB8, 0x07, 0x05, 0xD5, 0x01, 0x20, 0xFE, 0xF7,
+ 0x2B, 0xFD, 0x01, 0x20, 0xFF, 0xF7, 0x5D, 0xF8, 0x78, 0x07, 0x05, 0xD5, 0x00, 0x20, 0xFE, 0xF7,
+ 0x23, 0xFD, 0x00, 0x20, 0xFF, 0xF7, 0x55, 0xF8, 0x4F, 0xF4, 0x80, 0x01, 0x00, 0x20, 0x11, 0xF0,
+ 0x26, 0xF8, 0x5B, 0xE7, 0x28, 0x07, 0x10, 0x00, 0x2C, 0x07, 0x10, 0x00, 0x30, 0x07, 0x10, 0x00,
+ 0x34, 0x07, 0x10, 0x00, 0x38, 0x07, 0x10, 0x00, 0x3C, 0x07, 0x10, 0x00, 0x83, 0x9F, 0xF0, 0x00,
+ 0x20, 0x48, 0x10, 0xB5, 0x01, 0x68, 0x20, 0x48, 0x02, 0x68, 0x13, 0x46, 0x92, 0xEA, 0x01, 0x0F,
+ 0x28, 0xD0, 0x1E, 0x4A, 0xCC, 0x07, 0x12, 0x68, 0x25, 0xD0, 0x92, 0xF8, 0x21, 0x43, 0xE4, 0x07,
+ 0x02, 0xD0, 0x43, 0xF0, 0x01, 0x03, 0x03, 0x60, 0x8B, 0x07, 0x1F, 0xD5, 0x92, 0xF8, 0x40, 0x33,
+ 0xDB, 0x07, 0x03, 0xD0, 0x03, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x03, 0x60, 0x0B, 0x07, 0x19, 0xD5,
+ 0x92, 0xF8, 0x60, 0x33, 0xDB, 0x07, 0x03, 0xD0, 0x03, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x03, 0x60,
+ 0x49, 0x06, 0x13, 0xD5, 0x92, 0xF8, 0x60, 0x13, 0xC9, 0x07, 0x03, 0xD0, 0x01, 0x68, 0x41, 0xF0,
+ 0x40, 0x01, 0x01, 0x60, 0x10, 0xBD, 0x23, 0xF0, 0x01, 0x03, 0xDC, 0xE7, 0x03, 0x68, 0x23, 0xF0,
+ 0x02, 0x03, 0xE2, 0xE7, 0x03, 0x68, 0x23, 0xF0, 0x08, 0x03, 0xE8, 0xE7, 0x01, 0x68, 0x21, 0xF0,
+ 0x40, 0x01, 0xEE, 0xE7, 0x48, 0x07, 0x10, 0x00, 0xF0, 0x04, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x10, 0x92, 0x84, 0x4C, 0x00, 0x25, 0xD9, 0xF8, 0x00, 0x10,
+ 0x91, 0xF8, 0x31, 0x00, 0x84, 0xF8, 0x30, 0x00, 0x91, 0xF8, 0x30, 0x20, 0x80, 0x49, 0x84, 0xF8,
+ 0x31, 0x20, 0x50, 0x43, 0x09, 0x78, 0x84, 0xF8, 0x33, 0x10, 0x7E, 0x49, 0x21, 0x60, 0x34, 0x39,
+ 0x06, 0xB2, 0x8B, 0x7B, 0x84, 0xF8, 0x2D, 0x30, 0x88, 0x46, 0x77, 0x00, 0x0F, 0xE0, 0x2A, 0x46,
+ 0x31, 0x46, 0xD8, 0xF8, 0x08, 0x00, 0x0D, 0xF0, 0xD6, 0xFD, 0x01, 0x46, 0x22, 0x68, 0x06, 0xFB,
+ 0x05, 0xF0, 0x02, 0xEB, 0x40, 0x00, 0x3A, 0x46, 0x13, 0xF0, 0x04, 0xF8, 0x6D, 0x1C, 0x94, 0xF8,
+ 0x2D, 0x00, 0xA8, 0x42, 0xEB, 0xDC, 0x70, 0x48, 0x70, 0x49, 0x00, 0x78, 0x09, 0x78, 0x08, 0x43,
+ 0x40, 0x07, 0x11, 0xD5, 0x6E, 0x48, 0x60, 0x60, 0xD9, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xF1, 0x11,
+ 0x89, 0x07, 0x4A, 0x0F, 0x94, 0xF8, 0x31, 0x10, 0x92, 0x1C, 0x4A, 0x43, 0xD8, 0xF8, 0x10, 0x10,
+ 0xBD, 0xE8, 0xF0, 0x47, 0x12, 0xF0, 0xE6, 0xBF, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x41,
+ 0x61, 0x48, 0x62, 0x4F, 0x00, 0x26, 0x05, 0x68, 0x38, 0x68, 0x05, 0x43, 0x01, 0x20, 0x10, 0xF0,
+ 0xEA, 0xFF, 0x38, 0x21, 0x59, 0x48, 0x13, 0xF0, 0x76, 0xF8, 0xE8, 0x07, 0x06, 0xD0, 0xFF, 0xF7,
+ 0x9F, 0xFF, 0xE8, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0x77, 0xF8, 0x01, 0x26, 0x59, 0x48, 0x53, 0x4C,
+ 0x00, 0x68, 0xC4, 0xE9, 0x07, 0x05, 0x38, 0x68, 0x60, 0x62, 0x52, 0x48, 0x56, 0x4F, 0x34, 0x38,
+ 0x41, 0x68, 0xA1, 0x62, 0xC1, 0x7B, 0x84, 0xF8, 0x35, 0x10, 0x90, 0xF8, 0x30, 0x00, 0x84, 0xF8,
+ 0x36, 0x00, 0x38, 0x78, 0x84, 0xF8, 0x2C, 0x00, 0xE8, 0x07, 0x1A, 0xD0, 0xE8, 0x06, 0x18, 0xD5,
+ 0x45, 0x4D, 0x28, 0x68, 0x90, 0xF8, 0x50, 0x02, 0xC0, 0x07, 0x06, 0xD0, 0x00, 0xF0, 0x75, 0xFD,
+ 0x18, 0xB9, 0xE0, 0x69, 0x40, 0xF0, 0x10, 0x00, 0xE0, 0x61, 0x28, 0x68, 0x90, 0xF8, 0x80, 0x02,
+ 0xC0, 0x07, 0x06, 0xD0, 0x00, 0xF0, 0x69, 0xFD, 0x18, 0xB9, 0xE0, 0x69, 0x40, 0xF0, 0x20, 0x00,
+ 0xE0, 0x61, 0x01, 0x20, 0x10, 0xF0, 0xC2, 0xFF, 0x00, 0x2E, 0x0C, 0xD0, 0x38, 0x78, 0x05, 0x28,
+ 0x07, 0xD0, 0x06, 0x28, 0x05, 0xD0, 0x01, 0x21, 0xBD, 0xE8, 0xF0, 0x41, 0x02, 0x20, 0x10, 0xF0,
+ 0xFA, 0xBE, 0x02, 0x21, 0xF8, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x48, 0x10, 0xB5, 0x00, 0x78,
+ 0x00, 0x28, 0x28, 0xD1, 0x2F, 0x4C, 0x34, 0x3C, 0xD4, 0xE9, 0x06, 0x01, 0x00, 0xF0, 0x48, 0xFD,
+ 0x94, 0xF8, 0x31, 0x10, 0xA0, 0x6A, 0x00, 0xF0, 0x40, 0xFC, 0xFF, 0xF7, 0x8F, 0xFF, 0x26, 0x48,
+ 0x00, 0x68, 0x90, 0xF8, 0x60, 0x03, 0xC1, 0x07, 0x15, 0xD0, 0x81, 0x07, 0x13, 0xD5, 0x00, 0x24,
+ 0x40, 0x09, 0x13, 0xF0, 0x8B, 0xF8, 0x00, 0xB1, 0x01, 0x24, 0x29, 0x48, 0x01, 0x78, 0x8C, 0x42,
+ 0x09, 0xD0, 0x04, 0x70, 0x0C, 0xB1, 0x08, 0x21, 0x00, 0xE0, 0x10, 0x21, 0xBD, 0xE8, 0x10, 0x40,
+ 0x03, 0x20, 0x10, 0xF0, 0xC8, 0xBE, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x16, 0x48, 0x19, 0x4E,
+ 0x16, 0x4C, 0x00, 0x68, 0x34, 0x3E, 0x90, 0xF8, 0x31, 0x50, 0x90, 0xF8, 0x30, 0x70, 0xB1, 0x69,
+ 0x39, 0xB1, 0x17, 0x48, 0x84, 0xF8, 0x30, 0x50, 0xC2, 0x38, 0x6A, 0x00, 0x20, 0x61, 0x12, 0xF0,
+ 0x41, 0xFF, 0xF1, 0x69, 0x39, 0xB1, 0x12, 0x48, 0x84, 0xF8, 0x31, 0x70, 0x98, 0x38, 0x7A, 0x00,
+ 0x60, 0x61, 0x12, 0xF0, 0x37, 0xFF, 0x0C, 0x48, 0x0C, 0x49, 0x00, 0x78, 0x09, 0x78, 0x08, 0x43,
+ 0x80, 0x06, 0xA8, 0xD5, 0x0A, 0x48, 0x4C, 0x38, 0xE0, 0x60, 0x6A, 0x00, 0x71, 0x6A, 0xBD, 0xE8,
+ 0xF0, 0x41, 0x12, 0xF0, 0x27, 0xBF, 0x9E, 0xE7, 0x20, 0x07, 0x10, 0x00, 0x7C, 0x6C, 0x10, 0x00,
+ 0xFC, 0x04, 0x10, 0x00, 0x64, 0x0A, 0x10, 0x00, 0xF4, 0x04, 0x10, 0x00, 0xF8, 0x04, 0x10, 0x00,
+ 0xD6, 0x07, 0x01, 0x20, 0xF0, 0x04, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0xE9, 0x04, 0x10, 0x00,
+ 0xC8, 0x04, 0x10, 0x00, 0x12, 0x48, 0x10, 0xB5, 0x12, 0x49, 0x04, 0x78, 0x00, 0x20, 0x08, 0x60,
+ 0x00, 0xF0, 0x47, 0xF8, 0x00, 0xF0, 0xEC, 0xFA, 0x05, 0x2C, 0x11, 0xD0, 0x06, 0x2C, 0x0F, 0xD0,
+ 0x0D, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x02, 0x01, 0x41, 0xF0, 0x04, 0x01, 0x01, 0x60, 0x01, 0x21,
+ 0x05, 0x20, 0x0C, 0xF0, 0x6F, 0xFF, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x10, 0xF0, 0x63, 0xFE,
+ 0x00, 0xF0, 0x7D, 0xFD, 0x02, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0x10, 0xF0, 0x5B, 0xBE,
+ 0xE8, 0x04, 0x10, 0x00, 0xEC, 0x04, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xC0, 0x07,
+ 0x1E, 0xD0, 0x38, 0x48, 0x03, 0x24, 0x00, 0x68, 0x90, 0xF8, 0x50, 0x12, 0xC9, 0x07, 0x03, 0xD1,
+ 0x90, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x0B, 0x24, 0xFC, 0xF7, 0xC7, 0xFC, 0x32, 0x48,
+ 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xFC, 0xF7, 0xBF, 0xFC, 0x01, 0x21, 0x05, 0x20, 0x0C, 0xF0,
+ 0x41, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x10, 0xF0, 0x33, 0xBE,
+ 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF0, 0x4B, 0xFD, 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x57, 0xFE,
+ 0x01, 0x20, 0x10, 0xF0, 0xC8, 0xFE, 0x38, 0x21, 0x24, 0x48, 0x12, 0xF0, 0x54, 0xFF, 0x23, 0x49,
+ 0x01, 0x20, 0x81, 0xF8, 0x2C, 0x00, 0x10, 0xF0, 0xD9, 0xFE, 0x01, 0x21, 0x02, 0x20, 0x10, 0xF0,
+ 0x1A, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x84, 0xBA, 0x70, 0xB5, 0x1C, 0x48, 0x1D, 0x4E,
+ 0x05, 0x68, 0x30, 0x68, 0x90, 0xEA, 0x05, 0x04, 0x1F, 0xD0, 0x35, 0xB1, 0x40, 0xB1, 0x04, 0xEA,
+ 0x05, 0x00, 0xFF, 0xF7, 0xB3, 0xFF, 0x35, 0x60, 0x70, 0xBD, 0xFF, 0xF7, 0xD2, 0xFF, 0xFA, 0xE7,
+ 0x00, 0xF0, 0x1D, 0xFD, 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x29, 0xFE, 0x00, 0xF0, 0xDB, 0xF8,
+ 0x00, 0xF0, 0x5F, 0xFA, 0x04, 0xEA, 0x05, 0x00, 0xFF, 0xF7, 0xA0, 0xFF, 0x00, 0xF0, 0x48, 0xFA,
+ 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0xEF, 0xFD, 0xE5, 0xE7, 0x00, 0x2D, 0xE4, 0xD1, 0x0A, 0x48,
+ 0x00, 0x78, 0x05, 0x28, 0x01, 0xD0, 0x06, 0x28, 0xDE, 0xD1, 0x35, 0x60, 0xBD, 0xE8, 0x70, 0x40,
+ 0xAF, 0xE7, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0x7C, 0x6C, 0x10, 0x00,
+ 0x44, 0x07, 0x10, 0x00, 0xEC, 0x04, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x70, 0xB5, 0xFB, 0x49,
+ 0x00, 0x20, 0x03, 0x46, 0x09, 0x68, 0x91, 0xF8, 0x40, 0x20, 0xD2, 0x07, 0x33, 0xD0, 0xF8, 0x4A,
+ 0x15, 0x78, 0x02, 0x2D, 0x16, 0xD0, 0x04, 0x2D, 0x03, 0xD0, 0x05, 0x2D, 0x0F, 0xD0, 0x06, 0x2D,
+ 0x0D, 0xD0, 0x91, 0xF8, 0x41, 0x20, 0xF3, 0x49, 0x0C, 0x68, 0x64, 0x1C, 0x0C, 0x60, 0x94, 0x42,
+ 0x21, 0xDD, 0xF1, 0x4A, 0x00, 0x20, 0x14, 0x78, 0x64, 0xB1, 0x08, 0x60, 0x0C, 0xE0, 0x91, 0xF8,
+ 0x43, 0x20, 0xF0, 0xE7, 0x91, 0xF8, 0x42, 0x20, 0x91, 0xF8, 0x90, 0x10, 0xC9, 0x06, 0xEA, 0xD5,
+ 0x01, 0x23, 0xE8, 0xE7, 0x13, 0xB1, 0x01, 0x20, 0x10, 0x70, 0x00, 0xE0, 0x08, 0x60, 0x05, 0x2D,
+ 0x0A, 0xD0, 0x00, 0xF0, 0xB3, 0xF8, 0x04, 0x46, 0x00, 0xF0, 0xB6, 0xF8, 0x40, 0xEA, 0x04, 0x05,
+ 0x00, 0xF0, 0xC0, 0xF8, 0x28, 0x43, 0x70, 0xBD, 0x01, 0x20, 0x70, 0xBD, 0x10, 0xB5, 0x01, 0x46,
+ 0x34, 0x22, 0xDE, 0x48, 0x12, 0xF0, 0x63, 0xFE, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46,
+ 0x10, 0xF0, 0x89, 0xBD, 0x2D, 0xE9, 0xFF, 0x47, 0x81, 0x46, 0xD5, 0x48, 0x01, 0x24, 0x00, 0x78,
+ 0x02, 0x28, 0x22, 0xD0, 0x03, 0x28, 0x1C, 0xD0, 0x04, 0x25, 0xD5, 0x4E, 0xDF, 0xF8, 0x54, 0x83,
+ 0x05, 0x28, 0x1E, 0xD0, 0x06, 0x28, 0x68, 0x46, 0x2F, 0xD0, 0x00, 0xF0, 0x11, 0xF9, 0xD2, 0x48,
+ 0x00, 0x90, 0xCA, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x10, 0xC8, 0x07, 0x38, 0xD0, 0x89, 0x07,
+ 0x30, 0xD5, 0xCE, 0x49, 0x0A, 0x78, 0x52, 0xB3, 0x00, 0x20, 0x8D, 0xF8, 0x0B, 0x00, 0x08, 0x70,
+ 0x2E, 0xE0, 0x68, 0x46, 0x00, 0xF0, 0xCD, 0xF8, 0xE9, 0xE7, 0x68, 0x46, 0x00, 0xF0, 0x91, 0xF8,
+ 0xE5, 0xE7, 0x68, 0x46, 0x10, 0xF0, 0xA2, 0xF8, 0xFF, 0xF7, 0x80, 0xFF, 0x40, 0x21, 0xC2, 0x07,
+ 0x01, 0xD0, 0x8D, 0xF8, 0x04, 0x50, 0xC2, 0x06, 0x01, 0xD5, 0x8D, 0xF8, 0x06, 0x40, 0x8D, 0xF8,
+ 0x08, 0x40, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x10, 0xD1, 0xE7, 0x00, 0x27, 0x10, 0xF0, 0x8E, 0xF8,
+ 0x8D, 0xF8, 0x04, 0x50, 0x01, 0x20, 0x37, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0xC7, 0xE7, 0xB9, 0xF1,
+ 0x08, 0x0F, 0x02, 0xD9, 0x8D, 0xF8, 0x0B, 0x40, 0x02, 0xE0, 0x02, 0x20, 0x8D, 0xF8, 0x0B, 0x00,
+ 0x68, 0x46, 0x10, 0xF0, 0xA0, 0xF8, 0xB2, 0x49, 0xB2, 0x4A, 0xC9, 0x78, 0x11, 0x70, 0x04, 0xB0,
+ 0xBD, 0xE8, 0xF0, 0x87, 0x10, 0xB5, 0x00, 0xF0, 0x42, 0xFC, 0x02, 0x21, 0xBD, 0xE8, 0x10, 0x40,
+ 0x01, 0x20, 0x10, 0xF0, 0x20, 0xBD, 0xA3, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0xA1, 0x49,
+ 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x38, 0xB5, 0x00, 0x20, 0x10, 0xF0, 0xB4, 0xFD, 0x00, 0xF0,
+ 0x94, 0xF9, 0x9B, 0x48, 0x00, 0x78, 0x00, 0xF0, 0xDA, 0xF8, 0x04, 0x46, 0xAF, 0xF2, 0x3B, 0x01,
+ 0x00, 0xF0, 0x1D, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0x7D, 0xFF, 0x01, 0x28, 0x0E, 0xD1, 0x01, 0x21,
+ 0x6B, 0x46, 0x00, 0x22, 0x08, 0x46, 0x10, 0xF0, 0x47, 0xFD, 0x01, 0x21, 0x08, 0x46, 0x10, 0xF0,
+ 0x26, 0xFD, 0x92, 0x48, 0x00, 0x78, 0x30, 0xB1, 0x0C, 0xF0, 0x2D, 0xFB, 0xBD, 0xE8, 0x38, 0x40,
+ 0x00, 0x20, 0x10, 0xF0, 0xAB, 0xBD, 0xFF, 0xF7, 0xF8, 0xFD, 0xF7, 0xE7, 0x92, 0x48, 0x00, 0x78,
+ 0xC0, 0x07, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x8F, 0x48, 0x00, 0x78, 0xC0, 0x07, 0x07, 0xD0,
+ 0x82, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x50, 0x02, 0xC0, 0x07, 0x01, 0xD0, 0x10, 0x20, 0x70, 0x47,
+ 0x00, 0x20, 0x70, 0x47, 0x88, 0x48, 0x00, 0x78, 0xC1, 0x07, 0x7C, 0x48, 0x00, 0x68, 0x90, 0xF8,
+ 0x80, 0x02, 0x03, 0xD0, 0xC1, 0x07, 0x01, 0xD0, 0x10, 0x20, 0x70, 0x47, 0x00, 0xF0, 0x01, 0x00,
+ 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x06, 0x46, 0x00, 0x24, 0x10, 0xF0, 0x0F, 0xF8, 0xFF, 0xF7,
+ 0xED, 0xFE, 0x05, 0x46, 0x7C, 0x48, 0x00, 0x78, 0xC0, 0x07, 0x00, 0xD0, 0x40, 0x24, 0x6D, 0xB1,
+ 0x6E, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x90, 0x00, 0x00, 0x07, 0x07, 0xD5, 0x00, 0xF0, 0xAE, 0xF8,
+ 0x40, 0xEA, 0x04, 0x07, 0x00, 0xF0, 0xB8, 0xF8, 0x40, 0xEA, 0x07, 0x04, 0x45, 0xEA, 0x04, 0x00,
+ 0xC0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0xBE, 0xF8, 0x30, 0x71, 0x61, 0x07, 0x4F, 0xF0, 0x01, 0x00,
+ 0x00, 0xD5, 0x70, 0x71, 0xE9, 0x06, 0x00, 0xD5, 0xB0, 0x71, 0x61, 0x06, 0x00, 0xD5, 0x30, 0x72,
+ 0xA1, 0x06, 0x00, 0xD5, 0xF0, 0x71, 0x62, 0x48, 0x05, 0x60, 0x62, 0x48, 0x04, 0x60, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x41, 0x06, 0x46, 0x0F, 0xF0, 0xD8, 0xFF, 0xFF, 0xF7, 0xB6, 0xFE,
+ 0x07, 0x46, 0xFF, 0xF7, 0x9B, 0xFF, 0x04, 0x46, 0xFF, 0xF7, 0x9E, 0xFF, 0x04, 0x43, 0xFF, 0xF7,
+ 0xA9, 0xFF, 0x04, 0x43, 0x00, 0xF0, 0x7A, 0xF8, 0x04, 0x43, 0x00, 0xF0, 0x85, 0xF8, 0x40, 0xEA,
+ 0x04, 0x05, 0x47, 0xEA, 0x05, 0x04, 0xE0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0x8B, 0xF8, 0x30, 0x71,
+ 0x69, 0x07, 0x4F, 0xF0, 0x01, 0x00, 0x00, 0xD5, 0x70, 0x71, 0xE1, 0x06, 0x00, 0xD5, 0xB0, 0x71,
+ 0xA9, 0x06, 0x00, 0xD5, 0xF0, 0x71, 0x4A, 0x48, 0x07, 0x60, 0x4A, 0x48, 0x05, 0x60, 0xCE, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x0F, 0xF0, 0xA9, 0xFF, 0xFF, 0xF7, 0x87, 0xFE, 0x05, 0x46,
+ 0xFF, 0xF7, 0x6C, 0xFF, 0x04, 0x46, 0xFF, 0xF7, 0x6F, 0xFF, 0x04, 0x43, 0xFF, 0xF7, 0x7A, 0xFF,
+ 0x04, 0x43, 0x00, 0xF0, 0x4B, 0xF8, 0x04, 0x43, 0x00, 0xF0, 0x56, 0xF8, 0x40, 0xEA, 0x04, 0x06,
+ 0x45, 0xEA, 0x06, 0x04, 0xE0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0x5C, 0xF8, 0x38, 0x71, 0x61, 0x07,
+ 0x4F, 0xF0, 0x01, 0x00, 0x00, 0xD5, 0x78, 0x71, 0xE1, 0x06, 0x00, 0xD5, 0xB8, 0x71, 0xB1, 0x06,
+ 0x00, 0xD5, 0xF8, 0x71, 0x32, 0x48, 0x05, 0x60, 0x32, 0x48, 0x06, 0x60, 0x9F, 0xE7, 0x38, 0xB5,
+ 0x2A, 0x49, 0x80, 0x1E, 0x05, 0x28, 0x09, 0x68, 0x13, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x06,
+ 0x09, 0x0C, 0x0F, 0x00, 0x91, 0xF8, 0x73, 0x40, 0x0C, 0xE0, 0x91, 0xF8, 0x72, 0x40, 0x09, 0xE0,
+ 0x91, 0xF8, 0x71, 0x40, 0x06, 0xE0, 0x91, 0xF8, 0x74, 0x40, 0x03, 0xE0, 0x91, 0xF8, 0x75, 0x40,
+ 0x00, 0xE0, 0x01, 0x24, 0x00, 0x25, 0x0B, 0xF0, 0x6B, 0xFE, 0x00, 0xB1, 0x01, 0x25, 0x69, 0x46,
+ 0x03, 0x20, 0x10, 0xF0, 0x4A, 0xFC, 0x00, 0x98, 0x00, 0xB9, 0x1D, 0xB1, 0x14, 0x2C, 0x01, 0xD2,
+ 0x14, 0x24, 0x01, 0xE0, 0x04, 0xB9, 0x01, 0x24, 0x20, 0x46, 0x38, 0xBD, 0x1E, 0x48, 0x00, 0x78,
+ 0xC0, 0x07, 0x07, 0xD0, 0x11, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xF0, 0x01, 0xC0, 0x07, 0x01, 0xD0,
+ 0x04, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x17, 0x48, 0x00, 0x78, 0xC0, 0x07, 0x07, 0xD0,
+ 0x0A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x10, 0x02, 0xC0, 0x07, 0x01, 0xD0, 0x20, 0x20, 0x70, 0x47,
+ 0x00, 0x20, 0x70, 0x47, 0x05, 0x49, 0x01, 0x20, 0x09, 0x68, 0x91, 0xF8, 0xE7, 0x10, 0x09, 0x06,
+ 0x03, 0xD5, 0x0B, 0x48, 0x40, 0x78, 0xC8, 0xB1, 0x03, 0x20, 0x70, 0x47, 0x20, 0x07, 0x10, 0x00,
+ 0xE8, 0x04, 0x10, 0x00, 0xCC, 0x04, 0x10, 0x00, 0xE9, 0x04, 0x10, 0x00, 0x30, 0x0A, 0x10, 0x00,
+ 0xF8, 0x04, 0x10, 0x00, 0xF4, 0x04, 0x10, 0x00, 0x7D, 0x3B, 0x00, 0x00, 0xDB, 0x04, 0x10, 0x00,
+ 0x4C, 0x07, 0x10, 0x00, 0xFC, 0x04, 0x10, 0x00, 0xEC, 0x04, 0x10, 0x00, 0x02, 0x20, 0xE4, 0xE7,
+ 0x10, 0xB5, 0x00, 0xF0, 0x9C, 0xF9, 0x00, 0xF0, 0x12, 0xFA, 0x62, 0x49, 0x00, 0x20, 0x48, 0x60,
+ 0x61, 0x49, 0x02, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF0, 0x90, 0xF9, 0x00, 0xF0,
+ 0x06, 0xFA, 0x5C, 0x49, 0x00, 0x20, 0x48, 0x60, 0x5B, 0x49, 0x03, 0x20, 0x08, 0x70, 0x10, 0xBD,
+ 0x10, 0xB5, 0x00, 0xF0, 0x84, 0xF9, 0x00, 0xF0, 0xFA, 0xF9, 0x56, 0x49, 0x00, 0x20, 0x48, 0x60,
+ 0x55, 0x49, 0x04, 0x20, 0x08, 0x70, 0x55, 0x49, 0x01, 0x20, 0x08, 0x70, 0x54, 0x49, 0x08, 0x70,
+ 0x10, 0xBD, 0x50, 0x49, 0x00, 0x20, 0x48, 0x60, 0x70, 0x47, 0x4E, 0x49, 0x00, 0x20, 0x48, 0x60,
+ 0x70, 0x47, 0x4C, 0x49, 0x00, 0x20, 0x48, 0x60, 0x4B, 0x49, 0x01, 0x20, 0x08, 0x70, 0x70, 0x47,
+ 0x10, 0xB5, 0x00, 0xF0, 0x61, 0xF9, 0x47, 0x49, 0x08, 0x70, 0x00, 0xF0, 0x60, 0xF9, 0x00, 0xF0,
+ 0xD6, 0xF9, 0x45, 0x49, 0x05, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x70, 0xB5, 0x42, 0x4D, 0x00, 0x26,
+ 0x40, 0x4C, 0x28, 0x78, 0x80, 0x1E, 0x04, 0x28, 0x10, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x30, 0x1F,
+ 0x02, 0x3E, 0x00, 0xF0, 0x45, 0xF8, 0x01, 0x28, 0x07, 0xD0, 0x60, 0x68, 0x40, 0x1C, 0x60, 0x60,
+ 0x00, 0xF0, 0x46, 0xF8, 0x01, 0x28, 0x02, 0xD0, 0x0B, 0xE0, 0x66, 0x60, 0x70, 0xBD, 0x39, 0x48,
+ 0x61, 0x68, 0x00, 0x68, 0x90, 0xF8, 0x77, 0x00, 0x88, 0x42, 0x02, 0xD2, 0xBD, 0xE8, 0x70, 0x40,
+ 0xA2, 0xE7, 0x00, 0xF0, 0x47, 0xF8, 0x01, 0x28, 0x0E, 0xD0, 0x70, 0xBD, 0x00, 0xF0, 0x28, 0xF8,
+ 0x01, 0x28, 0x17, 0xD0, 0x60, 0x68, 0x40, 0x1C, 0x60, 0x60, 0x00, 0xF0, 0x3B, 0xF8, 0x01, 0x28,
+ 0x02, 0xD0, 0x00, 0xF0, 0x25, 0xF8, 0x0B, 0xE0, 0xBD, 0xE8, 0x70, 0x40, 0x80, 0xE7, 0x00, 0xF0,
+ 0x17, 0xF8, 0x01, 0x28, 0x06, 0xD0, 0x60, 0x68, 0x40, 0x1C, 0x60, 0x60, 0x00, 0xF0, 0x22, 0xF8,
+ 0x01, 0x28, 0xE2, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x8A, 0xE7, 0x00, 0xF0, 0x0D, 0xF9, 0x08, 0xB1,
+ 0x21, 0x78, 0x09, 0xB1, 0x20, 0x70, 0x70, 0xBD, 0x20, 0x70, 0x06, 0x20, 0x28, 0x70, 0x70, 0xBD,
+ 0x10, 0xB5, 0x00, 0xF0, 0x01, 0xF9, 0x04, 0x46, 0x0B, 0xF0, 0x4F, 0xF8, 0x20, 0x43, 0x10, 0xBD,
+ 0x18, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x70, 0x00, 0x80, 0x07, 0x01, 0xD5, 0x01, 0x20, 0x70, 0x47,
+ 0x00, 0x20, 0x70, 0x47, 0x13, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x70, 0x00, 0xC0, 0x07, 0x00, 0xD0,
+ 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0xFF, 0xF7, 0xF5, 0xFF, 0x01, 0x28, 0x0F, 0xD1, 0x00, 0xF0,
+ 0x64, 0xF9, 0x60, 0xB9, 0x0B, 0x48, 0x07, 0x49, 0x00, 0x68, 0x49, 0x68, 0x90, 0xF8, 0x78, 0x00,
+ 0x00, 0xEB, 0x80, 0x00, 0xB1, 0xEB, 0x40, 0x0F, 0x01, 0xD9, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20,
+ 0x10, 0xBD, 0x00, 0x00, 0xD0, 0x04, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00,
+ 0x51, 0x07, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x90, 0x4C, 0x07, 0x46,
+ 0x0E, 0x46, 0x20, 0x68, 0x00, 0x25, 0x90, 0xF8, 0x98, 0x20, 0x8E, 0x48, 0x0D, 0xF0, 0x07, 0xFF,
+ 0x02, 0x00, 0x8D, 0x48, 0x29, 0x46, 0x34, 0xD0, 0x02, 0x78, 0x01, 0x25, 0x52, 0x1C, 0xD2, 0xB2,
+ 0x02, 0x70, 0x23, 0x68, 0x93, 0xF8, 0x99, 0x30, 0x93, 0x42, 0x2B, 0xD2, 0x01, 0x70, 0x85, 0x48,
+ 0x76, 0x00, 0x32, 0x46, 0x39, 0x46, 0x54, 0x38, 0x12, 0xF0, 0x5C, 0xFB, 0x81, 0x48, 0x32, 0x46,
+ 0x39, 0x46, 0x2A, 0x38, 0x12, 0xF0, 0x56, 0xFB, 0x20, 0x68, 0x03, 0x26, 0x90, 0xF8, 0x50, 0x12,
+ 0xC9, 0x07, 0x03, 0xD1, 0x90, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x0B, 0x26, 0xFC, 0xF7,
+ 0x3D, 0xF9, 0x7A, 0x48, 0x01, 0x68, 0x31, 0x43, 0x01, 0x60, 0xFC, 0xF7, 0x35, 0xF9, 0x20, 0x21,
+ 0x05, 0x20, 0x0C, 0xF0, 0xB7, 0xFB, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x10, 0xF0, 0xAB, 0xFA,
+ 0x00, 0xE0, 0x01, 0x70, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x5F, 0x8A, 0x46,
+ 0x00, 0x28, 0x6E, 0xD0, 0x6C, 0x4D, 0x00, 0x21, 0xDF, 0xF8, 0xB4, 0xB1, 0xE9, 0x70, 0x89, 0x46,
+ 0x9B, 0xF8, 0x00, 0x20, 0x0C, 0x46, 0x02, 0x2A, 0x03, 0xD0, 0x03, 0x2A, 0x01, 0xD0, 0x05, 0x2A,
+ 0x5E, 0xD1, 0x00, 0x21, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xD0, 0x01, 0x21, 0xAA, 0x88, 0x00, 0xEB,
+ 0x41, 0x00, 0x52, 0x1A, 0x16, 0xB2, 0x80, 0x46, 0xAA, 0x78, 0x31, 0x46, 0x00, 0xF0, 0x72, 0xF8,
+ 0x5B, 0x4F, 0xA8, 0x70, 0x38, 0x68, 0x90, 0xF8, 0x90, 0x00, 0x80, 0x07, 0x04, 0xD5, 0x40, 0x46,
+ 0x31, 0x46, 0xFF, 0xF7, 0x89, 0xFF, 0x81, 0x46, 0x01, 0x20, 0xDF, 0xF8, 0x58, 0x81, 0xBA, 0xF1,
+ 0x00, 0x0F, 0x17, 0xD0, 0x00, 0x23, 0x19, 0x46, 0x3F, 0x68, 0x0F, 0xE0, 0x38, 0xF9, 0x11, 0x20,
+ 0x00, 0x2A, 0x00, 0xDA, 0x52, 0x42, 0xB7, 0xF8, 0x92, 0xC0, 0x62, 0x45, 0x04, 0xDD, 0x97, 0xF8,
+ 0x91, 0x20, 0x5B, 0x1C, 0x9A, 0x42, 0x14, 0xDD, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xED, 0xDB,
+ 0x21, 0x46, 0x25, 0xE0, 0x00, 0x22, 0x11, 0x46, 0x3B, 0x68, 0x16, 0xE0, 0x38, 0xF9, 0x11, 0x70,
+ 0xB3, 0xF8, 0x92, 0xC0, 0x67, 0x45, 0x0E, 0xDD, 0x93, 0xF8, 0x91, 0x70, 0x52, 0x1C, 0x97, 0x42,
+ 0x09, 0xDC, 0x9B, 0xF8, 0x00, 0x20, 0x01, 0x46, 0x02, 0x2A, 0x09, 0xD0, 0x03, 0x2A, 0x07, 0xD0,
+ 0x05, 0x2A, 0x08, 0xD0, 0x0C, 0xE0, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xE6, 0xDB, 0xDF, 0xE7,
+ 0x68, 0x70, 0xE8, 0x70, 0x08, 0xE0, 0x68, 0x78, 0x10, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x02, 0xD0,
+ 0x69, 0x70, 0xBD, 0xE8, 0xF0, 0x9F, 0x69, 0x70, 0x00, 0xF0, 0x49, 0xF9, 0xBD, 0xE8, 0xF0, 0x5F,
+ 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x27, 0xBA, 0x2F, 0x48, 0x40, 0x78, 0x70, 0x47, 0x2E, 0x48,
+ 0x00, 0x21, 0x01, 0x22, 0x01, 0x70, 0x82, 0x70, 0x29, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x31, 0x20,
+ 0x82, 0x80, 0x2B, 0x4A, 0x12, 0x78, 0x05, 0x2A, 0x02, 0xD0, 0x06, 0x2A, 0x00, 0xD0, 0x41, 0x70,
+ 0x70, 0x47, 0xEC, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x80, 0x46, 0x23, 0x48, 0x14, 0x46, 0x0D, 0x46,
+ 0x40, 0x78, 0x16, 0x46, 0x40, 0xB9, 0x1F, 0x48, 0x0A, 0x46, 0x7F, 0x23, 0x41, 0x46, 0x54, 0x38,
+ 0x00, 0x94, 0x0D, 0xF0, 0x79, 0xFE, 0x00, 0x26, 0x19, 0x4F, 0x38, 0x68, 0x90, 0xF8, 0x90, 0x10,
+ 0xC9, 0x07, 0x00, 0xD0, 0xEC, 0xB1, 0x17, 0x48, 0x6A, 0x00, 0x41, 0x46, 0x2A, 0x38, 0x12, 0xF0,
+ 0x81, 0xFA, 0x14, 0x4A, 0x2B, 0x46, 0x54, 0x3A, 0x02, 0xF1, 0x2A, 0x01, 0x11, 0x48, 0x0D, 0xF0,
+ 0x2C, 0xFE, 0x38, 0x68, 0x90, 0xF8, 0x90, 0x10, 0x49, 0x07, 0x07, 0xD5, 0x90, 0xF8, 0x9A, 0x30,
+ 0x23, 0xB1, 0x0C, 0x49, 0x2A, 0x46, 0x08, 0x46, 0x0D, 0xF0, 0x6F, 0xFE, 0x30, 0x46, 0xBD, 0xE8,
+ 0xFC, 0x81, 0xB0, 0xF9, 0x96, 0x10, 0xCD, 0xE9, 0x00, 0x15, 0x06, 0x4A, 0xB0, 0xF9, 0x94, 0x30,
+ 0x54, 0x3A, 0x41, 0x46, 0x02, 0xF1, 0x2A, 0x00, 0x0D, 0xF0, 0x96, 0xFD, 0xD9, 0xE7, 0x00, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x5A, 0x09, 0x01, 0x20, 0xD8, 0x04, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00,
+ 0xE8, 0x04, 0x10, 0x00, 0x70, 0xB5, 0x00, 0x28, 0x04, 0x9E, 0x0D, 0xD0, 0x00, 0x24, 0x06, 0xE0,
+ 0x30, 0xF9, 0x11, 0x50, 0x9D, 0x42, 0x01, 0xDD, 0x95, 0x42, 0x00, 0xDB, 0x64, 0x1C, 0x49, 0x1E,
+ 0xF6, 0xD2, 0xB4, 0x42, 0x01, 0xDD, 0x01, 0x20, 0x70, 0xBD, 0x00, 0x20, 0x70, 0xBD, 0x3F, 0x48,
+ 0x00, 0x21, 0x01, 0x70, 0x41, 0x60, 0x70, 0x47, 0xF9, 0xE7, 0x3C, 0x48, 0x00, 0x78, 0x70, 0x47,
+ 0x2D, 0xE9, 0xF3, 0x4F, 0xDF, 0xF8, 0xE8, 0xA0, 0x84, 0x46, 0x4F, 0xF0, 0x00, 0x08, 0xDA, 0xF8,
+ 0x00, 0x00, 0xDF, 0xF8, 0xD8, 0xB0, 0x81, 0xB0, 0x90, 0xF8, 0x80, 0x10, 0x47, 0x46, 0xC9, 0x07,
+ 0xC1, 0x46, 0x2B, 0xD0, 0x33, 0x49, 0x09, 0x78, 0x03, 0x29, 0x2D, 0xD0, 0x04, 0x29, 0x2B, 0xD0,
+ 0x05, 0x29, 0x36, 0xD1, 0xB0, 0xF8, 0x88, 0x60, 0xB0, 0xF8, 0x8A, 0x50, 0x90, 0xF8, 0x87, 0x40,
+ 0xBC, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x00, 0x94, 0x90, 0xF8, 0x31, 0x10, 0x2B, 0xB2, 0x32, 0xB2,
+ 0x60, 0x46, 0xFF, 0xF7, 0xB7, 0xFF, 0x80, 0x46, 0x02, 0x98, 0x50, 0xB1, 0x00, 0x94, 0xDA, 0xF8,
+ 0x00, 0x00, 0x2B, 0xB2, 0x32, 0xB2, 0x90, 0xF8, 0x30, 0x10, 0x02, 0x98, 0xFF, 0xF7, 0xAA, 0xFF,
+ 0x07, 0x46, 0xB8, 0xF1, 0x01, 0x0F, 0x0E, 0xD0, 0x01, 0x2F, 0x0C, 0xD0, 0x9B, 0xF8, 0x00, 0x10,
+ 0x58, 0x46, 0x01, 0x29, 0x1D, 0xD0, 0x0A, 0xE0, 0xB0, 0xF8, 0x82, 0x60, 0xB0, 0xF8, 0x84, 0x50,
+ 0x90, 0xF8, 0x86, 0x40, 0xD4, 0xE7, 0x9B, 0xF8, 0x00, 0x10, 0x58, 0x46, 0x19, 0xB1, 0xCB, 0xF8,
+ 0x04, 0x90, 0xBD, 0xE8, 0xFE, 0x8F, 0x41, 0x68, 0x49, 0x1C, 0x41, 0x60, 0xDA, 0xF8, 0x00, 0x20,
+ 0x92, 0xF8, 0x81, 0x20, 0x8A, 0x42, 0xF4, 0xDA, 0x01, 0x21, 0x01, 0x70, 0xCB, 0xF8, 0x04, 0x90,
+ 0x0D, 0xE0, 0x41, 0x68, 0x49, 0x1C, 0x41, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0x92, 0xF8, 0x81, 0x20,
+ 0x8A, 0x42, 0xE6, 0xDA, 0x80, 0xF8, 0x00, 0x90, 0x00, 0x21, 0xCB, 0xF8, 0x04, 0x90, 0x03, 0xB0,
+ 0x07, 0x20, 0xBD, 0xE8, 0xF0, 0x4F, 0x0C, 0xF0, 0x35, 0xBA, 0x00, 0x00, 0xE0, 0x04, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x22, 0x48, 0x08, 0xB5, 0x00, 0x21, 0x41, 0x60,
+ 0x01, 0x22, 0x81, 0x60, 0x02, 0x70, 0x41, 0x70, 0x1F, 0x48, 0x01, 0x70, 0xFF, 0xF7, 0x09, 0xFF,
+ 0xFF, 0xF7, 0x72, 0xFF, 0xFF, 0xF7, 0xFB, 0xFB, 0xFF, 0xF7, 0x7F, 0xFD, 0x6B, 0x46, 0x00, 0x22,
+ 0x5E, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x58, 0xF9, 0x00, 0x98, 0x41, 0x07, 0x03, 0xD5, 0xFF, 0xF7,
+ 0xF4, 0xFA, 0x04, 0x21, 0x0E, 0xE0, 0x01, 0x07, 0x03, 0xD5, 0xFF, 0xF7, 0x19, 0xF9, 0x08, 0x21,
+ 0x08, 0xE0, 0xC1, 0x06, 0x03, 0xD5, 0xFF, 0xF7, 0x7D, 0xFA, 0x10, 0x21, 0x02, 0xE0, 0x41, 0x06,
+ 0x04, 0xD5, 0x40, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x22, 0xF9, 0xDF, 0xE7, 0x80, 0x07, 0xDD, 0xD5,
+ 0x02, 0x21, 0x01, 0x20, 0x10, 0xF0, 0x1B, 0xF9, 0xFF, 0xF7, 0xD5, 0xFB, 0xD6, 0xE7, 0x00, 0xEB,
+ 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x11, 0xF0, 0x85, 0xBE, 0x11, 0xF0,
+ 0xA5, 0xBE, 0x00, 0x00, 0xE8, 0x04, 0x10, 0x00, 0x52, 0x07, 0x10, 0x00, 0x00, 0xF0, 0xA3, 0xBF,
+ 0x5E, 0x48, 0x40, 0x78, 0x00, 0x28, 0x0B, 0xD0, 0x5D, 0x48, 0x5E, 0x49, 0x00, 0x7E, 0x09, 0x7E,
+ 0xC8, 0x42, 0x05, 0xD1, 0x01, 0x23, 0x5C, 0x4A, 0x5A, 0x49, 0x59, 0x48, 0x00, 0xF0, 0xE0, 0xBB,
+ 0x70, 0x47, 0x3C, 0xB5, 0x00, 0x23, 0x00, 0x93, 0x01, 0x93, 0x6B, 0x46, 0x07, 0xE0, 0x44, 0x18,
+ 0x64, 0x78, 0x14, 0xB1, 0x1D, 0x5D, 0x6D, 0x1C, 0x1D, 0x55, 0x49, 0x1C, 0xC9, 0xB2, 0x91, 0x42,
+ 0xF5, 0xD9, 0x00, 0x20, 0x01, 0x21, 0x1C, 0x5C, 0x5A, 0x5C, 0xA2, 0x42, 0x00, 0xD9, 0x08, 0x46,
+ 0x49, 0x1C, 0xC9, 0xB2, 0x06, 0x29, 0xF6, 0xD3, 0x3C, 0xBD, 0x70, 0xB5, 0x04, 0x46, 0x00, 0x20,
+ 0x08, 0x70, 0x0E, 0x46, 0x10, 0x70, 0x46, 0x48, 0x46, 0x49, 0x15, 0x46, 0x00, 0x7E, 0x09, 0x7E,
+ 0xC8, 0x42, 0x0B, 0xD0, 0xE2, 0x78, 0xA1, 0x78, 0x44, 0x48, 0xFF, 0xF7, 0xD2, 0xFF, 0x30, 0x70,
+ 0x62, 0x78, 0x21, 0x78, 0x42, 0x48, 0xFF, 0xF7, 0xCC, 0xFF, 0x28, 0x70, 0x70, 0xBD, 0x70, 0xB5,
+ 0x00, 0x24, 0x01, 0x23, 0x05, 0x7E, 0x08, 0xE0, 0xC6, 0x18, 0x96, 0xF9, 0x12, 0x60, 0x8E, 0x42,
+ 0x02, 0xDB, 0x96, 0x42, 0x00, 0xDC, 0x64, 0x1C, 0x5B, 0x1C, 0x9D, 0x42, 0xF4, 0xD2, 0x01, 0x2C,
+ 0x01, 0xDC, 0x01, 0x20, 0x70, 0xBD, 0x00, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x43, 0x99, 0x46,
+ 0x00, 0x23, 0x1F, 0x46, 0x47, 0xF6, 0xFF, 0x76, 0x4F, 0xF0, 0xFF, 0x3C, 0x01, 0x25, 0x04, 0x7E,
+ 0x0D, 0xE0, 0x00, 0xBF, 0x00, 0xEB, 0x05, 0x08, 0x98, 0xF9, 0x12, 0x80, 0x88, 0x45, 0x05, 0xDB,
+ 0x90, 0x45, 0x03, 0xDC, 0x43, 0x19, 0x93, 0xF9, 0x12, 0x30, 0x02, 0xE0, 0x6D, 0x1C, 0xAC, 0x42,
+ 0xF0, 0xD2, 0x64, 0x1C, 0x0A, 0xE0, 0x05, 0x19, 0x95, 0xF9, 0x12, 0x50, 0x8D, 0x42, 0x05, 0xDB,
+ 0x95, 0x42, 0x03, 0xDC, 0x20, 0x44, 0x90, 0xF9, 0x12, 0x70, 0x01, 0xE0, 0x64, 0x1E, 0xF2, 0xD1,
+ 0xBB, 0x42, 0x09, 0xD1, 0x0A, 0xE0, 0x00, 0xBF, 0x39, 0xF9, 0x13, 0x00, 0xB0, 0x42, 0x02, 0xDA,
+ 0x06, 0x46, 0x4F, 0xFA, 0x83, 0xFC, 0x5B, 0x1C, 0xBB, 0x42, 0xF5, 0xDD, 0x60, 0x46, 0xBD, 0xE8,
+ 0xF0, 0x83, 0x2D, 0xE9, 0xF0, 0x41, 0x17, 0x46, 0x0E, 0x46, 0x04, 0x46, 0xC2, 0x78, 0x81, 0x78,
+ 0x0F, 0x48, 0xFF, 0xF7, 0xA4, 0xFF, 0x05, 0x00, 0x06, 0xD1, 0xE2, 0x78, 0xA1, 0x78, 0x11, 0x4B,
+ 0x0B, 0x48, 0xFF, 0xF7, 0xB2, 0xFF, 0x30, 0x70, 0x62, 0x78, 0x21, 0x78, 0x09, 0x48, 0xFF, 0xF7,
+ 0x96, 0xFF, 0x06, 0x00, 0x06, 0xD1, 0x62, 0x78, 0x21, 0x78, 0x0B, 0x4B, 0x05, 0x48, 0xFF, 0xF7,
+ 0xA4, 0xFF, 0x38, 0x70, 0x05, 0xEA, 0x06, 0x00, 0xBD, 0xE8, 0xF0, 0x81, 0xEC, 0x06, 0x10, 0x00,
+ 0x58, 0x23, 0x10, 0x00, 0x98, 0x23, 0x10, 0x00, 0x80, 0x24, 0x10, 0x00, 0xFC, 0x0B, 0x01, 0x20,
+ 0x13, 0x0C, 0x01, 0x20, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, 0x2D, 0xE9, 0xF0, 0x47,
+ 0x00, 0x25, 0x82, 0x46, 0xA6, 0xB0, 0x50, 0x1E, 0xC7, 0xB2, 0x2C, 0x46, 0x28, 0x46, 0x6B, 0x46,
+ 0x0D, 0xF1, 0x4C, 0x09, 0x12, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x10, 0x60, 0x35, 0x44, 0x46, 0x1C,
+ 0xB4, 0x46, 0x95, 0xFB, 0xF6, 0xF6, 0x23, 0xF8, 0x10, 0x60, 0x3E, 0x1A, 0x40, 0x1C, 0x31, 0xF9,
+ 0x16, 0x80, 0x44, 0x44, 0x94, 0xFB, 0xFC, 0xFC, 0x29, 0xF8, 0x16, 0xC0, 0x90, 0x42, 0xEB, 0xDB,
+ 0x48, 0x46, 0x0C, 0xE0, 0x33, 0xF9, 0x12, 0x40, 0x30, 0xF9, 0x12, 0x50, 0x2C, 0x44, 0x31, 0xF8,
+ 0x12, 0x50, 0x04, 0xEB, 0xD4, 0x74, 0xA5, 0xEB, 0x64, 0x04, 0x2A, 0xF8, 0x12, 0x40, 0x52, 0x1E,
+ 0xF0, 0xD2, 0x26, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x4F, 0x4F, 0xF0, 0x00, 0x0B,
+ 0xA7, 0xB0, 0xC0, 0xF8, 0x00, 0xB0, 0x81, 0x46, 0xC0, 0xF8, 0x04, 0xB0, 0x98, 0x46, 0x14, 0x46,
+ 0x5D, 0x46, 0x5E, 0x46, 0xDA, 0x46, 0x5F, 0x46, 0x28, 0x21, 0x01, 0xA8, 0x12, 0xF0, 0xF3, 0xF8,
+ 0x4C, 0x21, 0x0B, 0xA8, 0x12, 0xF0, 0xEF, 0xF8, 0xCD, 0xF8, 0x00, 0x80, 0x02, 0x23, 0x22, 0x46,
+ 0x0B, 0xA8, 0x28, 0x99, 0x0D, 0xF0, 0x16, 0xFC, 0x8E, 0x49, 0x01, 0x20, 0x02, 0x46, 0x00, 0x23,
+ 0x0D, 0xF1, 0x04, 0x0E, 0xD1, 0xF8, 0x00, 0x80, 0x17, 0xE0, 0x0B, 0xA9, 0x31, 0xF9, 0x10, 0xC0,
+ 0xB8, 0xF9, 0x4E, 0x12, 0x8C, 0x45, 0x04, 0xDD, 0x4F, 0xF0, 0x01, 0x0B, 0x0E, 0xF8, 0x00, 0x20,
+ 0x0A, 0xE0, 0x49, 0x42, 0x8C, 0x45, 0x05, 0xDA, 0xFF, 0x21, 0x4F, 0xF0, 0x01, 0x0B, 0x0E, 0xF8,
+ 0x00, 0x10, 0x01, 0xE0, 0x0E, 0xF8, 0x00, 0x30, 0x40, 0x1C, 0xA0, 0x42, 0xE5, 0xDB, 0xBB, 0xF1,
+ 0x01, 0x0F, 0x42, 0xD1, 0x01, 0x20, 0x71, 0x46, 0x09, 0xE0, 0x0A, 0x5C, 0x32, 0xB1, 0xC5, 0xB2,
+ 0x08, 0x56, 0x00, 0x28, 0x05, 0xDD, 0x4F, 0xF0, 0x01, 0x0A, 0x02, 0xE0, 0x40, 0x1C, 0xA0, 0x42,
+ 0xF3, 0xDB, 0x60, 0x1E, 0x07, 0xE0, 0x0A, 0x5C, 0x2A, 0xB1, 0xC6, 0xB2, 0x08, 0x56, 0x00, 0x28,
+ 0x03, 0xDA, 0x01, 0x27, 0x01, 0xE0, 0x40, 0x1E, 0xF5, 0xD2, 0xA4, 0xF1, 0x01, 0x08, 0xBA, 0xF1,
+ 0x00, 0x0F, 0x01, 0xD0, 0x97, 0xB9, 0x02, 0xE0, 0x4F, 0xF0, 0x01, 0x05, 0x77, 0xB9, 0x08, 0xF0,
+ 0xFF, 0x06, 0x0B, 0xE0, 0xD9, 0xE9, 0x00, 0x47, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0,
+ 0xBA, 0xFF, 0x04, 0x43, 0x0F, 0x43, 0xC9, 0xE9, 0x00, 0x47, 0x6D, 0x1C, 0xB5, 0x42, 0xF1, 0xDD,
+ 0xD9, 0xE9, 0x00, 0x04, 0x40, 0xF0, 0x01, 0x05, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0,
+ 0xAA, 0xFF, 0x05, 0x43, 0x0C, 0x43, 0xC9, 0xE9, 0x00, 0x54, 0x2B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F,
+ 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0x16, 0x46, 0x0F, 0x46, 0x03, 0x20, 0x0F, 0xF0, 0xE3, 0xFF,
+ 0x55, 0x4C, 0x56, 0x4A, 0x29, 0x46, 0x23, 0x78, 0x55, 0x48, 0x0D, 0xF0, 0x7E, 0xFB, 0x55, 0x4D,
+ 0x53, 0x48, 0x55, 0x4A, 0x2B, 0x78, 0x39, 0x46, 0x2A, 0x30, 0x0D, 0xF0, 0x76, 0xFB, 0x03, 0x20,
+ 0x0F, 0xF0, 0xEC, 0xFF, 0xDF, 0xF8, 0x2C, 0x81, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE0, 0x13,
+ 0x89, 0x07, 0x12, 0xD5, 0x90, 0xF8, 0xF4, 0x03, 0x00, 0x96, 0x00, 0xF0, 0x0F, 0x07, 0x3B, 0x46,
+ 0x22, 0x78, 0x47, 0x49, 0x49, 0x48, 0x0D, 0xF0, 0x7D, 0xFB, 0x45, 0x49, 0x00, 0x96, 0x3B, 0x46,
+ 0x2A, 0x78, 0x2A, 0x31, 0x46, 0x48, 0x0D, 0xF0, 0x75, 0xFB, 0x22, 0x78, 0x40, 0x49, 0x45, 0x48,
+ 0x00, 0xF0, 0x5B, 0xF8, 0x3E, 0x49, 0x2A, 0x78, 0x2A, 0x31, 0x43, 0x48, 0x00, 0xF0, 0x55, 0xF8,
+ 0x42, 0x4F, 0x00, 0x96, 0x22, 0x78, 0x3F, 0x49, 0x41, 0x48, 0x3B, 0x68, 0x0D, 0xF0, 0x62, 0xFB,
+ 0x00, 0x96, 0x2A, 0x78, 0x3C, 0x49, 0x3F, 0x48, 0x3B, 0x68, 0x0D, 0xF0, 0x5B, 0xFB, 0xD8, 0xF8,
+ 0x00, 0x00, 0x47, 0x46, 0x90, 0xF8, 0x30, 0x02, 0xC0, 0x06, 0x0A, 0xD5, 0x22, 0x78, 0x38, 0x49,
+ 0x39, 0x48, 0xFF, 0xF7, 0xE3, 0xFE, 0x2A, 0x78, 0x36, 0x49, 0x38, 0x48, 0xFF, 0xF7, 0xDE, 0xFE,
+ 0x0B, 0xE0, 0x20, 0x78, 0x32, 0x49, 0x42, 0x00, 0x33, 0x48, 0x11, 0xF0, 0x73, 0xFF, 0x28, 0x78,
+ 0x30, 0x49, 0x42, 0x00, 0x31, 0x48, 0x11, 0xF0, 0x6D, 0xFF, 0x38, 0x68, 0x90, 0xF8, 0x30, 0x02,
+ 0x80, 0x06, 0x04, 0xD5, 0x2C, 0x49, 0x22, 0x78, 0x08, 0x46, 0x00, 0xF0, 0x30, 0xF8, 0x38, 0x68,
+ 0x90, 0xF8, 0x30, 0x02, 0x40, 0x06, 0x04, 0xD5, 0x28, 0x49, 0x2A, 0x78, 0x08, 0x46, 0x00, 0xF0,
+ 0x26, 0xF8, 0x33, 0x46, 0x22, 0x78, 0x1A, 0x49, 0x25, 0x48, 0xFF, 0xF7, 0xED, 0xFE, 0x2A, 0x78,
+ 0x01, 0xB0, 0x33, 0x46, 0xBD, 0xE8, 0xF0, 0x43, 0x15, 0x49, 0x21, 0x48, 0x2A, 0x31, 0x08, 0x30,
+ 0xE2, 0xE6, 0x20, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x30, 0xB5, 0x00, 0x23, 0x03, 0x80,
+ 0x01, 0x23, 0x09, 0xE0, 0x00, 0xEB, 0x43, 0x04, 0x31, 0xF8, 0x13, 0x50, 0x34, 0xF8, 0x02, 0x4C,
+ 0x2C, 0x44, 0x20, 0xF8, 0x13, 0x40, 0x5B, 0x1C, 0x93, 0x42, 0xF3, 0xDB, 0x30, 0xBD, 0x08, 0xB5,
+ 0x00, 0x92, 0x04, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x4C, 0x32, 0xB2, 0xF9, 0x4A, 0x22, 0x01, 0xF0,
+ 0xED, 0xFC, 0x08, 0xBD, 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20,
+ 0x84, 0x09, 0x01, 0x20, 0xBA, 0x06, 0x10, 0x00, 0x94, 0x4A, 0x01, 0x20, 0x08, 0x24, 0x10, 0x00,
+ 0x32, 0x24, 0x10, 0x00, 0x92, 0x0A, 0x01, 0x20, 0xAC, 0x0B, 0x01, 0x20, 0x78, 0x06, 0x10, 0x00,
+ 0xC0, 0x0A, 0x01, 0x20, 0xEA, 0x0A, 0x01, 0x20, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20,
+ 0x90, 0x24, 0x10, 0x00, 0xC0, 0x06, 0x10, 0x00, 0x10, 0xB5, 0x40, 0x21, 0xFA, 0x48, 0x11, 0xF0,
+ 0xA2, 0xFF, 0xF9, 0x48, 0x40, 0x21, 0x40, 0x30, 0x11, 0xF0, 0x9D, 0xFF, 0xF6, 0x48, 0x00, 0x21,
+ 0x80, 0x30, 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x10, 0x30, 0xC0, 0xE9, 0x00, 0x11,
+ 0xC0, 0xE9, 0x02, 0x11, 0x10, 0x30, 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x08, 0x46,
+ 0xEE, 0x49, 0x08, 0x60, 0x10, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x06, 0x46, 0x89, 0x46, 0xEC, 0x48,
+ 0xEC, 0x49, 0x98, 0x46, 0x00, 0x78, 0x09, 0x68, 0x14, 0x46, 0x01, 0x28, 0x50, 0xD0, 0xB1, 0xF9,
+ 0x86, 0xA2, 0x91, 0xF8, 0x88, 0x52, 0xB1, 0xF9, 0x82, 0x72, 0x11, 0x46, 0x48, 0x46, 0x0D, 0xF0,
+ 0x26, 0xFB, 0x83, 0x46, 0x21, 0x46, 0x48, 0x46, 0x0D, 0xF0, 0x2C, 0xFB, 0x00, 0x90, 0x39, 0x46,
+ 0x58, 0x46, 0x0C, 0xF0, 0xFB, 0xFB, 0x0F, 0xFA, 0x80, 0xFB, 0x39, 0x46, 0x00, 0x98, 0x0C, 0xF0,
+ 0xF5, 0xFB, 0x00, 0xB2, 0xAB, 0xEB, 0x00, 0x00, 0x68, 0x43, 0x64, 0x21, 0x90, 0xFB, 0xF1, 0xF0,
+ 0x38, 0x44, 0x05, 0xB2, 0xA8, 0xF8, 0x08, 0x50, 0x70, 0x1C, 0x00, 0x21, 0x03, 0x90, 0xC8, 0xF8,
+ 0x00, 0x10, 0xC8, 0xF8, 0x04, 0x10, 0xB9, 0xF9, 0x00, 0x00, 0xA8, 0x42, 0x02, 0xDD, 0x03, 0x99,
+ 0x01, 0x20, 0x08, 0x70, 0x09, 0xEB, 0x44, 0x00, 0x76, 0x1C, 0x30, 0xF9, 0x02, 0x2C, 0x31, 0x19,
+ 0xAA, 0x42, 0x02, 0xDD, 0x01, 0x22, 0x01, 0xF8, 0x01, 0x2C, 0xB9, 0xF9, 0x02, 0x30, 0x03, 0xEB,
+ 0x0A, 0x02, 0x12, 0xB2, 0xAB, 0x42, 0x18, 0xDD, 0xB9, 0xF9, 0x00, 0x30, 0x93, 0x42, 0x03, 0xDD,
+ 0xB9, 0xF9, 0x04, 0x30, 0x93, 0x42, 0x0A, 0xDC, 0x03, 0x9B, 0x01, 0x22, 0x5A, 0x70, 0x0C, 0xE0,
+ 0xB1, 0xF9, 0x6A, 0xA2, 0x91, 0xF8, 0x65, 0x52, 0xB1, 0xF9, 0x66, 0x72, 0xAD, 0xE7, 0xD8, 0xF8,
+ 0x00, 0x60, 0x46, 0xF0, 0x02, 0x06, 0xC8, 0xF8, 0x00, 0x60, 0x30, 0xF9, 0x04, 0x3C, 0xA4, 0xF1,
+ 0x02, 0x0B, 0x03, 0xEB, 0x0A, 0x02, 0x12, 0xB2, 0xAB, 0x42, 0x16, 0xDD, 0x30, 0xF9, 0x06, 0x3C,
+ 0x93, 0x42, 0x03, 0xDD, 0x30, 0xF9, 0x02, 0x0C, 0x90, 0x42, 0x03, 0xDC, 0x01, 0x20, 0x01, 0xF8,
+ 0x02, 0x0C, 0x0A, 0xE0, 0xD8, 0xE9, 0x00, 0x64, 0x5A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0,
+ 0x2A, 0xFE, 0x06, 0x43, 0x0C, 0x43, 0xC8, 0xE9, 0x00, 0x64, 0x02, 0x24, 0x58, 0xE0, 0x00, 0xBF,
+ 0x39, 0xF9, 0x14, 0x00, 0xA8, 0x42, 0x52, 0xDD, 0x09, 0xEB, 0x44, 0x01, 0x02, 0x91, 0x50, 0x44,
+ 0x31, 0xF9, 0x02, 0x1C, 0x00, 0xB2, 0x81, 0x42, 0x04, 0xDD, 0x02, 0x9A, 0xB2, 0xF9, 0x02, 0x20,
+ 0x82, 0x42, 0x10, 0xDC, 0x02, 0x9A, 0x32, 0xF9, 0x04, 0x2C, 0x82, 0x42, 0x04, 0xDD, 0x02, 0x9A,
+ 0xB2, 0xF9, 0x02, 0x20, 0x82, 0x42, 0x06, 0xDC, 0x81, 0x42, 0x35, 0xDD, 0x02, 0x99, 0xB1, 0xF9,
+ 0x04, 0x10, 0x81, 0x42, 0x30, 0xDD, 0xD8, 0xE9, 0x00, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x11, 0xF0, 0xF9, 0xFD, 0xCD, 0xE9, 0x00, 0x01, 0x06, 0x43, 0x0F, 0x43, 0x62, 0x1E, 0x01, 0x20,
+ 0x00, 0x21, 0xC8, 0xE9, 0x00, 0x67, 0x11, 0xF0, 0xEE, 0xFD, 0x02, 0x46, 0x0B, 0x46, 0x06, 0xEA,
+ 0x02, 0x00, 0x07, 0xEA, 0x03, 0x01, 0x08, 0x43, 0x19, 0xD0, 0x02, 0x98, 0x39, 0xF9, 0x14, 0x10,
+ 0x30, 0xF9, 0x02, 0x0C, 0x81, 0x42, 0x09, 0xDA, 0x96, 0x43, 0x9F, 0x43, 0xC8, 0xE9, 0x00, 0x67,
+ 0x03, 0x99, 0x01, 0x20, 0x21, 0x44, 0x01, 0xF8, 0x01, 0x0C, 0x08, 0xE0, 0xDD, 0xE9, 0x00, 0x10,
+ 0x8E, 0x43, 0x87, 0x43, 0xC8, 0xE9, 0x00, 0x67, 0x03, 0x99, 0x01, 0x20, 0x08, 0x55, 0x64, 0x1C,
+ 0x5C, 0x45, 0xA5, 0xD3, 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0x82, 0x46,
+ 0x00, 0x21, 0x1D, 0x46, 0x19, 0x76, 0x06, 0x20, 0x90, 0x46, 0xC3, 0x1F, 0x76, 0x4C, 0x07, 0xE0,
+ 0x00, 0x22, 0x29, 0x18, 0x0A, 0x73, 0x8B, 0x74, 0x05, 0xEB, 0x40, 0x01, 0x22, 0x88, 0x0A, 0x80,
+ 0x40, 0x1E, 0xF5, 0xD2, 0x6E, 0x48, 0x01, 0x78, 0x6E, 0x48, 0x01, 0x29, 0x00, 0x68, 0x06, 0xD0,
+ 0xB0, 0xF9, 0x84, 0x22, 0x4F, 0xF0, 0x00, 0x0B, 0x59, 0x46, 0x58, 0x46, 0x16, 0xE0, 0xB0, 0xF9,
+ 0x68, 0x22, 0xF7, 0xE7, 0x0A, 0xEB, 0x00, 0x03, 0x5C, 0x78, 0x74, 0xB1, 0x1A, 0xF8, 0x00, 0x40,
+ 0x0C, 0xB9, 0x49, 0x1C, 0xC9, 0xB2, 0x59, 0x70, 0x02, 0x9B, 0x33, 0xF9, 0x10, 0x30, 0x93, 0x42,
+ 0x03, 0xDD, 0x01, 0x23, 0x8B, 0x40, 0x43, 0xEA, 0x0B, 0x0B, 0x40, 0x1C, 0x40, 0x45, 0xE9, 0xD3,
+ 0x5E, 0x48, 0x00, 0x90, 0x0E, 0x98, 0x4F, 0xF0, 0x00, 0x09, 0x4C, 0x46, 0xC0, 0xE9, 0x00, 0x99,
+ 0x37, 0xE0, 0x00, 0xBF, 0x0A, 0xEB, 0x04, 0x00, 0x42, 0x78, 0x8A, 0xB3, 0x01, 0x21, 0x91, 0x40,
+ 0x11, 0xEA, 0x0B, 0x0F, 0x02, 0xD1, 0x00, 0x21, 0x41, 0x70, 0x29, 0xE0, 0x1A, 0xF8, 0x04, 0x10,
+ 0x39, 0xB9, 0x09, 0xF1, 0x01, 0x01, 0x01, 0xF0, 0xFF, 0x09, 0x50, 0x49, 0x00, 0x91, 0x05, 0xF8,
+ 0x19, 0x40, 0x80, 0xF8, 0x01, 0x90, 0x0E, 0x98, 0x22, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67,
+ 0x01, 0x20, 0x11, 0xF0, 0x60, 0xFD, 0x06, 0x43, 0x0E, 0x98, 0x0F, 0x43, 0xC0, 0xE9, 0x00, 0x67,
+ 0x05, 0xEB, 0x09, 0x00, 0x01, 0x7B, 0x49, 0x1C, 0x01, 0x73, 0x05, 0xEB, 0x49, 0x01, 0x4C, 0x70,
+ 0x02, 0x99, 0x00, 0x9A, 0x31, 0xF9, 0x14, 0x10, 0x91, 0x42, 0x01, 0xDD, 0x00, 0x91, 0x84, 0x74,
+ 0x64, 0x1C, 0x44, 0x45, 0xC6, 0xD3, 0x85, 0xF8, 0x18, 0x90, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F,
+ 0x2D, 0xE9, 0xF8, 0x4F, 0x0C, 0x46, 0x05, 0x46, 0x1E, 0x46, 0x91, 0x46, 0x17, 0x21, 0x38, 0x48,
+ 0x11, 0xF0, 0xEF, 0xFD, 0x28, 0x21, 0x37, 0x48, 0x11, 0xF0, 0xEB, 0xFD, 0xDF, 0xF8, 0xD8, 0xA0,
+ 0x36, 0x4F, 0x09, 0xF1, 0x08, 0x08, 0x9A, 0xF8, 0x00, 0x10, 0x76, 0xB1, 0x0A, 0x46, 0x05, 0xF1,
+ 0x20, 0x03, 0x33, 0x49, 0x2E, 0x48, 0xFF, 0xF7, 0x76, 0xFE, 0x04, 0xF1, 0x20, 0x03, 0x3A, 0x78,
+ 0x30, 0x49, 0x2C, 0x48, 0xFF, 0xF7, 0x6F, 0xFE, 0x11, 0xE0, 0x4A, 0x46, 0x28, 0x48, 0x00, 0xF0,
+ 0x24, 0xF9, 0x42, 0x46, 0x39, 0x78, 0x27, 0x48, 0x00, 0xF0, 0x1F, 0xF9, 0x00, 0x20, 0xC5, 0xE9,
+ 0x08, 0x00, 0xC4, 0xE9, 0x08, 0x00, 0x28, 0x48, 0x00, 0x88, 0x28, 0x85, 0x20, 0x85, 0x27, 0x4E,
+ 0x28, 0x8D, 0x2B, 0x46, 0x26, 0xF8, 0x11, 0x0F, 0x20, 0x8D, 0x70, 0x80, 0xCD, 0xF8, 0x00, 0x90,
+ 0x9A, 0xF8, 0x00, 0x20, 0x1E, 0x49, 0x1A, 0x48, 0xFF, 0xF7, 0x36, 0xFF, 0xCD, 0xF8, 0x00, 0x80,
+ 0x23, 0x46, 0x3A, 0x78, 0x1B, 0x49, 0x17, 0x48, 0xFF, 0xF7, 0x2E, 0xFF, 0x29, 0x7E, 0x30, 0x79,
+ 0x61, 0xF3, 0x03, 0x00, 0x30, 0x71, 0x21, 0x7E, 0x61, 0xF3, 0x07, 0x10, 0x30, 0x71, 0xBD, 0xE8,
+ 0xF8, 0x8F, 0x70, 0xB5, 0x0B, 0x4C, 0x20, 0x68, 0x90, 0xF8, 0x30, 0x12, 0x09, 0x07, 0x42, 0xD5,
+ 0x13, 0x49, 0x0A, 0x78, 0x0A, 0xB9, 0x49, 0x78, 0xE9, 0xB3, 0x05, 0x49, 0x09, 0x78, 0x01, 0x29,
+ 0x20, 0xD0, 0xB0, 0xF8, 0x42, 0x12, 0x1F, 0xE0, 0x58, 0x23, 0x10, 0x00, 0x00, 0x05, 0x10, 0x00,
+ 0x0E, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x18, 0x6B, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF,
+ 0xFC, 0x0B, 0x01, 0x20, 0x13, 0x0C, 0x01, 0x20, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00,
+ 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, 0x10, 0x05, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20,
+ 0xEC, 0x06, 0x10, 0x00, 0xB0, 0xF8, 0x48, 0x12, 0x01, 0x22, 0x0D, 0xB2, 0xB0, 0xF9, 0x44, 0x12,
+ 0x6A, 0x48, 0x00, 0xF0, 0x94, 0xFA, 0x20, 0x68, 0x01, 0x22, 0xB0, 0xF9, 0x46, 0x12, 0x67, 0x48,
+ 0x10, 0x30, 0x00, 0xF0, 0x8C, 0xFA, 0x29, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x63, 0x48, 0x01, 0x22,
+ 0x10, 0x38, 0x00, 0xF0, 0x84, 0xBA, 0x61, 0x48, 0x4F, 0xF0, 0xFF, 0x31, 0xC0, 0xE9, 0x00, 0x11,
+ 0xC0, 0xE9, 0x02, 0x11, 0x10, 0x38, 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x20, 0x30,
+ 0xC0, 0xE9, 0x00, 0x11, 0xC0, 0xE9, 0x02, 0x11, 0x70, 0xBD, 0x2D, 0xE9, 0xFF, 0x4F, 0x83, 0xB0,
+ 0x15, 0x46, 0x06, 0x99, 0x91, 0xF8, 0x40, 0x10, 0x02, 0x29, 0x0C, 0xD0, 0x01, 0x29, 0x0C, 0xD0,
+ 0x52, 0x49, 0x10, 0x39, 0x8A, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0xA9, 0x78, 0x11, 0xF0, 0x48, 0xFE,
+ 0x81, 0x46, 0xA8, 0x78, 0x32, 0xE0, 0x4D, 0x49, 0xF4, 0xE7, 0x4C, 0x49, 0x10, 0x31, 0xF1, 0xE7,
+ 0x02, 0x46, 0x2C, 0x78, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x6D, 0xFC, 0xCD, 0xE9, 0x00, 0x01,
+ 0x1D, 0xE0, 0x00, 0xBF, 0x19, 0xF8, 0x04, 0x10, 0x04, 0x98, 0x81, 0x42, 0x16, 0xD1, 0xDD, 0xE9,
+ 0x00, 0x23, 0xDA, 0xE9, 0x00, 0x01, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x23, 0xD0, 0xDA, 0xE9,
+ 0x02, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x55, 0xFC, 0x06, 0x40, 0x0F, 0x40,
+ 0x3E, 0x43, 0x18, 0xD0, 0x0B, 0xF1, 0x01, 0x00, 0x1F, 0xFA, 0x80, 0xFB, 0x64, 0x1C, 0x68, 0x78,
+ 0xA0, 0x42, 0xDF, 0xDA, 0x09, 0xF1, 0x28, 0x09, 0x08, 0xF1, 0x01, 0x00, 0xE9, 0x78, 0x80, 0x46,
+ 0x41, 0x45, 0xCD, 0xDA, 0x06, 0x99, 0x5F, 0xEA, 0x0B, 0x00, 0xA1, 0xF8, 0x26, 0xB0, 0x00, 0xD0,
+ 0x01, 0x20, 0x07, 0xB0, 0xF2, 0xE6, 0x00, 0x20, 0x09, 0xF8, 0x04, 0x00, 0xE6, 0xE7, 0x2D, 0xE9,
+ 0xFC, 0x5F, 0x80, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0x87, 0x78, 0x90, 0xF8, 0x03, 0xA0, 0x2A, 0xE0,
+ 0x98, 0xF8, 0x00, 0x40, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x24, 0xFC, 0x24, 0x4E,
+ 0xD6, 0xE9, 0x00, 0x32, 0x03, 0x40, 0x0A, 0x40, 0xCD, 0xE9, 0x00, 0x23, 0xD6, 0xE9, 0x02, 0x56,
+ 0x98, 0xF8, 0x01, 0x90, 0x14, 0xE0, 0x00, 0xBF, 0xDD, 0xE9, 0x00, 0x10, 0x08, 0x43, 0x0E, 0xD0,
+ 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0x0E, 0xFC, 0x05, 0xEA, 0x00, 0x02, 0x06, 0xEA,
+ 0x01, 0x00, 0x02, 0x43, 0x03, 0xD0, 0x0B, 0xF1, 0x01, 0x00, 0x1F, 0xFA, 0x80, 0xFB, 0x64, 0x1C,
+ 0xA1, 0x45, 0xE9, 0xDA, 0x7F, 0x1C, 0xBA, 0x45, 0xD2, 0xDA, 0xBB, 0xF1, 0x00, 0x0F, 0x02, 0xD0,
+ 0x01, 0x20, 0xBD, 0xE8, 0xFC, 0x9F, 0x00, 0x20, 0xFB, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0x91, 0x46,
+ 0x45, 0x1C, 0x0C, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x0C, 0xE0, 0xD9, 0xE9, 0x00, 0x67, 0x22, 0x46,
+ 0x01, 0x20, 0x00, 0x21, 0x11, 0xF0, 0xE7, 0xFB, 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x01, 0xD0,
+ 0x05, 0xF8, 0x04, 0x80, 0x64, 0x1E, 0xF0, 0xD2, 0xBD, 0xE8, 0xF0, 0x87, 0xE8, 0x23, 0x10, 0x00,
+ 0x90, 0x24, 0x10, 0x00, 0xA1, 0x4A, 0x10, 0xB5, 0x13, 0x68, 0x00, 0x21, 0xB3, 0xF8, 0x14, 0x22,
+ 0x82, 0x42, 0x05, 0xDA, 0x93, 0xF8, 0x10, 0x22, 0x52, 0x07, 0x01, 0xD5, 0x02, 0x21, 0x08, 0xE0,
+ 0xB3, 0xF8, 0x12, 0x22, 0x82, 0x42, 0x04, 0xDA, 0x93, 0xF8, 0x10, 0x02, 0x80, 0x07, 0x00, 0xD5,
+ 0x01, 0x21, 0x97, 0x48, 0x97, 0x4C, 0x42, 0x78, 0x91, 0x42, 0x14, 0xD1, 0xA1, 0x78, 0x91, 0x42,
+ 0x0D, 0xD0, 0x95, 0x4B, 0x1B, 0x78, 0x1A, 0x43, 0x94, 0x4B, 0x1B, 0x78, 0x1A, 0x43, 0x07, 0xD0,
+ 0x41, 0x68, 0x49, 0x1E, 0x41, 0x60, 0x00, 0x29, 0x01, 0xDC, 0x40, 0x78, 0xA0, 0x70, 0x10, 0xBD,
+ 0x41, 0x70, 0x41, 0x68, 0xF7, 0xE7, 0x59, 0xB1, 0x02, 0x29, 0x01, 0xD1, 0x01, 0x2A, 0x07, 0xD0,
+ 0x93, 0xF8, 0x18, 0x22, 0x42, 0x60, 0x41, 0x70, 0x00, 0x2A, 0xF0, 0xDC, 0xA1, 0x70, 0x10, 0xBD,
+ 0x93, 0xF8, 0x19, 0x22, 0xF6, 0xE7, 0x70, 0xB5, 0x85, 0x4A, 0x86, 0x4B, 0x81, 0x4D, 0x16, 0x78,
+ 0x7E, 0x4A, 0x9C, 0x79, 0x00, 0x21, 0x12, 0x68, 0xAB, 0x78, 0x01, 0x2E, 0x02, 0xD1, 0x82, 0x4E,
+ 0x36, 0x78, 0x4E, 0xB1, 0xB2, 0xF8, 0x14, 0x62, 0x86, 0x42, 0x17, 0xDA, 0x92, 0xF8, 0x10, 0x62,
+ 0x76, 0x07, 0x13, 0xD5, 0x02, 0x21, 0x25, 0xE0, 0xB2, 0xF8, 0x1C, 0x62, 0x86, 0x42, 0x03, 0xDA,
+ 0x92, 0xF8, 0x10, 0x62, 0x76, 0x07, 0xF5, 0xD4, 0xB2, 0xF8, 0x1A, 0x62, 0x08, 0xE0, 0x00, 0xBF,
+ 0x92, 0xF8, 0x10, 0x02, 0x80, 0x07, 0x05, 0xD5, 0x01, 0x21, 0x13, 0xE0, 0xB2, 0xF8, 0x12, 0x62,
+ 0x86, 0x42, 0xF5, 0xDB, 0x73, 0xB1, 0x6C, 0x48, 0x00, 0x78, 0x01, 0x28, 0x03, 0xD0, 0x6B, 0x48,
+ 0x00, 0x78, 0x01, 0x28, 0x03, 0xD1, 0x92, 0xF8, 0x10, 0x02, 0x00, 0x07, 0x01, 0xD5, 0x01, 0x2C,
+ 0x00, 0xD1, 0x19, 0x46, 0x62, 0x48, 0x34, 0xB1, 0x19, 0xB1, 0x00, 0xBF, 0x92, 0xF8, 0x19, 0x22,
+ 0x42, 0x60, 0xA9, 0x70, 0x70, 0xBD, 0x00, 0x29, 0xF8, 0xD1, 0x00, 0x2B, 0xF6, 0xD0, 0x44, 0x68,
+ 0x00, 0x2C, 0xF6, 0xDD, 0x92, 0xF8, 0x10, 0x12, 0x0A, 0x07, 0x59, 0x49, 0x49, 0x68, 0xA1, 0xF1,
+ 0x01, 0x01, 0x02, 0xD5, 0x5D, 0x4A, 0x12, 0x78, 0x02, 0xB1, 0x41, 0x60, 0x19, 0x46, 0xE8, 0xE7,
+ 0x52, 0x48, 0x53, 0x49, 0x00, 0x68, 0x90, 0xF8, 0x10, 0x02, 0xC2, 0x06, 0x4F, 0xF0, 0x00, 0x00,
+ 0x03, 0xD4, 0x50, 0x4A, 0x90, 0x70, 0x48, 0x70, 0x48, 0x60, 0x08, 0x70, 0x70, 0x47, 0x10, 0xB5,
+ 0x04, 0x46, 0x4A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x10, 0x02, 0xC0, 0x06, 0x20, 0x46, 0x02, 0xD5,
+ 0xFF, 0xF7, 0x89, 0xFF, 0x01, 0xE0, 0xFF, 0xF7, 0x45, 0xFF, 0x46, 0x48, 0x82, 0x78, 0x4C, 0x48,
+ 0x41, 0x7B, 0x62, 0xF3, 0x07, 0x11, 0x41, 0x73, 0xA0, 0xF8, 0x2F, 0x40, 0x10, 0xBD, 0x2D, 0xE9,
+ 0xFC, 0x5F, 0x83, 0x46, 0x47, 0x48, 0x00, 0x25, 0x0A, 0x46, 0x00, 0x78, 0x2F, 0x46, 0x2C, 0x46,
+ 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x44, 0x48, 0x06, 0x78, 0x00, 0x78, 0x41, 0x00, 0x01, 0x2A,
+ 0x1B, 0xD0, 0xDF, 0xF8, 0xD8, 0x80, 0xDF, 0xF8, 0x04, 0xA1, 0xDF, 0xF8, 0x04, 0x91, 0xD8, 0xF8,
+ 0x00, 0x00, 0x90, 0xF8, 0x10, 0x22, 0x92, 0x06, 0x14, 0xD5, 0x32, 0x1B, 0xB0, 0xF9, 0x20, 0x12,
+ 0xCD, 0xE9, 0x00, 0x12, 0xB0, 0xF9, 0x1E, 0x32, 0x0A, 0xEB, 0x44, 0x02, 0x0B, 0xEB, 0x44, 0x01,
+ 0x09, 0xEB, 0x44, 0x00, 0x0C, 0xF0, 0x58, 0xFE, 0x09, 0xE0, 0x34, 0x48, 0x4C, 0x38, 0x11, 0xF0,
+ 0x98, 0xFB, 0x41, 0xE0, 0x0A, 0x46, 0x59, 0x46, 0x31, 0x48, 0x11, 0xF0, 0x13, 0xFB, 0x2F, 0x48,
+ 0x4C, 0x38, 0x34, 0xE0, 0x3A, 0xF9, 0x14, 0x20, 0x39, 0xF9, 0x14, 0x10, 0x51, 0x1A, 0x00, 0xD5,
+ 0x49, 0x42, 0xD8, 0xF8, 0x00, 0x30, 0x09, 0xB2, 0x93, 0xF8, 0x10, 0x22, 0x52, 0x06, 0x0B, 0xD5,
+ 0x20, 0x4A, 0x92, 0x79, 0x01, 0x2A, 0x07, 0xD1, 0x26, 0x4A, 0x12, 0x78, 0x22, 0xB9, 0xB3, 0xF8,
+ 0x22, 0x22, 0x8A, 0x42, 0x00, 0xDA, 0x01, 0x27, 0x30, 0xF9, 0x14, 0x20, 0x8A, 0x42, 0x02, 0xDA,
+ 0x93, 0xF8, 0x16, 0x32, 0x01, 0xE0, 0x93, 0xF8, 0x17, 0x32, 0x5A, 0x43, 0xC3, 0xF5, 0x80, 0x73,
+ 0x01, 0xFB, 0x03, 0x21, 0xCA, 0x17, 0x01, 0xEB, 0x12, 0x61, 0x09, 0x12, 0x20, 0xF8, 0x14, 0x10,
+ 0x30, 0xF9, 0x14, 0x10, 0xA9, 0x42, 0x00, 0xDD, 0x0D, 0x46, 0x64, 0x1C, 0x24, 0xB2, 0xB4, 0x42,
+ 0xC8, 0xDB, 0x28, 0x46, 0xFF, 0xF7, 0x73, 0xFF, 0x72, 0x00, 0x59, 0x46, 0x0F, 0x48, 0x11, 0xF0,
+ 0xD1, 0xFA, 0x03, 0x48, 0x07, 0x70, 0xBD, 0xE8, 0xFC, 0x9F, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x04, 0x05, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, 0xC1, 0x06, 0x10, 0x00, 0x0C, 0x05, 0x10, 0x00,
+ 0xC2, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0xC3, 0x06, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00,
+ 0xE6, 0x43, 0x01, 0x20, 0xC0, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x46, 0x0A, 0x01, 0x20,
+ 0x92, 0x0A, 0x01, 0x20, 0x1C, 0x05, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x81, 0x46, 0xDD, 0xE9,
+ 0x09, 0xB5, 0x01, 0x20, 0x47, 0xF6, 0xFF, 0x77, 0x9A, 0x46, 0x84, 0x46, 0xFE, 0x43, 0x2C, 0x46,
+ 0x15, 0xE0, 0x00, 0xBF, 0x32, 0xF8, 0x14, 0x30, 0x31, 0xF8, 0x14, 0x80, 0xA3, 0xEB, 0x08, 0x03,
+ 0x1B, 0xB2, 0xBB, 0x42, 0x00, 0xDA, 0x1F, 0x46, 0xB3, 0x42, 0x00, 0xDD, 0x1E, 0x46, 0x00, 0x2B,
+ 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x0C, 0x02, 0xE0, 0x01, 0xDA, 0x4F, 0xF0, 0x00, 0x00, 0x64, 0x1E,
+ 0xE8, 0xD2, 0x20, 0xB1, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x00, 0x23, 0x09, 0xE0, 0x50, 0xEA,
+ 0x0C, 0x03, 0x06, 0xD0, 0x20, 0xB9, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x33, 0x46, 0x00, 0xE0,
+ 0x3B, 0x46, 0x00, 0x27, 0x3C, 0x46, 0x28, 0x46, 0xCB, 0xF1, 0x00, 0x0C, 0x0E, 0xE0, 0x00, 0xBF,
+ 0x32, 0xF8, 0x10, 0x60, 0x31, 0xF8, 0x10, 0x80, 0xA6, 0xEB, 0x08, 0x06, 0xF6, 0x1A, 0x36, 0xB2,
+ 0x56, 0x45, 0x03, 0xDA, 0x66, 0x45, 0x01, 0xDD, 0x37, 0x44, 0x64, 0x1C, 0x40, 0x1E, 0xEF, 0xD2,
+ 0x04, 0xB9, 0x01, 0x24, 0x97, 0xFB, 0xF4, 0xF0, 0x18, 0x44, 0x04, 0xE0, 0x31, 0xF8, 0x15, 0x20,
+ 0x02, 0x44, 0x29, 0xF8, 0x15, 0x20, 0x6D, 0x1E, 0xF8, 0xD2, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x04, 0x46, 0x03, 0x46, 0xFE, 0x48, 0x15, 0x46, 0x0E, 0x46, 0x0A, 0x46, 0x01, 0x78,
+ 0xFC, 0x48, 0x00, 0xF0, 0x57, 0xFA, 0xFC, 0x48, 0x04, 0xF1, 0x08, 0x03, 0x1F, 0x46, 0x01, 0x78,
+ 0xF8, 0x48, 0x32, 0x46, 0x2A, 0x30, 0x00, 0xF0, 0x4D, 0xFA, 0x00, 0x2D, 0x07, 0xD0, 0x20, 0x46,
+ 0x11, 0xF0, 0xB0, 0xFB, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x11, 0xF0, 0xAB, 0xBB, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0x07, 0x46, 0x14, 0x46, 0x88, 0x46, 0x03, 0x20, 0x0F, 0xF0,
+ 0x3A, 0xFA, 0xEE, 0x4D, 0xEA, 0x4E, 0x00, 0x94, 0xEA, 0x48, 0x32, 0x78, 0x39, 0x46, 0x76, 0x38,
+ 0x2B, 0x68, 0x0C, 0xF0, 0xEF, 0xFD, 0x00, 0x94, 0xE7, 0x4C, 0xE6, 0x48, 0x41, 0x46, 0x22, 0x78,
+ 0x4C, 0x38, 0x2B, 0x68, 0x0C, 0xF0, 0xE6, 0xFD, 0xE5, 0x4D, 0x28, 0x68, 0x90, 0xF8, 0x30, 0x12,
+ 0xC9, 0x07, 0x1A, 0xD0, 0x32, 0x78, 0xB0, 0xF9, 0x34, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xDD, 0x49,
+ 0xB0, 0xF9, 0x32, 0x32, 0x76, 0x39, 0xDF, 0x4A, 0x08, 0x46, 0xFF, 0xF7, 0x55, 0xFF, 0x28, 0x68,
+ 0x22, 0x78, 0xB0, 0xF9, 0x38, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xD6, 0x49, 0xB0, 0xF9, 0x36, 0x32,
+ 0x4C, 0x39, 0xD9, 0x4A, 0x08, 0x46, 0xFF, 0xF7, 0x47, 0xFF, 0xD2, 0x49, 0x33, 0x78, 0xD5, 0x4A,
+ 0x76, 0x39, 0xD0, 0x48, 0x0C, 0xF0, 0xA1, 0xFD, 0xCE, 0x49, 0x23, 0x78, 0x4C, 0x39, 0xD2, 0x4A,
+ 0x01, 0xF1, 0x76, 0x00, 0x0C, 0xF0, 0x99, 0xFD, 0x28, 0x68, 0x90, 0xF8, 0x30, 0x12, 0x8A, 0x07,
+ 0x04, 0xD4, 0xCE, 0x4A, 0x12, 0x78, 0x8A, 0xB1, 0x49, 0x07, 0x0F, 0xD5, 0xC5, 0x49, 0x90, 0xF8,
+ 0x41, 0x32, 0x32, 0x78, 0x08, 0x46, 0x0C, 0xF0, 0xD8, 0xFD, 0x28, 0x68, 0xC1, 0x49, 0x22, 0x78,
+ 0x90, 0xF8, 0x41, 0x32, 0x2A, 0x31, 0x08, 0x46, 0x0C, 0xF0, 0xCF, 0xFD, 0xBD, 0xE8, 0xFC, 0x41,
+ 0x03, 0x20, 0x0F, 0xF0, 0xF3, 0xB9, 0x70, 0xB5, 0xC1, 0x4C, 0xC2, 0x49, 0x00, 0x25, 0xA5, 0x70,
+ 0x01, 0x20, 0x08, 0x70, 0xBA, 0x48, 0x25, 0x70, 0x65, 0x70, 0x00, 0x68, 0xB0, 0xF8, 0x3A, 0x02,
+ 0xA0, 0x80, 0x00, 0xF0, 0xE9, 0xF9, 0xFF, 0xF7, 0x6C, 0xFA, 0xA5, 0x60, 0xE5, 0x60, 0x70, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, 0xB7, 0x49, 0x07, 0x46, 0xB5, 0x4C, 0x0D, 0x78, 0x00, 0x20,
+ 0x08, 0x70, 0x60, 0x70, 0x00, 0xF0, 0xD8, 0xF9, 0xB3, 0x48, 0x2A, 0x46, 0x31, 0x46, 0x00, 0x78,
+ 0x00, 0x28, 0x38, 0x46, 0x02, 0xD0, 0xFF, 0xF7, 0xC3, 0xF9, 0x01, 0xE0, 0xFF, 0xF7, 0x69, 0xFF,
+ 0xAE, 0x48, 0x41, 0x78, 0xA6, 0x48, 0xA9, 0xB1, 0xA1, 0x78, 0x01, 0x29, 0x12, 0xD0, 0x00, 0x68,
+ 0xB0, 0xF9, 0x3C, 0x12, 0xAA, 0x4D, 0xA1, 0x80, 0x01, 0x22, 0x28, 0x46, 0xFF, 0xF7, 0x37, 0xFF,
+ 0xD5, 0xE9, 0x00, 0x01, 0x08, 0x43, 0x09, 0xD0, 0xD5, 0xE9, 0x02, 0x01, 0x08, 0x43, 0x05, 0xD0,
+ 0x01, 0x20, 0x04, 0xE0, 0x00, 0x68, 0xB0, 0xF9, 0x3A, 0x12, 0xEB, 0xE7, 0x00, 0x20, 0x20, 0x70,
+ 0x45, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0x04, 0x46, 0x9E, 0x48, 0xA7, 0xB0, 0x4F, 0xF0, 0x01, 0x0A,
+ 0x01, 0x78, 0x93, 0x48, 0x01, 0x29, 0x00, 0x68, 0x18, 0xD0, 0x94, 0x49, 0x09, 0x78, 0xC1, 0xB1,
+ 0xB0, 0xF9, 0x54, 0x62, 0x8A, 0x48, 0x01, 0x21, 0x00, 0x27, 0x00, 0x78, 0x80, 0x1E, 0x00, 0xF0,
+ 0xFF, 0x09, 0x89, 0x48, 0x03, 0x78, 0x5A, 0x1E, 0x02, 0xF0, 0xFF, 0x08, 0x92, 0x4A, 0x12, 0x78,
+ 0x02, 0xB1, 0x01, 0x27, 0x91, 0x4D, 0x22, 0x46, 0x83, 0x46, 0x12, 0xE0, 0xB0, 0xF9, 0x59, 0x62,
+ 0xE8, 0xE7, 0xB0, 0xF9, 0x52, 0x62, 0xE5, 0xE7, 0x38, 0x46, 0x05, 0xE0, 0x32, 0xF9, 0x10, 0xC0,
+ 0xAC, 0x45, 0x00, 0xDD, 0x65, 0x46, 0x40, 0x1C, 0x40, 0x45, 0xF7, 0xDD, 0x02, 0xEB, 0x43, 0x02,
+ 0x49, 0x1C, 0x49, 0x45, 0xF0, 0xDD, 0x5F, 0x46, 0x5A, 0x00, 0x04, 0xEB, 0x43, 0x01, 0x68, 0x46,
+ 0x11, 0xF0, 0x38, 0xF9, 0x82, 0x4A, 0x38, 0x78, 0x6B, 0x46, 0x12, 0x88, 0x41, 0x42, 0x02, 0xEB,
+ 0x41, 0x01, 0x09, 0xB2, 0x42, 0x00, 0x04, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x40, 0x00, 0x11, 0xF0,
+ 0x29, 0xF9, 0x38, 0x78, 0x69, 0x46, 0x42, 0x00, 0x08, 0x46, 0x0C, 0xF0, 0x44, 0xFD, 0x28, 0x1A,
+ 0x00, 0xB2, 0xB0, 0x42, 0x01, 0xDD, 0x4F, 0xF0, 0x00, 0x0A, 0x50, 0x46, 0x27, 0xB0, 0xC4, 0xE6,
+ 0x2D, 0xE9, 0xF0, 0x4F, 0x73, 0x49, 0x72, 0x4A, 0x00, 0x27, 0x0C, 0x68, 0xB2, 0xF9, 0x00, 0x20,
+ 0x4F, 0xF0, 0x01, 0x0B, 0x21, 0x8E, 0x3B, 0x46, 0x91, 0x42, 0x4F, 0xD1, 0x63, 0x49, 0x0A, 0x78,
+ 0x5F, 0x49, 0x0E, 0x68, 0xB2, 0xB1, 0xB6, 0xF9, 0x54, 0x12, 0x02, 0x25, 0x89, 0x46, 0x58, 0x49,
+ 0x4F, 0xF0, 0x00, 0x0A, 0x09, 0x78, 0xC9, 0x1E, 0x01, 0xF0, 0xFF, 0x0E, 0x56, 0x49, 0x09, 0x78,
+ 0x49, 0x1E, 0x01, 0xF0, 0xFF, 0x0C, 0x60, 0x49, 0x09, 0x78, 0x09, 0xB1, 0x4F, 0xF0, 0x01, 0x0A,
+ 0x32, 0x34, 0x2B, 0xE0, 0xB6, 0xF9, 0x52, 0x12, 0xE7, 0xE7, 0x52, 0x46, 0x1D, 0xE0, 0x00, 0xBF,
+ 0x34, 0xF8, 0x12, 0x10, 0x30, 0xF8, 0x12, 0x80, 0xA1, 0xEB, 0x08, 0x01, 0x09, 0xB2, 0x00, 0x29,
+ 0x01, 0xDB, 0x88, 0x46, 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x08, 0xB8, 0x45, 0x05, 0xDD, 0x00, 0x29,
+ 0x01, 0xDB, 0x0F, 0x46, 0x00, 0xE0, 0x4F, 0x42, 0x3F, 0xB2, 0x00, 0x29, 0x00, 0xDA, 0x49, 0x42,
+ 0x49, 0x45, 0x01, 0xDD, 0x5B, 0x1C, 0x9B, 0xB2, 0x52, 0x1C, 0x62, 0x45, 0xE0, 0xDD, 0x96, 0xF8,
+ 0x30, 0x10, 0x6D, 0x1C, 0x04, 0xEB, 0x41, 0x04, 0x00, 0xEB, 0x41, 0x00, 0x75, 0x45, 0xD4, 0xDD,
+ 0x96, 0xF8, 0x56, 0x02, 0x98, 0x42, 0x01, 0xD2, 0x4F, 0xF0, 0x00, 0x0B, 0x46, 0x48, 0x20, 0xF8,
+ 0x33, 0x7F, 0x83, 0x70, 0x58, 0x46, 0x60, 0xE6, 0x2D, 0xE9, 0xF0, 0x41, 0x06, 0x46, 0x43, 0x48,
+ 0x00, 0x24, 0x00, 0x78, 0x00, 0x28, 0x5A, 0xD0, 0x3A, 0x48, 0x34, 0x4D, 0x00, 0x78, 0x88, 0xB1,
+ 0x3F, 0x48, 0x2F, 0x4B, 0x32, 0x49, 0x02, 0x68, 0x18, 0x68, 0x08, 0x31, 0xB0, 0xF8, 0x5D, 0x02,
+ 0x40, 0x42, 0x07, 0xB2, 0x00, 0x20, 0xC8, 0x80, 0x88, 0x80, 0x08, 0x60, 0x34, 0x48, 0xB0, 0xF9,
+ 0x00, 0x00, 0x25, 0xE0, 0x2C, 0x78, 0x01, 0x29, 0x01, 0xD0, 0x11, 0xB1, 0x3B, 0xE0, 0x01, 0x24,
+ 0x3A, 0xE0, 0x00, 0x24, 0x69, 0xE0, 0x00, 0xBF, 0x32, 0xF9, 0x10, 0xC0, 0xBC, 0xF1, 0x00, 0x0F,
+ 0x16, 0xDA, 0xB1, 0xF8, 0x04, 0xC0, 0x0C, 0xF1, 0x01, 0x0C, 0xA1, 0xF8, 0x04, 0xC0, 0x32, 0xF9,
+ 0x10, 0xE0, 0xD1, 0xF8, 0x00, 0xC0, 0xF4, 0x44, 0xC1, 0xF8, 0x00, 0xC0, 0x32, 0xF9, 0x10, 0xC0,
+ 0xBC, 0x45, 0x05, 0xDA, 0xB1, 0xF8, 0x06, 0xC0, 0x0C, 0xF1, 0x01, 0x0C, 0xA1, 0xF8, 0x06, 0xC0,
+ 0x40, 0x1E, 0xE1, 0xD2, 0x08, 0x68, 0x40, 0x42, 0x08, 0x60, 0x15, 0x48, 0x19, 0x68, 0x08, 0x30,
+ 0x02, 0x68, 0xB1, 0xF8, 0x5F, 0x32, 0x9A, 0x42, 0x3F, 0xDD, 0xB0, 0xF9, 0x06, 0x00, 0x91, 0xF8,
+ 0x61, 0x12, 0x88, 0x42, 0x39, 0xDD, 0x1B, 0x48, 0x11, 0x4A, 0xB0, 0xF9, 0x00, 0x10, 0x30, 0x46,
+ 0x00, 0xF0, 0x1E, 0xF9, 0x04, 0x46, 0x7C, 0xB3, 0x00, 0xF0, 0xF0, 0xF8, 0x2F, 0xE0, 0x3F, 0xE0,
+ 0xB9, 0x06, 0x10, 0x00, 0x36, 0x0B, 0x01, 0x20, 0xBA, 0x06, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, 0x1C, 0x05, 0x10, 0x00,
+ 0x0C, 0x05, 0x10, 0x00, 0x51, 0x07, 0x10, 0x00, 0xC0, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0x80, 0x24, 0x10, 0x00, 0x21, 0x05, 0x10, 0x00, 0xBF, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF,
+ 0xCA, 0x06, 0x10, 0x00, 0x24, 0x07, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0xEC, 0x06, 0x10, 0x00,
+ 0xE0, 0x06, 0x10, 0x00, 0x74, 0x06, 0x10, 0x00, 0xFF, 0xE7, 0x00, 0xF0, 0xD5, 0xF8, 0x50, 0x4E,
+ 0x28, 0x78, 0x31, 0x78, 0x88, 0x42, 0x06, 0xD0, 0x08, 0xB1, 0x01, 0x21, 0x00, 0xE0, 0x00, 0x21,
+ 0x06, 0x20, 0x0B, 0xF0, 0x8F, 0xF8, 0x28, 0x78, 0x30, 0x70, 0x0C, 0xB1, 0x01, 0x20, 0xDE, 0xE5,
+ 0x00, 0x20, 0xDC, 0xE5, 0x70, 0xB5, 0x03, 0x20, 0x0F, 0xF0, 0x1D, 0xF8, 0x00, 0xF0, 0x48, 0xF8,
+ 0x04, 0x46, 0x03, 0x20, 0x0F, 0xF0, 0x32, 0xF8, 0x42, 0x49, 0xC8, 0x7B, 0x64, 0xF3, 0x05, 0x10,
+ 0xC8, 0x73, 0x41, 0x48, 0x01, 0x78, 0x21, 0xB1, 0x00, 0x21, 0x01, 0x70, 0x20, 0x46, 0x00, 0xF0,
+ 0x35, 0xF9, 0x3E, 0x4D, 0x3E, 0x48, 0x21, 0x46, 0x2A, 0x78, 0x00, 0x68, 0xFF, 0xF7, 0x3C, 0xFF,
+ 0xA8, 0x70, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x1D, 0x46, 0x4F, 0xF0, 0x00, 0x08, 0xC5, 0xE9,
+ 0x00, 0x88, 0x91, 0x46, 0x82, 0x46, 0x0C, 0x46, 0x11, 0xE0, 0x00, 0xBF, 0x3A, 0xF9, 0x14, 0x10,
+ 0x49, 0x45, 0x0C, 0xDD, 0xD5, 0xE9, 0x00, 0x67, 0x4F, 0xF0, 0x01, 0x08, 0x22, 0x46, 0x40, 0x46,
+ 0x00, 0x21, 0x10, 0xF0, 0xA0, 0xFF, 0x06, 0x43, 0x0F, 0x43, 0xC5, 0xE9, 0x00, 0x67, 0x64, 0x1E,
+ 0xEC, 0xD2, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x2A, 0x48, 0x00, 0x21, 0xC0, 0xE9, 0x00, 0x11,
+ 0xC0, 0xE9, 0x02, 0x11, 0x08, 0x46, 0x28, 0x49, 0x08, 0x76, 0x28, 0x49, 0x08, 0x76, 0x70, 0x47,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x26, 0x4C, 0x20, 0x78, 0x02, 0x28, 0x33, 0xD9, 0x25, 0x4E, 0x30, 0x68,
+ 0x90, 0xF8, 0x50, 0x02, 0x41, 0x07, 0x24, 0x48, 0x00, 0x68, 0x02, 0xD5, 0x23, 0x49, 0x09, 0x78,
+ 0x79, 0xB1, 0xFF, 0xF7, 0x36, 0xFE, 0x05, 0x46, 0x30, 0x68, 0x90, 0xF8, 0x50, 0x02, 0x00, 0x07,
+ 0x1F, 0xD5, 0x22, 0x78, 0x1E, 0x4B, 0x1F, 0x49, 0x02, 0x2A, 0x1A, 0xDB, 0x1E, 0x4C, 0x50, 0x1E,
+ 0x07, 0xE0, 0xFF, 0xF7, 0x85, 0xFE, 0xEE, 0xE7, 0x33, 0xF9, 0x10, 0x70, 0xA7, 0x42, 0x00, 0xDD,
+ 0x3C, 0x46, 0x40, 0x1E, 0xF8, 0xD1, 0x98, 0x1C, 0x92, 0x1E, 0x0C, 0xF0, 0xB4, 0xFB, 0x20, 0x1A,
+ 0x01, 0xB2, 0x30, 0x68, 0xB0, 0xF9, 0x57, 0x02, 0x81, 0x42, 0x02, 0xDD, 0x35, 0xB1, 0x02, 0x20,
+ 0x55, 0xE5, 0x0D, 0xB1, 0x00, 0x20, 0x52, 0xE5, 0x01, 0x20, 0x50, 0xE5, 0x03, 0x20, 0x4E, 0xE5,
+ 0x1D, 0x05, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x20, 0x05, 0x10, 0x00, 0x0C, 0x05, 0x10, 0x00,
+ 0xE0, 0x06, 0x10, 0x00, 0x80, 0x24, 0x10, 0x00, 0x58, 0x23, 0x10, 0x00, 0x98, 0x23, 0x10, 0x00,
+ 0xB9, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, 0x21, 0x05, 0x10, 0x00,
+ 0x6A, 0x4A, 0x01, 0x20, 0x92, 0x0A, 0x01, 0x20, 0x00, 0x80, 0xFF, 0xFF, 0x53, 0x48, 0x00, 0x21,
+ 0xC1, 0x70, 0x02, 0x78, 0x00, 0x2A, 0x0E, 0xD1, 0x82, 0x78, 0x51, 0x4B, 0x52, 0x1C, 0xD2, 0xB2,
+ 0x82, 0x70, 0x1B, 0x68, 0x93, 0xF8, 0x62, 0x32, 0x03, 0xF0, 0x0F, 0x03, 0x93, 0x42, 0x02, 0xD2,
+ 0x01, 0x22, 0x02, 0x70, 0x81, 0x70, 0x70, 0x47, 0x48, 0x48, 0x00, 0x21, 0x81, 0x70, 0x02, 0x78,
+ 0x00, 0x2A, 0x0C, 0xD0, 0xC2, 0x78, 0x46, 0x4B, 0x52, 0x1C, 0xD2, 0xB2, 0xC2, 0x70, 0x1B, 0x68,
+ 0x93, 0xF8, 0x62, 0x32, 0xB2, 0xEB, 0x13, 0x1F, 0x01, 0xD9, 0x01, 0x70, 0xC1, 0x70, 0x70, 0x47,
+ 0x2D, 0xE9, 0xF7, 0x4F, 0x86, 0xB0, 0x8B, 0x46, 0xD2, 0xE9, 0x00, 0x01, 0xCD, 0xE9, 0x02, 0x01,
+ 0xD2, 0xE9, 0x02, 0x01, 0xCD, 0xE9, 0x04, 0x01, 0x02, 0xA8, 0x11, 0xF0, 0xA3, 0xF8, 0x04, 0xA8,
+ 0x11, 0xF0, 0xA0, 0xF8, 0x37, 0x48, 0x00, 0x27, 0xB9, 0x46, 0x06, 0x78, 0x31, 0xE0, 0xF1, 0xB2,
+ 0x06, 0x98, 0x11, 0xF0, 0xAD, 0xF8, 0x82, 0x46, 0x33, 0x48, 0x32, 0x46, 0x00, 0x21, 0x05, 0x78,
+ 0x01, 0x20, 0x10, 0xF0, 0xE0, 0xFE, 0x02, 0x9A, 0x00, 0xEA, 0x02, 0x04, 0x03, 0x98, 0x01, 0xEA,
+ 0x00, 0x08, 0xDD, 0xE9, 0x04, 0x01, 0xCD, 0xE9, 0x00, 0x01, 0x18, 0xE0, 0x3A, 0xF9, 0x15, 0x10,
+ 0x59, 0x45, 0x14, 0xDD, 0x54, 0xEA, 0x08, 0x00, 0x0F, 0xD0, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x10, 0xF0, 0xC9, 0xFE, 0xDD, 0xE9, 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x04, 0xD0,
+ 0x09, 0xF1, 0x01, 0x00, 0x1F, 0xFA, 0x80, 0xF9, 0x01, 0xE0, 0x7F, 0x1C, 0xBF, 0xB2, 0x6D, 0x1E,
+ 0xE4, 0xD2, 0x76, 0x1E, 0xCB, 0xD2, 0x1A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x5B, 0x12, 0xB9, 0x42,
+ 0x07, 0xD8, 0x90, 0xF8, 0x5C, 0x12, 0x49, 0x45, 0x03, 0xD3, 0x01, 0x20, 0x09, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0x00, 0x20, 0xFA, 0xE7, 0x11, 0x48, 0x10, 0xB5, 0x41, 0x78, 0x01, 0x70, 0x00, 0x21,
+ 0x81, 0x70, 0xC1, 0x70, 0xFF, 0xF7, 0x0F, 0xFD, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0xCC, 0xBF,
+ 0x0A, 0x48, 0x00, 0x21, 0x0A, 0x4A, 0x01, 0x70, 0x41, 0x70, 0x12, 0x68, 0x92, 0xF8, 0x50, 0x22,
+ 0x92, 0x07, 0x00, 0xD5, 0x01, 0x21, 0x41, 0x71, 0x01, 0x71, 0x70, 0x47, 0x03, 0x49, 0x4A, 0x79,
+ 0x01, 0x2A, 0x02, 0xD1, 0x00, 0x28, 0x00, 0xD1, 0x48, 0x71, 0x70, 0x47, 0x1C, 0x05, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x4F,
+ 0xCE, 0x4B, 0x83, 0xB0, 0x1B, 0x68, 0xB3, 0xF9, 0xD2, 0x42, 0xB3, 0xF9, 0xD4, 0xE2, 0x99, 0xE0,
+ 0x47, 0xF6, 0xFF, 0x76, 0xF7, 0x43, 0x06, 0x9D, 0x08, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x15, 0x30,
+ 0xB3, 0x42, 0x00, 0xDA, 0x1E, 0x46, 0xBB, 0x42, 0x00, 0xDD, 0x1F, 0x46, 0x6D, 0x1E, 0xF5, 0xD1,
+ 0xAB, 0x46, 0x00, 0x2F, 0x01, 0xDA, 0xBB, 0x46, 0x02, 0xE0, 0x00, 0x2E, 0x00, 0xDD, 0xB3, 0x46,
+ 0x00, 0x26, 0x37, 0x46, 0xB2, 0x46, 0x35, 0x46, 0xB1, 0x46, 0x06, 0x9B, 0x13, 0xE0, 0x00, 0xBF,
+ 0x31, 0xF9, 0x13, 0x80, 0xA8, 0xEB, 0x0B, 0x0C, 0xA4, 0x45, 0x0C, 0xDA, 0x0C, 0xEB, 0x04, 0x08,
+ 0xB8, 0xF1, 0x00, 0x0F, 0x07, 0xDD, 0x03, 0xFB, 0x03, 0x77, 0x03, 0xFB, 0x0C, 0x55, 0x1E, 0x44,
+ 0xE2, 0x44, 0x09, 0xF1, 0x01, 0x09, 0x5B, 0x1E, 0xEA, 0xD1, 0x07, 0xFB, 0x09, 0xF3, 0x06, 0xFB,
+ 0x16, 0x33, 0x02, 0x93, 0x05, 0xFB, 0x09, 0xF3, 0x06, 0xFB, 0x1A, 0x33, 0x07, 0xFB, 0x0A, 0xF7,
+ 0x01, 0x93, 0x05, 0xFB, 0x16, 0x73, 0x4F, 0xF0, 0x00, 0x0C, 0x00, 0x93, 0x67, 0x46, 0x66, 0x46,
+ 0xE2, 0x46, 0x06, 0x9B, 0x28, 0xE0, 0xDD, 0xF8, 0x08, 0x80, 0x00, 0x25, 0xB8, 0xF1, 0x00, 0x0F,
+ 0x0D, 0xD0, 0xDD, 0xE9, 0x00, 0x58, 0x08, 0xFB, 0x03, 0x58, 0x02, 0x9D, 0x98, 0xFB, 0xF5, 0xF5,
+ 0xA5, 0x42, 0x01, 0xDD, 0x25, 0x46, 0x02, 0xE0, 0xE5, 0x42, 0x00, 0xD5, 0x65, 0x42, 0x31, 0xF8,
+ 0x13, 0x80, 0x5D, 0x44, 0xA8, 0xEB, 0x05, 0x05, 0x2D, 0xB2, 0x7F, 0x1C, 0xA9, 0x46, 0xAC, 0x44,
+ 0x75, 0x45, 0x07, 0xDA, 0x05, 0xEB, 0x0E, 0x08, 0xB8, 0xF1, 0x00, 0x0F, 0x02, 0xDD, 0x4E, 0x44,
+ 0x0A, 0xF1, 0x01, 0x0A, 0x20, 0xF8, 0x13, 0x90, 0x5B, 0x1E, 0xD4, 0xD1, 0x9C, 0xFB, 0xF7, 0xF5,
+ 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0x96, 0xFB, 0xFA, 0xF3, 0x00, 0x2D,
+ 0x01, 0xDB, 0x2F, 0x46, 0x00, 0xE0, 0x6F, 0x42, 0x1E, 0x1E, 0x00, 0xDA, 0x5E, 0x42, 0xB7, 0xEB,
+ 0x46, 0x0F, 0x00, 0xDD, 0x1D, 0x46, 0x06, 0x9B, 0x05, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x13, 0x60,
+ 0x76, 0x1B, 0x20, 0xF8, 0x13, 0x60, 0x5B, 0x1E, 0xF8, 0xD1, 0x06, 0x9B, 0x01, 0xEB, 0x43, 0x01,
+ 0x00, 0xEB, 0x43, 0x00, 0x52, 0x1E, 0xBF, 0xF4, 0x63, 0xAF, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F,
+ 0x2D, 0xE9, 0xF7, 0x4F, 0x79, 0x4D, 0x7A, 0x4C, 0x7A, 0x4F, 0x28, 0x68, 0x0E, 0x46, 0x90, 0xF8,
+ 0xD0, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x3C, 0x68, 0x03, 0x20, 0x0E, 0xF0, 0x0C, 0xFE, 0x77, 0x48,
+ 0xDF, 0xF8, 0xD4, 0xB1, 0x31, 0x46, 0x02, 0x68, 0xBB, 0xF9, 0x00, 0x30, 0x20, 0x46, 0x0C, 0xF0,
+ 0xA4, 0xF9, 0x03, 0x20, 0x0E, 0xF0, 0x1A, 0xFE, 0x28, 0x68, 0xDF, 0xF8, 0xC4, 0xA1, 0x71, 0x4E,
+ 0x90, 0xF8, 0xD0, 0x02, 0xC0, 0x07, 0x06, 0xD0, 0x9A, 0xF8, 0x00, 0x30, 0x32, 0x78, 0x21, 0x46,
+ 0x67, 0x48, 0xFF, 0xF7, 0x2B, 0xFF, 0xB9, 0x46, 0x65, 0x4A, 0x33, 0x78, 0x4F, 0xF0, 0x00, 0x08,
+ 0x54, 0x46, 0x38, 0x68, 0x16, 0xE0, 0x00, 0xBF, 0xA0, 0xF8, 0x00, 0x80, 0x01, 0x21, 0x09, 0xE0,
+ 0x00, 0xEB, 0x41, 0x07, 0x32, 0xF8, 0x11, 0xC0, 0x37, 0xF8, 0x02, 0x7C, 0x67, 0x44, 0x20, 0xF8,
+ 0x11, 0x70, 0x49, 0x1C, 0x27, 0x78, 0xB9, 0x42, 0xF2, 0xDB, 0xF9, 0xB2, 0x02, 0xEB, 0x41, 0x02,
+ 0x00, 0xEB, 0x41, 0x00, 0x5B, 0x1E, 0xE7, 0xD2, 0x5B, 0x48, 0x5C, 0x4F, 0x02, 0x9B, 0x02, 0x68,
+ 0xD9, 0xF8, 0x00, 0x10, 0x38, 0x68, 0x00, 0xF0, 0x66, 0xFA, 0x28, 0x68, 0x90, 0xF8, 0xD0, 0x02,
+ 0x80, 0x07, 0x06, 0xD5, 0x23, 0x78, 0x32, 0x78, 0x39, 0x68, 0x00, 0x98, 0x00, 0xF0, 0x1C, 0xF8,
+ 0x06, 0xE0, 0xBB, 0xF9, 0x00, 0x00, 0x39, 0x68, 0x42, 0x00, 0x00, 0x98, 0x10, 0xF0, 0xA2, 0xFD,
+ 0x28, 0x68, 0x90, 0xF8, 0xD0, 0x02, 0x00, 0x07, 0x08, 0xD5, 0x00, 0x99, 0x23, 0x78, 0x32, 0x78,
+ 0x03, 0xB0, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0x03, 0xBC, 0xBD, 0xE8, 0xFE, 0x8F,
+ 0x47, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0xA7, 0xB0, 0x1C, 0x46,
+ 0x0D, 0x46, 0x06, 0x46, 0x17, 0x46, 0xEA, 0x46, 0x0D, 0xF1, 0x4C, 0x0B, 0x3C, 0xE0, 0x00, 0x22,
+ 0x60, 0x1E, 0x00, 0xF0, 0xFF, 0x09, 0x11, 0x46, 0x10, 0x46, 0x11, 0xE0, 0x35, 0xF9, 0x10, 0x30,
+ 0x1A, 0x44, 0x43, 0x1C, 0x92, 0xFB, 0xF3, 0xFC, 0x2A, 0xF8, 0x10, 0xC0, 0xA9, 0xEB, 0x00, 0x0C,
+ 0x40, 0x1C, 0x35, 0xF9, 0x1C, 0x80, 0x41, 0x44, 0x91, 0xFB, 0xF3, 0xF3, 0x2B, 0xF8, 0x1C, 0x30,
+ 0xA0, 0x42, 0xEB, 0xDB, 0x20, 0x46, 0x52, 0x46, 0x5B, 0x46, 0x0C, 0xE0, 0x32, 0xF9, 0x10, 0x10,
+ 0x33, 0xF9, 0x10, 0xC0, 0x61, 0x44, 0x35, 0xF8, 0x10, 0xC0, 0x01, 0xEB, 0xD1, 0x71, 0xAC, 0xEB,
+ 0x61, 0x01, 0x26, 0xF8, 0x10, 0x10, 0x40, 0x1E, 0xF0, 0xD2, 0x20, 0x48, 0x00, 0x68, 0x90, 0xF8,
+ 0xD0, 0x02, 0x40, 0x07, 0x04, 0xD5, 0x31, 0x46, 0x22, 0x46, 0x08, 0x46, 0x00, 0xF0, 0x08, 0xF8,
+ 0x05, 0xEB, 0x44, 0x05, 0x06, 0xEB, 0x44, 0x06, 0x7F, 0x1E, 0xC0, 0xD2, 0x27, 0xB0, 0x35, 0xE7,
+ 0xF0, 0xB5, 0x16, 0x4B, 0x00, 0x26, 0x35, 0x46, 0xD3, 0xF8, 0x00, 0xE0, 0x34, 0x46, 0x13, 0x46,
+ 0xBE, 0xF9, 0xD6, 0x72, 0xC7, 0xF1, 0x00, 0x0C, 0x06, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x13, 0x70,
+ 0x67, 0x45, 0x01, 0xDA, 0x3E, 0x44, 0x6D, 0x1C, 0x5B, 0x1E, 0xF7, 0xD2, 0x00, 0x2D, 0x01, 0xDD,
+ 0x96, 0xFB, 0xF5, 0xF4, 0xBE, 0xF8, 0xD8, 0x32, 0x5E, 0x42, 0xA6, 0x42, 0x00, 0xDD, 0x1C, 0x44,
+ 0x53, 0x1B, 0x63, 0x43, 0x93, 0xFB, 0xF2, 0xF3, 0x05, 0xE0, 0x00, 0xBF, 0x31, 0xF8, 0x12, 0x40,
+ 0xE4, 0x1A, 0x20, 0xF8, 0x12, 0x40, 0x52, 0x1E, 0xF8, 0xD2, 0xF0, 0xBD, 0x20, 0x07, 0x10, 0x00,
+ 0x3C, 0x0C, 0x01, 0x20, 0x2C, 0x05, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00,
+ 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, 0xE4, 0x06, 0x10, 0x00,
+ 0xBF, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x1E, 0x46, 0x15, 0x46, 0x88, 0x46, 0x83, 0x46,
+ 0x00, 0x24, 0x4F, 0xF0, 0xAA, 0x09, 0x0A, 0x9F, 0x4F, 0xE0, 0x30, 0x5D, 0x08, 0xB9, 0x28, 0x5D,
+ 0xF0, 0xB3, 0x06, 0xF8, 0x04, 0x90, 0x38, 0xF9, 0x14, 0x00, 0x00, 0xF0, 0xCE, 0xF8, 0x28, 0xF8,
+ 0x14, 0x00, 0x28, 0x5D, 0xA0, 0xB3, 0x05, 0xEB, 0x04, 0x0A, 0x1A, 0xF8, 0x01, 0x1C, 0x81, 0x42,
+ 0x1C, 0xD0, 0xAA, 0x28, 0x1A, 0xD0, 0x0A, 0xF8, 0x01, 0x9C, 0x0B, 0xEB, 0x44, 0x01, 0x00, 0x91,
+ 0x31, 0xF9, 0x02, 0x0C, 0x00, 0xF0, 0xB9, 0xF8, 0x00, 0x99, 0x21, 0xF8, 0x02, 0x0C, 0x31, 0x19,
+ 0x01, 0xF8, 0x01, 0x9C, 0x08, 0xEB, 0x44, 0x01, 0x00, 0x91, 0x31, 0xF9, 0x02, 0x0C, 0x00, 0xF0,
+ 0xAC, 0xF8, 0x00, 0x99, 0x21, 0xF8, 0x02, 0x0C, 0x28, 0x5D, 0x88, 0xB1, 0x9A, 0xF8, 0x01, 0x10,
+ 0x28, 0x5D, 0x81, 0x42, 0x18, 0xD0, 0xAA, 0x28, 0x16, 0xD0, 0x8A, 0xF8, 0x01, 0x90, 0x0B, 0xEB,
+ 0x44, 0x0A, 0xBA, 0xF9, 0x02, 0x00, 0x00, 0xF0, 0x98, 0xF8, 0xAA, 0xF8, 0x02, 0x00, 0x00, 0xE0,
+ 0x0A, 0xE0, 0x31, 0x19, 0x08, 0xEB, 0x44, 0x0A, 0x81, 0xF8, 0x01, 0x90, 0xBA, 0xF9, 0x02, 0x00,
+ 0x00, 0xF0, 0x8B, 0xF8, 0xAA, 0xF8, 0x02, 0x00, 0x64, 0x1C, 0xBC, 0x42, 0xAD, 0xD3, 0xBD, 0xE8,
+ 0xF8, 0x8F, 0x4A, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x48, 0x49, 0x08, 0x60, 0x70, 0x47,
+ 0x2D, 0xE9, 0xF7, 0x4F, 0x46, 0x48, 0x8A, 0xB0, 0x90, 0x46, 0x00, 0x78, 0x0C, 0x46, 0x00, 0x28,
+ 0x70, 0xD0, 0x44, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x00, 0x04, 0x80, 0x07, 0x6A, 0xD5, 0x42, 0x48,
+ 0x04, 0x90, 0x42, 0x48, 0xDF, 0xF8, 0xF4, 0xA0, 0x01, 0x25, 0x07, 0x78, 0x4F, 0xF0, 0x00, 0x0B,
+ 0xDA, 0xF8, 0x00, 0x90, 0x20, 0xE0, 0x01, 0x20, 0xA8, 0x40, 0x10, 0xEA, 0x09, 0x0F, 0x1A, 0xD1,
+ 0x3B, 0x48, 0x00, 0xEB, 0x85, 0x06, 0x04, 0x98, 0xB1, 0x78, 0x10, 0xF0, 0x09, 0xFE, 0xB2, 0x78,
+ 0x5B, 0x46, 0x0D, 0xE0, 0x31, 0x78, 0x05, 0xE0, 0x10, 0xF8, 0x01, 0xC0, 0xAC, 0x45, 0x00, 0xD1,
+ 0x43, 0x54, 0x49, 0x1C, 0x96, 0xF8, 0x01, 0xC0, 0x8C, 0x45, 0xF5, 0xDA, 0x28, 0x30, 0x52, 0x1C,
+ 0xF1, 0x78, 0x91, 0x42, 0xEE, 0xDA, 0x6D, 0x1C, 0xBD, 0x42, 0xDC, 0xD9, 0x00, 0x21, 0x0A, 0x98,
+ 0x10, 0xF0, 0xF4, 0xFD, 0x01, 0x90, 0x01, 0x21, 0x0A, 0x98, 0x10, 0xF0, 0xEF, 0xFD, 0x08, 0x90,
+ 0x00, 0x21, 0x25, 0x48, 0x10, 0xF0, 0xE4, 0xFD, 0x81, 0x46, 0x01, 0x21, 0x22, 0x48, 0x10, 0xF0,
+ 0xDF, 0xFD, 0x06, 0x46, 0x65, 0x1E, 0xE9, 0xB2, 0x0A, 0x98, 0x10, 0xF0, 0xDF, 0xFD, 0xA4, 0x1E,
+ 0x06, 0x90, 0xE1, 0xB2, 0x0A, 0x98, 0x10, 0xF0, 0xD9, 0xFD, 0x07, 0x46, 0xE9, 0xB2, 0x1A, 0x48,
+ 0x10, 0xF0, 0xCE, 0xFD, 0x05, 0x46, 0xE1, 0xB2, 0x17, 0x48, 0x10, 0xF0, 0xC9, 0xFD, 0x04, 0x46,
+ 0x33, 0x46, 0x4A, 0x46, 0xCD, 0xF8, 0x00, 0x80, 0x08, 0x99, 0x01, 0x98, 0xFF, 0xF7, 0x2A, 0xFF,
+ 0x23, 0x46, 0x2A, 0x46, 0x39, 0x46, 0xCD, 0xF8, 0x00, 0x80, 0x06, 0x98, 0xFF, 0xF7, 0x22, 0xFF,
+ 0xCA, 0xF8, 0x00, 0xB0, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0A, 0x49, 0x09, 0x68, 0x91, 0xF8,
+ 0x08, 0x24, 0x42, 0x43, 0x64, 0x20, 0x92, 0xFB, 0xF0, 0xF0, 0xB1, 0xF8, 0x06, 0x24, 0x00, 0xB2,
+ 0x82, 0x42, 0x01, 0xDA, 0xB1, 0xF9, 0x06, 0x04, 0x70, 0x47, 0x00, 0x00, 0x24, 0x05, 0x10, 0x00,
+ 0x80, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xB4, 0x18, 0x01, 0x20, 0x15, 0x06, 0x10, 0x00,
+ 0x4C, 0x1C, 0x01, 0x20, 0x2D, 0xE9, 0xF0, 0x4F, 0xFE, 0x4C, 0x80, 0x25, 0xFE, 0x4E, 0x23, 0x68,
+ 0x93, 0xF8, 0x31, 0x10, 0x93, 0xF8, 0x30, 0x00, 0x01, 0xFB, 0x00, 0xF2, 0x02, 0xE0, 0x00, 0xBF,
+ 0x26, 0xF8, 0x12, 0x50, 0x52, 0x1E, 0xFB, 0xD2, 0x93, 0xF8, 0xAA, 0x22, 0xA6, 0x46, 0x12, 0x07,
+ 0x4F, 0xF0, 0x64, 0x08, 0x31, 0xD5, 0x4A, 0x1E, 0x02, 0xFB, 0x00, 0xFA, 0xDF, 0xF8, 0xC8, 0xB3,
+ 0x03, 0xF5, 0x94, 0x69, 0x02, 0x46, 0x26, 0xE0, 0x19, 0xF8, 0x02, 0x30, 0x0A, 0xEB, 0x02, 0x04,
+ 0xDB, 0x01, 0xB3, 0xFB, 0xF8, 0xF3, 0x0B, 0xEB, 0x44, 0x05, 0x0C, 0x46, 0x19, 0xE0, 0x80, 0x2B,
+ 0x05, 0xDD, 0xC3, 0xF1, 0x80, 0x06, 0x66, 0x43, 0x96, 0xFB, 0xF1, 0xF6, 0x06, 0xE0, 0xA3, 0xF1,
+ 0x80, 0x06, 0x06, 0xFB, 0x04, 0xF7, 0x97, 0xFB, 0xF1, 0xF7, 0xF6, 0x1B, 0xB5, 0xF9, 0x00, 0x70,
+ 0x80, 0x36, 0x77, 0x43, 0xFE, 0x17, 0x07, 0xEB, 0x56, 0x66, 0xF6, 0x11, 0x2E, 0x80, 0xA5, 0xEB,
+ 0x40, 0x05, 0x64, 0x1E, 0xE3, 0xD2, 0x52, 0x1E, 0xD6, 0xD2, 0xDE, 0xF8, 0x00, 0x20, 0xF2, 0x46,
+ 0x92, 0xF8, 0xAA, 0x32, 0xDB, 0x06, 0x2F, 0xD5, 0x02, 0xF5, 0x98, 0x69, 0xD6, 0x4B, 0x4A, 0x1E,
+ 0x42, 0x43, 0x03, 0xEB, 0x42, 0x05, 0x0A, 0x46, 0x24, 0xE0, 0x00, 0xBF, 0x19, 0xF8, 0x02, 0x30,
+ 0xDB, 0x01, 0xB3, 0xFB, 0xF8, 0xF6, 0x03, 0x46, 0x18, 0xE0, 0x80, 0x2E, 0x05, 0xDD, 0xC6, 0xF1,
+ 0x80, 0x04, 0x5C, 0x43, 0x94, 0xFB, 0xF0, 0xF4, 0x06, 0xE0, 0xA6, 0xF1, 0x80, 0x04, 0x04, 0xFB,
+ 0x03, 0xF7, 0x97, 0xFB, 0xF0, 0xF7, 0xE4, 0x1B, 0x35, 0xF9, 0x13, 0x70, 0x80, 0x34, 0x67, 0x43,
+ 0xFC, 0x17, 0x07, 0xEB, 0x54, 0x64, 0xE4, 0x11, 0x25, 0xF8, 0x13, 0x40, 0x5B, 0x1E, 0xE4, 0xD2,
+ 0xA5, 0xEB, 0x40, 0x05, 0x52, 0x1E, 0xD9, 0xD2, 0xDA, 0xF8, 0x00, 0x40, 0x94, 0xF8, 0xAB, 0x22,
+ 0xD2, 0x07, 0x20, 0xD0, 0xBC, 0x4E, 0x00, 0x23, 0x04, 0xF5, 0x9C, 0x64, 0x19, 0xE0, 0x00, 0xBF,
+ 0x03, 0xFB, 0x00, 0xF2, 0x06, 0xEB, 0x42, 0x07, 0x00, 0x22, 0x0F, 0xE0, 0xA5, 0x5C, 0xED, 0x01,
+ 0xB5, 0xFB, 0xF8, 0xFC, 0x37, 0xF9, 0x12, 0x50, 0x05, 0xFB, 0x0C, 0xF5, 0x4F, 0xEA, 0xE5, 0x7C,
+ 0x05, 0xEB, 0x5C, 0x65, 0xED, 0x11, 0x27, 0xF8, 0x12, 0x50, 0x52, 0x1C, 0x82, 0x42, 0xED, 0xD3,
+ 0x5B, 0x1C, 0x8B, 0x42, 0xE4, 0xD3, 0xBD, 0xE8, 0xF0, 0x8F, 0x08, 0xB5, 0x00, 0x93, 0x80, 0x23,
+ 0x0B, 0xF0, 0x10, 0xFF, 0x08, 0xBD, 0x08, 0xB5, 0x00, 0x93, 0x13, 0x46, 0xA7, 0x4A, 0xB2, 0xF9,
+ 0x00, 0x20, 0x0B, 0xF0, 0x17, 0xFF, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x5F, 0x00, 0xF0, 0x36, 0xFD,
+ 0xA0, 0x4F, 0xDF, 0xF8, 0x8C, 0xA2, 0x38, 0x68, 0x9A, 0xF8, 0x01, 0x40, 0xB0, 0xF9, 0x00, 0x13,
+ 0xB0, 0xF9, 0x22, 0x33, 0xB0, 0xF9, 0x42, 0x23, 0x01, 0x2C, 0x50, 0xD0, 0x02, 0x2C, 0x04, 0xD3,
+ 0xB0, 0xF8, 0x04, 0x43, 0x0C, 0xB1, 0xB0, 0xF9, 0x04, 0x13, 0x9A, 0x4C, 0xA5, 0x79, 0x9D, 0xB1,
+ 0x90, 0xF8, 0x69, 0x53, 0x64, 0x26, 0x05, 0xFB, 0x01, 0xFC, 0x9C, 0xFB, 0xF6, 0xFC, 0x61, 0x44,
+ 0x05, 0xFB, 0x03, 0xFC, 0x55, 0x43, 0x9C, 0xFB, 0xF6, 0xFC, 0x95, 0xFB, 0xF6, 0xF5, 0x63, 0x44,
+ 0x2A, 0x44, 0x09, 0xB2, 0x1B, 0xB2, 0x12, 0xB2, 0x8F, 0x4E, 0x90, 0x4D, 0xDF, 0xF8, 0x40, 0xC2,
+ 0x31, 0x80, 0x2B, 0x80, 0xAC, 0xF8, 0x00, 0x20, 0x90, 0xF8, 0x02, 0x73, 0xC9, 0x1B, 0x8D, 0x4F,
+ 0x39, 0x80, 0x90, 0xF8, 0x24, 0x13, 0x5B, 0x1A, 0x8B, 0x49, 0x0B, 0x80, 0x90, 0xF8, 0x44, 0x33,
+ 0xD3, 0x1A, 0x8A, 0x4A, 0x13, 0x80, 0x23, 0x78, 0x53, 0xB1, 0x89, 0x4B, 0x1B, 0x78, 0x3B, 0xB1,
+ 0xB0, 0xF8, 0x6C, 0x32, 0x33, 0x80, 0x90, 0xF8, 0x6E, 0x82, 0xA3, 0xEB, 0x08, 0x03, 0x3B, 0x80,
+ 0xDF, 0xF8, 0x10, 0xB2, 0x9B, 0xF8, 0x00, 0x30, 0x33, 0xB1, 0xB0, 0xF8, 0x6C, 0x32, 0x33, 0x80,
+ 0x90, 0xF8, 0x6E, 0x02, 0x18, 0x1A, 0x38, 0x80, 0xA0, 0x78, 0x68, 0xB1, 0x10, 0xE0, 0x90, 0xF8,
+ 0x03, 0x43, 0x21, 0x44, 0x90, 0xF8, 0x25, 0x43, 0x09, 0xB2, 0x23, 0x44, 0x90, 0xF8, 0x45, 0x43,
+ 0x1B, 0xB2, 0x22, 0x44, 0x12, 0xB2, 0xA8, 0xE7, 0x30, 0x88, 0x28, 0x80, 0x38, 0x88, 0x08, 0x80,
+ 0xE0, 0x78, 0xA1, 0x46, 0x20, 0xB9, 0x30, 0x88, 0xAC, 0xF8, 0x00, 0x00, 0x38, 0x88, 0x10, 0x80,
+ 0xB2, 0xF9, 0x00, 0x20, 0xB1, 0xF9, 0x00, 0x10, 0xB7, 0xF9, 0x00, 0x00, 0x0A, 0xF0, 0xE4, 0xFF,
+ 0x6D, 0x4D, 0x00, 0xB2, 0x6D, 0x4A, 0x28, 0x80, 0x31, 0x88, 0x6D, 0x4B, 0x11, 0x80, 0x5D, 0x4C,
+ 0x39, 0x88, 0x19, 0x80, 0x21, 0x68, 0x91, 0xF8, 0x00, 0xC4, 0x5F, 0xEA, 0xCC, 0x7C, 0x14, 0xD0,
+ 0x9A, 0xF8, 0x01, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x91, 0xF8, 0x05, 0xC4, 0xB1, 0xF8,
+ 0x02, 0x84, 0xC4, 0x44, 0xA2, 0xF8, 0x00, 0xC0, 0x91, 0xF8, 0x04, 0x14, 0xAC, 0xEB, 0x01, 0x01,
+ 0x09, 0xB2, 0x19, 0x80, 0x0A, 0xF0, 0xCE, 0xFF, 0x28, 0x80, 0xB2, 0x46, 0x30, 0x88, 0x5D, 0x4E,
+ 0x5D, 0x49, 0x5E, 0x4A, 0x30, 0x80, 0x08, 0x80, 0x38, 0x88, 0x10, 0x80, 0x99, 0xF8, 0x04, 0x00,
+ 0xC8, 0x46, 0x00, 0xB3, 0x20, 0x68, 0xB0, 0xF8, 0x44, 0x34, 0x2B, 0xB1, 0x98, 0xF8, 0x06, 0x30,
+ 0x13, 0xB1, 0xB0, 0xF8, 0x44, 0x34, 0x04, 0xE0, 0xB0, 0xF8, 0x42, 0x34, 0x13, 0xB1, 0xB0, 0xF8,
+ 0x42, 0x34, 0x33, 0x80, 0xB0, 0xF8, 0x46, 0x34, 0x33, 0xB1, 0xB0, 0xF8, 0x46, 0x34, 0x0B, 0x80,
+ 0x90, 0xF8, 0x48, 0x04, 0x18, 0x1A, 0x10, 0x80, 0xB2, 0xF9, 0x00, 0x10, 0xB5, 0xF9, 0x00, 0x00,
+ 0x0A, 0xF0, 0xA0, 0xFF, 0x28, 0x80, 0x4A, 0x4F, 0xBA, 0xF8, 0x00, 0x00, 0x38, 0x80, 0x98, 0xF8,
+ 0x05, 0x00, 0x30, 0xB1, 0x20, 0x68, 0xB0, 0xF8, 0x21, 0x14, 0x11, 0xB1, 0xB0, 0xF8, 0x21, 0x04,
+ 0x38, 0x80, 0x3B, 0x48, 0x43, 0x4D, 0x00, 0x78, 0x18, 0xB1, 0x20, 0x68, 0xB0, 0xF8, 0xBE, 0x02,
+ 0x19, 0xE0, 0x9B, 0xF8, 0x00, 0x00, 0x00, 0x28, 0xF7, 0xD1, 0x20, 0x68, 0xB0, 0xF9, 0xBC, 0x02,
+ 0x28, 0x80, 0x98, 0xF8, 0x04, 0x10, 0x21, 0xB1, 0xB6, 0xF9, 0x00, 0x10, 0x0A, 0xF0, 0x7A, 0xFF,
+ 0x28, 0x80, 0x98, 0xF8, 0x05, 0x00, 0x00, 0x28, 0x06, 0xD0, 0xB7, 0xF9, 0x00, 0x10, 0xB5, 0xF9,
+ 0x00, 0x00, 0x0A, 0xF0, 0x6F, 0xFF, 0x28, 0x80, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFF, 0x4F,
+ 0x8A, 0x46, 0x81, 0x46, 0x30, 0x49, 0x0D, 0x98, 0x93, 0x46, 0x4A, 0x0C, 0x04, 0x46, 0x07, 0xE0,
+ 0x3A, 0xF9, 0x14, 0x30, 0x93, 0x42, 0x00, 0xDA, 0x1A, 0x46, 0x8B, 0x42, 0x00, 0xDD, 0x19, 0x46,
+ 0x64, 0x1E, 0xF5, 0xD2, 0x00, 0x25, 0x00, 0x29, 0x01, 0xDA, 0x0D, 0x46, 0x02, 0xE0, 0x00, 0x2A,
+ 0x00, 0xDD, 0x15, 0x46, 0x00, 0x23, 0x1C, 0x46, 0x1E, 0x46, 0x19, 0x46, 0x1F, 0x46, 0x02, 0x46,
+ 0x12, 0xE0, 0x00, 0xBF, 0x3A, 0xF9, 0x12, 0xC0, 0xAC, 0xEB, 0x05, 0x0C, 0xDC, 0x45, 0x0B, 0xDA,
+ 0x0C, 0xEB, 0x0B, 0x08, 0xB8, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x02, 0xFB, 0x02, 0x44, 0x02, 0xFB,
+ 0x0C, 0x11, 0x13, 0x44, 0x66, 0x44, 0x7F, 0x1C, 0x52, 0x1E, 0xEB, 0xD2, 0x04, 0xFB, 0x07, 0xF2,
+ 0x2C, 0xE0, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0x78, 0x12, 0x01, 0x20, 0xCA, 0x06, 0x10, 0x00,
+ 0x4C, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00, 0x6A, 0x06, 0x10, 0x00,
+ 0x6C, 0x06, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, 0x70, 0x06, 0x10, 0x00, 0x72, 0x06, 0x10, 0x00,
+ 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0x74, 0x06, 0x10, 0x00, 0x7C, 0x06, 0x10, 0x00,
+ 0x7E, 0x06, 0x10, 0x00, 0x84, 0x06, 0x10, 0x00, 0x86, 0x06, 0x10, 0x00, 0x88, 0x06, 0x10, 0x00,
+ 0x82, 0x06, 0x10, 0x00, 0x76, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x03, 0xFB, 0x13, 0x2E,
+ 0x01, 0xFB, 0x07, 0xF2, 0x03, 0xFB, 0x16, 0x27, 0x74, 0x43, 0x01, 0xFB, 0x13, 0x46, 0x00, 0x24,
+ 0x21, 0x46, 0x02, 0x46, 0x25, 0xE0, 0x00, 0x23, 0xBE, 0xF1, 0x00, 0x0F, 0x0F, 0xD0, 0x07, 0xFB,
+ 0x02, 0x6C, 0x9C, 0xFB, 0xFE, 0xF3, 0xDC, 0x46, 0x5B, 0x45, 0x01, 0xDD, 0x63, 0x46, 0x06, 0xE0,
+ 0xDD, 0xF8, 0x0C, 0xC0, 0x13, 0xEB, 0x0C, 0x0F, 0x01, 0xD5, 0x03, 0x9B, 0x5B, 0x42, 0x3A, 0xF8,
+ 0x12, 0xC0, 0x2B, 0x44, 0xAC, 0xEB, 0x03, 0x03, 0xDD, 0xF8, 0x0C, 0xC0, 0x1B, 0xB2, 0x63, 0x45,
+ 0x05, 0xDA, 0x9C, 0x44, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xDD, 0x1C, 0x44, 0x49, 0x1C, 0x29, 0xF8,
+ 0x12, 0x30, 0x52, 0x1E, 0xD7, 0xD2, 0x01, 0xB9, 0x01, 0x21, 0x94, 0xFB, 0xF1, 0xF1, 0x04, 0xE0,
+ 0x39, 0xF8, 0x10, 0x20, 0x52, 0x1A, 0x29, 0xF8, 0x10, 0x20, 0x40, 0x1E, 0xF8, 0xD2, 0xBD, 0xE8,
+ 0xFF, 0x8F, 0x2D, 0xE9, 0xF8, 0x43, 0x1F, 0x46, 0xFE, 0x4B, 0x0E, 0x46, 0x05, 0x46, 0x1B, 0x68,
+ 0x14, 0x46, 0xB3, 0xF9, 0xDA, 0x92, 0xB3, 0xF9, 0xDC, 0x82, 0x0A, 0xE0, 0x43, 0x46, 0x4A, 0x46,
+ 0x31, 0x46, 0x28, 0x46, 0x00, 0x97, 0xFF, 0xF7, 0x41, 0xFF, 0x06, 0xEB, 0x47, 0x06, 0x05, 0xEB,
+ 0x47, 0x05, 0x64, 0x1E, 0xF2, 0xD2, 0xBD, 0xE8, 0xF8, 0x83, 0x2D, 0xE9, 0xFF, 0x5F, 0xF2, 0x4C,
+ 0x88, 0x46, 0x00, 0x26, 0x07, 0x46, 0x92, 0x46, 0x35, 0x46, 0x4F, 0xF4, 0x66, 0x71, 0x40, 0x46,
+ 0x26, 0x60, 0x10, 0xF0, 0xE6, 0xF9, 0x00, 0x21, 0x40, 0x46, 0x10, 0xF0, 0xF9, 0xFA, 0x81, 0x46,
+ 0x00, 0x21, 0x38, 0x46, 0x10, 0xF0, 0xEC, 0xFA, 0x00, 0x22, 0xE8, 0x4B, 0xE8, 0x4F, 0x29, 0xE0,
+ 0x00, 0x21, 0x4F, 0xF0, 0x01, 0x0E, 0xDF, 0xF8, 0x8C, 0xB3, 0x18, 0xE0, 0x30, 0xF9, 0x11, 0x80,
+ 0xD0, 0x45, 0x05, 0xDD, 0x09, 0xF8, 0x01, 0xE0, 0x30, 0xF9, 0x11, 0xC0, 0x76, 0x1C, 0x65, 0x44,
+ 0xDB, 0xF8, 0x00, 0xC0, 0x30, 0xF9, 0x11, 0x80, 0xBC, 0xF8, 0x55, 0xC3, 0xE0, 0x45, 0x05, 0xDD,
+ 0xD4, 0xF8, 0x00, 0xC0, 0x0C, 0xF1, 0x01, 0x0C, 0xC4, 0xF8, 0x00, 0xC0, 0x49, 0x1C, 0x93, 0xF8,
+ 0x00, 0xC0, 0x61, 0x45, 0xE2, 0xDB, 0x0C, 0xF0, 0xFF, 0x01, 0x09, 0xF1, 0x28, 0x09, 0x00, 0xEB,
+ 0x41, 0x00, 0x52, 0x1C, 0x39, 0x78, 0x8A, 0x42, 0xD2, 0xDB, 0x03, 0x98, 0x05, 0x60, 0x30, 0x46,
+ 0x04, 0xB0, 0xE9, 0xE6, 0x06, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x12, 0x30, 0x8B, 0x42, 0x01, 0xDD,
+ 0x01, 0x20, 0x70, 0x47, 0x52, 0x1E, 0xF7, 0xD2, 0x00, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xFC, 0x47,
+ 0x04, 0x46, 0xC8, 0x48, 0xC8, 0x4F, 0x13, 0x46, 0x02, 0x68, 0x38, 0x68, 0xFF, 0xF7, 0xC3, 0xFD,
+ 0x03, 0x20, 0x0E, 0xF0, 0x20, 0xF9, 0xDF, 0xF8, 0xFC, 0x92, 0xDF, 0xF8, 0x10, 0x83, 0xBF, 0x4D,
+ 0xD9, 0xF8, 0x00, 0x00, 0xBE, 0x4E, 0x90, 0xF8, 0xAA, 0x02, 0x80, 0x07, 0x15, 0xD5, 0xC0, 0x48,
+ 0xB0, 0xF9, 0x00, 0x20, 0xBF, 0x48, 0xB0, 0xF9, 0x00, 0x10, 0xBF, 0x48, 0xB0, 0xF9, 0x00, 0x00,
+ 0x0A, 0xF0, 0x1A, 0xFE, 0x03, 0xB2, 0x29, 0x78, 0x30, 0x78, 0xCD, 0xE9, 0x00, 0x01, 0x39, 0x68,
+ 0xD8, 0xF8, 0x00, 0x20, 0x08, 0x46, 0x00, 0xF0, 0xF6, 0xFA, 0xB8, 0x48, 0xD8, 0xF8, 0x00, 0x20,
+ 0x39, 0x68, 0xB0, 0xF9, 0x00, 0x30, 0x20, 0x46, 0x0B, 0xF0, 0x97, 0xFC, 0x03, 0x20, 0x0E, 0xF0,
+ 0x0D, 0xF9, 0xD9, 0xF8, 0x00, 0x00, 0x4F, 0x46, 0x90, 0xF8, 0xAA, 0x02, 0x00, 0x06, 0x05, 0xD5,
+ 0x21, 0x46, 0x2B, 0x78, 0x32, 0x78, 0x08, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0x38, 0x68, 0x90, 0xF8,
+ 0xAA, 0x02, 0x40, 0x07, 0x25, 0xD5, 0x30, 0x78, 0x2E, 0x78, 0x32, 0x46, 0x1F, 0xE0, 0x00, 0x21,
+ 0x03, 0x46, 0x0C, 0xE0, 0x03, 0xFB, 0x06, 0x27, 0x34, 0xF9, 0x17, 0x50, 0x00, 0x2D, 0x04, 0xDD,
+ 0x09, 0xB1, 0x8D, 0x42, 0x03, 0xDA, 0x29, 0x46, 0x01, 0xE0, 0x00, 0x21, 0x43, 0x1C, 0x5B, 0x1E,
+ 0xF0, 0xD2, 0x00, 0x29, 0x0B, 0xDD, 0x03, 0x46, 0x07, 0xE0, 0x00, 0xBF, 0x03, 0xFB, 0x06, 0x25,
+ 0x34, 0xF8, 0x15, 0x70, 0x7F, 0x1A, 0x24, 0xF8, 0x15, 0x70, 0x5B, 0x1E, 0xF6, 0xD2, 0x52, 0x1E,
+ 0xDD, 0xD2, 0xBD, 0xE8, 0xFC, 0x87, 0x2D, 0xE9, 0xF0, 0x43, 0x91, 0x46, 0x1C, 0x46, 0x36, 0xE0,
+ 0x93, 0x4D, 0x4F, 0xF0, 0x01, 0x0C, 0x6A, 0x0C, 0xE0, 0x46, 0x4F, 0x46, 0x12, 0xE0, 0x00, 0xBF,
+ 0x07, 0xFB, 0x03, 0x46, 0x31, 0xF9, 0x16, 0x60, 0x96, 0x42, 0x00, 0xDA, 0x32, 0x46, 0xAE, 0x42,
+ 0x00, 0xDD, 0x35, 0x46, 0x00, 0x2E, 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x08, 0x02, 0xE0, 0x01, 0xDA,
+ 0x4F, 0xF0, 0x00, 0x0C, 0x7F, 0x1E, 0xEB, 0xD2, 0xBC, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0xB8, 0xF1,
+ 0x00, 0x0F, 0x14, 0xD1, 0x5C, 0xEA, 0x08, 0x06, 0x11, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, 0x03, 0xD1,
+ 0xB8, 0xF1, 0x00, 0x0F, 0x00, 0xD0, 0x2A, 0x46, 0x4E, 0x46, 0x06, 0xE0, 0x06, 0xFB, 0x03, 0x45,
+ 0x31, 0xF8, 0x15, 0x70, 0xBF, 0x1A, 0x20, 0xF8, 0x15, 0x70, 0x76, 0x1E, 0xF6, 0xD2, 0x64, 0x1E,
+ 0xC6, 0xD2, 0xBD, 0xE8, 0xF0, 0x83, 0x2D, 0xE9, 0xF3, 0x4F, 0x76, 0x49, 0x89, 0xB0, 0x09, 0x78,
+ 0x00, 0x29, 0x75, 0xD1, 0xCD, 0xE9, 0x00, 0x10, 0x68, 0x48, 0x07, 0x91, 0x8A, 0x46, 0x90, 0xF8,
+ 0x00, 0x90, 0x67, 0x48, 0x88, 0x46, 0x00, 0x78, 0x08, 0x90, 0x57, 0xE0, 0xDF, 0xF8, 0xB0, 0xB1,
+ 0x00, 0x20, 0xCD, 0xE9, 0x05, 0x0B, 0x05, 0x46, 0x04, 0x90, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x10, 0xF0, 0x11, 0xF8, 0x0A, 0x9A, 0xD2, 0xE9, 0x00, 0x32, 0x03, 0x40, 0x0A, 0x40, 0xCD, 0xE9,
+ 0x02, 0x23, 0x22, 0xE0, 0x01, 0x98, 0x30, 0xF9, 0x15, 0x40, 0x5C, 0x45, 0x00, 0xDD, 0xA3, 0x46,
+ 0x05, 0x98, 0x84, 0x42, 0x00, 0xDA, 0x05, 0x94, 0xDD, 0xE9, 0x02, 0x10, 0x08, 0x43, 0x13, 0xD1,
+ 0x0A, 0x98, 0x2A, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x02, 0x67, 0x01, 0x20, 0x0F, 0xF0, 0xF3, 0xFF,
+ 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x07, 0xD1, 0x06, 0x98, 0x84, 0x42, 0x00, 0xDD, 0x06, 0x94,
+ 0x04, 0x98, 0x84, 0x42, 0x00, 0xDA, 0x04, 0x94, 0x6D, 0x1C, 0x4D, 0x45, 0xDA, 0xDB, 0x05, 0x98,
+ 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0xAB, 0xEB, 0x00, 0x00, 0x01, 0xB2, 0x04, 0x98, 0x00, 0x28,
+ 0x00, 0xDA, 0x40, 0x42, 0x06, 0x9A, 0x10, 0x1A, 0x02, 0xB2, 0x51, 0x45, 0x00, 0xDD, 0x8A, 0x46,
+ 0xDD, 0xE9, 0x02, 0x10, 0x08, 0x43, 0x03, 0xD1, 0x00, 0x98, 0x82, 0x42, 0x00, 0xDA, 0x00, 0x92,
+ 0x01, 0x99, 0x08, 0xF1, 0x01, 0x08, 0x01, 0xEB, 0x49, 0x00, 0x01, 0x90, 0x08, 0x99, 0x88, 0x45,
+ 0xA4, 0xDB, 0x34, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0xC0, 0x22, 0xB0, 0xF9, 0xC2, 0x12, 0x92, 0x45,
+ 0x07, 0xDD, 0x00, 0x9A, 0x49, 0x42, 0x8A, 0x42, 0x03, 0xDA, 0x01, 0x21, 0x07, 0x91, 0x03, 0xE0,
+ 0x18, 0xE0, 0x38, 0x49, 0x00, 0x22, 0x4A, 0x70, 0x90, 0xF8, 0xC4, 0x12, 0x35, 0x48, 0x07, 0x9A,
+ 0x40, 0x1C, 0x0A, 0xF0, 0x98, 0xFD, 0x33, 0x49, 0x08, 0x70, 0x28, 0xB1, 0xFF, 0xF7, 0x94, 0xFC,
+ 0x01, 0x21, 0x08, 0x20, 0x0A, 0xF0, 0x4E, 0xF8, 0x2F, 0x48, 0xA0, 0xF8, 0x40, 0xA0, 0x00, 0x99,
+ 0xA0, 0xF8, 0x42, 0x10, 0x2B, 0x48, 0x02, 0x78, 0x2B, 0x48, 0x01, 0x7C, 0x62, 0xF3, 0xC7, 0x11,
+ 0x01, 0x74, 0x0B, 0xB0, 0x6F, 0xE4, 0x2D, 0xE9, 0xF7, 0x4F, 0x93, 0x46, 0x27, 0x4A, 0x4F, 0xF0,
+ 0x00, 0x09, 0x06, 0x46, 0x15, 0x78, 0x82, 0xF8, 0x00, 0x90, 0xFF, 0xF7, 0x75, 0xFC, 0x21, 0x48,
+ 0x02, 0x21, 0x00, 0x1D, 0x08, 0xF0, 0x3E, 0xF8, 0x21, 0x48, 0x1E, 0x4C, 0x2A, 0x46, 0x00, 0x78,
+ 0x31, 0x46, 0x01, 0x28, 0x60, 0x68, 0x5B, 0xD0, 0xFF, 0xF7, 0x90, 0xFE, 0x0D, 0x4D, 0xDF, 0xF8,
+ 0x3C, 0x80, 0x0F, 0x4E, 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x80, 0x07, 0x06, 0xD5, 0x61, 0x68,
+ 0x98, 0xF8, 0x00, 0x30, 0x32, 0x78, 0x08, 0x46, 0xFF, 0xF7, 0xF5, 0xFE, 0x29, 0x68, 0x0F, 0x4F,
+ 0x91, 0xF8, 0xAA, 0x02, 0x02, 0x07, 0x26, 0xD4, 0xC0, 0x06, 0x24, 0xD4, 0x91, 0xF8, 0xAB, 0x02,
+ 0xC0, 0x07, 0x1F, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x5C, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00,
+ 0xB9, 0x06, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, 0xE4, 0x06, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00,
+ 0x6C, 0x06, 0x10, 0x00, 0x6A, 0x06, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00,
+ 0x00, 0x80, 0xFF, 0xFF, 0x28, 0x05, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x50, 0x07, 0x10, 0x00,
+ 0xBF, 0x06, 0x10, 0x00, 0x06, 0xD0, 0x61, 0x68, 0xB7, 0xF9, 0x00, 0x30, 0xF8, 0x4A, 0x08, 0x46,
+ 0xFF, 0xF7, 0x13, 0xFC, 0xB7, 0xF9, 0x00, 0x00, 0x61, 0x68, 0x42, 0x00, 0xF5, 0x48, 0x00, 0x68,
+ 0x0F, 0xF0, 0x60, 0xFF, 0x98, 0xF8, 0x00, 0x20, 0x31, 0x78, 0x60, 0x68, 0xFF, 0xF7, 0xC0, 0xFA,
+ 0xDF, 0xF8, 0xC4, 0x83, 0xDF, 0xF8, 0xC4, 0xA3, 0x98, 0xF8, 0x00, 0x00, 0x30, 0xB9, 0x02, 0xE0,
+ 0xFF, 0xF7, 0x46, 0xF9, 0xA2, 0xE7, 0x98, 0xF8, 0x01, 0x00, 0x28, 0xB1, 0x59, 0x46, 0x62, 0x68,
+ 0x01, 0x98, 0xFE, 0xF7, 0x95, 0xFD, 0x01, 0xE0, 0x8A, 0xF8, 0x00, 0x90, 0xE8, 0x48, 0xE9, 0x4E,
+ 0x40, 0x78, 0x02, 0x28, 0x28, 0x68, 0x90, 0xF8, 0xAA, 0x12, 0x4F, 0xEA, 0x81, 0x61, 0x16, 0xD3,
+ 0x00, 0x29, 0x07, 0xDA, 0x61, 0x68, 0xB0, 0xF9, 0xBA, 0x22, 0xB7, 0xF9, 0x00, 0x30, 0x08, 0x46,
+ 0x00, 0xF0, 0xA9, 0xF9, 0x28, 0x68, 0x90, 0xF8, 0xAA, 0x12, 0x49, 0x06, 0x12, 0xD5, 0xB0, 0xF9,
+ 0xB8, 0x32, 0xDD, 0x4A, 0x61, 0x68, 0x30, 0x68, 0x06, 0xF0, 0x70, 0xFB, 0x11, 0xE0, 0x00, 0x29,
+ 0x08, 0xDA, 0xB0, 0xF9, 0xBA, 0x22, 0xB7, 0xF9, 0x00, 0x30, 0x61, 0x68, 0x30, 0x68, 0x00, 0xF0,
+ 0x92, 0xF9, 0x06, 0xE0, 0xB7, 0xF9, 0x00, 0x00, 0x61, 0x68, 0x42, 0x00, 0x30, 0x68, 0x0F, 0xF0,
+ 0x11, 0xFF, 0x02, 0x21, 0xD1, 0x48, 0x07, 0xF0, 0xF8, 0xFF, 0x9A, 0xF8, 0x00, 0x00, 0x4F, 0xF0,
+ 0x01, 0x0B, 0xA8, 0xB1, 0x98, 0xF8, 0x00, 0x00, 0x90, 0xB1, 0xCD, 0x48, 0x00, 0x78, 0x01, 0x28,
+ 0x0E, 0xD1, 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x40, 0x07, 0x24, 0xD5, 0x20, 0x78, 0x60, 0xB9,
+ 0x84, 0xF8, 0x00, 0xB0, 0xFF, 0xF7, 0xB0, 0xFB, 0x01, 0x21, 0x08, 0x20, 0x09, 0xF0, 0x6A, 0xFF,
+ 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x40, 0x07, 0x12, 0xD5, 0xC2, 0x49, 0x30, 0x68, 0xFF, 0xF7,
+ 0x82, 0xFE, 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x12, 0x09, 0x07, 0x09, 0xD5, 0x21, 0x78, 0x39, 0xB1,
+ 0xB0, 0xF9, 0xC5, 0x32, 0xB3, 0x48, 0xB8, 0x4A, 0x01, 0x68, 0x30, 0x68, 0x06, 0xF0, 0x26, 0xFB,
+ 0x9A, 0xF8, 0x00, 0x00, 0x30, 0xB1, 0x98, 0xF8, 0x01, 0x00, 0x18, 0xB1, 0xB4, 0x48, 0x00, 0x78,
+ 0x02, 0x28, 0x1C, 0xD0, 0xB4, 0x48, 0xB7, 0xF9, 0x00, 0x20, 0xB0, 0xF9, 0x00, 0x10, 0x30, 0x68,
+ 0xFF, 0xF7, 0xA0, 0xFD, 0xB1, 0x49, 0xB2, 0x4D, 0xA0, 0xB1, 0x81, 0xF8, 0x00, 0xB0, 0x02, 0x24,
+ 0x01, 0x21, 0xB0, 0x48, 0x07, 0xF0, 0x46, 0xFF, 0xB0, 0x48, 0xAF, 0x4B, 0xB0, 0xF9, 0x00, 0x20,
+ 0xAC, 0x48, 0x01, 0x68, 0x30, 0x68, 0xFF, 0xF7, 0x40, 0xFD, 0x28, 0x60, 0x0D, 0xE0, 0x04, 0x20,
+ 0xBD, 0xE8, 0xFE, 0x8F, 0xAA, 0x4A, 0xC5, 0xF8, 0x00, 0x90, 0x01, 0x24, 0xC2, 0xF8, 0x00, 0x90,
+ 0xA5, 0x4A, 0xC2, 0xF8, 0x00, 0x90, 0x81, 0xF8, 0x00, 0x90, 0x20, 0x46, 0xF0, 0xE7, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x07, 0x46, 0xA3, 0x48, 0x00, 0x26, 0x05, 0x78, 0x06, 0x70, 0xFF, 0xF7, 0x54, 0xFB,
+ 0x02, 0x21, 0x96, 0x48, 0x07, 0xF0, 0x1E, 0xFF, 0x9F, 0x48, 0x94, 0x4C, 0x2A, 0x46, 0x00, 0x78,
+ 0x24, 0x1F, 0x01, 0x28, 0x60, 0x68, 0x39, 0x46, 0x4B, 0xD0, 0xFF, 0xF7, 0x6F, 0xFD, 0x9B, 0x4D,
+ 0x28, 0x68, 0x90, 0xF8, 0xAB, 0x02, 0x80, 0x07, 0x07, 0xD5, 0x99, 0x48, 0x61, 0x68, 0x03, 0x78,
+ 0x98, 0x48, 0x02, 0x78, 0x08, 0x46, 0xFF, 0xF7, 0xD6, 0xFD, 0x29, 0x68, 0x96, 0x4D, 0x91, 0xF8,
+ 0xAA, 0x02, 0x02, 0x07, 0x05, 0xD4, 0xC0, 0x06, 0x03, 0xD4, 0x91, 0xF8, 0xAB, 0x02, 0xC0, 0x07,
+ 0x06, 0xD0, 0x61, 0x68, 0xB5, 0xF9, 0x00, 0x30, 0x79, 0x4A, 0x08, 0x46, 0xFF, 0xF7, 0x15, 0xFB,
+ 0x61, 0x68, 0xB5, 0xF9, 0x00, 0x00, 0x7B, 0x4C, 0x42, 0x00, 0x20, 0x68, 0x0F, 0xF0, 0x62, 0xFE,
+ 0x02, 0x21, 0x7A, 0x48, 0x07, 0xF0, 0x49, 0xFF, 0x7B, 0x48, 0xB5, 0xF9, 0x00, 0x20, 0xB0, 0xF9,
+ 0x00, 0x10, 0x20, 0x68, 0xFF, 0xF7, 0x2E, 0xFD, 0x78, 0x49, 0xA8, 0xB1, 0x01, 0x20, 0x08, 0x70,
+ 0x01, 0x46, 0x02, 0x25, 0x77, 0x48, 0x07, 0xF0, 0xD5, 0xFE, 0x78, 0x48, 0x76, 0x4B, 0xB0, 0xF9,
+ 0x00, 0x20, 0x74, 0x48, 0x01, 0x68, 0x20, 0x68, 0xFF, 0xF7, 0xCF, 0xFC, 0x70, 0x49, 0x08, 0x60,
+ 0x04, 0xE0, 0xFF, 0xF7, 0x35, 0xF8, 0xB2, 0xE7, 0x0E, 0x70, 0x01, 0x25, 0x28, 0x46, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x66, 0x49, 0x10, 0xB5, 0x09, 0x1F, 0x68, 0x4A, 0x00, 0x20, 0x48, 0x60, 0x10, 0x70,
+ 0x08, 0x70, 0x48, 0x70, 0xFF, 0xF7, 0x9C, 0xF8, 0xFF, 0xF7, 0x8B, 0xF9, 0xBD, 0xE8, 0x10, 0x40,
+ 0x00, 0xF0, 0x02, 0xB8, 0xFF, 0xF7, 0x26, 0xBA, 0x68, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x6B, 0x49,
+ 0x6B, 0x4B, 0xB0, 0xF8, 0x00, 0x23, 0x0A, 0x80, 0xB0, 0xF8, 0x22, 0x13, 0x69, 0x4C, 0x19, 0x80,
+ 0xB0, 0xF8, 0x42, 0x33, 0x23, 0x80, 0x68, 0x4C, 0x22, 0x80, 0x68, 0x4A, 0x11, 0x80, 0x68, 0x49,
+ 0x0B, 0x80, 0x5A, 0x49, 0xB0, 0xF8, 0xBC, 0x02, 0x08, 0x80, 0x10, 0xBD, 0x4C, 0x48, 0x00, 0x22,
+ 0x43, 0x78, 0x4E, 0x48, 0x00, 0x1F, 0x02, 0x2B, 0x01, 0x78, 0x47, 0x48, 0x00, 0xD2, 0x21, 0xB1,
+ 0x82, 0x70, 0x02, 0x2B, 0x00, 0xD2, 0x01, 0xB1, 0xC2, 0x70, 0x83, 0x79, 0x0B, 0x43, 0x01, 0xD0,
+ 0x02, 0x71, 0x42, 0x71, 0x70, 0x47, 0x2D, 0xE9, 0xFF, 0x4F, 0x9B, 0x46, 0xDD, 0xE9, 0x0D, 0x19,
+ 0x86, 0x46, 0x64, 0xE0, 0x01, 0x9A, 0x01, 0xFB, 0x09, 0xF0, 0x02, 0xEB, 0x40, 0x04, 0x02, 0x9A,
+ 0x54, 0x4F, 0x02, 0xEB, 0x40, 0x06, 0x4F, 0xF0, 0x01, 0x0C, 0x0E, 0xEB, 0x40, 0x05, 0x7B, 0x0C,
+ 0xE2, 0x46, 0x4A, 0x46, 0x15, 0xE0, 0x00, 0xBF, 0x36, 0xF8, 0x12, 0x00, 0x34, 0xF8, 0x12, 0x80,
+ 0xA0, 0xEB, 0x08, 0x00, 0x00, 0xB2, 0x98, 0x42, 0x00, 0xDA, 0x03, 0x46, 0xB8, 0x42, 0x00, 0xDD,
+ 0x07, 0x46, 0x00, 0x28, 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x0A, 0x02, 0xE0, 0x01, 0xDA, 0x4F, 0xF0,
+ 0x00, 0x0C, 0x52, 0x1E, 0xE8, 0xD2, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0xBA, 0xF1, 0x00, 0x0F,
+ 0x01, 0xD0, 0x00, 0x20, 0x0B, 0xE0, 0x5C, 0xEA, 0x0A, 0x00, 0x08, 0xD0, 0xBC, 0xF1, 0x00, 0x0F,
+ 0x04, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x38, 0x46, 0x00, 0xE0, 0x18, 0x46, 0x00, 0x27,
+ 0x3B, 0x46, 0x4A, 0x46, 0xCB, 0xF1, 0x00, 0x0A, 0x10, 0xE0, 0x00, 0xBF, 0x36, 0xF8, 0x12, 0xC0,
+ 0x34, 0xF8, 0x12, 0x80, 0xAC, 0xEB, 0x08, 0x0C, 0xAC, 0xEB, 0x00, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC,
+ 0xDC, 0x45, 0x03, 0xDA, 0xD4, 0x45, 0x01, 0xDD, 0x67, 0x44, 0x5B, 0x1C, 0x52, 0x1E, 0xED, 0xD2,
+ 0x03, 0xB9, 0x01, 0x23, 0x97, 0xFB, 0xF3, 0xF2, 0x02, 0x44, 0x48, 0x46, 0x05, 0xE0, 0x00, 0xBF,
+ 0x34, 0xF8, 0x10, 0x30, 0x13, 0x44, 0x25, 0xF8, 0x10, 0x30, 0x40, 0x1E, 0xF8, 0xD2, 0x49, 0x1E,
+ 0x98, 0xD2, 0xBD, 0xE8, 0xFF, 0x8F, 0x70, 0xB5, 0x00, 0x24, 0x26, 0x46, 0x47, 0xE0, 0x00, 0xBF,
+ 0x31, 0xF9, 0x14, 0x50, 0x95, 0x42, 0x3F, 0xDA, 0x20, 0xF8, 0x14, 0x60, 0x3E, 0xE0, 0x00, 0x00,
+ 0x78, 0x12, 0x01, 0x20, 0xE0, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x0C, 0x05, 0x10, 0x00,
+ 0x4C, 0x07, 0x10, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x2A, 0x6C, 0x01, 0x00, 0x2C, 0x05, 0x10, 0x00,
+ 0x0E, 0x05, 0x10, 0x00, 0x80, 0x24, 0x10, 0x00, 0x74, 0x06, 0x10, 0x00, 0xC1, 0x06, 0x10, 0x00,
+ 0x58, 0x06, 0x10, 0x00, 0x2C, 0x06, 0x10, 0x00, 0x60, 0x06, 0x10, 0x00, 0x76, 0x06, 0x10, 0x00,
+ 0x5C, 0x06, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, 0xBF, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00,
+ 0x6A, 0x06, 0x10, 0x00, 0x6C, 0x06, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, 0x70, 0x06, 0x10, 0x00,
+ 0x72, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x20, 0xF8, 0x14, 0x50, 0x64, 0x1C, 0x9C, 0x42,
+ 0xB6, 0xDB, 0x70, 0xBD, 0x7F, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x80, 0x70, 0x47, 0x30, 0xB5,
+ 0x7D, 0x49, 0x02, 0x46, 0x01, 0x20, 0x0C, 0x68, 0x94, 0xF8, 0xC6, 0x39, 0x4B, 0xB1, 0x79, 0x4D,
+ 0xB2, 0xF8, 0x44, 0x10, 0x6D, 0x68, 0x49, 0x1B, 0x00, 0xD5, 0x49, 0x42, 0x8B, 0x42, 0x00, 0xDA,
+ 0x00, 0x20, 0x94, 0xF8, 0xC7, 0x19, 0x00, 0x29, 0x12, 0xD0, 0x72, 0x4C, 0xB2, 0xF9, 0x1A, 0x50,
+ 0x08, 0x34, 0xB2, 0xF9, 0x18, 0x20, 0xB4, 0xF9, 0x02, 0x30, 0xB4, 0xF9, 0x00, 0x40, 0x5B, 0x1B,
+ 0xA2, 0x1A, 0x5B, 0x43, 0x02, 0xFB, 0x02, 0x32, 0x49, 0x43, 0x8A, 0x42, 0x00, 0xDD, 0x00, 0x20,
+ 0x30, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x68, 0x4F, 0xDF, 0xF8, 0x98, 0x81, 0x06, 0x00, 0x4F, 0xF0,
+ 0x05, 0x04, 0x4F, 0xF0, 0x06, 0x05, 0x10, 0xD0, 0x96, 0xF8, 0x3E, 0x01, 0x00, 0xF0, 0x74, 0xF9,
+ 0x04, 0x46, 0x38, 0x68, 0x90, 0xF8, 0xC5, 0x09, 0x18, 0xB1, 0xB6, 0xF8, 0x44, 0x10, 0x81, 0x42,
+ 0x2B, 0xD8, 0xB0, 0x69, 0x00, 0xF0, 0x8A, 0xF8, 0x38, 0xB3, 0x98, 0xF8, 0x00, 0x00, 0x4F, 0xF0,
+ 0x00, 0x09, 0x07, 0x28, 0x0E, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x04, 0x04, 0x23, 0x3B, 0x54, 0x04,
+ 0x04, 0x00, 0x05, 0x2C, 0x04, 0xD0, 0x04, 0x2C, 0x06, 0xD0, 0x01, 0x2C, 0x06, 0xD0, 0x14, 0xE0,
+ 0x88, 0xF8, 0x00, 0x90, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x20, 0x51, 0xE0, 0xFF, 0xF7, 0x9A, 0xFF,
+ 0x02, 0x20, 0x88, 0xF8, 0x00, 0x00, 0xA8, 0xF8, 0x02, 0x90, 0xB6, 0xF8, 0x44, 0x00, 0xC8, 0xF8,
+ 0x04, 0x00, 0xB0, 0x69, 0xC8, 0xF8, 0x08, 0x00, 0xEC, 0xE7, 0x88, 0xF8, 0x00, 0x50, 0xE9, 0xE7,
+ 0xB8, 0xF8, 0x02, 0x00, 0x40, 0x1C, 0x80, 0xB2, 0xA8, 0xF8, 0x02, 0x00, 0x03, 0x2C, 0x03, 0xD0,
+ 0x39, 0x68, 0x91, 0xF8, 0xC0, 0x19, 0x2F, 0xE0, 0x03, 0x20, 0x88, 0xF8, 0x00, 0x00, 0xA8, 0xF8,
+ 0x02, 0x90, 0xD7, 0xE7, 0x05, 0x2C, 0xD5, 0xD0, 0x30, 0x46, 0xFF, 0xF7, 0x78, 0xFF, 0x15, 0xE0,
+ 0xB8, 0xF8, 0x02, 0x10, 0x49, 0x1C, 0x89, 0xB2, 0xA8, 0xF8, 0x02, 0x10, 0x01, 0x2C, 0x05, 0xD0,
+ 0x38, 0x68, 0x90, 0xF8, 0xC1, 0x29, 0x8A, 0x42, 0xD7, 0xD9, 0xC3, 0xE7, 0x30, 0x46, 0xFF, 0xF7,
+ 0x66, 0xFF, 0x04, 0x22, 0x88, 0xF8, 0x00, 0x20, 0xA8, 0xF8, 0x02, 0x90, 0x00, 0x28, 0xCC, 0xD0,
+ 0xB8, 0xE7, 0xB8, 0xF8, 0x02, 0x00, 0x40, 0x1C, 0x80, 0xB2, 0xA8, 0xF8, 0x02, 0x00, 0x03, 0x2C,
+ 0x05, 0xD0, 0x39, 0x68, 0x91, 0xF8, 0xC2, 0x19, 0x81, 0x42, 0xD3, 0xD8, 0xBD, 0xE7, 0x05, 0x20,
+ 0x88, 0xF8, 0x00, 0x00, 0xA6, 0xE7, 0x38, 0xB5, 0x00, 0x21, 0x00, 0x91, 0x69, 0x46, 0x00, 0xF0,
+ 0xCE, 0xF8, 0x20, 0x4C, 0x01, 0x28, 0x02, 0xD9, 0x06, 0x20, 0x20, 0x70, 0x05, 0xE0, 0x00, 0x98,
+ 0xFF, 0xF7, 0x67, 0xFF, 0x20, 0x78, 0x05, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x38, 0xBD, 0x1B, 0x48,
+ 0x01, 0x21, 0x41, 0x70, 0x05, 0x21, 0x81, 0x70, 0x01, 0x20, 0x38, 0xBD, 0xF0, 0xB5, 0x16, 0x49,
+ 0x04, 0x46, 0x01, 0x20, 0x0A, 0x68, 0x92, 0xF8, 0xC3, 0x19, 0x92, 0xF8, 0xC3, 0x39, 0x8E, 0x00,
+ 0x92, 0xF8, 0xC4, 0x19, 0x8D, 0x00, 0x92, 0xF8, 0x36, 0x10, 0xCF, 0x07, 0x51, 0x8E, 0xA1, 0xEB,
+ 0x83, 0x01, 0x93, 0x8E, 0x92, 0xF8, 0xC4, 0x29, 0x09, 0xB2, 0xA3, 0xEB, 0x82, 0x02, 0x12, 0xB2,
+ 0x0C, 0xD0, 0x13, 0x46, 0x22, 0x14, 0xB2, 0x42, 0x06, 0xDB, 0x9A, 0x42, 0x04, 0xDC, 0x22, 0xB2,
+ 0xAA, 0x42, 0x01, 0xDB, 0x8A, 0x42, 0x00, 0xDD, 0x00, 0x20, 0xF0, 0xBD, 0x0B, 0x46, 0x11, 0x46,
+ 0xF0, 0xE7, 0x00, 0x00, 0x30, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xA0, 0x24, 0x10, 0x00,
+ 0x75, 0x48, 0x90, 0xF8, 0x2C, 0x00, 0x06, 0x28, 0x01, 0xD0, 0x05, 0x28, 0x07, 0xD1, 0x73, 0x48,
+ 0x73, 0x49, 0x00, 0x68, 0x90, 0xF8, 0xB4, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x08, 0x60, 0x71, 0x49,
+ 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0xB8, 0x81, 0x04, 0x46,
+ 0x98, 0xF8, 0x00, 0x00, 0x10, 0xB9, 0x0A, 0x21, 0x88, 0xF8, 0x00, 0x10, 0x00, 0x27, 0x04, 0xF5,
+ 0x80, 0x56, 0x01, 0x25, 0xD6, 0xF8, 0xB0, 0x03, 0x05, 0xFA, 0x07, 0xF1, 0x08, 0x42, 0x0C, 0xD0,
+ 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x04, 0xEB, 0x01, 0x11, 0x91, 0xF8, 0x3E, 0x01,
+ 0x03, 0x28, 0x02, 0xD1, 0x20, 0x46, 0x03, 0xF0, 0x83, 0xF9, 0x7F, 0x1C, 0xFF, 0xB2, 0x0F, 0x2F,
+ 0xE8, 0xD3, 0x00, 0x26, 0x04, 0xF5, 0x80, 0x57, 0x05, 0xFA, 0x06, 0xF1, 0xD7, 0xF8, 0xB0, 0x03,
+ 0x08, 0x42, 0x0A, 0xD0, 0xC6, 0xEB, 0xC6, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x04, 0xEB, 0x01, 0x10,
+ 0x00, 0xF1, 0x18, 0x01, 0x0C, 0x30, 0x0A, 0xF0, 0x48, 0xFA, 0x76, 0x1C, 0xF6, 0xB2, 0x0F, 0x2E,
+ 0xEA, 0xD3, 0x51, 0x48, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x98, 0xF8, 0x08, 0x00, 0x80, 0x06,
+ 0x08, 0xD5, 0x20, 0x46, 0xFF, 0xF7, 0x57, 0xFF, 0x20, 0xB1, 0x4B, 0x48, 0x09, 0xF0, 0x55, 0xFC,
+ 0xFF, 0xF7, 0x98, 0xFE, 0x00, 0x27, 0xA8, 0x46, 0x04, 0xF5, 0x80, 0x56, 0x08, 0xFA, 0x07, 0xF0,
+ 0xD6, 0xF8, 0xB0, 0x13, 0x01, 0x42, 0x11, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x01,
+ 0x04, 0xEB, 0x01, 0x15, 0x95, 0xF8, 0x3E, 0x01, 0x08, 0x28, 0x07, 0xD1, 0x29, 0x46, 0x20, 0x46,
+ 0x03, 0xF0, 0x59, 0xF9, 0x29, 0x46, 0x20, 0x46, 0x03, 0xF0, 0x1C, 0xF9, 0x7F, 0x1C, 0xFF, 0xB2,
+ 0x0F, 0x2F, 0xE3, 0xD3, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0xF0, 0x38, 0xB8, 0x30, 0xB5,
+ 0x05, 0x46, 0x00, 0x20, 0x4F, 0xEA, 0x00, 0x03, 0xC3, 0xEB, 0xC3, 0x02, 0x02, 0xEB, 0x42, 0x02,
+ 0x05, 0xEB, 0x02, 0x14, 0x94, 0xF8, 0x3E, 0x21, 0x01, 0x2A, 0x0D, 0xD0, 0x02, 0x2A, 0x0B, 0xD0,
+ 0x03, 0x2A, 0x09, 0xD0, 0x04, 0x2A, 0x07, 0xD0, 0x05, 0x2A, 0x05, 0xD0, 0x06, 0x2A, 0x03, 0xD0,
+ 0x07, 0x2A, 0x01, 0xD0, 0x08, 0x2A, 0x02, 0xD1, 0x40, 0x1C, 0xC0, 0xB2, 0x0C, 0x60, 0x5B, 0x1C,
+ 0xDB, 0xB2, 0x0F, 0x2B, 0xE0, 0xD3, 0x30, 0xBD, 0x09, 0x28, 0x0E, 0xD2, 0xDF, 0xE8, 0x00, 0xF0,
+ 0x0D, 0x05, 0x05, 0x07, 0x09, 0x09, 0x09, 0x0B, 0x0B, 0x00, 0x04, 0x20, 0x70, 0x47, 0x01, 0x20,
+ 0x70, 0x47, 0x02, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x05, 0x20, 0x70, 0x47, 0x70, 0xB5,
+ 0x1A, 0x49, 0x0A, 0x78, 0x17, 0x49, 0x06, 0x2A, 0x05, 0xD0, 0x22, 0xB1, 0x05, 0x2A, 0x02, 0xD0,
+ 0x0A, 0x20, 0x08, 0x70, 0x70, 0xBD, 0x0A, 0x78, 0x22, 0xB1, 0x52, 0x1E, 0x12, 0xF0, 0xFF, 0x02,
+ 0x0A, 0x70, 0xF7, 0xD1, 0x05, 0x46, 0x00, 0x24, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00,
+ 0x05, 0xEB, 0x00, 0x16, 0x31, 0x46, 0x28, 0x46, 0x03, 0xF0, 0xBC, 0xF8, 0x31, 0x46, 0x28, 0x46,
+ 0x03, 0xF0, 0xF1, 0xF8, 0x64, 0x1C, 0xE4, 0xB2, 0x0F, 0x2C, 0xED, 0xD3, 0xBD, 0xE8, 0x70, 0x40,
+ 0x10, 0x21, 0x01, 0x20, 0x0D, 0xF0, 0xB7, 0xBA, 0x7C, 0x6C, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x78, 0x06, 0x10, 0x00, 0x40, 0x05, 0x10, 0x00, 0xA0, 0x24, 0x10, 0x00, 0x30, 0x05, 0x10, 0x00,
+ 0x70, 0x47, 0xA5, 0x4A, 0x30, 0xB4, 0x12, 0x68, 0x92, 0xF8, 0xA4, 0x23, 0x12, 0x09, 0x80, 0xF8,
+ 0x28, 0x20, 0x0A, 0x68, 0x02, 0x62, 0x4A, 0x68, 0x42, 0x62, 0xB1, 0xF9, 0x02, 0x20, 0xD3, 0x17,
+ 0x1B, 0x04, 0x43, 0xEA, 0x12, 0x43, 0x12, 0x04, 0x82, 0x60, 0xC3, 0x60, 0xB1, 0xF9, 0x00, 0x10,
+ 0xCA, 0x17, 0x12, 0x04, 0x42, 0xEA, 0x11, 0x42, 0x09, 0x04, 0x01, 0x60, 0x42, 0x60, 0x10, 0x22,
+ 0x01, 0x46, 0x30, 0xBC, 0x10, 0x30, 0x0F, 0xF0, 0x15, 0xBB, 0x2D, 0xE9, 0xF0, 0x4F, 0x92, 0x4F,
+ 0x81, 0x46, 0x8A, 0x46, 0x38, 0x68, 0x8F, 0xB0, 0x16, 0x46, 0xB0, 0xF8, 0xA6, 0x13, 0x90, 0xF8,
+ 0xAA, 0x53, 0x01, 0xFB, 0x01, 0xFB, 0xB0, 0xF8, 0xA8, 0x13, 0x01, 0xFB, 0x01, 0xF8, 0x0F, 0xF0,
+ 0x53, 0xFC, 0x00, 0x28, 0x38, 0x68, 0x02, 0xD0, 0x90, 0xF8, 0xAC, 0x43, 0x01, 0xE0, 0x90, 0xF8,
+ 0xAB, 0x43, 0xAC, 0x42, 0x00, 0xD2, 0x25, 0x46, 0x00, 0x2E, 0x02, 0xDB, 0x89, 0xF8, 0x28, 0x60,
+ 0x19, 0xE0, 0x09, 0xF1, 0x24, 0x01, 0x99, 0xF8, 0x28, 0x60, 0x08, 0x1F, 0x0A, 0xF0, 0x11, 0xF9,
+ 0x58, 0x45, 0x01, 0xDB, 0x26, 0x46, 0x02, 0xE0, 0x40, 0x45, 0x00, 0xDC, 0x2E, 0x46, 0x38, 0x68,
+ 0x99, 0xF8, 0x28, 0x10, 0x90, 0xF8, 0xA4, 0x03, 0x00, 0xF0, 0x0F, 0x02, 0x30, 0x46, 0x0A, 0xF0,
+ 0x23, 0xF9, 0x89, 0xF8, 0x28, 0x00, 0x99, 0xF8, 0x28, 0x10, 0x74, 0x48, 0x00, 0xEB, 0x81, 0x00,
+ 0x01, 0x68, 0xCA, 0x17, 0xCD, 0xE9, 0x07, 0x21, 0x41, 0x6C, 0xCA, 0x17, 0xCD, 0xE9, 0x04, 0x12,
+ 0xD0, 0xF8, 0xCC, 0x20, 0xD0, 0xF8, 0x88, 0x50, 0xD4, 0x17, 0x01, 0x94, 0x93, 0x46, 0xDD, 0xE9,
+ 0x07, 0x21, 0xD9, 0xF8, 0x08, 0x30, 0xD9, 0xF8, 0x0C, 0x40, 0xA3, 0xFB, 0x01, 0x07, 0x04, 0xFB,
+ 0x01, 0x71, 0x03, 0xFB, 0x02, 0x11, 0xEE, 0x17, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0,
+ 0x8D, 0xFA, 0xBA, 0xF9, 0x02, 0x30, 0xB9, 0xF9, 0x26, 0x20, 0x01, 0x9C, 0x9F, 0x18, 0xA7, 0xFB,
+ 0x0B, 0x38, 0x4F, 0xEA, 0xE7, 0x7C, 0x0C, 0xFB, 0x0B, 0x82, 0x07, 0xFB, 0x04, 0x24, 0xB9, 0xF9,
+ 0x22, 0x20, 0xA2, 0xFB, 0x05, 0xC8, 0xD7, 0x17, 0x07, 0xFB, 0x05, 0x87, 0x13, 0xEB, 0x0C, 0x03,
+ 0x02, 0xFB, 0x06, 0x72, 0x54, 0x41, 0x1F, 0x1A, 0x64, 0xEB, 0x01, 0x04, 0xDD, 0xE9, 0x04, 0x12,
+ 0xD9, 0xF8, 0x18, 0x30, 0xD9, 0xF8, 0x1C, 0xC0, 0xA3, 0xFB, 0x01, 0x08, 0x0C, 0xFB, 0x01, 0x81,
+ 0x03, 0xFB, 0x02, 0x11, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0x5F, 0xFA, 0x38, 0x1A,
+ 0x64, 0xEB, 0x01, 0x04, 0xCD, 0xE9, 0x0D, 0x04, 0x06, 0x94, 0x0A, 0x90, 0xDD, 0xE9, 0x07, 0x21,
+ 0xD9, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x04, 0x40, 0xA3, 0xFB, 0x01, 0x07, 0x04, 0xFB, 0x01, 0x71,
+ 0x03, 0xFB, 0x02, 0x11, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0x47, 0xFA, 0xBA, 0xF9,
+ 0x00, 0x30, 0xB9, 0xF9, 0x24, 0x20, 0x01, 0x9C, 0x13, 0x44, 0xA3, 0xFB, 0x0B, 0xC8, 0xDF, 0x17,
+ 0x07, 0xFB, 0x0B, 0x82, 0x03, 0xFB, 0x04, 0x27, 0xB9, 0xF9, 0x20, 0x20, 0xA2, 0xFB, 0x05, 0x48,
+ 0xD3, 0x17, 0x03, 0xFB, 0x05, 0x83, 0x02, 0xFB, 0x06, 0x32, 0x1C, 0xEB, 0x04, 0x03, 0x57, 0x41,
+ 0x1C, 0x1A, 0x67, 0xEB, 0x01, 0x07, 0xDD, 0xE9, 0x04, 0x12, 0xD9, 0xF8, 0x10, 0x30, 0xD9, 0xF8,
+ 0x14, 0x50, 0xA3, 0xFB, 0x01, 0x06, 0x05, 0xFB, 0x01, 0x61, 0x03, 0xFB, 0x02, 0x11, 0x4F, 0xF4,
+ 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0x1A, 0xFA, 0x25, 0x1A, 0x67, 0xEB, 0x01, 0x07, 0xCD, 0xE9,
+ 0x0B, 0x57, 0xD9, 0xF8, 0x20, 0x10, 0xC9, 0xF8, 0x24, 0x10, 0xDA, 0xF8, 0x00, 0x10, 0xC9, 0xF8,
+ 0x20, 0x10, 0x10, 0x22, 0x49, 0x46, 0x09, 0xF1, 0x10, 0x00, 0x0F, 0xF0, 0x2B, 0xFA, 0x10, 0x22,
+ 0x0B, 0xA9, 0x48, 0x46, 0x0F, 0xF0, 0x26, 0xFA, 0x0A, 0x98, 0x4F, 0xF4, 0x00, 0x41, 0x06, 0x9C,
+ 0x40, 0x18, 0x44, 0xF1, 0x00, 0x01, 0x4F, 0xF4, 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0xF6, 0xF9,
+ 0xAA, 0xF8, 0x02, 0x00, 0x4F, 0xF4, 0x00, 0x40, 0x28, 0x18, 0x47, 0xF1, 0x00, 0x01, 0x4F, 0xF4,
+ 0x80, 0x32, 0x00, 0x23, 0x0F, 0xF0, 0xEA, 0xF9, 0xAA, 0xF8, 0x00, 0x00, 0x0F, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0x70, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x01, 0x46, 0x10, 0x22, 0x10, 0x30, 0x0F, 0xF0,
+ 0x01, 0xFA, 0xB5, 0xF9, 0x02, 0x00, 0xC1, 0x17, 0x09, 0x04, 0x41, 0xEA, 0x10, 0x41, 0x00, 0x04,
+ 0xA0, 0x60, 0xE1, 0x60, 0xB5, 0xF9, 0x00, 0x00, 0xC1, 0x17, 0x09, 0x04, 0x41, 0xEA, 0x10, 0x41,
+ 0x00, 0x04, 0x20, 0x60, 0x61, 0x60, 0x70, 0xBD, 0x20, 0x07, 0x10, 0x00, 0x1A, 0x6B, 0x01, 0x00,
+ 0x30, 0xB5, 0x2A, 0x49, 0x0B, 0x68, 0x93, 0xF8, 0x14, 0x14, 0x89, 0x07, 0x17, 0xD5, 0x41, 0xF2,
+ 0xB0, 0x34, 0x0E, 0x21, 0x24, 0x58, 0x01, 0x22, 0x02, 0xFA, 0x01, 0xF5, 0x2C, 0x42, 0x0F, 0xD0,
+ 0xC1, 0xEB, 0xC1, 0x05, 0x05, 0xEB, 0x45, 0x05, 0x00, 0xEB, 0x05, 0x15, 0x95, 0xF8, 0x3F, 0x51,
+ 0x6D, 0x07, 0x05, 0xD5, 0x1E, 0x48, 0x93, 0xF8, 0x15, 0x14, 0x01, 0x70, 0x42, 0x70, 0x30, 0xBD,
+ 0x49, 0x1E, 0xE9, 0xD2, 0x30, 0xBD, 0x19, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x14, 0x14, 0x89, 0x07,
+ 0x09, 0xD5, 0x17, 0x49, 0x10, 0xB1, 0x00, 0x20, 0x48, 0x70, 0x03, 0xE0, 0x08, 0x78, 0x00, 0x28,
+ 0x01, 0xD0, 0x40, 0x1E, 0x08, 0x70, 0x70, 0x47, 0x10, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x14, 0x14,
+ 0x8A, 0x07, 0x06, 0xD5, 0x0E, 0x49, 0x4A, 0x78, 0x01, 0x2A, 0x08, 0xD0, 0x09, 0x78, 0x31, 0xB9,
+ 0x70, 0x47, 0xC9, 0x07, 0xFC, 0xD0, 0x90, 0xF8, 0x3F, 0x11, 0x04, 0x29, 0xF8, 0xD1, 0x90, 0xF8,
+ 0x3E, 0x11, 0x03, 0x29, 0x05, 0xD0, 0x04, 0x29, 0x01, 0xD0, 0x06, 0x29, 0xF0, 0xD1, 0x08, 0x21,
+ 0x00, 0xE0, 0x02, 0x21, 0x80, 0xF8, 0x3E, 0x11, 0x70, 0x47, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x58, 0x05, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x84, 0xF8, 0x42, 0x01, 0xE9, 0x48,
+ 0xE9, 0x4D, 0x0E, 0x46, 0x01, 0x78, 0x28, 0x68, 0x11, 0xB9, 0xE8, 0x49, 0x09, 0x78, 0x41, 0xB1,
+ 0x94, 0xF9, 0x4A, 0x11, 0x90, 0xF8, 0x63, 0x02, 0xB1, 0x42, 0x0D, 0xD1, 0x00, 0xF0, 0x0F, 0x00,
+ 0x0B, 0xE0, 0x0F, 0xF0, 0xC9, 0xFA, 0x00, 0x28, 0x94, 0xF9, 0x4A, 0x01, 0x0D, 0xD0, 0xB0, 0x42,
+ 0x28, 0x68, 0x90, 0xF8, 0x9B, 0x03, 0xF1, 0xD0, 0x00, 0x09, 0x84, 0xF8, 0x42, 0x01, 0x20, 0x46,
+ 0x00, 0xF0, 0x2A, 0xF9, 0x01, 0x28, 0x06, 0xD0, 0x0F, 0xE0, 0xB0, 0x42, 0x28, 0x68, 0x90, 0xF8,
+ 0x9A, 0x03, 0xE3, 0xD0, 0xF0, 0xE7, 0x29, 0x68, 0x94, 0xF8, 0x42, 0x01, 0x91, 0xF8, 0x9C, 0x13,
+ 0x01, 0xF0, 0x0F, 0x01, 0x08, 0x44, 0x84, 0xF8, 0x42, 0x01, 0xD1, 0x48, 0xD1, 0x49, 0x00, 0x78,
+ 0x09, 0x78, 0x08, 0x43, 0x07, 0xD0, 0x29, 0x68, 0x94, 0xF8, 0x42, 0x01, 0x91, 0xF8, 0x9D, 0x13,
+ 0x08, 0x44, 0x84, 0xF8, 0x42, 0x01, 0x70, 0xBD, 0xCB, 0x49, 0x00, 0x20, 0x08, 0x70, 0xCB, 0x49,
+ 0x08, 0x70, 0xCB, 0x49, 0x08, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, 0x00, 0xF5, 0x80, 0x55,
+ 0x04, 0x46, 0xB5, 0xF8, 0xB0, 0x03, 0x4F, 0xF0, 0x00, 0x0A, 0x00, 0x04, 0xC2, 0x4E, 0xD1, 0x46,
+ 0x00, 0x0C, 0x0D, 0xD0, 0x20, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0x30, 0x46, 0x4F, 0xF0, 0xFF, 0x37,
+ 0x00, 0x78, 0x39, 0x46, 0x4F, 0xF0, 0x00, 0x48, 0x4F, 0xF0, 0x01, 0x0B, 0x18, 0xBB, 0x08, 0xE0,
+ 0xBA, 0x49, 0x00, 0x20, 0x30, 0x70, 0x08, 0x70, 0xBD, 0xE8, 0xF8, 0x4F, 0x01, 0x20, 0xFF, 0xF7,
+ 0x52, 0xBF, 0x04, 0xF5, 0x80, 0x52, 0x00, 0x20, 0x92, 0xF9, 0xB8, 0x63, 0x22, 0xE0, 0x00, 0xBF,
+ 0xD2, 0xF8, 0xB0, 0xC3, 0x0B, 0xFA, 0x00, 0xF3, 0x1C, 0xEA, 0x03, 0x0F, 0x18, 0xD0, 0xC0, 0xEB,
+ 0xC0, 0x03, 0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x03, 0x13, 0x93, 0xF8, 0x3E, 0xC1, 0xBC, 0xF1,
+ 0x01, 0x0F, 0x01, 0xD0, 0x39, 0x46, 0x0F, 0xE0, 0xB3, 0xF8, 0x44, 0xC0, 0xBC, 0xF1, 0x00, 0x0F,
+ 0x06, 0xD0, 0x5B, 0x6B, 0x93, 0xFB, 0xFC, 0xF3, 0x98, 0x45, 0x01, 0xDA, 0x98, 0x46, 0x01, 0x46,
+ 0x40, 0x1C, 0x40, 0xB2, 0x86, 0x42, 0xDB, 0xDA, 0x00, 0x27, 0xDF, 0xF8, 0x6C, 0x82, 0x00, 0x91,
+ 0x9A, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, 0x0B, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x72, 0xD0,
+ 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x04, 0xEB, 0x00, 0x16, 0x96, 0xF8, 0x3E, 0x01,
+ 0x01, 0x28, 0x02, 0xD0, 0x05, 0x28, 0x08, 0xD0, 0x10, 0xE0, 0x30, 0x46, 0x00, 0x99, 0xFF, 0xF7,
+ 0x41, 0xFF, 0x02, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x11, 0xE0, 0x30, 0x46, 0x00, 0xF0, 0xA8, 0xF8,
+ 0x06, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x30, 0x46, 0x00, 0xF0, 0xDB, 0xF8, 0x96, 0xF8, 0x3E, 0x01,
+ 0x02, 0x28, 0x04, 0xD0, 0x06, 0x28, 0x30, 0xD0, 0x07, 0x28, 0x39, 0xD0, 0x3E, 0xE0, 0x96, 0xF8,
+ 0x42, 0x00, 0xC0, 0x07, 0x12, 0xD0, 0x30, 0x46, 0x00, 0xF0, 0x76, 0xF8, 0x70, 0xB9, 0xD8, 0xF8,
+ 0x00, 0x00, 0x96, 0xF8, 0x42, 0x11, 0x90, 0xF8, 0x9C, 0x03, 0x00, 0xF0, 0x0F, 0x00, 0x81, 0x42,
+ 0x01, 0xD9, 0x08, 0x1A, 0x00, 0xE0, 0x00, 0x20, 0x86, 0xF8, 0x42, 0x01, 0x78, 0x48, 0x00, 0x78,
+ 0x40, 0xB1, 0x96, 0xF8, 0x42, 0x01, 0x08, 0xBB, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x9D, 0x03,
+ 0x86, 0xF8, 0x42, 0x01, 0x96, 0xF8, 0x42, 0x01, 0xC0, 0xB9, 0x03, 0x20, 0x86, 0xF8, 0x3E, 0x01,
+ 0x71, 0x48, 0x01, 0x78, 0x49, 0x1C, 0x01, 0x70, 0x10, 0xE0, 0x96, 0xF8, 0x43, 0x01, 0x68, 0xB9,
+ 0x96, 0xF8, 0x42, 0x00, 0x80, 0x07, 0x03, 0xD5, 0x07, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x05, 0xE0,
+ 0x08, 0x20, 0x86, 0xF8, 0x3E, 0x01, 0x30, 0x46, 0x00, 0xF0, 0x8C, 0xF8, 0x30, 0x46, 0xFF, 0xF7,
+ 0xC3, 0xFE, 0x96, 0xF8, 0x3E, 0x01, 0x02, 0x28, 0x06, 0xD0, 0x06, 0x28, 0x0B, 0xD0, 0x03, 0x28,
+ 0x10, 0xD0, 0x04, 0x28, 0x0E, 0xD0, 0x1D, 0xE0, 0x96, 0xF8, 0x42, 0x01, 0xD0, 0xB1, 0x40, 0x1E,
+ 0x86, 0xF8, 0x42, 0x01, 0x16, 0xE0, 0x96, 0xF8, 0x43, 0x01, 0x98, 0xB1, 0x40, 0x1E, 0x86, 0xF8,
+ 0x43, 0x01, 0x0F, 0xE0, 0x96, 0xF8, 0x3F, 0x01, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x28, 0x05, 0xD0,
+ 0x08, 0xE0, 0x09, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x09, 0x03, 0xE0, 0x0A, 0xF1, 0x01, 0x00,
+ 0x00, 0xF0, 0xFF, 0x0A, 0x7F, 0x1C, 0x7F, 0xB2, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xBF, 0xF6,
+ 0x61, 0xAF, 0x00, 0x20, 0xFF, 0xF7, 0x7F, 0xFE, 0x4E, 0x49, 0x81, 0xF8, 0x00, 0xA0, 0x4E, 0x49,
+ 0x81, 0xF8, 0x00, 0x90, 0xBD, 0xE8, 0xF8, 0x8F, 0x90, 0xF8, 0x5B, 0x10, 0x90, 0xF8, 0x5A, 0x20,
+ 0x8A, 0x1A, 0xB0, 0xF8, 0x42, 0x10, 0x52, 0x1C, 0x02, 0x2A, 0x0B, 0xD9, 0x90, 0xF8, 0x5D, 0x20,
+ 0x90, 0xF8, 0x5C, 0x30, 0x9A, 0x42, 0x05, 0xD1, 0x41, 0xF0, 0x01, 0x01, 0xA0, 0xF8, 0x42, 0x10,
+ 0x01, 0x20, 0x70, 0x47, 0x21, 0xF0, 0x01, 0x01, 0xA0, 0xF8, 0x42, 0x10, 0x00, 0x20, 0x70, 0x47,
+ 0x70, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x84, 0xF8, 0x43, 0x01, 0x32, 0x48, 0x32, 0x4D, 0x01, 0x78,
+ 0x28, 0x68, 0x51, 0xB1, 0x90, 0xF8, 0x64, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x84, 0xF8, 0x43, 0x01,
+ 0x94, 0xF8, 0x42, 0x00, 0x80, 0x07, 0x0E, 0xD5, 0x70, 0xBD, 0x2C, 0x49, 0x09, 0x78, 0x00, 0x29,
+ 0xF0, 0xD1, 0x0F, 0xF0, 0x59, 0xF9, 0x00, 0x28, 0x28, 0x68, 0x90, 0xF8, 0x9E, 0x03, 0xEB, 0xD0,
+ 0x00, 0x09, 0x84, 0xF8, 0x43, 0x01, 0x28, 0x68, 0xE1, 0x6A, 0x90, 0xF8, 0x9F, 0x03, 0x00, 0xF0,
+ 0x0F, 0x02, 0x91, 0x42, 0xE8, 0xD9, 0x94, 0xF8, 0x43, 0x11, 0x01, 0xEB, 0x10, 0x10, 0x84, 0xF8,
+ 0x43, 0x01, 0x70, 0xBD, 0x20, 0x49, 0x08, 0x78, 0x00, 0x28, 0x01, 0xD0, 0x40, 0x1E, 0x08, 0x70,
+ 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x18, 0x4D, 0x04, 0x46, 0x28, 0x68, 0x90, 0xF8, 0x81, 0x03,
+ 0xC0, 0x07, 0x24, 0xD0, 0x21, 0x46, 0x20, 0x1D, 0x09, 0xF0, 0x03, 0xFE, 0x07, 0x46, 0x21, 0x46,
+ 0x04, 0xF1, 0x20, 0x00, 0x09, 0xF0, 0xFD, 0xFD, 0x06, 0x46, 0x0F, 0xF0, 0x25, 0xF9, 0x00, 0x28,
+ 0x28, 0x68, 0x05, 0xD0, 0xB0, 0xF8, 0x93, 0x13, 0xB0, 0xF8, 0x8F, 0x03, 0x49, 0x43, 0x04, 0xE0,
+ 0xB0, 0xF8, 0x91, 0x13, 0xB0, 0xF8, 0x8D, 0x03, 0x49, 0x43, 0x40, 0x43, 0x86, 0x42, 0x06, 0xDD,
+ 0x8F, 0x42, 0x04, 0xDD, 0x34, 0xF8, 0x42, 0x0F, 0x40, 0xF0, 0x02, 0x00, 0x20, 0x80, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x00, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00,
+ 0x52, 0x06, 0x10, 0x00, 0x52, 0x07, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, 0xF3, 0x06, 0x10, 0x00,
+ 0xC5, 0x06, 0x10, 0x00, 0xC7, 0x06, 0x10, 0x00, 0xC8, 0x06, 0x10, 0x00, 0xF8, 0xB5, 0x07, 0x46,
+ 0xFD, 0x48, 0x0E, 0x46, 0xFE, 0x4C, 0x01, 0x78, 0xFC, 0x48, 0x15, 0x46, 0x00, 0x78, 0x01, 0xB9,
+ 0x88, 0xB1, 0x20, 0x68, 0x90, 0xF8, 0xBE, 0x13, 0xB0, 0xF8, 0xC9, 0x23, 0x01, 0xF0, 0x0F, 0x03,
+ 0x0C, 0x09, 0xB0, 0xF8, 0xC7, 0x13, 0x49, 0x43, 0x52, 0x43, 0x30, 0x46, 0x00, 0x94, 0x09, 0xF0,
+ 0xBE, 0xFD, 0x2C, 0x60, 0xF8, 0xBD, 0x0F, 0xF0, 0xD7, 0xF8, 0x58, 0xB1, 0x20, 0x68, 0x90, 0xF8,
+ 0xB4, 0x13, 0xB0, 0xF8, 0xB7, 0x23, 0x01, 0xF0, 0x0F, 0x03, 0x0C, 0x09, 0xB0, 0xF8, 0xB5, 0x13,
+ 0x49, 0x43, 0xE9, 0xE7, 0x97, 0xF8, 0x3F, 0x01, 0x02, 0x28, 0x0E, 0xD0, 0x01, 0x28, 0x20, 0x68,
+ 0x0F, 0xD0, 0x90, 0xF8, 0xB9, 0x13, 0x00, 0xBF, 0x01, 0xF0, 0x0F, 0x03, 0x0C, 0x09, 0xB0, 0xF8,
+ 0xBF, 0x13, 0xB0, 0xF8, 0xC1, 0x23, 0x49, 0x43, 0xD6, 0xE7, 0x20, 0x68, 0x90, 0xF8, 0xBA, 0x13,
+ 0xF2, 0xE7, 0x90, 0xF8, 0xBB, 0x13, 0xB0, 0xF8, 0xC5, 0x23, 0x01, 0xF0, 0x0F, 0x03, 0x0C, 0x09,
+ 0xB0, 0xF8, 0xC3, 0x13, 0x49, 0x43, 0xC7, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x90, 0xF8,
+ 0x3E, 0x01, 0x88, 0x46, 0x04, 0xF1, 0x78, 0x07, 0x03, 0x28, 0x0B, 0xD0, 0xD4, 0x4E, 0x04, 0x28,
+ 0x0D, 0xD0, 0x07, 0x28, 0x3B, 0xD0, 0x08, 0x28, 0x37, 0xD1, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x43,
+ 0x00, 0xF0, 0xCB, 0xBB, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0x00, 0xF0, 0x94, 0xBB, 0x20, 0x46,
+ 0x0F, 0xF0, 0x9F, 0xF8, 0x18, 0xB1, 0x20, 0x46, 0x0F, 0xF0, 0x96, 0xF8, 0x1D, 0xE0, 0x04, 0xF1,
+ 0x0C, 0x01, 0x08, 0x1D, 0x09, 0xF0, 0x55, 0xFD, 0x01, 0x46, 0x6A, 0x46, 0x20, 0x46, 0xFF, 0xF7,
+ 0x85, 0xFF, 0x05, 0x46, 0x94, 0xF8, 0x41, 0x01, 0x80, 0xB9, 0x20, 0x46, 0x0F, 0xF0, 0x86, 0xF8,
+ 0x10, 0xB1, 0x00, 0x98, 0x85, 0x42, 0x09, 0xDB, 0x30, 0x68, 0xD4, 0xF8, 0x80, 0x10, 0x90, 0xF8,
+ 0xBC, 0x03, 0x02, 0x09, 0x28, 0x46, 0x09, 0xF0, 0x5F, 0xFD, 0x05, 0x46, 0x2A, 0x46, 0x41, 0x46,
+ 0x38, 0x46, 0x00, 0xF0, 0x6A, 0xFB, 0xC4, 0xF8, 0x80, 0x50, 0xBD, 0xE8, 0xF8, 0x83, 0x30, 0x68,
+ 0x00, 0x24, 0x90, 0xF8, 0x81, 0x13, 0x89, 0x07, 0x0A, 0xD5, 0x90, 0xF8, 0xBD, 0x03, 0x00, 0xF0,
+ 0x0F, 0x04, 0x0F, 0xF0, 0x51, 0xF8, 0x18, 0xB1, 0x30, 0x68, 0x90, 0xF8, 0xBD, 0x03, 0x04, 0x09,
+ 0x22, 0x46, 0x41, 0x46, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0x00, 0xF0, 0x66, 0xBB, 0x2D, 0xE9,
+ 0xF0, 0x43, 0xDF, 0xF8, 0x9C, 0x92, 0x4F, 0xF0, 0x00, 0x0C, 0xB0, 0xF9, 0x02, 0x30, 0xD9, 0xF8,
+ 0x00, 0x40, 0x67, 0x46, 0x66, 0x46, 0x65, 0x46, 0x00, 0x2B, 0x02, 0xDA, 0x4F, 0xF0, 0x01, 0x0C,
+ 0x04, 0xE0, 0xB4, 0xF8, 0x32, 0x80, 0x98, 0x45, 0x00, 0xDA, 0x01, 0x27, 0xB0, 0xF9, 0x00, 0x30,
+ 0x00, 0x2B, 0x01, 0xDA, 0x01, 0x26, 0x04, 0xE0, 0xB4, 0xF8, 0x34, 0x80, 0x98, 0x45, 0x00, 0xDA,
+ 0x01, 0x25, 0x00, 0x23, 0xBC, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0x0E, 0xB1, 0x43, 0x80, 0x03, 0xE0,
+ 0x4F, 0xB1, 0x26, 0xB1, 0x61, 0x8E, 0x38, 0xE0, 0x03, 0x80, 0xBD, 0xE8, 0xF0, 0x83, 0x15, 0xB1,
+ 0x62, 0x8E, 0x42, 0x80, 0x04, 0xE0, 0xBC, 0xF1, 0x00, 0x0F, 0x30, 0xD0, 0x2D, 0xB1, 0x43, 0x80,
+ 0xD9, 0xF8, 0x00, 0x10, 0x89, 0x8E, 0x01, 0x80, 0xEF, 0xE7, 0xB2, 0xF8, 0x02, 0xC0, 0xBC, 0xF1,
+ 0x00, 0x0F, 0x24, 0xD0, 0x43, 0x80, 0xB1, 0xF9, 0x02, 0x40, 0x67, 0x42, 0x2C, 0xE0, 0x00, 0xBF,
+ 0x0C, 0xFB, 0x07, 0xFC, 0x00, 0x2C, 0x00, 0xDA, 0x64, 0x42, 0x9C, 0xFB, 0xF4, 0xF4, 0x0F, 0x88,
+ 0x3C, 0x44, 0x04, 0x80, 0x46, 0xB3, 0xB2, 0xF9, 0x00, 0x40, 0x2C, 0xB3, 0xB1, 0xF9, 0x00, 0x50,
+ 0xB2, 0xF9, 0x02, 0x20, 0x6D, 0x42, 0x00, 0xD5, 0x6D, 0x42, 0x6A, 0x43, 0x00, 0x2C, 0x00, 0xDA,
+ 0x64, 0x42, 0x92, 0xFB, 0xF4, 0xF2, 0x49, 0x88, 0x11, 0x44, 0x41, 0x80, 0xC4, 0xE7, 0x00, 0x2F,
+ 0xE8, 0xD0, 0x57, 0x88, 0x00, 0x2F, 0xE5, 0xD0, 0x64, 0x8E, 0x44, 0x80, 0xD9, 0xF8, 0x00, 0x40,
+ 0xB1, 0xF9, 0x02, 0x70, 0x64, 0x8E, 0xE7, 0x1B, 0xB2, 0xF9, 0x02, 0x40, 0xB2, 0xF9, 0x00, 0xC0,
+ 0x00, 0x2F, 0xCD, 0xDA, 0x7F, 0x42, 0xCB, 0xE7, 0x00, 0x2D, 0xAE, 0xD0, 0xB2, 0xF9, 0x00, 0x30,
+ 0x00, 0x2B, 0xAA, 0xD0, 0xD9, 0xF8, 0x00, 0x40, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x02, 0x20,
+ 0xA4, 0x8E, 0xA4, 0x1B, 0x00, 0xD5, 0x64, 0x42, 0x62, 0x43, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42,
+ 0x92, 0xFB, 0xF3, 0xF2, 0x49, 0x88, 0x11, 0x44, 0x41, 0x80, 0xA1, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F,
+ 0x0D, 0x46, 0x5C, 0x49, 0x04, 0x46, 0x00, 0x20, 0x48, 0x80, 0x08, 0x80, 0xA1, 0xF1, 0x10, 0x08,
+ 0x28, 0x68, 0xC8, 0xF8, 0x00, 0x00, 0x17, 0x46, 0x4F, 0xF0, 0x01, 0x0A, 0x46, 0x46, 0x29, 0x46,
+ 0x20, 0x46, 0x00, 0xF0, 0x6D, 0xFF, 0xDF, 0xF8, 0x48, 0x91, 0x28, 0x68, 0x70, 0x60, 0xD9, 0xF8,
+ 0x00, 0x00, 0x04, 0xF1, 0x0C, 0x0B, 0x90, 0xF8, 0x80, 0x03, 0x41, 0x07, 0x22, 0xD5, 0x94, 0xF8,
+ 0x3E, 0x01, 0x04, 0xF1, 0x84, 0x06, 0x02, 0x28, 0x0A, 0xD0, 0x03, 0x28, 0x08, 0xD0, 0x04, 0x28,
+ 0x0B, 0xD0, 0x06, 0x28, 0x12, 0xD0, 0x07, 0x28, 0x10, 0xD0, 0x08, 0x28, 0x0E, 0xD0, 0x11, 0xE0,
+ 0x59, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0xED, 0xFA, 0x0C, 0xE0, 0x20, 0x46, 0x00, 0xF0, 0xD9, 0xF9,
+ 0x02, 0x46, 0x29, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x08, 0xFB, 0x03, 0xE0, 0x29, 0x46, 0x30, 0x46,
+ 0xFF, 0xF7, 0x0F, 0xFC, 0x29, 0x68, 0xC8, 0xF8, 0x08, 0x10, 0xD9, 0xF8, 0x00, 0x00, 0x4E, 0x46,
+ 0x90, 0xF8, 0x80, 0x03, 0x00, 0x07, 0x14, 0xD5, 0x94, 0xF8, 0x42, 0x00, 0x10, 0xF0, 0xC8, 0x0F,
+ 0x05, 0xD0, 0x32, 0x48, 0x00, 0x78, 0x10, 0xB9, 0x2F, 0x48, 0x00, 0x78, 0x20, 0xB1, 0x29, 0x46,
+ 0x20, 0x46, 0x00, 0xF0, 0xE6, 0xF9, 0x04, 0xE0, 0x59, 0x46, 0x04, 0xF1, 0xB0, 0x00, 0x00, 0xF0,
+ 0xEE, 0xFD, 0x29, 0x68, 0xC8, 0xF8, 0x0C, 0x10, 0x30, 0x68, 0x90, 0xF8, 0x80, 0x13, 0x49, 0x06,
+ 0x0F, 0xD4, 0x90, 0xF8, 0x40, 0x14, 0x49, 0x06, 0x03, 0xD5, 0x94, 0xF8, 0x42, 0x10, 0x09, 0x07,
+ 0x07, 0xD4, 0x90, 0xF8, 0x20, 0x04, 0x80, 0x07, 0x08, 0xD5, 0x94, 0xF8, 0x42, 0x00, 0x00, 0x06,
+ 0x04, 0xD5, 0x29, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x37, 0xFE, 0x82, 0x46, 0x30, 0x68, 0x90, 0xF8,
+ 0x80, 0x03, 0x80, 0x06, 0x03, 0xD5, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x7D, 0xFE, 0x30, 0x68,
+ 0x90, 0xF8, 0x80, 0x03, 0x01, 0x07, 0x0B, 0xD5, 0xC0, 0x06, 0x09, 0xD5, 0x94, 0xF8, 0x3E, 0x01,
+ 0x07, 0x28, 0x05, 0xD1, 0x13, 0x4A, 0x04, 0xF1, 0xF4, 0x01, 0x28, 0x46, 0xFF, 0xF7, 0xCF, 0xFE,
+ 0x30, 0x68, 0xB0, 0xF9, 0x32, 0x10, 0xB5, 0xF9, 0x02, 0x00, 0x09, 0xF0, 0xAB, 0xFB, 0x68, 0x80,
+ 0x30, 0x68, 0xB0, 0xF9, 0x34, 0x10, 0xB5, 0xF9, 0x00, 0x00, 0x09, 0xF0, 0xA3, 0xFB, 0x28, 0x80,
+ 0x94, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x0F, 0xD0, 0x04, 0x28, 0x11, 0xD0, 0x07, 0x28, 0x1F, 0xD0,
+ 0x08, 0x28, 0x1D, 0xD0, 0x1F, 0xE0, 0x00, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x6A, 0x05, 0x10, 0x00, 0x38, 0x88, 0xA4, 0xF8, 0x50, 0x00, 0x12, 0xE0,
+ 0x30, 0x68, 0x34, 0xF8, 0x50, 0x2F, 0x90, 0xF8, 0xBC, 0x03, 0x00, 0xF0, 0x0F, 0x01, 0xC1, 0xF1,
+ 0x10, 0x00, 0x4A, 0x43, 0x39, 0x88, 0x01, 0xFB, 0x00, 0x20, 0x00, 0x09, 0x20, 0x80, 0x01, 0xE0,
+ 0xB4, 0xF8, 0x50, 0x00, 0x38, 0x80, 0x50, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xF3, 0x4F,
+ 0xE1, 0x49, 0x83, 0xB0, 0x4F, 0xF0, 0x00, 0x08, 0xC1, 0xF8, 0x00, 0x80, 0xDF, 0x49, 0xE0, 0x4D,
+ 0x83, 0x46, 0xC1, 0xF8, 0x00, 0x80, 0x85, 0xF8, 0x00, 0x80, 0x46, 0x46, 0xDF, 0xF8, 0x74, 0xA3,
+ 0x4F, 0xF0, 0x01, 0x09, 0x00, 0xF5, 0x80, 0x57, 0x6A, 0xE0, 0x00, 0xBF, 0xD7, 0xF8, 0xB0, 0x13,
+ 0x09, 0xFA, 0x06, 0xF0, 0x01, 0x42, 0x62, 0xD0, 0xC6, 0xEB, 0xC6, 0x00, 0x00, 0xEB, 0x40, 0x00,
+ 0x0B, 0xEB, 0x00, 0x14, 0x94, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x05, 0xD0, 0x04, 0x28, 0x03, 0xD0,
+ 0x07, 0x28, 0x01, 0xD0, 0x08, 0x28, 0x52, 0xD1, 0xE0, 0x68, 0x00, 0x90, 0xB4, 0xF8, 0x4E, 0x00,
+ 0xAD, 0xF8, 0x04, 0x00, 0x04, 0xF1, 0x0C, 0x01, 0xC7, 0x4A, 0x08, 0x1D, 0x00, 0xF0, 0xF8, 0xF8,
+ 0x01, 0xAA, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xE9, 0xFE, 0x02, 0x90, 0xC3, 0x4A, 0x69, 0x46,
+ 0x04, 0xF1, 0x24, 0x00, 0x00, 0xF0, 0xEC, 0xF8, 0xDA, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x00, 0x04,
+ 0xC0, 0x07, 0x0E, 0xD0, 0x94, 0xF8, 0x42, 0x00, 0x40, 0x07, 0x02, 0xD5, 0x00, 0x20, 0x02, 0x90,
+ 0x07, 0xE0, 0x94, 0xF8, 0x34, 0x01, 0x01, 0x28, 0x03, 0xD1, 0x20, 0x6A, 0x00, 0x90, 0x84, 0xF8,
+ 0x34, 0x81, 0x94, 0xF8, 0x3F, 0x01, 0x03, 0x28, 0x09, 0xD1, 0x28, 0x78, 0x40, 0x1C, 0xC0, 0xB2,
+ 0x28, 0x70, 0x94, 0xF8, 0x42, 0x10, 0x49, 0x07, 0x01, 0xD5, 0x40, 0x1E, 0x28, 0x70, 0x00, 0x98,
+ 0x60, 0x62, 0xBD, 0xF8, 0x04, 0x00, 0xA4, 0xF8, 0x50, 0x00, 0x02, 0x98, 0x01, 0x28, 0x0E, 0xD1,
+ 0x00, 0x98, 0xA0, 0x61, 0xBD, 0xF8, 0x04, 0x00, 0xA4, 0xF8, 0x52, 0x00, 0x04, 0x98, 0x94, 0xF8,
+ 0x4A, 0x21, 0x01, 0x68, 0x09, 0xFA, 0x02, 0xF0, 0x01, 0x43, 0x04, 0x98, 0x01, 0x60, 0x76, 0x1C,
+ 0x97, 0xF9, 0xB8, 0x03, 0xB0, 0x42, 0x91, 0xDA, 0xDA, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x00, 0x04,
+ 0x00, 0x07, 0x0E, 0xD5, 0x29, 0x78, 0xA0, 0x48, 0x29, 0xB1, 0xA0, 0x49, 0x09, 0x78, 0x01, 0x29,
+ 0x01, 0xD1, 0x80, 0xF8, 0x00, 0x90, 0xD7, 0xF8, 0xB4, 0x13, 0x00, 0x29, 0x01, 0xD1, 0x80, 0xF8,
+ 0x00, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xF0, 0x47, 0x89, 0x46, 0x06, 0x46,
+ 0x00, 0x27, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0xF5, 0x80, 0x55, 0x3C, 0xE0, 0xD5, 0xF8, 0xB0, 0x13,
+ 0x08, 0xFA, 0x07, 0xF2, 0x11, 0x42, 0x35, 0xD0, 0xC7, 0xEB, 0xC7, 0x01, 0x01, 0xEB, 0x41, 0x01,
+ 0x06, 0xEB, 0x01, 0x14, 0x94, 0xF8, 0x3E, 0x11, 0x03, 0x29, 0x05, 0xD0, 0x04, 0x29, 0x03, 0xD0,
+ 0x07, 0x29, 0x01, 0xD0, 0x08, 0x29, 0x25, 0xD1, 0x94, 0xF8, 0x4A, 0x31, 0xD9, 0xF8, 0x00, 0x20,
+ 0x08, 0xFA, 0x03, 0xF0, 0x02, 0x42, 0x1D, 0xD0, 0x03, 0x29, 0x03, 0xD1, 0x21, 0x46, 0x30, 0x46,
+ 0x02, 0xF0, 0x3E, 0xFA, 0x94, 0xF9, 0x4B, 0x01, 0x00, 0x28, 0x13, 0xDB, 0x94, 0xF8, 0x3F, 0x01,
+ 0x00, 0x21, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x04, 0xD0, 0x04, 0xE0,
+ 0x03, 0x21, 0x02, 0xE0, 0x04, 0x21, 0x00, 0xE0, 0x05, 0x21, 0x84, 0xF8, 0x40, 0x11, 0x20, 0x46,
+ 0x08, 0xF0, 0x04, 0xFD, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xBE, 0xDA, 0x00, 0x24,
+ 0x47, 0x46, 0x24, 0xE0, 0xD5, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x04, 0xF1, 0x08, 0x42, 0x1D, 0xD0,
+ 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x18, 0x98, 0xF8, 0x3E, 0x01,
+ 0x08, 0x28, 0x13, 0xD1, 0x98, 0xF8, 0x4A, 0x21, 0xD9, 0xF8, 0x00, 0x10, 0x07, 0xFA, 0x02, 0xF0,
+ 0x01, 0x42, 0x07, 0xD0, 0x98, 0xF9, 0x4B, 0x01, 0x00, 0x28, 0x03, 0xDB, 0x41, 0x46, 0x30, 0x46,
+ 0x02, 0xF0, 0x19, 0xFA, 0x41, 0x46, 0x30, 0x46, 0x02, 0xF0, 0xDC, 0xF9, 0x64, 0x1C, 0x95, 0xF9,
+ 0xB8, 0x03, 0xA0, 0x42, 0xD6, 0xDA, 0xBD, 0xE8, 0xF0, 0x87, 0x57, 0x49, 0x10, 0xB5, 0x00, 0x20,
+ 0x08, 0x60, 0x56, 0x49, 0x08, 0x60, 0xFF, 0xF7, 0x2B, 0xF9, 0x00, 0xF0, 0x39, 0xFC, 0xBD, 0xE8,
+ 0x10, 0x40, 0x00, 0xF0, 0xB7, 0xB8, 0x38, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x00, 0x90, 0x69, 0x46,
+ 0x20, 0x46, 0xFF, 0xF7, 0xD3, 0xFE, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x6D, 0xFF, 0x38, 0xBD,
+ 0x10, 0xB5, 0x14, 0x46, 0x09, 0xF0, 0x75, 0xFA, 0x21, 0x68, 0x81, 0x42, 0x00, 0xDA, 0x20, 0x60,
+ 0x10, 0xBD, 0x4B, 0x49, 0x10, 0xB5, 0x0B, 0x78, 0x46, 0x49, 0x02, 0x46, 0x4F, 0xF0, 0xFF, 0x30,
+ 0x09, 0x68, 0x13, 0xB1, 0x91, 0xF9, 0xAA, 0x03, 0x10, 0xBD, 0x46, 0x4B, 0x1B, 0x78, 0x00, 0x2B,
+ 0xF8, 0xD1, 0xB2, 0xF8, 0x42, 0x30, 0x5C, 0x06, 0x03, 0xD5, 0x91, 0xF8, 0xA5, 0x03, 0x00, 0x09,
+ 0x10, 0xBD, 0x1C, 0x07, 0x02, 0xD5, 0x91, 0xF8, 0x51, 0x04, 0x03, 0xE0, 0x1B, 0x06, 0x04, 0xD5,
+ 0x91, 0xF8, 0x2A, 0x04, 0x00, 0xF0, 0x0F, 0x00, 0x10, 0xBD, 0x92, 0xF8, 0x3F, 0x21, 0x01, 0x2A,
+ 0x04, 0xD0, 0x39, 0x4A, 0x12, 0x78, 0x01, 0x2A, 0xDC, 0xD8, 0x10, 0xBD, 0x91, 0xF8, 0xA5, 0x03,
+ 0xF0, 0xE7, 0x30, 0xB4, 0x0C, 0x46, 0x90, 0xF8, 0x3E, 0x11, 0x00, 0xF1, 0xB0, 0x03, 0x03, 0x29,
+ 0x23, 0xD0, 0x04, 0x29, 0x03, 0xD0, 0x06, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x41, 0xD1, 0x29, 0x4A,
+ 0x12, 0x68, 0x92, 0xF8, 0x80, 0x23, 0xD2, 0x06, 0x2D, 0xD5, 0x90, 0xF8, 0x5B, 0x20, 0x90, 0xF8,
+ 0x5A, 0x50, 0x52, 0x1B, 0xC0, 0xF8, 0x24, 0x21, 0x90, 0xF8, 0x5D, 0x20, 0x90, 0xF8, 0x5C, 0x50,
+ 0x52, 0x1B, 0xC0, 0xF8, 0x28, 0x21, 0x82, 0x6B, 0xC0, 0xF8, 0x20, 0x21, 0x23, 0x4A, 0x07, 0x29,
+ 0x12, 0x88, 0xC0, 0xF8, 0x2C, 0x21, 0x06, 0xD0, 0x0F, 0xE0, 0x00, 0xF1, 0x0C, 0x01, 0x30, 0xBC,
+ 0x18, 0x46, 0x00, 0xF0, 0xDC, 0xBB, 0x90, 0xF8, 0x31, 0x11, 0x03, 0x29, 0x05, 0xD9, 0x21, 0x46,
+ 0x30, 0xBC, 0x1B, 0x4A, 0x18, 0x46, 0x00, 0xF0, 0x6A, 0xBC, 0x90, 0xF8, 0x31, 0x11, 0x49, 0x1C,
+ 0x80, 0xF8, 0x31, 0x11, 0x03, 0xE0, 0x90, 0xF8, 0x31, 0x21, 0x03, 0x2A, 0x04, 0xD9, 0x21, 0x46,
+ 0x30, 0xBC, 0x18, 0x46, 0x00, 0xF0, 0x28, 0xBC, 0x04, 0x29, 0x04, 0xD0, 0x00, 0x21, 0x80, 0xF8,
+ 0x31, 0x11, 0x30, 0xBC, 0x70, 0x47, 0x52, 0x1C, 0x80, 0xF8, 0x31, 0x21, 0x21, 0x46, 0x30, 0xBC,
+ 0x18, 0x46, 0x00, 0xF0, 0x02, 0xBC, 0x00, 0x00, 0xF4, 0x06, 0x10, 0x00, 0xF8, 0x06, 0x10, 0x00,
+ 0xF3, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00,
+ 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, 0x54, 0x06, 0x10, 0x00,
+ 0x6A, 0x05, 0x10, 0x00, 0x70, 0x47, 0x00, 0xF0, 0x35, 0xB8, 0x7C, 0xB5, 0x04, 0x46, 0x15, 0x46,
+ 0x0E, 0x46, 0x68, 0x46, 0x00, 0xF0, 0x2E, 0xF8, 0x01, 0x99, 0x2A, 0x46, 0x60, 0x68, 0x00, 0xF0,
+ 0x3B, 0xF8, 0x60, 0x60, 0x00, 0x99, 0x2A, 0x46, 0x20, 0x68, 0x00, 0xF0, 0x35, 0xF8, 0x20, 0x60,
+ 0x21, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x27, 0xF8, 0x7C, 0xBD, 0x7C, 0xB5, 0x04, 0x46, 0x15, 0x46,
+ 0x0E, 0x46, 0x68, 0x46, 0x00, 0xF0, 0x16, 0xF8, 0x01, 0x99, 0x2A, 0x46, 0x60, 0x68, 0x00, 0xF0,
+ 0x23, 0xF8, 0x60, 0x60, 0x00, 0x99, 0x2A, 0x46, 0x20, 0x68, 0x00, 0xF0, 0x1D, 0xF8, 0x20, 0x60,
+ 0x21, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x0F, 0xF8, 0x7C, 0xBD, 0x0A, 0x46, 0x01, 0x46, 0x10, 0x46,
+ 0x00, 0xF0, 0x09, 0xB8, 0xB1, 0xF9, 0x02, 0x20, 0x12, 0x02, 0x42, 0x60, 0xB1, 0xF9, 0x00, 0x10,
+ 0x09, 0x02, 0x01, 0x60, 0x70, 0x47, 0x4A, 0x68, 0x80, 0x32, 0x12, 0x12, 0x42, 0x80, 0x09, 0x68,
+ 0x80, 0x31, 0x09, 0x12, 0x01, 0x80, 0x70, 0x47, 0xC2, 0xF1, 0x10, 0x03, 0x50, 0x43, 0x01, 0xFB,
+ 0x03, 0x00, 0x00, 0x11, 0x70, 0x47, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xFE, 0x4A, 0x12, 0x68,
+ 0x51, 0xB3, 0x51, 0x8E, 0x92, 0xF8, 0x30, 0x30, 0x82, 0x6F, 0x04, 0x6F, 0xC0, 0x6F, 0x64, 0x26,
+ 0x40, 0x00, 0x00, 0xFB, 0x02, 0x40, 0x48, 0x43, 0xA0, 0xFB, 0x00, 0x25, 0x00, 0x21, 0x01, 0xFB,
+ 0x00, 0x55, 0x00, 0xFB, 0x01, 0x51, 0xA2, 0xFB, 0x06, 0x07, 0x00, 0x25, 0x01, 0xFB, 0x06, 0x71,
+ 0x02, 0xFB, 0x05, 0x11, 0x5C, 0x43, 0x22, 0x46, 0x2B, 0x46, 0x0E, 0xF0, 0x85, 0xFA, 0x22, 0x46,
+ 0x00, 0x23, 0x0E, 0xF0, 0x81, 0xFA, 0xED, 0x4B, 0x00, 0x22, 0x1B, 0x1A, 0x8A, 0x41, 0x01, 0xD2,
+ 0xEA, 0x48, 0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x81, 0x91, 0x8E, 0x92, 0xF8, 0x31, 0x30, 0x42, 0x6F,
+ 0xD3, 0xE7, 0x7C, 0xB5, 0x04, 0x46, 0xE6, 0x48, 0xB4, 0xF9, 0x02, 0x10, 0x00, 0x78, 0x01, 0x28,
+ 0x30, 0xD0, 0xB4, 0xF9, 0x06, 0x00, 0xB4, 0xF9, 0x0A, 0x20, 0x09, 0x1A, 0x80, 0x1A, 0x08, 0x1A,
+ 0x01, 0x90, 0xB4, 0xF9, 0x00, 0x10, 0xB4, 0xF9, 0x04, 0x00, 0xB4, 0xF9, 0x08, 0x20, 0x09, 0x1A,
+ 0x80, 0x1A, 0x08, 0x1A, 0xD8, 0x49, 0x00, 0x90, 0x20, 0x6C, 0x09, 0x68, 0x01, 0x9B, 0x91, 0xF8,
+ 0xB3, 0x23, 0x50, 0x43, 0xC2, 0xF1, 0x80, 0x02, 0x53, 0x43, 0xC2, 0x17, 0x00, 0xEB, 0x52, 0x60,
+ 0x03, 0xEB, 0xE0, 0x10, 0x20, 0x64, 0x91, 0xF8, 0xB3, 0x13, 0xE0, 0x6B, 0x00, 0x9A, 0x48, 0x43,
+ 0xC1, 0xF1, 0x80, 0x01, 0x4A, 0x43, 0xC1, 0x17, 0x00, 0xEB, 0x51, 0x60, 0x02, 0xEB, 0xE0, 0x10,
+ 0xE0, 0x63, 0x7C, 0xBD, 0xB4, 0xF9, 0x46, 0x00, 0xB4, 0xF9, 0x4A, 0x20, 0x09, 0x1A, 0x80, 0x1A,
+ 0x08, 0x1A, 0x01, 0x90, 0xB4, 0xF9, 0x00, 0x10, 0xB4, 0xF9, 0x44, 0x00, 0xB4, 0xF9, 0x48, 0x20,
+ 0x09, 0x1A, 0x80, 0x1A, 0x08, 0x1A, 0x00, 0x90, 0x04, 0xF1, 0x50, 0x00, 0x03, 0x22, 0x69, 0x46,
+ 0x05, 0x46, 0x09, 0xF0, 0xDC, 0xF8, 0x94, 0xF8, 0x80, 0x00, 0x03, 0x28, 0x02, 0xD2, 0x40, 0x1C,
+ 0x84, 0xF8, 0x80, 0x00, 0xC2, 0xB2, 0x29, 0x46, 0x04, 0xF1, 0x68, 0x00, 0x00, 0xF0, 0x98, 0xFB,
+ 0x7C, 0xBD, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x00, 0x26, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96,
+ 0x01, 0x24, 0x0D, 0xF1, 0x14, 0x08, 0x08, 0x96, 0x02, 0x25, 0xCD, 0xE9, 0x01, 0x48, 0x07, 0x46,
+ 0xCD, 0xE9, 0x03, 0x54, 0x00, 0xF1, 0x0C, 0x03, 0xAD, 0x48, 0x9B, 0x46, 0x2A, 0x46, 0x29, 0x46,
+ 0x20, 0x30, 0x00, 0x95, 0x09, 0xF0, 0x2C, 0xF8, 0xDF, 0xF8, 0xA4, 0x92, 0x4F, 0xF4, 0x80, 0x7A,
+ 0x99, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x48, 0xD0, 0x38, 0x6C, 0x00, 0x90, 0x01, 0x23, 0x02, 0x22,
+ 0x07, 0xA9, 0x09, 0xF1, 0x08, 0x00, 0x08, 0xF0, 0xF2, 0xFF, 0x07, 0xA9, 0x01, 0x23, 0x02, 0x22,
+ 0x08, 0x46, 0xCD, 0xF8, 0x00, 0xA0, 0x08, 0xF0, 0xDC, 0xFF, 0x02, 0x23, 0x5A, 0x46, 0x07, 0xA9,
+ 0x05, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0xF0, 0xFF, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, 0x08, 0x96,
+ 0xCD, 0xE9, 0x01, 0x48, 0xCD, 0xE9, 0x03, 0x54, 0x95, 0x48, 0x07, 0xF1, 0x14, 0x03, 0x00, 0x95,
+ 0x02, 0x22, 0x1D, 0x46, 0x11, 0x46, 0x20, 0x30, 0x08, 0xF0, 0xFA, 0xFF, 0x99, 0xF8, 0x00, 0x00,
+ 0x01, 0x28, 0x1F, 0xD0, 0xF8, 0x6B, 0x00, 0x90, 0x8D, 0x48, 0x01, 0x23, 0x02, 0x22, 0x07, 0xA9,
+ 0x08, 0x30, 0x08, 0xF0, 0xC4, 0xFF, 0x07, 0xA9, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0xCD, 0xF8,
+ 0x00, 0xA0, 0x08, 0xF0, 0xAE, 0xFF, 0x02, 0x23, 0x2A, 0x46, 0x07, 0xA9, 0x05, 0xA8, 0x00, 0x94,
+ 0x08, 0xF0, 0xC2, 0xFF, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDD, 0xE9, 0x05, 0x01, 0xC7, 0xE9,
+ 0x03, 0x01, 0xC9, 0xE7, 0xDD, 0xE9, 0x05, 0x01, 0xC7, 0xE9, 0x05, 0x01, 0xF2, 0xE7, 0x2D, 0xE9,
+ 0xF0, 0x4F, 0x8D, 0xB0, 0x00, 0x26, 0x02, 0x24, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, 0x08, 0x96,
+ 0x09, 0x96, 0x0A, 0x96, 0x0B, 0x96, 0x05, 0xAF, 0x0C, 0x96, 0xCD, 0xE9, 0x01, 0x47, 0x05, 0x46,
+ 0x73, 0x48, 0x05, 0xF1, 0x1C, 0x03, 0x03, 0x94, 0x04, 0x94, 0x9B, 0x46, 0x22, 0x46, 0x21, 0x46,
+ 0x20, 0x30, 0x00, 0x94, 0x08, 0xF0, 0xB4, 0xFF, 0x0D, 0xF1, 0x24, 0x0A, 0xCD, 0xE9, 0x01, 0x4A,
+ 0x6B, 0x4B, 0x02, 0x22, 0x03, 0x94, 0x04, 0x94, 0x30, 0x33, 0x11, 0x46, 0x05, 0xA8, 0x00, 0x94,
+ 0x08, 0xF0, 0xA6, 0xFF, 0xDF, 0xF8, 0x98, 0x81, 0x4F, 0xF0, 0x04, 0x09, 0x98, 0xF8, 0x00, 0x00,
+ 0x01, 0x28, 0x12, 0xD1, 0xE8, 0x6E, 0x02, 0x23, 0x08, 0xF1, 0x60, 0x01, 0x00, 0x90, 0x1A, 0x46,
+ 0xA1, 0xF1, 0x10, 0x00, 0x08, 0xF0, 0x6B, 0xFF, 0x02, 0x23, 0x08, 0xF1, 0x60, 0x01, 0x1A, 0x46,
+ 0x08, 0x46, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0x54, 0xFF, 0x59, 0x49, 0x02, 0x23, 0x5A, 0x46,
+ 0x60, 0x31, 0x09, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0x67, 0xFF, 0x05, 0x96, 0x06, 0x96, 0x07, 0x96,
+ 0x08, 0x96, 0x09, 0x96, 0x0A, 0x96, 0x0B, 0x96, 0x0C, 0x96, 0xCD, 0xE9, 0x01, 0x47, 0x50, 0x48,
+ 0x05, 0xF1, 0x2C, 0x03, 0x02, 0x22, 0x03, 0x94, 0x04, 0x94, 0x1E, 0x46, 0x11, 0x46, 0x20, 0x30,
+ 0x00, 0x94, 0x08, 0xF0, 0x6D, 0xFF, 0xCD, 0xE9, 0x01, 0x4A, 0x49, 0x4B, 0x02, 0x22, 0x03, 0x94,
+ 0x04, 0x94, 0x30, 0x33, 0x11, 0x46, 0x05, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0x61, 0xFF, 0x98, 0xF8,
+ 0x00, 0x00, 0x01, 0x28, 0x12, 0xD1, 0x42, 0x49, 0xA8, 0x6E, 0x02, 0x23, 0x60, 0x31, 0x00, 0x90,
+ 0x1A, 0x46, 0xA1, 0xF1, 0x10, 0x00, 0x08, 0xF0, 0x2A, 0xFF, 0x3D, 0x49, 0x02, 0x23, 0x60, 0x31,
+ 0x1A, 0x46, 0x08, 0x46, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0x13, 0xFF, 0x38, 0x49, 0x02, 0x23,
+ 0x32, 0x46, 0x60, 0x31, 0x09, 0xA8, 0x00, 0x94, 0x08, 0xF0, 0x26, 0xFF, 0x0D, 0xB0, 0x62, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x00, 0x26, 0x01, 0x24, 0x05, 0x96, 0x06, 0x96, 0x0D, 0xF1,
+ 0x14, 0x0A, 0x07, 0x96, 0xCD, 0xE9, 0x01, 0x4A, 0x05, 0x46, 0x00, 0xF1, 0x0C, 0x03, 0x4F, 0xF0,
+ 0x02, 0x09, 0x2B, 0x48, 0x93, 0x46, 0x0F, 0x46, 0x03, 0x94, 0x98, 0x46, 0x4A, 0x46, 0x21, 0x46,
+ 0x10, 0x30, 0xCD, 0xF8, 0x00, 0x90, 0x04, 0x94, 0x08, 0xF0, 0x22, 0xFF, 0xB5, 0xF9, 0x02, 0x00,
+ 0x05, 0x99, 0x01, 0x23, 0x40, 0x1A, 0x05, 0x90, 0x00, 0x90, 0x02, 0x22, 0x06, 0xA9, 0x38, 0x46,
+ 0x08, 0xF0, 0xED, 0xFE, 0x64, 0x27, 0x41, 0x46, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0x00, 0x97,
+ 0x08, 0xF0, 0xE5, 0xFE, 0x42, 0x46, 0x02, 0x23, 0x06, 0xA9, 0x10, 0x46, 0x00, 0x94, 0x08, 0xF0,
+ 0xEB, 0xFE, 0x41, 0x46, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0x00, 0x97, 0x08, 0xF0, 0xC9, 0xFE,
+ 0x05, 0x96, 0x06, 0x96, 0x07, 0x96, 0xCD, 0xE9, 0x01, 0x4A, 0x11, 0x48, 0x05, 0xF1, 0x14, 0x03,
+ 0x03, 0x94, 0x1E, 0x46, 0x02, 0x22, 0x01, 0x21, 0x10, 0x30, 0xCD, 0xF8, 0x00, 0x90, 0x04, 0x94,
+ 0x08, 0xF0, 0xEE, 0xFE, 0xB5, 0xF9, 0x00, 0x00, 0x05, 0x99, 0x01, 0x23, 0x40, 0x1A, 0x05, 0x90,
+ 0x00, 0x90, 0x02, 0x22, 0x06, 0xA9, 0x58, 0x46, 0x08, 0xF0, 0xB9, 0xFE, 0x01, 0x23, 0x31, 0x46,
+ 0x02, 0x22, 0x08, 0x46, 0x00, 0x97, 0x05, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x40, 0x42, 0x0F, 0x00,
+ 0x70, 0x05, 0x10, 0x00, 0x08, 0xF0, 0xAB, 0xFE, 0x32, 0x46, 0x02, 0x23, 0x06, 0xA9, 0x10, 0x46,
+ 0x00, 0x94, 0x08, 0xF0, 0xB1, 0xFE, 0x31, 0x46, 0x01, 0x23, 0x02, 0x22, 0x08, 0x46, 0x00, 0x97,
+ 0x08, 0xF0, 0x8F, 0xFE, 0xE6, 0xE6, 0x2D, 0xE9, 0xF7, 0x4F, 0x8A, 0xB0, 0x00, 0x26, 0x05, 0x96,
+ 0x06, 0x96, 0x07, 0x96, 0x08, 0x96, 0x01, 0x24, 0x4F, 0xF0, 0x02, 0x09, 0x0D, 0xF1, 0x14, 0x0A,
+ 0x09, 0x96, 0xCD, 0xE9, 0x01, 0x4A, 0xCD, 0xE9, 0x03, 0x94, 0x07, 0x46, 0x07, 0xF1, 0x1C, 0x00,
+ 0x4D, 0x46, 0xFD, 0x4B, 0x4A, 0x46, 0x49, 0x46, 0x80, 0x46, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0,
+ 0xA7, 0xFE, 0x07, 0xA8, 0xCD, 0xE9, 0x01, 0x50, 0xF7, 0x48, 0xCD, 0xE9, 0x03, 0x45, 0x43, 0x46,
+ 0x02, 0x22, 0x01, 0x21, 0x08, 0x38, 0x00, 0x95, 0x08, 0xF0, 0x9A, 0xFE, 0x0D, 0xF1, 0x24, 0x0B,
+ 0xCD, 0xE9, 0x01, 0x4B, 0x03, 0x94, 0xF0, 0x4B, 0x02, 0x22, 0x01, 0x21, 0x07, 0xA8, 0x00, 0x95,
+ 0x04, 0x94, 0x08, 0xF0, 0x8D, 0xFE, 0xEC, 0x4D, 0x18, 0x3D, 0x28, 0x78, 0x01, 0x28, 0x04, 0xD1,
+ 0x01, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0xA8, 0xFD, 0x68, 0x60, 0x09, 0x98, 0x69, 0x68, 0x4F, 0xF0,
+ 0x64, 0x08, 0x08, 0x44, 0x05, 0xA9, 0x09, 0x90, 0x01, 0x23, 0x02, 0x22, 0xCD, 0xF8, 0x00, 0x80,
+ 0x08, 0x46, 0x08, 0xF0, 0x4C, 0xFE, 0x09, 0x98, 0x00, 0x90, 0x01, 0x23, 0x02, 0x22, 0x05, 0xA8,
+ 0x0B, 0x99, 0x08, 0xF0, 0x36, 0xFE, 0x07, 0x96, 0x08, 0x96, 0x05, 0x96, 0x06, 0x96, 0x09, 0x96,
+ 0xCD, 0xE9, 0x01, 0x4A, 0xCD, 0xE9, 0x03, 0x94, 0x4E, 0x46, 0x02, 0x22, 0x07, 0xF1, 0x2C, 0x00,
+ 0xCD, 0xF8, 0x00, 0x90, 0xD4, 0x4B, 0x11, 0x46, 0x81, 0x46, 0x08, 0xF0, 0x59, 0xFE, 0x07, 0xA8,
+ 0xCD, 0xE9, 0x01, 0x60, 0xCD, 0xE9, 0x03, 0x46, 0xCF, 0x48, 0x4B, 0x46, 0x02, 0x22, 0x01, 0x21,
+ 0x08, 0x38, 0x00, 0x96, 0x08, 0xF0, 0x4C, 0xFE, 0xCD, 0xE9, 0x01, 0x4B, 0x03, 0x94, 0xCA, 0x4B,
+ 0x02, 0x22, 0x01, 0x21, 0x07, 0xA8, 0x00, 0x96, 0x04, 0x94, 0x08, 0xF0, 0x41, 0xFE, 0x28, 0x78,
+ 0x01, 0x28, 0x04, 0xD1, 0x00, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0x5E, 0xFD, 0x68, 0x60, 0x09, 0x98,
+ 0x69, 0x68, 0x01, 0x23, 0x08, 0x44, 0x05, 0xA9, 0x09, 0x90, 0x02, 0x22, 0xCD, 0xF8, 0x00, 0x80,
+ 0x08, 0x46, 0x08, 0xF0, 0x04, 0xFE, 0x09, 0x98, 0x00, 0x90, 0x01, 0x23, 0x02, 0x22, 0x05, 0xA8,
+ 0x0C, 0x99, 0x08, 0xF0, 0xEE, 0xFD, 0xE1, 0xE6, 0x2D, 0xE9, 0xF7, 0x4F, 0x8E, 0xB0, 0x00, 0x25,
+ 0x05, 0x95, 0x06, 0x95, 0x07, 0x95, 0x02, 0x24, 0x08, 0x95, 0x09, 0x95, 0x0A, 0x95, 0x0B, 0x95,
+ 0x05, 0xAF, 0x0C, 0x95, 0xCD, 0xE9, 0x01, 0x47, 0x8C, 0x46, 0x4F, 0xF0, 0x01, 0x0A, 0xAE, 0x4B,
+ 0x06, 0x46, 0x03, 0x94, 0x08, 0x3B, 0x52, 0x46, 0x21, 0x46, 0x60, 0x46, 0xCD, 0xF8, 0x00, 0xA0,
+ 0x04, 0x94, 0x08, 0xF0, 0x05, 0xFE, 0xA8, 0x48, 0x05, 0xAA, 0x02, 0x23, 0x11, 0x46, 0x28, 0x30,
+ 0x00, 0x94, 0x08, 0xF0, 0xEF, 0xFD, 0x0D, 0xF1, 0x24, 0x08, 0xCD, 0xE9, 0x01, 0x48, 0x06, 0xF1,
+ 0x1C, 0x03, 0x02, 0x22, 0x03, 0x94, 0x04, 0x94, 0x9B, 0x46, 0x11, 0x46, 0x05, 0xA8, 0x00, 0x94,
+ 0x08, 0xF0, 0xEE, 0xFD, 0x4F, 0xF0, 0x64, 0x09, 0x02, 0x23, 0x1A, 0x46, 0x59, 0x46, 0x09, 0xA8,
+ 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0xAD, 0xFD, 0x05, 0x95, 0x06, 0x95, 0x07, 0x95, 0x08, 0x95,
+ 0x09, 0x95, 0x0A, 0x95, 0x0B, 0x95, 0x0C, 0x95, 0xCD, 0xE9, 0x01, 0x47, 0x92, 0x4B, 0x03, 0x94,
+ 0x08, 0x3B, 0x01, 0x22, 0x02, 0x21, 0xCD, 0xF8, 0x00, 0xA0, 0x04, 0x94, 0x10, 0x98, 0x08, 0xF0,
+ 0xCF, 0xFD, 0x8D, 0x48, 0x05, 0xAA, 0x02, 0x23, 0x11, 0x46, 0x28, 0x30, 0x00, 0x94, 0x08, 0xF0,
+ 0xB9, 0xFD, 0xCD, 0xE9, 0x01, 0x48, 0x03, 0x94, 0x04, 0x94, 0x06, 0xF1, 0x2C, 0x03, 0x00, 0x94,
+ 0x02, 0x22, 0x1C, 0x46, 0x11, 0x46, 0x05, 0xA8, 0x08, 0xF0, 0xBA, 0xFD, 0x02, 0x23, 0x1A, 0x46,
+ 0x21, 0x46, 0x09, 0xA8, 0xCD, 0xF8, 0x00, 0x90, 0x08, 0xF0, 0x7B, 0xFD, 0x11, 0xB0, 0xD2, 0xE5,
+ 0x38, 0xB5, 0x7E, 0x48, 0x7C, 0x4C, 0x01, 0x68, 0x18, 0x3C, 0x91, 0xF8, 0x80, 0x03, 0xC0, 0xF3,
+ 0x00, 0x12, 0x22, 0x70, 0xB1, 0xF8, 0xB1, 0x03, 0x1A, 0xB1, 0x64, 0x21, 0x48, 0x43, 0x0D, 0x46,
+ 0x01, 0xE0, 0xD1, 0xF8, 0xAD, 0x53, 0x74, 0x49, 0x80, 0x08, 0x02, 0x23, 0x48, 0x31, 0x00, 0x90,
+ 0x1A, 0x46, 0xA1, 0xF1, 0x10, 0x00, 0x08, 0xF0, 0x6A, 0xFD, 0x65, 0x60, 0x38, 0xBD, 0xF8, 0xB5,
+ 0x04, 0x46, 0x08, 0x68, 0x20, 0x60, 0x48, 0x68, 0x60, 0x60, 0x88, 0x68, 0xA0, 0x60, 0x00, 0x25,
+ 0x25, 0x64, 0xE5, 0x63, 0xB1, 0xF9, 0x02, 0x00, 0xC4, 0xE9, 0x03, 0x05, 0xB1, 0xF9, 0x00, 0x00,
+ 0xC4, 0xE9, 0x05, 0x05, 0x64, 0x48, 0x18, 0x38, 0x01, 0x78, 0x01, 0x29, 0x09, 0xD0, 0x60, 0x30,
+ 0x1C, 0x34, 0x0F, 0xC8, 0x0F, 0xC4, 0x84, 0xE8, 0x0F, 0x00, 0x2C, 0x3C, 0x84, 0xF8, 0x81, 0x50,
+ 0xF8, 0xBD, 0x50, 0x30, 0x1C, 0x34, 0x0F, 0xC8, 0x0F, 0xC4, 0x5C, 0x4E, 0x0F, 0xC4, 0x30, 0x68,
+ 0x64, 0x21, 0x02, 0x23, 0xB0, 0xF8, 0xB1, 0x03, 0x1A, 0x46, 0x48, 0x43, 0x80, 0x08, 0xA4, 0xF1,
+ 0x20, 0x01, 0x00, 0x90, 0x08, 0x46, 0x3C, 0x3C, 0x08, 0xF0, 0x31, 0xFD, 0x30, 0x68, 0x64, 0x21,
+ 0x02, 0x23, 0xB0, 0xF8, 0xB1, 0x03, 0x1A, 0x46, 0x48, 0x43, 0x80, 0x08, 0x04, 0xF1, 0x2C, 0x01,
+ 0x00, 0x90, 0x08, 0x46, 0x08, 0xF0, 0x23, 0xFD, 0x94, 0xE8, 0x07, 0x00, 0x04, 0xF1, 0x44, 0x03,
+ 0x83, 0xE8, 0x07, 0x00, 0x84, 0xF8, 0x80, 0x50, 0xD0, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x03, 0x22,
+ 0x08, 0xF0, 0xB0, 0xFD, 0x20, 0x46, 0xFF, 0xF7, 0x94, 0xFC, 0xB4, 0xF9, 0x02, 0x00, 0xE0, 0x60,
+ 0xB4, 0xF9, 0x06, 0x10, 0x40, 0x1A, 0x20, 0x61, 0xB4, 0xF9, 0x00, 0x00, 0x60, 0x61, 0xB4, 0xF9,
+ 0x04, 0x10, 0x40, 0x1A, 0xA0, 0x61, 0x10, 0xBD, 0x7F, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x03, 0x22,
+ 0x08, 0xF0, 0x98, 0xFD, 0x20, 0x46, 0xFF, 0xF7, 0x7C, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0xD9, 0xFC,
+ 0x20, 0x46, 0xFF, 0xF7, 0x4C, 0xFD, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90,
+ 0x02, 0xAA, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x4E, 0xFE, 0x02, 0xAA, 0x69, 0x46, 0x20, 0x46,
+ 0xFF, 0xF7, 0xCE, 0xFD, 0x02, 0xAA, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFE, 0xA0, 0x89,
+ 0x68, 0x80, 0xA0, 0x8A, 0x28, 0x80, 0x28, 0x48, 0x18, 0x38, 0x00, 0x78, 0x01, 0x28, 0x05, 0xD1,
+ 0x03, 0x22, 0x29, 0x46, 0x04, 0xF1, 0x44, 0x00, 0x08, 0xF0, 0x6C, 0xFD, 0x7F, 0xBD, 0x2D, 0xE9,
+ 0xF0, 0x47, 0x06, 0x46, 0x48, 0x88, 0xB6, 0xF8, 0x4A, 0x30, 0x89, 0x46, 0xC0, 0x1A, 0xB6, 0xF8,
+ 0x46, 0x40, 0x92, 0x46, 0x01, 0xB2, 0xB9, 0xF8, 0x00, 0x00, 0xB6, 0xF8, 0x48, 0x20, 0xE3, 0x1A,
+ 0x1C, 0xB2, 0x80, 0x1A, 0xB6, 0xF8, 0x44, 0x30, 0x00, 0xB2, 0x9A, 0x1A, 0x15, 0xB2, 0x0C, 0xB9,
+ 0x00, 0x2D, 0x27, 0xD0, 0x49, 0x43, 0x00, 0xFB, 0x00, 0x10, 0x64, 0x21, 0x48, 0x43, 0x04, 0xFB,
+ 0x04, 0xF1, 0x05, 0xFB, 0x05, 0x11, 0xB0, 0xFB, 0xF1, 0xF0, 0x08, 0xF0, 0x83, 0xFC, 0x44, 0x43,
+ 0x0A, 0x22, 0x45, 0x43, 0x21, 0xB2, 0x28, 0xB2, 0x91, 0xFB, 0xF2, 0xF1, 0x90, 0xFB, 0xF2, 0xF0,
+ 0xB6, 0xF8, 0x46, 0x20, 0x61, 0xF3, 0x1F, 0x48, 0x11, 0x44, 0x61, 0xF3, 0x1F, 0x47, 0xB6, 0xF8,
+ 0x44, 0x10, 0x60, 0xF3, 0x0F, 0x08, 0x08, 0x44, 0x60, 0xF3, 0x0F, 0x07, 0xC9, 0xF8, 0x00, 0x70,
+ 0xCA, 0xF8, 0x00, 0x80, 0xBD, 0xE8, 0xF0, 0x87, 0x88, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xF0, 0xB5, 0x4F, 0xF0, 0x00, 0x0C, 0x63, 0x46, 0x65, 0x46, 0x14, 0x46, 0x07, 0xE0, 0x00, 0xBF,
+ 0x01, 0xEB, 0xC4, 0x06, 0x76, 0x68, 0x35, 0x44, 0x51, 0xF8, 0x34, 0x60, 0x33, 0x44, 0x64, 0x1E,
+ 0xF6, 0xD2, 0x95, 0xFB, 0xF2, 0xF6, 0x93, 0xFB, 0xF2, 0xF7, 0xC0, 0xF8, 0x04, 0xC0, 0x15, 0x46,
+ 0x42, 0xF2, 0x10, 0x74, 0xC0, 0xF8, 0x00, 0xC0, 0x17, 0xE0, 0x00, 0xBF, 0x01, 0xEB, 0xC5, 0x03,
+ 0x5B, 0x68, 0x9B, 0x1B, 0x5B, 0x43, 0xA3, 0x42, 0x00, 0xDD, 0x23, 0x46, 0xD0, 0xF8, 0x04, 0xC0,
+ 0x63, 0x44, 0x43, 0x60, 0x51, 0xF8, 0x35, 0x30, 0xDB, 0x1B, 0x5B, 0x43, 0xA3, 0x42, 0x00, 0xDD,
+ 0x23, 0x46, 0xD0, 0xF8, 0x00, 0xC0, 0x63, 0x44, 0x03, 0x60, 0x6D, 0x1E, 0xE6, 0xD2, 0x41, 0x68,
+ 0x64, 0x23, 0x59, 0x43, 0x91, 0xFB, 0xF2, 0xF1, 0x41, 0x60, 0x01, 0x68, 0x59, 0x43, 0x91, 0xFB,
+ 0xF2, 0xF1, 0x01, 0x60, 0xF0, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x14, 0x21, 0x53, 0x48, 0x0D, 0xF0,
+ 0x82, 0xFF, 0x0D, 0xF0, 0x24, 0xFD, 0x64, 0x21, 0x48, 0x43, 0x50, 0x49, 0x08, 0x60, 0x10, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x38, 0x81, 0x04, 0x46, 0x0D, 0x46, 0xD8, 0xF8, 0x00, 0x00,
+ 0x90, 0xF8, 0xA0, 0x03, 0x00, 0xF0, 0x0F, 0x06, 0xC6, 0xF1, 0x10, 0x07, 0x20, 0x46, 0x00, 0xF0,
+ 0x5C, 0xF8, 0xF0, 0xB1, 0xE0, 0x89, 0x61, 0x8A, 0x22, 0x8A, 0x40, 0x1A, 0xA1, 0x89, 0x00, 0xB2,
+ 0x89, 0x1A, 0xB4, 0xF9, 0x2A, 0x20, 0x78, 0x43, 0x02, 0xFB, 0x06, 0x00, 0x00, 0x11, 0x60, 0x85,
+ 0x09, 0xB2, 0xB4, 0xF9, 0x28, 0x00, 0x79, 0x43, 0x00, 0xFB, 0x06, 0x10, 0x00, 0x11, 0x20, 0x85,
+ 0x0D, 0xF0, 0xDF, 0xFB, 0x39, 0x4A, 0x91, 0x89, 0x08, 0x1A, 0x11, 0x7C, 0x01, 0x29, 0x0E, 0xD0,
+ 0x0F, 0xE0, 0x20, 0x6B, 0x02, 0x28, 0x07, 0xD1, 0xE0, 0x89, 0x61, 0x8A, 0x40, 0x1A, 0x60, 0x85,
+ 0xA0, 0x89, 0x21, 0x8A, 0x40, 0x1A, 0x20, 0x85, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x51, 0x68,
+ 0x08, 0x44, 0x00, 0x28, 0x00, 0xDA, 0x00, 0x20, 0x00, 0xEB, 0x80, 0x01, 0x16, 0x68, 0x49, 0x00,
+ 0xB1, 0xFB, 0xF6, 0xF7, 0xD8, 0xF8, 0x00, 0x10, 0xB1, 0xF8, 0xA1, 0x33, 0x9F, 0x42, 0x03, 0xD9,
+ 0x73, 0x43, 0x0A, 0x20, 0xB3, 0xFB, 0xF0, 0xF0, 0xB4, 0xF9, 0x2A, 0x60, 0x91, 0xF8, 0xA3, 0x33,
+ 0x92, 0x68, 0x5E, 0x43, 0x64, 0x21, 0x46, 0x43, 0x4A, 0x43, 0xB4, 0xF9, 0x28, 0x40, 0x96, 0xFB,
+ 0xF2, 0xF1, 0x5C, 0x43, 0x44, 0x43, 0x94, 0xFB, 0xF2, 0xF0, 0x6A, 0x88, 0x11, 0x44, 0x69, 0x80,
+ 0x29, 0x88, 0x08, 0x44, 0x28, 0x80, 0x01, 0x20, 0xCF, 0xE7, 0x70, 0xB5, 0x04, 0x46, 0x18, 0x48,
+ 0x01, 0x25, 0x00, 0x68, 0x90, 0xF8, 0x80, 0x03, 0x80, 0x07, 0x12, 0xD5, 0xB4, 0xF8, 0x42, 0x00,
+ 0x01, 0x07, 0x0E, 0xD4, 0x00, 0x06, 0x0C, 0xD4, 0x0D, 0xF0, 0xAE, 0xFF, 0x48, 0xB9, 0x11, 0x48,
+ 0x00, 0x78, 0x30, 0xB9, 0x10, 0x48, 0x00, 0x78, 0x18, 0xB9, 0x10, 0x48, 0x00, 0x78, 0x01, 0x28,
+ 0x02, 0xD9, 0x00, 0x20, 0x20, 0x63, 0x0E, 0xE0, 0x20, 0x6B, 0x02, 0x28, 0x0C, 0xD8, 0x40, 0x1C,
+ 0x20, 0x63, 0x02, 0x28, 0x07, 0xD9, 0x94, 0xF8, 0x3E, 0x01, 0x04, 0x28, 0x04, 0xD0, 0x06, 0x28,
+ 0x02, 0xD0, 0x07, 0x28, 0x00, 0xD0, 0x00, 0x25, 0x28, 0x46, 0x70, 0xBD, 0xC8, 0x24, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xF3, 0x06, 0x10, 0x00,
+ 0xB0, 0xF8, 0x44, 0x20, 0xB1, 0xF8, 0x44, 0x30, 0x1A, 0x44, 0xA0, 0xF8, 0x44, 0x20, 0xB0, 0xF8,
+ 0x46, 0x20, 0xB1, 0xF8, 0x46, 0x30, 0x1A, 0x44, 0xA0, 0xF8, 0x46, 0x20, 0x42, 0x6B, 0x4B, 0x6B,
+ 0x1A, 0x44, 0x42, 0x63, 0x82, 0x6B, 0x8B, 0x6B, 0x1A, 0x44, 0x82, 0x63, 0xB1, 0xF9, 0x54, 0x20,
+ 0xB0, 0xF9, 0x54, 0x30, 0x9A, 0x42, 0x01, 0xDD, 0xA0, 0xF8, 0x54, 0x20, 0xB1, 0xF9, 0x56, 0x20,
+ 0xB0, 0xF9, 0x56, 0x30, 0x9A, 0x42, 0x01, 0xDD, 0xA0, 0xF8, 0x56, 0x20, 0x90, 0xF8, 0x44, 0x21,
+ 0x91, 0xF8, 0x44, 0x31, 0x9A, 0x42, 0x0A, 0xD0, 0x30, 0xF8, 0x48, 0x2F, 0xB1, 0xF8, 0x48, 0x30,
+ 0x1A, 0x44, 0x20, 0xF8, 0x0C, 0x29, 0xC9, 0x6B, 0x02, 0x68, 0x11, 0x44, 0x01, 0x60, 0x70, 0x47,
+ 0x2D, 0xE9, 0xF0, 0x4F, 0x97, 0xB0, 0x80, 0x46, 0x00, 0xF5, 0x80, 0x50, 0x00, 0x26, 0x11, 0x90,
+ 0xBF, 0xE0, 0x00, 0x20, 0x08, 0x90, 0x05, 0x90, 0x10, 0x90, 0x12, 0x90, 0x81, 0x46, 0x82, 0x46,
+ 0x83, 0x46, 0x05, 0x46, 0x07, 0x46, 0x0A, 0x90, 0x0B, 0x90, 0x0C, 0x90, 0x0D, 0x90, 0x08, 0xEB,
+ 0x86, 0x00, 0x00, 0xF5, 0x80, 0x50, 0x14, 0x90, 0xD0, 0xF8, 0x2C, 0x04, 0x0A, 0xAA, 0x04, 0x46,
+ 0x17, 0xE0, 0x00, 0xBF, 0x90, 0xF8, 0x44, 0x11, 0x08, 0xEB, 0x01, 0x0C, 0x53, 0x5C, 0x0C, 0xF5,
+ 0x80, 0x5C, 0x5B, 0x1C, 0xDB, 0xB2, 0x53, 0x54, 0x9C, 0xF8, 0x1A, 0xC4, 0x63, 0x45, 0x06, 0xD1,
+ 0x01, 0x2B, 0x04, 0xD9, 0x01, 0x23, 0x8B, 0x40, 0x12, 0x99, 0x0B, 0x43, 0x12, 0x93, 0xD0, 0xF8,
+ 0x4C, 0x01, 0x00, 0x28, 0xE6, 0xD1, 0x40, 0xE0, 0x94, 0xF8, 0x44, 0x11, 0x01, 0x20, 0x00, 0xFA,
+ 0x01, 0xFC, 0x12, 0x99, 0x1C, 0xEA, 0x01, 0x0F, 0x12, 0xD1, 0xA0, 0x6B, 0xB4, 0xF9, 0x0E, 0x30,
+ 0x05, 0x9A, 0x49, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x05, 0x92, 0x89, 0x46, 0xB4, 0xF9, 0x0C, 0x30,
+ 0x51, 0x46, 0x5A, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x8A, 0x46, 0x93, 0x46, 0x05, 0x44, 0x19, 0xE0,
+ 0x08, 0x99, 0x1C, 0xEA, 0x01, 0x0F, 0x15, 0xD1, 0xE0, 0x6B, 0xB4, 0xF9, 0x1E, 0x30, 0x05, 0x9A,
+ 0x49, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x05, 0x92, 0x89, 0x46, 0xB4, 0xF9, 0x1C, 0x30, 0x51, 0x46,
+ 0x5A, 0x46, 0xC0, 0xFB, 0x03, 0x12, 0x8A, 0x46, 0x08, 0x99, 0x05, 0x44, 0x4C, 0xEA, 0x01, 0x00,
+ 0x93, 0x46, 0x08, 0x90, 0x20, 0x46, 0x00, 0xF0, 0xFA, 0xFC, 0x01, 0x28, 0x02, 0xD1, 0x10, 0x98,
+ 0x40, 0x1C, 0x10, 0x90, 0xD4, 0xF8, 0x4C, 0x41, 0x7F, 0x1C, 0x00, 0x2C, 0xBC, 0xD1, 0x00, 0x2F,
+ 0x45, 0xDD, 0xE8, 0x17, 0x04, 0x46, 0x03, 0x46, 0x2A, 0x46, 0x48, 0x46, 0x05, 0x99, 0x0D, 0xF0,
+ 0x4D, 0xFD, 0xAD, 0xF8, 0x1E, 0x00, 0x2A, 0x46, 0x23, 0x46, 0x50, 0x46, 0x59, 0x46, 0x0D, 0xF0,
+ 0x45, 0xFD, 0xAD, 0xF8, 0x1C, 0x00, 0x14, 0x98, 0x4F, 0xF0, 0xFF, 0x37, 0x00, 0x25, 0xD0, 0xF8,
+ 0x2C, 0x44, 0x23, 0xE0, 0x20, 0x46, 0x00, 0xF0, 0xD2, 0xFC, 0x01, 0x28, 0x01, 0xD0, 0x10, 0x98,
+ 0x90, 0xB9, 0x04, 0xF1, 0x10, 0x01, 0x07, 0xA8, 0x08, 0xF0, 0x7B, 0xFB, 0xB8, 0x42, 0x0B, 0xD2,
+ 0x07, 0x46, 0x3D, 0xB1, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x1A, 0xFF, 0x29, 0x46, 0x40, 0x46,
+ 0x00, 0xF0, 0xD4, 0xFC, 0x25, 0x46, 0x07, 0xE0, 0x21, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x10, 0xFF,
+ 0x21, 0x46, 0x40, 0x46, 0x00, 0xF0, 0xCA, 0xFC, 0xD4, 0xF8, 0x4C, 0x41, 0x00, 0x2C, 0xD9, 0xD1,
+ 0x07, 0x98, 0x45, 0xF8, 0x0C, 0x0F, 0xE8, 0x8E, 0x40, 0xF0, 0x40, 0x00, 0xE8, 0x86, 0x11, 0x98,
+ 0x76, 0x1C, 0x90, 0xF8, 0xA4, 0x04, 0xB0, 0x42, 0x3F, 0xF7, 0x3B, 0xAF, 0x17, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0x2D, 0xE9, 0xF7, 0x4F, 0x05, 0x46, 0x0E, 0x46, 0xC1, 0xEB, 0xC6, 0x00, 0x00, 0xEB,
+ 0x40, 0x00, 0x82, 0xB0, 0x05, 0xEB, 0x00, 0x1A, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0xDF, 0xF8,
+ 0x98, 0xB5, 0x05, 0xF5, 0x80, 0x57, 0x7F, 0xE0, 0xD7, 0xF8, 0xB0, 0x23, 0x08, 0xFA, 0x04, 0xF9,
+ 0x12, 0xEA, 0x09, 0x0F, 0x77, 0xD0, 0xB4, 0x42, 0x75, 0xD0, 0xDB, 0xF8, 0x0C, 0x10, 0x31, 0xF8,
+ 0x16, 0x10, 0x11, 0xEA, 0x09, 0x0F, 0x6E, 0xD1, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00,
+ 0x05, 0xEB, 0x00, 0x10, 0x00, 0x90, 0x00, 0xF0, 0x6C, 0xFC, 0x01, 0x28, 0x04, 0xD0, 0x00, 0x98,
+ 0x00, 0xF0, 0x6D, 0xFC, 0x01, 0x28, 0x5E, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x5A, 0xFC, 0xE8, 0xBB,
+ 0x00, 0x99, 0x0A, 0xF1, 0x0C, 0x00, 0x0C, 0x31, 0x08, 0xF0, 0x13, 0xFB, 0x01, 0x90, 0xDB, 0xF8,
+ 0x0C, 0x00, 0x08, 0xFA, 0x06, 0xF2, 0x30, 0xF8, 0x16, 0x30, 0x43, 0xEA, 0x09, 0x03, 0x20, 0xF8,
+ 0x16, 0x30, 0x30, 0xF8, 0x14, 0x30, 0x13, 0x43, 0x20, 0xF8, 0x14, 0x30, 0x50, 0x46, 0xDB, 0xF8,
+ 0x04, 0x90, 0x00, 0xF0, 0x58, 0xFC, 0x01, 0x28, 0x04, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x41, 0xFC,
+ 0x01, 0x28, 0x1D, 0xD0, 0x50, 0x46, 0x00, 0xF0, 0x3C, 0xFC, 0x01, 0x28, 0x04, 0xD1, 0x00, 0x98,
+ 0x00, 0xF0, 0x49, 0xFC, 0x01, 0x28, 0x13, 0xD0, 0x50, 0x46, 0x00, 0xF0, 0x32, 0xFC, 0x01, 0x28,
+ 0x1E, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x2D, 0xFC, 0x01, 0x28, 0x19, 0xD1, 0x00, 0x99, 0x9A, 0xF8,
+ 0x42, 0x00, 0x91, 0xF8, 0x42, 0x10, 0x08, 0x43, 0x80, 0x06, 0x00, 0xE0, 0x1B, 0xE0, 0x0F, 0xD5,
+ 0xBA, 0xF8, 0x42, 0x00, 0xDB, 0xF8, 0x08, 0x90, 0x40, 0xF0, 0x20, 0x01, 0xAA, 0xF8, 0x42, 0x10,
+ 0x00, 0x98, 0xB0, 0xF8, 0x42, 0x00, 0x40, 0xF0, 0x20, 0x01, 0x00, 0x98, 0xA0, 0xF8, 0x42, 0x10,
+ 0x01, 0x98, 0x48, 0x45, 0x07, 0xD2, 0x41, 0xF2, 0x2C, 0x40, 0x51, 0x46, 0x28, 0x44, 0x04, 0x9B,
+ 0x00, 0x9A, 0x00, 0xF0, 0x32, 0xFC, 0x64, 0x1C, 0x97, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0xBF, 0xF6,
+ 0x7B, 0xAF, 0x05, 0xB0, 0x63, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0x88, 0x46, 0x06, 0x46, 0xC1, 0xEB,
+ 0xC8, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x14, 0xDF, 0xF8, 0x6C, 0xA4, 0x94, 0xF8,
+ 0x42, 0x00, 0x4F, 0xF0, 0x04, 0x0B, 0x40, 0x06, 0x4F, 0xF0, 0x01, 0x09, 0x06, 0xF5, 0x80, 0x55,
+ 0x2E, 0xD5, 0x00, 0x27, 0x04, 0xF1, 0x0C, 0x0B, 0x24, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13,
+ 0x09, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x1C, 0xD0, 0x47, 0x45, 0x1A, 0xD0, 0xC7, 0xEB, 0xC7, 0x00,
+ 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x10, 0x00, 0x90, 0x00, 0xF0, 0xD2, 0xFB, 0x01, 0x28,
+ 0x0F, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0xC5, 0xFB, 0x58, 0xB9, 0x00, 0x99, 0x58, 0x46, 0x10, 0x31,
+ 0x08, 0xF0, 0x7F, 0xFA, 0xDA, 0xF8, 0x08, 0x10, 0x88, 0x42, 0x02, 0xD2, 0x04, 0x20, 0x84, 0xF8,
+ 0x3E, 0x01, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xD7, 0xDA, 0xBD, 0xE8, 0xF8, 0x8F,
+ 0xFE, 0x49, 0xE0, 0x6A, 0x09, 0x68, 0x91, 0xF8, 0x95, 0x13, 0x88, 0x42, 0xF6, 0xD9, 0x00, 0x27,
+ 0x31, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, 0x09, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x29, 0xD0,
+ 0x47, 0x45, 0x27, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x10,
+ 0x00, 0x90, 0x00, 0xF0, 0x9E, 0xFB, 0x01, 0x28, 0x1C, 0xD1, 0x00, 0x98, 0x94, 0xF8, 0x44, 0x11,
+ 0x90, 0xF8, 0x45, 0x01, 0x81, 0x42, 0x15, 0xD1, 0x00, 0x98, 0x00, 0xF0, 0x8A, 0xFB, 0x88, 0xB9,
+ 0x00, 0x99, 0x04, 0xF1, 0x0C, 0x00, 0x10, 0x31, 0x08, 0xF0, 0x43, 0xFA, 0xDA, 0xF8, 0x08, 0x10,
+ 0x88, 0x42, 0x07, 0xD2, 0x84, 0xF8, 0x3E, 0xB1, 0xB4, 0xF8, 0x42, 0x00, 0x40, 0xF0, 0x40, 0x00,
+ 0xA4, 0xF8, 0x42, 0x00, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xCA, 0xDA, 0x00, 0x27,
+ 0x28, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x13, 0x09, 0xFA, 0x07, 0xF0, 0x01, 0x42, 0x20, 0xD0,
+ 0x47, 0x45, 0x1E, 0xD0, 0xC7, 0xEB, 0xC7, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x10,
+ 0x83, 0x46, 0x00, 0xF0, 0x6C, 0xFB, 0x01, 0x28, 0x13, 0xD1, 0x58, 0x46, 0x00, 0xF0, 0x59, 0xFB,
+ 0x78, 0xB9, 0x0B, 0xF1, 0x10, 0x01, 0x04, 0xF1, 0x0C, 0x00, 0x08, 0xF0, 0x12, 0xFA, 0xDA, 0xF8,
+ 0x08, 0x10, 0x88, 0x42, 0x05, 0xD2, 0xBB, 0xF8, 0x42, 0x00, 0x40, 0xF0, 0x40, 0x01, 0xAB, 0xF8,
+ 0x42, 0x10, 0x7F, 0x1C, 0x95, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0xD3, 0xDA, 0x8E, 0xE7, 0x2D, 0xE9,
+ 0xF8, 0x43, 0x06, 0x46, 0xFF, 0x20, 0x00, 0x25, 0x8D, 0xF8, 0x00, 0x00, 0x01, 0x27, 0x06, 0xF5,
+ 0x80, 0x54, 0x19, 0xE0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x18,
+ 0xD4, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x05, 0xF1, 0x08, 0x42, 0x0C, 0xD0, 0x40, 0x46, 0x00, 0xF0,
+ 0x28, 0xFB, 0x01, 0x28, 0x07, 0xD0, 0x98, 0xF8, 0x3E, 0x01, 0x05, 0x28, 0x03, 0xD1, 0x29, 0x46,
+ 0x30, 0x46, 0xFF, 0xF7, 0x28, 0xFF, 0x6D, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0xE1, 0xDA,
+ 0x00, 0x25, 0x1B, 0xE0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x18,
+ 0xD4, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x05, 0xF1, 0x08, 0x42, 0x0E, 0xD0, 0x40, 0x46, 0x00, 0xF0,
+ 0x08, 0xFB, 0x01, 0x28, 0x09, 0xD0, 0x40, 0x46, 0x00, 0xF0, 0x11, 0xFB, 0x01, 0x28, 0x04, 0xD1,
+ 0x6A, 0x46, 0x29, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x6C, 0xFE, 0x6D, 0x1C, 0x94, 0xF9, 0xB8, 0x03,
+ 0xA8, 0x42, 0xDF, 0xDA, 0x00, 0x25, 0xB8, 0x46, 0x21, 0xE0, 0x00, 0xBF, 0xC5, 0xEB, 0xC5, 0x00,
+ 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x17, 0xD4, 0xF8, 0xB0, 0x13, 0x08, 0xFA, 0x05, 0xF0,
+ 0x01, 0x42, 0x13, 0xD0, 0x38, 0x46, 0x00, 0xF0, 0xE4, 0xFA, 0x01, 0x28, 0x0E, 0xD0, 0x38, 0x46,
+ 0x00, 0xF0, 0xE7, 0xFA, 0x01, 0x28, 0x04, 0xD1, 0x6A, 0x46, 0x29, 0x46, 0x30, 0x46, 0xFF, 0xF7,
+ 0x48, 0xFE, 0x37, 0xF8, 0x42, 0x0F, 0x20, 0xF0, 0x20, 0x00, 0x38, 0x80, 0x6D, 0x1C, 0x94, 0xF9,
+ 0xB8, 0x03, 0xA8, 0x42, 0xDA, 0xDA, 0x9D, 0xF8, 0x00, 0x00, 0x40, 0x1C, 0x84, 0xF8, 0xA4, 0x04,
+ 0xBD, 0xE8, 0xF8, 0x83, 0x10, 0xB5, 0x04, 0x46, 0x87, 0x48, 0x03, 0x21, 0x0C, 0x30, 0x05, 0xF0,
+ 0x97, 0xFB, 0x85, 0x48, 0x1E, 0x21, 0xC0, 0x68, 0x0D, 0xF0, 0xD3, 0xFB, 0x41, 0xF2, 0x2C, 0x40,
+ 0x7C, 0x21, 0x20, 0x44, 0x0D, 0xF0, 0xEF, 0xFB, 0x80, 0x48, 0x02, 0x68, 0x80, 0x48, 0xB2, 0xF8,
+ 0x96, 0x13, 0x80, 0x79, 0x49, 0x43, 0x10, 0xB1, 0xB2, 0xF8, 0x6C, 0x13, 0x49, 0x43, 0xB2, 0xF8,
+ 0x98, 0x23, 0x02, 0xFB, 0x02, 0x10, 0x78, 0x4A, 0x12, 0x1D, 0x11, 0x60, 0x11, 0x1D, 0x08, 0x60,
+ 0x20, 0x46, 0xFF, 0xF7, 0x5C, 0xFF, 0x20, 0x46, 0xFF, 0xF7, 0x3A, 0xFD, 0x72, 0x48, 0x03, 0x21,
+ 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x30, 0x05, 0xF0, 0x83, 0xBB, 0xF0, 0xB4, 0x84, 0x6B, 0xC2, 0x68,
+ 0x8B, 0x6B, 0xCE, 0x68, 0x17, 0x14, 0x67, 0x43, 0x4F, 0xEA, 0x26, 0x4C, 0x03, 0xFB, 0x0C, 0x77,
+ 0xE5, 0x18, 0x97, 0xFB, 0xF5, 0xF7, 0x67, 0xF3, 0x1F, 0x42, 0x17, 0xB2, 0x67, 0x43, 0x34, 0xB2,
+ 0x03, 0xFB, 0x04, 0x73, 0x93, 0xFB, 0xF5, 0xF3, 0x63, 0xF3, 0x0F, 0x02, 0xC2, 0x60, 0xF0, 0xBC,
+ 0xDE, 0xE4, 0x62, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x40, 0x24, 0x92, 0x06, 0x11, 0xD5, 0x90, 0xF8,
+ 0x47, 0x31, 0x23, 0xB1, 0x91, 0xF8, 0x47, 0x21, 0x0A, 0xB1, 0x93, 0x42, 0x07, 0xD1, 0x90, 0xF8,
+ 0x48, 0x01, 0x30, 0xB1, 0x91, 0xF8, 0x48, 0x11, 0x19, 0xB1, 0x88, 0x42, 0x01, 0xD0, 0x00, 0x20,
+ 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xFC, 0x5F, 0x00, 0xF5, 0x80, 0x54, 0x05, 0x46,
+ 0xD4, 0xF8, 0xBC, 0x13, 0xD4, 0xF8, 0xB0, 0x03, 0x01, 0x40, 0x00, 0x28, 0xC4, 0xF8, 0xBC, 0x13,
+ 0x4F, 0xF0, 0x00, 0x00, 0x0A, 0xD0, 0x81, 0x46, 0x0F, 0x21, 0x4E, 0x48, 0x0D, 0xF0, 0x83, 0xFB,
+ 0x00, 0x26, 0xDF, 0xF8, 0x30, 0xA1, 0x4F, 0xF0, 0x01, 0x08, 0x5B, 0xE0, 0xC4, 0xF8, 0xBC, 0x03,
+ 0xBD, 0xE8, 0xFC, 0x9F, 0xD4, 0xF8, 0xB0, 0x13, 0x08, 0xFA, 0x06, 0xF2, 0x40, 0x46, 0x11, 0x42,
+ 0x4F, 0xD0, 0xC6, 0xEB, 0xC6, 0x01, 0x01, 0xEB, 0x41, 0x01, 0x05, 0xEB, 0x01, 0x11, 0x91, 0xF8,
+ 0x40, 0x30, 0x1B, 0x06, 0xD4, 0xF8, 0xBC, 0x33, 0x11, 0xD5, 0x13, 0x43, 0x05, 0xEB, 0x86, 0x02,
+ 0xC4, 0xF8, 0xBC, 0x33, 0x02, 0xF5, 0x9C, 0x52, 0xD1, 0xF8, 0x5A, 0x30, 0x13, 0x64, 0x91, 0xF8,
+ 0x44, 0x11, 0x88, 0x40, 0x40, 0xEA, 0x09, 0x09, 0x0A, 0xF8, 0x01, 0x60, 0x31, 0xE0, 0x13, 0x42,
+ 0x2F, 0xD0, 0x91, 0xF8, 0x3E, 0x31, 0x06, 0x2B, 0x15, 0xD0, 0x05, 0x2B, 0x13, 0xD0, 0x91, 0xF8,
+ 0x44, 0x21, 0x08, 0xFA, 0x02, 0xF0, 0x40, 0xEA, 0x09, 0x09, 0x0A, 0xF8, 0x02, 0x60, 0x00, 0xBF,
+ 0x05, 0xEB, 0x86, 0x07, 0x5A, 0x31, 0x07, 0xF5, 0x9E, 0x57, 0x8B, 0x46, 0x38, 0x46, 0x03, 0xF0,
+ 0x15, 0xFA, 0x98, 0xB1, 0x15, 0xE0, 0xB1, 0xF8, 0x42, 0x00, 0x20, 0xF0, 0x08, 0x00, 0xA1, 0xF8,
+ 0x42, 0x00, 0xD4, 0xF8, 0xBC, 0x03, 0x90, 0x43, 0xC4, 0xF8, 0xBC, 0x03, 0x22, 0x4A, 0x05, 0xEB,
+ 0x86, 0x00, 0x00, 0xF5, 0x9C, 0x50, 0x12, 0x68, 0x02, 0x64, 0xE1, 0xE7, 0xDB, 0xF8, 0x00, 0x00,
+ 0x38, 0x60, 0x76, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xB0, 0x42, 0xA3, 0xDA, 0x00, 0x27, 0x71, 0xE0,
+ 0xD4, 0xF8, 0xB0, 0x23, 0x08, 0xFA, 0x07, 0xF1, 0x40, 0x46, 0x0A, 0x42, 0x69, 0xD0, 0xD4, 0xF8,
+ 0xBC, 0x23, 0x0A, 0x42, 0x65, 0xD1, 0xC7, 0xEB, 0xC7, 0x01, 0x01, 0xEB, 0x41, 0x01, 0x05, 0xEB,
+ 0x01, 0x1B, 0x9B, 0xF8, 0x3E, 0x11, 0x02, 0x29, 0x01, 0xD0, 0x01, 0x29, 0x59, 0xD1, 0x9B, 0xF8,
+ 0x44, 0x11, 0x00, 0xFA, 0x01, 0xF2, 0x12, 0xEA, 0x09, 0x0F, 0x24, 0xD0, 0x1A, 0xF8, 0x01, 0x00,
+ 0xB8, 0x42, 0x4E, 0xD0, 0xC0, 0xEB, 0xC0, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x05, 0xEB, 0x00, 0x16,
+ 0x30, 0x46, 0x59, 0x46, 0x0A, 0xE0, 0x00, 0x00, 0xE0, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xEC, 0x06, 0x10, 0x00, 0x70, 0x25, 0x10, 0x00, 0x52, 0x6C, 0x01, 0x00, 0xFF, 0xF7, 0x31, 0xFF,
+ 0x01, 0x28, 0x36, 0xD1, 0x30, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0x0F, 0xFF, 0x59, 0x46, 0x28, 0x46,
+ 0x00, 0xF0, 0xA0, 0xFF, 0x2D, 0xE0, 0x0B, 0xF1, 0x5A, 0x01, 0x00, 0x26, 0x01, 0x91, 0x24, 0xE0,
+ 0xD4, 0xF8, 0xBC, 0x13, 0x08, 0xFA, 0x06, 0xF0, 0x01, 0x42, 0x1D, 0xD0, 0xC6, 0xEB, 0xC6, 0x00,
+ 0x00, 0xEB, 0x40, 0x00, 0x05, 0xEB, 0x00, 0x10, 0x05, 0xEB, 0x86, 0x01, 0x00, 0x90, 0x01, 0xF5,
+ 0x9E, 0x51, 0x01, 0x98, 0x03, 0xF0, 0x9A, 0xF9, 0x01, 0x28, 0x0D, 0xD1, 0x59, 0x46, 0x00, 0x98,
+ 0xFF, 0xF7, 0x07, 0xFF, 0x01, 0x28, 0x07, 0xD1, 0x59, 0x46, 0x00, 0x98, 0xFF, 0xF7, 0xE5, 0xFE,
+ 0x59, 0x46, 0x28, 0x46, 0x00, 0xF0, 0x76, 0xFF, 0x76, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xB0, 0x42,
+ 0xD6, 0xDA, 0x7F, 0x1C, 0x94, 0xF9, 0xB8, 0x03, 0xB8, 0x42, 0x89, 0xDA, 0x28, 0xE7, 0x2D, 0xE9,
+ 0xF0, 0x47, 0x04, 0x46, 0x91, 0x42, 0x56, 0xD0, 0x07, 0xD9, 0x01, 0xEB, 0x02, 0x00, 0xA0, 0xEB,
+ 0x02, 0x01, 0xCA, 0xB2, 0xA0, 0xEB, 0x02, 0x00, 0xC1, 0xB2, 0x01, 0xEB, 0xC1, 0x00, 0x04, 0xEB,
+ 0xC0, 0x01, 0x02, 0xEB, 0xC2, 0x00, 0x04, 0xEB, 0xC0, 0x00, 0xB1, 0xF9, 0x32, 0x50, 0xB0, 0xF9,
+ 0x32, 0x30, 0x81, 0x46, 0x9D, 0x42, 0x00, 0xDA, 0x4B, 0x86, 0xCB, 0x8C, 0xC5, 0x8C, 0x2B, 0x44,
+ 0xCB, 0x84, 0x0B, 0x8D, 0x05, 0x8D, 0x2B, 0x44, 0x0B, 0x85, 0x8B, 0x69, 0x85, 0x69, 0x2B, 0x44,
+ 0x8B, 0x61, 0xC7, 0x69, 0xCE, 0x69, 0xCB, 0x68, 0xD9, 0xF8, 0x0C, 0x00, 0x4F, 0xEA, 0x23, 0x4C,
+ 0x4F, 0xEA, 0x20, 0x48, 0x0C, 0xFB, 0x06, 0xFC, 0xF5, 0x19, 0x07, 0xFB, 0x08, 0xCC, 0x9C, 0xFB,
+ 0xF5, 0xFC, 0x6C, 0xF3, 0x1F, 0x43, 0x0F, 0xFA, 0x83, 0xFC, 0x0C, 0xFB, 0x06, 0xFC, 0x00, 0xB2,
+ 0x07, 0xFB, 0x00, 0xC0, 0x90, 0xFB, 0xF5, 0xF0, 0x60, 0xF3, 0x0F, 0x03, 0xCD, 0x61, 0xCB, 0x60,
+ 0x94, 0xF8, 0x38, 0x04, 0x41, 0x1E, 0x91, 0x42, 0x08, 0xD0, 0x00, 0xEB, 0xC0, 0x00, 0x04, 0xEB,
+ 0xC0, 0x01, 0x48, 0x46, 0x48, 0x22, 0x48, 0x39, 0x0D, 0xF0, 0xF1, 0xF9, 0x94, 0xF8, 0x38, 0x04,
+ 0x40, 0x1E, 0x84, 0xF8, 0x38, 0x04, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x5F, 0x16, 0x46,
+ 0x0F, 0x46, 0x82, 0x46, 0x01, 0x2B, 0x2C, 0xD1, 0x01, 0x20, 0xB2, 0x4A, 0x10, 0xE0, 0x00, 0xBF,
+ 0x17, 0xF8, 0x10, 0x10, 0x11, 0xB1, 0x49, 0x1E, 0x07, 0xF8, 0x10, 0x10, 0x07, 0xEB, 0x40, 0x04,
+ 0x11, 0x78, 0x63, 0x78, 0x49, 0x1E, 0x8B, 0x42, 0x01, 0xDA, 0x5B, 0x1C, 0x63, 0x70, 0x40, 0x1C,
+ 0x39, 0x7E, 0x81, 0x42, 0xEC, 0xD2, 0x01, 0x20, 0xA7, 0x4B, 0x0F, 0xE0, 0x16, 0xF8, 0x10, 0x10,
+ 0x11, 0xB1, 0x49, 0x1E, 0x06, 0xF8, 0x10, 0x10, 0x06, 0xEB, 0x40, 0x02, 0x1C, 0x78, 0x51, 0x78,
+ 0x64, 0x1E, 0xA1, 0x42, 0x01, 0xDA, 0x49, 0x1C, 0x51, 0x70, 0x40, 0x1C, 0x31, 0x7E, 0x81, 0x42,
+ 0xEC, 0xD2, 0x9E, 0x48, 0x4F, 0xF0, 0x01, 0x09, 0xCB, 0x46, 0x00, 0x68, 0xB0, 0xF8, 0x8E, 0x02,
+ 0x40, 0x43, 0x03, 0x90, 0x00, 0x20, 0x01, 0x90, 0x62, 0xE0, 0x01, 0x20, 0x5A, 0xE0, 0x00, 0x20,
+ 0x00, 0x90, 0x9A, 0xF8, 0x38, 0x04, 0x06, 0xEB, 0x48, 0x03, 0x07, 0xEB, 0x49, 0x02, 0x19, 0xE0,
+ 0x00, 0xEB, 0xC0, 0x04, 0x0A, 0xEB, 0xC4, 0x01, 0x16, 0xF8, 0x18, 0x50, 0x11, 0xF8, 0x3E, 0x4F,
+ 0xAC, 0x42, 0x0F, 0xD3, 0x5D, 0x78, 0xAC, 0x42, 0x0C, 0xD8, 0x49, 0x78, 0x17, 0xF8, 0x19, 0x40,
+ 0xA1, 0x42, 0x07, 0xD3, 0x54, 0x78, 0xA1, 0x42, 0x04, 0xD8, 0x00, 0x9C, 0x0B, 0xFA, 0x00, 0xF1,
+ 0x21, 0x43, 0x00, 0x91, 0x40, 0x1E, 0xE3, 0xD2, 0x04, 0x21, 0x68, 0x46, 0x0B, 0xF0, 0x7A, 0xFE,
+ 0x01, 0x28, 0x2D, 0xDD, 0x00, 0x24, 0x58, 0x46, 0x00, 0x99, 0x01, 0xE0, 0x64, 0x1C, 0xE4, 0xB2,
+ 0x00, 0xFA, 0x04, 0xF2, 0x0A, 0x42, 0xF9, 0xD0, 0x04, 0xEB, 0xC4, 0x00, 0x0A, 0xEB, 0xC0, 0x00,
+ 0x9A, 0xF8, 0x38, 0x54, 0x0C, 0x30, 0x02, 0x90, 0x17, 0xE0, 0x00, 0xBF, 0x00, 0x99, 0x0B, 0xFA,
+ 0x05, 0xF0, 0x08, 0x42, 0x11, 0xD0, 0x05, 0xEB, 0xC5, 0x02, 0x0A, 0xEB, 0xC2, 0x01, 0x0C, 0x31,
+ 0x02, 0x98, 0x07, 0xF0, 0x3E, 0xFF, 0x03, 0x99, 0x88, 0x42, 0x06, 0xD2, 0xEA, 0xB2, 0x21, 0x46,
+ 0x50, 0x46, 0xFF, 0xF7, 0x0C, 0xFF, 0x01, 0x20, 0x01, 0x90, 0x6D, 0x1E, 0xA5, 0x42, 0xE5, 0xD8,
+ 0x08, 0xF1, 0x01, 0x00, 0x31, 0x7E, 0x80, 0x46, 0x41, 0x45, 0xA0, 0xD2, 0x09, 0xF1, 0x01, 0x09,
+ 0x39, 0x7E, 0x49, 0x45, 0x99, 0xD2, 0x01, 0x98, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x9F, 0x64, 0x48,
+ 0x10, 0xB5, 0x40, 0x78, 0x0C, 0x46, 0x00, 0x28, 0x52, 0xD0, 0x62, 0x48, 0x00, 0x78, 0x00, 0x28,
+ 0x4E, 0xD1, 0x61, 0x48, 0x00, 0x78, 0x00, 0x28, 0x4A, 0xD1, 0x5C, 0x48, 0x94, 0xF8, 0x38, 0x24,
+ 0x00, 0x68, 0x90, 0xF8, 0x89, 0x12, 0x8A, 0x42, 0x42, 0xD8, 0x00, 0x23, 0x09, 0xE0, 0x00, 0xBF,
+ 0x02, 0xEB, 0xC2, 0x01, 0x04, 0xEB, 0xC1, 0x01, 0xB1, 0xF9, 0x32, 0x10, 0x99, 0x42, 0x00, 0xDD,
+ 0x0B, 0x46, 0x52, 0x1E, 0xF4, 0xD2, 0x55, 0x49, 0x0B, 0x80, 0xB0, 0xF8, 0x8A, 0x12, 0x99, 0x42,
+ 0x2E, 0xDB, 0xB0, 0xF9, 0x8C, 0x12, 0x00, 0x22, 0x51, 0x48, 0xFB, 0xF7, 0x78, 0xFE, 0x50, 0x4A,
+ 0xD2, 0xE9, 0x00, 0x10, 0x01, 0x43, 0x23, 0xD0, 0xD2, 0xE9, 0x02, 0x01, 0x08, 0x43, 0x1F, 0xD0,
+ 0xA2, 0xF1, 0x40, 0x01, 0x01, 0x23, 0xA1, 0xF1, 0x40, 0x00, 0xFB, 0xF7, 0x41, 0xFB, 0x48, 0x48,
+ 0x80, 0x38, 0x00, 0x7E, 0x00, 0x28, 0x13, 0xD0, 0x45, 0x49, 0x40, 0x39, 0x09, 0x7E, 0x00, 0x29,
+ 0x0E, 0xD0, 0x48, 0x43, 0x94, 0xF8, 0x38, 0x14, 0x00, 0x23, 0x88, 0x42, 0x00, 0xD2, 0x01, 0x23,
+ 0x3F, 0x4A, 0x20, 0x46, 0x40, 0x3A, 0xBD, 0xE8, 0x10, 0x40, 0xA2, 0xF1, 0x40, 0x01, 0xFC, 0xE6,
+ 0x10, 0xBD, 0x3A, 0x49, 0x00, 0x20, 0xC8, 0x60, 0x39, 0x48, 0x0F, 0x21, 0x10, 0x30, 0x0D, 0xF0,
+ 0x3A, 0xB9, 0x90, 0xF8, 0x42, 0x00, 0x40, 0x07, 0x01, 0xD5, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20,
+ 0x70, 0x47, 0x90, 0xF8, 0x3E, 0x01, 0x01, 0x28, 0x00, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x90, 0xF8,
+ 0x3E, 0x01, 0x02, 0x28, 0x05, 0xD0, 0x03, 0x28, 0x03, 0xD0, 0x04, 0x28, 0x01, 0xD0, 0x00, 0x20,
+ 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x90, 0xF8, 0x42, 0x10, 0x49, 0x06, 0x03, 0xD5,
+ 0xFF, 0xF7, 0xED, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x91, 0xF8, 0x3E, 0x21,
+ 0x01, 0x2A, 0x08, 0xD0, 0x02, 0x2A, 0x06, 0xD0, 0x06, 0x20, 0x81, 0xF8, 0x3E, 0x01, 0x00, 0x20,
+ 0x81, 0xF8, 0x43, 0x01, 0x70, 0x47, 0x00, 0xF0, 0xCD, 0xBD, 0xF0, 0xB5, 0x91, 0xF9, 0x49, 0x61,
+ 0x93, 0xF9, 0x00, 0x40, 0x92, 0xF9, 0x49, 0x51, 0x77, 0x1C, 0x02, 0xD0, 0x6D, 0x1C, 0x15, 0xD0,
+ 0x0B, 0xE0, 0x6E, 0x1C, 0x0B, 0xD0, 0x00, 0xEB, 0x85, 0x02, 0x00, 0xEB, 0x84, 0x00, 0xD2, 0x6B,
+ 0xC2, 0xF8, 0x4C, 0x11, 0xC1, 0x63, 0x81, 0xF8, 0x49, 0x41, 0x1C, 0x70, 0xF0, 0xBD, 0x64, 0x1C,
+ 0x64, 0xB2, 0x40, 0xF8, 0x24, 0x10, 0x81, 0xF8, 0x49, 0x41, 0x02, 0xE0, 0x00, 0xEB, 0x86, 0x01,
+ 0xC9, 0x6B, 0x00, 0xEB, 0x84, 0x00, 0xC1, 0xF8, 0x4C, 0x21, 0xC2, 0x63, 0x82, 0xF8, 0x49, 0x41,
+ 0xEB, 0xE7, 0x00, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xEC, 0x06, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xE0, 0x05, 0x10, 0x00,
+ 0x60, 0x25, 0x10, 0x00, 0xF0, 0xB5, 0x44, 0x88, 0x4E, 0x88, 0x01, 0x25, 0xA4, 0x1B, 0x24, 0xB2,
+ 0x00, 0x2C, 0x01, 0xDB, 0x26, 0x46, 0x00, 0xE0, 0x66, 0x42, 0x5E, 0x80, 0x56, 0x42, 0x94, 0x42,
+ 0x02, 0xDD, 0x44, 0x88, 0xA4, 0x1A, 0x03, 0xE0, 0xB4, 0x42, 0x03, 0xDA, 0x44, 0x88, 0x14, 0x44,
+ 0x4C, 0x80, 0x00, 0x25, 0x04, 0x88, 0x0F, 0x88, 0xE4, 0x1B, 0x24, 0xB2, 0x00, 0x2C, 0x01, 0xDB,
+ 0x27, 0x46, 0x00, 0xE0, 0x67, 0x42, 0x1F, 0x80, 0x94, 0x42, 0x02, 0xDD, 0x00, 0x88, 0x80, 0x1A,
+ 0x03, 0xE0, 0xB4, 0x42, 0x03, 0xDA, 0x00, 0x88, 0x10, 0x44, 0x08, 0x80, 0x00, 0x25, 0x28, 0x46,
+ 0xF0, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x96, 0x4D, 0x0F, 0x46, 0x06, 0x46, 0x81, 0x89, 0x28, 0x68,
+ 0x90, 0x46, 0xF9, 0xB1, 0x90, 0xF8, 0xCC, 0x43, 0x0D, 0xF0, 0x3E, 0xF9, 0x18, 0xB1, 0x28, 0x68,
+ 0x90, 0xF8, 0xCE, 0x43, 0x12, 0xE0, 0xB0, 0x7D, 0x02, 0x28, 0x04, 0xD0, 0x01, 0x28, 0x06, 0xD0,
+ 0x03, 0x28, 0x08, 0xD0, 0x0A, 0xE0, 0x28, 0x68, 0x90, 0xF8, 0xD3, 0x43, 0x06, 0xE0, 0x28, 0x68,
+ 0x90, 0xF8, 0x53, 0x44, 0x02, 0xE0, 0x28, 0x68, 0x90, 0xF8, 0x2C, 0x44, 0xB0, 0x89, 0x40, 0x1E,
+ 0xB0, 0x81, 0x11, 0xE0, 0xB1, 0x7D, 0x90, 0xF8, 0xD0, 0x43, 0x02, 0x29, 0x04, 0xD0, 0x01, 0x29,
+ 0x05, 0xD0, 0x03, 0x29, 0x06, 0xD0, 0x07, 0xE0, 0x90, 0xF8, 0xD3, 0x43, 0x04, 0xE0, 0x90, 0xF8,
+ 0x54, 0x44, 0x01, 0xE0, 0x90, 0xF8, 0x2D, 0x44, 0x29, 0x68, 0xB2, 0x7D, 0x91, 0xF8, 0xCF, 0x03,
+ 0x02, 0x2A, 0x04, 0xD0, 0x01, 0x2A, 0x05, 0xD0, 0x03, 0x2A, 0x06, 0xD0, 0x07, 0xE0, 0x91, 0xF8,
+ 0xD2, 0x03, 0x04, 0xE0, 0x91, 0xF8, 0x55, 0x04, 0x01, 0xE0, 0x91, 0xF8, 0x2E, 0x04, 0x38, 0x80,
+ 0xA8, 0xF8, 0x00, 0x40, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0xF1, 0x5E, 0x04,
+ 0x85, 0xB0, 0x4F, 0xF0, 0x00, 0x0B, 0x84, 0xF8, 0x15, 0xB0, 0xDF, 0xF8, 0xA4, 0x91, 0x0E, 0x46,
+ 0x80, 0xF8, 0x74, 0xB0, 0x05, 0x46, 0xB0, 0xF8, 0x42, 0x10, 0x4F, 0xF0, 0x01, 0x08, 0xD9, 0xF8,
+ 0x00, 0x00, 0x4A, 0x06, 0xC2, 0x46, 0x01, 0xD5, 0x02, 0x21, 0x0F, 0xE0, 0x0A, 0x07, 0x06, 0xD5,
+ 0x90, 0xF8, 0x40, 0x24, 0x52, 0x06, 0x02, 0xD5, 0x84, 0xF8, 0x16, 0xA0, 0x07, 0xE0, 0x90, 0xF8,
+ 0x20, 0x24, 0x92, 0x07, 0x03, 0xD5, 0x09, 0x06, 0x01, 0xD5, 0x03, 0x21, 0xA1, 0x75, 0x95, 0xF8,
+ 0x3E, 0x11, 0x03, 0x29, 0x09, 0xD0, 0xA2, 0x7C, 0x01, 0x2A, 0x06, 0xD0, 0x04, 0x29, 0x2D, 0xD0,
+ 0x07, 0x29, 0x2B, 0xD0, 0x08, 0x29, 0x76, 0xD0, 0x9C, 0xE0, 0x90, 0xF8, 0xCB, 0x73, 0x0D, 0xF0,
+ 0xBB, 0xF8, 0x18, 0xB1, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xCD, 0x73, 0x95, 0xF8, 0x3E, 0x01,
+ 0x03, 0x28, 0x00, 0xD0, 0x00, 0x27, 0xA0, 0x7D, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x28, 0x05, 0xD0,
+ 0x08, 0xE0, 0xD9, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x52, 0x74, 0x03, 0xE0, 0xD9, 0xF8, 0x00, 0x00,
+ 0x90, 0xF8, 0x2B, 0x74, 0xA7, 0x81, 0x31, 0x68, 0x21, 0x60, 0x31, 0x68, 0x61, 0x60, 0x84, 0xF8,
+ 0x14, 0xA0, 0x84, 0xF8, 0x13, 0xA0, 0x84, 0xF8, 0x12, 0xB0, 0x73, 0xE0, 0x02, 0xAA, 0x01, 0xA9,
+ 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFF, 0x03, 0xAB, 0xBD, 0xF9, 0x08, 0x20, 0x21, 0x46, 0x30, 0x46,
+ 0xFF, 0xF7, 0x10, 0xFF, 0x83, 0x46, 0x04, 0xAB, 0xBD, 0xF9, 0x04, 0x20, 0x21, 0x1D, 0x30, 0x46,
+ 0xFF, 0xF7, 0x08, 0xFF, 0x07, 0x46, 0xBB, 0xF1, 0x01, 0x0F, 0x03, 0xD0, 0x20, 0x7D, 0x01, 0x28,
+ 0x4D, 0xD0, 0x4E, 0xE0, 0xBD, 0xF9, 0x0C, 0x00, 0xBD, 0xF9, 0x0E, 0x10, 0x81, 0x42, 0x00, 0xDD,
+ 0x08, 0x46, 0xD9, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xD1, 0x23, 0x02, 0xF0, 0x0F, 0x03, 0x4F, 0xEA,
+ 0x12, 0x1C, 0xA2, 0x7D, 0x02, 0x2A, 0x04, 0xD0, 0x01, 0x2A, 0x05, 0xD0, 0x03, 0x2A, 0x06, 0xD0,
+ 0x0B, 0xE0, 0x91, 0xF8, 0xD4, 0x13, 0x04, 0xE0, 0x91, 0xF8, 0x56, 0x14, 0x01, 0xE0, 0x91, 0xF8,
+ 0x2F, 0x14, 0x01, 0xF0, 0x0F, 0x03, 0x4F, 0xEA, 0x11, 0x1C, 0x01, 0x2F, 0x0C, 0xD0, 0xCD, 0xF8,
+ 0x00, 0xC0, 0xBD, 0xF9, 0x08, 0x20, 0xBD, 0xF9, 0x04, 0x10, 0x07, 0xF0, 0x30, 0xFD, 0x21, 0x7D,
+ 0x01, 0x29, 0x0D, 0xD0, 0x18, 0xE0, 0x23, 0xE0, 0xA0, 0x68, 0x30, 0x60, 0xD9, 0xF8, 0x00, 0x00,
+ 0x90, 0xF8, 0x80, 0x03, 0x00, 0x06, 0x01, 0xD4, 0x4F, 0xF0, 0x00, 0x08, 0x60, 0x46, 0xEE, 0xE7,
+ 0x95, 0xF8, 0x41, 0x11, 0x41, 0xB9, 0xD9, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xBC, 0x13, 0x0A, 0x09,
+ 0xD4, 0xF8, 0x0E, 0x10, 0x07, 0xF0, 0x28, 0xFD, 0xC4, 0xF8, 0x0E, 0x00, 0x01, 0xE0, 0x84, 0xF8,
+ 0x15, 0xA0, 0x84, 0xF8, 0x14, 0xB0, 0xE7, 0x74, 0xB8, 0xF1, 0x00, 0x0F, 0x02, 0xD1, 0x03, 0xE0,
+ 0xA0, 0x68, 0x30, 0x60, 0x30, 0x68, 0xA0, 0x60, 0x05, 0xB0, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x8F,
+ 0x20, 0x07, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x17, 0x46, 0x06, 0x46, 0xDD, 0xE9, 0x06, 0xC2,
+ 0xC8, 0x78, 0x00, 0x25, 0x0C, 0x46, 0x03, 0x28, 0x30, 0xD2, 0xFE, 0x48, 0xDF, 0xF8, 0xF8, 0xE3,
+ 0x01, 0x68, 0x91, 0xF8, 0x0A, 0x14, 0xA1, 0x70, 0xDE, 0xF8, 0x04, 0xE0, 0xBE, 0xF1, 0x00, 0x0F,
+ 0x06, 0xDD, 0xD0, 0xF8, 0x00, 0xE0, 0x9E, 0xF8, 0x0B, 0xE4, 0xA1, 0xEB, 0x0E, 0x01, 0xA1, 0x70,
+ 0x00, 0x68, 0x71, 0x6B, 0xB0, 0xF8, 0x0C, 0x04, 0x81, 0x42, 0x15, 0xDD, 0xDB, 0xB2, 0x39, 0x46,
+ 0x60, 0x46, 0x00, 0xF0, 0xE8, 0xFA, 0xE0, 0x78, 0x40, 0x1C, 0xC0, 0xB2, 0xE0, 0x70, 0x03, 0x28,
+ 0x06, 0xD0, 0xEE, 0x49, 0xB6, 0xF9, 0x56, 0x00, 0xB1, 0xF9, 0x00, 0x10, 0x88, 0x42, 0x05, 0xDD,
+ 0x03, 0x20, 0xE0, 0x70, 0x01, 0x25, 0x01, 0xE0, 0x00, 0x20, 0xE0, 0x70, 0x28, 0x46, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x5F, 0x4F, 0xF0, 0x00, 0x0B, 0x0C, 0x46, 0x81, 0x46, 0x5D, 0x46,
+ 0x4F, 0xF0, 0x02, 0x0A, 0x01, 0x26, 0x00, 0xF5, 0x80, 0x57, 0x7C, 0xE0, 0xD7, 0xF8, 0xB0, 0x03,
+ 0x06, 0xFA, 0x05, 0xFE, 0x10, 0xEA, 0x0E, 0x0F, 0x74, 0xD0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB,
+ 0x40, 0x01, 0x09, 0xEB, 0x01, 0x10, 0x00, 0xF5, 0x9A, 0x71, 0x90, 0xF8, 0x3E, 0x81, 0xB0, 0xF9,
+ 0x0C, 0xC0, 0xB8, 0xF1, 0x01, 0x0F, 0x0F, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0x0C, 0xD0, 0x90, 0xF8,
+ 0x42, 0x00, 0x40, 0x07, 0x51, 0xD5, 0xD2, 0x48, 0xEB, 0xB2, 0x61, 0x46, 0xB0, 0xF9, 0x08, 0x20,
+ 0x20, 0x46, 0x00, 0xF0, 0xA0, 0xFA, 0x55, 0xE0, 0xCE, 0x4B, 0xB0, 0xF9, 0x54, 0x20, 0xB3, 0xF9,
+ 0x00, 0x30, 0x9A, 0x42, 0x4E, 0xDB, 0xB8, 0xF1, 0x01, 0x0F, 0x03, 0xD1, 0x00, 0x22, 0x0A, 0x60,
+ 0x4A, 0x60, 0x0A, 0x81, 0xC6, 0x4A, 0xB2, 0xF9, 0x00, 0x30, 0x63, 0x45, 0x03, 0xDC, 0xB2, 0xF9,
+ 0x02, 0x30, 0x63, 0x45, 0x0C, 0xDA, 0xB0, 0xF8, 0x42, 0x30, 0x43, 0xF0, 0x04, 0x03, 0xA0, 0xF8,
+ 0x42, 0x30, 0xC3, 0x68, 0x4B, 0x60, 0x81, 0xF8, 0x08, 0xA0, 0xB2, 0xF9, 0x00, 0x20, 0x19, 0xE0,
+ 0xB2, 0xF9, 0x08, 0x30, 0x63, 0x45, 0x03, 0xDC, 0xB2, 0xF9, 0x0A, 0x30, 0x63, 0x45, 0x19, 0xDA,
+ 0xB0, 0xF8, 0x42, 0x30, 0x43, 0xF0, 0x04, 0x03, 0xA0, 0xF8, 0x42, 0x30, 0x90, 0xF8, 0x3E, 0x31,
+ 0x01, 0x2B, 0x02, 0xD0, 0x0B, 0x7A, 0x02, 0x2B, 0x01, 0xD1, 0xC3, 0x68, 0x4B, 0x60, 0x0E, 0x72,
+ 0xB2, 0xF9, 0x08, 0x20, 0x2B, 0x46, 0xCD, 0xE9, 0x00, 0x42, 0x62, 0x46, 0xFF, 0xF7, 0x4A, 0xFF,
+ 0x83, 0x46, 0x0F, 0xE0, 0x00, 0x20, 0x08, 0x72, 0x08, 0xE0, 0xA9, 0x48, 0xB0, 0xF9, 0x08, 0x10,
+ 0x61, 0x45, 0x07, 0xDA, 0xB0, 0xF9, 0x0A, 0x00, 0x60, 0x45, 0x03, 0xDD, 0xA0, 0x68, 0x40, 0xEA,
+ 0x0E, 0x00, 0xA0, 0x60, 0x6D, 0x1C, 0x97, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0xBF, 0xF6, 0x7E, 0xAF,
+ 0x20, 0x68, 0x61, 0x68, 0x9C, 0x4A, 0x50, 0xEA, 0x01, 0x03, 0xA3, 0x68, 0x01, 0xD0, 0x23, 0xB1,
+ 0x04, 0xE0, 0x1B, 0xB1, 0x82, 0xF8, 0x00, 0xA0, 0x00, 0xE0, 0x16, 0x70, 0x98, 0x4A, 0x18, 0x32,
+ 0x13, 0x68, 0x98, 0x43, 0x20, 0x60, 0x50, 0x68, 0x81, 0x43, 0x61, 0x60, 0x96, 0x49, 0xA0, 0x68,
+ 0x09, 0x78, 0x08, 0x43, 0x05, 0xD1, 0x92, 0x49, 0x18, 0x22, 0x18, 0x39, 0x90, 0x48, 0x0C, 0xF0,
+ 0x1E, 0xFE, 0x58, 0x46, 0xBD, 0xE8, 0xFC, 0x9F, 0x8B, 0x4A, 0x10, 0xB5, 0x12, 0x78, 0x00, 0x21,
+ 0x01, 0x2A, 0x01, 0xD1, 0x03, 0xB1, 0x01, 0x21, 0x90, 0xF8, 0x3E, 0x21, 0x04, 0x2A, 0x18, 0xD1,
+ 0x84, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x00, 0x34, 0x5B, 0x07, 0x12, 0xD5, 0xB0, 0xF8, 0x4A, 0x30,
+ 0xB0, 0xF8, 0x4C, 0x40, 0x1B, 0x1B, 0x82, 0x4C, 0xA4, 0x8A, 0xA3, 0x42, 0x09, 0xDD, 0x90, 0xF8,
+ 0x5B, 0x30, 0x90, 0xF8, 0x5A, 0x00, 0x92, 0xF8, 0x09, 0x24, 0x18, 0x1A, 0x90, 0x42, 0x00, 0xDD,
+ 0x01, 0x21, 0x08, 0x46, 0x10, 0xBD, 0x30, 0xB5, 0x79, 0x4D, 0x00, 0x24, 0x18, 0x35, 0x09, 0xB1,
+ 0x29, 0x68, 0x11, 0xB9, 0x12, 0xB1, 0x69, 0x68, 0x01, 0xB1, 0x01, 0x24, 0x72, 0x49, 0x09, 0x78,
+ 0x01, 0x29, 0x01, 0xD1, 0x03, 0xB1, 0x01, 0x24, 0x6E, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x00, 0x24,
+ 0x52, 0x07, 0x16, 0xD5, 0x90, 0xF8, 0x3E, 0x21, 0x04, 0x2A, 0x12, 0xD1, 0xB0, 0xF8, 0x4A, 0x20,
+ 0xB0, 0xF8, 0x4C, 0x30, 0xD2, 0x1A, 0x6A, 0x4B, 0x9B, 0x8A, 0x9A, 0x42, 0x09, 0xDD, 0x90, 0xF8,
+ 0x5B, 0x20, 0x90, 0xF8, 0x5A, 0x00, 0x91, 0xF8, 0x09, 0x14, 0x10, 0x1A, 0x88, 0x42, 0x00, 0xDD,
+ 0x01, 0x24, 0x20, 0x46, 0x30, 0xBD, 0x2D, 0xE9, 0xF3, 0x4F, 0x8D, 0xB0, 0x5E, 0x48, 0x00, 0x25,
+ 0x8B, 0x46, 0x0A, 0x95, 0x01, 0x78, 0x5E, 0x48, 0x18, 0x38, 0x01, 0x29, 0x06, 0xD1, 0xDB, 0xF8,
+ 0x08, 0x10, 0x19, 0xB1, 0xD0, 0xF8, 0x1C, 0x80, 0x47, 0x6A, 0x02, 0xE0, 0xD0, 0xF8, 0x18, 0x80,
+ 0x07, 0x6A, 0x0D, 0x9E, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x09, 0x06, 0xF5, 0x80, 0x56, 0x0F, 0xE1,
+ 0x09, 0xFA, 0x04, 0xF0, 0xD6, 0xF8, 0xB0, 0x13, 0x0B, 0x90, 0x01, 0x42, 0x1A, 0xD0, 0xC4, 0xEB,
+ 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x0D, 0x98, 0x00, 0xEB, 0x01, 0x1A, 0x9A, 0xF8, 0x42, 0x00,
+ 0x40, 0x07, 0x0F, 0xD5, 0x0A, 0xF5, 0x9A, 0x70, 0x01, 0x90, 0xBA, 0xF9, 0x0C, 0x00, 0x02, 0x90,
+ 0x9A, 0xF8, 0x3E, 0x01, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x1F, 0xD0,
+ 0x05, 0x28, 0x7D, 0xD0, 0xEB, 0xE0, 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x04, 0x20, 0xDB, 0xF8,
+ 0x08, 0x30, 0x50, 0x46, 0xFF, 0xF7, 0x60, 0xFF, 0x01, 0x28, 0x02, 0xD1, 0x01, 0x99, 0x81, 0xF8,
+ 0x01, 0x90, 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x04, 0x20, 0xDB, 0xF8, 0x08, 0x30, 0x50, 0x46,
+ 0xFF, 0xF7, 0x79, 0xFF, 0x01, 0x28, 0xE5, 0xD1, 0x01, 0x99, 0x00, 0x20, 0x88, 0x70, 0xCE, 0xE0,
+ 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x04, 0x20, 0xDB, 0xF8, 0x08, 0x30, 0x50, 0x46, 0xFF, 0xF7,
+ 0x6A, 0xFF, 0x01, 0x28, 0x09, 0xD0, 0x01, 0x98, 0x80, 0x78, 0x48, 0xB1, 0x01, 0x99, 0x40, 0x1E,
+ 0x10, 0xF0, 0xFF, 0x00, 0x88, 0x70, 0x03, 0xD0, 0x07, 0xE0, 0x01, 0x99, 0x00, 0x20, 0x88, 0x70,
+ 0x9A, 0xF8, 0x46, 0x11, 0x09, 0xFA, 0x01, 0xF0, 0x05, 0x43, 0xDB, 0xF8, 0x00, 0x10, 0xDB, 0xF8,
+ 0x04, 0x20, 0xDB, 0xF8, 0x08, 0x30, 0x50, 0x46, 0xFF, 0xF7, 0x26, 0xFF, 0x01, 0x28, 0x02, 0xD1,
+ 0x01, 0x99, 0x81, 0xF8, 0x01, 0x90, 0x01, 0x98, 0xC0, 0x78, 0x03, 0x28, 0x1D, 0xD2, 0x01, 0x99,
+ 0x89, 0x78, 0xD1, 0xB1, 0x17, 0x49, 0xDA, 0xF8, 0x34, 0x20, 0x09, 0x68, 0xB1, 0xF8, 0x0C, 0x14,
+ 0x8A, 0x42, 0x0F, 0xDD, 0x40, 0x1C, 0x01, 0x99, 0xC0, 0xB2, 0x03, 0x28, 0xC8, 0x70, 0x06, 0xD0,
+ 0x12, 0x49, 0xBA, 0xF9, 0x56, 0x00, 0xB1, 0xF9, 0x00, 0x10, 0x88, 0x42, 0x05, 0xDD, 0x01, 0x20,
+ 0x0A, 0x90, 0x02, 0xE0, 0x01, 0x99, 0x00, 0x20, 0xC8, 0x70, 0x02, 0x98, 0x0F, 0xFA, 0x88, 0xF2,
+ 0x82, 0x42, 0x04, 0xDC, 0x02, 0x98, 0x4F, 0xEA, 0x28, 0x41, 0x81, 0x42, 0x16, 0xDA, 0x01, 0x98,
+ 0x02, 0x21, 0xE3, 0xB2, 0x01, 0x72, 0x01, 0x98, 0xDA, 0xF8, 0x0C, 0x10, 0x41, 0x60, 0x37, 0xE0,
+ 0x56, 0xE0, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00, 0xF0, 0x05, 0x10, 0x00, 0x68, 0x06, 0x10, 0x00,
+ 0x98, 0x25, 0x10, 0x00, 0x7C, 0x06, 0x10, 0x00, 0xF3, 0x06, 0x10, 0x00, 0x38, 0xB2, 0x02, 0x99,
+ 0x04, 0x90, 0x88, 0x42, 0x03, 0xDC, 0x02, 0x98, 0x39, 0x14, 0x81, 0x42, 0x25, 0xDA, 0x01, 0x98,
+ 0x00, 0x7A, 0x02, 0x28, 0x06, 0xD1, 0x01, 0x99, 0x81, 0xF8, 0x08, 0x90, 0x01, 0x98, 0xDA, 0xF8,
+ 0x0C, 0x10, 0x41, 0x60, 0x01, 0x98, 0x40, 0x78, 0x80, 0xB9, 0x01, 0x98, 0x53, 0x46, 0x80, 0x78,
+ 0x00, 0x28, 0x82, 0x48, 0x02, 0x69, 0x04, 0xD0, 0x01, 0x98, 0x0A, 0xF1, 0x0C, 0x01, 0x00, 0x1D,
+ 0x02, 0xE0, 0x0A, 0xF1, 0x10, 0x01, 0x08, 0x1F, 0x00, 0xF0, 0xE2, 0xF8, 0x04, 0x9A, 0xE3, 0xB2,
+ 0x58, 0x46, 0x02, 0x99, 0x00, 0xF0, 0xCF, 0xF8, 0x31, 0xE0, 0xDB, 0xF8, 0x08, 0x00, 0x0B, 0x99,
+ 0x08, 0x43, 0xCB, 0xF8, 0x08, 0x00, 0x01, 0x98, 0x80, 0x78, 0x20, 0xB1, 0x01, 0x99, 0x00, 0x22,
+ 0x50, 0x46, 0x09, 0x1D, 0x03, 0xE0, 0x01, 0x22, 0x0A, 0xF1, 0x0C, 0x01, 0x50, 0x46, 0x00, 0xF0,
+ 0xA8, 0xF8, 0xBA, 0xF8, 0x42, 0x00, 0x20, 0xF0, 0x04, 0x01, 0xAA, 0xF8, 0x42, 0x10, 0x16, 0xE0,
+ 0x01, 0x98, 0x00, 0x7A, 0x01, 0x28, 0x12, 0xD1, 0x01, 0x98, 0x80, 0x78, 0x78, 0xB1, 0x01, 0x99,
+ 0x01, 0x22, 0x50, 0x46, 0x09, 0x1D, 0x00, 0xF0, 0x94, 0xF8, 0xBA, 0xF8, 0x42, 0x00, 0x20, 0xF0,
+ 0x04, 0x01, 0xAA, 0xF8, 0x42, 0x10, 0xBA, 0xF8, 0x56, 0x10, 0xAA, 0xF8, 0x54, 0x10, 0x64, 0x1C,
+ 0x96, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0xBF, 0xF6, 0xEB, 0xAE, 0x5D, 0x48, 0x00, 0x68, 0x90, 0xF8,
+ 0x00, 0x04, 0x80, 0x07, 0x02, 0xD5, 0x28, 0x46, 0xFB, 0xF7, 0xA7, 0xFF, 0x59, 0x48, 0x15, 0xB1,
+ 0x80, 0xF8, 0x00, 0x90, 0x01, 0xE0, 0x00, 0x21, 0x01, 0x70, 0x0A, 0x98, 0x0F, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0x53, 0x49, 0x0B, 0x68, 0x51, 0x49, 0x9A, 0x8E, 0x18, 0x39, 0x12, 0x1A, 0x08, 0x80,
+ 0x4A, 0x80, 0x93, 0xF8, 0x0F, 0x34, 0x18, 0x44, 0x88, 0x80, 0xD0, 0x1A, 0xC8, 0x80, 0x70, 0x47,
+ 0x4B, 0x49, 0x0B, 0x68, 0x49, 0x49, 0x9A, 0x8E, 0x18, 0x39, 0x12, 0x1A, 0x08, 0x81, 0x4A, 0x81,
+ 0x93, 0xF8, 0x12, 0x34, 0x18, 0x44, 0x88, 0x81, 0xD0, 0x1A, 0xC8, 0x81, 0x70, 0x47, 0x10, 0xB5,
+ 0x43, 0x4C, 0x20, 0x68, 0x90, 0xF8, 0x0E, 0x04, 0xFF, 0xF7, 0xDB, 0xFF, 0x20, 0x68, 0x90, 0xF8,
+ 0x0E, 0x04, 0xFF, 0xF7, 0xE5, 0xFF, 0x22, 0x68, 0x3C, 0x49, 0x92, 0xF8, 0x10, 0x04, 0x18, 0x39,
+ 0x40, 0x43, 0x08, 0x61, 0x92, 0xF8, 0x11, 0x04, 0x88, 0x82, 0x18, 0x22, 0x37, 0x48, 0x0C, 0xF0,
+ 0x46, 0xFC, 0x38, 0x49, 0x00, 0x20, 0x35, 0x4A, 0x08, 0x70, 0x37, 0x49, 0x18, 0x3A, 0x48, 0x60,
+ 0x10, 0x63, 0x50, 0x63, 0x90, 0x63, 0x35, 0x4A, 0x10, 0x70, 0x08, 0x70, 0x10, 0xBD, 0xFE, 0xB5,
+ 0x00, 0x24, 0x06, 0x46, 0x00, 0x94, 0x01, 0x94, 0x69, 0x46, 0x02, 0x94, 0xFF, 0xF7, 0x61, 0xFD,
+ 0x05, 0x46, 0x69, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x66, 0xFE, 0x40, 0xEA, 0x05, 0x01, 0x2A, 0x48,
+ 0x01, 0x29, 0x01, 0xD0, 0x41, 0x68, 0x05, 0xE0, 0x25, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x0A, 0x14,
+ 0x49, 0x1F, 0x41, 0x60, 0x00, 0x29, 0x04, 0xDD, 0x49, 0x1E, 0x41, 0x60, 0x21, 0x49, 0x09, 0x78,
+ 0x01, 0xB9, 0x44, 0x60, 0x1D, 0x48, 0x9D, 0xE8, 0x0E, 0x00, 0x18, 0x30, 0x80, 0xE8, 0x0E, 0x00,
+ 0xFE, 0xBD, 0x02, 0x23, 0x80, 0xF8, 0x3E, 0x31, 0x00, 0x23, 0x80, 0xF8, 0x42, 0x31, 0x01, 0x2A,
+ 0x05, 0xD0, 0x09, 0x68, 0x01, 0x62, 0x01, 0x21, 0x80, 0xF8, 0x34, 0x11, 0x70, 0x47, 0x03, 0x22,
+ 0x0C, 0x30, 0x07, 0xF0, 0xBB, 0xB9, 0x10, 0xB5, 0x01, 0x24, 0x9C, 0x40, 0x91, 0x42, 0x03, 0xDA,
+ 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0x10, 0xBD, 0x41, 0x68, 0x21, 0x43, 0x41, 0x60, 0x10, 0xBD,
+ 0x70, 0xB5, 0x15, 0x46, 0x0A, 0x46, 0x06, 0x46, 0x01, 0x46, 0x1C, 0x46, 0x10, 0x46, 0x07, 0xF0,
+ 0xC8, 0xF9, 0xA8, 0x42, 0x09, 0xDD, 0x00, 0x22, 0x31, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xD1, 0xFF,
+ 0x34, 0xF8, 0x42, 0x0F, 0x20, 0xF0, 0x04, 0x00, 0x20, 0x80, 0x70, 0xBD, 0x98, 0x25, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, 0xF0, 0x05, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00,
+ 0x10, 0xB5, 0x41, 0xF2, 0xA8, 0x41, 0x9F, 0x48, 0x0C, 0xF0, 0x25, 0xFC, 0x40, 0xF2, 0x3C, 0x41,
+ 0x9D, 0x48, 0x0C, 0xF0, 0x20, 0xFC, 0x9D, 0x48, 0xFF, 0x21, 0x80, 0xF8, 0xB8, 0x13, 0x00, 0xF0,
+ 0xFC, 0xFB, 0xFF, 0xF7, 0xD6, 0xFA, 0xFF, 0xF7, 0x5A, 0xFF, 0x00, 0xF0, 0x37, 0xF9, 0xFD, 0xF7,
+ 0x2B, 0xFA, 0xFD, 0xF7, 0x02, 0xFF, 0xFE, 0xF7, 0x87, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7,
+ 0x37, 0xBF, 0x70, 0xB5, 0x92, 0x4D, 0x00, 0x24, 0x8E, 0x48, 0xAC, 0x71, 0x00, 0xF0, 0xEB, 0xFB,
+ 0x90, 0x4E, 0x30, 0x68, 0x90, 0xF8, 0x40, 0x04, 0xC0, 0x06, 0x05, 0xD5, 0x8E, 0x48, 0x00, 0x79,
+ 0x10, 0xB1, 0x88, 0x48, 0xFF, 0xF7, 0x5F, 0xF8, 0x30, 0x68, 0x90, 0xF8, 0x00, 0x04, 0xC0, 0x07,
+ 0x05, 0xD0, 0x84, 0x48, 0xFF, 0xF7, 0x5B, 0xFF, 0x82, 0x48, 0x00, 0xF0, 0x10, 0xF9, 0x81, 0x48,
+ 0xFD, 0xF7, 0x0A, 0xFA, 0x7F, 0x48, 0xFD, 0xF7, 0xE6, 0xFE, 0x7F, 0x48, 0x80, 0xF8, 0x38, 0x44,
+ 0x7E, 0x48, 0xB0, 0xF8, 0xBC, 0x03, 0xA5, 0xF8, 0x1F, 0x00, 0x70, 0xBD, 0x70, 0xB5, 0x7A, 0x4D,
+ 0x7B, 0x4E, 0x95, 0xF8, 0x38, 0x04, 0xD8, 0xB3, 0x7A, 0x4C, 0xB0, 0x71, 0x20, 0x68, 0x90, 0xF8,
+ 0x80, 0x02, 0x80, 0x07, 0x03, 0xD5, 0x29, 0x46, 0x72, 0x48, 0xFF, 0xF7, 0x30, 0xFA, 0x72, 0x49,
+ 0x70, 0x48, 0x00, 0xF0, 0xE3, 0xFB, 0x20, 0x68, 0x90, 0xF8, 0x40, 0x04, 0xC0, 0x06, 0x05, 0xD5,
+ 0x71, 0x48, 0x00, 0x79, 0x10, 0xB1, 0x6B, 0x48, 0xFF, 0xF7, 0x25, 0xF8, 0x20, 0x68, 0x90, 0xF8,
+ 0x00, 0x04, 0xC0, 0x07, 0x02, 0xD0, 0x67, 0x48, 0xFF, 0xF7, 0x21, 0xFF, 0x20, 0x68, 0x90, 0xF8,
+ 0x80, 0x03, 0xC0, 0x07, 0x02, 0xD0, 0x63, 0x48, 0xFE, 0xF7, 0xAC, 0xFF, 0x61, 0x48, 0x00, 0xF0,
+ 0xCE, 0xF8, 0x60, 0x48, 0xFD, 0xF7, 0xC8, 0xF9, 0x5E, 0x48, 0xFD, 0xF7, 0xA4, 0xFE, 0x00, 0x20,
+ 0x85, 0xF8, 0x38, 0x04, 0x5D, 0x48, 0xB0, 0xF8, 0xBC, 0x03, 0xA6, 0xF8, 0x1F, 0x00, 0x70, 0xBD,
+ 0xFF, 0xE7, 0xFF, 0xF7, 0x8E, 0xFF, 0xF5, 0xE7, 0x10, 0xB5, 0x59, 0x48, 0x00, 0x24, 0x84, 0x71,
+ 0x54, 0x48, 0x00, 0xF0, 0x78, 0xFB, 0x53, 0x48, 0xFD, 0xF7, 0xAE, 0xF9, 0x51, 0x48, 0xFC, 0xF7,
+ 0xCA, 0xFE, 0x51, 0x48, 0x80, 0xF8, 0x38, 0x44, 0x10, 0xBD, 0x10, 0xB5, 0x4E, 0x4C, 0x94, 0xF8,
+ 0x38, 0x04, 0x90, 0xB1, 0x4E, 0x49, 0x88, 0x71, 0x21, 0x46, 0x4A, 0x48, 0x00, 0xF0, 0x96, 0xFB,
+ 0x48, 0x48, 0x00, 0xF0, 0x9C, 0xF8, 0x47, 0x48, 0xFD, 0xF7, 0x96, 0xF9, 0x45, 0x48, 0xFC, 0xF7,
+ 0xB2, 0xFE, 0x00, 0x20, 0x84, 0xF8, 0x38, 0x04, 0x10, 0xBD, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xE7,
+ 0x10, 0xB5, 0x41, 0x4C, 0x01, 0x46, 0x94, 0xF8, 0x38, 0x04, 0x0F, 0x28, 0x0B, 0xD2, 0x00, 0xEB,
+ 0xC0, 0x00, 0x04, 0xEB, 0xC0, 0x00, 0x48, 0x22, 0x0C, 0xF0, 0x01, 0xFB, 0x94, 0xF8, 0x38, 0x04,
+ 0x40, 0x1C, 0x84, 0xF8, 0x38, 0x04, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x00, 0x21,
+ 0xD0, 0xF8, 0xB0, 0x33, 0x01, 0x22, 0x00, 0xBF, 0x02, 0xFA, 0x01, 0xF4, 0x23, 0x42, 0x0B, 0xD1,
+ 0x8A, 0x40, 0x13, 0x43, 0xC0, 0xF8, 0xB0, 0x33, 0x90, 0xF9, 0xB8, 0x23, 0x8A, 0x42, 0x01, 0xDA,
+ 0x80, 0xF8, 0xB8, 0x13, 0x48, 0xB2, 0x10, 0xBD, 0x49, 0x1C, 0x0F, 0x29, 0xEC, 0xDB, 0x4F, 0xF0,
+ 0xFF, 0x30, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x91, 0xF8, 0x4A, 0x41, 0x01, 0x23,
+ 0xD0, 0xF8, 0xB0, 0x23, 0xA3, 0x40, 0x9A, 0x43, 0xC0, 0xF8, 0xB0, 0x23, 0x00, 0x22, 0x81, 0xF8,
+ 0x3E, 0x21, 0x90, 0xF9, 0xB8, 0x23, 0x91, 0xF9, 0x4A, 0x11, 0x8A, 0x42, 0x07, 0xD1, 0xD0, 0xF8,
+ 0xB0, 0x13, 0xB1, 0xFA, 0x81, 0xF1, 0xC1, 0xF1, 0x1F, 0x01, 0x80, 0xF8, 0xB8, 0x13, 0x10, 0xBD,
+ 0x30, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x00, 0x22, 0xD0, 0xF8, 0xB4, 0x43, 0x01, 0x23, 0x00, 0xBF,
+ 0x03, 0xFA, 0x02, 0xF5, 0x2C, 0x42, 0x06, 0xD1, 0x93, 0x40, 0x1C, 0x43, 0xC0, 0xF8, 0xB4, 0x43,
+ 0x81, 0xF8, 0x4B, 0x21, 0x30, 0xBD, 0x52, 0x1C, 0x52, 0xB2, 0x0A, 0x2A, 0xF0, 0xDB, 0xFF, 0x20,
+ 0x81, 0xF8, 0x4B, 0x01, 0x30, 0xBD, 0x10, 0xB5, 0x00, 0xF5, 0x80, 0x50, 0x91, 0xF8, 0x4B, 0x41,
+ 0x01, 0x23, 0xD0, 0xF8, 0xB4, 0x23, 0xA3, 0x40, 0x9A, 0x43, 0xC0, 0xF8, 0xB4, 0x23, 0xFF, 0x20,
+ 0x81, 0xF8, 0x4B, 0x01, 0x10, 0xBD, 0x04, 0x48, 0x70, 0x47, 0x03, 0x48, 0x90, 0xF8, 0x38, 0x04,
+ 0x70, 0x47, 0x00, 0x00, 0xBC, 0x25, 0x10, 0x00, 0x64, 0x3A, 0x10, 0x00, 0xBC, 0x35, 0x10, 0x00,
+ 0xE6, 0x43, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x70, 0x47, 0x2D, 0xE9,
+ 0xF0, 0x47, 0x00, 0x24, 0x06, 0x46, 0x01, 0x27, 0xDF, 0xF8, 0xE0, 0x80, 0x4F, 0xF0, 0x05, 0x09,
+ 0x00, 0xF5, 0x80, 0x55, 0x64, 0xE0, 0x00, 0xBF, 0xD5, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x04, 0xF1,
+ 0x08, 0x42, 0x5B, 0xD0, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x06, 0xEB, 0x00, 0x11,
+ 0x91, 0xF8, 0x3E, 0x01, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x02, 0xD0, 0x04, 0x28, 0x27, 0xD0,
+ 0x4C, 0xE0, 0x91, 0xF8, 0x3F, 0x01, 0x03, 0x28, 0x01, 0xD0, 0x04, 0x28, 0x46, 0xD1, 0x28, 0x48,
+ 0xB1, 0xF8, 0x42, 0x20, 0xB0, 0xF9, 0x00, 0x00, 0x53, 0x07, 0x02, 0xD5, 0x25, 0x48, 0xB0, 0xF9,
+ 0x00, 0x00, 0x13, 0x07, 0x02, 0xD5, 0x24, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0xB1, 0xF9, 0x54, 0x30,
+ 0x83, 0x42, 0x33, 0xDA, 0xD0, 0x05, 0x07, 0xD5, 0x20, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0x83, 0x42,
+ 0x02, 0xDD, 0x81, 0xF8, 0x3F, 0x71, 0x29, 0xE0, 0x30, 0x46, 0xFF, 0xF7, 0x5B, 0xFF, 0x25, 0xE0,
+ 0x91, 0xF8, 0x40, 0x00, 0x10, 0xF0, 0x06, 0x0F, 0x20, 0xD0, 0x91, 0xF8, 0x42, 0x00, 0x40, 0x07,
+ 0x1C, 0xD4, 0x17, 0x48, 0xB0, 0xF9, 0x00, 0x20, 0x16, 0x48, 0x00, 0x78, 0x01, 0x28, 0x01, 0xD1,
+ 0xB8, 0xF9, 0x00, 0x20, 0x91, 0xF8, 0x3F, 0x01, 0x03, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x07, 0xD0,
+ 0x0C, 0xE0, 0xB1, 0xF9, 0x54, 0x20, 0xB8, 0xF9, 0x00, 0x00, 0x82, 0x42, 0x04, 0xDB, 0x05, 0xE0,
+ 0xB1, 0xF9, 0x54, 0x00, 0x90, 0x42, 0x01, 0xDA, 0x81, 0xF8, 0x3E, 0x91, 0x64, 0x1C, 0x64, 0xB2,
+ 0x95, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0x97, 0xDA, 0xBD, 0xE8, 0xF0, 0x87, 0x6E, 0x06, 0x10, 0x00,
+ 0x68, 0x06, 0x10, 0x00, 0x7C, 0x06, 0x10, 0x00, 0x86, 0x06, 0x10, 0x00, 0x6C, 0x06, 0x10, 0x00,
+ 0x70, 0x06, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, 0x90, 0xF8, 0x40, 0x10, 0x09, 0x06, 0x14, 0xD5,
+ 0xB0, 0xF8, 0x42, 0x10, 0x0A, 0x07, 0x0C, 0xD4, 0xF8, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x40, 0x34,
+ 0x5B, 0x06, 0x06, 0xD5, 0x92, 0xF8, 0x80, 0x23, 0x52, 0x06, 0x02, 0xD4, 0x01, 0x22, 0x80, 0xF8,
+ 0x70, 0x20, 0x41, 0xF0, 0x08, 0x01, 0xA0, 0xF8, 0x42, 0x10, 0x70, 0x47, 0xB0, 0xF8, 0x40, 0x10,
+ 0xC9, 0x05, 0x14, 0xD5, 0xB0, 0xF8, 0x42, 0x10, 0x0A, 0x06, 0x0C, 0xD4, 0xEB, 0x4A, 0x12, 0x68,
+ 0x92, 0xF8, 0x20, 0x34, 0x9B, 0x07, 0x06, 0xD5, 0x92, 0xF8, 0x80, 0x23, 0x52, 0x06, 0x02, 0xD4,
+ 0x01, 0x22, 0x80, 0xF8, 0x70, 0x20, 0x41, 0xF0, 0x80, 0x01, 0xA0, 0xF8, 0x42, 0x10, 0x70, 0x47,
+ 0x2D, 0xE9, 0xF0, 0x47, 0x15, 0x46, 0x0C, 0x46, 0x82, 0x46, 0x01, 0xF1, 0x0C, 0x07, 0x4F, 0xF0,
+ 0x00, 0x08, 0x4F, 0xF0, 0xFF, 0x39, 0x02, 0xF1, 0x0C, 0x06, 0x53, 0xB3, 0x01, 0x20, 0x84, 0xF8,
+ 0x3E, 0x01, 0x95, 0xF8, 0x40, 0x00, 0x84, 0xF8, 0x3F, 0x01, 0x84, 0xF8, 0x4B, 0x91, 0x84, 0xF8,
+ 0x42, 0x81, 0x84, 0xF8, 0x43, 0x81, 0xA4, 0xF8, 0x42, 0x80, 0xC4, 0xF8, 0x2C, 0x80, 0x84, 0xF8,
+ 0x41, 0x81, 0x95, 0xF8, 0x42, 0x00, 0x84, 0xF8, 0x45, 0x01, 0x68, 0x8E, 0xA4, 0xF8, 0x56, 0x00,
+ 0x95, 0xF8, 0x41, 0x00, 0x84, 0xF8, 0x46, 0x01, 0xE8, 0x68, 0x20, 0x62, 0x03, 0x22, 0x31, 0x46,
+ 0x20, 0x46, 0x06, 0xF0, 0x53, 0xFF, 0x03, 0x22, 0x31, 0x46, 0x38, 0x46, 0x06, 0xF0, 0x4E, 0xFF,
+ 0x10, 0xE0, 0xE0, 0x6A, 0x03, 0x22, 0x40, 0x1C, 0xE0, 0x62, 0x31, 0x46, 0x20, 0x46, 0x06, 0xF0,
+ 0x39, 0xFF, 0x03, 0x22, 0x31, 0x46, 0x38, 0x46, 0x06, 0xF0, 0x34, 0xFF, 0x94, 0xF8, 0x44, 0x01,
+ 0x84, 0xF8, 0x45, 0x01, 0x95, 0xF8, 0x40, 0x00, 0x84, 0xF8, 0x3F, 0x01, 0x95, 0xF8, 0x42, 0x00,
+ 0x84, 0xF8, 0x44, 0x01, 0xE8, 0x8C, 0xA4, 0xF8, 0x44, 0x00, 0x28, 0x8D, 0xA4, 0xF8, 0x46, 0x00,
+ 0x68, 0x8D, 0xA4, 0xF8, 0x48, 0x00, 0xE8, 0x8D, 0xA4, 0xF8, 0x4A, 0x00, 0x28, 0x8E, 0xA4, 0xF8,
+ 0x4C, 0x00, 0x28, 0x8B, 0xA4, 0xF8, 0x4E, 0x00, 0xB5, 0xF9, 0x32, 0x00, 0xA4, 0xF8, 0x54, 0x00,
+ 0xA9, 0x69, 0x61, 0x63, 0xE9, 0x69, 0xA1, 0x63, 0x29, 0x6A, 0xE1, 0x63, 0xA9, 0x8E, 0xA4, 0xF8,
+ 0x58, 0x10, 0xA9, 0x8C, 0xA4, 0xF8, 0x40, 0x10, 0xD5, 0xF8, 0x36, 0x10, 0xC4, 0xF8, 0x5A, 0x10,
+ 0x69, 0x69, 0xE1, 0x61, 0x95, 0xF8, 0x43, 0x10, 0x84, 0xF8, 0x47, 0x11, 0x95, 0xF8, 0x44, 0x10,
+ 0x84, 0xF8, 0x48, 0x11, 0xB4, 0xF9, 0x56, 0x10, 0x81, 0x42, 0x01, 0xDA, 0xA4, 0xF8, 0x56, 0x00,
+ 0xC4, 0xF8, 0x4C, 0x81, 0x84, 0xF8, 0x49, 0x91, 0xA8, 0x8C, 0x80, 0x05, 0xB4, 0xF8, 0x42, 0x00,
+ 0x02, 0xD5, 0x40, 0xF4, 0x80, 0x70, 0x01, 0xE0, 0x20, 0xF4, 0x80, 0x70, 0xA4, 0xF8, 0x42, 0x00,
+ 0x21, 0x46, 0x50, 0x46, 0x00, 0xF0, 0x21, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0x2D, 0xFF, 0x20, 0x46,
+ 0xBD, 0xE8, 0xF0, 0x47, 0x42, 0xE7, 0xF0, 0xB5, 0xB1, 0xF9, 0x02, 0x60, 0xB2, 0xF9, 0x02, 0x50,
+ 0x78, 0x24, 0x06, 0xFB, 0x05, 0xF7, 0x00, 0x2F, 0x2A, 0xDD, 0xB1, 0xF9, 0x00, 0x70, 0xB2, 0xF9,
+ 0x00, 0xC0, 0x07, 0xFB, 0x0C, 0xF7, 0x00, 0x2F, 0x22, 0xDD, 0x76, 0x43, 0x5D, 0x43, 0x96, 0xFB,
+ 0xF5, 0xF5, 0x2D, 0xB2, 0x45, 0x80, 0xB1, 0xF9, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x20, 0x49, 0x43,
+ 0x5A, 0x43, 0x91, 0xFB, 0xF2, 0xF1, 0x0A, 0xB2, 0x02, 0x80, 0x78, 0x2D, 0x00, 0xDD, 0x44, 0x80,
+ 0xB0, 0xF9, 0x02, 0x30, 0x6F, 0xF0, 0x77, 0x01, 0x8B, 0x42, 0x00, 0xDA, 0x41, 0x80, 0x78, 0x2A,
+ 0x00, 0xDD, 0x04, 0x80, 0xB0, 0xF9, 0x00, 0x20, 0x8A, 0x42, 0x00, 0xDA, 0x01, 0x80, 0xF0, 0xBD,
+ 0x00, 0x21, 0x41, 0x80, 0xFA, 0xE7, 0x2D, 0xE9, 0xFF, 0x4F, 0xDF, 0xF8, 0xD4, 0x91, 0x83, 0x46,
+ 0x0F, 0x46, 0xD9, 0xF8, 0x04, 0x00, 0x71, 0x4D, 0x8F, 0xB0, 0x00, 0x21, 0x01, 0x60, 0x28, 0x68,
+ 0xB0, 0xF8, 0x82, 0x43, 0x0C, 0xF0, 0xF2, 0xF9, 0x01, 0x28, 0x04, 0xD1, 0x28, 0x68, 0xB0, 0xF8,
+ 0x84, 0x03, 0x00, 0xB1, 0x04, 0x46, 0x0C, 0xF0, 0xDF, 0xF9, 0x80, 0xB1, 0x28, 0x68, 0x69, 0x49,
+ 0xB0, 0xF8, 0x86, 0x43, 0xB0, 0xF8, 0x8A, 0x03, 0x09, 0x68, 0x88, 0x42, 0x07, 0xDA, 0x0C, 0xF0,
+ 0xDD, 0xF9, 0x01, 0x28, 0x03, 0xD1, 0x28, 0x68, 0xB0, 0xF8, 0x88, 0x03, 0x04, 0x44, 0x64, 0x43,
+ 0x02, 0x94, 0x28, 0x68, 0x00, 0x25, 0x0B, 0xF5, 0x80, 0x56, 0x90, 0xF8, 0x8C, 0x03, 0x4F, 0xF0,
+ 0x01, 0x0A, 0x05, 0x90, 0x65, 0xE0, 0x00, 0xBF, 0xD6, 0xF8, 0xB0, 0x13, 0x0A, 0xFA, 0x05, 0xF0,
+ 0x01, 0x42, 0x5C, 0xD0, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x0B, 0xEB, 0x01, 0x14,
+ 0x94, 0xF8, 0x3E, 0x01, 0x07, 0x28, 0x52, 0xD0, 0x21, 0x46, 0x20, 0x1D, 0x06, 0xF0, 0x81, 0xFE,
+ 0x05, 0x99, 0x48, 0x43, 0x00, 0xFB, 0x01, 0xF8, 0x02, 0x99, 0x88, 0x45, 0x00, 0xDA, 0x88, 0x46,
+ 0x22, 0x46, 0x21, 0x1D, 0x08, 0xA8, 0x06, 0xF0, 0x6A, 0xFE, 0x22, 0x1D, 0x11, 0x1D, 0x0A, 0xA8,
+ 0x06, 0xF0, 0x65, 0xFE, 0xBD, 0xF9, 0x20, 0x00, 0x64, 0x30, 0xC8, 0x28, 0x04, 0xD8, 0xBD, 0xF9,
+ 0x22, 0x00, 0x64, 0x30, 0xC8, 0x28, 0x01, 0xD9, 0x01, 0x23, 0x00, 0xE0, 0x03, 0x23, 0x0A, 0xAA,
+ 0x08, 0xA9, 0x09, 0xA8, 0xFF, 0xF7, 0x57, 0xFF, 0x60, 0x88, 0xBD, 0xF8, 0x26, 0x10, 0x08, 0x44,
+ 0xAD, 0xF8, 0x2E, 0x00, 0x20, 0x88, 0xBD, 0xF8, 0x24, 0x10, 0x00, 0x24, 0x08, 0x44, 0xAD, 0xF8,
+ 0x2C, 0x00, 0x18, 0xE0, 0x04, 0xEB, 0xC4, 0x00, 0x07, 0xEB, 0xC0, 0x01, 0x0B, 0xA8, 0x0C, 0x31,
+ 0x06, 0xF0, 0x47, 0xFE, 0x40, 0x45, 0x0C, 0xDA, 0xD9, 0xF8, 0x04, 0x10, 0x0A, 0x68, 0x02, 0xEB,
+ 0x42, 0x02, 0x01, 0xEB, 0x42, 0x02, 0x50, 0x60, 0x54, 0x72, 0x15, 0x72, 0x08, 0x68, 0x40, 0x1C,
+ 0x08, 0x60, 0x64, 0x1C, 0xE4, 0xB2, 0x97, 0xF8, 0x38, 0x04, 0xA0, 0x42, 0xE2, 0xD8, 0x6D, 0x1C,
+ 0x6D, 0xB2, 0x96, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0x96, 0xDA, 0xD9, 0xF8, 0x04, 0x00, 0x4D, 0x46,
+ 0x01, 0x68, 0x00, 0x29, 0x7E, 0xD0, 0x00, 0xF0, 0x61, 0xF9, 0x00, 0x26, 0x4F, 0xF0, 0x04, 0x09,
+ 0x74, 0xE0, 0x00, 0xBF, 0x06, 0xEB, 0x46, 0x01, 0x00, 0xEB, 0x41, 0x00, 0x51, 0x46, 0x90, 0xF9,
+ 0x08, 0x40, 0x90, 0xF9, 0x09, 0xC0, 0x11, 0x98, 0x03, 0x68, 0x0A, 0xFA, 0x04, 0xF0, 0x03, 0x42,
+ 0x63, 0xD1, 0x12, 0x9A, 0xD2, 0xF8, 0x00, 0x80, 0x01, 0xFA, 0x0C, 0xF2, 0x18, 0xEA, 0x02, 0x0F,
+ 0x5B, 0xD1, 0x03, 0x43, 0x11, 0x98, 0x88, 0x46, 0x03, 0x60, 0x12, 0x98, 0x12, 0x99, 0x00, 0x23,
+ 0x00, 0x68, 0x10, 0x43, 0x08, 0x60, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x01, 0x0C, 0xEB,
+ 0xCC, 0x00, 0x0B, 0xEB, 0x01, 0x14, 0x07, 0xEB, 0xC0, 0x02, 0x21, 0x46, 0x58, 0x46, 0xFF, 0xF7,
+ 0x47, 0xFE, 0x94, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x0C, 0xD0, 0x06, 0x28,
+ 0x10, 0xD0, 0x3A, 0xE0, 0x84, 0xF8, 0x41, 0x81, 0x09, 0xE0, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xF8, 0x05, 0x10, 0x00, 0xF4, 0x06, 0x10, 0x00, 0x00, 0x20, 0x84, 0xF8, 0x41, 0x01, 0x84, 0xF8,
+ 0x3E, 0x91, 0x2A, 0xE0, 0x84, 0xF8, 0x3E, 0x91, 0x94, 0xF8, 0x40, 0x00, 0x10, 0xF0, 0x06, 0x0F,
+ 0x23, 0xD0, 0x94, 0xF8, 0x42, 0x00, 0x40, 0x07, 0x1F, 0xD4, 0x97, 0x49, 0x95, 0x48, 0x09, 0x78,
+ 0xB0, 0xF9, 0x00, 0x00, 0x01, 0x29, 0x02, 0xD1, 0x94, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0x94, 0xF8,
+ 0x3F, 0x11, 0x03, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x0B, 0xD0, 0x0E, 0xE0, 0x8F, 0x48, 0xB4, 0xF9,
+ 0x54, 0x10, 0xB0, 0xF9, 0x00, 0x00, 0x06, 0xE0, 0x0C, 0xE0, 0x06, 0x20, 0x84, 0xF8, 0x3E, 0x01,
+ 0x03, 0xE0, 0xB4, 0xF9, 0x54, 0x10, 0x81, 0x42, 0xF7, 0xDB, 0x76, 0x1C, 0x68, 0x68, 0x01, 0x68,
+ 0xB1, 0x42, 0x87, 0xDC, 0x13, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x85, 0x48, 0x00, 0x21, 0x01, 0x70,
+ 0x41, 0x60, 0x81, 0x60, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x41, 0xF2, 0xFC, 0x30,
+ 0x2E, 0x21, 0x28, 0x44, 0x0C, 0xF0, 0x0F, 0xF8, 0x00, 0x24, 0x05, 0xF5, 0x80, 0x56, 0x01, 0x27,
+ 0x4F, 0xF0, 0x05, 0x08, 0x1C, 0xE0, 0x00, 0xBF, 0xD6, 0xF8, 0xB0, 0x03, 0x07, 0xFA, 0x04, 0xF1,
+ 0x08, 0x42, 0x14, 0xD0, 0xC4, 0xEB, 0xC4, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x05, 0xEB, 0x00, 0x11,
+ 0x91, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x04, 0xD0, 0x04, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x03, 0xD0,
+ 0x05, 0xE0, 0x81, 0xF8, 0x3E, 0x81, 0x02, 0xE0, 0x28, 0x46, 0xFF, 0xF7, 0xB3, 0xFC, 0x64, 0x1C,
+ 0x96, 0xF9, 0xB8, 0x03, 0xA0, 0x42, 0xDF, 0xDA, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x47,
+ 0x04, 0x46, 0x00, 0x25, 0x66, 0x48, 0x0E, 0x46, 0x00, 0x95, 0x01, 0x21, 0x00, 0x1D, 0x01, 0x95,
+ 0x03, 0xF0, 0x76, 0xFF, 0x62, 0x48, 0x05, 0x21, 0x08, 0x30, 0x03, 0xF0, 0x71, 0xFF, 0x41, 0xF2,
+ 0xFC, 0x30, 0x2E, 0x21, 0x20, 0x44, 0x0B, 0xF0, 0xCE, 0xFF, 0x5D, 0x4F, 0xFF, 0x22, 0x2D, 0x21,
+ 0xB8, 0x68, 0x0B, 0xF0, 0x9E, 0xFF, 0x3D, 0x70, 0x04, 0xF5, 0x80, 0x57, 0x4F, 0xF0, 0x01, 0x08,
+ 0xD7, 0xF8, 0xB0, 0x03, 0x58, 0xB3, 0x6B, 0x46, 0x01, 0xAA, 0x31, 0x46, 0x20, 0x46, 0xFF, 0xF7,
+ 0x72, 0xFE, 0x4F, 0xF0, 0x05, 0x09, 0x1E, 0xE0, 0xD7, 0xF8, 0xB0, 0x13, 0x08, 0xFA, 0x05, 0xF0,
+ 0x01, 0x42, 0x17, 0xD0, 0x01, 0x99, 0x08, 0x42, 0x14, 0xD1, 0xC5, 0xEB, 0xC5, 0x00, 0x00, 0xEB,
+ 0x40, 0x00, 0x04, 0xEB, 0x00, 0x11, 0x91, 0xF8, 0x3E, 0x01, 0x03, 0x28, 0x04, 0xD0, 0x04, 0x28,
+ 0x02, 0xD0, 0x02, 0x28, 0x03, 0xD0, 0x05, 0xE0, 0x81, 0xF8, 0x3E, 0x91, 0x02, 0xE0, 0x20, 0x46,
+ 0xFF, 0xF7, 0x60, 0xFC, 0x6D, 0x1C, 0x97, 0xF9, 0xB8, 0x03, 0xA8, 0x42, 0xDC, 0xDA, 0x00, 0x25,
+ 0x47, 0x46, 0x1A, 0xE0, 0x00, 0x99, 0x07, 0xFA, 0x05, 0xF0, 0x08, 0x42, 0x14, 0xD1, 0x20, 0x46,
+ 0xFF, 0xF7, 0x32, 0xFC, 0x00, 0x28, 0x0F, 0xDB, 0xC0, 0xEB, 0xC0, 0x01, 0x01, 0xEB, 0x41, 0x01,
+ 0x04, 0xEB, 0x01, 0x11, 0x05, 0xEB, 0xC5, 0x02, 0x81, 0xF8, 0x4A, 0x01, 0x06, 0xEB, 0xC2, 0x02,
+ 0x01, 0x23, 0x20, 0x46, 0xFF, 0xF7, 0x54, 0xFD, 0x6D, 0x1C, 0x96, 0xF8, 0x38, 0x04, 0xA8, 0x42,
+ 0xE0, 0xD8, 0x2F, 0x48, 0x01, 0x21, 0x00, 0x1D, 0x03, 0xF0, 0x22, 0xFF, 0x2C, 0x48, 0x05, 0x21,
+ 0x08, 0x30, 0x03, 0xF0, 0x1D, 0xFF, 0xBD, 0xE8, 0xFC, 0x87, 0x30, 0xB5, 0x28, 0x4A, 0x91, 0xF8,
+ 0x44, 0x51, 0x94, 0x68, 0x63, 0x5D, 0xFF, 0x2B, 0x05, 0xD1, 0x13, 0x78, 0x63, 0x55, 0x0F, 0x2B,
+ 0x01, 0xD2, 0x5B, 0x1C, 0x13, 0x70, 0x91, 0xF8, 0x44, 0x21, 0xA2, 0x5C, 0x81, 0xF8, 0x44, 0x21,
+ 0x00, 0xEB, 0x42, 0x02, 0x02, 0xF5, 0x80, 0x52, 0x91, 0xF8, 0x4A, 0x51, 0xB2, 0xF8, 0xFC, 0x33,
+ 0x01, 0x24, 0xAC, 0x40, 0x23, 0x43, 0xA2, 0xF8, 0xFC, 0x33, 0x91, 0xF8, 0x44, 0x11, 0x41, 0xF2,
+ 0x1A, 0x42, 0x10, 0x44, 0x0A, 0x5C, 0x52, 0x1C, 0x0A, 0x54, 0x30, 0xBD, 0x7C, 0xB5, 0x00, 0x21,
+ 0x1C, 0xE0, 0x01, 0xEB, 0x41, 0x03, 0x4A, 0x1C, 0x00, 0xEB, 0x43, 0x03, 0x12, 0xE0, 0x02, 0xEB,
+ 0x42, 0x04, 0x00, 0xEB, 0x44, 0x04, 0x5E, 0x68, 0x65, 0x68, 0xAE, 0x42, 0x09, 0xDD, 0x00, 0x96,
+ 0x1E, 0x89, 0xAD, 0xF8, 0x04, 0x60, 0x5D, 0x60, 0x25, 0x89, 0x1D, 0x81, 0x00, 0x9D, 0x65, 0x60,
+ 0x26, 0x81, 0x52, 0x1C, 0x04, 0x68, 0x94, 0x42, 0xE9, 0xDC, 0x49, 0x1C, 0x02, 0x68, 0x8A, 0x42,
+ 0xDF, 0xDC, 0x7C, 0xBD, 0x70, 0x06, 0x10, 0x00, 0x81, 0x06, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00,
+ 0xF8, 0x05, 0x10, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x00, 0x22, 0x91, 0x46, 0x15, 0x46, 0x14, 0x46,
+ 0x00, 0x92, 0xFE, 0x4A, 0xFE, 0x4B, 0x12, 0x68, 0xB3, 0xF9, 0x00, 0xC0, 0xFD, 0x4B, 0x17, 0x8E,
+ 0x1E, 0x68, 0x67, 0x45, 0x60, 0xD1, 0x86, 0x46, 0xFB, 0x48, 0x02, 0xF1, 0x32, 0x0A, 0x8B, 0x46,
+ 0x90, 0xF8, 0x00, 0xC0, 0xF9, 0x48, 0x07, 0x78, 0x4D, 0xE0, 0x3A, 0x46, 0x43, 0xE0, 0x00, 0xBF,
+ 0x3A, 0xF8, 0x12, 0x10, 0x3E, 0xF8, 0x12, 0x00, 0x3B, 0xF8, 0x12, 0x30, 0x08, 0x1A, 0xC9, 0x1A,
+ 0x00, 0xB2, 0x0B, 0xB2, 0x00, 0x28, 0x01, 0xDB, 0x01, 0x46, 0x00, 0xE0, 0x41, 0x42, 0x49, 0x45,
+ 0x06, 0xDD, 0x00, 0x28, 0x01, 0xDB, 0x01, 0x46, 0x00, 0xE0, 0x41, 0x42, 0x0F, 0xFA, 0x81, 0xF9,
+ 0x19, 0x1A, 0x01, 0xD4, 0x88, 0x46, 0x01, 0xE0, 0xC1, 0xF1, 0x00, 0x08, 0xA8, 0x45, 0x05, 0xDD,
+ 0x00, 0x29, 0x01, 0xDB, 0x0D, 0x46, 0x00, 0xE0, 0x4D, 0x42, 0x2D, 0xB2, 0x00, 0x29, 0x00, 0xDA,
+ 0x49, 0x42, 0xB6, 0xF8, 0xE2, 0x83, 0x41, 0x45, 0x15, 0xDD, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42,
+ 0x01, 0x1E, 0x00, 0xDA, 0x41, 0x42, 0x8B, 0x42, 0x02, 0xDD, 0x64, 0x1C, 0xA4, 0xB2, 0x0A, 0xE0,
+ 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0xB6, 0xF8, 0xE4, 0x13, 0x88, 0x42, 0x03, 0xDD, 0x4F, 0xF0,
+ 0x00, 0x0C, 0x64, 0x46, 0x01, 0xE0, 0x52, 0x1E, 0xBA, 0xD1, 0x0A, 0xEB, 0x47, 0x0A, 0x0E, 0xEB,
+ 0x47, 0x0E, 0x0B, 0xEB, 0x47, 0x0B, 0xBC, 0xF1, 0x01, 0x0C, 0xAE, 0xD2, 0x96, 0xF8, 0xE6, 0x03,
+ 0xA0, 0x42, 0x01, 0xD2, 0x01, 0x20, 0x00, 0x90, 0x96, 0xF8, 0xE7, 0x13, 0xCC, 0x48, 0x00, 0x9A,
+ 0x06, 0xF0, 0xB1, 0xFB, 0xCB, 0x49, 0x21, 0xF8, 0x25, 0x5F, 0x21, 0xF8, 0x02, 0x9C, 0x8C, 0x70,
+ 0xBD, 0xE8, 0xF8, 0x8F, 0x10, 0xB5, 0x0C, 0x46, 0xC3, 0x49, 0x09, 0x78, 0x4A, 0x00, 0x01, 0x46,
+ 0xC5, 0x48, 0x0B, 0xF0, 0xE7, 0xFD, 0xC1, 0x48, 0x21, 0x46, 0x00, 0x78, 0x42, 0x00, 0xC3, 0x48,
+ 0x0B, 0xF0, 0xE0, 0xFD, 0xC2, 0x49, 0x01, 0x20, 0x08, 0x70, 0x10, 0xBD, 0xB8, 0x49, 0x10, 0xB5,
+ 0xB1, 0xF9, 0x00, 0x10, 0x4A, 0x00, 0x01, 0x46, 0xBE, 0x48, 0x00, 0x68, 0x0B, 0xF0, 0xD2, 0xFD,
+ 0xBD, 0x49, 0x01, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x10, 0xB5, 0x01, 0x23, 0x0A, 0xE0, 0x00, 0xBF,
+ 0x30, 0xF9, 0x13, 0x40, 0x00, 0x2C, 0x00, 0xDA, 0x64, 0x42, 0x8C, 0x42, 0x01, 0xDD, 0x01, 0x20,
+ 0x10, 0xBD, 0x5B, 0x1C, 0x93, 0x42, 0xF3, 0xDB, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F,
+ 0xAB, 0x48, 0x00, 0x24, 0x08, 0x38, 0xDF, 0xF8, 0x9C, 0x82, 0x44, 0x60, 0x04, 0x70, 0xD8, 0xF8,
+ 0x00, 0x00, 0x9A, 0x46, 0x27, 0x46, 0x90, 0xF8, 0xAB, 0x02, 0x26, 0x46, 0x25, 0x46, 0x40, 0x07,
+ 0x03, 0xD5, 0xAA, 0x48, 0x00, 0x68, 0x00, 0xF0, 0xAB, 0xF9, 0xD8, 0xF8, 0x00, 0x00, 0xDF, 0xF8,
+ 0x80, 0x92, 0x90, 0xF8, 0xE0, 0x03, 0xC0, 0x07, 0x0E, 0xD0, 0x03, 0x20, 0x09, 0xF0, 0xAB, 0xFD,
+ 0xA0, 0x48, 0x01, 0x68, 0x00, 0x98, 0xFF, 0xF7, 0x25, 0xFF, 0x04, 0x46, 0x11, 0x26, 0x03, 0x20,
+ 0x09, 0xF0, 0xBC, 0xFD, 0x14, 0xB1, 0x74, 0xE0, 0x89, 0xF8, 0x00, 0x50, 0x9C, 0x48, 0x01, 0x78,
+ 0x11, 0xB9, 0x40, 0x78, 0x00, 0x28, 0x6C, 0xD0, 0xFA, 0xF7, 0x74, 0xFD, 0xD8, 0xF8, 0x00, 0x00,
+ 0xDF, 0xF8, 0x60, 0xB2, 0x90, 0xF8, 0xE0, 0x03, 0x80, 0x07, 0x14, 0xD5, 0x96, 0x48, 0x00, 0x78,
+ 0x88, 0xB9, 0x96, 0x48, 0x00, 0x78, 0x70, 0xB9, 0x0B, 0xF0, 0xC6, 0xFE, 0x58, 0xB9, 0x94, 0x4A,
+ 0x94, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x35, 0xF9, 0x04, 0x00, 0x4F, 0xF0, 0x30, 0x06,
+ 0x4F, 0xF0, 0x01, 0x07, 0x0F, 0xD1, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE1, 0x03, 0xC0, 0x07,
+ 0x09, 0xD0, 0x8D, 0x4A, 0x8D, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x7D, 0xF8, 0x30, 0x26,
+ 0x04, 0x46, 0x01, 0x27, 0x01, 0xE0, 0x89, 0xF8, 0x01, 0x50, 0x7C, 0xB9, 0xD8, 0xF8, 0x00, 0x00,
+ 0x90, 0xF8, 0xE1, 0x03, 0x80, 0x07, 0x09, 0xD5, 0x83, 0x4A, 0x84, 0x49, 0xDB, 0xF8, 0x00, 0x00,
+ 0x00, 0xF0, 0xA5, 0xF8, 0x31, 0x26, 0x04, 0x46, 0x01, 0x27, 0x01, 0xE0, 0x89, 0xF8, 0x02, 0x50,
+ 0x2C, 0xBB, 0xD8, 0xF8, 0x00, 0x10, 0x91, 0xF8, 0xE0, 0x03, 0x40, 0x07, 0x1F, 0xD5, 0xB1, 0xF9,
+ 0xFD, 0x23, 0x69, 0x49, 0x79, 0x48, 0x78, 0x4C, 0x09, 0x78, 0x07, 0xF0, 0xC8, 0xF8, 0x06, 0x46,
+ 0xD8, 0xF8, 0x00, 0x00, 0xB0, 0xF9, 0xFD, 0x23, 0x64, 0x48, 0x01, 0x78, 0x20, 0x46, 0x07, 0xF0,
+ 0xBE, 0xF8, 0x40, 0xEA, 0x06, 0x02, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xFF, 0x13, 0x09, 0xF1,
+ 0x03, 0x00, 0x06, 0xF0, 0xD8, 0xFA, 0x21, 0x26, 0x04, 0x46, 0x01, 0x27, 0x01, 0xE0, 0x89, 0xF8,
+ 0x03, 0x50, 0x0B, 0xF0, 0x81, 0xFE, 0x01, 0x46, 0x69, 0x48, 0x01, 0x70, 0x4C, 0xB3, 0x6F, 0xB1,
+ 0x8A, 0xF8, 0x00, 0x50, 0x31, 0x46, 0x05, 0x20, 0x05, 0xF0, 0x84, 0xFD, 0x00, 0x98, 0xFF, 0xF7,
+ 0x2D, 0xFF, 0xDD, 0xE9, 0x01, 0x01, 0xFF, 0xF7, 0x15, 0xFF, 0x16, 0xE0, 0x01, 0x20, 0x8A, 0xF8,
+ 0x00, 0x00, 0x4F, 0x48, 0x08, 0x38, 0x06, 0x70, 0x41, 0x68, 0x41, 0xF0, 0x02, 0x01, 0x41, 0x60,
+ 0xD8, 0xF8, 0x00, 0x20, 0x92, 0xF8, 0x50, 0x32, 0xDB, 0x07, 0x03, 0xD1, 0x92, 0xF8, 0x80, 0x22,
+ 0xD2, 0x07, 0x02, 0xD0, 0x41, 0xF0, 0x08, 0x01, 0x41, 0x60, 0x01, 0x20, 0x04, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x9F, 0x8A, 0xF8, 0x00, 0x50, 0x00, 0x78, 0xF8, 0xE7, 0x41, 0x48, 0x00, 0x21, 0x08, 0x38,
+ 0x41, 0x60, 0x01, 0x70, 0x81, 0x60, 0x70, 0x47, 0x2D, 0xE9, 0xF7, 0x4F, 0xDF, 0xF8, 0xE4, 0x80,
+ 0x93, 0x46, 0x0B, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0x25, 0x2C, 0x46, 0x90, 0xF8, 0xEC, 0x73,
+ 0xB0, 0xF9, 0xE8, 0x63, 0xB0, 0xF9, 0xEA, 0xA3, 0x33, 0x48, 0x31, 0x46, 0x02, 0x78, 0x18, 0x46,
+ 0x00, 0xF0, 0x07, 0xF9, 0x81, 0x46, 0x31, 0x48, 0x31, 0x46, 0x02, 0x78, 0x58, 0x46, 0x00, 0xF0,
+ 0x00, 0xF9, 0x01, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xD0, 0x51, 0xB9, 0x28, 0x48, 0x51, 0x46,
+ 0xB0, 0xF9, 0x00, 0x20, 0x00, 0x98, 0x00, 0xF0, 0x0C, 0xF9, 0x04, 0x46, 0xB8, 0x42, 0x00, 0xD9,
+ 0x01, 0x25, 0xD8, 0xF8, 0x00, 0x00, 0x2A, 0x46, 0x90, 0xF8, 0xED, 0x13, 0x24, 0x48, 0x40, 0x1C,
+ 0x06, 0xF0, 0x61, 0xFA, 0x23, 0x49, 0x81, 0xF8, 0x31, 0x40, 0xBD, 0xE8, 0xFE, 0x8F, 0x2D, 0xE9,
+ 0xF0, 0x47, 0xDF, 0xF8, 0x70, 0x80, 0x84, 0x46, 0x0B, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x18, 0x49,
+ 0x00, 0x25, 0x90, 0xF8, 0xF2, 0x73, 0xB0, 0xF9, 0xF0, 0x63, 0x91, 0x46, 0x2C, 0x46, 0xB0, 0xF9,
+ 0xEE, 0x03, 0xB1, 0xF9, 0x00, 0x10, 0x06, 0xE0, 0x3C, 0xF9, 0x11, 0x20, 0x00, 0x2A, 0x00, 0xDA,
+ 0x52, 0x42, 0x82, 0x42, 0x13, 0xDC, 0x49, 0x1E, 0xF6, 0xD2, 0x0F, 0x48, 0x31, 0x46, 0x02, 0x78,
+ 0x18, 0x46, 0x00, 0xF0, 0xC9, 0xF8, 0x04, 0x46, 0x0C, 0x48, 0x31, 0x46, 0x02, 0x78, 0x48, 0x46,
+ 0x00, 0xF0, 0xC2, 0xF8, 0x20, 0x44, 0xC4, 0xB2, 0xBC, 0x42, 0x00, 0xD9, 0x01, 0x25, 0xD8, 0xF8,
+ 0x00, 0x00, 0x2A, 0x46, 0x90, 0xF8, 0xF3, 0x13, 0x05, 0x48, 0x2B, 0xE0, 0x24, 0x07, 0x10, 0x00,
+ 0xCA, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00,
+ 0x0C, 0x06, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20,
+ 0x51, 0x07, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, 0x50, 0x07, 0x10, 0x00, 0xE0, 0x06, 0x10, 0x00,
+ 0xEC, 0x06, 0x10, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xC5, 0x06, 0x10, 0x00,
+ 0x32, 0x24, 0x10, 0x00, 0x08, 0x24, 0x10, 0x00, 0x60, 0x0B, 0x01, 0x20, 0x36, 0x0B, 0x01, 0x20,
+ 0x52, 0x06, 0x10, 0x00, 0x80, 0x1C, 0x06, 0xF0, 0xF6, 0xF9, 0x52, 0x49, 0x81, 0xF8, 0x32, 0x40,
+ 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x5F, 0x4F, 0x4E, 0x83, 0x46, 0x00, 0x25, 0x30, 0x68,
+ 0x92, 0x46, 0x0B, 0x46, 0x90, 0xF8, 0xF5, 0x73, 0xB0, 0xF9, 0xF6, 0xC3, 0xB0, 0xF9, 0xFA, 0x93,
+ 0x4A, 0x48, 0x2C, 0x46, 0x00, 0x78, 0x18, 0xB1, 0x49, 0x48, 0x00, 0x78, 0x90, 0xB1, 0x1C, 0xE0,
+ 0x48, 0x48, 0x61, 0x46, 0x02, 0x78, 0x18, 0x46, 0xFF, 0xF7, 0x4E, 0xFE, 0x80, 0x46, 0x46, 0x48,
+ 0x61, 0x46, 0x02, 0x78, 0x50, 0x46, 0xFF, 0xF7, 0x47, 0xFE, 0x01, 0x46, 0xB8, 0xF1, 0x00, 0x0F,
+ 0x00, 0xD0, 0x51, 0xB9, 0x41, 0x48, 0x49, 0x46, 0xB0, 0xF9, 0x00, 0x20, 0x58, 0x46, 0x00, 0xF0,
+ 0x60, 0xF8, 0x04, 0x46, 0xB8, 0x42, 0x00, 0xD9, 0x01, 0x25, 0x30, 0x68, 0x2A, 0x46, 0x90, 0xF8,
+ 0xFC, 0x13, 0x3B, 0x48, 0x06, 0xF0, 0xB7, 0xF9, 0x32, 0x49, 0x81, 0xF8, 0x31, 0x40, 0x0E, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x37, 0x4F, 0x39, 0x78, 0x00, 0x29, 0x30, 0xD0, 0x36, 0x49, 0x09, 0x78,
+ 0x00, 0x29, 0x2C, 0xD1, 0x2F, 0x49, 0x35, 0x4D, 0x0B, 0x78, 0x2F, 0x49, 0x6C, 0x0C, 0x0E, 0x78,
+ 0x0E, 0xE0, 0x31, 0x46, 0x08, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x11, 0x20, 0xAA, 0x42, 0x00, 0xDD,
+ 0x15, 0x46, 0xA2, 0x42, 0x00, 0xDA, 0x14, 0x46, 0x49, 0x1E, 0xF5, 0xD2, 0x00, 0xEB, 0x46, 0x00,
+ 0x5B, 0x1E, 0xEE, 0xD2, 0x20, 0x48, 0x01, 0x68, 0xB1, 0xF9, 0xC7, 0x02, 0xB1, 0xF9, 0xC9, 0x12,
+ 0x85, 0x42, 0x08, 0xDA, 0x48, 0x42, 0x84, 0x42, 0x05, 0xDD, 0x00, 0x20, 0x38, 0x70, 0x01, 0x46,
+ 0x08, 0x20, 0x05, 0xF0, 0x3F, 0xFC, 0x17, 0x48, 0x20, 0xF8, 0x44, 0x5F, 0x44, 0x80, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x05, 0xE0, 0x30, 0xF9, 0x12, 0x30, 0x8B, 0x42, 0x01, 0xDD, 0x01, 0x20, 0x70, 0x47,
+ 0x52, 0x1E, 0xF7, 0xD2, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x03, 0x46, 0x00, 0x20, 0x05, 0xE0,
+ 0x33, 0xF9, 0x12, 0x40, 0x8C, 0x42, 0x01, 0xDD, 0x40, 0x1C, 0xC0, 0xB2, 0x52, 0x1E, 0xF7, 0xD2,
+ 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x09, 0xE0, 0x00, 0xBF, 0x34, 0xF9, 0x12, 0x30,
+ 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, 0x8B, 0x42, 0x01, 0xDD, 0x40, 0x1C, 0xC0, 0xB2, 0x52, 0x1E,
+ 0xF4, 0xD2, 0x10, 0xBD, 0xE6, 0x43, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00,
+ 0x0C, 0x05, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00,
+ 0x0D, 0x06, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0xC6, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF,
+ 0x2D, 0xE9, 0xFF, 0x4F, 0x87, 0xB0, 0x00, 0x20, 0x81, 0x46, 0x03, 0x90, 0x02, 0x90, 0x01, 0x90,
+ 0x6C, 0x48, 0x88, 0x46, 0x93, 0x46, 0x00, 0x68, 0xB0, 0xF8, 0xBA, 0x02, 0x06, 0x90, 0x89, 0x78,
+ 0x50, 0x68, 0x0B, 0xF0, 0xFD, 0xFC, 0x00, 0x90, 0x98, 0xF8, 0x02, 0x50, 0x98, 0xF8, 0x03, 0x00,
+ 0x05, 0x90, 0x32, 0xE0, 0x07, 0x98, 0x98, 0xF8, 0x00, 0x40, 0x00, 0xEB, 0xC5, 0x00, 0x04, 0x90,
+ 0x98, 0xF8, 0x01, 0xA0, 0x1F, 0xE0, 0x04, 0x98, 0x22, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67,
+ 0x01, 0x20, 0x0B, 0xF0, 0x20, 0xFB, 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x12, 0xD0, 0x00, 0x98,
+ 0x06, 0x99, 0x30, 0xF9, 0x14, 0x00, 0x88, 0x42, 0x0C, 0xDD, 0x02, 0x99, 0x81, 0x44, 0x04, 0xFB,
+ 0x00, 0x11, 0x02, 0x91, 0x01, 0x99, 0x05, 0xFB, 0x00, 0x10, 0x01, 0x90, 0x03, 0x98, 0x40, 0x1C,
+ 0x80, 0xB2, 0x03, 0x90, 0x64, 0x1C, 0xA2, 0x45, 0xDD, 0xDA, 0x4F, 0x49, 0x00, 0x98, 0x6D, 0x1C,
+ 0x09, 0x78, 0x00, 0xEB, 0x41, 0x00, 0x00, 0x90, 0x05, 0x98, 0xA8, 0x42, 0xCA, 0xDA, 0x49, 0x48,
+ 0x00, 0x25, 0x04, 0x68, 0x01, 0x98, 0xA1, 0x8E, 0xC2, 0x17, 0xA1, 0xFB, 0x00, 0x36, 0x05, 0xFB,
+ 0x00, 0x60, 0x01, 0xFB, 0x02, 0x02, 0x4F, 0xF6, 0xFF, 0x76, 0xA3, 0xFB, 0x06, 0x07, 0x02, 0xFB,
+ 0x06, 0x72, 0x03, 0xFB, 0x05, 0x21, 0x94, 0xF8, 0x31, 0x30, 0x30, 0x34, 0x5B, 0x1E, 0x89, 0xFB,
+ 0x03, 0x23, 0x0B, 0xF0, 0xF3, 0xFA, 0x72, 0x10, 0x80, 0x18, 0xB0, 0x46, 0x41, 0xF1, 0x00, 0x01,
+ 0x42, 0x46, 0x00, 0x23, 0x0B, 0xF0, 0xEA, 0xFA, 0x07, 0x46, 0x02, 0x98, 0x61, 0x88, 0xC2, 0x17,
+ 0xA1, 0xFB, 0x00, 0x36, 0x05, 0xFB, 0x00, 0x60, 0x01, 0xFB, 0x02, 0x01, 0x42, 0x46, 0xA3, 0xFB,
+ 0x02, 0x06, 0x01, 0xFB, 0x02, 0x61, 0x03, 0xFB, 0x05, 0x11, 0x23, 0x78, 0x5B, 0x1E, 0x89, 0xFB,
+ 0x03, 0x23, 0x0B, 0xF0, 0xD3, 0xFA, 0x47, 0xF6, 0xFF, 0x72, 0x80, 0x18, 0x41, 0xF1, 0x00, 0x01,
+ 0x42, 0x46, 0x00, 0x23, 0x0B, 0xF0, 0xCA, 0xFA, 0xCB, 0xF8, 0x1C, 0x90, 0x03, 0x99, 0xAB, 0xF8,
+ 0x28, 0x10, 0x0A, 0x99, 0x48, 0x60, 0x0A, 0x99, 0x0F, 0x60, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F,
+ 0x10, 0xB5, 0x20, 0x49, 0x43, 0x68, 0x00, 0x22, 0x09, 0x68, 0x00, 0x2B, 0x01, 0xDA, 0x42, 0x60,
+ 0x03, 0xE0, 0x4C, 0x8E, 0xA3, 0x42, 0x00, 0xDD, 0x44, 0x60, 0x03, 0x68, 0x00, 0x2B, 0x01, 0xDA,
+ 0x02, 0x60, 0x10, 0xBD, 0x89, 0x8E, 0x8B, 0x42, 0xFB, 0xDD, 0x01, 0x60, 0x10, 0xBD, 0x7C, 0xB5,
+ 0x14, 0x46, 0x00, 0x25, 0x6B, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0x14, 0x48, 0x01, 0x78, 0x11, 0x48,
+ 0x29, 0xB1, 0x01, 0x68, 0x91, 0xF8, 0x07, 0x15, 0x09, 0x07, 0x00, 0xD5, 0x04, 0x25, 0x94, 0xF8,
+ 0x40, 0x10, 0x03, 0x29, 0x08, 0xD1, 0x00, 0x68, 0x90, 0xF8, 0x07, 0x05, 0xC0, 0x07, 0x03, 0xD0,
+ 0x29, 0x46, 0x68, 0x46, 0x01, 0xF0, 0xD2, 0xFC, 0x68, 0x46, 0xFF, 0xF7, 0xC9, 0xFF, 0x01, 0x98,
+ 0xE0, 0x81, 0x00, 0x98, 0xA0, 0x81, 0x94, 0xF8, 0x24, 0x00, 0xC0, 0x06, 0x01, 0xD4, 0xE0, 0x68,
+ 0x60, 0x61, 0x7C, 0xBD, 0x20, 0x07, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00,
+ 0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x90, 0xF8, 0x02, 0x80, 0x0F, 0x46, 0x88, 0x68, 0x14, 0x46,
+ 0x01, 0x26, 0x41, 0x46, 0x0B, 0xF0, 0x1C, 0xFC, 0x81, 0x46, 0xA8, 0xF1, 0x01, 0x00, 0xC1, 0xB2,
+ 0xB8, 0x68, 0x0B, 0xF0, 0x15, 0xFC, 0x29, 0x78, 0x09, 0xEB, 0x41, 0x02, 0x32, 0xF9, 0x02, 0x2C,
+ 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, 0x11, 0x10, 0xA1, 0x42, 0x00, 0xDA, 0x00, 0x26, 0x69, 0x78,
+ 0x09, 0xEB, 0x41, 0x02, 0xB2, 0xF9, 0x02, 0x20, 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, 0x11, 0x00,
+ 0xA0, 0x42, 0x00, 0xDA, 0x00, 0x26, 0x95, 0xF8, 0x03, 0x80, 0xB8, 0x68, 0x41, 0x46, 0x0B, 0xF0,
+ 0xF7, 0xFB, 0x81, 0x46, 0x08, 0xF1, 0x01, 0x00, 0xC1, 0xB2, 0xB8, 0x68, 0x0B, 0xF0, 0xF0, 0xFB,
+ 0x29, 0x78, 0x09, 0xEB, 0x41, 0x02, 0x32, 0xF9, 0x02, 0x2C, 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9,
+ 0x11, 0x10, 0xA1, 0x42, 0x00, 0xDA, 0x00, 0x26, 0x69, 0x78, 0x09, 0xEB, 0x41, 0x02, 0xB2, 0xF9,
+ 0x02, 0x20, 0xA2, 0x42, 0x03, 0xDB, 0x30, 0xF9, 0x11, 0x00, 0xA0, 0x42, 0x00, 0xDA, 0x00, 0x26,
+ 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x4F, 0xFB, 0x48, 0xDF, 0xF8, 0xEC, 0x83,
+ 0x92, 0x46, 0x04, 0x68, 0x97, 0xB0, 0x99, 0x46, 0x01, 0x22, 0x51, 0x46, 0xD8, 0xF8, 0x00, 0x00,
+ 0x01, 0xF0, 0xC8, 0xF9, 0xF6, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0x4D, 0x14, 0x11, 0x91, 0x90, 0xF8,
+ 0x4C, 0x04, 0x0A, 0x90, 0xF3, 0x48, 0x9A, 0xF8, 0x02, 0x70, 0x9A, 0xF8, 0x03, 0x60, 0x00, 0x78,
+ 0x9A, 0xF8, 0x00, 0xB0, 0x9A, 0xF8, 0x01, 0x50, 0x40, 0x1E, 0x87, 0x42, 0x01, 0xDA, 0x7F, 0x1C,
+ 0xFF, 0xB2, 0x0E, 0xB1, 0x76, 0x1E, 0xF6, 0xB2, 0xEB, 0x49, 0x09, 0x78, 0x49, 0x1E, 0x8B, 0x45,
+ 0x03, 0xDA, 0x0B, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x0B, 0x0D, 0xB1, 0x6D, 0x1E, 0xED, 0xB2,
+ 0xB8, 0x1E, 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, 0x0B, 0xF0, 0x9A, 0xFB, 0x0B, 0x90, 0x78, 0x1E,
+ 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, 0x0B, 0xF0, 0x93, 0xFB, 0x04, 0x90, 0x39, 0x46, 0xD9, 0xF8,
+ 0x08, 0x00, 0x0B, 0xF0, 0x8D, 0xFB, 0x01, 0x90, 0x78, 0x1C, 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00,
+ 0x0B, 0xF0, 0x86, 0xFB, 0x02, 0x90, 0xB8, 0x1C, 0xC1, 0xB2, 0xD9, 0xF8, 0x08, 0x00, 0x0B, 0xF0,
+ 0x7F, 0xFB, 0x03, 0x90, 0x39, 0x46, 0x17, 0x98, 0x0B, 0xF0, 0x74, 0xFB, 0x08, 0x90, 0xCF, 0x48,
+ 0x39, 0x46, 0x00, 0x68, 0x0B, 0xF0, 0x7C, 0xFB, 0x86, 0x46, 0x00, 0x20, 0x7A, 0xB2, 0xCF, 0x4F,
+ 0x0C, 0x90, 0xB7, 0xE0, 0x4F, 0xFA, 0x8B, 0xF0, 0x94, 0xE0, 0x00, 0x21, 0x0E, 0xF8, 0x00, 0x10,
+ 0x08, 0x99, 0x18, 0x9B, 0x09, 0x5C, 0x99, 0x42, 0x75, 0xD1, 0xDF, 0xF8, 0x14, 0xC3, 0x01, 0x9B,
+ 0xDC, 0xF8, 0x00, 0xC0, 0x33, 0xF9, 0x10, 0x30, 0xBC, 0xF8, 0x4F, 0xC4, 0x63, 0x45, 0x6A, 0xDA,
+ 0x00, 0x21, 0x14, 0x91, 0x13, 0x91, 0x11, 0x99, 0x19, 0x44, 0x04, 0x9B, 0x09, 0xB2, 0x33, 0xF9,
+ 0x10, 0x30, 0x10, 0x93, 0x8B, 0x42, 0x06, 0xDD, 0x02, 0x9B, 0x33, 0xF9, 0x10, 0x30, 0x8B, 0x42,
+ 0x01, 0xDD, 0x01, 0x23, 0x13, 0x93, 0x01, 0x9B, 0x03, 0xEB, 0x40, 0x03, 0x33, 0xF9, 0x02, 0x8C,
+ 0x88, 0x45, 0x07, 0xDD, 0xB3, 0xF9, 0x02, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, 0x01, 0x0C,
+ 0xCD, 0xF8, 0x50, 0xC0, 0x01, 0x2A, 0x0F, 0xDD, 0xDD, 0xF8, 0x2C, 0xC0, 0x3C, 0xF9, 0x10, 0xC0,
+ 0x8C, 0x45, 0x09, 0xDD, 0xDD, 0xF8, 0x08, 0xC0, 0x3C, 0xF9, 0x10, 0xC0, 0x8C, 0x45, 0x03, 0xDD,
+ 0x4F, 0xF0, 0x01, 0x0C, 0xCD, 0xF8, 0x4C, 0xC0, 0xDF, 0xF8, 0x98, 0xC2, 0x9C, 0xF8, 0x00, 0xC0,
+ 0xAC, 0xF1, 0x02, 0x0C, 0x62, 0x45, 0x0D, 0xDA, 0xDD, 0xF8, 0x40, 0xC0, 0x8C, 0x45, 0x09, 0xDD,
+ 0xDD, 0xF8, 0x0C, 0xC0, 0x3C, 0xF9, 0x10, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, 0x01, 0x0C,
+ 0xCD, 0xF8, 0x4C, 0xC0, 0x01, 0x28, 0x0B, 0xDD, 0x33, 0xF9, 0x04, 0xCC, 0x8C, 0x45, 0x07, 0xDD,
+ 0xB3, 0xF9, 0x02, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0, 0x01, 0x0C, 0xCD, 0xF8, 0x50, 0xC0,
+ 0xDF, 0xF8, 0x54, 0xC2, 0x9C, 0xF8, 0x00, 0xC0, 0xAC, 0xF1, 0x02, 0x0C, 0x60, 0x45, 0x05, 0xDA,
+ 0x88, 0x45, 0x03, 0xDD, 0xB3, 0xF9, 0x04, 0x30, 0x8B, 0x42, 0x12, 0xDC, 0x14, 0x99, 0x81, 0xB9,
+ 0x13, 0x99, 0x0D, 0xE0, 0xFF, 0xE7, 0x99, 0xB9, 0x01, 0x99, 0xB7, 0xF9, 0x00, 0x30, 0x31, 0xF9,
+ 0x10, 0x10, 0x99, 0x42, 0x0C, 0xDA, 0x86, 0x49, 0x09, 0x68, 0x91, 0xF8, 0x41, 0x14, 0xC9, 0x07,
+ 0x31, 0xB1, 0x01, 0x21, 0x0E, 0xF8, 0x00, 0x10, 0x0C, 0x99, 0x49, 0x1C, 0x89, 0xB2, 0x0C, 0x91,
+ 0x40, 0x1C, 0x40, 0xB2, 0xA8, 0x42, 0x7F, 0xF7, 0x68, 0xAF, 0x7F, 0x48, 0x0B, 0x99, 0x0E, 0xF1,
+ 0x28, 0x0E, 0x00, 0x78, 0x01, 0xEB, 0x40, 0x01, 0x0B, 0x91, 0x04, 0x99, 0x01, 0xEB, 0x40, 0x01,
+ 0x04, 0x91, 0x01, 0x99, 0x01, 0xEB, 0x40, 0x01, 0x01, 0x91, 0x02, 0x99, 0x01, 0xEB, 0x40, 0x01,
+ 0x02, 0x91, 0x03, 0x99, 0x01, 0xEB, 0x40, 0x00, 0x03, 0x90, 0x08, 0x98, 0x28, 0x30, 0x52, 0x1C,
+ 0x52, 0xB2, 0x08, 0x90, 0xB2, 0x42, 0x7F, 0xF7, 0x45, 0xAF, 0x0A, 0x99, 0x0C, 0x98, 0x88, 0x42,
+ 0x2A, 0xD9, 0x00, 0x20, 0x84, 0xF8, 0x0E, 0x01, 0xDA, 0xF8, 0x00, 0x00, 0x20, 0x60, 0x67, 0x48,
+ 0x00, 0x23, 0x1A, 0x46, 0x21, 0x46, 0x00, 0x68, 0x01, 0xF0, 0xA6, 0xF9, 0x01, 0x25, 0x17, 0xE0,
+ 0x04, 0xEB, 0x85, 0x00, 0x06, 0x46, 0x51, 0x46, 0x00, 0xF0, 0x3F, 0xF9, 0x70, 0xB1, 0x04, 0xEB,
+ 0x45, 0x00, 0xB0, 0xF8, 0xB4, 0x10, 0x0A, 0x98, 0x81, 0x42, 0x07, 0xD9, 0x30, 0x46, 0xB7, 0xF9,
+ 0x00, 0x20, 0x49, 0x46, 0xFF, 0xF7, 0x64, 0xFE, 0x01, 0x28, 0x06, 0xD0, 0x6D, 0x1C, 0xED, 0xB2,
+ 0x94, 0xF8, 0x0E, 0x01, 0xA8, 0x42, 0xE3, 0xD2, 0x00, 0x20, 0x1B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F,
+ 0x2D, 0xE9, 0xF8, 0x4F, 0x04, 0x46, 0x50, 0x48, 0xDF, 0xF8, 0x40, 0x81, 0x91, 0x46, 0x8B, 0x46,
+ 0x05, 0x68, 0x01, 0x22, 0x21, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x73, 0xF8, 0x00, 0x27,
+ 0xA6, 0x78, 0x4F, 0xF0, 0x01, 0x0A, 0x1D, 0xE0, 0x31, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x0B, 0xF0,
+ 0x6F, 0xFA, 0x00, 0x90, 0x31, 0x46, 0xDB, 0xF8, 0x08, 0x00, 0x0B, 0xF0, 0x61, 0xFA, 0x01, 0x46,
+ 0x20, 0x78, 0x52, 0x46, 0x09, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x10, 0xC0, 0xCC, 0x45, 0x02, 0xDA,
+ 0x00, 0x9B, 0x01, 0x27, 0x1A, 0x54, 0x40, 0x1C, 0xC0, 0xB2, 0x63, 0x78, 0x83, 0x42, 0xF3, 0xD2,
+ 0x76, 0x1C, 0xF6, 0xB2, 0xE0, 0x78, 0xB0, 0x42, 0xDE, 0xD2, 0x01, 0x2F, 0x2E, 0xD1, 0x00, 0x20,
+ 0x85, 0xF8, 0x0E, 0x01, 0x20, 0x68, 0x28, 0x60, 0x00, 0x23, 0x1A, 0x46, 0x29, 0x46, 0xD8, 0xF8,
+ 0x00, 0x00, 0x01, 0xF0, 0x41, 0xF9, 0x01, 0x26, 0xDF, 0xF8, 0xC4, 0x80, 0x1A, 0xE0, 0x00, 0xBF,
+ 0x05, 0xEB, 0x86, 0x07, 0x21, 0x46, 0x38, 0x46, 0x00, 0xF0, 0xD7, 0xF8, 0x80, 0xB1, 0x05, 0xEB,
+ 0x46, 0x00, 0xB0, 0xF8, 0xB4, 0x10, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x4C, 0x04, 0x81, 0x42,
+ 0x06, 0xD9, 0x38, 0x46, 0x4A, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0xFA, 0xFD, 0x01, 0x28, 0x06, 0xD0,
+ 0x76, 0x1C, 0xF6, 0xB2, 0x95, 0xF8, 0x0E, 0x01, 0xB0, 0x42, 0xE1, 0xD2, 0x00, 0x20, 0xBD, 0xE8,
+ 0xF8, 0x8F, 0x2D, 0xE9, 0xF0, 0x41, 0x1E, 0x4E, 0x0F, 0x46, 0x80, 0x46, 0x31, 0x68, 0x14, 0x46,
+ 0x1F, 0x48, 0x1D, 0x46, 0x9A, 0x69, 0xB1, 0xF8, 0x49, 0x34, 0x00, 0x78, 0x9A, 0x42, 0x10, 0xDC,
+ 0xEA, 0x8C, 0x04, 0x2A, 0x0D, 0xD9, 0x62, 0x78, 0x23, 0x78, 0x91, 0xF8, 0x4B, 0x14, 0xD2, 0x1A,
+ 0x52, 0x1C, 0x8A, 0x42, 0x05, 0xDC, 0xE2, 0x78, 0xA3, 0x78, 0xD2, 0x1A, 0x52, 0x1C, 0x8A, 0x42,
+ 0x02, 0xDD, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x28, 0xFB, 0xD1, 0x0F, 0x48, 0x29, 0x46,
+ 0xB0, 0xF9, 0x00, 0x20, 0x20, 0x46, 0xFF, 0xF7, 0x6B, 0xFF, 0x00, 0x28, 0xF2, 0xD1, 0x31, 0x68,
+ 0x91, 0xF8, 0x40, 0x14, 0x89, 0x07, 0xED, 0xD5, 0x2B, 0x46, 0x22, 0x46, 0x39, 0x46, 0x40, 0x46,
+ 0xBD, 0xE8, 0xF0, 0x41, 0x07, 0xE6, 0x00, 0x00, 0x48, 0x06, 0x10, 0x00, 0x30, 0x06, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x84, 0x06, 0x10, 0x00,
+ 0x10, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0xDF, 0xF8, 0x08, 0xB1, 0xDD, 0xF8,
+ 0x38, 0x90, 0x5F, 0xEA, 0x03, 0x08, 0x15, 0x46, 0x1D, 0xD4, 0x2C, 0x78, 0x0B, 0xEB, 0xC8, 0x0A,
+ 0x16, 0xE0, 0x00, 0xBF, 0x08, 0xF0, 0xFF, 0x01, 0x01, 0x98, 0x0B, 0xF0, 0xC1, 0xF9, 0x00, 0x90,
+ 0xDA, 0xE9, 0x00, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0xEC, 0xFF, 0x06, 0x40,
+ 0x0F, 0x40, 0x3E, 0x43, 0x02, 0xD1, 0x00, 0x98, 0x00, 0x21, 0x01, 0x55, 0x64, 0x1C, 0xE4, 0xB2,
+ 0x68, 0x78, 0xA0, 0x42, 0xE6, 0xD2, 0xB9, 0xF1, 0x00, 0x00, 0x1E, 0xDB, 0x02, 0x46, 0xAC, 0x78,
+ 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0xD7, 0xFF, 0x06, 0x46, 0x0F, 0x46, 0x4F, 0xF0, 0x00, 0x08,
+ 0x10, 0xE0, 0x21, 0x46, 0x01, 0x98, 0x0B, 0xF0, 0x9B, 0xF9, 0x0B, 0xEB, 0xC4, 0x01, 0x02, 0x46,
+ 0xD1, 0xE9, 0x00, 0x01, 0x30, 0x40, 0x39, 0x40, 0x08, 0x43, 0x01, 0xD1, 0x02, 0xF8, 0x09, 0x80,
+ 0x64, 0x1C, 0xE4, 0xB2, 0xE8, 0x78, 0xA0, 0x42, 0xEB, 0xD2, 0x05, 0xB0, 0xFE, 0xE6, 0x70, 0xB5,
+ 0x1E, 0x4B, 0x1D, 0x4A, 0x8C, 0x69, 0x1B, 0x68, 0x12, 0x78, 0xB3, 0xF8, 0x49, 0x54, 0xAC, 0x42,
+ 0x10, 0xDC, 0xCC, 0x8C, 0x04, 0x2C, 0x0D, 0xD9, 0x44, 0x78, 0x05, 0x78, 0x93, 0xF8, 0x4B, 0x34,
+ 0x64, 0x1B, 0x64, 0x1C, 0x9C, 0x42, 0x05, 0xDC, 0xC4, 0x78, 0x85, 0x78, 0x64, 0x1B, 0x64, 0x1C,
+ 0x9C, 0x42, 0x01, 0xDD, 0x00, 0x22, 0x06, 0xE0, 0x2A, 0xB9, 0x11, 0x4A, 0xB2, 0xF9, 0x00, 0x20,
+ 0xFF, 0xF7, 0xDE, 0xFE, 0x02, 0x46, 0x10, 0x46, 0x70, 0xBD, 0x02, 0x78, 0x0B, 0x78, 0x9A, 0x42,
+ 0x0B, 0xD9, 0x42, 0x78, 0x4B, 0x78, 0x9A, 0x42, 0x07, 0xD2, 0x82, 0x78, 0x8B, 0x78, 0x9A, 0x42,
+ 0x03, 0xD9, 0xC0, 0x78, 0xC9, 0x78, 0x88, 0x42, 0x01, 0xD3, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20,
+ 0x70, 0x47, 0x00, 0x00, 0x48, 0x3F, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x6E, 0x06, 0x10, 0x00, 0x70, 0xB5, 0xFE, 0x4C, 0x00, 0xEB, 0x43, 0x05, 0x04, 0x9E, 0x00, 0xEB,
+ 0x83, 0x03, 0x86, 0xB1, 0x8E, 0x69, 0xA6, 0x60, 0xCE, 0x8C, 0x66, 0x80, 0x09, 0x68, 0x61, 0x61,
+ 0xB5, 0xF8, 0xB4, 0x10, 0xA1, 0x80, 0x19, 0x68, 0xE1, 0x60, 0x90, 0xF8, 0x0E, 0x01, 0x20, 0x70,
+ 0x10, 0x68, 0x20, 0x61, 0x70, 0xBD, 0xA6, 0x68, 0x8E, 0x61, 0x66, 0x88, 0xCE, 0x84, 0x66, 0x69,
+ 0x0E, 0x60, 0xA1, 0x88, 0xA5, 0xF8, 0xB4, 0x10, 0xE1, 0x68, 0x19, 0x60, 0x21, 0x78, 0x80, 0xF8,
+ 0x0E, 0x11, 0x20, 0x69, 0x10, 0x60, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0xE9, 0x48,
+ 0x0F, 0x46, 0xE9, 0x4D, 0x01, 0x78, 0x1C, 0x46, 0x16, 0x46, 0x09, 0xB9, 0x40, 0x78, 0xD8, 0xB1,
+ 0x28, 0x68, 0x90, 0xF8, 0x30, 0x02, 0x00, 0x07, 0x05, 0xD5, 0x39, 0x46, 0x40, 0x46, 0xF9, 0xF7,
+ 0xAC, 0xFA, 0x00, 0x28, 0x41, 0xD0, 0x28, 0x68, 0x90, 0xF8, 0x30, 0x02, 0x00, 0x06, 0x0B, 0xD5,
+ 0xDE, 0x48, 0x00, 0x78, 0x01, 0x28, 0x07, 0xD0, 0xDD, 0x48, 0x00, 0x78, 0x20, 0xB1, 0x30, 0x46,
+ 0xF9, 0xF7, 0xF5, 0xFA, 0x00, 0x28, 0x30, 0xD0, 0xDA, 0x4B, 0x32, 0x46, 0x39, 0x46, 0x40, 0x46,
+ 0x00, 0xF0, 0x9F, 0xFE, 0x00, 0x28, 0x28, 0xD0, 0x94, 0xF8, 0x40, 0x00, 0x03, 0x28, 0x08, 0xD1,
+ 0x29, 0x68, 0xE0, 0x8C, 0x91, 0xF8, 0x07, 0x13, 0x88, 0x42, 0x02, 0xD9, 0x04, 0x20, 0x84, 0xF8,
+ 0x40, 0x00, 0x30, 0x68, 0xC4, 0xF8, 0x36, 0x00, 0x04, 0xF1, 0x44, 0x02, 0x51, 0x1E, 0x30, 0x46,
+ 0xF8, 0xF7, 0x03, 0xFE, 0x22, 0x46, 0x31, 0x46, 0xCA, 0x48, 0x00, 0xF0, 0x9C, 0xFD, 0x31, 0x46,
+ 0xC8, 0x48, 0x00, 0xF0, 0x17, 0xFE, 0x22, 0x46, 0x31, 0x46, 0xC6, 0x48, 0xFF, 0xF7, 0x67, 0xFC,
+ 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFE, 0xF7, 0x63, 0xBC, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x0D, 0x46, 0x1F, 0x46, 0x16, 0x46, 0x04, 0x46, 0x48, 0x21, 0x0A, 0xF0, 0xC3, 0xFF,
+ 0x00, 0x20, 0x84, 0xF8, 0x40, 0x00, 0xBC, 0x48, 0x00, 0x68, 0x60, 0x60, 0xA0, 0x60, 0x06, 0xEB,
+ 0x45, 0x00, 0x84, 0xF8, 0x42, 0x50, 0x30, 0xF8, 0xB4, 0x1F, 0x61, 0x85, 0x00, 0x88, 0xE0, 0x84,
+ 0x06, 0xEB, 0x85, 0x00, 0x00, 0x68, 0xC4, 0xF8, 0x3A, 0x00, 0xAD, 0x48, 0x81, 0x69, 0x21, 0x60,
+ 0x01, 0x21, 0xA9, 0x40, 0x39, 0x42, 0xD8, 0xD0, 0x40, 0x6A, 0x20, 0x60, 0xD5, 0xE7, 0x2D, 0xE9,
+ 0xF0, 0x47, 0x89, 0x46, 0x1C, 0x46, 0x16, 0x46, 0xAC, 0x4D, 0x03, 0xF1, 0x3E, 0x08, 0x91, 0x78,
+ 0x0B, 0xF0, 0x80, 0xF8, 0x07, 0x46, 0xB1, 0x78, 0x60, 0x68, 0x0B, 0xF0, 0x81, 0xF8, 0x02, 0x46,
+ 0x00, 0x20, 0xA0, 0x61, 0xB1, 0x78, 0x1F, 0xE0, 0x30, 0x78, 0x13, 0xE0, 0x17, 0xF8, 0x00, 0xC0,
+ 0xCC, 0x45, 0x0D, 0xD1, 0x32, 0xF9, 0x10, 0x30, 0xD4, 0xF8, 0x18, 0xC0, 0xAB, 0x42, 0x9C, 0x44,
+ 0xC4, 0xF8, 0x18, 0xC0, 0x04, 0xDD, 0x88, 0xF8, 0x00, 0x00, 0x1D, 0x46, 0x88, 0xF8, 0x01, 0x10,
+ 0x40, 0x1C, 0xC0, 0xB2, 0x73, 0x78, 0x83, 0x42, 0xE8, 0xD2, 0x99, 0x48, 0x49, 0x1C, 0xC9, 0xB2,
+ 0x00, 0x78, 0x28, 0x37, 0x02, 0xEB, 0x40, 0x02, 0xF0, 0x78, 0x88, 0x42, 0xDC, 0xD2, 0x65, 0x86,
+ 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0x0C, 0x46, 0x1E, 0x46, 0x99, 0x78,
+ 0xDD, 0xF8, 0x40, 0x80, 0x0E, 0x9D, 0x0B, 0xF0, 0x53, 0xF8, 0x00, 0x90, 0xB1, 0x78, 0x20, 0x46,
+ 0x0B, 0xF0, 0x40, 0xF8, 0x83, 0x46, 0xB1, 0x78, 0xD8, 0xF8, 0x04, 0x00, 0x0B, 0xF0, 0x40, 0xF8,
+ 0x81, 0x46, 0x88, 0x48, 0x4F, 0xF0, 0x00, 0x0A, 0xC8, 0xF8, 0x18, 0xA0, 0x00, 0x68, 0x28, 0x60,
+ 0xB7, 0x78, 0x41, 0xE0, 0x34, 0x78, 0x31, 0xE0, 0x1B, 0xF8, 0x04, 0x10, 0x03, 0x98, 0x81, 0x42,
+ 0x2A, 0xD1, 0x39, 0xF9, 0x14, 0x10, 0x0F, 0x98, 0x81, 0x42, 0x22, 0xDD, 0x00, 0x99, 0x03, 0x98,
+ 0x08, 0x55, 0x29, 0x78, 0x20, 0x46, 0x05, 0xF0, 0xC5, 0xFB, 0x28, 0x70, 0x69, 0x78, 0x20, 0x46,
+ 0x05, 0xF0, 0xC4, 0xFB, 0x68, 0x70, 0xA9, 0x78, 0x38, 0x46, 0x05, 0xF0, 0xBB, 0xFB, 0xA8, 0x70,
+ 0xE9, 0x78, 0x38, 0x46, 0x05, 0xF0, 0xBA, 0xFB, 0xE8, 0x70, 0x0A, 0xF1, 0x01, 0x00, 0x1F, 0xFA,
+ 0x80, 0xFA, 0x39, 0xF9, 0x14, 0x00, 0xD8, 0xF8, 0x18, 0x10, 0x01, 0x44, 0xC8, 0xF8, 0x18, 0x10,
+ 0x02, 0xE0, 0x00, 0x99, 0x00, 0x20, 0x08, 0x55, 0x64, 0x1C, 0xE4, 0xB2, 0x70, 0x78, 0xA0, 0x42,
+ 0xCA, 0xD2, 0x00, 0x98, 0x66, 0x49, 0x28, 0x30, 0x00, 0x90, 0x09, 0x78, 0x7F, 0x1C, 0x0B, 0xF1,
+ 0x28, 0x0B, 0x09, 0xEB, 0x41, 0x09, 0xFF, 0xB2, 0xF0, 0x78, 0xB8, 0x42, 0xBA, 0xD2, 0xA8, 0xF8,
+ 0x26, 0xA0, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xFF, 0x41, 0x17, 0x46, 0x0A, 0xAA,
+ 0x80, 0x46, 0x92, 0xE8, 0x31, 0x00, 0x5C, 0x4A, 0x1E, 0x46, 0xB2, 0xF9, 0x00, 0x20, 0x82, 0x42,
+ 0x02, 0xDB, 0x00, 0x20, 0x04, 0xB0, 0x20, 0xE7, 0x03, 0xAA, 0xCD, 0xE9, 0x00, 0x20, 0x02, 0x94,
+ 0x3A, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x7E, 0xFF, 0x01, 0x21, 0x28, 0x68, 0xB9, 0x40, 0x08, 0x43,
+ 0x28, 0x60, 0xC4, 0xF8, 0x00, 0x80, 0xE0, 0x8C, 0x10, 0xB1, 0x03, 0x98, 0x30, 0x60, 0xE8, 0xE7,
+ 0x01, 0x20, 0xE7, 0xE7, 0x2D, 0xE9, 0xFF, 0x4F, 0x81, 0xB0, 0x90, 0x46, 0x0E, 0x9C, 0x8B, 0x46,
+ 0x04, 0xEB, 0x88, 0x00, 0x94, 0xF8, 0x0E, 0x71, 0xDD, 0xF8, 0x40, 0xA0, 0x00, 0x68, 0x1E, 0x46,
+ 0x20, 0x60, 0x01, 0x23, 0x21, 0x46, 0x58, 0x46, 0x00, 0xF0, 0xB6, 0xFE, 0x01, 0x98, 0x58, 0x45,
+ 0x1F, 0xD0, 0xB5, 0x78, 0x1A, 0xE0, 0x29, 0x46, 0x01, 0x98, 0x0A, 0xF0, 0xB1, 0xFF, 0x81, 0x46,
+ 0x29, 0x46, 0x58, 0x46, 0x0A, 0xF0, 0xAC, 0xFF, 0x01, 0x46, 0x30, 0x78, 0x09, 0xE0, 0x00, 0xBF,
+ 0x19, 0xF8, 0x00, 0x30, 0x43, 0x45, 0x02, 0xD1, 0x0B, 0x5C, 0x09, 0xF8, 0x00, 0x30, 0x40, 0x1C,
+ 0xC0, 0xB2, 0x72, 0x78, 0x82, 0x42, 0xF3, 0xD2, 0x6D, 0x1C, 0xED, 0xB2, 0xF0, 0x78, 0xA8, 0x42,
+ 0xE1, 0xD2, 0x94, 0xF8, 0x0E, 0x01, 0x00, 0x25, 0x01, 0x21, 0xB8, 0x42, 0x12, 0xD0, 0x11, 0x98,
+ 0x78, 0xB1, 0x7F, 0x1C, 0xF8, 0xB2, 0x08, 0xE0, 0xDA, 0xF8, 0x00, 0x20, 0x01, 0xFA, 0x00, 0xF3,
+ 0x1A, 0x43, 0x40, 0x1C, 0xC0, 0xB2, 0xCA, 0xF8, 0x00, 0x20, 0x94, 0xF8, 0x0E, 0x21, 0x82, 0x42,
+ 0xF2, 0xD2, 0x01, 0x25, 0x00, 0x91, 0x43, 0x46, 0x52, 0x46, 0x20, 0x46, 0x0F, 0x99, 0xFF, 0xF7,
+ 0x31, 0xFE, 0x28, 0x46, 0x7D, 0xE7, 0x10, 0xB5, 0x17, 0x4A, 0x20, 0x4C, 0x13, 0x68, 0x64, 0x78,
+ 0x93, 0xF8, 0x06, 0x23, 0x4C, 0xB1, 0x91, 0xF8, 0x24, 0x10, 0x09, 0x07, 0x02, 0xD5, 0x93, 0xF8,
+ 0x09, 0x13, 0x01, 0xE0, 0x93, 0xF8, 0x08, 0x13, 0x0A, 0x44, 0x90, 0x42, 0x01, 0xD9, 0x01, 0x20,
+ 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x1C, 0x46, 0x90, 0x46, 0x89, 0x46,
+ 0x82, 0x46, 0x01, 0xF0, 0x41, 0xF8, 0x08, 0x4F, 0xE1, 0x8C, 0x38, 0x68, 0x90, 0xF8, 0x0E, 0x23,
+ 0x91, 0x42, 0x7C, 0xD8, 0x03, 0x21, 0x84, 0xF8, 0x40, 0x10, 0x00, 0x25, 0x18, 0xE0, 0x00, 0x00,
+ 0x14, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x0E, 0x05, 0x10, 0x00,
+ 0xC0, 0x06, 0x10, 0x00, 0xA0, 0x3E, 0x10, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF,
+ 0xBA, 0x06, 0x10, 0x00, 0x52, 0x6C, 0x01, 0x00, 0x76, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0x90, 0xF8, 0xE0, 0x12, 0x8A, 0x07, 0x01, 0xD4, 0x49, 0x07, 0x00, 0xD5, 0x01, 0x25, 0xFF, 0x4A,
+ 0xB0, 0xF8, 0x0A, 0x13, 0xFE, 0x4E, 0x52, 0x78, 0x1A, 0xB1, 0xB2, 0x79, 0x0A, 0xB9, 0xB0, 0xF8,
+ 0x0C, 0x13, 0xA2, 0x8D, 0x8A, 0x42, 0x02, 0xD2, 0xFA, 0x49, 0x09, 0x78, 0x21, 0xB1, 0x61, 0x8D,
+ 0x03, 0x29, 0x06, 0xD2, 0x00, 0x25, 0x29, 0xE0, 0x61, 0x8D, 0x00, 0x25, 0x03, 0x29, 0xF9, 0xD3,
+ 0x24, 0xE0, 0x1D, 0xB3, 0x31, 0x79, 0x79, 0xB1, 0x90, 0xF8, 0x40, 0x04, 0x40, 0x07, 0x0B, 0xD5,
+ 0x21, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x7B, 0xFD, 0xEF, 0x49, 0x08, 0x70, 0x20, 0xB1, 0xA0, 0x8C,
+ 0x40, 0xF0, 0x80, 0x00, 0xA0, 0x84, 0xE5, 0xE7, 0x70, 0x79, 0x78, 0xB1, 0xEB, 0x48, 0xEC, 0x49,
+ 0xB0, 0xF9, 0x00, 0x00, 0xB1, 0xF9, 0x00, 0x10, 0x88, 0x42, 0x07, 0xDB, 0x23, 0x46, 0x42, 0x46,
+ 0x49, 0x46, 0x50, 0x46, 0x02, 0xF0, 0xD3, 0xF9, 0x01, 0x28, 0x04, 0xD0, 0xA0, 0x8C, 0x10, 0xF4,
+ 0xC0, 0x7F, 0x19, 0xD1, 0x04, 0xE0, 0xA0, 0x8C, 0x40, 0xF4, 0x80, 0x70, 0xA0, 0x84, 0x13, 0xE0,
+ 0x95, 0xB1, 0x38, 0x68, 0x90, 0xF8, 0xE0, 0x02, 0xC0, 0x07, 0x03, 0xD0, 0x21, 0x46, 0x40, 0x46,
+ 0x01, 0xF0, 0x95, 0xF9, 0x23, 0x46, 0x42, 0x46, 0x49, 0x46, 0x50, 0x46, 0x00, 0xE0, 0x0A, 0xE0,
+ 0xBD, 0xE8, 0xF0, 0x47, 0x02, 0xF0, 0xA8, 0xB8, 0x23, 0x46, 0x42, 0x46, 0x49, 0x46, 0x50, 0x46,
+ 0xBD, 0xE8, 0xF0, 0x47, 0xA8, 0xE5, 0x04, 0x20, 0x84, 0xF8, 0x40, 0x00, 0xF4, 0xE7, 0x2D, 0xE9,
+ 0xFF, 0x4F, 0xD0, 0x48, 0x87, 0xB0, 0xDF, 0xF8, 0x28, 0xB3, 0xB0, 0xF9, 0x00, 0x80, 0x0C, 0x46,
+ 0x00, 0x26, 0x14, 0x98, 0x9B, 0xF8, 0x04, 0x10, 0xDF, 0xF8, 0x2C, 0xA3, 0x01, 0x27, 0x15, 0x46,
+ 0x87, 0x40, 0xB1, 0x46, 0xD1, 0xB3, 0xC9, 0x48, 0xC5, 0x4A, 0xB0, 0xF9, 0x00, 0x10, 0xB2, 0xF9,
+ 0x00, 0x20, 0x91, 0x42, 0x32, 0xDA, 0x2A, 0x68, 0x3A, 0x42, 0x2F, 0xD1, 0xE2, 0x8C, 0x04, 0x2A,
+ 0x2C, 0xD9, 0x8D, 0xE8, 0x32, 0x00, 0x0A, 0x9B, 0x14, 0x9A, 0xDA, 0xF8, 0x18, 0x10, 0xDA, 0xF8,
+ 0x24, 0x00, 0xFF, 0xF7, 0xA1, 0xFE, 0x06, 0x00, 0x20, 0xD1, 0x23, 0x46, 0x20, 0x68, 0x0A, 0x9A,
+ 0x14, 0x99, 0xFF, 0xF7, 0x6E, 0xFC, 0xB4, 0x49, 0x08, 0x70, 0xA0, 0xB1, 0x70, 0x1E, 0x8D, 0xF8,
+ 0x10, 0x00, 0x8D, 0xF8, 0x14, 0x00, 0xB6, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x41, 0x04, 0x80, 0x07,
+ 0x05, 0xD5, 0x05, 0xAA, 0x04, 0xA9, 0x0A, 0x98, 0xF8, 0xF7, 0x13, 0xFC, 0x90, 0xB3, 0xA0, 0x8C,
+ 0x40, 0xF0, 0x80, 0x00, 0xA0, 0x84, 0xAD, 0x48, 0xB0, 0xF9, 0x00, 0x80, 0x9B, 0xF8, 0x05, 0x00,
+ 0x38, 0xB3, 0x94, 0xF8, 0x24, 0x00, 0x00, 0x06, 0x4F, 0xD4, 0xA4, 0x48, 0xA4, 0x4A, 0xB0, 0xF9,
+ 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x47, 0xDA, 0x83, 0x46, 0x41, 0x45, 0x17, 0xD0,
+ 0x28, 0x68, 0x38, 0x42, 0x07, 0xD0, 0xCD, 0xF8, 0x00, 0x90, 0x2A, 0x46, 0x21, 0x46, 0x14, 0x9B,
+ 0x07, 0x98, 0xFF, 0xF7, 0x0F, 0xFD, 0xBB, 0xF9, 0x00, 0x00, 0x8D, 0xE8, 0x31, 0x00, 0x0A, 0x9B,
+ 0x14, 0x9A, 0xDA, 0xF8, 0x18, 0x10, 0xDA, 0xF8, 0x24, 0x00, 0xFF, 0xF7, 0x55, 0xFE, 0x06, 0x46,
+ 0xFE, 0xB1, 0x2A, 0xE0, 0xFF, 0xE7, 0x97, 0x49, 0x9D, 0xF9, 0x10, 0x30, 0x01, 0xF8, 0x36, 0x3F,
+ 0x9D, 0xF9, 0x14, 0x00, 0x48, 0x70, 0x00, 0x90, 0x20, 0x68, 0x0A, 0x9A, 0x07, 0x99, 0xFF, 0xF7,
+ 0x61, 0xFC, 0x07, 0x99, 0x04, 0xF1, 0x3A, 0x03, 0x8D, 0xE8, 0x32, 0x02, 0x21, 0x68, 0x14, 0x9A,
+ 0xDA, 0xF8, 0x18, 0x00, 0xFF, 0xF7, 0x5E, 0xFE, 0x00, 0x28, 0xB4, 0xD0, 0x01, 0x20, 0x0B, 0xB0,
+ 0x30, 0xE6, 0x23, 0x46, 0x20, 0x68, 0x0A, 0x9A, 0x14, 0x99, 0x02, 0xF0, 0x08, 0xF9, 0x01, 0x28,
+ 0x03, 0xD1, 0xA0, 0x8C, 0x40, 0xF4, 0x80, 0x70, 0xA0, 0x84, 0xA0, 0x8C, 0x10, 0xF4, 0xC0, 0x7F,
+ 0x0A, 0xD1, 0x28, 0x68, 0x38, 0x42, 0x07, 0xD0, 0xCD, 0xF8, 0x00, 0x90, 0x2A, 0x46, 0x21, 0x46,
+ 0x14, 0x9B, 0x07, 0x98, 0xFF, 0xF7, 0xC6, 0xFC, 0x30, 0x46, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F,
+ 0x79, 0x49, 0xDF, 0xF8, 0xCC, 0x81, 0xE5, 0xB0, 0xB1, 0xF9, 0x00, 0x10, 0xB8, 0xF9, 0x00, 0x00,
+ 0x00, 0x27, 0xCD, 0xE9, 0x60, 0x01, 0x70, 0x48, 0xBA, 0x46, 0xB9, 0x46, 0x3D, 0x46, 0x01, 0x21,
+ 0x1C, 0x30, 0x02, 0xF0, 0xE7, 0xFC, 0x6C, 0x48, 0x01, 0x21, 0x24, 0x30, 0x02, 0xF0, 0xE2, 0xFC,
+ 0x69, 0x48, 0x02, 0x21, 0x20, 0x30, 0x02, 0xF0, 0xDD, 0xFC, 0x02, 0x21, 0x6B, 0x48, 0x02, 0xF0,
+ 0x8F, 0xFC, 0x04, 0x21, 0x6A, 0x48, 0x02, 0xF0, 0x8B, 0xFC, 0x63, 0x4C, 0x4F, 0xF4, 0x66, 0x76,
+ 0x31, 0x46, 0xE0, 0x69, 0x0A, 0xF0, 0xC5, 0xFC, 0x31, 0x46, 0x60, 0x6A, 0x0A, 0xF0, 0xC1, 0xFC,
+ 0x64, 0x48, 0xB0, 0xF9, 0x00, 0x00, 0x41, 0x00, 0x20, 0x6A, 0x0A, 0xF0, 0xBA, 0xFC, 0x31, 0x46,
+ 0x61, 0x48, 0x0A, 0xF0, 0xB6, 0xFC, 0x4F, 0xF0, 0x00, 0x0B, 0x5E, 0x46, 0x84, 0xF8, 0x01, 0xB0,
+ 0xF8, 0xF7, 0x0F, 0xFF, 0xF8, 0xF7, 0xC4, 0xFA, 0x5C, 0x48, 0x8D, 0xF8, 0x72, 0x61, 0x01, 0x23,
+ 0x00, 0x68, 0x19, 0x90, 0x00, 0x22, 0x19, 0xA9, 0xA0, 0x69, 0x00, 0xF0, 0xB5, 0xFC, 0x58, 0x48,
+ 0x5E, 0x96, 0x00, 0x24, 0xB0, 0xF9, 0x00, 0x10, 0xB8, 0xF9, 0x00, 0x00, 0x05, 0xF0, 0x4A, 0xF9,
+ 0x0F, 0xFA, 0x80, 0xF8, 0x9D, 0xF8, 0x72, 0x01, 0x01, 0x28, 0x02, 0xD9, 0x42, 0x49, 0x81, 0xF8,
+ 0x00, 0xB0, 0x01, 0x26, 0xF1, 0xE0, 0x19, 0xA8, 0x00, 0xEB, 0x86, 0x00, 0x05, 0x90, 0x19, 0xAA,
+ 0x31, 0x46, 0x07, 0xA8, 0x5E, 0x9B, 0xFF, 0xF7, 0xDA, 0xFC, 0x07, 0xAB, 0x31, 0x46, 0x05, 0x9A,
+ 0x07, 0x98, 0xFF, 0xF7, 0xFC, 0xFC, 0x01, 0x20, 0x00, 0x90, 0x33, 0x46, 0x5E, 0xAA, 0x07, 0xA9,
+ 0x19, 0xA8, 0xFF, 0xF7, 0x47, 0xFC, 0x0D, 0xF1, 0x5A, 0x00, 0x00, 0xF0, 0xAD, 0xFA, 0x78, 0xB1,
+ 0xBD, 0xF8, 0x40, 0x00, 0x40, 0xF0, 0x01, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0x07, 0xA8, 0x00, 0xF0,
+ 0x18, 0xFC, 0x28, 0xB1, 0x3B, 0x48, 0x34, 0x49, 0x00, 0x88, 0x08, 0x80, 0x2C, 0x49, 0x08, 0x80,
+ 0x28, 0x48, 0x00, 0x78, 0x38, 0xB1, 0xBD, 0xF8, 0x40, 0x00, 0x10, 0xF0, 0x06, 0x0F, 0x02, 0xD1,
+ 0x35, 0x48, 0x00, 0x68, 0x08, 0x90, 0x05, 0x98, 0x00, 0xF0, 0xA0, 0xFA, 0x28, 0xB1, 0xBD, 0xF8,
+ 0x40, 0x00, 0x40, 0xF0, 0x08, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0xBD, 0xF9, 0x4E, 0x10, 0x41, 0x45,
+ 0x7E, 0xDD, 0x00, 0x96, 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0x05, 0x9B, 0xFF, 0xF7, 0x97, 0xFE,
+ 0x00, 0x28, 0x76, 0xD1, 0x01, 0x20, 0xB0, 0x40, 0x5E, 0x99, 0x03, 0x90, 0x08, 0x42, 0x67, 0xD1,
+ 0xBD, 0xF8, 0x40, 0x00, 0x10, 0xF4, 0xC0, 0x7F, 0x62, 0xD1, 0x15, 0x48, 0x5E, 0xAA, 0x07, 0xA9,
+ 0xB0, 0xF9, 0x00, 0x00, 0x8D, 0xE8, 0x07, 0x00, 0x13, 0x48, 0x32, 0x46, 0x05, 0x9B, 0x81, 0x69,
+ 0x40, 0x6A, 0xFF, 0xF7, 0x49, 0xFD, 0x5E, 0x9A, 0x03, 0x99, 0x01, 0x90, 0x11, 0x42, 0x4D, 0xD0,
+ 0x0F, 0x49, 0xBD, 0xF8, 0x42, 0x20, 0x09, 0x68, 0x91, 0xF8, 0x0E, 0x33, 0x9A, 0x42, 0x2E, 0xD8,
+ 0x91, 0xF8, 0xE0, 0x12, 0x8A, 0x07, 0x41, 0xD4, 0x49, 0x07, 0x27, 0xE0, 0x4C, 0x07, 0x10, 0x00,
+ 0xEC, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x82, 0x06, 0x10, 0x00,
+ 0x6E, 0x06, 0x10, 0x00, 0x76, 0x06, 0x10, 0x00, 0x14, 0x06, 0x10, 0x00, 0x84, 0x06, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x70, 0x06, 0x10, 0x00, 0x3C, 0x06, 0x10, 0x00,
+ 0x48, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0xB4, 0x18, 0x01, 0x20, 0x64, 0x06, 0x10, 0x00,
+ 0x88, 0x06, 0x10, 0x00, 0x7E, 0x06, 0x10, 0x00, 0xE0, 0x06, 0x10, 0x00, 0x16, 0xD4, 0x01, 0x23,
+ 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0x8D, 0xE8, 0x0F, 0x00, 0xFF, 0x48, 0x0D, 0xF1, 0x56, 0x03,
+ 0x32, 0x46, 0x41, 0x6A, 0x80, 0x69, 0xFF, 0xF7, 0x25, 0xFD, 0x01, 0x90, 0x01, 0x20, 0x00, 0x90,
+ 0x33, 0x46, 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0xFF, 0xF7, 0xA4, 0xFB, 0x01, 0x98, 0x80, 0xB9,
+ 0xBD, 0xF8, 0x42, 0x00, 0x07, 0xA9, 0xFF, 0xF7, 0x6E, 0xFD, 0x50, 0xB1, 0x07, 0xAB, 0x01, 0xE0,
+ 0x0F, 0xE0, 0x28, 0xE0, 0x31, 0x46, 0x05, 0x9A, 0x07, 0x98, 0xFF, 0xF7, 0x7C, 0xFD, 0x01, 0x27,
+ 0x07, 0xE0, 0x33, 0x46, 0x5E, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0xCD, 0xF8, 0x00, 0xB0, 0xFF, 0xF7,
+ 0x89, 0xFB, 0x01, 0x20, 0x5E, 0x99, 0xB0, 0x40, 0x01, 0x43, 0xE8, 0x4A, 0x5E, 0x91, 0x61, 0x99,
+ 0x11, 0x80, 0xE7, 0x4A, 0x60, 0x99, 0x11, 0x80, 0xE6, 0x49, 0x0A, 0x78, 0x32, 0xB1, 0x9D, 0xF8,
+ 0x72, 0x21, 0x04, 0x43, 0x01, 0x2A, 0x01, 0xD9, 0x81, 0xF8, 0x00, 0xB0, 0xBD, 0xF8, 0x40, 0x10,
+ 0xC9, 0x05, 0x00, 0xD5, 0x05, 0x43, 0x76, 0x1C, 0xF6, 0xB2, 0x9D, 0xF8, 0x72, 0x01, 0xB0, 0x42,
+ 0xBF, 0xF4, 0x09, 0xAF, 0xD8, 0x48, 0xDD, 0x4A, 0xDB, 0x4B, 0x41, 0x78, 0xA2, 0xF5, 0x66, 0x70,
+ 0x01, 0xF0, 0x0F, 0xFE, 0xDA, 0x48, 0x9D, 0xF8, 0x72, 0x11, 0x00, 0xF8, 0x05, 0x1F, 0xD9, 0x49,
+ 0x04, 0x83, 0x85, 0x83, 0xD8, 0x48, 0x81, 0xF8, 0x00, 0xA0, 0xD8, 0x49, 0x07, 0x70, 0xD8, 0x48,
+ 0x81, 0xF8, 0x00, 0x90, 0x02, 0x21, 0x02, 0xF0, 0x53, 0xFB, 0x04, 0x21, 0xD5, 0x48, 0x02, 0xF0,
+ 0x4F, 0xFB, 0xC9, 0x48, 0x01, 0x21, 0x18, 0x30, 0x02, 0xF0, 0xDF, 0xFB, 0xC6, 0x48, 0x01, 0x21,
+ 0x1C, 0x30, 0x02, 0xF0, 0xDA, 0xFB, 0xC4, 0x48, 0x01, 0x21, 0x24, 0x30, 0x02, 0xF0, 0xD5, 0xFB,
+ 0xC1, 0x48, 0x02, 0x21, 0x20, 0x30, 0x02, 0xF0, 0xD0, 0xFB, 0x65, 0xB0, 0x82, 0xE4, 0x2D, 0xE9,
+ 0xF0, 0x4F, 0xBF, 0x48, 0x00, 0x25, 0xE3, 0xB0, 0xB0, 0xF9, 0x00, 0x60, 0xBA, 0x48, 0xA9, 0x46,
+ 0xA8, 0x46, 0x01, 0x21, 0x1C, 0x30, 0x02, 0xF0, 0x5D, 0xFB, 0xB7, 0x48, 0x01, 0x21, 0x24, 0x30,
+ 0x02, 0xF0, 0x58, 0xFB, 0xB4, 0x48, 0x02, 0x21, 0x20, 0x30, 0x02, 0xF0, 0x53, 0xFB, 0x02, 0x21,
+ 0xBB, 0x48, 0x02, 0xF0, 0x05, 0xFB, 0x04, 0x21, 0xBA, 0x48, 0x02, 0xF0, 0x01, 0xFB, 0xDF, 0xF8,
+ 0xB8, 0xA2, 0x4F, 0xF4, 0x66, 0x77, 0x39, 0x46, 0x54, 0x46, 0xDA, 0xF8, 0x1C, 0x00, 0x0A, 0xF0,
+ 0x38, 0xFB, 0x39, 0x46, 0x60, 0x6A, 0x0A, 0xF0, 0x34, 0xFB, 0xB3, 0x48, 0xB0, 0xF9, 0x00, 0x00,
+ 0x41, 0x00, 0x20, 0x6A, 0x0A, 0xF0, 0x2D, 0xFB, 0x39, 0x46, 0xB0, 0x48, 0x0A, 0xF0, 0x29, 0xFB,
+ 0xAB, 0x46, 0xAF, 0x48, 0x84, 0xF8, 0x01, 0xB0, 0x8D, 0xF8, 0x72, 0xB1, 0x00, 0x68, 0x19, 0x90,
+ 0x5F, 0x46, 0x01, 0x23, 0x5A, 0x46, 0x19, 0xA9, 0xA0, 0x69, 0x00, 0xF0, 0x2D, 0xFB, 0x01, 0x24,
+ 0x05, 0x97, 0x8C, 0xE0, 0x19, 0xA8, 0x00, 0xEB, 0x84, 0x00, 0x5D, 0x90, 0x19, 0xAA, 0x21, 0x46,
+ 0x07, 0xA8, 0x05, 0x9B, 0xFF, 0xF7, 0x63, 0xFB, 0x07, 0xAB, 0x21, 0x46, 0x5D, 0x9A, 0x07, 0x98,
+ 0xFF, 0xF7, 0x85, 0xFB, 0x01, 0x27, 0x23, 0x46, 0x05, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0x00, 0x97,
+ 0xFF, 0xF7, 0xD0, 0xFA, 0x0D, 0xF1, 0x5A, 0x00, 0x00, 0xF0, 0x36, 0xF9, 0x28, 0xB1, 0xBD, 0xF8,
+ 0x40, 0x00, 0x40, 0xF0, 0x01, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0x5D, 0x98, 0x00, 0xF0, 0x3E, 0xF9,
+ 0x28, 0xB1, 0xBD, 0xF8, 0x40, 0x00, 0x40, 0xF0, 0x08, 0x00, 0xAD, 0xF8, 0x40, 0x00, 0xBD, 0xF9,
+ 0x4E, 0x00, 0xB0, 0x42, 0x55, 0xDD, 0x07, 0xFA, 0x04, 0xF0, 0x05, 0x99, 0x03, 0x90, 0x08, 0x42,
+ 0x39, 0xD1, 0xBD, 0xF8, 0x40, 0x00, 0x10, 0xF4, 0xC0, 0x7F, 0x34, 0xD1, 0x7C, 0x48, 0x05, 0xAA,
+ 0x07, 0xA9, 0xB0, 0xF9, 0x00, 0x00, 0x8D, 0xE8, 0x07, 0x00, 0x22, 0x46, 0x5D, 0x9B, 0xDA, 0xF8,
+ 0x18, 0x10, 0xDA, 0xF8, 0x24, 0x00, 0xFF, 0xF7, 0xEF, 0xFB, 0x5F, 0x90, 0x05, 0x99, 0x03, 0x98,
+ 0x08, 0x42, 0x1E, 0xD0, 0x7F, 0x48, 0xBD, 0xF8, 0x42, 0x10, 0x00, 0x68, 0x90, 0xF8, 0x0E, 0x23,
+ 0x91, 0x42, 0x05, 0xD8, 0x90, 0xF8, 0xE0, 0x02, 0x81, 0x07, 0x12, 0xD4, 0x40, 0x07, 0x10, 0xD4,
+ 0x07, 0xA9, 0x19, 0xAA, 0x05, 0xA8, 0xCD, 0xE9, 0x00, 0x21, 0xCD, 0xE9, 0x02, 0x07, 0x0D, 0xF1,
+ 0x56, 0x03, 0x22, 0x46, 0xDA, 0xF8, 0x24, 0x10, 0xDA, 0xF8, 0x18, 0x00, 0xFF, 0xF7, 0xF2, 0xFB,
+ 0xD8, 0xB9, 0x5F, 0x98, 0x68, 0xB9, 0xBD, 0xF8, 0x42, 0x00, 0x07, 0xA9, 0xFF, 0xF7, 0x43, 0xFC,
+ 0x38, 0xB1, 0x07, 0xAB, 0x21, 0x46, 0x5D, 0x9A, 0x07, 0x98, 0xFF, 0xF7, 0x54, 0xFC, 0x01, 0x25,
+ 0x07, 0xE0, 0x23, 0x46, 0x05, 0xAA, 0x07, 0xA9, 0x19, 0xA8, 0xCD, 0xF8, 0x00, 0xB0, 0xFF, 0xF7,
+ 0x61, 0xFA, 0x05, 0x98, 0xA7, 0x40, 0x07, 0x43, 0x05, 0x97, 0x64, 0x1C, 0xE4, 0xB2, 0x9D, 0xF8,
+ 0x72, 0x01, 0xA0, 0x42, 0xBF, 0xF4, 0x6E, 0xAF, 0x53, 0x4B, 0x54, 0x4A, 0x9A, 0xF8, 0x01, 0x10,
+ 0x5A, 0x48, 0x01, 0xF0, 0xFE, 0xFC, 0x52, 0x49, 0x9D, 0xF8, 0x72, 0x01, 0x48, 0x71, 0x51, 0x49,
+ 0x51, 0x48, 0x81, 0xF8, 0x00, 0x90, 0x51, 0x49, 0x05, 0x70, 0x51, 0x48, 0x81, 0xF8, 0x00, 0x80,
+ 0x02, 0x21, 0x02, 0xF0, 0x45, 0xFA, 0x04, 0x21, 0x4E, 0x48, 0x02, 0xF0, 0x41, 0xFA, 0x42, 0x48,
+ 0x01, 0x21, 0x18, 0x30, 0x02, 0xF0, 0xD1, 0xFA, 0x3F, 0x48, 0x01, 0x21, 0x1C, 0x30, 0x02, 0xF0,
+ 0xCC, 0xFA, 0x3D, 0x48, 0x01, 0x21, 0x24, 0x30, 0x02, 0xF0, 0xC7, 0xFA, 0x3A, 0x48, 0x02, 0x21,
+ 0x20, 0x30, 0x02, 0xF0, 0xC2, 0xFA, 0x63, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x3D, 0x49, 0x00, 0x20,
+ 0x08, 0x70, 0x3D, 0x49, 0x08, 0x70, 0x3D, 0x49, 0x08, 0x70, 0x36, 0x49, 0x08, 0x70, 0xA8, 0x21,
+ 0x35, 0x48, 0x0A, 0xF0, 0x68, 0xBA, 0xF1, 0xE7, 0x2F, 0x49, 0x00, 0x20, 0x38, 0x4A, 0x08, 0x62,
+ 0x88, 0x61, 0xC8, 0x61, 0x10, 0x60, 0x37, 0x4A, 0x10, 0x60, 0x32, 0x4A, 0x10, 0x70, 0x32, 0x4A,
+ 0x10, 0x70, 0x32, 0x4A, 0x10, 0x70, 0x2B, 0x4A, 0x10, 0x70, 0x48, 0x70, 0x70, 0x47, 0x26, 0x49,
+ 0x10, 0xB5, 0x00, 0x20, 0x48, 0x70, 0x4F, 0xF4, 0x66, 0x71, 0x30, 0x48, 0x0A, 0xF0, 0x29, 0xFA,
+ 0x25, 0x48, 0xA8, 0x21, 0xA8, 0x38, 0x0A, 0xF0, 0x46, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0xA8, 0x21,
+ 0x21, 0x48, 0x0A, 0xF0, 0x40, 0xBA, 0x2D, 0xE9, 0xF7, 0x4F, 0x1B, 0x48, 0x0D, 0x46, 0x41, 0x78,
+ 0x0F, 0x29, 0x01, 0xD2, 0x49, 0x1C, 0x41, 0x70, 0x01, 0xF0, 0xFF, 0x09, 0x1B, 0x49, 0x82, 0xF8,
+ 0x41, 0x90, 0x01, 0xEB, 0x89, 0x00, 0x29, 0x68, 0x01, 0x60, 0xA9, 0x78, 0x1F, 0x48, 0x0A, 0xF0,
+ 0x1F, 0xFB, 0x82, 0x46, 0xA8, 0x78, 0x19, 0xE0, 0x00, 0x98, 0x2C, 0x78, 0x00, 0xEB, 0xC8, 0x0B,
+ 0x0D, 0xE0, 0xDB, 0xE9, 0x00, 0x67, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0x43, 0xF9,
+ 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x01, 0xD0, 0x0A, 0xF8, 0x04, 0x90, 0x64, 0x1C, 0x68, 0x78,
+ 0xA0, 0x42, 0xEE, 0xDA, 0x0A, 0xF1, 0x28, 0x0A, 0x08, 0xF1, 0x01, 0x00, 0xE9, 0x78, 0x80, 0x46,
+ 0x41, 0x45, 0xE1, 0xDA, 0xBD, 0xE8, 0xFE, 0x8F, 0x14, 0x06, 0x10, 0x00, 0x70, 0x06, 0x10, 0x00,
+ 0x6E, 0x06, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x48, 0x3F, 0x10, 0x00, 0x4C, 0x1C, 0x01, 0x20,
+ 0xE6, 0x43, 0x01, 0x20, 0xC2, 0x06, 0x10, 0x00, 0xC3, 0x06, 0x10, 0x00, 0xC4, 0x06, 0x10, 0x00,
+ 0x3C, 0x06, 0x10, 0x00, 0x48, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00, 0xB4, 0x18, 0x01, 0x20,
+ 0x64, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x01, 0x78, 0x59, 0xB1, 0x95, 0x4A, 0x12, 0x78,
+ 0x52, 0x1E, 0x91, 0x42, 0x06, 0xD0, 0x40, 0x78, 0x20, 0xB1, 0x93, 0x49, 0x09, 0x78, 0x49, 0x1E,
+ 0x88, 0x42, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x78, 0x29, 0xB1,
+ 0x8C, 0x49, 0x42, 0x78, 0x09, 0x78, 0x49, 0x1E, 0x8A, 0x42, 0x09, 0xD1, 0x81, 0x78, 0x29, 0xB1,
+ 0xC1, 0x78, 0x89, 0x48, 0x00, 0x78, 0x40, 0x1E, 0x81, 0x42, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x47,
+ 0x00, 0x20, 0x70, 0x47, 0xF0, 0xB5, 0x85, 0x4D, 0x00, 0x22, 0x05, 0xEB, 0xC2, 0x06, 0x00, 0x23,
+ 0xC6, 0xE9, 0x00, 0x33, 0x52, 0x1C, 0xD2, 0xB2, 0x17, 0x2A, 0xF6, 0xD3, 0x8A, 0x78, 0x2C, 0xE0,
+ 0x00, 0xEB, 0xC2, 0x03, 0xD3, 0xE9, 0x00, 0x76, 0x57, 0xEA, 0x06, 0x03, 0x23, 0xD0, 0x74, 0x08,
+ 0x4F, 0xEA, 0x37, 0x03, 0x17, 0xEB, 0x07, 0x0E, 0x46, 0xEB, 0x06, 0x0C, 0x44, 0xEA, 0x0C, 0x04,
+ 0x34, 0x43, 0x43, 0xEA, 0x0E, 0x03, 0x05, 0xEB, 0xC2, 0x06, 0x3B, 0x43, 0xD6, 0xE9, 0x00, 0x7C,
+ 0x1F, 0x43, 0x4C, 0xEA, 0x04, 0x0C, 0xC6, 0xE9, 0x00, 0x7C, 0xD6, 0xE9, 0x02, 0x7C, 0x1F, 0x43,
+ 0x4C, 0xEA, 0x04, 0x0C, 0xC6, 0xE9, 0x02, 0x7C, 0xD6, 0xE9, 0x04, 0x7C, 0x1F, 0x43, 0x4C, 0xEA,
+ 0x04, 0x0C, 0xC6, 0xE9, 0x04, 0x7C, 0x52, 0x1C, 0xD2, 0xB2, 0xCB, 0x78, 0x93, 0x42, 0xCF, 0xD2,
+ 0x00, 0x22, 0x65, 0x4B, 0x0A, 0xE0, 0x00, 0xBF, 0x05, 0xEB, 0xC2, 0x04, 0x00, 0xEB, 0xC2, 0x07,
+ 0xD4, 0xE9, 0x02, 0x64, 0xC7, 0xE9, 0x00, 0x64, 0x52, 0x1C, 0xD2, 0xB2, 0x1C, 0x78, 0xA2, 0x42,
+ 0xF2, 0xD3, 0x08, 0x78, 0x08, 0xB1, 0x40, 0x1E, 0x08, 0x70, 0x5A, 0x4A, 0x48, 0x78, 0x12, 0x78,
+ 0x52, 0x1E, 0x90, 0x42, 0x01, 0xDA, 0x40, 0x1C, 0x48, 0x70, 0x88, 0x78, 0x08, 0xB1, 0x40, 0x1E,
+ 0x88, 0x70, 0x1A, 0x78, 0xC8, 0x78, 0x52, 0x1E, 0x90, 0x42, 0x01, 0xDA, 0x40, 0x1C, 0xC8, 0x70,
+ 0xF0, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x94, 0x78, 0x16, 0x46, 0x04, 0xEB, 0x84, 0x02, 0x8B, 0x46,
+ 0x00, 0xEB, 0xC2, 0x00, 0x00, 0x21, 0x00, 0xF1, 0x29, 0x08, 0x20, 0xE0, 0x00, 0x20, 0x81, 0x46,
+ 0x82, 0x46, 0x35, 0x78, 0x77, 0x78, 0x0F, 0xE0, 0x18, 0xF8, 0x05, 0x20, 0x5A, 0x45, 0x09, 0xD1,
+ 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21, 0x0A, 0xF0, 0x66, 0xF8, 0x41, 0xEA, 0x0A, 0x0A, 0x40, 0xEA,
+ 0x09, 0x09, 0x01, 0x21, 0x6D, 0x1C, 0xED, 0xB2, 0xAF, 0x42, 0xED, 0xD2, 0x03, 0x9B, 0x08, 0xF1,
+ 0x28, 0x08, 0x03, 0xEB, 0xC4, 0x03, 0x64, 0x1C, 0xC3, 0xE9, 0x00, 0x9A, 0xE4, 0xB2, 0xF0, 0x78,
+ 0xA0, 0x42, 0xDB, 0xD2, 0x04, 0xB0, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x0A, 0x78, 0x43, 0x78,
+ 0x9A, 0x42, 0x0B, 0xD8, 0x4A, 0x78, 0x03, 0x78, 0x9A, 0x42, 0x07, 0xD3, 0x8A, 0x78, 0xC3, 0x78,
+ 0x9A, 0x42, 0x03, 0xD8, 0xC9, 0x78, 0x80, 0x78, 0x81, 0x42, 0x01, 0xD2, 0x00, 0x20, 0x70, 0x47,
+ 0x01, 0x20, 0x70, 0x47, 0x70, 0xB5, 0x0C, 0x78, 0x8B, 0x78, 0x4D, 0x78, 0xC9, 0x78, 0x9A, 0xB1,
+ 0x0C, 0xB1, 0x64, 0x1E, 0xE4, 0xB2, 0x27, 0x4A, 0x12, 0x78, 0x52, 0x1E, 0x95, 0x42, 0x01, 0xDA,
+ 0x6D, 0x1C, 0xED, 0xB2, 0x0B, 0xB1, 0x5B, 0x1E, 0xDB, 0xB2, 0x23, 0x4A, 0x12, 0x78, 0x52, 0x1E,
+ 0x91, 0x42, 0x01, 0xDA, 0x49, 0x1C, 0xC9, 0xB2, 0x03, 0xEB, 0x83, 0x02, 0x00, 0xEB, 0xC2, 0x02,
+ 0x00, 0x26, 0x29, 0x32, 0x09, 0xE0, 0x20, 0x46, 0x02, 0xE0, 0x16, 0x54, 0x40, 0x1C, 0xC0, 0xB2,
+ 0xA8, 0x42, 0xFA, 0xD9, 0x5B, 0x1C, 0xDB, 0xB2, 0x28, 0x32, 0x8B, 0x42, 0xF3, 0xD9, 0x70, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x43, 0x9C, 0x78, 0x93, 0xF8, 0x03, 0xC0, 0x04, 0xEB, 0x84, 0x05, 0x00, 0xEB,
+ 0xC5, 0x05, 0x10, 0x48, 0x90, 0xF8, 0x00, 0x90, 0x04, 0xFB, 0x09, 0xF0, 0x01, 0xEB, 0x40, 0x06,
+ 0x00, 0x20, 0x29, 0x35, 0x12, 0xE0, 0x19, 0x78, 0x5F, 0x78, 0x08, 0xE0, 0x15, 0xF8, 0x01, 0x80,
+ 0x90, 0x45, 0x02, 0xD1, 0x36, 0xF9, 0x11, 0x80, 0x40, 0x44, 0x49, 0x1C, 0xC9, 0xB2, 0x8F, 0x42,
+ 0xF4, 0xD2, 0x64, 0x1C, 0x06, 0xEB, 0x49, 0x06, 0xE4, 0xB2, 0x28, 0x35, 0xA4, 0x45, 0xEA, 0xD2,
+ 0xBD, 0xE8, 0xF0, 0x83, 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0xF0, 0x3F, 0x10, 0x00,
+ 0x2D, 0xE9, 0xF0, 0x47, 0x80, 0x46, 0x27, 0x48, 0x8C, 0x78, 0x0D, 0x46, 0x00, 0x78, 0x80, 0x1E,
+ 0x01, 0x2C, 0x05, 0xD9, 0xE9, 0x78, 0x81, 0x42, 0x02, 0xDA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87,
+ 0x02, 0x2C, 0x01, 0xD2, 0x02, 0x27, 0x01, 0xE0, 0xEF, 0x78, 0xC4, 0xB2, 0x4F, 0xF0, 0x00, 0x09,
+ 0x21, 0x46, 0xD8, 0xF8, 0x08, 0x00, 0x0A, 0xF0, 0x83, 0xF9, 0x06, 0x46, 0x21, 0x46, 0xD8, 0xF8,
+ 0x04, 0x00, 0x0A, 0xF0, 0x7D, 0xF9, 0x01, 0x46, 0x17, 0x48, 0x02, 0x78, 0x15, 0xE0, 0x28, 0x78,
+ 0x6B, 0x78, 0x0A, 0xE0, 0x36, 0xF9, 0x10, 0xC0, 0x31, 0xF9, 0x10, 0x80, 0xC4, 0x45, 0x02, 0xD0,
+ 0x4F, 0xF0, 0x01, 0x09, 0x03, 0xE0, 0x40, 0x1C, 0xC0, 0xB2, 0x83, 0x42, 0xF2, 0xD2, 0x64, 0x1C,
+ 0x06, 0xEB, 0x42, 0x06, 0x01, 0xEB, 0x42, 0x01, 0xE4, 0xB2, 0xBC, 0x42, 0xE7, 0xD9, 0x48, 0x46,
+ 0xCC, 0xE7, 0x08, 0x49, 0x09, 0x78, 0x49, 0x1E, 0xCA, 0xB2, 0x90, 0xF8, 0x3F, 0x10, 0x09, 0xB1,
+ 0x91, 0x42, 0x05, 0xD1, 0x81, 0x8C, 0x41, 0xF0, 0x02, 0x01, 0x81, 0x84, 0x01, 0x20, 0x70, 0x47,
+ 0x00, 0x20, 0x70, 0x47, 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x30, 0xB5, 0xB0, 0xB1,
+ 0x88, 0x42, 0x14, 0xD0, 0x02, 0xD2, 0x0A, 0x46, 0x01, 0x46, 0x10, 0x46, 0xC9, 0x4A, 0x53, 0x68,
+ 0x03, 0xEB, 0x40, 0x03, 0x1C, 0x78, 0x8C, 0x42, 0x09, 0xD0, 0x5C, 0x78, 0x8C, 0x42, 0x06, 0xD0,
+ 0x95, 0x68, 0x2A, 0x5C, 0x02, 0x2A, 0x02, 0xD2, 0x54, 0x1C, 0x2C, 0x54, 0x99, 0x54, 0x08, 0x46,
+ 0x30, 0xBD, 0xF0, 0xB5, 0x03, 0xEB, 0x82, 0x04, 0xA5, 0x78, 0x05, 0xEB, 0x85, 0x06, 0x00, 0xEB,
+ 0xC6, 0x06, 0xE0, 0x78, 0x28, 0x36, 0xA8, 0x42, 0x0F, 0xD3, 0x20, 0x78, 0x07, 0xE0, 0x37, 0x18,
+ 0x97, 0xF8, 0x01, 0xC0, 0x94, 0x45, 0x00, 0xD1, 0x79, 0x70, 0x40, 0x1C, 0xC0, 0xB2, 0x67, 0x78,
+ 0x87, 0x42, 0xF4, 0xD2, 0x6D, 0x1C, 0xED, 0xB2, 0xEB, 0xE7, 0x03, 0xEB, 0x81, 0x00, 0x25, 0x68,
+ 0x05, 0x60, 0x03, 0xEB, 0x42, 0x00, 0x03, 0xEB, 0x41, 0x01, 0x30, 0xF8, 0xB4, 0x2F, 0xA1, 0xF8,
+ 0xB4, 0x20, 0xAD, 0x49, 0x09, 0x68, 0x21, 0x60, 0x00, 0x21, 0x01, 0x80, 0x93, 0xF8, 0x0E, 0x01,
+ 0x40, 0x1E, 0x83, 0xF8, 0x0E, 0x01, 0xF0, 0xBD, 0x2D, 0xE9, 0xFF, 0x4F, 0x88, 0x46, 0x08, 0x46,
+ 0x09, 0x78, 0x8F, 0xB0, 0xFF, 0x29, 0x13, 0xD0, 0x8A, 0x46, 0xA4, 0x49, 0x42, 0x78, 0x09, 0x78,
+ 0x8A, 0x42, 0x00, 0xD2, 0x51, 0x1C, 0xCE, 0xB2, 0xA1, 0x49, 0x90, 0xF8, 0x02, 0x90, 0xC0, 0x78,
+ 0x09, 0x78, 0x88, 0x42, 0x01, 0xD2, 0x40, 0x1C, 0x00, 0xE0, 0x08, 0x46, 0xC7, 0xB2, 0x04, 0xE0,
+ 0x4F, 0xF0, 0x00, 0x0A, 0x56, 0x46, 0xD1, 0x46, 0x57, 0x46, 0x11, 0x98, 0x4F, 0xF0, 0x00, 0x0B,
+ 0x08, 0xB1, 0x98, 0xF8, 0x0E, 0xB1, 0x93, 0x4A, 0x11, 0x68, 0x01, 0xF1, 0x5A, 0x00, 0xC2, 0xE9,
+ 0x01, 0x10, 0x02, 0x46, 0x5F, 0xF0, 0x2C, 0x00, 0x00, 0x23, 0x01, 0xF8, 0x10, 0x00, 0x13, 0x54,
+ 0x40, 0x1E, 0xC0, 0xB2, 0xF8, 0xD2, 0x0B, 0xF1, 0x01, 0x00, 0x0D, 0x90, 0xC0, 0xB2, 0x06, 0x90,
+ 0x0F, 0x98, 0x09, 0xEB, 0x89, 0x01, 0x00, 0xEB, 0xC1, 0x05, 0x09, 0xF1, 0x01, 0x00, 0x09, 0x95,
+ 0x39, 0xE0, 0x00, 0xBF, 0x0A, 0xF1, 0x01, 0x00, 0x0A, 0x95, 0xC4, 0xB2, 0x28, 0x35, 0x2E, 0xE0,
+ 0x29, 0x19, 0x08, 0x68, 0xE0, 0xB1, 0x28, 0x5D, 0x38, 0xB3, 0x11, 0xF8, 0x01, 0x1C, 0x00, 0x20,
+ 0x01, 0xB1, 0x08, 0x46, 0x0A, 0x99, 0x09, 0x5D, 0x09, 0xB1, 0xFF, 0xF7, 0x57, 0xFF, 0x12, 0x99,
+ 0x61, 0xB1, 0x0A, 0x99, 0x21, 0x44, 0x0E, 0x91, 0x11, 0xF8, 0x01, 0x1C, 0x09, 0xB1, 0xFF, 0xF7,
+ 0x4D, 0xFF, 0x0E, 0x99, 0x49, 0x78, 0x09, 0xB1, 0xFF, 0xF7, 0x48, 0xFF, 0x18, 0xB1, 0x0B, 0xE0,
+ 0xE4, 0x1C, 0xE4, 0xB2, 0x09, 0xE0, 0x06, 0x98, 0x2D, 0x28, 0x03, 0xD2, 0x41, 0x1C, 0xC9, 0xB2,
+ 0x06, 0x91, 0x01, 0xE0, 0x40, 0x1E, 0xC0, 0xB2, 0x28, 0x55, 0x64, 0x1C, 0xE4, 0xB2, 0xB4, 0x42,
+ 0xCE, 0xD9, 0x07, 0x98, 0x40, 0x1C, 0xC0, 0xB2, 0x07, 0x90, 0xB8, 0x42, 0xC2, 0xD9, 0x06, 0x98,
+ 0x00, 0xF0, 0x6F, 0xF8, 0x06, 0x90, 0x0D, 0x98, 0x00, 0x22, 0xC0, 0xB2, 0x62, 0x4C, 0x09, 0xE0,
+ 0x08, 0xEB, 0x80, 0x03, 0x21, 0x68, 0x19, 0x60, 0x08, 0xEB, 0x40, 0x01, 0x40, 0x1C, 0xA1, 0xF8,
+ 0xB4, 0x20, 0xC0, 0xB2, 0x06, 0x99, 0x88, 0x42, 0xF2, 0xD3, 0x09, 0x98, 0x4D, 0x46, 0x28, 0x30,
+ 0x00, 0x90, 0x39, 0xE0, 0x54, 0x46, 0x30, 0xE0, 0x20, 0x44, 0x01, 0x21, 0x09, 0x58, 0xE9, 0xB3,
+ 0x41, 0x78, 0x41, 0xB3, 0x53, 0x4A, 0x52, 0x68, 0x12, 0xF8, 0x11, 0x10, 0x41, 0x70, 0x08, 0xEB,
+ 0x41, 0x00, 0x08, 0xEB, 0x81, 0x09, 0x30, 0xF8, 0xB4, 0x2F, 0x52, 0x1C, 0x02, 0x80, 0x99, 0xF8,
+ 0x00, 0x10, 0x20, 0x46, 0x04, 0xF0, 0xE6, 0xFB, 0x89, 0xF8, 0x00, 0x00, 0x99, 0xF8, 0x01, 0x10,
+ 0x20, 0x46, 0x04, 0xF0, 0xE3, 0xFB, 0x89, 0xF8, 0x01, 0x00, 0x99, 0xF8, 0x02, 0x10, 0x28, 0x46,
+ 0x04, 0xF0, 0xD8, 0xFB, 0x89, 0xF8, 0x02, 0x00, 0x99, 0xF8, 0x03, 0x10, 0x28, 0x46, 0x04, 0xF0,
+ 0xD5, 0xFB, 0x89, 0xF8, 0x03, 0x00, 0x64, 0x1C, 0xE4, 0xB2, 0x00, 0x98, 0xB4, 0x42, 0xCB, 0xD3,
+ 0x28, 0x30, 0x6D, 0x1C, 0xED, 0xB2, 0x00, 0x90, 0xBD, 0x42, 0xC3, 0xD3, 0x06, 0x98, 0x40, 0x1E,
+ 0xC2, 0xB2, 0x88, 0xF8, 0x0E, 0x21, 0x11, 0x98, 0x00, 0x28, 0x00, 0xE0, 0x0B, 0xE0, 0x0D, 0xD0,
+ 0xA2, 0xEB, 0x0B, 0x00, 0x01, 0x28, 0x09, 0xD1, 0x11, 0x99, 0x0F, 0x98, 0x13, 0xB0, 0x43, 0x46,
+ 0xBD, 0xE8, 0xF0, 0x4F, 0xDD, 0xE6, 0xE4, 0x1C, 0xE4, 0xB2, 0xDC, 0xE7, 0x13, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0x2D, 0xE9, 0xF0, 0x5F, 0x07, 0x46, 0x00, 0x25, 0xDF, 0xF8, 0xA8, 0xB0, 0x2C, 0xE0,
+ 0xDB, 0xF8, 0x08, 0x10, 0x4E, 0x5D, 0xDB, 0xF8, 0x04, 0x10, 0x01, 0xEB, 0x45, 0x0A, 0x1A, 0xE0,
+ 0x0A, 0xEB, 0x06, 0x00, 0x80, 0x46, 0x10, 0xF8, 0x01, 0x1C, 0x10, 0xF8, 0x02, 0x9C, 0x08, 0x46,
+ 0x00, 0xF0, 0x35, 0xF8, 0x04, 0x46, 0x48, 0x46, 0x00, 0xF0, 0x31, 0xF8, 0x84, 0x42, 0x02, 0xD2,
+ 0x01, 0x46, 0x20, 0x46, 0x0C, 0x46, 0xDB, 0xF8, 0x04, 0x10, 0x76, 0x1E, 0xF6, 0xB2, 0x01, 0xF8,
+ 0x10, 0x40, 0x08, 0xF8, 0x02, 0x4C, 0x01, 0x2E, 0xE2, 0xD8, 0x04, 0xD1, 0x28, 0x46, 0x00, 0xF0,
+ 0x1E, 0xF8, 0x8A, 0xF8, 0x00, 0x00, 0x6D, 0x1C, 0xED, 0xB2, 0xBD, 0x42, 0xD0, 0xD3, 0x00, 0x21,
+ 0x08, 0x46, 0xDB, 0xF8, 0x04, 0x40, 0x0D, 0xE0, 0x04, 0xEB, 0x40, 0x02, 0x13, 0x78, 0x83, 0x42,
+ 0x03, 0xD1, 0x11, 0x70, 0x49, 0x1C, 0xC9, 0xB2, 0x02, 0xE0, 0x14, 0xF8, 0x13, 0x30, 0x13, 0x70,
+ 0x40, 0x1C, 0xC0, 0xB2, 0xB8, 0x42, 0xEF, 0xD3, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x05, 0x4A,
+ 0xD2, 0xE9, 0x01, 0x12, 0x02, 0xE0, 0x00, 0xBF, 0x11, 0xF8, 0x10, 0x00, 0x13, 0x5C, 0x00, 0x2B,
+ 0xFA, 0xD1, 0x70, 0x47, 0x3C, 0x06, 0x10, 0x00, 0x52, 0x6C, 0x01, 0x00, 0xBA, 0x06, 0x10, 0x00,
+ 0xB9, 0x06, 0x10, 0x00, 0xF0, 0xB5, 0xB2, 0xF9, 0x00, 0x40, 0x06, 0x68, 0xB4, 0x42, 0x02, 0xDD,
+ 0xB3, 0xF9, 0x00, 0x10, 0x30, 0xE0, 0x02, 0xEB, 0x41, 0x04, 0x34, 0xF9, 0x02, 0x5C, 0xB5, 0x42,
+ 0x04, 0xDA, 0x03, 0xEB, 0x41, 0x01, 0x31, 0xF9, 0x02, 0x1C, 0x25, 0xE0, 0x00, 0x25, 0x2C, 0x46,
+ 0x4F, 0x1E, 0x0C, 0xE0, 0x32, 0xF9, 0x14, 0xC0, 0xB4, 0x45, 0x07, 0xDC, 0x02, 0xEB, 0x44, 0x0C,
+ 0xBC, 0xF9, 0x02, 0xC0, 0xB4, 0x45, 0x01, 0xDB, 0x25, 0x46, 0x0C, 0x46, 0x64, 0x1C, 0xBC, 0x42,
+ 0xF0, 0xDB, 0x32, 0xF9, 0x15, 0x40, 0x03, 0xEB, 0x45, 0x01, 0x33, 0xF9, 0x15, 0x30, 0xB1, 0xF9,
+ 0x02, 0x10, 0x02, 0xEB, 0x45, 0x02, 0x36, 0x1B, 0xC9, 0x1A, 0xB2, 0xF9, 0x02, 0x20, 0x71, 0x43,
+ 0x12, 0x1B, 0x91, 0xFB, 0xF2, 0xF1, 0x19, 0x44, 0x01, 0x60, 0xF0, 0xBD, 0x2D, 0xE9, 0xF0, 0x41,
+ 0x05, 0x46, 0x1E, 0x48, 0x00, 0x68, 0x00, 0xF2, 0x0F, 0x53, 0x11, 0xB3, 0x03, 0x29, 0x27, 0xD0,
+ 0x04, 0x29, 0x30, 0xD1, 0x90, 0xF8, 0x08, 0x15, 0x90, 0xF8, 0x09, 0x45, 0x90, 0xF8, 0x0E, 0x05,
+ 0x03, 0xEB, 0x41, 0x06, 0x03, 0xEB, 0x40, 0x0C, 0x50, 0x18, 0x20, 0x44, 0x0C, 0xEB, 0x41, 0x07,
+ 0x64, 0x28, 0x20, 0xDC, 0x01, 0x29, 0x03, 0xDD, 0x28, 0x1D, 0x62, 0x46, 0xFF, 0xF7, 0xA2, 0xFF,
+ 0x01, 0x2C, 0x18, 0xDD, 0x28, 0x46, 0x33, 0x46, 0x3A, 0x46, 0x21, 0x46, 0xBD, 0xE8, 0xF0, 0x41,
+ 0x98, 0xE7, 0x90, 0xF8, 0x08, 0x15, 0x90, 0xF8, 0x09, 0x45, 0x90, 0xF8, 0x0A, 0x25, 0x05, 0xE0,
+ 0x90, 0xF8, 0x08, 0x15, 0x90, 0xF8, 0x09, 0x45, 0x90, 0xF8, 0x0D, 0x25, 0x03, 0xEB, 0x41, 0x06,
+ 0x03, 0xEB, 0x42, 0x0C, 0xD8, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x30, 0xB5, 0x42, 0x78, 0x03, 0x78, 0xCD, 0x8C, 0xD2, 0x1A, 0xC3, 0x78, 0x80, 0x78, 0x52, 0x1C,
+ 0x1B, 0x1A, 0x5B, 0x1C, 0x05, 0xFB, 0x02, 0xF0, 0xD4, 0x18, 0x5D, 0x43, 0x40, 0x00, 0x6A, 0x00,
+ 0xB0, 0xFB, 0xF4, 0xF0, 0xB2, 0xFB, 0xF4, 0xF2, 0x90, 0x42, 0x02, 0xD9, 0xC8, 0x85, 0x0A, 0x86,
+ 0x30, 0xBD, 0xCA, 0x85, 0x08, 0x86, 0x30, 0xBD, 0x2D, 0xE9, 0xFF, 0x4F, 0x00, 0x27, 0x83, 0xB0,
+ 0x15, 0x46, 0x01, 0x97, 0x00, 0x97, 0x3E, 0x46, 0x3C, 0x46, 0xBB, 0x46, 0x91, 0x78, 0x09, 0xF0,
+ 0xF9, 0xFE, 0x82, 0x46, 0xAB, 0x78, 0x95, 0xF8, 0x03, 0x90, 0x28, 0xE0, 0x29, 0x78, 0x95, 0xF8,
+ 0x01, 0xC0, 0x8E, 0x46, 0x1D, 0xE0, 0x00, 0xBF, 0x1A, 0xF8, 0x01, 0x20, 0x04, 0x98, 0x82, 0x42,
+ 0x15, 0xD1, 0xA1, 0xEB, 0x0E, 0x02, 0x52, 0x1C, 0xDD, 0xF8, 0x00, 0x80, 0xA9, 0xEB, 0x03, 0x00,
+ 0x02, 0xFB, 0x02, 0x88, 0x40, 0x1C, 0xCD, 0xF8, 0x00, 0x80, 0xDD, 0xF8, 0x04, 0x80, 0x16, 0x44,
+ 0x02, 0xFB, 0x00, 0x82, 0x00, 0xFB, 0x00, 0xBB, 0x04, 0x44, 0x7F, 0x1C, 0x01, 0x92, 0x49, 0x1C,
+ 0xC9, 0xB2, 0x8C, 0x45, 0xE0, 0xD2, 0x5B, 0x1C, 0x0A, 0xF1, 0x28, 0x0A, 0xDB, 0xB2, 0x99, 0x45,
+ 0xD4, 0xD2, 0x4F, 0xF4, 0x7A, 0x70, 0x70, 0x43, 0x90, 0xFB, 0xF7, 0xF1, 0x4F, 0xF4, 0x7A, 0x70,
+ 0x60, 0x43, 0x90, 0xFB, 0xF7, 0xF3, 0x4F, 0xF4, 0x7A, 0x72, 0x01, 0xFB, 0x04, 0xF0, 0x71, 0x43,
+ 0x90, 0xFB, 0xF2, 0xF7, 0x91, 0xFB, 0xF2, 0xF6, 0x63, 0x43, 0x93, 0xFB, 0xF2, 0xF3, 0x01, 0x98,
+ 0x00, 0x99, 0xC0, 0x1B, 0x89, 0x1B, 0xAB, 0xEB, 0x03, 0x02, 0x06, 0x9C, 0x8B, 0x1A, 0x00, 0xD5,
+ 0x5B, 0x42, 0x00, 0x28, 0x00, 0xDA, 0x40, 0x42, 0x03, 0xEB, 0x40, 0x00, 0x11, 0x44, 0x0A, 0x18,
+ 0x08, 0x1A, 0x52, 0x10, 0x40, 0x10, 0x4F, 0xF4, 0x7A, 0x71, 0x48, 0x43, 0x90, 0xFB, 0xF2, 0xF0,
+ 0xC0, 0xF5, 0x7A, 0x70, 0xA0, 0x85, 0x06, 0x99, 0x07, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x4F,
+ 0x6E, 0xE7, 0x00, 0x00, 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x25, 0xDD, 0xF8, 0x38, 0x80, 0x8B, 0x46,
+ 0x99, 0x46, 0x14, 0x46, 0x2E, 0x46, 0x2F, 0x46, 0x41, 0x46, 0x00, 0x98, 0x09, 0xF0, 0x88, 0xFE,
+ 0x30, 0xF9, 0x19, 0x00, 0xA0, 0x42, 0x32, 0xDD, 0xA8, 0xF1, 0x01, 0x00, 0x44, 0xB2, 0x08, 0xF1,
+ 0x01, 0x08, 0x28, 0xE0, 0x00, 0x2C, 0x22, 0xDB, 0xA9, 0x48, 0x00, 0x78, 0x84, 0x42, 0x1E, 0xDA,
+ 0xE1, 0xB2, 0x00, 0x98, 0x09, 0xF0, 0x74, 0xFE, 0xA6, 0x49, 0x82, 0x46, 0xA9, 0xF1, 0x01, 0x00,
+ 0x0A, 0x78, 0x40, 0xB2, 0x09, 0xF1, 0x01, 0x01, 0x0E, 0xE0, 0x00, 0x28, 0x08, 0xDB, 0x90, 0x42,
+ 0x06, 0xDA, 0x3B, 0xF9, 0x15, 0x30, 0x3A, 0xF9, 0x10, 0xC0, 0x1F, 0x44, 0x0C, 0xFB, 0x03, 0x66,
+ 0x6D, 0x1C, 0x40, 0x1C, 0xED, 0xB2, 0x40, 0xB2, 0x88, 0x42, 0xEE, 0xDD, 0x01, 0xE0, 0xED, 0x1C,
+ 0xED, 0xB2, 0x64, 0x1C, 0x64, 0xB2, 0x44, 0x45, 0xD4, 0xDD, 0x0F, 0xB1, 0x01, 0xE0, 0x06, 0x46,
+ 0x01, 0x27, 0x96, 0xFB, 0xF7, 0xF0, 0x04, 0xB0, 0x00, 0xB2, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9,
+ 0xFF, 0x4F, 0x83, 0xB0, 0x91, 0x46, 0x10, 0x99, 0x08, 0x78, 0x00, 0xB1, 0x40, 0x1E, 0xC4, 0xB2,
+ 0x88, 0x78, 0x00, 0xB1, 0x40, 0x1E, 0xDF, 0xF8, 0x2C, 0xA2, 0xC5, 0xB2, 0x4A, 0x78, 0x9A, 0xF8,
+ 0x00, 0x00, 0x43, 0x1E, 0x9A, 0x42, 0x01, 0xDA, 0x50, 0x1C, 0x00, 0xE0, 0x40, 0x1E, 0xDF, 0xF8,
+ 0x10, 0xB2, 0xC6, 0xB2, 0xC9, 0x78, 0x9B, 0xF8, 0x00, 0x00, 0x42, 0x1E, 0x91, 0x42, 0x01, 0xDA,
+ 0x48, 0x1C, 0x00, 0xE0, 0x40, 0x1E, 0xC7, 0xB2, 0xCC, 0xB9, 0xA8, 0x46, 0x12, 0xE0, 0x01, 0x46,
+ 0x03, 0x98, 0x09, 0xF0, 0x2B, 0xFE, 0xCD, 0xE9, 0x00, 0x80, 0x23, 0x46, 0x49, 0x46, 0x06, 0x9A,
+ 0x04, 0x98, 0xFF, 0xF7, 0x7F, 0xFF, 0x01, 0x99, 0x21, 0xF8, 0x14, 0x00, 0x08, 0xF1, 0x01, 0x00,
+ 0x00, 0xF0, 0xFF, 0x08, 0x40, 0x46, 0xB8, 0x45, 0xE9, 0xD9, 0x64, 0x1C, 0xE4, 0xB2, 0x71, 0x48,
+ 0x00, 0x78, 0x40, 0x1E, 0x86, 0x42, 0x19, 0xD1, 0xA8, 0x46, 0x12, 0xE0, 0x01, 0x46, 0x03, 0x98,
+ 0x09, 0xF0, 0x0C, 0xFE, 0x82, 0x46, 0x33, 0x46, 0xCD, 0xF8, 0x00, 0x80, 0x49, 0x46, 0x06, 0x9A,
+ 0x04, 0x98, 0xFF, 0xF7, 0x5F, 0xFF, 0x2A, 0xF8, 0x16, 0x00, 0x08, 0xF1, 0x01, 0x00, 0x00, 0xF0,
+ 0xFF, 0x08, 0x40, 0x46, 0xB8, 0x45, 0xE9, 0xD9, 0x76, 0x1E, 0xF6, 0xB2, 0xC5, 0xB9, 0x29, 0x46,
+ 0x03, 0x98, 0x09, 0xF0, 0xF3, 0xFD, 0x82, 0x46, 0xA0, 0x46, 0x0C, 0xE0, 0x03, 0x46, 0x00, 0x95,
+ 0x49, 0x46, 0x06, 0x9A, 0x04, 0x98, 0xFF, 0xF7, 0x45, 0xFF, 0x2A, 0xF8, 0x18, 0x00, 0x08, 0xF1,
+ 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x08, 0x40, 0x46, 0xB0, 0x45, 0xEF, 0xD9, 0x6D, 0x1C, 0xED, 0xB2,
+ 0x9B, 0xF8, 0x00, 0x00, 0x40, 0x1E, 0x87, 0x42, 0x18, 0xD1, 0x39, 0x46, 0x03, 0x98, 0x09, 0xF0,
+ 0xD5, 0xFD, 0x82, 0x46, 0xA0, 0x46, 0x0C, 0xE0, 0x03, 0x46, 0x00, 0x97, 0x49, 0x46, 0x06, 0x9A,
+ 0x04, 0x98, 0xFF, 0xF7, 0x27, 0xFF, 0x2A, 0xF8, 0x18, 0x00, 0x08, 0xF1, 0x01, 0x00, 0x00, 0xF0,
+ 0xFF, 0x08, 0x40, 0x46, 0xB0, 0x45, 0xEF, 0xD9, 0x7F, 0x1E, 0xFF, 0xB2, 0xB9, 0xF9, 0x12, 0x00,
+ 0x5F, 0xEA, 0x00, 0x0A, 0x65, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0x62, 0xE0, 0x29, 0x46, 0x03, 0x98,
+ 0x09, 0xF0, 0xB4, 0xFD, 0x01, 0x90, 0x68, 0x1E, 0xC1, 0xB2, 0x04, 0x98, 0x09, 0xF0, 0xA0, 0xFD,
+ 0x00, 0x90, 0x29, 0x46, 0x04, 0x98, 0x09, 0xF0, 0x9B, 0xFD, 0x21, 0x46, 0x4D, 0xE0, 0x00, 0xBF,
+ 0x30, 0xF9, 0x11, 0x20, 0x06, 0x9B, 0x9A, 0x42, 0x42, 0xDD, 0x00, 0x9A, 0xB9, 0xF9, 0x00, 0x80,
+ 0x02, 0xEB, 0x41, 0x02, 0x00, 0x23, 0x32, 0xF9, 0x02, 0xCD, 0x0C, 0xFB, 0x08, 0x33, 0xB2, 0xF9,
+ 0x02, 0xC0, 0xB9, 0xF9, 0x02, 0x80, 0x0C, 0xFB, 0x08, 0x33, 0xB2, 0xF9, 0x04, 0xC0, 0xB9, 0xF9,
+ 0x04, 0x80, 0x0C, 0xFB, 0x08, 0x3B, 0x2B, 0x4B, 0xB9, 0xF9, 0x06, 0x80, 0x93, 0xF8, 0x00, 0xE0,
+ 0x02, 0xEB, 0x4E, 0x02, 0xB2, 0xF9, 0x00, 0xC0, 0x0C, 0xFB, 0x08, 0xB3, 0xB2, 0xF9, 0x02, 0xC0,
+ 0xB9, 0xF9, 0x08, 0x80, 0x0C, 0xFB, 0x08, 0x33, 0xB2, 0xF9, 0x04, 0xC0, 0xB9, 0xF9, 0x0A, 0x80,
+ 0x02, 0xEB, 0x4E, 0x02, 0x0C, 0xFB, 0x08, 0x3B, 0xB2, 0xF9, 0x00, 0xC0, 0xB9, 0xF9, 0x0C, 0x80,
+ 0x0C, 0xFB, 0x08, 0xB3, 0xB2, 0xF9, 0x02, 0xC0, 0xB9, 0xF9, 0x0E, 0x80, 0x0C, 0xFB, 0x08, 0x33,
+ 0xB2, 0xF9, 0x04, 0xC0, 0xB9, 0xF9, 0x10, 0x20, 0x0C, 0xFB, 0x02, 0x32, 0x92, 0xFB, 0xFA, 0xF2,
+ 0x01, 0x9B, 0x23, 0xF8, 0x11, 0x20, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xB0, 0xD9, 0x6D, 0x1C,
+ 0xED, 0xB2, 0xBD, 0x42, 0x9A, 0xD9, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1C, 0xB5, 0x0E, 0x4C,
+ 0x24, 0x68, 0x01, 0x94, 0x01, 0xAC, 0x00, 0x94, 0xFF, 0xF7, 0xF1, 0xFE, 0x1C, 0xBD, 0x38, 0xB5,
+ 0x0D, 0x4D, 0x00, 0x90, 0x09, 0x48, 0x0C, 0x46, 0x09, 0x4A, 0x00, 0x68, 0xB0, 0xF9, 0xE2, 0x32,
+ 0x08, 0x48, 0x01, 0x68, 0x28, 0x68, 0xFF, 0xF7, 0xE2, 0xFE, 0x28, 0x68, 0xA0, 0x60, 0x38, 0xBD,
+ 0xB9, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x64, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x3E, 0x6C, 0x01, 0x00, 0xDC, 0x06, 0x10, 0x00, 0x34, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x5F,
+ 0x89, 0x46, 0x14, 0x46, 0x91, 0x78, 0x0F, 0x9D, 0x09, 0xF0, 0x0C, 0xFD, 0x82, 0x46, 0xA1, 0x78,
+ 0xA8, 0x68, 0x09, 0xF0, 0x0D, 0xFD, 0x47, 0xF6, 0xFF, 0x76, 0xA7, 0x78, 0xF5, 0x43, 0xFE, 0x49,
+ 0x94, 0xF8, 0x03, 0x80, 0x91, 0xF8, 0x00, 0xB0, 0x18, 0xE0, 0x22, 0x78, 0x94, 0xF8, 0x01, 0xC0,
+ 0x0D, 0xE0, 0x00, 0xBF, 0x1A, 0xF8, 0x02, 0x10, 0x49, 0x45, 0x07, 0xD1, 0x30, 0xF9, 0x12, 0x30,
+ 0xB3, 0x42, 0x00, 0xDA, 0x1E, 0x46, 0xAB, 0x42, 0x00, 0xDD, 0x1D, 0x46, 0x52, 0x1C, 0x94, 0x45,
+ 0xF0, 0xD2, 0x0A, 0xF1, 0x28, 0x0A, 0x00, 0xEB, 0x4B, 0x00, 0x7F, 0x1C, 0xB8, 0x45, 0xE4, 0xD2,
+ 0x03, 0x98, 0x06, 0x80, 0x0E, 0x98, 0x05, 0x80, 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xFF, 0x4F,
+ 0xEA, 0x48, 0x85, 0xB0, 0x9A, 0x46, 0x04, 0x68, 0x03, 0xA9, 0xCD, 0xE9, 0x00, 0x1A, 0xDD, 0xE9,
+ 0x05, 0x01, 0x15, 0x46, 0x04, 0xF5, 0x88, 0x79, 0x02, 0xAB, 0xFF, 0xF7, 0xB7, 0xFF, 0xE4, 0x48,
+ 0xBD, 0xF9, 0x0C, 0x20, 0xDF, 0xF8, 0x8C, 0xB3, 0x00, 0x68, 0x5F, 0x46, 0x90, 0xF8, 0xE4, 0x12,
+ 0xBD, 0xF9, 0x08, 0x00, 0x12, 0x1A, 0x4A, 0x43, 0x64, 0x21, 0x92, 0xFB, 0xF1, 0xF1, 0x0E, 0x18,
+ 0x01, 0x22, 0x29, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0xFF, 0xF7, 0xBC, 0xFA, 0xD7, 0xF8, 0x00, 0x80,
+ 0xDD, 0xE9, 0x05, 0x07, 0x31, 0xB2, 0x01, 0x91, 0xA9, 0x78, 0x09, 0xF0, 0xAB, 0xFC, 0x06, 0x46,
+ 0xA9, 0x78, 0x40, 0x46, 0x09, 0xF0, 0xB4, 0xFC, 0x00, 0x90, 0xA9, 0x78, 0xDA, 0xF8, 0x08, 0x00,
+ 0x09, 0xF0, 0xA6, 0xFC, 0x01, 0x46, 0xAA, 0x78, 0x01, 0x23, 0xDF, 0xF8, 0x2C, 0xE3, 0x1D, 0xE0,
+ 0x28, 0x78, 0x0E, 0xE0, 0x16, 0xF8, 0x00, 0xC0, 0xBC, 0x45, 0x09, 0xD1, 0x31, 0xF9, 0x10, 0x80,
+ 0xDD, 0xF8, 0x04, 0xC0, 0xE0, 0x45, 0x03, 0xDD, 0xDD, 0xF8, 0x00, 0xC0, 0x0C, 0xF8, 0x00, 0x30,
+ 0x40, 0x1C, 0x95, 0xF8, 0x01, 0xC0, 0x84, 0x45, 0xEC, 0xD2, 0x00, 0x98, 0x52, 0x1C, 0x28, 0x30,
+ 0x00, 0x90, 0x9E, 0xF8, 0x00, 0x00, 0x28, 0x36, 0x01, 0xEB, 0x40, 0x01, 0xE8, 0x78, 0x90, 0x42,
+ 0xDE, 0xD2, 0x00, 0x20, 0x84, 0xF8, 0x0E, 0x01, 0x28, 0x68, 0x20, 0x60, 0x01, 0x23, 0x00, 0x22,
+ 0x21, 0x46, 0x5E, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0xFF, 0xF7, 0x76, 0xFB, 0x94, 0xF8, 0x0E, 0x01,
+ 0x01, 0x28, 0x26, 0xD9, 0x01, 0x25, 0x1D, 0xE0, 0x48, 0x22, 0x51, 0x46, 0x48, 0x46, 0x09, 0xF0,
+ 0x1E, 0xFB, 0x04, 0xEB, 0x45, 0x00, 0x04, 0xEB, 0x85, 0x07, 0xB0, 0xF8, 0xB4, 0x10, 0xA9, 0xF8,
+ 0x26, 0x10, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x33, 0xFD, 0x3A, 0x46, 0xE9, 0xB2, 0x4B, 0x46,
+ 0x30, 0x68, 0xFE, 0xF7, 0xC4, 0xFB, 0x3A, 0x46, 0xE9, 0xB2, 0x4B, 0x46, 0x30, 0x68, 0xFE, 0xF7,
+ 0x3B, 0xFB, 0x6D, 0x1C, 0x94, 0xF8, 0x0E, 0x01, 0xA8, 0x42, 0xDD, 0xD2, 0x09, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x8F, 0xDD, 0xE9, 0x05, 0x01, 0x53, 0x46, 0x2A, 0x46, 0xFE, 0xF7, 0x2D, 0xFB, 0xF5, 0xE7,
+ 0x2D, 0xE9, 0xFE, 0x4F, 0x06, 0x46, 0x9A, 0x48, 0x1D, 0x46, 0x0B, 0x46, 0x00, 0x68, 0x9A, 0x49,
+ 0x0E, 0x9C, 0xB0, 0xF9, 0xE6, 0x92, 0x89, 0x79, 0x93, 0x46, 0x09, 0xB1, 0xB0, 0xF9, 0x62, 0x93,
+ 0x96, 0x49, 0x09, 0x78, 0x09, 0xB1, 0xB0, 0xF9, 0xF4, 0x92, 0x18, 0x46, 0x0C, 0x99, 0x09, 0xF0,
+ 0x21, 0xFC, 0x82, 0x46, 0x30, 0x46, 0x0C, 0x99, 0x09, 0xF0, 0x2A, 0xFC, 0x01, 0x90, 0xA0, 0x68,
+ 0x0C, 0x99, 0x09, 0xF0, 0x1D, 0xFC, 0x2C, 0x78, 0x6D, 0x78, 0x80, 0x46, 0x64, 0xB9, 0x9A, 0xF8,
+ 0x00, 0x10, 0x59, 0x45, 0x07, 0xD1, 0xB8, 0xF9, 0x00, 0x10, 0x0D, 0x98, 0x81, 0x42, 0x02, 0xDD,
+ 0x01, 0x99, 0x01, 0x20, 0x08, 0x70, 0x01, 0x24, 0x7F, 0x48, 0x00, 0x78, 0x40, 0x1E, 0x85, 0x42,
+ 0x55, 0xD1, 0x1A, 0xF8, 0x05, 0x10, 0x59, 0x45, 0x07, 0xD1, 0x38, 0xF9, 0x15, 0x10, 0x0D, 0x98,
+ 0x81, 0x42, 0x02, 0xDD, 0x01, 0x99, 0x01, 0x20, 0x48, 0x55, 0x6D, 0x1E, 0xED, 0xB2, 0x46, 0xE0,
+ 0x1A, 0xF8, 0x04, 0x10, 0x59, 0x45, 0x41, 0xD1, 0x38, 0xF9, 0x14, 0x10, 0x0D, 0x98, 0x02, 0x91,
+ 0x81, 0x42, 0x3B, 0xDD, 0x00, 0x20, 0x00, 0x90, 0x75, 0x49, 0x0C, 0x98, 0x22, 0x46, 0x01, 0xEB,
+ 0xC0, 0x00, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67, 0x01, 0x20, 0x09, 0xF0, 0x1C, 0xFA, 0x06, 0x40,
+ 0x0F, 0x40, 0x3E, 0x43, 0x27, 0xD1, 0x02, 0x98, 0x08, 0xEB, 0x44, 0x02, 0x48, 0x44, 0x32, 0xF9,
+ 0x02, 0x1C, 0x00, 0xB2, 0x81, 0x42, 0x05, 0xDD, 0xB2, 0xF9, 0x02, 0x30, 0x83, 0x42, 0x01, 0xDD,
+ 0x01, 0x23, 0x00, 0x93, 0x01, 0x2C, 0x09, 0xD9, 0x32, 0xF9, 0x04, 0x3C, 0x83, 0x42, 0x05, 0xDD,
+ 0xB2, 0xF9, 0x02, 0x30, 0x83, 0x42, 0x01, 0xDD, 0x01, 0x23, 0x00, 0x93, 0x5A, 0x4B, 0x1B, 0x78,
+ 0x9B, 0x1E, 0x9C, 0x42, 0x05, 0xD2, 0x81, 0x42, 0x03, 0xDD, 0xB2, 0xF9, 0x04, 0x10, 0x81, 0x42,
+ 0x04, 0xDC, 0x00, 0x98, 0x10, 0xB9, 0x01, 0x99, 0x01, 0x20, 0x08, 0x55, 0x64, 0x1C, 0xAC, 0x42,
+ 0xB6, 0xD9, 0xBD, 0xE8, 0xFE, 0x8F, 0x2D, 0xE9, 0xFF, 0x4F, 0x54, 0x48, 0x9B, 0xB0, 0xDF, 0xF8,
+ 0x48, 0x91, 0x01, 0x78, 0x4E, 0x48, 0x28, 0x9E, 0x1D, 0x46, 0x00, 0x68, 0x39, 0xB1, 0x90, 0xF8,
+ 0xF3, 0x42, 0xB0, 0xF9, 0xF4, 0x12, 0x11, 0x91, 0xB0, 0xF9, 0xF6, 0x02, 0x11, 0xE0, 0x99, 0xF8,
+ 0x06, 0x10, 0x39, 0xB1, 0x90, 0xF8, 0x68, 0x43, 0xB0, 0xF9, 0x62, 0x13, 0x11, 0x91, 0xB0, 0xF9,
+ 0x64, 0x03, 0x06, 0xE0, 0x90, 0xF8, 0xE5, 0x42, 0xB0, 0xF9, 0xE6, 0x12, 0x11, 0x91, 0xB0, 0xF9,
+ 0xE8, 0x02, 0x44, 0x4F, 0x83, 0x46, 0xAC, 0xB1, 0x04, 0xA8, 0xCD, 0xE9, 0x00, 0x06, 0xDD, 0xE9,
+ 0x1C, 0x01, 0x02, 0xAB, 0x2A, 0x46, 0xFF, 0xF7, 0x61, 0xFE, 0xBD, 0xF9, 0x10, 0x00, 0xBD, 0xF9,
+ 0x08, 0x10, 0x40, 0x1A, 0x60, 0x43, 0x64, 0x21, 0x90, 0xFB, 0xF1, 0xF0, 0x39, 0x88, 0x08, 0x44,
+ 0x00, 0xB2, 0x01, 0xE0, 0xB7, 0xF9, 0x00, 0x00, 0xAC, 0x78, 0x95, 0xF8, 0x03, 0x80, 0x82, 0x46,
+ 0x4C, 0xB9, 0xCD, 0xE9, 0x00, 0x4A, 0x1B, 0xAF, 0x02, 0x96, 0x97, 0xE8, 0x07, 0x00, 0x2B, 0x46,
+ 0xFF, 0xF7, 0x1E, 0xFF, 0x01, 0x24, 0x30, 0x48, 0x00, 0x78, 0x40, 0x1E, 0x80, 0x45, 0x0D, 0xD1,
+ 0xCD, 0xF8, 0x00, 0x80, 0xCD, 0xE9, 0x01, 0xA6, 0x1B, 0xAF, 0x2B, 0x46, 0x97, 0xE8, 0x07, 0x00,
+ 0xFF, 0xF7, 0x0E, 0xFF, 0xA8, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x08, 0xA0, 0x1E, 0xC1, 0xB2,
+ 0xB0, 0x68, 0x09, 0xF0, 0x45, 0xFB, 0x09, 0x90, 0x60, 0x1E, 0xC1, 0xB2, 0xB0, 0x68, 0x09, 0xF0,
+ 0x3F, 0xFB, 0x0B, 0x90, 0x21, 0x46, 0xB0, 0x68, 0x09, 0xF0, 0x3A, 0xFB, 0x06, 0x90, 0x60, 0x1C,
+ 0xC1, 0xB2, 0xB0, 0x68, 0x09, 0xF0, 0x34, 0xFB, 0x05, 0x90, 0xA0, 0x1C, 0xC1, 0xB2, 0xB0, 0x68,
+ 0x09, 0xF0, 0x2E, 0xFB, 0x0C, 0x90, 0x21, 0x46, 0x1C, 0x98, 0x09, 0xF0, 0x23, 0xFB, 0x07, 0x90,
+ 0x21, 0x46, 0x1B, 0x98, 0x09, 0xF0, 0x2C, 0xFB, 0x02, 0x90, 0x00, 0x20, 0x14, 0x90, 0x01, 0x20,
+ 0x13, 0x90, 0x00, 0x20, 0x12, 0x90, 0x99, 0xF8, 0x04, 0x00, 0x58, 0xB3, 0x08, 0x48, 0x00, 0x68,
+ 0x90, 0xF8, 0x40, 0x14, 0x09, 0x07, 0x25, 0xD5, 0x6A, 0x78, 0x29, 0x78, 0x52, 0x1A, 0x90, 0xF8,
+ 0x4B, 0x14, 0x52, 0x1C, 0x8A, 0x42, 0x11, 0xE0, 0xBA, 0x06, 0x10, 0x00, 0x48, 0x06, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x30, 0x06, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00,
+ 0x48, 0x3F, 0x10, 0x00, 0x6E, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x0A, 0xDC, 0xEA, 0x78,
+ 0xAB, 0x78, 0xD2, 0x1A, 0x52, 0x1C, 0x8A, 0x42, 0x04, 0xDC, 0xB0, 0xF8, 0x49, 0x04, 0xB1, 0x69,
+ 0x81, 0x42, 0x01, 0xDD, 0x00, 0x20, 0x13, 0x90, 0xA1, 0x46, 0xE0, 0xE0, 0x2C, 0x78, 0xBC, 0xE0,
+ 0x07, 0x98, 0x01, 0x5D, 0x1D, 0x98, 0x81, 0x42, 0x67, 0xD1, 0x00, 0x20, 0x10, 0x90, 0xFD, 0x49,
+ 0x16, 0x90, 0x15, 0x90, 0x01, 0xEB, 0xC9, 0x00, 0x22, 0x46, 0xD0, 0xE9, 0x00, 0x67, 0x01, 0x20,
+ 0x00, 0x21, 0x09, 0xF0, 0x10, 0xF9, 0x06, 0x40, 0x0F, 0x40, 0x3E, 0x43, 0x7D, 0xD1, 0x06, 0x98,
+ 0x0B, 0x9A, 0x30, 0xF8, 0x14, 0x10, 0x11, 0x98, 0x32, 0xF9, 0x14, 0x20, 0x08, 0x44, 0x00, 0xB2,
+ 0x59, 0x44, 0x09, 0xB2, 0x82, 0x42, 0x07, 0xDD, 0x05, 0x9B, 0x33, 0xF9, 0x14, 0x30, 0x83, 0x42,
+ 0x02, 0xDD, 0x01, 0x23, 0x10, 0x93, 0x15, 0x93, 0xF4, 0xB3, 0xEB, 0x4B, 0x1B, 0x78, 0x5E, 0x1E,
+ 0xB4, 0x42, 0x68, 0xD0, 0x06, 0x9E, 0x06, 0xEB, 0x44, 0x0E, 0x3E, 0xF9, 0x02, 0x6C, 0x86, 0x42,
+ 0x06, 0xDD, 0xBE, 0xF9, 0x02, 0x70, 0x87, 0x42, 0x02, 0xDD, 0x01, 0x27, 0x10, 0x97, 0x16, 0x97,
+ 0x0B, 0x9F, 0x07, 0xEB, 0x44, 0x07, 0x37, 0xF9, 0x02, 0xCC, 0x8C, 0x45, 0x0B, 0xDD, 0xDD, 0xF8,
+ 0x14, 0xC0, 0x0C, 0xEB, 0x44, 0x0C, 0xBC, 0xF9, 0x02, 0xC0, 0x8C, 0x45, 0x03, 0xDD, 0x4F, 0xF0,
+ 0x01, 0x0C, 0xCD, 0xF8, 0x40, 0xC0, 0xB7, 0xF9, 0x02, 0x70, 0x8F, 0x42, 0x06, 0xDD, 0x05, 0x9F,
+ 0x07, 0xEB, 0x44, 0x07, 0x37, 0xF9, 0x02, 0x7C, 0x8F, 0x42, 0x47, 0xDC, 0x10, 0x99, 0xA9, 0xBB,
+ 0xB9, 0xF1, 0x01, 0x0F, 0x0F, 0xD9, 0x09, 0x99, 0x31, 0xF9, 0x14, 0x10, 0x81, 0x42, 0x0A, 0xDD,
+ 0x05, 0x99, 0x31, 0xF9, 0x14, 0x10, 0x01, 0xE0, 0x2D, 0xE0, 0x4D, 0xE0, 0x81, 0x42, 0x02, 0xDD,
+ 0x01, 0x21, 0x10, 0x91, 0x15, 0x91, 0xC9, 0x4F, 0x3F, 0x78, 0xBF, 0x1E, 0xB9, 0x45, 0x09, 0xD2,
+ 0x82, 0x42, 0x07, 0xDD, 0x0C, 0x99, 0x31, 0xF9, 0x14, 0x10, 0x81, 0x42, 0x02, 0xDD, 0x01, 0x21,
+ 0x10, 0x91, 0x15, 0x91, 0x01, 0x2C, 0x0A, 0xD9, 0x3E, 0xF9, 0x04, 0x1C, 0x81, 0x42, 0x06, 0xDD,
+ 0xBE, 0xF9, 0x02, 0x10, 0x81, 0x42, 0x02, 0xDD, 0x01, 0x21, 0x10, 0x91, 0x16, 0x91, 0x9B, 0x1E,
+ 0x9C, 0x42, 0x08, 0xD2, 0x86, 0x42, 0x06, 0xDD, 0x01, 0xE0, 0x06, 0xE0, 0x0E, 0xE0, 0xBE, 0xF9,
+ 0x04, 0x10, 0x81, 0x42, 0x0C, 0xDC, 0x10, 0x98, 0x40, 0xB9, 0x06, 0x98, 0x30, 0xF9, 0x14, 0x10,
+ 0x51, 0x45, 0x03, 0xDD, 0x02, 0x99, 0x01, 0x20, 0x08, 0x55, 0x15, 0xE0, 0x16, 0x98, 0x98, 0xB1,
+ 0x15, 0x98, 0x88, 0xB1, 0x13, 0x98, 0x78, 0xB1, 0x02, 0x99, 0x01, 0x20, 0x08, 0x55, 0x12, 0x98,
+ 0x40, 0x1C, 0x80, 0xB2, 0x12, 0x90, 0xAA, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x4C, 0x14, 0x12, 0x98,
+ 0x81, 0x42, 0x01, 0xD2, 0x01, 0x20, 0x14, 0x90, 0x64, 0x1C, 0x68, 0x78, 0xA0, 0x42, 0xBF, 0xF4,
+ 0x3F, 0xAF, 0xA1, 0x48, 0x09, 0x99, 0x09, 0xF1, 0x01, 0x09, 0x00, 0x78, 0x01, 0xEB, 0x40, 0x01,
+ 0x09, 0x91, 0x0B, 0x99, 0x01, 0xEB, 0x40, 0x01, 0x0B, 0x91, 0x06, 0x99, 0x01, 0xEB, 0x40, 0x01,
+ 0x06, 0x91, 0x05, 0x99, 0x01, 0xEB, 0x40, 0x01, 0x05, 0x91, 0x0C, 0x99, 0x01, 0xEB, 0x40, 0x00,
+ 0x0C, 0x90, 0x07, 0x98, 0x28, 0x30, 0x07, 0x90, 0x02, 0x98, 0x28, 0x30, 0x02, 0x90, 0xC1, 0x45,
+ 0x7F, 0xF6, 0x1C, 0xAF, 0x14, 0x98, 0x1F, 0xB0, 0xB9, 0xE5, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46,
+ 0x91, 0x42, 0x5A, 0xD0, 0x07, 0xD9, 0x01, 0xEB, 0x02, 0x00, 0xA0, 0xEB, 0x02, 0x01, 0xCA, 0xB2,
+ 0xA0, 0xEB, 0x02, 0x00, 0xC1, 0xB2, 0x01, 0xEB, 0xC1, 0x00, 0x04, 0xEB, 0xC0, 0x01, 0x02, 0xEB,
+ 0xC2, 0x00, 0x04, 0xEB, 0xC0, 0x00, 0xB1, 0xF9, 0x32, 0x50, 0xB0, 0xF9, 0x32, 0x30, 0x81, 0x46,
+ 0x9D, 0x42, 0x00, 0xDA, 0x4B, 0x86, 0xCB, 0x8C, 0xC5, 0x8C, 0x2B, 0x44, 0xCB, 0x84, 0x0B, 0x8D,
+ 0x05, 0x8D, 0x2B, 0x44, 0x0B, 0x85, 0x4B, 0x8D, 0x45, 0x8D, 0x2B, 0x44, 0x4B, 0x85, 0x8B, 0x69,
+ 0x85, 0x69, 0x2B, 0x44, 0x8B, 0x61, 0xC7, 0x69, 0xCE, 0x69, 0xCB, 0x68, 0xD9, 0xF8, 0x0C, 0x00,
+ 0x4F, 0xEA, 0x23, 0x4C, 0x4F, 0xEA, 0x20, 0x48, 0x0C, 0xFB, 0x06, 0xFC, 0xF5, 0x19, 0x07, 0xFB,
+ 0x08, 0xCC, 0x9C, 0xFB, 0xF5, 0xFC, 0x6C, 0xF3, 0x1F, 0x43, 0x0F, 0xFA, 0x83, 0xFC, 0x0C, 0xFB,
+ 0x06, 0xFC, 0x00, 0xB2, 0x07, 0xFB, 0x00, 0xC0, 0x90, 0xFB, 0xF5, 0xF0, 0x60, 0xF3, 0x0F, 0x03,
+ 0xCD, 0x61, 0xCB, 0x60, 0x94, 0xF8, 0x38, 0x04, 0x41, 0x1E, 0x91, 0x42, 0x08, 0xD0, 0x00, 0xEB,
+ 0xC0, 0x00, 0x04, 0xEB, 0xC0, 0x01, 0x48, 0x46, 0x48, 0x22, 0x48, 0x39, 0x09, 0xF0, 0x5F, 0xF8,
+ 0x94, 0xF8, 0x38, 0x04, 0x40, 0x1E, 0x84, 0xF8, 0x38, 0x04, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9,
+ 0xFE, 0x4F, 0x07, 0x46, 0x5E, 0x48, 0x8A, 0x46, 0x00, 0x25, 0x01, 0x68, 0xB1, 0xF8, 0xEA, 0x02,
+ 0x00, 0xFB, 0x00, 0xF9, 0x5B, 0x48, 0x80, 0x79, 0x18, 0xB1, 0xB1, 0xF8, 0x66, 0x03, 0x00, 0xFB,
+ 0x00, 0xF9, 0x54, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x9D, 0xE0, 0x00, 0xBF, 0x0B, 0xFA, 0x04, 0xF0,
+ 0x26, 0x46, 0x00, 0x90, 0x66, 0xE0, 0x00, 0xBF, 0x00, 0x99, 0x0B, 0xFA, 0x06, 0xF0, 0x08, 0x42,
+ 0x5F, 0xD0, 0x06, 0xEB, 0xC6, 0x00, 0x07, 0xEB, 0xC0, 0x00, 0xC2, 0x68, 0x20, 0x46, 0x4D, 0xE0,
+ 0xB0, 0x42, 0x4A, 0xD0, 0x00, 0xEB, 0xC0, 0x01, 0x07, 0xEB, 0xC1, 0x01, 0xC9, 0x68, 0x4F, 0xEA,
+ 0x21, 0x4C, 0xAC, 0xEB, 0x22, 0x4C, 0x89, 0x1A, 0x0F, 0xFA, 0x8C, 0xFC, 0x09, 0xB2, 0x6C, 0xF3,
+ 0x1F, 0x45, 0x61, 0xF3, 0x0F, 0x05, 0x8E, 0x46, 0x41, 0x49, 0xCD, 0xF8, 0x04, 0xC0, 0x09, 0x68,
+ 0x91, 0xF8, 0xE0, 0xC2, 0xCD, 0xF8, 0x08, 0xC0, 0x5F, 0xEA, 0x8C, 0x6C, 0x0B, 0xD5, 0x91, 0xF8,
+ 0xED, 0x82, 0x0E, 0xFB, 0x08, 0xFC, 0x4F, 0xF0, 0x64, 0x08, 0x9C, 0xFB, 0xF8, 0xF8, 0x08, 0xEB,
+ 0x0E, 0x0C, 0x6C, 0xF3, 0x0F, 0x05, 0xDD, 0xF8, 0x08, 0xC0, 0x5F, 0xEA, 0xCC, 0x6C, 0x0C, 0xD5,
+ 0x91, 0xF8, 0xED, 0x12, 0xDD, 0xF8, 0x04, 0xC0, 0x0C, 0xFB, 0x01, 0xFC, 0x64, 0x21, 0x9C, 0xFB,
+ 0xF1, 0xFC, 0x01, 0x99, 0x61, 0x44, 0x61, 0xF3, 0x1F, 0x45, 0x4F, 0xEA, 0x25, 0x4C, 0x0C, 0xFB,
+ 0x0C, 0xFC, 0x29, 0xB2, 0x01, 0xFB, 0x01, 0xC1, 0x49, 0x45, 0x06, 0xD2, 0xDD, 0xF8, 0x00, 0xC0,
+ 0x0B, 0xFA, 0x00, 0xF1, 0x41, 0xEA, 0x0C, 0x01, 0x00, 0x91, 0x40, 0x1C, 0x83, 0x42, 0xAF, 0xD8,
+ 0x04, 0x21, 0x68, 0x46, 0x07, 0xF0, 0xD6, 0xFC, 0x01, 0x28, 0x02, 0xD1, 0x00, 0x98, 0x40, 0x00,
+ 0x00, 0x90, 0x76, 0x1C, 0x97, 0xF8, 0x38, 0x34, 0xB3, 0x42, 0x95, 0xD8, 0x04, 0x21, 0x68, 0x46,
+ 0x07, 0xF0, 0xC8, 0xFC, 0x01, 0x28, 0x0B, 0xD0, 0x04, 0x21, 0x68, 0x46, 0x07, 0xF0, 0xC2, 0xFC,
+ 0x97, 0xF8, 0x38, 0x64, 0xA6, 0xEB, 0x0A, 0x01, 0x88, 0x42, 0x05, 0xD1, 0x87, 0xF8, 0x38, 0xA4,
+ 0x57, 0xE5, 0x64, 0x1C, 0xE4, 0xB2, 0x01, 0xE0, 0x00, 0x99, 0x58, 0x46, 0x00, 0xFA, 0x04, 0xF2,
+ 0x0A, 0x42, 0xF6, 0xD0, 0xD8, 0x46, 0x09, 0xE0, 0x00, 0x99, 0x08, 0xFA, 0x06, 0xF0, 0x08, 0x42,
+ 0x04, 0xD0, 0xF2, 0xB2, 0x21, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xEF, 0xFE, 0x76, 0x1E, 0xA6, 0x42,
+ 0xF2, 0xD8, 0x64, 0x1C, 0xE4, 0xB2, 0x97, 0xF8, 0x38, 0x04, 0xA0, 0x42, 0x3F, 0xF6, 0x5E, 0xAF,
+ 0x37, 0xE5, 0x00, 0x00, 0x48, 0x3F, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xFE, 0x4C, 0x01, 0x2B,
+ 0x24, 0x68, 0x94, 0xF8, 0xF9, 0x72, 0x94, 0xF8, 0xF8, 0x62, 0x05, 0xD0, 0x0B, 0x78, 0x4C, 0x78,
+ 0xFA, 0x4D, 0x9C, 0x46, 0x69, 0x0C, 0x0D, 0xE0, 0x8B, 0x78, 0xCC, 0x78, 0xF8, 0xE7, 0x00, 0xBF,
+ 0x30, 0xF9, 0x1C, 0x80, 0xA8, 0x45, 0x00, 0xDD, 0x45, 0x46, 0x88, 0x45, 0x00, 0xDA, 0x41, 0x46,
+ 0x0C, 0xF1, 0x01, 0x0C, 0xA4, 0x45, 0xF3, 0xD9, 0xB5, 0x42, 0x00, 0xDA, 0x35, 0x46, 0xB1, 0x42,
+ 0x00, 0xDA, 0x31, 0x46, 0x69, 0x1A, 0x79, 0x43, 0x64, 0x25, 0x91, 0xFB, 0xF5, 0xF1, 0x31, 0x44,
+ 0x0E, 0xB2, 0x30, 0xF9, 0x13, 0x50, 0x01, 0x21, 0xB5, 0x42, 0x05, 0xDD, 0x15, 0x68, 0x01, 0xFA,
+ 0x03, 0xFC, 0x45, 0xEA, 0x0C, 0x05, 0x15, 0x60, 0x30, 0xF9, 0x14, 0x50, 0xB5, 0x42, 0x05, 0xDD,
+ 0x15, 0x68, 0x01, 0xFA, 0x04, 0xFC, 0x45, 0xEA, 0x0C, 0x05, 0x15, 0x60, 0xE5, 0x1A, 0x05, 0xF0,
+ 0xFF, 0x09, 0xB9, 0xF1, 0x01, 0x0F, 0x37, 0xD9, 0x5D, 0x1C, 0xED, 0xB2, 0x30, 0xF9, 0x15, 0x80,
+ 0x08, 0xEB, 0x07, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC, 0xB0, 0x45, 0x11, 0xDD, 0x00, 0xEB, 0x45, 0x0A,
+ 0x3A, 0xF9, 0x02, 0x8C, 0xE0, 0x45, 0x03, 0xDD, 0xBA, 0xF9, 0x02, 0x80, 0xE0, 0x45, 0x07, 0xDC,
+ 0xD2, 0xF8, 0x00, 0xC0, 0x01, 0xFA, 0x05, 0xF5, 0x4C, 0xEA, 0x05, 0x0C, 0xC2, 0xF8, 0x00, 0xC0,
+ 0x65, 0x1E, 0xED, 0xB2, 0x30, 0xF9, 0x15, 0x80, 0x08, 0xEB, 0x07, 0x0C, 0x0F, 0xFA, 0x8C, 0xFC,
+ 0xB0, 0x45, 0x11, 0xDD, 0x00, 0xEB, 0x45, 0x0A, 0x3A, 0xF9, 0x02, 0x8C, 0xE0, 0x45, 0x03, 0xDD,
+ 0xBA, 0xF9, 0x02, 0x80, 0xE0, 0x45, 0x07, 0xDC, 0xD2, 0xF8, 0x00, 0xC0, 0x01, 0xFA, 0x05, 0xF5,
+ 0x4C, 0xEA, 0x05, 0x0C, 0xC2, 0xF8, 0x00, 0xC0, 0xB9, 0xF1, 0x02, 0x0F, 0x2E, 0xD9, 0x9D, 0x1C,
+ 0xA4, 0xF1, 0x02, 0x09, 0x28, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x15, 0xC0, 0xB4, 0x45, 0x22, 0xDD,
+ 0x00, 0xEB, 0x45, 0x0B, 0xBC, 0x44, 0x3B, 0xF9, 0x02, 0xEC, 0x0F, 0xFA, 0x8C, 0xFA, 0xD6, 0x45,
+ 0x03, 0xDD, 0xBB, 0xF9, 0x02, 0x80, 0xD0, 0x45, 0x15, 0xDC, 0x3B, 0xF9, 0x04, 0x8C, 0xD0, 0x45,
+ 0x03, 0xDD, 0xBB, 0xF9, 0x02, 0x80, 0xD0, 0x45, 0x0D, 0xDC, 0xD6, 0x45, 0x03, 0xDD, 0xBB, 0xF9,
+ 0x04, 0x80, 0xD0, 0x45, 0x07, 0xDC, 0xD2, 0xF8, 0x00, 0xC0, 0x01, 0xFA, 0x05, 0xF8, 0x4C, 0xEA,
+ 0x08, 0x0C, 0xC2, 0xF8, 0x00, 0xC0, 0x6D, 0x1C, 0x4D, 0x45, 0xD5, 0xD9, 0x00, 0x25, 0x28, 0x46,
+ 0x0C, 0xE0, 0x00, 0xBF, 0x16, 0x68, 0x01, 0xFA, 0x03, 0xF7, 0x3E, 0x42, 0x04, 0xD0, 0x25, 0xB9,
+ 0x01, 0x25, 0x40, 0x1C, 0xC0, 0xB2, 0x00, 0xE0, 0x00, 0x25, 0x5B, 0x1C, 0xA3, 0x42, 0xF1, 0xD9,
+ 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0xE9, 0xFF, 0x4F, 0x9D, 0x48, 0x8F, 0xB0, 0xDF, 0xF8, 0x74, 0x92,
+ 0x04, 0x68, 0x16, 0x46, 0x04, 0xF5, 0x88, 0x70, 0x02, 0x90, 0x4F, 0xF0, 0xFF, 0x30, 0x0C, 0x90,
+ 0x00, 0x20, 0x0A, 0x90, 0x0B, 0x90, 0x98, 0x46, 0x01, 0x22, 0x31, 0x46, 0x4D, 0x46, 0xD9, 0xF8,
+ 0x00, 0x00, 0xFE, 0xF7, 0xFF, 0xFD, 0xCD, 0xF8, 0x00, 0x80, 0xDD, 0xE9, 0x0F, 0x12, 0x33, 0x46,
+ 0x28, 0x68, 0xFF, 0xF7, 0x48, 0xFC, 0x05, 0x00, 0x08, 0xD0, 0x8F, 0x49, 0x01, 0x20, 0x08, 0x70,
+ 0xB8, 0xF8, 0x24, 0x00, 0x40, 0xF0, 0x80, 0x01, 0xA8, 0xF8, 0x24, 0x10, 0x8B, 0x48, 0x00, 0x78,
+ 0x50, 0xB1, 0x4D, 0xB9, 0x98, 0xF8, 0x24, 0x00, 0x10, 0xF0, 0x06, 0x0F, 0x04, 0xD1, 0x31, 0x46,
+ 0x40, 0x46, 0xFE, 0xF7, 0x3D, 0xFE, 0x05, 0x46, 0x85, 0x48, 0x00, 0x78, 0x00, 0xB1, 0x01, 0x25,
+ 0x7D, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xE1, 0x02, 0x40, 0x07, 0x2F, 0xD5, 0x01, 0x23, 0x0A, 0xAA,
+ 0x31, 0x46, 0x80, 0x48, 0xFF, 0xF7, 0xF0, 0xFE, 0x07, 0x46, 0x00, 0x23, 0x0B, 0xAA, 0x31, 0x46,
+ 0x7D, 0x48, 0xFF, 0xF7, 0xE9, 0xFE, 0x78, 0x43, 0x01, 0x28, 0x1F, 0xD1, 0xB7, 0x78, 0x1A, 0xE0,
+ 0xF9, 0xB2, 0x0F, 0x98, 0x08, 0xF0, 0xC4, 0xFF, 0x83, 0x46, 0xF9, 0xB2, 0xD9, 0xF8, 0x00, 0x00,
+ 0x08, 0xF0, 0xBE, 0xFF, 0x02, 0x46, 0x30, 0x78, 0x01, 0x23, 0x08, 0xE0, 0x1B, 0xF8, 0x00, 0xC0,
+ 0x10, 0x99, 0x8C, 0x45, 0x02, 0xD1, 0x11, 0x5C, 0x01, 0xB9, 0x13, 0x54, 0x40, 0x1C, 0x71, 0x78,
+ 0x81, 0x42, 0xF3, 0xDA, 0x7F, 0x1C, 0xF0, 0x78, 0xB8, 0x42, 0xE1, 0xDA, 0x00, 0x20, 0x84, 0xF8,
+ 0x0E, 0x01, 0x30, 0x68, 0x20, 0x60, 0x63, 0x48, 0x2B, 0x46, 0x00, 0x22, 0x21, 0x46, 0x00, 0x68,
+ 0xFE, 0xF7, 0x9A, 0xFE, 0x94, 0xF8, 0x0E, 0x01, 0x00, 0x25, 0x01, 0x28, 0x70, 0xD9, 0xFC, 0xF7,
+ 0xB4, 0xFB, 0x83, 0x46, 0xFC, 0xF7, 0xAF, 0xFB, 0x82, 0x46, 0x32, 0x68, 0xDD, 0xE9, 0x0F, 0x01,
+ 0x07, 0x92, 0x47, 0x46, 0x5D, 0x4B, 0x07, 0xAA, 0xFE, 0xF7, 0x3B, 0xFD, 0x60, 0xB1, 0x07, 0xA9,
+ 0x5A, 0x48, 0xFE, 0xF7, 0xCF, 0xFC, 0x3A, 0x46, 0x07, 0xA9, 0x58, 0x48, 0xFD, 0xF7, 0x1F, 0xFB,
+ 0xF8, 0x68, 0x78, 0x61, 0xF8, 0x69, 0x38, 0x62, 0x51, 0x48, 0x00, 0x78, 0xE8, 0xB3, 0x4A, 0x48,
+ 0x00, 0x68, 0x90, 0xF8, 0xE1, 0x02, 0x80, 0x07, 0x46, 0xD5, 0x94, 0xF8, 0x0E, 0x01, 0x01, 0x28,
+ 0x42, 0xD9, 0x4F, 0xF0, 0x00, 0x09, 0x01, 0x27, 0x10, 0xE0, 0x00, 0xBF, 0x45, 0x48, 0x04, 0xEB,
+ 0x87, 0x03, 0xFA, 0xB2, 0xD8, 0xF8, 0x08, 0x10, 0x00, 0x68, 0xFE, 0xF7, 0x89, 0xFD, 0x48, 0x49,
+ 0x48, 0x45, 0x41, 0xF8, 0x27, 0x00, 0x00, 0xDD, 0x81, 0x46, 0x7F, 0x1C, 0x94, 0xF8, 0x0E, 0x21,
+ 0xBA, 0x42, 0xEB, 0xD2, 0xB9, 0xF1, 0x00, 0x0F, 0x1F, 0xDD, 0x37, 0x49, 0x01, 0x20, 0x40, 0x4B,
+ 0x86, 0x46, 0x09, 0x68, 0x17, 0xE0, 0x00, 0xBF, 0x53, 0xF8, 0x20, 0x70, 0x4F, 0xF0, 0x64, 0x0C,
+ 0x07, 0xFB, 0x0C, 0xF7, 0x97, 0xFB, 0xF9, 0xF7, 0x91, 0xF8, 0xF2, 0xC2, 0xBC, 0x45, 0x09, 0xDD,
+ 0x0E, 0xFA, 0x00, 0xF7, 0xDD, 0xF8, 0x30, 0xC0, 0x00, 0xE0, 0x0D, 0xE0, 0x2C, 0xEA, 0x07, 0x0C,
+ 0xCD, 0xF8, 0x30, 0xC0, 0x40, 0x1C, 0x82, 0x42, 0xE6, 0xD2, 0x94, 0xF8, 0x0E, 0x01, 0x01, 0x28,
+ 0x02, 0xD9, 0x00, 0x20, 0x84, 0xF8, 0x0E, 0x01, 0x01, 0x27, 0xDF, 0xF8, 0x8C, 0x90, 0x35, 0xE0,
+ 0x7D, 0xE0, 0x48, 0x22, 0x41, 0x46, 0x02, 0x98, 0x08, 0xF0, 0xD1, 0xFD, 0xD9, 0xF8, 0x00, 0x10,
+ 0x04, 0xEB, 0x47, 0x00, 0xB0, 0xF8, 0xB4, 0x20, 0x91, 0xF8, 0xEC, 0x12, 0x8A, 0x42, 0x24, 0xD9,
+ 0x01, 0x21, 0x0C, 0x9A, 0xB9, 0x40, 0x11, 0x42, 0x1F, 0xD0, 0x02, 0x99, 0x89, 0x8C, 0x41, 0xF0,
+ 0x10, 0x02, 0x02, 0x99, 0x8A, 0x84, 0xB0, 0xF8, 0xB4, 0x10, 0x02, 0x98, 0xC1, 0x84, 0x04, 0xEB,
+ 0x87, 0x00, 0x08, 0x90, 0x02, 0x99, 0xFE, 0xF7, 0xD3, 0xFF, 0x12, 0x48, 0xF9, 0xB2, 0x02, 0x9B,
+ 0x08, 0x9A, 0x00, 0x68, 0xFD, 0xF7, 0x63, 0xFE, 0x0E, 0x48, 0xF9, 0xB2, 0x02, 0x9B, 0x08, 0x9A,
+ 0x00, 0x68, 0xFD, 0xF7, 0xD9, 0xFD, 0x6D, 0x1C, 0xED, 0xB2, 0x7F, 0x1C, 0x94, 0xF8, 0x0E, 0x01,
+ 0xB8, 0x42, 0xC6, 0xD2, 0xD9, 0xF8, 0x00, 0x00, 0x4C, 0x46, 0x90, 0xF8, 0xE0, 0x02, 0x00, 0x07,
+ 0x21, 0xD5, 0x01, 0x2D, 0x1F, 0xD9, 0x15, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x00, 0x80, 0xFF, 0xFF,
+ 0x48, 0x06, 0x10, 0x00, 0x30, 0x06, 0x10, 0x00, 0x10, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00,
+ 0x28, 0x05, 0x10, 0x00, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20, 0xA0, 0x3E, 0x10, 0x00,
+ 0xA8, 0x40, 0x10, 0x00, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x21, 0xFD, 0xFC, 0xF7, 0xE5, 0xFA,
+ 0xA0, 0xEB, 0x0B, 0x00, 0xC5, 0xB2, 0x22, 0x68, 0x92, 0xF8, 0xE0, 0x02, 0x00, 0x06, 0x12, 0xD5,
+ 0x28, 0x46, 0x0E, 0xE0, 0x0B, 0xEB, 0x00, 0x01, 0xC9, 0xB2, 0x01, 0xEB, 0xC1, 0x03, 0x0A, 0xEB,
+ 0xC3, 0x01, 0x92, 0xF8, 0x07, 0x33, 0xC9, 0x8C, 0x99, 0x42, 0x02, 0xD9, 0x8A, 0xF8, 0x38, 0xB4,
+ 0x05, 0xE0, 0x40, 0x1E, 0xEE, 0xD2, 0x01, 0x2D, 0x09, 0xD0, 0x00, 0x2D, 0x05, 0xD1, 0xDD, 0xE9,
+ 0x0F, 0x01, 0x43, 0x46, 0x32, 0x46, 0xFD, 0xF7, 0x87, 0xFD, 0x13, 0xB0, 0x80, 0xE6, 0xE0, 0x48,
+ 0x00, 0x78, 0x00, 0x28, 0xF9, 0xD1, 0x9A, 0xF8, 0x38, 0x04, 0x40, 0x1E, 0x8A, 0xF8, 0x38, 0x04,
+ 0xED, 0xE7, 0x2D, 0xE9, 0xFF, 0x4F, 0xDB, 0x48, 0x81, 0xB0, 0x00, 0x68, 0x90, 0xF8, 0xE1, 0x02,
+ 0xC0, 0x07, 0x67, 0xD0, 0xA8, 0x21, 0x04, 0x98, 0x08, 0xF0, 0x95, 0xFD, 0x01, 0x25, 0x44, 0xE0,
+ 0x03, 0x98, 0x00, 0xEB, 0x85, 0x00, 0x82, 0x46, 0x84, 0x78, 0x90, 0xF8, 0x03, 0x90, 0xD2, 0x48,
+ 0x00, 0x78, 0x40, 0x1E, 0x84, 0x42, 0x01, 0xDA, 0x64, 0x1C, 0xE4, 0xB2, 0xB9, 0xF1, 0x00, 0x0F,
+ 0x03, 0xD0, 0xA9, 0xF1, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x09, 0x21, 0x46, 0x01, 0x98, 0x08, 0xF0,
+ 0x61, 0xFE, 0x83, 0x46, 0xA0, 0x46, 0x24, 0xE0, 0x03, 0x98, 0x04, 0x99, 0x10, 0xF8, 0x25, 0x40,
+ 0x01, 0xEB, 0xC8, 0x00, 0x00, 0x90, 0x12, 0xE0, 0x1B, 0xF8, 0x04, 0x00, 0xA8, 0x42, 0x0C, 0xD1,
+ 0x00, 0x98, 0x22, 0x46, 0x00, 0x21, 0xD0, 0xE9, 0x00, 0x67, 0x01, 0x20, 0x08, 0xF0, 0x8B, 0xFC,
+ 0x06, 0x43, 0x00, 0x98, 0x0F, 0x43, 0xC0, 0xE9, 0x00, 0x67, 0x64, 0x1C, 0xE4, 0xB2, 0x9A, 0xF8,
+ 0x01, 0x00, 0xA0, 0x42, 0xE8, 0xD2, 0x08, 0xF1, 0x01, 0x00, 0x0B, 0xF1, 0x28, 0x0B, 0x00, 0xF0,
+ 0xFF, 0x08, 0xC8, 0x45, 0xD8, 0xD9, 0x6D, 0x1C, 0xED, 0xB2, 0x02, 0x98, 0x85, 0x42, 0xB7, 0xD9,
+ 0x00, 0x21, 0xB1, 0x4E, 0x13, 0xE0, 0x04, 0x98, 0x00, 0xEB, 0xC1, 0x05, 0x01, 0xF1, 0x01, 0x01,
+ 0xD5, 0xE9, 0x00, 0x32, 0xDC, 0x18, 0x42, 0xEB, 0x02, 0x00, 0x52, 0x08, 0x4F, 0xEA, 0x33, 0x03,
+ 0x04, 0xEA, 0x03, 0x04, 0x00, 0xEA, 0x02, 0x00, 0xC5, 0xE9, 0x00, 0x40, 0xC9, 0xB2, 0x30, 0x78,
+ 0x81, 0x42, 0xE8, 0xD3, 0x05, 0xB0, 0x03, 0xE6, 0xF0, 0xB4, 0x14, 0x68, 0xC3, 0xF8, 0x3A, 0x40,
+ 0xA0, 0x4C, 0x25, 0x68, 0x95, 0xF8, 0xE0, 0x42, 0xA6, 0x07, 0x13, 0xD4, 0x93, 0xF8, 0x40, 0x60,
+ 0x01, 0x2E, 0x0F, 0xD0, 0x66, 0x07, 0x13, 0xD5, 0x64, 0x06, 0x09, 0xD5, 0x9B, 0x4C, 0x64, 0x78,
+ 0x5C, 0xB1, 0xB5, 0xF8, 0xF0, 0x42, 0x9A, 0x4D, 0x64, 0x43, 0x2D, 0x68, 0xA5, 0x42, 0x07, 0xDC,
+ 0xF0, 0xBC, 0xE7, 0xE5, 0xF0, 0xBC, 0xFF, 0xF7, 0x19, 0xB9, 0xB5, 0xF8, 0xEE, 0x42, 0xF2, 0xE7,
+ 0xF0, 0xBC, 0xFD, 0xF7, 0xE1, 0xBC, 0x2D, 0xE9, 0xFF, 0x4F, 0x94, 0x78, 0xD7, 0x78, 0x15, 0x78,
+ 0x56, 0x78, 0x81, 0xB0, 0x98, 0x46, 0x82, 0x46, 0x04, 0xB9, 0x01, 0x24, 0x8A, 0x48, 0x00, 0x78,
+ 0x40, 0x1E, 0x87, 0x42, 0x01, 0xD1, 0x7F, 0x1E, 0xFF, 0xB2, 0x05, 0xB9, 0x01, 0x25, 0xDF, 0xF8,
+ 0x24, 0xB2, 0x9B, 0xF8, 0x00, 0x00, 0x40, 0x1E, 0x86, 0x42, 0x01, 0xD1, 0x76, 0x1E, 0xF6, 0xB2,
+ 0x60, 0x1E, 0xC1, 0xB2, 0xD8, 0xF8, 0x08, 0x00, 0x08, 0xF0, 0xD2, 0xFD, 0x00, 0x90, 0x21, 0x46,
+ 0xD8, 0xF8, 0x08, 0x00, 0x08, 0xF0, 0xCC, 0xFD, 0x81, 0x46, 0x60, 0x1C, 0xC1, 0xB2, 0xD8, 0xF8,
+ 0x08, 0x00, 0x08, 0xF0, 0xC5, 0xFD, 0x80, 0x46, 0x21, 0x46, 0x50, 0x46, 0x08, 0xF0, 0xBA, 0xFD,
+ 0x35, 0xE0, 0x74, 0x4A, 0x29, 0x46, 0xD2, 0xF8, 0x00, 0xA0, 0x24, 0xE0, 0x43, 0x5C, 0x02, 0x9A,
+ 0x93, 0x42, 0x1E, 0xD1, 0x39, 0xF8, 0x11, 0x30, 0x9A, 0xF8, 0x27, 0x24, 0x1A, 0x44, 0x00, 0x9B,
+ 0x12, 0xB2, 0x03, 0xEB, 0x41, 0x03, 0x33, 0xF9, 0x02, 0xCC, 0x94, 0x45, 0x05, 0xDD, 0x08, 0xEB,
+ 0x41, 0x0C, 0xBC, 0xF9, 0x02, 0xC0, 0x94, 0x45, 0x09, 0xDC, 0xB3, 0xF9, 0x02, 0x30, 0x93, 0x42,
+ 0x07, 0xDD, 0x08, 0xEB, 0x41, 0x03, 0x33, 0xF9, 0x02, 0x3C, 0x93, 0x42, 0x01, 0xDD, 0x01, 0x20,
+ 0x78, 0xE7, 0x49, 0x1C, 0xC9, 0xB2, 0xB1, 0x42, 0xD8, 0xD9, 0xCD, 0xF8, 0x00, 0x90, 0x9B, 0xF8,
+ 0x00, 0x20, 0x64, 0x1C, 0xC1, 0x46, 0x08, 0xEB, 0x42, 0x08, 0xE4, 0xB2, 0x28, 0x30, 0xBC, 0x42,
+ 0xC7, 0xD9, 0x00, 0x20, 0x66, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0x4F, 0xF0, 0x00, 0x0A, 0x89, 0x46,
+ 0x04, 0x46, 0x01, 0x26, 0x57, 0x46, 0xD0, 0x46, 0x85, 0x78, 0x2A, 0xE0, 0x29, 0x46, 0xD9, 0xF8,
+ 0x08, 0x00, 0x08, 0xF0, 0x75, 0xFD, 0x02, 0x46, 0x00, 0x20, 0x21, 0x78, 0x63, 0x78, 0x04, 0xE0,
+ 0x32, 0xF9, 0x11, 0xC0, 0x49, 0x1C, 0x60, 0x44, 0xC9, 0xB2, 0x8B, 0x42, 0xF8, 0xD2, 0xA1, 0x78,
+ 0x4A, 0x1C, 0xAA, 0x42, 0x10, 0xD2, 0x47, 0x4A, 0x12, 0x68, 0xB2, 0xF8, 0x28, 0x34, 0x03, 0xEB,
+ 0x08, 0x02, 0xBA, 0x42, 0x01, 0xDA, 0x82, 0x42, 0x33, 0xDB, 0x89, 0x1C, 0xA9, 0x42, 0x03, 0xD2,
+ 0x52, 0x45, 0x01, 0xDA, 0x82, 0x42, 0x2C, 0xDB, 0xBA, 0x46, 0x47, 0x46, 0x6D, 0x1C, 0x80, 0x46,
+ 0xED, 0xB2, 0xE0, 0x78, 0xA8, 0x42, 0xD1, 0xD2, 0x00, 0x20, 0x00, 0x90, 0x82, 0x46, 0x83, 0x46,
+ 0x25, 0x78, 0x2E, 0xE0, 0x4F, 0xF0, 0x00, 0x08, 0xA7, 0x78, 0x09, 0xE0, 0x39, 0x46, 0xD9, 0xF8,
+ 0x08, 0x00, 0x08, 0xF0, 0x3D, 0xFD, 0x30, 0xF9, 0x15, 0x10, 0x7F, 0x1C, 0x88, 0x44, 0xFF, 0xB2,
+ 0xE0, 0x78, 0xB8, 0x42, 0xF2, 0xD2, 0x20, 0x78, 0x41, 0x1C, 0xA9, 0x42, 0x13, 0xD2, 0x2D, 0x49,
+ 0x09, 0x68, 0xB1, 0xF8, 0x28, 0x24, 0x02, 0xEB, 0x0B, 0x01, 0x51, 0x45, 0x03, 0xDA, 0x41, 0x45,
+ 0x01, 0xDA, 0x00, 0x26, 0x10, 0xE0, 0x80, 0x1C, 0xA8, 0x42, 0x04, 0xD2, 0x00, 0x98, 0x81, 0x42,
+ 0x01, 0xDA, 0x41, 0x45, 0xF5, 0xDB, 0xCD, 0xF8, 0x00, 0xA0, 0xDA, 0x46, 0x6D, 0x1C, 0xC3, 0x46,
+ 0xED, 0xB2, 0x60, 0x78, 0xA8, 0x42, 0xCD, 0xD2, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x07, 0x46, 0x98, 0x8C, 0x14, 0x46, 0x00, 0x26, 0x1D, 0x46, 0xC2, 0x05, 0x02, 0xD5,
+ 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x06, 0x27, 0xD4, 0x16, 0x48, 0xEA, 0x8C, 0x00, 0x68,
+ 0x90, 0xF8, 0x23, 0x34, 0x9A, 0x42, 0x20, 0xD3, 0xB0, 0xF8, 0x24, 0x34, 0xAA, 0x69, 0x9A, 0x42,
+ 0x1B, 0xDC, 0x62, 0x78, 0x23, 0x78, 0x90, 0xF8, 0x26, 0x04, 0xD2, 0x1A, 0x52, 0x1C, 0x82, 0x42,
+ 0x13, 0xDC, 0xE2, 0x78, 0xA3, 0x78, 0xD2, 0x1A, 0x52, 0x1C, 0x82, 0x42, 0x0D, 0xDC, 0x2B, 0x46,
+ 0x22, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xEF, 0xFE, 0x01, 0x28, 0x06, 0xD1, 0x29, 0x46, 0x20, 0x46,
+ 0xFF, 0xF7, 0x59, 0xFF, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x26, 0x30, 0x46, 0xD1, 0xE7, 0x00, 0x00,
+ 0x28, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xB9, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0xF4, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x70, 0x47, 0xF0, 0xB5, 0x68, 0x4B, 0x02, 0x46,
+ 0x0C, 0x46, 0x1F, 0x78, 0x67, 0x4B, 0x1E, 0x68, 0x67, 0x4B, 0x1D, 0x78, 0x19, 0xE0, 0x2B, 0x46,
+ 0x11, 0xE0, 0x00, 0xBF, 0x34, 0xF8, 0x13, 0xC0, 0x32, 0xF8, 0x13, 0xE0, 0xAC, 0xEB, 0x0E, 0x0C,
+ 0xB6, 0xF9, 0x46, 0xE0, 0x0F, 0xFA, 0x8C, 0xFC, 0x1E, 0xEB, 0x0C, 0x0F, 0x22, 0xD4, 0xB6, 0xF8,
+ 0x48, 0xE0, 0xE6, 0x45, 0x1E, 0xDB, 0x5B, 0x1E, 0xEC, 0xD1, 0x02, 0xEB, 0x45, 0x02, 0x04, 0xEB,
+ 0x45, 0x04, 0x7F, 0x1E, 0xE3, 0xD2, 0x96, 0xF8, 0x44, 0x20, 0x58, 0x4B, 0x02, 0xF0, 0x0F, 0x02,
+ 0xC2, 0xF1, 0x10, 0x04, 0xB3, 0xF9, 0x00, 0x30, 0x0A, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x13, 0x50,
+ 0x30, 0xF9, 0x13, 0x60, 0x55, 0x43, 0x06, 0xFB, 0x04, 0x55, 0x2D, 0x11, 0x21, 0xF8, 0x13, 0x50,
+ 0x5B, 0x1E, 0xF3, 0xD2, 0xF0, 0xBD, 0xF0, 0xB5, 0x14, 0x46, 0x05, 0x9F, 0x0B, 0xE0, 0x00, 0xBF,
+ 0x31, 0xF9, 0x14, 0x50, 0x30, 0xF9, 0x14, 0x60, 0x05, 0xEB, 0x03, 0x0C, 0xB4, 0x45, 0x19, 0xDB,
+ 0xED, 0x1B, 0xB5, 0x42, 0x16, 0xDC, 0x64, 0x1E, 0xF2, 0xD1, 0x42, 0x4B, 0x1B, 0x68, 0x93, 0xF8,
+ 0x45, 0x30, 0x1B, 0x09, 0xC3, 0xF1, 0x10, 0x04, 0x0A, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x12, 0x50,
+ 0x30, 0xF9, 0x12, 0x60, 0x5D, 0x43, 0x06, 0xFB, 0x04, 0x55, 0x2D, 0x11, 0x21, 0xF8, 0x12, 0x50,
+ 0x52, 0x1E, 0xF3, 0xD2, 0xF0, 0xBD, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x00, 0xF0, 0x6D, 0xFF,
+ 0x00, 0x28, 0x25, 0xD1, 0xE8, 0x07, 0x08, 0xD0, 0x35, 0x48, 0x36, 0x49, 0x00, 0x78, 0x09, 0x68,
+ 0x01, 0x28, 0x20, 0x68, 0x1D, 0xD0, 0x00, 0xF0, 0x1F, 0xF8, 0xE8, 0x06, 0x18, 0xD5, 0x2D, 0x4D,
+ 0x28, 0x68, 0xB0, 0xF9, 0x50, 0x10, 0x00, 0x91, 0x29, 0x49, 0xB0, 0xF9, 0x4E, 0x30, 0x20, 0x69,
+ 0x0A, 0x78, 0x2D, 0x49, 0xFF, 0xF7, 0xB7, 0xFF, 0x28, 0x68, 0xB0, 0xF9, 0x54, 0x10, 0x00, 0x91,
+ 0x25, 0x49, 0xB0, 0xF9, 0x52, 0x30, 0x60, 0x69, 0x0A, 0x78, 0x28, 0x49, 0xFF, 0xF7, 0xAB, 0xFF,
+ 0x38, 0xBD, 0xFF, 0xF7, 0x6A, 0xFF, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x43, 0x81, 0x46, 0x24, 0x48,
+ 0x03, 0x78, 0x1C, 0x48, 0x05, 0x2B, 0x00, 0x68, 0x90, 0xF8, 0x44, 0x20, 0x0D, 0xD0, 0x30, 0xF9,
+ 0x46, 0x5F, 0x02, 0xF0, 0x0F, 0x03, 0xB0, 0xF9, 0x02, 0x60, 0x00, 0xBF, 0x17, 0x48, 0xC3, 0xF1,
+ 0x10, 0x04, 0xB0, 0xF9, 0x00, 0x00, 0x02, 0x46, 0x11, 0xE0, 0x30, 0xF9, 0x4A, 0x5F, 0x13, 0x09,
+ 0xB0, 0xF9, 0x02, 0x60, 0xF2, 0xE7, 0x00, 0xBF, 0x31, 0xF9, 0x12, 0x70, 0x39, 0xF9, 0x12, 0xC0,
+ 0x07, 0xEB, 0x05, 0x08, 0xE0, 0x45, 0x11, 0xDB, 0xBF, 0x1B, 0x67, 0x45, 0x0E, 0xDC, 0x52, 0x1E,
+ 0xF2, 0xD2, 0x09, 0xE0, 0x31, 0xF9, 0x10, 0x20, 0x39, 0xF9, 0x10, 0x50, 0x5A, 0x43, 0x05, 0xFB,
+ 0x04, 0x22, 0x12, 0x11, 0x21, 0xF8, 0x10, 0x20, 0x40, 0x1E, 0xF3, 0xD2, 0xBD, 0xE8, 0xF0, 0x83,
+ 0xB9, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0xCA, 0x06, 0x10, 0x00,
+ 0xBF, 0x06, 0x10, 0x00, 0xE8, 0x06, 0x10, 0x00, 0x6A, 0x4A, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20,
+ 0xB8, 0x06, 0x10, 0x00, 0x2D, 0xE9, 0xFC, 0x47, 0x81, 0x46, 0xB9, 0x48, 0xB9, 0x4E, 0x88, 0x46,
+ 0x01, 0x78, 0x30, 0x68, 0x01, 0x25, 0x11, 0xB9, 0xB7, 0x49, 0x09, 0x78, 0x11, 0xB1, 0xB0, 0xF9,
+ 0xA1, 0x42, 0x0D, 0xE0, 0xB5, 0x49, 0xB0, 0xF9, 0x9B, 0x42, 0x49, 0x78, 0x01, 0x29, 0x02, 0xD0,
+ 0x02, 0x29, 0x03, 0xD0, 0x04, 0xE0, 0xB0, 0xF9, 0x9D, 0x42, 0x01, 0xE0, 0xB0, 0xF9, 0x9F, 0x42,
+ 0x02, 0x21, 0x01, 0xA8, 0x00, 0xF0, 0xBE, 0xFA, 0xAD, 0x4F, 0x42, 0x46, 0x49, 0x46, 0xB7, 0xF9,
+ 0x00, 0x30, 0x01, 0x98, 0x03, 0xF0, 0xE1, 0xFD, 0x31, 0x68, 0x91, 0xF8, 0xAA, 0x02, 0x02, 0x07,
+ 0x05, 0xD4, 0xC0, 0x06, 0x03, 0xD4, 0x91, 0xF8, 0xAB, 0x02, 0xC0, 0x07, 0x08, 0xD0, 0xB7, 0xF9,
+ 0x00, 0x00, 0x01, 0x99, 0x00, 0x90, 0x80, 0x23, 0xA2, 0x4A, 0x08, 0x46, 0x03, 0xF0, 0xDA, 0xFD,
+ 0xB7, 0xF9, 0x00, 0x10, 0x01, 0x9A, 0x0C, 0xE0, 0x32, 0xF9, 0x11, 0x00, 0x00, 0x28, 0x01, 0xDB,
+ 0x03, 0x46, 0x00, 0xE0, 0x43, 0x42, 0xA3, 0x42, 0x03, 0xDD, 0x9B, 0x49, 0x00, 0x25, 0x08, 0x80,
+ 0x01, 0xE0, 0x49, 0x1E, 0xF0, 0xD2, 0x02, 0x21, 0x01, 0xA8, 0x00, 0xF0, 0xEE, 0xFA, 0x28, 0x46,
+ 0xBD, 0xE8, 0xFC, 0x87, 0x8F, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x90, 0x02, 0x40, 0x07, 0x07, 0xD5,
+ 0x8E, 0x48, 0x92, 0x49, 0xC0, 0x78, 0x09, 0x78, 0x88, 0x42, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47,
+ 0x00, 0x20, 0x70, 0x47, 0x87, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x90, 0xF8, 0x90, 0x12, 0x89, 0x07,
+ 0x27, 0xD5, 0x8B, 0x49, 0x0A, 0x78, 0x52, 0x1C, 0xD2, 0xB2, 0x0A, 0x70, 0x90, 0xF8, 0x92, 0x32,
+ 0x93, 0x42, 0x1E, 0xD2, 0x00, 0x22, 0x0A, 0x70, 0x90, 0xF8, 0x50, 0x12, 0x03, 0x24, 0xC9, 0x07,
+ 0x03, 0xD1, 0x90, 0xF8, 0x80, 0x02, 0xC0, 0x07, 0x00, 0xD0, 0x0B, 0x24, 0xF1, 0xF7, 0xC6, 0xFF,
+ 0x80, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF1, 0xF7, 0xBE, 0xFF, 0x10, 0x21, 0x05, 0x20,
+ 0x02, 0xF0, 0x40, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x06, 0xF0,
+ 0x32, 0xB9, 0x10, 0xBD, 0x6E, 0x49, 0x70, 0x4A, 0x70, 0x48, 0x09, 0x78, 0x12, 0x78, 0x43, 0x78,
+ 0x11, 0x43, 0x0B, 0x43, 0x72, 0x49, 0x4F, 0xF0, 0x00, 0x02, 0x08, 0xD1, 0x4B, 0x78, 0x5B, 0x1C,
+ 0xDB, 0xB2, 0x4B, 0x70, 0x05, 0x2B, 0x03, 0xD9, 0x01, 0x23, 0x43, 0x70, 0x83, 0x70, 0x4A, 0x70,
+ 0x70, 0x47, 0x2D, 0xE9, 0xF3, 0x4F, 0x6C, 0x48, 0x00, 0x27, 0xDF, 0xF8, 0x94, 0xA1, 0x90, 0xF8,
+ 0x00, 0x80, 0x60, 0x48, 0x81, 0xB0, 0x8B, 0x46, 0x00, 0x68, 0x3C, 0x46, 0xB9, 0x46, 0x90, 0xF8,
+ 0x90, 0x02, 0xC0, 0x07, 0x1F, 0xD0, 0x00, 0x26, 0x01, 0x9D, 0x16, 0xE0, 0x63, 0x4A, 0x28, 0x46,
+ 0x59, 0x46, 0x12, 0x78, 0x01, 0x2A, 0x13, 0xD0, 0xFF, 0xF7, 0x34, 0xFF, 0x10, 0xF0, 0x01, 0x0F,
+ 0x05, 0xD0, 0x01, 0x20, 0xB0, 0x40, 0x38, 0x43, 0x64, 0x1C, 0xC7, 0xB2, 0xE4, 0xB2, 0xBA, 0xF9,
+ 0x00, 0x00, 0x76, 0x1C, 0x05, 0xEB, 0x40, 0x05, 0x36, 0xB2, 0x46, 0x45, 0xE6, 0xDB, 0x04, 0xE0,
+ 0x00, 0xF0, 0x21, 0xF8, 0xEA, 0xE7, 0x44, 0x46, 0xFF, 0x27, 0x55, 0x48, 0x07, 0x70, 0x4C, 0xB1,
+ 0x00, 0x94, 0xBA, 0xF8, 0x00, 0x00, 0x3B, 0x46, 0x82, 0xB2, 0x41, 0x46, 0x01, 0x98, 0x00, 0xF0,
+ 0x4A, 0xF8, 0x07, 0xE0, 0x48, 0x48, 0xB0, 0xF9, 0x00, 0x10, 0x03, 0x20, 0x02, 0xF0, 0xDA, 0xF9,
+ 0x4F, 0xF0, 0x01, 0x09, 0x48, 0x46, 0xBD, 0xE8, 0xFE, 0x8F, 0x70, 0x47, 0x44, 0x48, 0x00, 0x21,
+ 0x01, 0x70, 0x41, 0x70, 0x70, 0x47, 0x70, 0xB5, 0x39, 0x4A, 0x13, 0x78, 0x39, 0x4A, 0x12, 0x68,
+ 0x13, 0xB9, 0x39, 0x4B, 0x1B, 0x78, 0x13, 0xB1, 0xB2, 0xF9, 0x99, 0x32, 0x0D, 0xE0, 0x37, 0x4C,
+ 0xB2, 0xF9, 0x93, 0x32, 0x64, 0x78, 0x01, 0x2C, 0x02, 0xD0, 0x02, 0x2C, 0x03, 0xD0, 0x04, 0xE0,
+ 0xB2, 0xF9, 0x95, 0x32, 0x01, 0xE0, 0xB2, 0xF9, 0x97, 0x32, 0x31, 0x4A, 0x39, 0x4C, 0xB2, 0xF9,
+ 0x00, 0x20, 0x25, 0x78, 0x13, 0xE0, 0x00, 0xBF, 0x30, 0xF9, 0x12, 0x40, 0x31, 0xF9, 0x12, 0x60,
+ 0xA4, 0x1B, 0x00, 0xD5, 0x64, 0x42, 0x24, 0xB2, 0x9C, 0x42, 0x08, 0xDD, 0x92, 0xFB, 0xF5, 0xF6,
+ 0x05, 0xFB, 0x16, 0x26, 0x1E, 0xB1, 0x28, 0x48, 0x04, 0x80, 0x00, 0x20, 0x70, 0xBD, 0x52, 0x1E,
+ 0xEA, 0xD2, 0x01, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x03, 0x06, 0x9F, 0x00, 0x2F, 0x19, 0xD0,
+ 0x01, 0x25, 0x01, 0x2F, 0x02, 0xD0, 0x14, 0x46, 0xA9, 0x46, 0x2E, 0xE0, 0x00, 0x24, 0x0F, 0xE0,
+ 0x05, 0xFA, 0x04, 0xF6, 0x1E, 0x42, 0x0A, 0xD0, 0x00, 0x2C, 0x0B, 0xD0, 0x53, 0x00, 0x62, 0x43,
+ 0xBD, 0xE8, 0xF0, 0x03, 0x00, 0xEB, 0x42, 0x01, 0x1A, 0x46, 0x08, 0xF0, 0x03, 0xB9, 0x64, 0x1C,
+ 0x8C, 0x42, 0xED, 0xDB, 0xBD, 0xE8, 0xF0, 0x03, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x26, 0x00, 0xEB,
+ 0x44, 0x0C, 0x35, 0x46, 0x0B, 0xE0, 0x00, 0xBF, 0x09, 0xFA, 0x05, 0xF8, 0x18, 0xEA, 0x03, 0x0F,
+ 0x02, 0xD0, 0xBC, 0xF9, 0x00, 0x80, 0x46, 0x44, 0x0C, 0xEB, 0x42, 0x0C, 0x6D, 0x1C, 0x8D, 0x42,
+ 0xF2, 0xDB, 0x96, 0xFB, 0xF7, 0xF5, 0x20, 0xF8, 0x14, 0x50, 0x64, 0x1E, 0xE6, 0xD2, 0xE1, 0xE7,
+ 0x1C, 0x05, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x28, 0x05, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0xCA, 0x06, 0x10, 0x00, 0x78, 0x12, 0x01, 0x20, 0x56, 0x06, 0x10, 0x00, 0xBB, 0x06, 0x10, 0x00,
+ 0x4C, 0x06, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0xBC, 0x06, 0x10, 0x00, 0xBF, 0x06, 0x10, 0x00,
+ 0x51, 0x06, 0x10, 0x00, 0xBA, 0x06, 0x10, 0x00, 0x10, 0xB5, 0xF6, 0xF7, 0x51, 0xFD, 0xF7, 0xF7,
+ 0xE2, 0xF9, 0xBD, 0xE8, 0x10, 0x40, 0xF5, 0xF7, 0x51, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0x81, 0x46,
+ 0x1F, 0x46, 0x90, 0x46, 0x0E, 0x46, 0x03, 0x20, 0x08, 0x9D, 0x06, 0xF0, 0xC4, 0xF8, 0x6E, 0x48,
+ 0x01, 0x68, 0x48, 0x46, 0xFF, 0xF7, 0x05, 0xFF, 0x04, 0x46, 0x03, 0x20, 0x06, 0xF0, 0xD6, 0xF8,
+ 0x64, 0xB1, 0xFF, 0xF7, 0xE7, 0xFE, 0xFF, 0xF7, 0xB5, 0xFE, 0x31, 0x46, 0x48, 0x46, 0xFF, 0xF7,
+ 0x44, 0xFF, 0x66, 0x48, 0x04, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xFF, 0xF7, 0x3E, 0xFF,
+ 0x16, 0xB1, 0x30, 0x46, 0x00, 0xF0, 0xCC, 0xFB, 0x5D, 0xB1, 0x61, 0x48, 0x01, 0x78, 0x28, 0x46,
+ 0xF6, 0xF7, 0x45, 0xFD, 0x5F, 0x48, 0x80, 0x78, 0x18, 0xB1, 0x5F, 0x49, 0x00, 0x20, 0x08, 0x70,
+ 0x48, 0x70, 0x08, 0xF0, 0xC3, 0xF9, 0x05, 0x46, 0xFF, 0xF7, 0x84, 0xFE, 0x50, 0xEA, 0x05, 0x04,
+ 0xDB, 0xD1, 0x3A, 0x46, 0x41, 0x46, 0x48, 0x46, 0x00, 0xF0, 0x3C, 0xF8, 0x04, 0x46, 0xD4, 0xE7,
+ 0x10, 0xB5, 0x04, 0x46, 0x00, 0xF0, 0x7F, 0xF8, 0x00, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x15, 0xFF,
+ 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xF8, 0xF7, 0x34, 0xFA, 0xFD, 0xF7, 0xA5, 0xFE, 0xFB, 0xF7,
+ 0xDF, 0xFC, 0xFF, 0xF7, 0xA1, 0xFF, 0xFF, 0xF7, 0x09, 0xFF, 0xFC, 0xF7, 0x7E, 0xFB, 0x47, 0x49,
+ 0x00, 0x20, 0x08, 0x70, 0x48, 0x70, 0x88, 0x80, 0xC8, 0x80, 0x88, 0x70, 0x88, 0x60, 0xC8, 0x60,
+ 0x08, 0x61, 0x14, 0x31, 0x08, 0x70, 0x88, 0x70, 0x44, 0x48, 0x00, 0x68, 0x10, 0xF8, 0x30, 0x2F,
+ 0x4A, 0x70, 0x40, 0x78, 0xC8, 0x70, 0x10, 0xBD, 0x10, 0xB5, 0xF8, 0xF7, 0x23, 0xFA, 0xFD, 0xF7,
+ 0x96, 0xFE, 0x00, 0xF0, 0xF0, 0xFB, 0xF7, 0xF7, 0x73, 0xF9, 0x3A, 0x48, 0x00, 0x21, 0x41, 0x70,
+ 0x81, 0x70, 0x10, 0xBD, 0xF8, 0xB5, 0x07, 0x46, 0x00, 0x24, 0x15, 0x46, 0x0E, 0x46, 0x8D, 0xF8,
+ 0x00, 0x40, 0x02, 0x20, 0x06, 0xF0, 0x47, 0xF8, 0x2A, 0x46, 0x31, 0x46, 0x38, 0x46, 0xF8, 0xF7,
+ 0x6A, 0xF8, 0x33, 0x49, 0x01, 0x28, 0xCA, 0x78, 0x60, 0xF3, 0x03, 0x02, 0xCA, 0x70, 0x28, 0xD0,
+ 0x02, 0x28, 0x2B, 0xD0, 0x04, 0x28, 0x00, 0xD0, 0x01, 0x24, 0x6B, 0x46, 0x2A, 0x46, 0x31, 0x46,
+ 0x38, 0x46, 0xFC, 0xF7, 0x63, 0xFA, 0x40, 0xEA, 0x04, 0x05, 0x02, 0x20, 0x06, 0xF0, 0x46, 0xF8,
+ 0x9D, 0xF8, 0x00, 0x00, 0x98, 0xB1, 0xF1, 0xF7, 0x09, 0xFE, 0x26, 0x48, 0x26, 0x4A, 0x01, 0x68,
+ 0x12, 0x68, 0x11, 0x43, 0x01, 0x60, 0xF1, 0xF7, 0xFF, 0xFD, 0x24, 0x48, 0x01, 0x78, 0x05, 0x20,
+ 0x02, 0xF0, 0x80, 0xF8, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x05, 0xF0, 0x74, 0xFF, 0x28, 0x46,
+ 0xF8, 0xBD, 0xFD, 0xF7, 0x2B, 0xFE, 0xFB, 0xF7, 0x94, 0xFC, 0xD6, 0xE7, 0xFD, 0xF7, 0x86, 0xFB,
+ 0xFB, 0xF7, 0xBC, 0xFC, 0xD1, 0xE7, 0x70, 0xB5, 0x05, 0x46, 0x00, 0x24, 0x02, 0x20, 0x06, 0xF0,
+ 0x02, 0xF8, 0x28, 0x46, 0xF8, 0xF7, 0x4B, 0xF9, 0x11, 0x49, 0x01, 0x28, 0xCA, 0x78, 0x60, 0xF3,
+ 0x03, 0x02, 0xCA, 0x70, 0x02, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x08, 0xE0, 0xFD, 0xF7, 0x1B, 0xFE,
+ 0xFB, 0xF7, 0xEA, 0xFC, 0x03, 0xE0, 0xFD, 0xF7, 0xFA, 0xFC, 0xFB, 0xF7, 0xF6, 0xFC, 0x02, 0x20,
+ 0x06, 0xF0, 0x04, 0xF8, 0x20, 0x46, 0x70, 0xBD, 0xE8, 0x06, 0x10, 0x00, 0x50, 0x06, 0x10, 0x00,
+ 0x50, 0x07, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00, 0xEC, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0xE6, 0x43, 0x01, 0x20, 0x28, 0x07, 0x10, 0x00, 0x08, 0x06, 0x10, 0x00, 0x04, 0x06, 0x10, 0x00,
+ 0x06, 0x29, 0x04, 0xD2, 0x8B, 0x4A, 0x51, 0x5C, 0x8B, 0x4A, 0x53, 0x5C, 0x2B, 0xB1, 0x00, 0x21,
+ 0x01, 0x60, 0x01, 0x46, 0x48, 0x20, 0x01, 0xF0, 0x02, 0xBD, 0x86, 0x4B, 0x08, 0x33, 0x53, 0xF8,
+ 0x21, 0x30, 0x03, 0x60, 0x85, 0x4B, 0x43, 0xF8, 0x21, 0x00, 0x01, 0x20, 0x50, 0x54, 0x70, 0x47,
+ 0x0A, 0x46, 0x30, 0xB4, 0x00, 0x21, 0x06, 0x2A, 0x11, 0xD2, 0x7E, 0x4B, 0x9A, 0x5C, 0x72, 0xB1,
+ 0x7C, 0x4C, 0x03, 0x68, 0x08, 0x34, 0x54, 0xF8, 0x22, 0x40, 0xA3, 0x42, 0x07, 0xD1, 0x7A, 0x4B,
+ 0x99, 0x54, 0x7A, 0x4B, 0x43, 0xF8, 0x22, 0x10, 0x01, 0x60, 0x30, 0xBC, 0x70, 0x47, 0x01, 0x60,
+ 0x01, 0x46, 0x30, 0xBC, 0x49, 0x20, 0x01, 0xF0, 0xDA, 0xBC, 0x2D, 0xE9, 0xF0, 0x41, 0x01, 0x24,
+ 0x71, 0x4D, 0x72, 0x4F, 0x00, 0x26, 0x28, 0x5D, 0x38, 0xB1, 0x2E, 0x55, 0x57, 0xF8, 0x24, 0x10,
+ 0x4A, 0x20, 0x01, 0xF0, 0xCC, 0xFC, 0x47, 0xF8, 0x24, 0x60, 0x64, 0x1C, 0x03, 0x2C, 0xF2, 0xDB,
+ 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xF0, 0x41, 0x68, 0x4D, 0x67, 0x4B, 0x00, 0x27, 0x0A, 0x46,
+ 0x0C, 0x35, 0x07, 0x60, 0x59, 0x68, 0x05, 0xF1, 0x14, 0x06, 0x03, 0xF1, 0x08, 0x04, 0x01, 0x2A,
+ 0x38, 0xD0, 0x02, 0x2A, 0x1C, 0xD0, 0x03, 0x2A, 0x3F, 0xD1, 0x00, 0x22, 0x04, 0xEB, 0x02, 0x0C,
+ 0xDC, 0xF8, 0x00, 0xE0, 0xBE, 0xF1, 0x00, 0x0F, 0x07, 0xD0, 0x52, 0x1C, 0x02, 0x2A, 0xF5, 0xDB,
+ 0x04, 0x29, 0x30, 0xD3, 0x01, 0x46, 0x4C, 0x20, 0x31, 0xE0, 0x55, 0xF8, 0x22, 0x40, 0x04, 0x60,
+ 0x46, 0xF8, 0x22, 0x00, 0x4F, 0xF0, 0x03, 0x30, 0x09, 0x1F, 0xCC, 0xF8, 0x00, 0x00, 0x32, 0xE0,
+ 0x5F, 0xF0, 0x00, 0x02, 0x04, 0xEB, 0x02, 0x0C, 0xBC, 0xF8, 0x00, 0xE0, 0xBE, 0xF1, 0x00, 0x0F,
+ 0x05, 0xD0, 0x52, 0x1C, 0x04, 0x2A, 0xF5, 0xDB, 0x02, 0x29, 0xE3, 0xD2, 0x13, 0xE0, 0x55, 0xF8,
+ 0x22, 0x40, 0x04, 0x60, 0x46, 0xF8, 0x22, 0x00, 0x40, 0xF2, 0x02, 0x20, 0xAC, 0xF8, 0x00, 0x00,
+ 0x89, 0x1E, 0x18, 0xE0, 0x5F, 0xF0, 0x04, 0x02, 0x14, 0xF8, 0x02, 0xC0, 0xBC, 0xF1, 0x00, 0x0F,
+ 0x09, 0xD0, 0x52, 0x1E, 0xF8, 0xD2, 0x00, 0x2F, 0xAA, 0xD1, 0x01, 0x46, 0x4B, 0x20, 0xBD, 0xE8,
+ 0xF0, 0x41, 0x01, 0xF0, 0x6C, 0xBC, 0x55, 0xF8, 0x22, 0x50, 0x05, 0x60, 0x46, 0xF8, 0x22, 0x00,
+ 0x01, 0x20, 0xA0, 0x54, 0x49, 0x1E, 0x59, 0x60, 0x9A, 0xE7, 0xF0, 0xB4, 0x37, 0x4E, 0x36, 0x4C,
+ 0x00, 0x25, 0x04, 0x22, 0x0C, 0x36, 0xD0, 0xF8, 0x00, 0x30, 0x08, 0x34, 0x56, 0xF8, 0x22, 0x70,
+ 0x9F, 0x42, 0x12, 0xD1, 0xA7, 0x5C, 0x8F, 0x42, 0x0F, 0xD1, 0x53, 0x1C, 0x11, 0xD0, 0x2F, 0x4D,
+ 0x00, 0x23, 0x20, 0x35, 0x03, 0x60, 0x45, 0xF8, 0x22, 0x30, 0xA3, 0x54, 0x01, 0x29, 0x11, 0xD0,
+ 0x02, 0x29, 0x11, 0xD0, 0x03, 0x29, 0x04, 0xD1, 0x08, 0xE0, 0x52, 0x1E, 0xE6, 0xD2, 0x00, 0x2D,
+ 0x08, 0xD1, 0xF0, 0xBC, 0x01, 0x46, 0x4D, 0x20, 0x01, 0xF0, 0x39, 0xBC, 0xA0, 0x18, 0x43, 0x70,
+ 0x83, 0x70, 0xC3, 0x70, 0xF0, 0xBC, 0x70, 0x47, 0xA0, 0x18, 0x43, 0x70, 0xFA, 0xE7, 0x70, 0xB5,
+ 0x1D, 0x4E, 0x1E, 0x4D, 0x05, 0x24, 0x08, 0x36, 0x20, 0x35, 0x0B, 0xE0, 0x30, 0x5D, 0x48, 0xB1,
+ 0x55, 0xF8, 0x24, 0x10, 0x4E, 0x20, 0x01, 0xF0, 0x22, 0xFC, 0x31, 0x5D, 0x55, 0xF8, 0x24, 0x00,
+ 0xFF, 0xF7, 0xBB, 0xFF, 0x64, 0x1E, 0xF1, 0xD2, 0x70, 0xBD, 0x70, 0xB5, 0x01, 0x20, 0x13, 0x4B,
+ 0x11, 0x4A, 0x00, 0x21, 0x43, 0xF8, 0x20, 0x10, 0x11, 0x54, 0x40, 0x1C, 0x03, 0x28, 0xF9, 0xDB,
+ 0x01, 0x20, 0x10, 0x70, 0x0C, 0x4A, 0x05, 0x20, 0x0C, 0x4B, 0x50, 0x60, 0x0C, 0x33, 0x0A, 0x4C,
+ 0x04, 0x20, 0x0B, 0x4A, 0x08, 0x34, 0x03, 0xF1, 0x14, 0x05, 0x73, 0x26, 0x46, 0x43, 0x02, 0xEB,
+ 0xC6, 0x06, 0x43, 0xF8, 0x20, 0x60, 0x21, 0x54, 0x45, 0xF8, 0x20, 0x10, 0x40, 0x1E, 0xF4, 0xD2,
+ 0x70, 0xBD, 0x00, 0x00, 0x58, 0x6C, 0x01, 0x00, 0x8C, 0x06, 0x10, 0x00, 0x88, 0x47, 0x10, 0x00,
+ 0x84, 0x5A, 0x10, 0x00, 0xF0, 0xB5, 0x06, 0x46, 0xF8, 0x48, 0x00, 0x24, 0xA7, 0xB0, 0x00, 0x78,
+ 0x0D, 0x46, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x98, 0x21, 0x68, 0x46, 0x07, 0xF0, 0x33, 0xFF,
+ 0xF3, 0x4A, 0x00, 0x21, 0x68, 0x46, 0x13, 0x78, 0x11, 0xE0, 0x00, 0xBF, 0x01, 0xFB, 0x03, 0xF7,
+ 0x22, 0x46, 0x09, 0xE0, 0x07, 0xEB, 0x02, 0x0E, 0x50, 0xF8, 0x22, 0xC0, 0x36, 0xF9, 0x1E, 0xE0,
+ 0xF4, 0x44, 0x40, 0xF8, 0x22, 0xC0, 0x52, 0x1C, 0x9A, 0x42, 0xF3, 0xDB, 0x49, 0x1C, 0xA9, 0x42,
+ 0xEC, 0xDB, 0x21, 0x46, 0x07, 0xE0, 0x00, 0xBF, 0x50, 0xF8, 0x21, 0x20, 0x92, 0xFB, 0xF5, 0xF2,
+ 0x40, 0xF8, 0x21, 0x20, 0x49, 0x1C, 0x99, 0x42, 0xF6, 0xDB, 0x00, 0x21, 0x17, 0xE0, 0x00, 0x27,
+ 0x3A, 0x46, 0x0C, 0xE0, 0x02, 0xFB, 0x03, 0x4C, 0x50, 0xF8, 0x24, 0xE0, 0x36, 0xF9, 0x1C, 0xC0,
+ 0xBC, 0xEB, 0x0E, 0x0C, 0x01, 0xD5, 0xCC, 0xF1, 0x00, 0x0C, 0x67, 0x44, 0x52, 0x1C, 0xAA, 0x42,
+ 0xF0, 0xDB, 0x97, 0xFB, 0xF5, 0xF2, 0x8A, 0x42, 0x00, 0xDD, 0x11, 0x46, 0x64, 0x1C, 0x9C, 0x42,
+ 0xE5, 0xDB, 0xB1, 0xF5, 0x80, 0x3F, 0x03, 0xDB, 0x4F, 0xF6, 0xFF, 0x70, 0x27, 0xB0, 0xF0, 0xBD,
+ 0x88, 0xB2, 0xFB, 0xE7, 0xF0, 0xB5, 0xCF, 0x49, 0xCF, 0x4B, 0x09, 0x68, 0x91, 0xF8, 0xAA, 0x22,
+ 0xD2, 0x07, 0x34, 0xD0, 0xCD, 0x4A, 0x57, 0x78, 0x4F, 0xB1, 0x91, 0xF8, 0xB5, 0x42, 0xB1, 0xF8,
+ 0xB2, 0x52, 0x04, 0xF0, 0x0F, 0x02, 0x26, 0x09, 0xB1, 0xF8, 0xB0, 0x42, 0x08, 0xE0, 0x91, 0xF8,
+ 0xB4, 0x42, 0xB1, 0xF8, 0xAE, 0x52, 0x04, 0xF0, 0x0F, 0x02, 0x26, 0x09, 0xB1, 0xF8, 0xAC, 0x42,
+ 0xDF, 0xF8, 0x0C, 0xC3, 0x9C, 0xF8, 0x00, 0xC0, 0xBC, 0xF1, 0x03, 0x0F, 0x06, 0xD1, 0x91, 0xF8,
+ 0xB6, 0x12, 0x0F, 0xB1, 0x0A, 0x09, 0x01, 0xE0, 0x01, 0xF0, 0x0F, 0x02, 0xA0, 0x42, 0x01, 0xDC,
+ 0x1A, 0x60, 0xF0, 0xBD, 0xA8, 0x42, 0x01, 0xDB, 0x1E, 0x60, 0xF0, 0xBD, 0x00, 0x1B, 0xB1, 0x1A,
+ 0x48, 0x43, 0x29, 0x1B, 0x90, 0xFB, 0xF1, 0xF0, 0x10, 0x44, 0x18, 0x60, 0xF0, 0xBD, 0x00, 0x20,
+ 0xFB, 0xE7, 0xB0, 0x48, 0xB1, 0x49, 0x00, 0x68, 0x0A, 0x78, 0x00, 0xF5, 0xF9, 0x70, 0x80, 0x5C,
+ 0xC8, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x0F, 0x83, 0x46, 0xAA, 0x48, 0xDF, 0xF8, 0xAC, 0x92,
+ 0xDF, 0xF8, 0xB0, 0xA2, 0x01, 0x68, 0x99, 0xF8, 0x00, 0x70, 0x00, 0x20, 0x91, 0xF8, 0x0A, 0x62,
+ 0x91, 0xF8, 0x09, 0x12, 0x3A, 0xF8, 0x17, 0x40, 0x6F, 0xF0, 0x00, 0x42, 0x4F, 0xEA, 0x11, 0x18,
+ 0x0B, 0x07, 0x1C, 0xD0, 0x01, 0xF0, 0x0F, 0x05, 0x9E, 0x4B, 0x00, 0x21, 0x8C, 0x46, 0x1B, 0x68,
+ 0xB4, 0x42, 0x93, 0xF8, 0x08, 0x32, 0x05, 0xDB, 0xA6, 0x1B, 0x06, 0xFB, 0x08, 0xF6, 0x96, 0xFB,
+ 0xF5, 0xF5, 0x2B, 0x44, 0x97, 0x4D, 0x99, 0xF8, 0x01, 0x60, 0x2D, 0x68, 0x01, 0x2E, 0x95, 0xF8,
+ 0xF1, 0x51, 0x06, 0xD0, 0x02, 0x2E, 0x07, 0xD0, 0x05, 0xF0, 0x03, 0x06, 0x13, 0xE0, 0x01, 0x25,
+ 0xE2, 0xE7, 0xC5, 0xF3, 0x81, 0x06, 0x0E, 0xE0, 0xC5, 0xF3, 0x01, 0x16, 0x0B, 0xE0, 0x00, 0xBF,
+ 0x3A, 0xF8, 0x1C, 0x50, 0xAA, 0x42, 0x01, 0xDD, 0x2A, 0x46, 0x60, 0x46, 0xA9, 0x42, 0x00, 0xDA,
+ 0x29, 0x46, 0x0C, 0xF1, 0x01, 0x0C, 0xB4, 0x45, 0xF2, 0xDD, 0xAB, 0xF8, 0x00, 0x10, 0xA1, 0x1A,
+ 0x99, 0x42, 0x01, 0xDC, 0xB7, 0x42, 0x04, 0xDD, 0x89, 0xF8, 0x00, 0x00, 0xBD, 0xE8, 0xF0, 0x0F,
+ 0x9F, 0xE7, 0xBD, 0xE8, 0xF0, 0x0F, 0x70, 0x47, 0x83, 0x49, 0x10, 0xB5, 0x0B, 0x78, 0x7D, 0x49,
+ 0x00, 0x22, 0x01, 0x2B, 0x09, 0x68, 0x02, 0xD1, 0x80, 0x4B, 0x1B, 0x78, 0x4B, 0xB1, 0xB1, 0xF8,
+ 0xFC, 0x31, 0x83, 0x42, 0x18, 0xD2, 0x91, 0xF8, 0xF0, 0x31, 0x1B, 0x07, 0x14, 0xD5, 0x03, 0x22,
+ 0x25, 0xE0, 0xB1, 0xF8, 0x02, 0x32, 0x83, 0x42, 0x03, 0xD2, 0x91, 0xF8, 0xF0, 0x31, 0x1B, 0x07,
+ 0xF5, 0xD4, 0xB1, 0xF8, 0x00, 0x32, 0x83, 0x42, 0x03, 0xD2, 0x91, 0xF8, 0xF0, 0x31, 0x5B, 0x07,
+ 0x0A, 0xD4, 0xB1, 0xF8, 0xFE, 0x31, 0x0B, 0xE0, 0xB1, 0xF8, 0xFA, 0x31, 0x83, 0x42, 0x05, 0xD2,
+ 0x91, 0xF8, 0xF0, 0x31, 0x5B, 0x07, 0x01, 0xD5, 0x02, 0x22, 0x08, 0xE0, 0xB1, 0xF8, 0xF8, 0x31,
+ 0x83, 0x42, 0x04, 0xD2, 0x91, 0xF8, 0xF0, 0x01, 0x80, 0x07, 0x00, 0xD5, 0x01, 0x22, 0x65, 0x48,
+ 0x62, 0x4C, 0x14, 0x38, 0x03, 0x78, 0x9A, 0x42, 0x11, 0xD1, 0x61, 0x78, 0x99, 0x42, 0x1A, 0xD0,
+ 0x63, 0x4A, 0x12, 0x78, 0x13, 0x43, 0x07, 0xD0, 0x81, 0x68, 0x49, 0x1E, 0x81, 0x60, 0x00, 0x29,
+ 0x11, 0xDC, 0x00, 0x78, 0x60, 0x70, 0x0E, 0xE0, 0x01, 0x70, 0x81, 0x68, 0xF7, 0xE7, 0x8A, 0xB1,
+ 0x02, 0x2A, 0x01, 0xD1, 0x01, 0x2B, 0x0D, 0xD0, 0x91, 0xF8, 0xF6, 0x11, 0x81, 0x60, 0x02, 0x70,
+ 0x00, 0x29, 0x00, 0xDC, 0x62, 0x70, 0x57, 0x48, 0x62, 0x78, 0x41, 0x7B, 0x62, 0xF3, 0x03, 0x01,
+ 0x41, 0x73, 0x10, 0xBD, 0x91, 0xF8, 0xF7, 0x11, 0xF0, 0xE7, 0x4A, 0x4A, 0x12, 0x68, 0x92, 0xF8,
+ 0xF0, 0x21, 0xD2, 0x06, 0x07, 0xD5, 0x42, 0x1A, 0x00, 0x2A, 0x04, 0xDC, 0xC1, 0xEB, 0xC1, 0x11,
+ 0x08, 0x44, 0xC0, 0xF3, 0xCF, 0x10, 0x70, 0x47, 0x44, 0x49, 0x00, 0x20, 0x41, 0x4A, 0x48, 0x70,
+ 0x44, 0x49, 0x14, 0x39, 0x48, 0x60, 0x88, 0x60, 0x08, 0x70, 0x12, 0x68, 0x92, 0xF8, 0xAA, 0x32,
+ 0xDB, 0x07, 0x03, 0xD0, 0x92, 0xF8, 0xB5, 0x22, 0x12, 0x09, 0x00, 0xE0, 0x00, 0x22, 0x3A, 0x4B,
+ 0x1A, 0x60, 0xC8, 0x60, 0x08, 0x61, 0x48, 0x61, 0x88, 0x61, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F,
+ 0x00, 0x21, 0xAD, 0xF8, 0x00, 0x10, 0x32, 0x49, 0xDF, 0xF8, 0xD8, 0x90, 0xDF, 0xF8, 0xD4, 0x80,
+ 0x0E, 0x78, 0x4F, 0xF0, 0x10, 0x0B, 0x37, 0x01, 0x05, 0x46, 0x00, 0x24, 0xA9, 0xF1, 0x08, 0x09,
+ 0xA8, 0xF1, 0x14, 0x0A, 0x10, 0xE0, 0x32, 0x46, 0x59, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x5A, 0xFE,
+ 0x29, 0xF8, 0x14, 0x00, 0x43, 0x46, 0x38, 0xF8, 0x14, 0x10, 0xFF, 0xF7, 0xB6, 0xFF, 0x23, 0xF8,
+ 0x14, 0x00, 0x05, 0xEB, 0x47, 0x05, 0x64, 0x1C, 0x9A, 0xF8, 0x01, 0x00, 0x84, 0x42, 0xEA, 0xDD,
+ 0x68, 0x46, 0xFF, 0xF7, 0xE7, 0xFE, 0x1F, 0x48, 0x20, 0x4D, 0x00, 0x68, 0x90, 0xF8, 0xF0, 0x01,
+ 0x40, 0x06, 0x02, 0xD5, 0xBD, 0xF8, 0x00, 0x40, 0x02, 0xE0, 0x29, 0x78, 0x38, 0xF8, 0x11, 0x40,
+ 0x21, 0x48, 0x04, 0x80, 0x20, 0x46, 0xFF, 0xF7, 0x2F, 0xFF, 0x20, 0x46, 0xFF, 0xF7, 0x8A, 0xFE,
+ 0x29, 0x78, 0x39, 0xF8, 0x11, 0x00, 0x1B, 0x49, 0xA1, 0xF8, 0x1B, 0x00, 0xBD, 0xE8, 0xF8, 0x8F,
+ 0x2D, 0xE9, 0xFC, 0x5F, 0x0E, 0x49, 0x4F, 0xF0, 0x00, 0x09, 0x0D, 0x78, 0x0B, 0x49, 0x09, 0x78,
+ 0x01, 0x29, 0x00, 0xD1, 0x89, 0x46, 0x0F, 0x49, 0x10, 0x26, 0x14, 0x39, 0x04, 0x46, 0x4A, 0x68,
+ 0x12, 0x48, 0x92, 0xFB, 0xF6, 0xF3, 0x06, 0xFB, 0x13, 0x22, 0x6A, 0x43, 0x4F, 0x78, 0x4F, 0xEA,
+ 0x05, 0x1A, 0x00, 0xEB, 0x42, 0x08, 0x83, 0x46, 0x7F, 0x1C, 0x3D, 0xE0, 0xBF, 0x06, 0x10, 0x00,
+ 0xBA, 0x06, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x78, 0x06, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0xB8, 0x06, 0x10, 0x00, 0xB0, 0x06, 0x10, 0x00, 0xC2, 0x06, 0x10, 0x00, 0xC3, 0x06, 0x10, 0x00,
+ 0xC1, 0x06, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x54, 0x06, 0x10, 0x00, 0x8C, 0x1C, 0x01, 0x20,
+ 0x2A, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xF0, 0x11, 0x89, 0x06, 0x14, 0xD5, 0x28, 0x49, 0x49, 0x68,
+ 0x00, 0x29, 0x0E, 0xDD, 0xA5, 0xEB, 0x09, 0x02, 0xB0, 0xF9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12,
+ 0xB0, 0xF9, 0x04, 0x32, 0x04, 0xEB, 0x49, 0x00, 0x0B, 0xEB, 0x49, 0x02, 0x01, 0x46, 0x02, 0xF0,
+ 0xB3, 0xFF, 0x0B, 0xEB, 0x4A, 0x0B, 0x6A, 0x00, 0x21, 0x46, 0x40, 0x46, 0x07, 0xF0, 0x72, 0xFC,
+ 0x04, 0xEB, 0x45, 0x04, 0x08, 0xEB, 0x4A, 0x08, 0x7F, 0x1E, 0xD9, 0xD2, 0x18, 0x48, 0x4F, 0xF0,
+ 0xFF, 0x31, 0x01, 0xEB, 0x46, 0x01, 0x42, 0x68, 0x52, 0x1C, 0x42, 0x60, 0x91, 0x42, 0x00, 0xDA,
+ 0x46, 0x60, 0x40, 0x68, 0xB0, 0x42, 0x03, 0xDB, 0xBD, 0xE8, 0xFC, 0x5F, 0x11, 0x48, 0x45, 0xE7,
+ 0xBD, 0xE8, 0xFC, 0x9F, 0x28, 0xE7, 0x10, 0xB5, 0x0C, 0x4C, 0x20, 0x68, 0x90, 0xF8, 0xF1, 0x01,
+ 0xC0, 0xF3, 0x01, 0x12, 0xC0, 0xF3, 0x81, 0x01, 0x00, 0xF0, 0x03, 0x00, 0x02, 0xF0, 0x73, 0xF9,
+ 0x07, 0x49, 0x48, 0x70, 0x20, 0x68, 0x08, 0x49, 0x90, 0xF8, 0xEC, 0x00, 0x00, 0xF0, 0x03, 0x00,
+ 0x08, 0x70, 0xFF, 0xF7, 0x36, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x0D, 0xE7, 0x20, 0x07, 0x10, 0x00,
+ 0x9C, 0x06, 0x10, 0x00, 0x8C, 0x1C, 0x01, 0x20, 0x4C, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xD1, 0x48,
+ 0x00, 0x24, 0x84, 0x61, 0x44, 0x63, 0x04, 0x87, 0x80, 0xF8, 0x3A, 0x40, 0x04, 0x62, 0xC4, 0x61,
+ 0xFF, 0xF7, 0xDA, 0xFB, 0xFF, 0xF7, 0x59, 0xFD, 0xCB, 0x48, 0x04, 0x80, 0xBD, 0xE8, 0x10, 0x40,
+ 0x00, 0xF0, 0xED, 0xB8, 0xC9, 0x48, 0x10, 0xB5, 0x90, 0xF8, 0x2C, 0x10, 0xC6, 0x48, 0xC5, 0x4A,
+ 0x81, 0x70, 0x53, 0x7A, 0x01, 0x79, 0x63, 0xF3, 0x00, 0x01, 0xD3, 0x7A, 0x63, 0xF3, 0xC3, 0x01,
+ 0x93, 0x7A, 0x63, 0xF3, 0x82, 0x01, 0x13, 0x7B, 0x63, 0xF3, 0x41, 0x01, 0xC0, 0x4B, 0xDB, 0x78,
+ 0x03, 0x72, 0x93, 0x7B, 0xC3, 0x71, 0x53, 0x7B, 0xD4, 0x7B, 0x63, 0xF3, 0x04, 0x11, 0x83, 0x7B,
+ 0x12, 0x7C, 0x64, 0xF3, 0x03, 0x03, 0x62, 0xF3, 0x07, 0x13, 0xBA, 0x4A, 0x83, 0x73, 0x12, 0x78,
+ 0x80, 0xF8, 0x28, 0x20, 0xB8, 0x4A, 0x12, 0x88, 0xA0, 0xF8, 0x29, 0x20, 0xB7, 0x4A, 0x12, 0x78,
+ 0x62, 0xF3, 0x45, 0x11, 0xB6, 0x4A, 0x12, 0x78, 0x62, 0xF3, 0xC7, 0x11, 0x01, 0x71, 0xB5, 0x49,
+ 0x09, 0x88, 0xA0, 0xF8, 0x2B, 0x10, 0xB4, 0x49, 0x09, 0x88, 0xA0, 0xF8, 0x2D, 0x10, 0xB3, 0x49,
+ 0x0A, 0x78, 0xC1, 0x7B, 0x62, 0xF3, 0x03, 0x01, 0xC1, 0x73, 0xB1, 0x49, 0x0A, 0x78, 0x01, 0x7C,
+ 0x62, 0xF3, 0x00, 0x01, 0xAF, 0x4A, 0x12, 0x78, 0x62, 0xF3, 0x41, 0x01, 0xAE, 0x4A, 0x12, 0x78,
+ 0x62, 0xF3, 0xC3, 0x01, 0x21, 0xF0, 0x04, 0x01, 0x01, 0x74, 0xAC, 0x49, 0x0A, 0x88, 0x02, 0x87,
+ 0x4A, 0x88, 0x42, 0x87, 0x8A, 0x88, 0x82, 0x87, 0xC9, 0x88, 0xC1, 0x87, 0x10, 0xBD, 0x70, 0xB5,
+ 0x0D, 0x46, 0x80, 0xEA, 0x05, 0x06, 0xF0, 0x06, 0x01, 0xD5, 0xF6, 0xF7, 0xDC, 0xFC, 0x95, 0x4C,
+ 0xC5, 0xF3, 0x00, 0x10, 0x34, 0x34, 0x20, 0x70, 0xB0, 0x06, 0x01, 0xD5, 0xF5, 0xF7, 0x46, 0xFA,
+ 0xC5, 0xF3, 0x40, 0x10, 0x60, 0x70, 0x15, 0xF0, 0x48, 0x00, 0x00, 0xD0, 0x01, 0x20, 0xA0, 0x71,
+ 0x9B, 0x48, 0x00, 0x68, 0x90, 0xF8, 0x40, 0x14, 0x01, 0xF0, 0x01, 0x01, 0x21, 0x71, 0x90, 0xF8,
+ 0x20, 0x04, 0x00, 0xF0, 0x01, 0x00, 0x60, 0x71, 0x70, 0xBD, 0x70, 0xB5, 0x85, 0x4D, 0x87, 0x4C,
+ 0x29, 0x6A, 0x20, 0x6A, 0x81, 0xEA, 0x00, 0x06, 0x19, 0xB9, 0x10, 0xB1, 0xFF, 0xF7, 0x5E, 0xFF,
+ 0x09, 0xE0, 0xF0, 0x07, 0x03, 0xD0, 0xFF, 0xF7, 0x1D, 0xFB, 0xFF, 0xF7, 0x33, 0xFF, 0xF0, 0x06,
+ 0x01, 0xD5, 0xFF, 0xF7, 0xC1, 0xFA, 0xE1, 0x69, 0xA8, 0x69, 0xFF, 0xF7, 0xC0, 0xFF, 0xE0, 0x69,
+ 0xA8, 0x61, 0x20, 0x6A, 0x28, 0x62, 0x60, 0x6A, 0xE8, 0x61, 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0,
+ 0x66, 0xB8, 0x70, 0xB5, 0x83, 0x4D, 0x2C, 0x68, 0x00, 0x2C, 0x0D, 0xD0, 0x71, 0x49, 0xA0, 0xB2,
+ 0x0A, 0x7A, 0xC9, 0x79, 0x01, 0xF0, 0x1F, 0xFA, 0x28, 0x68, 0xA0, 0x43, 0x28, 0x60, 0x03, 0xD1,
+ 0xBD, 0xE8, 0x70, 0x40, 0x01, 0xF0, 0x7C, 0xBA, 0x70, 0xBD, 0x6A, 0x48, 0x81, 0x7A, 0x01, 0x29,
+ 0x08, 0xD0, 0xC1, 0x7A, 0x01, 0x29, 0x05, 0xD0, 0x01, 0x7B, 0x01, 0x29, 0x02, 0xD0, 0x80, 0x7B,
+ 0x00, 0x28, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x08, 0xB5, 0xFF, 0xF7, 0x1F, 0xFF, 0x6B, 0x46,
+ 0x00, 0x22, 0x0B, 0x21, 0x02, 0x20, 0x05, 0xF0, 0x07, 0xFB, 0x00, 0x98, 0xC0, 0x07, 0x05, 0xD0,
+ 0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0xE3, 0xFA, 0x00, 0xF0, 0x56, 0xF8, 0x00, 0x98, 0x80, 0x07,
+ 0x05, 0xD5, 0x02, 0x21, 0x08, 0x46, 0x05, 0xF0, 0xDA, 0xFA, 0x00, 0xF0, 0x7E, 0xF8, 0x00, 0x98,
+ 0x00, 0x07, 0xE4, 0xD5, 0x08, 0x21, 0x02, 0x20, 0x05, 0xF0, 0xD1, 0xFA, 0xDF, 0xE7, 0x60, 0x48,
+ 0x10, 0xB5, 0x02, 0x68, 0x4F, 0x48, 0x92, 0xF8, 0x31, 0x10, 0x41, 0x70, 0x92, 0xF8, 0x30, 0x20,
+ 0x82, 0x70, 0x51, 0x43, 0x41, 0x82, 0x4E, 0x49, 0xC9, 0x78, 0xC1, 0x70, 0x01, 0x21, 0x01, 0x71,
+ 0x41, 0x71, 0x81, 0x71, 0x01, 0x70, 0x00, 0x21, 0x81, 0x82, 0xC1, 0x71, 0x01, 0x72, 0xC1, 0x73,
+ 0x01, 0x74, 0xFF, 0xF7, 0xA7, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0xFE, 0xF7, 0xD5, 0xBF, 0x43, 0x49,
+ 0x40, 0x48, 0x91, 0xF8, 0x30, 0x20, 0x42, 0x70, 0x91, 0xF8, 0x31, 0x30, 0x83, 0x70, 0x5A, 0x43,
+ 0x42, 0x82, 0x91, 0xF8, 0x33, 0x20, 0xC2, 0x70, 0x11, 0xF8, 0x2C, 0x2F, 0x02, 0x70, 0x4A, 0x78,
+ 0x02, 0x71, 0x8A, 0x78, 0x42, 0x71, 0xCA, 0x78, 0x82, 0x71, 0x4A, 0x7A, 0xC2, 0x71, 0x89, 0x7A,
+ 0x01, 0x72, 0x45, 0x49, 0x41, 0x62, 0x01, 0xF2, 0x3C, 0x61, 0x81, 0x62, 0xA1, 0xF6, 0x78, 0x41,
+ 0xC1, 0x62, 0x42, 0x49, 0x01, 0x63, 0x70, 0x47, 0x38, 0xB5, 0x00, 0x24, 0x01, 0xF0, 0x10, 0xF8,
+ 0x01, 0x20, 0x05, 0xF0, 0xF8, 0xFA, 0xFF, 0xF7, 0x48, 0xFF, 0x2A, 0x4D, 0x95, 0xF8, 0x20, 0x00,
+ 0xC0, 0x07, 0x08, 0xD0, 0x29, 0x48, 0xC1, 0x68, 0x00, 0x91, 0xD0, 0xE9, 0x04, 0x23, 0x03, 0xC8,
+ 0xFF, 0xF7, 0x1B, 0xFA, 0x04, 0x46, 0xE8, 0x69, 0x50, 0xB1, 0x4C, 0xB9, 0x03, 0x20, 0x05, 0xF0,
+ 0xE2, 0xFA, 0x22, 0x48, 0xE9, 0x69, 0xFE, 0xF7, 0xF6, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0xF6, 0xFA,
+ 0xFF, 0xF7, 0xA8, 0xFE, 0xFF, 0xF7, 0x4D, 0xFF, 0xFF, 0xF7, 0xE1, 0xFB, 0xFF, 0xF7, 0x35, 0xFB,
+ 0xBD, 0xE8, 0x38, 0x40, 0x01, 0x20, 0x05, 0xF0, 0xE9, 0xBA, 0x70, 0xB5, 0x00, 0x24, 0x00, 0xF0,
+ 0xDF, 0xFF, 0x01, 0x20, 0x05, 0xF0, 0xC7, 0xFA, 0xFF, 0xF7, 0x17, 0xFF, 0x11, 0x4D, 0x95, 0xF8,
+ 0x20, 0x00, 0xC0, 0x07, 0x04, 0xD0, 0x11, 0x48, 0x00, 0x68, 0xFF, 0xF7, 0x31, 0xFA, 0x04, 0x46,
+ 0xE8, 0x69, 0x50, 0xB1, 0x4C, 0xB9, 0x03, 0x20, 0x05, 0xF0, 0xB5, 0xFA, 0x0B, 0x48, 0xE9, 0x69,
+ 0xFE, 0xF7, 0xC9, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0xC9, 0xFA, 0xFF, 0xF7, 0x7B, 0xFE, 0xFF, 0xF7,
+ 0x20, 0xFF, 0xFF, 0xF7, 0xB4, 0xFB, 0xFF, 0xF7, 0x08, 0xFB, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20,
+ 0x05, 0xF0, 0xBC, 0xBA, 0xB8, 0x06, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x7C, 0x6C, 0x10, 0x00,
+ 0x4C, 0x07, 0x10, 0x00, 0x51, 0x06, 0x10, 0x00, 0x56, 0x06, 0x10, 0x00, 0x80, 0x06, 0x10, 0x00,
+ 0x52, 0x07, 0x10, 0x00, 0x54, 0x07, 0x10, 0x00, 0x56, 0x07, 0x10, 0x00, 0x0E, 0x05, 0x10, 0x00,
+ 0x0C, 0x05, 0x10, 0x00, 0x1C, 0x05, 0x10, 0x00, 0x21, 0x05, 0x10, 0x00, 0xB0, 0x06, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x40, 0x07, 0x10, 0x00, 0xC8, 0x35, 0x01, 0x20, 0x2E, 0x44, 0x01, 0x20,
+ 0x0D, 0x4D, 0x00, 0x20, 0x0D, 0x4C, 0x28, 0x60, 0x28, 0x68, 0x40, 0x1C, 0x28, 0x60, 0xF1, 0xF7,
+ 0x55, 0xF8, 0x07, 0xF0, 0x20, 0xF9, 0x01, 0x28, 0x20, 0x68, 0x09, 0xD0, 0x40, 0xF0, 0x04, 0x00,
+ 0x20, 0x60, 0x05, 0xF0, 0x6C, 0xFF, 0x00, 0xBF, 0xF1, 0xF7, 0x46, 0xF8, 0x30, 0xBF, 0xEB, 0xE7,
+ 0x20, 0xF0, 0x04, 0x00, 0x20, 0x60, 0xF7, 0xE7, 0xFC, 0x06, 0x10, 0x00, 0x10, 0xED, 0x00, 0xE0,
+ 0x2D, 0xE9, 0xF0, 0x47, 0x1C, 0x4D, 0xDF, 0xF8, 0x74, 0x90, 0xA8, 0x46, 0x20, 0x21, 0x1A, 0x48,
+ 0x07, 0xF0, 0xBF, 0xFA, 0x18, 0x48, 0x00, 0xF0, 0xE9, 0xFB, 0x47, 0x1E, 0xD9, 0xF8, 0x00, 0x00,
+ 0x98, 0xF8, 0x00, 0x60, 0x08, 0xF1, 0x01, 0x04, 0x90, 0xF8, 0xA0, 0x00, 0xC0, 0x07, 0x05, 0xD0,
+ 0x3A, 0x46, 0x21, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x23, 0xF8, 0x28, 0xB9, 0x3A, 0x46, 0x21, 0x46,
+ 0x30, 0x46, 0x00, 0xF0, 0xEB, 0xF8, 0x18, 0xB1, 0x01, 0x20, 0x29, 0x68, 0x01, 0xF0, 0x9A, 0xFA,
+ 0x00, 0xF0, 0xE6, 0xFB, 0x00, 0x28, 0xD9, 0xD1, 0xBD, 0xE8, 0xF0, 0x87, 0x38, 0xB5, 0x0C, 0x46,
+ 0x05, 0x46, 0x05, 0xF0, 0x88, 0xF9, 0x69, 0x46, 0x28, 0x46, 0x05, 0xF0, 0xBE, 0xF9, 0x00, 0x99,
+ 0x21, 0x42, 0xF8, 0xD1, 0x38, 0xBD, 0x00, 0x00, 0xBC, 0x47, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x70, 0xB5, 0x0D, 0x46, 0xA0, 0xF1, 0x10, 0x01, 0x03, 0x29, 0x01, 0xD8, 0x5C, 0x48, 0x05, 0xE0,
+ 0xA0, 0xF1, 0x30, 0x01, 0x0A, 0x29, 0x06, 0xD8, 0x59, 0x48, 0x20, 0x30, 0x50, 0xF8, 0x31, 0x30,
+ 0x00, 0xEB, 0xC1, 0x00, 0x0D, 0xE0, 0x62, 0x28, 0x02, 0xD0, 0x4F, 0xF0, 0x00, 0x04, 0x10, 0xE0,
+ 0x53, 0x49, 0xA0, 0xF1, 0x62, 0x00, 0xA1, 0xF1, 0x08, 0x01, 0x51, 0xF8, 0x30, 0x30, 0x01, 0xEB,
+ 0xC0, 0x00, 0x4F, 0xF0, 0x01, 0x04, 0x40, 0x68, 0x90, 0x42, 0x02, 0xD1, 0x11, 0x46, 0x28, 0x46,
+ 0x98, 0x47, 0x20, 0x46, 0x70, 0xBD, 0x4B, 0x49, 0x01, 0x20, 0x08, 0x60, 0x04, 0x21, 0xFF, 0xF7,
+ 0xBD, 0xBF, 0x48, 0x49, 0x00, 0x20, 0x08, 0x60, 0x04, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xB6, 0xBF,
+ 0x05, 0xF0, 0xA1, 0xBE, 0x10, 0xB5, 0xF0, 0xF7, 0xC1, 0xFF, 0x43, 0x49, 0x0E, 0x20, 0x08, 0x60,
+ 0xF0, 0xF7, 0xBA, 0xFF, 0x02, 0x21, 0x05, 0x20, 0x01, 0xF0, 0x3C, 0xFA, 0xBD, 0xE8, 0x10, 0x40,
+ 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0xFF, 0xF7, 0xA1, 0xBF, 0x3C, 0x49, 0x02, 0x78, 0x0A, 0x70,
+ 0x42, 0x78, 0x4A, 0x70, 0x01, 0x78, 0x4B, 0x07, 0x39, 0x49, 0x0A, 0x68, 0x02, 0xD5, 0x42, 0xF0,
+ 0x04, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0x02, 0x78, 0x12, 0x07, 0x0A, 0x68,
+ 0x02, 0xD5, 0x42, 0xF0, 0x02, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x02, 0x02, 0x0A, 0x60, 0x02, 0x78,
+ 0xD2, 0x06, 0x0A, 0x68, 0x02, 0xD5, 0x42, 0xF0, 0x01, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x01, 0x02,
+ 0x0A, 0x60, 0x00, 0x78, 0x40, 0x06, 0x02, 0xD5, 0x42, 0xF0, 0x10, 0x00, 0x01, 0xE0, 0x22, 0xF0,
+ 0x10, 0x00, 0x08, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x70, 0xBF, 0x00, 0x78, 0x28, 0xB1,
+ 0x01, 0x28, 0x05, 0xD1, 0x10, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x68, 0xBF, 0x04, 0x21, 0xFA, 0xE7,
+ 0x70, 0x47, 0x02, 0x78, 0x1E, 0x48, 0x01, 0x68, 0x22, 0xB1, 0x01, 0x2A, 0x05, 0xD0, 0x02, 0x2A,
+ 0x08, 0xD1, 0x0B, 0xE0, 0x21, 0xF0, 0x08, 0x01, 0x01, 0xE0, 0x41, 0xF0, 0x08, 0x01, 0x21, 0xF0,
+ 0x40, 0x01, 0x01, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x50, 0xBF, 0x21, 0xF0, 0x08, 0x01,
+ 0x41, 0xF0, 0x40, 0x01, 0xF5, 0xE7, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47,
+ 0x70, 0x47, 0x00, 0x21, 0x00, 0x78, 0x0A, 0x46, 0x83, 0x07, 0x01, 0xD5, 0x20, 0x21, 0x00, 0x22,
+ 0xC0, 0x07, 0x01, 0xD0, 0x41, 0xF0, 0x02, 0x01, 0x0A, 0x48, 0xC0, 0xE9, 0x00, 0x12, 0x0A, 0x4A,
+ 0x00, 0x20, 0xC2, 0xE9, 0x00, 0x00, 0x70, 0x47, 0x70, 0x47, 0x00, 0xF0, 0xBF, 0xBC, 0x00, 0x00,
+ 0x74, 0x6C, 0x01, 0x00, 0x44, 0x07, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0xDC, 0x48, 0x10, 0x00,
+ 0x48, 0x07, 0x10, 0x00, 0x48, 0x05, 0x10, 0x00, 0x50, 0x05, 0x10, 0x00, 0x0B, 0x46, 0x10, 0xB5,
+ 0x00, 0x21, 0xA0, 0x38, 0x09, 0x28, 0x06, 0xD8, 0xFE, 0x49, 0x51, 0xF8, 0x20, 0x40, 0x11, 0x46,
+ 0x18, 0x46, 0xA0, 0x47, 0x01, 0x46, 0x08, 0x46, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, 0x70, 0xB5,
+ 0x00, 0x23, 0x00, 0x29, 0x11, 0xDD, 0x02, 0x78, 0x49, 0x1E, 0x03, 0x2A, 0x0D, 0xD2, 0xF5, 0x4D,
+ 0x40, 0x1C, 0x28, 0x35, 0x55, 0xF8, 0x32, 0x40, 0x05, 0xEB, 0xC2, 0x02, 0x52, 0x68, 0x00, 0x2A,
+ 0x03, 0xDB, 0x91, 0x42, 0x01, 0xD1, 0xA0, 0x47, 0x03, 0x46, 0x18, 0x46, 0x70, 0xBD, 0x10, 0xB5,
+ 0x00, 0x78, 0x00, 0x21, 0xC0, 0x07, 0x00, 0xD0, 0x01, 0x21, 0xEB, 0x48, 0x02, 0x68, 0x8A, 0x42,
+ 0x04, 0xD0, 0x01, 0x60, 0x04, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xE8, 0xFE, 0x01, 0x20, 0x10, 0xBD,
+ 0x10, 0xB5, 0x10, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xE1, 0xFE, 0xE3, 0x49, 0x00, 0x20, 0x08, 0x60,
+ 0x01, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x00, 0x23, 0x00, 0x29, 0x0F, 0xDD, 0x02, 0x78, 0x49, 0x1E,
+ 0x05, 0x2A, 0x0B, 0xD2, 0xDB, 0x4D, 0x40, 0x1C, 0x40, 0x35, 0x55, 0xF8, 0x32, 0x40, 0x05, 0xEB,
+ 0xC2, 0x02, 0x52, 0x68, 0x91, 0x42, 0x01, 0xD1, 0xA0, 0x47, 0x03, 0x46, 0x18, 0x46, 0x70, 0xBD,
+ 0x10, 0xB5, 0x00, 0x78, 0xC2, 0x07, 0xD5, 0x48, 0x01, 0x68, 0x02, 0xD0, 0x41, 0xF0, 0x02, 0x01,
+ 0x01, 0xE0, 0x21, 0xF0, 0x02, 0x01, 0x01, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xB6, 0xFE,
+ 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0xC2, 0x07, 0xCC, 0x48, 0x01, 0x68, 0x02, 0xD0,
+ 0x41, 0xF0, 0x04, 0x01, 0x01, 0xE0, 0x21, 0xF0, 0x04, 0x01, 0x01, 0x60, 0x08, 0x21, 0x01, 0x20,
+ 0xFF, 0xF7, 0xA4, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x01, 0x78, 0xCB, 0x07, 0xC3, 0x49,
+ 0x0A, 0x68, 0x02, 0xD0, 0x42, 0xF0, 0x08, 0x02, 0x01, 0xE0, 0x22, 0xF0, 0x08, 0x02, 0x0A, 0x60,
+ 0x00, 0x78, 0x80, 0x07, 0x02, 0xD5, 0x42, 0xF0, 0x40, 0x00, 0x01, 0xE0, 0x22, 0xF0, 0x40, 0x00,
+ 0x08, 0x60, 0x08, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0x89, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5,
+ 0x00, 0x21, 0x03, 0x78, 0x0A, 0x46, 0x9C, 0x07, 0x01, 0xD5, 0x20, 0x21, 0x00, 0x22, 0x5C, 0x07,
+ 0x01, 0xD5, 0x41, 0xF0, 0x02, 0x01, 0x1C, 0x07, 0x01, 0xD5, 0x41, 0xF0, 0x04, 0x01, 0xDC, 0x06,
+ 0x01, 0xD5, 0x41, 0xF0, 0x08, 0x01, 0x9B, 0x06, 0x01, 0xD5, 0x41, 0xF0, 0x10, 0x01, 0x43, 0x78,
+ 0x5C, 0x07, 0x01, 0xD5, 0x41, 0xF0, 0x40, 0x01, 0x1C, 0x07, 0x01, 0xD5, 0x41, 0xF0, 0x80, 0x01,
+ 0xDC, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x71, 0x9C, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x00, 0x71,
+ 0x5C, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x61, 0x1B, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x00, 0x61,
+ 0x80, 0x78, 0xC3, 0x07, 0x01, 0xD0, 0x41, 0xF4, 0x80, 0x51, 0x83, 0x07, 0x01, 0xD5, 0x41, 0xF4,
+ 0x00, 0x51, 0x43, 0x07, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x41, 0x03, 0x07, 0x01, 0xD5, 0x41, 0xF4,
+ 0x00, 0x41, 0xC3, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x31, 0x83, 0x06, 0x01, 0xD5, 0x41, 0xF4,
+ 0x00, 0x31, 0x43, 0x06, 0x01, 0xD5, 0x41, 0xF4, 0x80, 0x21, 0x00, 0x06, 0x01, 0xD5, 0x41, 0xF4,
+ 0x00, 0x21, 0x8F, 0x48, 0xC0, 0xE9, 0x00, 0x12, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47,
+ 0x70, 0xB5, 0x00, 0x23, 0x00, 0x29, 0x0F, 0xDD, 0x02, 0x78, 0x49, 0x1E, 0x0B, 0x2A, 0x0B, 0xD2,
+ 0x84, 0x4D, 0x40, 0x1C, 0x68, 0x35, 0x55, 0xF8, 0x32, 0x40, 0x05, 0xEB, 0xC2, 0x02, 0x52, 0x68,
+ 0x91, 0x42, 0x01, 0xD1, 0xA0, 0x47, 0x03, 0x46, 0x18, 0x46, 0x70, 0xBD, 0x01, 0x46, 0x00, 0x20,
+ 0x09, 0x78, 0x05, 0x29, 0x06, 0xD2, 0x7B, 0x48, 0xC0, 0x30, 0x50, 0xF8, 0x21, 0x20, 0x00, 0x21,
+ 0x08, 0x46, 0x10, 0x47, 0x70, 0x47, 0x10, 0xB5, 0x05, 0xF0, 0xF5, 0xFC, 0x01, 0x20, 0x10, 0xBD,
+ 0x10, 0xB5, 0x00, 0xF0, 0x93, 0xFB, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x61,
+ 0x00, 0x20, 0xFF, 0xF7, 0xFB, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x80, 0x51,
+ 0x00, 0x20, 0xFF, 0xF7, 0xF3, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x01,
+ 0x00, 0x20, 0xFF, 0xF7, 0xEB, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0xC0, 0x07,
+ 0x02, 0xD0, 0x00, 0xF0, 0x02, 0xFB, 0x01, 0xE0, 0x00, 0xF0, 0xF6, 0xFA, 0x01, 0x20, 0x10, 0xBD,
+ 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, 0x02, 0x24, 0x81, 0x07, 0x01, 0xD5,
+ 0x44, 0xF0, 0x04, 0x04, 0x40, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x08, 0x04, 0x94, 0xB1, 0xF0, 0xF7,
+ 0xDD, 0xFD, 0x5C, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, 0xD5, 0xFD, 0x02, 0x21,
+ 0x05, 0x20, 0x01, 0xF0, 0x57, 0xF8, 0x4F, 0xF4, 0x80, 0x71, 0x00, 0x20, 0xFF, 0xF7, 0xBE, 0xFD,
+ 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07,
+ 0x00, 0xD0, 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x41, 0x07, 0x01, 0xD5,
+ 0x44, 0xF0, 0x04, 0x04, 0x00, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x08, 0x04, 0x6C, 0xB1, 0xF0, 0xF7,
+ 0xB5, 0xFD, 0x49, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, 0xAD, 0xFD, 0x02, 0x21,
+ 0x00, 0x20, 0xFF, 0xF7, 0x9B, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5,
+ 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0,
+ 0x02, 0x04, 0x41, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x04, 0x04, 0x00, 0x07, 0x01, 0xD5, 0x44, 0xF0,
+ 0x08, 0x04, 0x74, 0xB1, 0xF0, 0xF7, 0x92, 0xFD, 0x38, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60,
+ 0xF0, 0xF7, 0x8A, 0xFD, 0x4F, 0xF4, 0x00, 0x11, 0x00, 0x20, 0xFF, 0xF7, 0x77, 0xFD, 0x01, 0x20,
+ 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0,
+ 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x41, 0x07, 0x01, 0xD5, 0x44, 0xF0,
+ 0x04, 0x04, 0x01, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x08, 0x04, 0xC1, 0x06, 0x01, 0xD5, 0x44, 0xF0,
+ 0x10, 0x04, 0x81, 0x06, 0x01, 0xD5, 0x44, 0xF0, 0x20, 0x04, 0x41, 0x06, 0x01, 0xD5, 0x44, 0xF0,
+ 0x40, 0x04, 0x01, 0x06, 0x01, 0xD5, 0x44, 0xF0, 0x80, 0x04, 0xC1, 0x05, 0x01, 0xD5, 0x44, 0xF4,
+ 0x80, 0x74, 0x81, 0x05, 0x01, 0xD5, 0x44, 0xF4, 0x00, 0x74, 0x40, 0x05, 0x01, 0xD5, 0x44, 0xF4,
+ 0x80, 0x64, 0x6C, 0xB1, 0xF0, 0xF7, 0x52, 0xFD, 0x19, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60,
+ 0xF0, 0xF7, 0x4A, 0xFD, 0x80, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0x38, 0xFD, 0x01, 0x20, 0x10, 0xBD,
+ 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x88, 0x00, 0x24, 0xC1, 0x07, 0x00, 0xD0, 0x01, 0x24,
+ 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x40, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x04, 0x04,
+ 0x0C, 0xB3, 0xF0, 0xF7, 0x33, 0xFD, 0x0B, 0x48, 0x01, 0x68, 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7,
+ 0x2B, 0xFD, 0x11, 0xE0, 0xEC, 0x6C, 0x01, 0x00, 0x44, 0x07, 0x10, 0x00, 0x48, 0x07, 0x10, 0x00,
+ 0x48, 0x05, 0x10, 0x00, 0x28, 0x07, 0x10, 0x00, 0x2C, 0x07, 0x10, 0x00, 0x30, 0x07, 0x10, 0x00,
+ 0x38, 0x07, 0x10, 0x00, 0x3C, 0x07, 0x10, 0x00, 0x4F, 0xF4, 0x80, 0x01, 0x00, 0x20, 0xFF, 0xF7,
+ 0x05, 0xFD, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0x00, 0x24,
+ 0xC1, 0x07, 0x00, 0xD0, 0x01, 0x24, 0x81, 0x07, 0x01, 0xD5, 0x44, 0xF0, 0x02, 0x04, 0x40, 0x07,
+ 0x01, 0xD5, 0x44, 0xF0, 0x04, 0x04, 0x74, 0xB1, 0xF0, 0xF7, 0x00, 0xFD, 0x2B, 0x48, 0x01, 0x68,
+ 0x21, 0x43, 0x01, 0x60, 0xF0, 0xF7, 0xF8, 0xFC, 0x4F, 0xF4, 0x80, 0x61, 0x00, 0x20, 0xFF, 0xF7,
+ 0xE5, 0xFC, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x78, 0x00, 0x24,
+ 0x51, 0x28, 0x3D, 0xD0, 0x18, 0xDC, 0x30, 0x28, 0x36, 0xD0, 0x0C, 0xDC, 0x11, 0x28, 0x2F, 0xD0,
+ 0x04, 0xDC, 0x01, 0x28, 0x29, 0xD0, 0x10, 0x28, 0x30, 0xD1, 0x29, 0xE0, 0x12, 0x28, 0x27, 0xD0,
+ 0x13, 0x28, 0x2B, 0xD1, 0x24, 0xE0, 0x31, 0x28, 0x26, 0xD0, 0x32, 0x28, 0x24, 0xD0, 0x33, 0x28,
+ 0x22, 0xD0, 0x50, 0x28, 0x22, 0xD1, 0x23, 0xE0, 0x73, 0x28, 0x24, 0xD0, 0x0C, 0xDC, 0x70, 0x28,
+ 0x21, 0xD0, 0x04, 0xDC, 0x52, 0x28, 0x1B, 0xD0, 0x53, 0x28, 0x17, 0xD1, 0x18, 0xE0, 0x71, 0x28,
+ 0x19, 0xD0, 0x72, 0x28, 0x12, 0xD1, 0x16, 0xE0, 0x74, 0x28, 0x14, 0xD0, 0x75, 0x28, 0x12, 0xD0,
+ 0x76, 0x28, 0x10, 0xD0, 0x77, 0x28, 0x09, 0xD1, 0x0D, 0xE0, 0x00, 0xF0, 0x90, 0xFC, 0x01, 0xE0,
+ 0x00, 0xF0, 0x25, 0xFD, 0x01, 0x24, 0x01, 0xE0, 0x00, 0xF0, 0x41, 0xFD, 0x20, 0x46, 0x10, 0xBD,
+ 0x00, 0xF0, 0x2B, 0xFD, 0xF6, 0xE7, 0x00, 0xF0, 0x0B, 0xFE, 0xF3, 0xE7, 0x34, 0x07, 0x10, 0x00,
+ 0x1B, 0x49, 0x08, 0xB5, 0x1B, 0x4C, 0x00, 0x20, 0x08, 0x60, 0x20, 0x60, 0x00, 0xF0, 0x77, 0xFC,
+ 0x00, 0xF0, 0x02, 0xFF, 0x6B, 0x46, 0x00, 0x22, 0x19, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x5C, 0xFE,
+ 0x00, 0x98, 0xC0, 0x07, 0x05, 0xD0, 0x01, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x38, 0xFE, 0xFF, 0xF7,
+ 0x4F, 0xFC, 0x00, 0x98, 0x00, 0x07, 0x0B, 0xD5, 0x08, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x2F, 0xFE,
+ 0x20, 0x68, 0x08, 0x21, 0x40, 0xF0, 0x08, 0x00, 0x20, 0x60, 0x01, 0x20, 0xFF, 0xF7, 0x6E, 0xFC,
+ 0x00, 0x98, 0xC0, 0x06, 0xDE, 0xD5, 0x10, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x20, 0xFE, 0x20, 0x68,
+ 0x08, 0x21, 0x20, 0xF0, 0x08, 0x00, 0x20, 0x60, 0x01, 0x20, 0xFF, 0xF7, 0x5F, 0xFC, 0xD1, 0xE7,
+ 0x44, 0x07, 0x10, 0x00, 0x48, 0x07, 0x10, 0x00, 0x1F, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x70,
+ 0x81, 0x70, 0x70, 0x47, 0x10, 0xB5, 0x1C, 0x4C, 0x03, 0x46, 0xA0, 0x78, 0x10, 0x28, 0x14, 0xD2,
+ 0x0F, 0x29, 0x00, 0xD9, 0x0F, 0x21, 0x19, 0x48, 0x22, 0x78, 0x00, 0xEB, 0x02, 0x10, 0x0A, 0x46,
+ 0x00, 0xF8, 0x01, 0x1B, 0x19, 0x46, 0x06, 0xF0, 0x5D, 0xFE, 0x20, 0x78, 0x40, 0x1C, 0x00, 0xF0,
+ 0x0F, 0x00, 0x20, 0x70, 0xA0, 0x78, 0x40, 0x1C, 0xA0, 0x70, 0x10, 0xBD, 0x70, 0xB5, 0x0E, 0x4C,
+ 0x00, 0x25, 0xA1, 0x78, 0x91, 0xB1, 0x0D, 0x49, 0x62, 0x78, 0x01, 0xEB, 0x02, 0x11, 0x11, 0xF8,
+ 0x01, 0x5B, 0x2A, 0x46, 0x06, 0xF0, 0x46, 0xFE, 0x60, 0x78, 0x40, 0x1C, 0x00, 0xF0, 0x0F, 0x00,
+ 0x60, 0x70, 0x72, 0xB6, 0xA0, 0x78, 0x40, 0x1E, 0xA0, 0x70, 0x62, 0xB6, 0x28, 0x46, 0x70, 0xBD,
+ 0x01, 0x48, 0x80, 0x78, 0x70, 0x47, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0xDC, 0x47, 0x10, 0x00,
+ 0x70, 0xB5, 0x14, 0x46, 0x00, 0x20, 0x06, 0xF0, 0x51, 0xFF, 0x00, 0xF0, 0x01, 0x05, 0x01, 0x20,
+ 0x06, 0xF0, 0x4C, 0xFF, 0x00, 0xF0, 0x01, 0x00, 0x45, 0xEA, 0x00, 0x10, 0x20, 0x70, 0x01, 0x20,
+ 0x70, 0xBD, 0x80, 0x20, 0x10, 0x70, 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x14, 0x46, 0x05, 0xF0,
+ 0xCE, 0xFA, 0x53, 0x21, 0x21, 0x70, 0x54, 0x21, 0x61, 0x70, 0x01, 0x0A, 0xA1, 0x70, 0xE0, 0x70,
+ 0x05, 0xF0, 0xC9, 0xFA, 0x20, 0x71, 0x05, 0x20, 0x10, 0xBD, 0x38, 0xB5, 0x14, 0x46, 0x74, 0x4A,
+ 0x13, 0x68, 0x59, 0x8E, 0x98, 0x8E, 0x93, 0xF8, 0x36, 0x30, 0xDB, 0x07, 0x0A, 0xD0, 0x03, 0x0A,
+ 0x23, 0x70, 0x60, 0x70, 0x0D, 0x0A, 0xA5, 0x70, 0xE1, 0x70, 0x23, 0x71, 0x60, 0x71, 0xA5, 0x71,
+ 0xE1, 0x71, 0x09, 0xE0, 0x0B, 0x0A, 0x23, 0x70, 0x61, 0x70, 0x05, 0x0A, 0xA5, 0x70, 0xE0, 0x70,
+ 0x23, 0x71, 0x61, 0x71, 0xA5, 0x71, 0xE0, 0x71, 0x10, 0x68, 0x90, 0xF8, 0x31, 0x10, 0x21, 0x72,
+ 0x10, 0xF8, 0x30, 0x1F, 0x61, 0x72, 0x90, 0xF8, 0x31, 0x04, 0x8D, 0xF8, 0x00, 0x00, 0x01, 0x21,
+ 0x68, 0x46, 0x05, 0xF0, 0x1F, 0xFB, 0xA0, 0x72, 0x0B, 0x20, 0x38, 0xBD, 0x00, 0x20, 0x10, 0x70,
+ 0x10, 0x20, 0x50, 0x70, 0x5A, 0x48, 0x01, 0x68, 0x49, 0x8A, 0x09, 0x0A, 0x91, 0x70, 0x01, 0x68,
+ 0x89, 0x7C, 0xD1, 0x70, 0x00, 0x68, 0x01, 0x7E, 0x11, 0x71, 0x40, 0x7E, 0x50, 0x71, 0x06, 0x20,
+ 0x70, 0x47, 0x08, 0xB5, 0x02, 0x23, 0x00, 0x93, 0x52, 0x4B, 0x00, 0xF0, 0x8D, 0xF8, 0x02, 0x20,
+ 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x4E, 0x4B, 0x9B, 0x1C, 0x00, 0xF0, 0x84, 0xF8,
+ 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x4A, 0x4B, 0xDB, 0x1C, 0x00, 0xF0,
+ 0x7B, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x45, 0x4B, 0x1B, 0x1D,
+ 0x00, 0xF0, 0x72, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x41, 0x4B,
+ 0x5B, 0x1D, 0x00, 0xF0, 0x69, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93,
+ 0x3C, 0x4B, 0x9B, 0x1D, 0x00, 0xF0, 0x60, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x02, 0x23,
+ 0x00, 0x93, 0x38, 0x4B, 0xDB, 0x1D, 0x00, 0xF0, 0x57, 0xF8, 0x02, 0x20, 0x08, 0xBD, 0x08, 0xB5,
+ 0x02, 0x23, 0x00, 0x93, 0x33, 0x4B, 0x09, 0x33, 0x00, 0xF0, 0x4E, 0xF8, 0x02, 0x20, 0x08, 0xBD,
+ 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x2F, 0x4B, 0x0B, 0x33, 0x00, 0xF0, 0x45, 0xF8, 0x01, 0x20,
+ 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x2A, 0x4B, 0x0C, 0x33, 0x00, 0xF0, 0x3C, 0xF8,
+ 0x01, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x01, 0x23, 0x00, 0x93, 0x26, 0x4B, 0x0D, 0x33, 0x00, 0xF0,
+ 0x33, 0xF8, 0x01, 0x20, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x46, 0x04, 0x46, 0x00, 0x78,
+ 0x49, 0x1E, 0xCE, 0xB2, 0x00, 0x25, 0x63, 0x1C, 0xA0, 0xF1, 0x20, 0x01, 0x04, 0x29, 0x09, 0xD8,
+ 0x1D, 0x49, 0x01, 0xEB, 0x80, 0x00, 0x31, 0x46, 0x50, 0xF8, 0x80, 0x4C, 0x18, 0x46, 0xA0, 0x47,
+ 0x05, 0x46, 0x16, 0xE0, 0xA0, 0xF1, 0x30, 0x01, 0x0B, 0x29, 0x12, 0xD8, 0x16, 0x49, 0x14, 0x31,
+ 0x01, 0xEB, 0x80, 0x00, 0x31, 0x46, 0x50, 0xF8, 0xC0, 0x5C, 0x18, 0x46, 0xA8, 0x47, 0x05, 0x46,
+ 0x3E, 0xB1, 0x39, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xCD, 0xFE, 0x01, 0x21, 0x03, 0x20, 0x04, 0xF0,
+ 0xAA, 0xFC, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x70, 0xB5, 0x1D, 0x46, 0x04, 0x9C, 0x16, 0x46,
+ 0x39, 0xB1, 0xA1, 0x42, 0x00, 0xD9, 0x21, 0x46, 0x0A, 0x46, 0x01, 0x46, 0x18, 0x46, 0x06, 0xF0,
+ 0x29, 0xFD, 0x22, 0x46, 0x29, 0x46, 0x30, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x06, 0xF0, 0x22, 0xBD,
+ 0x20, 0x07, 0x10, 0x00, 0xDC, 0x48, 0x10, 0x00, 0xC0, 0x6D, 0x01, 0x00, 0x10, 0xB5, 0x4F, 0xF4,
+ 0x86, 0x71, 0x4F, 0x48, 0x06, 0xF0, 0xB7, 0xFD, 0x4D, 0x49, 0x01, 0x20, 0xC1, 0xF8, 0x04, 0x01,
+ 0x4C, 0x48, 0x00, 0x21, 0x41, 0x60, 0x01, 0x70, 0x06, 0xF0, 0x3E, 0xFE, 0x00, 0x21, 0xBD, 0xE8,
+ 0x10, 0x40, 0x01, 0x20, 0x05, 0xF0, 0x5B, 0xBD, 0x10, 0xB5, 0x72, 0xB6, 0x00, 0x20, 0x45, 0x49,
+ 0x08, 0x70, 0x06, 0xF0, 0x31, 0xFE, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xB5, 0x72, 0xB6, 0x01, 0x20,
+ 0x40, 0x49, 0x08, 0x70, 0x3E, 0x48, 0xD0, 0xF8, 0x08, 0x01, 0x08, 0xB1, 0x06, 0xF0, 0xC8, 0xFD,
+ 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xB5, 0x72, 0xB6, 0x39, 0x49, 0x3A, 0x4B, 0x0A, 0x46, 0xD1, 0xF8,
+ 0x08, 0x41, 0xD2, 0xF8, 0x00, 0x21, 0x52, 0x1C, 0x20, 0x2C, 0x07, 0xD2, 0x64, 0x1C, 0x22, 0xF0,
+ 0x20, 0x02, 0xC1, 0xF8, 0x08, 0x41, 0xC1, 0xF8, 0x00, 0x21, 0x0F, 0xE0, 0xD1, 0xF8, 0x04, 0x41,
+ 0x22, 0xF0, 0x20, 0x02, 0x64, 0x1C, 0xC1, 0xF8, 0x00, 0x21, 0x24, 0xF0, 0x20, 0x02, 0xC1, 0xF8,
+ 0x04, 0x21, 0x5A, 0x68, 0x52, 0x1C, 0x5A, 0x60, 0xD1, 0xF8, 0x00, 0x21, 0x04, 0x68, 0x01, 0xEB,
+ 0xC2, 0x02, 0x14, 0x60, 0x40, 0x68, 0x50, 0x60, 0x18, 0x78, 0x01, 0x28, 0x05, 0xD1, 0xD1, 0xF8,
+ 0x08, 0x01, 0x01, 0x28, 0x01, 0xD1, 0x06, 0xF0, 0x93, 0xFD, 0x62, 0xB6, 0x10, 0xBD, 0x20, 0x4A,
+ 0xD2, 0xF8, 0x08, 0x01, 0x00, 0x28, 0x0E, 0xD0, 0xD2, 0xF8, 0x04, 0x01, 0x02, 0xEB, 0xC0, 0x00,
+ 0xC3, 0x79, 0x23, 0xF0, 0x3F, 0x03, 0xC3, 0x71, 0x92, 0xF8, 0x08, 0x21, 0x52, 0x1E, 0x02, 0xF0,
+ 0x3F, 0x02, 0x13, 0x43, 0xC3, 0x71, 0x70, 0x47, 0x10, 0xB5, 0x72, 0xB6, 0x14, 0x48, 0xD0, 0xF8,
+ 0x08, 0x11, 0x59, 0xB1, 0x49, 0x1E, 0xC0, 0xF8, 0x08, 0x11, 0xD0, 0xF8, 0x04, 0x21, 0x02, 0xF1,
+ 0x01, 0x02, 0x22, 0xF0, 0x20, 0x02, 0xC0, 0xF8, 0x04, 0x21, 0x05, 0xD1, 0x0D, 0x48, 0x00, 0x78,
+ 0x01, 0x28, 0x01, 0xD1, 0x06, 0xF0, 0xC0, 0xFD, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xB5, 0x72, 0xB6,
+ 0x00, 0x20, 0x07, 0x49, 0x01, 0x22, 0xC1, 0xF8, 0x08, 0x01, 0xC1, 0xE9, 0x40, 0x02, 0x05, 0x49,
+ 0x48, 0x60, 0x08, 0x78, 0x01, 0x28, 0x01, 0xD1, 0x06, 0xF0, 0xAE, 0xFD, 0x62, 0xB6, 0x10, 0xBD,
+ 0x40, 0x42, 0x01, 0x20, 0x04, 0x07, 0x10, 0x00, 0x18, 0x49, 0x00, 0x22, 0x0A, 0x80, 0x4A, 0x80,
+ 0x4F, 0xF4, 0x70, 0x42, 0x8A, 0x80, 0x16, 0x4A, 0xCA, 0x80, 0x16, 0x4A, 0x0A, 0x81, 0x16, 0x4A,
+ 0xC0, 0xE9, 0x00, 0x21, 0x05, 0x21, 0x01, 0x72, 0x70, 0x47, 0x1C, 0xB5, 0x12, 0x49, 0xAD, 0xF8,
+ 0x04, 0x00, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x04, 0x20, 0x09, 0x1F, 0x8D, 0xF8, 0x07, 0x00,
+ 0x00, 0x91, 0x68, 0x46, 0x05, 0xF0, 0x59, 0xFE, 0x1C, 0xBD, 0x30, 0xB4, 0x03, 0x46, 0x0A, 0x4A,
+ 0x00, 0x20, 0x14, 0x78, 0x9C, 0x42, 0x02, 0xD1, 0x30, 0xBC, 0x05, 0xF0, 0x84, 0xBE, 0x40, 0x1C,
+ 0xC0, 0xB2, 0x52, 0x1D, 0x05, 0x28, 0xF4, 0xD3, 0x30, 0xBC, 0x70, 0x47, 0xEA, 0x48, 0x10, 0x00,
+ 0x4C, 0x62, 0x01, 0x20, 0xD0, 0x5E, 0x01, 0x20, 0x04, 0x6E, 0x01, 0x00, 0x10, 0xB5, 0x88, 0xB3,
+ 0xA3, 0x49, 0xA4, 0x4A, 0x09, 0x78, 0x37, 0x29, 0x71, 0xD0, 0x11, 0xDC, 0xA1, 0xF1, 0x20, 0x01,
+ 0x17, 0x29, 0x2C, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x2B, 0x2B, 0x2B,
+ 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x00,
+ 0x97, 0x4B, 0x70, 0x29, 0x5B, 0x78, 0x26, 0xD0, 0x0C, 0xDC, 0x3B, 0x29, 0x57, 0xD0, 0x04, 0xDC,
+ 0x38, 0x29, 0x54, 0xD0, 0x3A, 0x29, 0x12, 0xD1, 0x51, 0xE0, 0x60, 0x29, 0x19, 0xD0, 0x61, 0x29,
+ 0x0D, 0xD1, 0x16, 0xE0, 0x73, 0x29, 0x28, 0xD0, 0x05, 0xDC, 0x71, 0x29, 0x15, 0xD0, 0x72, 0x29,
+ 0x05, 0xD1, 0x14, 0xE0, 0x0B, 0xE0, 0x85, 0x29, 0x0B, 0xD0, 0x86, 0x29, 0x09, 0xD0, 0xC1, 0xB2,
+ 0x87, 0x48, 0xFF, 0xF7, 0x8F, 0xFD, 0x01, 0x21, 0x03, 0x20, 0x04, 0xF0, 0x6C, 0xFB, 0x00, 0x20,
+ 0x10, 0xBD, 0x02, 0x20, 0x10, 0xBD, 0x93, 0x70, 0xF9, 0xE7, 0xD3, 0x70, 0xF7, 0xE7, 0x90, 0x78,
+ 0x01, 0x28, 0x08, 0xD0, 0x00, 0x28, 0xF2, 0xD1, 0x7F, 0x48, 0x81, 0xB2, 0x5F, 0xF0, 0x72, 0x00,
+ 0xFF, 0xF7, 0x93, 0xFF, 0xEB, 0xE7, 0x7D, 0x48, 0xF7, 0xE7, 0xD0, 0x78, 0x01, 0x28, 0x05, 0xD0,
+ 0x00, 0x28, 0xE4, 0xD1, 0x7A, 0x48, 0x81, 0xB2, 0x73, 0x20, 0xF1, 0xE7, 0x79, 0x4C, 0x7A, 0x49,
+ 0x20, 0x68, 0x90, 0xF8, 0x31, 0x00, 0x42, 0x00, 0x71, 0x48, 0x10, 0x30, 0x06, 0xF0, 0xD2, 0xFB,
+ 0x20, 0x68, 0x10, 0xF8, 0x30, 0x1F, 0x4A, 0x00, 0x6D, 0x49, 0x40, 0x78, 0x10, 0x31, 0x01, 0xEB,
+ 0x40, 0x00, 0x72, 0x49, 0x06, 0xF0, 0xC6, 0xFB, 0x69, 0x48, 0x10, 0x30, 0xE3, 0xE7, 0xC1, 0xB2,
+ 0x52, 0x68, 0x67, 0x48, 0xFF, 0xF7, 0x57, 0xFE, 0x6D, 0x49, 0x08, 0x70, 0x01, 0x20, 0x10, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x5F, 0xDF, 0xF8, 0x88, 0xB1, 0x62, 0x4E, 0x62, 0x4D, 0x89, 0x46, 0x07, 0x46,
+ 0x4F, 0xF0, 0x01, 0x0A, 0xAB, 0xF1, 0x10, 0x0B, 0x08, 0x36, 0x28, 0x78, 0xA8, 0x46, 0x04, 0x46,
+ 0x07, 0x28, 0x76, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x04, 0x21, 0x25, 0x40, 0x5C, 0x78, 0x8A, 0x00,
+ 0x01, 0x2F, 0x02, 0xD0, 0x02, 0x2F, 0x0C, 0xD0, 0x6B, 0xE0, 0x48, 0x46, 0xFF, 0xF7, 0x5E, 0xFF,
+ 0x02, 0x28, 0x02, 0xD0, 0x01, 0x28, 0x02, 0xD0, 0x63, 0xE0, 0x03, 0x24, 0x61, 0xE0, 0x02, 0x24,
+ 0x5F, 0xE0, 0x68, 0x78, 0x01, 0x28, 0x04, 0xD0, 0x4D, 0x48, 0x10, 0x21, 0x10, 0x38, 0x06, 0xF0,
+ 0x08, 0xFC, 0x54, 0x46, 0x86, 0xF8, 0x00, 0xA0, 0x53, 0xE0, 0x02, 0x2F, 0x4F, 0xD0, 0x00, 0x24,
+ 0x39, 0xE0, 0x02, 0x2F, 0x1A, 0xD1, 0x4E, 0x4C, 0x45, 0x48, 0xD8, 0xF8, 0x04, 0x10, 0x22, 0x78,
+ 0x10, 0x38, 0x06, 0xF0, 0x77, 0xFB, 0x03, 0x20, 0x30, 0x70, 0x20, 0x78, 0xB0, 0x80, 0x98, 0xF8,
+ 0x00, 0x00, 0x04, 0x24, 0x88, 0xF8, 0x01, 0x00, 0x88, 0xF8, 0x00, 0x40, 0x27, 0xE0, 0x00, 0x24,
+ 0x88, 0xF8, 0x01, 0x00, 0x2C, 0x70, 0xB8, 0xE7, 0x02, 0x2F, 0x02, 0xD0, 0x01, 0x2F, 0xF6, 0xD0,
+ 0x2F, 0xE0, 0xFF, 0xF7, 0xA4, 0xFE, 0x08, 0x21, 0x28, 0xB1, 0x02, 0x22, 0x32, 0x70, 0x70, 0x80,
+ 0xB1, 0x80, 0x05, 0x24, 0x25, 0xE0, 0x68, 0x78, 0x06, 0x28, 0x04, 0xD0, 0x00, 0x22, 0xCB, 0xF8,
+ 0x00, 0x20, 0xCB, 0xF8, 0x04, 0x20, 0x03, 0x20, 0x30, 0x70, 0xB1, 0x80, 0x06, 0x24, 0x18, 0xE0,
+ 0x02, 0x2F, 0x08, 0xD0, 0x02, 0x24, 0xC0, 0xB2, 0x88, 0xF8, 0x01, 0x00, 0x2C, 0x70, 0x29, 0x48,
+ 0x08, 0x30, 0xBD, 0xE8, 0xF0, 0x9F, 0x68, 0x78, 0x04, 0x28, 0x08, 0xD0, 0x0B, 0xEB, 0x09, 0x00,
+ 0x49, 0x46, 0x10, 0xF8, 0x01, 0x2C, 0x22, 0x48, 0x10, 0x38, 0x06, 0xF0, 0xAA, 0xFB, 0x86, 0xF8,
+ 0x00, 0xA0, 0xA8, 0x46, 0x28, 0x78, 0xE7, 0xE7, 0x02, 0x2F, 0x05, 0xD0, 0xB9, 0xF1, 0x08, 0x0F,
+ 0x93, 0xD1, 0xFF, 0xF7, 0x81, 0xFE, 0x90, 0xE7, 0xFF, 0xF7, 0x7E, 0xFE, 0x98, 0xF8, 0x00, 0x00,
+ 0x03, 0x24, 0x88, 0xF8, 0x01, 0x00, 0x88, 0xF8, 0x00, 0x40, 0x6E, 0xE7, 0x02, 0x2F, 0x4F, 0xF0,
+ 0x03, 0x04, 0xAD, 0xD0, 0xCF, 0xE7, 0x13, 0x49, 0x00, 0x22, 0x0A, 0x70, 0x4A, 0x70, 0x18, 0x4A,
+ 0x52, 0x1C, 0x4A, 0x60, 0x17, 0x49, 0x01, 0x60, 0x0D, 0x49, 0x10, 0x39, 0x81, 0x80, 0x10, 0x31,
+ 0xC1, 0x80, 0x10, 0x21, 0x01, 0x81, 0x0E, 0x21, 0x13, 0x48, 0x06, 0xF0, 0x82, 0xBB, 0x10, 0xB5,
+ 0x04, 0x46, 0x06, 0xF0, 0x31, 0xFC, 0x06, 0x48, 0x21, 0x68, 0x10, 0x38, 0x01, 0x60, 0x61, 0x68,
+ 0x41, 0x60, 0x0E, 0x48, 0xFF, 0xF7, 0x91, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x06, 0xF0, 0xC8, 0xBB,
+ 0x5C, 0x43, 0x01, 0x20, 0x0C, 0x07, 0x10, 0x00, 0x4C, 0x62, 0x01, 0x20, 0xC8, 0x35, 0x01, 0x20,
+ 0xD0, 0x5E, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0x36, 0x0B, 0x01, 0x20, 0x60, 0x0B, 0x01, 0x20,
+ 0xF4, 0x48, 0x10, 0x00, 0x51, 0x00, 0x01, 0x00, 0xDC, 0x48, 0x10, 0x00, 0x4C, 0x43, 0x00, 0x00,
+ 0x70, 0xB5, 0x0F, 0x4D, 0x48, 0x21, 0x28, 0x46, 0x2C, 0x88, 0x06, 0xF0, 0x52, 0xFB, 0x64, 0x1C,
+ 0x2C, 0x80, 0x70, 0xBD, 0x0A, 0x48, 0x00, 0x1F, 0x00, 0x21, 0x01, 0x60, 0x70, 0x47, 0x08, 0x49,
+ 0x09, 0x1F, 0x0A, 0x88, 0x02, 0x42, 0x04, 0xD0, 0xC8, 0x78, 0x18, 0xB1, 0xC8, 0x78, 0x40, 0x1E,
+ 0xC8, 0x70, 0x70, 0x47, 0xA5, 0x20, 0x88, 0x70, 0x88, 0x78, 0xA5, 0x28, 0xFC, 0xD0, 0x70, 0x47,
+ 0xE6, 0x43, 0x01, 0x20, 0x37, 0x48, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x70, 0x47, 0xC0, 0xB2,
+ 0x01, 0x22, 0x00, 0xF0, 0x29, 0xFB, 0xFE, 0xE7, 0x34, 0x4C, 0x00, 0x25, 0x32, 0x4F, 0xC4, 0xE9,
+ 0x02, 0x25, 0xC4, 0xE9, 0x00, 0x71, 0x06, 0x46, 0x00, 0x68, 0x20, 0x61, 0x70, 0x68, 0x60, 0x61,
+ 0xB0, 0x68, 0xA0, 0x61, 0xF0, 0x68, 0xE0, 0x61, 0x30, 0x69, 0x20, 0x62, 0x70, 0x69, 0x60, 0x62,
+ 0xB0, 0x69, 0xA0, 0x62, 0xF0, 0x69, 0xE0, 0x62, 0x29, 0x48, 0x90, 0x46, 0x89, 0x46, 0x00, 0x68,
+ 0x20, 0x63, 0x27, 0x48, 0x10, 0x38, 0x00, 0x68, 0x60, 0x63, 0x25, 0x48, 0x0C, 0x38, 0x00, 0x68,
+ 0xA0, 0x63, 0x23, 0x48, 0x08, 0x38, 0x00, 0x68, 0xE0, 0x63, 0x21, 0x48, 0x00, 0x1D, 0x00, 0x68,
+ 0x20, 0x64, 0x1F, 0x48, 0x34, 0x38, 0x00, 0x68, 0x60, 0x64, 0x1D, 0x48, 0x14, 0x38, 0x00, 0x68,
+ 0xC4, 0xE9, 0x12, 0x05, 0x04, 0xF0, 0x37, 0xFB, 0x20, 0x65, 0xC4, 0xE9, 0x15, 0x65, 0xE5, 0x65,
+ 0x25, 0x66, 0x65, 0x66, 0xA5, 0x66, 0xE5, 0x66, 0x25, 0x67, 0x65, 0x67, 0xC4, 0xE9, 0x1E, 0x57,
+ 0x41, 0x46, 0x48, 0x46, 0xFF, 0xF7, 0xB3, 0xFF, 0x10, 0xB5, 0x04, 0x46, 0xC0, 0xB2, 0x00, 0x22,
+ 0x00, 0xF0, 0xDA, 0xFA, 0x0F, 0x49, 0x08, 0x68, 0x08, 0x28, 0x03, 0xDA, 0x09, 0x4A, 0x14, 0x54,
+ 0x40, 0x1C, 0x08, 0x60, 0x10, 0xBD, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x08, 0xD1, 0x00, 0x22,
+ 0x11, 0x46, 0x13, 0x20, 0x00, 0xF0, 0xC8, 0xBA, 0x00, 0x22, 0x11, 0x46, 0x12, 0x20, 0xF9, 0xE7,
+ 0x70, 0x47, 0x00, 0x00, 0x70, 0xEF, 0x01, 0x20, 0xAF, 0x05, 0x50, 0xFA, 0x80, 0xEF, 0x01, 0x20,
+ 0x38, 0xED, 0x00, 0xE0, 0x1C, 0x07, 0x10, 0x00, 0xF4, 0x48, 0xF5, 0x4A, 0x01, 0x68, 0x91, 0x42,
+ 0x04, 0xD1, 0xF4, 0x49, 0x02, 0x79, 0x4A, 0x70, 0x00, 0x21, 0x01, 0x60, 0x70, 0x47, 0xF0, 0xB5,
+ 0x85, 0xB0, 0x40, 0xF2, 0x14, 0x71, 0xED, 0x48, 0x06, 0xF0, 0xCD, 0xFA, 0x68, 0x46, 0x05, 0xF0,
+ 0x11, 0xFA, 0xEA, 0x4C, 0x01, 0x26, 0x00, 0x25, 0x66, 0x70, 0xA5, 0x80, 0xA5, 0x71, 0x02, 0x20,
+ 0xE0, 0x71, 0x04, 0xF0, 0xD8, 0xFE, 0x20, 0x81, 0x04, 0xF0, 0xD1, 0xFE, 0x07, 0x02, 0x04, 0xF0,
+ 0xCE, 0xFE, 0x47, 0xEA, 0x10, 0x20, 0x60, 0x81, 0x10, 0x20, 0x20, 0x82, 0x40, 0xF2, 0x32, 0x20,
+ 0x60, 0x82, 0xE1, 0x48, 0x00, 0x68, 0x41, 0x8A, 0xA1, 0x82, 0x01, 0x8A, 0xE1, 0x82, 0xC1, 0x8A,
+ 0x21, 0x83, 0x81, 0x8A, 0x61, 0x83, 0xDD, 0x49, 0xB1, 0xF8, 0xFA, 0x2E, 0xA4, 0xF8, 0x44, 0x20,
+ 0xB1, 0xF8, 0xF8, 0x1E, 0xA4, 0xF8, 0x46, 0x10, 0x90, 0xF8, 0x3F, 0x10, 0x21, 0x77, 0xD8, 0x49,
+ 0x09, 0x68, 0x09, 0x7E, 0x61, 0x77, 0x90, 0xF8, 0xA0, 0x10, 0x01, 0xF0, 0x01, 0x01, 0xA1, 0x77,
+ 0x01, 0x99, 0x21, 0x62, 0x00, 0x99, 0x61, 0x62, 0x02, 0x99, 0xA1, 0x62, 0xDD, 0xE9, 0x03, 0x12,
+ 0x41, 0xEA, 0x02, 0x21, 0xE1, 0x62, 0x81, 0x69, 0x21, 0x63, 0xC1, 0x69, 0xC4, 0xE9, 0x0D, 0x15,
+ 0xE5, 0x63, 0xA4, 0xF8, 0x40, 0x50, 0x84, 0xF8, 0x42, 0x50, 0x84, 0xF8, 0x43, 0x60, 0x41, 0x8E,
+ 0xA4, 0xF8, 0x50, 0x10, 0x81, 0x8E, 0xA4, 0xF8, 0x52, 0x10, 0x90, 0xF8, 0x31, 0x10, 0x84, 0xF8,
+ 0x54, 0x10, 0x90, 0xF8, 0x30, 0x00, 0x84, 0xF8, 0x55, 0x00, 0xC2, 0x48, 0xA4, 0xF8, 0x80, 0x00,
+ 0xC1, 0x48, 0xA4, 0xF8, 0x88, 0x00, 0xC1, 0x48, 0xA4, 0xF8, 0x8A, 0x00, 0xC0, 0x48, 0xA4, 0xF8,
+ 0x8C, 0x00, 0xC0, 0x48, 0xA4, 0xF8, 0x8E, 0x00, 0xBF, 0x48, 0xA4, 0xF8, 0x90, 0x00, 0xBF, 0x48,
+ 0xA4, 0xF8, 0x92, 0x00, 0xBE, 0x48, 0xA4, 0xF8, 0x94, 0x00, 0xBE, 0x48, 0xA4, 0xF8, 0x96, 0x00,
+ 0xBD, 0x48, 0xA4, 0xF8, 0x98, 0x00, 0xBD, 0x48, 0xA4, 0xF8, 0x9A, 0x00, 0xBC, 0x48, 0xA4, 0xF8,
+ 0x9C, 0x00, 0xAC, 0x49, 0xBB, 0x48, 0xA4, 0xF8, 0x9E, 0x00, 0x88, 0x88, 0x40, 0x1C, 0x88, 0x80,
+ 0xA5, 0x22, 0x22, 0x70, 0x66, 0x70, 0x60, 0x80, 0x0E, 0x70, 0x05, 0xB0, 0xF0, 0xBD, 0x70, 0xB5,
+ 0xA4, 0x4C, 0x05, 0x46, 0x00, 0x23, 0xA0, 0x88, 0xA0, 0x49, 0x40, 0x1C, 0x82, 0xB2, 0xA2, 0x80,
+ 0x28, 0x46, 0x01, 0xF0, 0x2A, 0xFB, 0x25, 0x70, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x46, 0x40, 0xF2,
+ 0x14, 0x71, 0x9A, 0x48, 0x06, 0xF0, 0x27, 0xFA, 0x9A, 0x4C, 0x98, 0x49, 0xA0, 0x88, 0x40, 0x1C,
+ 0x82, 0xB2, 0xA2, 0x80, 0x28, 0x46, 0x01, 0xF0, 0x45, 0xFB, 0x25, 0x70, 0x70, 0xBD, 0x70, 0xB5,
+ 0x94, 0x4C, 0x05, 0x46, 0x20, 0x78, 0xA8, 0x42, 0x04, 0xD0, 0x40, 0xF2, 0x14, 0x71, 0x8F, 0x48,
+ 0x06, 0xF0, 0x11, 0xFA, 0xA0, 0x48, 0xA5, 0x70, 0x0F, 0x21, 0x01, 0x60, 0x8B, 0x48, 0x8B, 0x4A,
+ 0x10, 0x30, 0xA0, 0x60, 0x48, 0x20, 0x10, 0x71, 0x8B, 0x48, 0x02, 0xF1, 0x58, 0x05, 0xE5, 0x60,
+ 0x00, 0x68, 0x90, 0xF8, 0x31, 0x10, 0x90, 0xF8, 0x30, 0x30, 0x51, 0x71, 0x01, 0xFB, 0x03, 0xF0,
+ 0x05, 0xEB, 0x40, 0x06, 0x93, 0x71, 0x26, 0x61, 0x08, 0x44, 0xD1, 0x71, 0x05, 0xEB, 0x40, 0x00,
+ 0x60, 0x61, 0x13, 0x72, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x7D, 0x4C, 0x17, 0x46,
+ 0x88, 0x46, 0xC0, 0x07, 0x04, 0xD0, 0x48, 0x22, 0x7E, 0x49, 0xA0, 0x68, 0x06, 0xF0, 0x42, 0xF9,
+ 0x79, 0x4E, 0xA8, 0x07, 0x12, 0xD5, 0x31, 0x68, 0x91, 0xF8, 0x31, 0x00, 0x91, 0xF8, 0x30, 0x10,
+ 0x48, 0x43, 0xA1, 0x78, 0x30, 0x29, 0x2D, 0xD0, 0x31, 0x29, 0x2D, 0xD0, 0x32, 0x29, 0x31, 0xD0,
+ 0x77, 0x49, 0xE3, 0x68, 0x42, 0x00, 0x18, 0x46, 0x06, 0xF0, 0x2C, 0xF9, 0x68, 0x07, 0x0E, 0xD5,
+ 0x30, 0x68, 0x90, 0xF8, 0x31, 0x20, 0xA0, 0x78, 0x30, 0x28, 0x25, 0xD0, 0x31, 0x28, 0x25, 0xD0,
+ 0x32, 0x28, 0x28, 0xD0, 0x72, 0x49, 0x52, 0x00, 0x20, 0x69, 0x06, 0xF0, 0x1B, 0xF9, 0x28, 0x07,
+ 0x2C, 0xD5, 0x30, 0x68, 0x90, 0xF8, 0x30, 0x20, 0xA0, 0x78, 0x30, 0x28, 0x1D, 0xD0, 0x31, 0x28,
+ 0x1D, 0xD0, 0x32, 0x28, 0x20, 0xD0, 0x6E, 0x49, 0x60, 0x69, 0xBD, 0xE8, 0xF0, 0x41, 0x52, 0x00,
+ 0x06, 0xF0, 0x08, 0xB9, 0x60, 0x49, 0xD4, 0xE7, 0x60, 0x49, 0xB8, 0xF1, 0x00, 0x0F, 0xD0, 0xD0,
+ 0x6A, 0x49, 0xCE, 0xE7, 0x5F, 0x49, 0xCC, 0xE7, 0x5F, 0x49, 0xDC, 0xE7, 0x5F, 0x49, 0x00, 0x2F,
+ 0xD9, 0xD0, 0x67, 0x49, 0xD7, 0xE7, 0x5F, 0x49, 0xD5, 0xE7, 0x5F, 0x49, 0xE4, 0xE7, 0x5F, 0x49,
+ 0x00, 0x2F, 0xE1, 0xD0, 0x63, 0x49, 0xDF, 0xE7, 0x5E, 0x49, 0xDD, 0xE7, 0xBD, 0xE8, 0xF0, 0x81,
+ 0x4A, 0x4A, 0xA5, 0x20, 0x10, 0x70, 0x4B, 0x48, 0x81, 0x78, 0x51, 0x70, 0x01, 0x70, 0x81, 0x88,
+ 0x49, 0x1C, 0x81, 0x80, 0x51, 0x80, 0x70, 0x47, 0x30, 0xB5, 0x85, 0xB0, 0x0C, 0x46, 0x00, 0x21,
+ 0x8D, 0xF8, 0x0C, 0x10, 0x4F, 0xF4, 0x83, 0x25, 0x04, 0xAB, 0x03, 0xAA, 0x69, 0x46, 0x00, 0xF0,
+ 0xD0, 0xF8, 0x9D, 0xF8, 0x10, 0x00, 0x10, 0xB1, 0x11, 0x28, 0x15, 0xD0, 0x19, 0xE0, 0x9D, 0xF8,
+ 0x0C, 0x00, 0xB0, 0xB1, 0x00, 0x98, 0x05, 0xEB, 0x80, 0x01, 0x04, 0xF1, 0x10, 0x00, 0x0A, 0x78,
+ 0x93, 0x07, 0x03, 0xD0, 0x02, 0xF0, 0xFC, 0x02, 0x08, 0x32, 0x00, 0xE0, 0x12, 0x1D, 0xD2, 0xB2,
+ 0x06, 0xF0, 0xB8, 0xF8, 0x05, 0xB0, 0x30, 0xBD, 0x32, 0x20, 0x00, 0x22, 0x20, 0x71, 0x11, 0x46,
+ 0x03, 0xE0, 0x30, 0x20, 0x00, 0x22, 0x20, 0x71, 0x11, 0x46, 0x00, 0xF0, 0x25, 0xF9, 0xF1, 0xE7,
+ 0x70, 0xB5, 0x05, 0x46, 0x4F, 0xF4, 0xC8, 0x71, 0x28, 0x48, 0x06, 0xF0, 0x44, 0xF9, 0x29, 0x4C,
+ 0x26, 0x49, 0xA0, 0x88, 0x40, 0x1C, 0xA0, 0x80, 0x28, 0x46, 0xFF, 0xF7, 0xBD, 0xFF, 0x23, 0x48,
+ 0x25, 0x70, 0xA5, 0x21, 0x01, 0x70, 0x45, 0x70, 0xA1, 0x88, 0x41, 0x80, 0x70, 0xBD, 0x2D, 0xE9,
+ 0xF8, 0x4F, 0x0C, 0x46, 0x88, 0x46, 0x0E, 0x1D, 0x00, 0x23, 0x9B, 0x22, 0x04, 0x21, 0x20, 0x46,
+ 0x00, 0xF0, 0x60, 0xFE, 0x80, 0xBB, 0x21, 0x78, 0x00, 0x23, 0x9B, 0x22, 0x30, 0x46, 0x00, 0xF0,
+ 0x59, 0xFE, 0x61, 0x78, 0x88, 0x42, 0x76, 0xD1, 0x20, 0x78, 0x81, 0x07, 0x0A, 0xD0, 0x02, 0x22,
+ 0x02, 0xEB, 0x90, 0x05, 0x00, 0x21, 0x01, 0xE0, 0x31, 0x54, 0x40, 0x1C, 0xB0, 0xEB, 0x85, 0x0F,
+ 0xFA, 0xD3, 0x02, 0xE0, 0x01, 0x21, 0x01, 0xEB, 0x90, 0x05, 0x00, 0x24, 0xDF, 0xF8, 0x2C, 0xB0,
+ 0x4F, 0xF4, 0x83, 0x26, 0xA1, 0x46, 0x4F, 0xF0, 0x33, 0x0A, 0x00, 0xBF, 0x56, 0xF8, 0x24, 0x00,
+ 0x06, 0xEB, 0x84, 0x07, 0x40, 0x1C, 0x37, 0xD0, 0x00, 0x23, 0x9B, 0x22, 0x04, 0x21, 0x38, 0x46,
+ 0x00, 0xF0, 0x30, 0xFE, 0x08, 0xB1, 0x45, 0xE0, 0x4D, 0xE0, 0x2F, 0xE0, 0x00, 0x00, 0x01, 0x20,
+ 0x4B, 0x43, 0x55, 0x46, 0x58, 0x07, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xFC, 0x4C, 0x01, 0x20,
+ 0x24, 0x07, 0x10, 0x00, 0xE6, 0x43, 0x01, 0x20, 0x4C, 0x62, 0x01, 0x20, 0x8C, 0x2F, 0x01, 0x20,
+ 0xC8, 0x35, 0x01, 0x20, 0x2E, 0x44, 0x01, 0x20, 0x68, 0x5F, 0x01, 0x20, 0xC0, 0x0A, 0x01, 0x20,
+ 0x36, 0x0B, 0x01, 0x20, 0x6A, 0x4A, 0x01, 0x20, 0x92, 0x5F, 0x01, 0x20, 0xEA, 0x0A, 0x01, 0x20,
+ 0x60, 0x0B, 0x01, 0x20, 0x94, 0x4A, 0x01, 0x20, 0x40, 0x07, 0x10, 0x00, 0x3C, 0x0C, 0x01, 0x20,
+ 0x84, 0x09, 0x01, 0x20, 0xAE, 0x09, 0x01, 0x20, 0x00, 0x94, 0x0C, 0xE0, 0x38, 0x78, 0x81, 0x07,
+ 0x04, 0xEB, 0x90, 0x04, 0x01, 0xD0, 0xA4, 0x1C, 0x00, 0xE0, 0x64, 0x1C, 0x60, 0x2C, 0xB5, 0xD3,
+ 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xD0, 0x29, 0x46, 0x40, 0x46, 0x00, 0x9A, 0x04, 0xF0, 0xEB, 0xFD,
+ 0x00, 0x28, 0x0C, 0xD0, 0x00, 0x22, 0x8B, 0xF8, 0x04, 0xA0, 0x11, 0x46, 0x33, 0x20, 0xBD, 0xE8,
+ 0xF8, 0x4F, 0x00, 0xF0, 0x81, 0xB8, 0x00, 0x22, 0x11, 0x46, 0x31, 0x20, 0xF7, 0xE7, 0xBD, 0xE8,
+ 0xF8, 0x8F, 0x2D, 0xE9, 0xFF, 0x5F, 0x00, 0x26, 0x0E, 0x60, 0x1D, 0x46, 0x88, 0x46, 0x4F, 0xF4,
+ 0x83, 0x27, 0xB1, 0x46, 0x34, 0x46, 0xB3, 0x46, 0x83, 0xF8, 0x00, 0x60, 0x57, 0xF8, 0x24, 0x00,
+ 0x07, 0xEB, 0x84, 0x0A, 0x40, 0x1C, 0x23, 0xD0, 0x00, 0x23, 0x9B, 0x22, 0x04, 0x21, 0x50, 0x46,
+ 0x00, 0xF0, 0xC0, 0xFD, 0x18, 0xB1, 0x12, 0x20, 0x28, 0x70, 0x01, 0x26, 0x1C, 0xE0, 0x9A, 0xF8,
+ 0x02, 0x20, 0x00, 0x99, 0x9A, 0xF8, 0x00, 0x00, 0x8A, 0x42, 0x08, 0xD1, 0x02, 0x99, 0x02, 0x9A,
+ 0x4F, 0xF0, 0x01, 0x09, 0x09, 0x78, 0x49, 0x1C, 0x11, 0x70, 0xC8, 0xF8, 0x00, 0x40, 0x81, 0x07,
+ 0x04, 0xEB, 0x90, 0x04, 0x01, 0xD0, 0xA4, 0x1C, 0x00, 0xE0, 0x64, 0x1C, 0x60, 0x2C, 0xD5, 0xD3,
+ 0x16, 0xB9, 0xB9, 0xF1, 0x01, 0x0F, 0x0B, 0xD0, 0x56, 0xEA, 0x09, 0x06, 0x06, 0xD1, 0x11, 0x20,
+ 0x28, 0x70, 0x02, 0x99, 0x81, 0xF8, 0x00, 0xB0, 0xC8, 0xF8, 0x00, 0xB0, 0xBD, 0xE8, 0xFF, 0x9F,
+ 0xD8, 0xF8, 0x00, 0x00, 0x00, 0x23, 0x07, 0xEB, 0x80, 0x04, 0x20, 0x1D, 0x21, 0x78, 0x9B, 0x22,
+ 0x00, 0xF0, 0x88, 0xFD, 0x61, 0x78, 0x88, 0x42, 0x02, 0xD1, 0x85, 0xF8, 0x00, 0xB0, 0xED, 0xE7,
+ 0x12, 0x20, 0x28, 0x70, 0xEA, 0xE7, 0x00, 0x00, 0x19, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xA0, 0x00,
+ 0xC0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0x2E, 0xB8, 0x00, 0xF0, 0xDE, 0xB8, 0x38, 0xB5, 0x04, 0x46,
+ 0x69, 0x46, 0x18, 0x30, 0x00, 0xF0, 0xF9, 0xFD, 0x11, 0x48, 0x00, 0x99, 0x00, 0x68, 0x90, 0xF8,
+ 0xA0, 0x00, 0xC0, 0x07, 0x20, 0x46, 0x02, 0xD0, 0x00, 0xF0, 0x39, 0xF8, 0x38, 0xBD, 0x00, 0xF0,
+ 0xD5, 0xF8, 0x38, 0xBD, 0x00, 0xF0, 0x25, 0xB9, 0x09, 0x4B, 0x1B, 0x68, 0x93, 0xF8, 0xA0, 0x30,
+ 0xDB, 0x07, 0x01, 0xD1, 0x00, 0xF0, 0x3B, 0xB9, 0x70, 0x47, 0x05, 0x49, 0x09, 0x68, 0x91, 0xF8,
+ 0xA0, 0x10, 0xC9, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0x99, 0xB8, 0x00, 0xF0, 0x42, 0xB9, 0x00, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x1C, 0xB5, 0x56, 0x49, 0xD1, 0xE9, 0x00, 0x01, 0xCD, 0xE9, 0x00, 0x01,
+ 0x68, 0x46, 0xFF, 0xF7, 0x77, 0xFA, 0x1C, 0xBD, 0x88, 0x42, 0x0E, 0xD9, 0x90, 0x42, 0x01, 0xD3,
+ 0xFF, 0x20, 0x70, 0x47, 0x91, 0x42, 0x08, 0xD0, 0x40, 0x1A, 0xC0, 0xEB, 0x00, 0x20, 0x51, 0x1A,
+ 0xB0, 0xFB, 0xF1, 0xF0, 0x10, 0xF0, 0xFF, 0x00, 0xF3, 0xD1, 0x01, 0x20, 0x70, 0x47, 0x7C, 0xB5,
+ 0x05, 0x46, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x95, 0xF8, 0x4B, 0x21, 0x9D, 0xF8, 0x00, 0x00,
+ 0x62, 0xF3, 0x85, 0x00, 0x8D, 0xF8, 0x00, 0x00, 0x95, 0xF8, 0x3E, 0x21, 0x03, 0x2A, 0x3E, 0xD0,
+ 0x08, 0x2A, 0x40, 0xD0, 0x20, 0xF0, 0xC0, 0x00, 0x10, 0xF1, 0x80, 0x00, 0x8D, 0xF8, 0x00, 0x00,
+ 0x0A, 0x14, 0x10, 0x09, 0x8D, 0xF8, 0x01, 0x00, 0x9D, 0xF8, 0x03, 0x00, 0x39, 0x4E, 0x62, 0xF3,
+ 0x07, 0x10, 0x0A, 0x09, 0x8D, 0xF8, 0x02, 0x20, 0x61, 0xF3, 0x03, 0x00, 0x8D, 0xF8, 0x03, 0x00,
+ 0x30, 0x68, 0xB0, 0xF8, 0xA3, 0x20, 0xB0, 0xF8, 0xA1, 0x10, 0x35, 0xF8, 0x4A, 0x0F, 0xFF, 0xF7,
+ 0xBB, 0xFF, 0x8D, 0xF8, 0x04, 0x00, 0x30, 0x68, 0xB0, 0xF8, 0xA7, 0x20, 0xB0, 0xF8, 0xA5, 0x10,
+ 0x68, 0x88, 0xFF, 0xF7, 0xB1, 0xFF, 0x8D, 0xF8, 0x05, 0x00, 0x29, 0x7A, 0x9D, 0xF8, 0x06, 0x00,
+ 0x61, 0xF3, 0x05, 0x00, 0x8D, 0xF8, 0x06, 0x00, 0x95, 0xF8, 0xF6, 0x10, 0x09, 0x29, 0x1E, 0xD2,
+ 0xDF, 0xE8, 0x01, 0xF0, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x00, 0x20, 0xF0,
+ 0xC0, 0x00, 0x40, 0x30, 0xC2, 0xE7, 0x40, 0xF0, 0xC0, 0x00, 0xBF, 0xE7, 0x00, 0x24, 0x0E, 0xE0,
+ 0x01, 0x24, 0x0C, 0xE0, 0x02, 0x24, 0x0A, 0xE0, 0x03, 0x24, 0x08, 0xE0, 0x04, 0x24, 0x06, 0xE0,
+ 0x05, 0x24, 0x04, 0xE0, 0x06, 0x24, 0x02, 0xE0, 0x07, 0x24, 0x00, 0xE0, 0x08, 0x24, 0xA1, 0x08,
+ 0x61, 0xF3, 0x87, 0x10, 0x8D, 0xF8, 0x06, 0x00, 0x9D, 0xF8, 0x07, 0x00, 0x64, 0xF3, 0x87, 0x10,
+ 0x8D, 0xF8, 0x07, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0xED, 0xF9, 0x7C, 0xBD, 0x1C, 0xB5, 0x0C, 0x4A,
+ 0xD2, 0xE9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0x9D, 0xF8, 0x00, 0x10, 0x21, 0xF0, 0x3C, 0x01,
+ 0x8D, 0xF8, 0x00, 0x10, 0x80, 0x78, 0x01, 0x28, 0x03, 0xD0, 0x05, 0x28, 0x07, 0xD1, 0x01, 0x20,
+ 0x00, 0xE0, 0x00, 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0xD3, 0xF9, 0x1C, 0xBD,
+ 0x20, 0x6E, 0x01, 0x00, 0x20, 0x07, 0x10, 0x00, 0x1C, 0xB5, 0x51, 0x49, 0xD1, 0xE9, 0x00, 0x01,
+ 0xCD, 0xE9, 0x00, 0x01, 0x68, 0x46, 0xFF, 0xF7, 0xC5, 0xF9, 0x1C, 0xBD, 0x1C, 0xB5, 0x4C, 0x4B,
+ 0xD3, 0xE9, 0x02, 0x23, 0xCD, 0xE9, 0x00, 0x23, 0x90, 0xF8, 0x3E, 0x21, 0x03, 0x2A, 0x19, 0xD0,
+ 0x08, 0x2A, 0x9D, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0xF0, 0x02, 0x19, 0xD0, 0x12, 0xF1, 0x20, 0x02,
+ 0x8D, 0xF8, 0x00, 0x20, 0x90, 0xF8, 0x3F, 0x21, 0x02, 0xF0, 0x0F, 0x02, 0x01, 0x2A, 0x11, 0xD0,
+ 0x02, 0x2A, 0x15, 0xD0, 0x04, 0x2A, 0x9D, 0xF8, 0x01, 0x20, 0x22, 0xF0, 0x0F, 0x02, 0x2E, 0xD0,
+ 0x52, 0x1C, 0x12, 0xE0, 0x9D, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0xF0, 0x02, 0x10, 0x32, 0xE7, 0xE7,
+ 0x30, 0x32, 0xE5, 0xE7, 0x9D, 0xF8, 0x01, 0x20, 0x22, 0xF0, 0x0F, 0x02, 0x92, 0x1C, 0x04, 0xE0,
+ 0x9D, 0xF8, 0x01, 0x20, 0x22, 0xF0, 0x0F, 0x02, 0xD2, 0x1C, 0x8D, 0xF8, 0x01, 0x20, 0x90, 0xF8,
+ 0x4B, 0x01, 0xD2, 0xB2, 0x60, 0xF3, 0x07, 0x12, 0x8D, 0xF8, 0x01, 0x20, 0xBD, 0xF8, 0x02, 0x00,
+ 0x0A, 0x0C, 0x62, 0xF3, 0x0B, 0x00, 0xAD, 0xF8, 0x02, 0x00, 0xBD, 0xF8, 0x03, 0x00, 0x61, 0xF3,
+ 0x0F, 0x10, 0xAD, 0xF8, 0x03, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x74, 0xF9, 0x1C, 0xBD, 0x12, 0x1D,
+ 0xE3, 0xE7, 0x1C, 0xB5, 0x23, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0xA0, 0x20, 0x93, 0x07, 0x15, 0xD5,
+ 0x08, 0x28, 0x13, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x12, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x12, 0x06, 0x0B, 0xD5, 0x1A, 0x4B, 0xD3, 0xE9, 0x06, 0x23, 0xCD, 0xE9, 0x00, 0x23, 0x8D, 0xF8,
+ 0x01, 0x00, 0xCD, 0xF8, 0x02, 0x10, 0x68, 0x46, 0xFF, 0xF7, 0x54, 0xF9, 0x1C, 0xBD, 0x1C, 0xB5,
+ 0x13, 0x4C, 0xD4, 0xE9, 0x08, 0x34, 0xCD, 0xE9, 0x00, 0x34, 0x8D, 0xF8, 0x01, 0x00, 0xCD, 0xF8,
+ 0x02, 0x10, 0x68, 0x46, 0x12, 0xB1, 0xFF, 0xF7, 0x32, 0xFB, 0x1C, 0xBD, 0xFF, 0xF7, 0x42, 0xF9,
+ 0x1C, 0xBD, 0x1C, 0xB5, 0x41, 0x78, 0x00, 0x29, 0x10, 0xD0, 0x05, 0x29, 0x0E, 0xD2, 0x08, 0x4A,
+ 0xD2, 0xE9, 0x0C, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xD0, 0xF8, 0x02, 0x10, 0xCD, 0xF8, 0x02, 0x10,
+ 0xC0, 0x88, 0xAD, 0xF8, 0x06, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x2C, 0xF9, 0x1C, 0xBD, 0x00, 0x00,
+ 0x40, 0x6E, 0x01, 0x00, 0x20, 0x07, 0x10, 0x00, 0x2D, 0xE9, 0xFF, 0x41, 0x03, 0xF0, 0xCE, 0xFC,
+ 0x23, 0x4D, 0x00, 0x24, 0xC4, 0xEB, 0xC4, 0x01, 0x05, 0xEB, 0x81, 0x00, 0x00, 0xF1, 0x0C, 0x03,
+ 0x02, 0x7E, 0xC8, 0xCB, 0xCD, 0xE9, 0x02, 0x72, 0xCD, 0xE9, 0x00, 0x36, 0xD0, 0xE9, 0x01, 0x23,
+ 0x55, 0xF8, 0x21, 0x00, 0x00, 0x21, 0x03, 0xF0, 0x63, 0xFE, 0x18, 0xB1, 0x21, 0x46, 0x43, 0x20,
+ 0xFF, 0xF7, 0x45, 0xFB, 0x64, 0x1C, 0x05, 0x2C, 0xE4, 0xDB, 0x15, 0x4D, 0x00, 0x24, 0x8C, 0x35,
+ 0x05, 0xEB, 0xC4, 0x00, 0x00, 0x21, 0x42, 0x68, 0x55, 0xF8, 0x34, 0x00, 0x03, 0xF0, 0xD7, 0xFD,
+ 0x18, 0xB1, 0x21, 0x46, 0x44, 0x20, 0xFF, 0xF7, 0x32, 0xFB, 0x64, 0x1C, 0x06, 0x2C, 0xEF, 0xDB,
+ 0x0B, 0x4D, 0x00, 0x24, 0x15, 0xF1, 0xBC, 0x05, 0x00, 0x21, 0x55, 0xF8, 0x24, 0x00, 0x03, 0xF0,
+ 0x2C, 0xFD, 0x18, 0xB1, 0x21, 0x46, 0x45, 0x20, 0xFF, 0xF7, 0x21, 0xFB, 0x64, 0x1C, 0x04, 0x2C,
+ 0xF2, 0xDB, 0xBD, 0xE8, 0xFF, 0x81, 0x01, 0x46, 0x46, 0x20, 0xFF, 0xF7, 0x18, 0xBB, 0x00, 0x00,
+ 0x78, 0x6E, 0x01, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x64, 0x27, 0x07, 0x26, 0x00, 0x25, 0xFB, 0x4C,
+ 0xFB, 0x48, 0x04, 0xF0, 0x4A, 0xFD, 0xFA, 0x48, 0x03, 0x68, 0xD9, 0x1C, 0x40, 0xD0, 0x42, 0x68,
+ 0xD1, 0x1C, 0x3D, 0xD0, 0x81, 0x68, 0x11, 0xF1, 0x03, 0x0F, 0x39, 0xD0, 0x00, 0x69, 0x10, 0xF1,
+ 0x03, 0x0F, 0x35, 0xD0, 0xB3, 0xF1, 0xFF, 0x3F, 0x35, 0xD0, 0x13, 0xF1, 0x02, 0x0F, 0x32, 0xD0,
+ 0xB2, 0xF1, 0xFF, 0x3F, 0x2F, 0xD0, 0x12, 0xF1, 0x02, 0x0F, 0x2C, 0xD0, 0xB1, 0xF1, 0xFF, 0x3F,
+ 0x29, 0xD0, 0x11, 0xF1, 0x02, 0x0F, 0x26, 0xD0, 0xB0, 0xF1, 0xFF, 0x3F, 0x23, 0xD0, 0x10, 0xF1,
+ 0x02, 0x0F, 0x20, 0xD0, 0xDF, 0xB2, 0xD6, 0xB2, 0xCD, 0xB2, 0x04, 0x46, 0x2A, 0x46, 0x31, 0x46,
+ 0x38, 0x46, 0x04, 0xF0, 0x6D, 0xFA, 0x20, 0x46, 0x04, 0xF0, 0x77, 0xFA, 0xE1, 0x48, 0x04, 0xF0,
+ 0xEA, 0xFC, 0x03, 0x28, 0x14, 0xD0, 0x01, 0x28, 0x15, 0xD0, 0x02, 0x28, 0x13, 0xD0, 0xDD, 0x48,
+ 0x01, 0x68, 0x01, 0x29, 0x15, 0xD1, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0x1D, 0x03, 0xF0, 0x78, 0xBE,
+ 0x00, 0x21, 0x24, 0x20, 0x01, 0xE0, 0x00, 0x21, 0x25, 0x20, 0xFF, 0xF7, 0x0D, 0xFB, 0xDD, 0xE7,
+ 0x00, 0x21, 0x29, 0x20, 0x01, 0xE0, 0x00, 0x21, 0x2A, 0x20, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7,
+ 0x03, 0xBB, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0xCF, 0x4F, 0x01, 0x25, 0x01, 0xAA,
+ 0x69, 0x46, 0x38, 0x46, 0x04, 0xF0, 0xB0, 0xFA, 0xCC, 0x4C, 0x4F, 0xF4, 0x8C, 0x56, 0x01, 0x28,
+ 0x03, 0xD1, 0x00, 0x98, 0xB0, 0xF5, 0x8C, 0x6F, 0x04, 0xD0, 0x00, 0x21, 0x22, 0x20, 0xFF, 0xF7,
+ 0xEB, 0xFA, 0x30, 0xE0, 0x32, 0x46, 0x39, 0x46, 0x20, 0x68, 0x05, 0xF0, 0x4B, 0xFD, 0x20, 0x68,
+ 0x04, 0xF0, 0xAD, 0xFA, 0x01, 0x28, 0x04, 0xD0, 0x00, 0x21, 0x23, 0x20, 0xFF, 0xF7, 0xDC, 0xFA,
+ 0x00, 0x25, 0x21, 0x68, 0x26, 0x22, 0x0F, 0x46, 0xBD, 0x48, 0x01, 0xF5, 0x86, 0x51, 0x05, 0xF0,
+ 0x39, 0xFD, 0x41, 0xF2, 0xE6, 0x00, 0x39, 0x18, 0xB9, 0x48, 0x36, 0x22, 0x28, 0x30, 0x05, 0xF0,
+ 0x31, 0xFD, 0x41, 0xF2, 0x1C, 0x10, 0x39, 0x18, 0xB5, 0x48, 0x26, 0x22, 0x48, 0x30, 0x05, 0xF0,
+ 0x29, 0xFD, 0x41, 0xF2, 0x42, 0x10, 0x39, 0x18, 0xB1, 0x48, 0x36, 0x22, 0x70, 0x30, 0x05, 0xF0,
+ 0x21, 0xFD, 0x00, 0x2D, 0x03, 0xD1, 0x31, 0x46, 0x20, 0x68, 0x05, 0xF0, 0x9A, 0xFD, 0xBD, 0xE8,
+ 0xFC, 0x81, 0xF8, 0xB5, 0x0D, 0x46, 0x06, 0x46, 0x00, 0x24, 0x6A, 0x46, 0x04, 0xF0, 0x64, 0xFA,
+ 0x01, 0x28, 0x01, 0xD0, 0x01, 0x24, 0x0B, 0xE0, 0x28, 0x68, 0x31, 0x46, 0x82, 0x00, 0xA5, 0x48,
+ 0x05, 0xF0, 0x4D, 0xFD, 0xA3, 0x48, 0x04, 0xF0, 0x6A, 0xFA, 0x01, 0x28, 0x00, 0xD0, 0x02, 0x24,
+ 0x20, 0x46, 0xF8, 0xBD, 0x2D, 0xE9, 0xF8, 0x43, 0x9E, 0x4D, 0x9F, 0x4F, 0x10, 0x35, 0x40, 0xF6,
+ 0xFC, 0x61, 0x9E, 0x48, 0x05, 0xF0, 0x97, 0xFD, 0x69, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xD9, 0xFF,
+ 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x06, 0xD0, 0xE8, 0x78, 0x01, 0x28, 0x0A, 0xD1, 0x05, 0xE0,
+ 0x00, 0x21, 0xA0, 0x20, 0x38, 0xE0, 0x00, 0x21, 0xA1, 0x20, 0x35, 0xE0, 0xA8, 0x78, 0x08, 0xB9,
+ 0x28, 0x88, 0x10, 0xB1, 0x00, 0x21, 0xA2, 0x20, 0x2E, 0xE0, 0xDF, 0xF8, 0x44, 0x82, 0xE9, 0x88,
+ 0xD8, 0xF8, 0x00, 0x00, 0x82, 0x8A, 0x91, 0x42, 0x02, 0xD0, 0x00, 0x21, 0xA3, 0x20, 0x05, 0xE0,
+ 0xA9, 0x88, 0xC0, 0x8A, 0x81, 0x42, 0x03, 0xD0, 0x00, 0x21, 0xA4, 0x20, 0xFF, 0xF7, 0x64, 0xFA,
+ 0x86, 0x48, 0xE9, 0x88, 0x00, 0x24, 0xA0, 0xF8, 0xF8, 0x1E, 0xA9, 0x88, 0xA0, 0xF8, 0xFA, 0x1E,
+ 0x00, 0x98, 0x69, 0x46, 0x07, 0xEB, 0x80, 0x07, 0x38, 0x46, 0xFF, 0xF7, 0xA2, 0xFF, 0x78, 0xB1,
+ 0x01, 0x28, 0x03, 0xD0, 0x00, 0x21, 0xA6, 0x20, 0xFF, 0xF7, 0x4E, 0xFA, 0xE0, 0x07, 0x24, 0xD0,
+ 0xA0, 0x07, 0x24, 0xD4, 0x11, 0x21, 0xA7, 0x20, 0xFF, 0xF7, 0x46, 0xFA, 0xBD, 0xE8, 0xF8, 0x83,
+ 0x6E, 0x78, 0x29, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x1F, 0xFE, 0x50, 0xB1, 0x10, 0x2E, 0x0B, 0xD0,
+ 0x11, 0x2E, 0x0C, 0xD0, 0x12, 0x2E, 0x0D, 0xD0, 0x13, 0x2E, 0xD9, 0xD1, 0x44, 0xF0, 0x10, 0x04,
+ 0xD6, 0xE7, 0x31, 0x46, 0xA8, 0x20, 0xDF, 0xE7, 0x44, 0xF0, 0x01, 0x04, 0xD0, 0xE7, 0x44, 0xF0,
+ 0x02, 0x04, 0xCD, 0xE7, 0x44, 0xF0, 0x08, 0x04, 0xCA, 0xE7, 0x10, 0x21, 0xDB, 0xE7, 0x20, 0x07,
+ 0x0B, 0xD4, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x50, 0x12, 0xC9, 0x07, 0x03, 0xD1, 0x90, 0xF8,
+ 0x80, 0x02, 0xC0, 0x07, 0x01, 0xD0, 0x12, 0x21, 0xCD, 0xE7, 0xE0, 0x06, 0xCE, 0xD4, 0x13, 0x21,
+ 0xC9, 0xE7, 0x38, 0xB5, 0x02, 0xF0, 0xEC, 0xFE, 0x03, 0xF0, 0x47, 0xFD, 0x00, 0x23, 0x01, 0x22,
+ 0x19, 0x46, 0x05, 0x20, 0x05, 0xF0, 0x12, 0xFB, 0x00, 0x23, 0x1A, 0x46, 0x01, 0x21, 0x06, 0x20,
+ 0x05, 0xF0, 0x0C, 0xFB, 0x03, 0x21, 0x01, 0x20, 0x00, 0xF0, 0x20, 0xF9, 0x04, 0x21, 0x07, 0x20,
+ 0x00, 0xF0, 0x1C, 0xF9, 0x04, 0x21, 0x08, 0x20, 0x00, 0xF0, 0x18, 0xF9, 0x50, 0x4C, 0x20, 0x68,
+ 0x90, 0xF8, 0xB0, 0x10, 0xC9, 0x07, 0x3B, 0xD0, 0x00, 0x25, 0x00, 0x95, 0x90, 0xF8, 0xC2, 0x00,
+ 0x2B, 0x46, 0xC0, 0xF3, 0x02, 0x10, 0x01, 0x22, 0x29, 0x46, 0x04, 0xF0, 0xA6, 0xFC, 0x20, 0x68,
+ 0x0A, 0x21, 0x90, 0xF8, 0xC2, 0x00, 0xC0, 0xF3, 0x02, 0x10, 0x04, 0xF0, 0xC6, 0xFC, 0x00, 0x95,
+ 0x20, 0x68, 0x00, 0x23, 0x01, 0x22, 0x90, 0xF8, 0xC2, 0x00, 0x19, 0x46, 0x00, 0xF0, 0x07, 0x00,
+ 0x04, 0xF0, 0x93, 0xFC, 0x20, 0x68, 0x01, 0x21, 0x90, 0xF8, 0xC2, 0x00, 0x00, 0xF0, 0x07, 0x00,
+ 0x04, 0xF0, 0xB3, 0xFC, 0x0D, 0x20, 0x00, 0xF0, 0xC3, 0xF8, 0x0D, 0x20, 0x00, 0xF0, 0xCB, 0xF8,
+ 0x07, 0x21, 0x0D, 0x20, 0x00, 0xF0, 0xD2, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0xB9, 0xF8, 0x0C, 0x20,
+ 0x00, 0xF0, 0xC1, 0xF8, 0xBD, 0xE8, 0x38, 0x40, 0x07, 0x21, 0x0C, 0x20, 0x00, 0xF0, 0xC6, 0xB8,
+ 0x38, 0xBD, 0x30, 0xB5, 0x8D, 0xB0, 0xEF, 0xF7, 0x09, 0xFA, 0x00, 0x24, 0x60, 0xB2, 0x00, 0xF0,
+ 0xA7, 0xF8, 0x64, 0x1C, 0x1F, 0x2C, 0xF9, 0xDB, 0xEF, 0xF7, 0xFE, 0xF9, 0x04, 0xF0, 0x96, 0xF8,
+ 0xFF, 0xF7, 0xCA, 0xF9, 0x04, 0xF0, 0x44, 0xFC, 0x07, 0x21, 0x0A, 0x20, 0x00, 0xF0, 0xBE, 0xF8,
+ 0x07, 0x21, 0x0B, 0x20, 0x00, 0xF0, 0xBA, 0xF8, 0xFE, 0xF7, 0xE0, 0xFE, 0xFE, 0xF7, 0x84, 0xFD,
+ 0x04, 0xA8, 0xFF, 0xF7, 0xE0, 0xF8, 0x0A, 0xA9, 0x07, 0xA8, 0xFE, 0xF7, 0x7D, 0xFF, 0x04, 0xA8,
+ 0x00, 0x90, 0x07, 0xA8, 0x02, 0x90, 0x0A, 0xA8, 0x03, 0x90, 0x68, 0x46, 0x04, 0xF0, 0x28, 0xFE,
+ 0x02, 0x21, 0x00, 0x20, 0x00, 0xF0, 0xA2, 0xF8, 0x05, 0xF0, 0x1C, 0xFD, 0x00, 0x78, 0xC0, 0x07,
+ 0x01, 0xD1, 0xFE, 0xF7, 0xE2, 0xFE, 0xFF, 0xF7, 0x25, 0xF9, 0xFF, 0xF7, 0x13, 0xFE, 0x04, 0xF0,
+ 0xAF, 0xF8, 0x10, 0x4D, 0x01, 0xAA, 0x69, 0x46, 0x28, 0x46, 0x04, 0xF0, 0x25, 0xF9, 0x0C, 0x4C,
+ 0x01, 0x28, 0x19, 0xD0, 0x00, 0x21, 0x20, 0x20, 0x27, 0xE0, 0x00, 0x00, 0x00, 0x90, 0xD0, 0x03,
+ 0x34, 0x7F, 0x10, 0x00, 0x08, 0x84, 0x10, 0x00, 0xF0, 0x9F, 0x01, 0x00, 0x24, 0x07, 0x10, 0x00,
+ 0xF8, 0x5B, 0x01, 0x20, 0x84, 0x5A, 0x10, 0x00, 0xF0, 0xBF, 0x01, 0x00, 0xFC, 0x4C, 0x01, 0x20,
+ 0x20, 0x07, 0x10, 0x00, 0xF0, 0xEF, 0x01, 0x00, 0x00, 0x98, 0xB0, 0xF5, 0x26, 0x7F, 0xE1, 0xD1,
+ 0x4F, 0xF4, 0x26, 0x62, 0x29, 0x46, 0x20, 0x68, 0x05, 0xF0, 0xAC, 0xFB, 0x20, 0x68, 0x04, 0xF0,
+ 0x0E, 0xF9, 0x01, 0x28, 0x03, 0xD0, 0x00, 0x21, 0x21, 0x20, 0xFF, 0xF7, 0xF0, 0xF8, 0xFF, 0xF7,
+ 0x3A, 0xFE, 0x04, 0xF0, 0xA7, 0xFB, 0x05, 0x00, 0x2D, 0xD0, 0x01, 0x21, 0x01, 0x2D, 0x02, 0xD0,
+ 0x2E, 0x20, 0xFF, 0xF7, 0xE4, 0xF8, 0x20, 0x68, 0x90, 0xF8, 0x3D, 0x10, 0xA9, 0x42, 0x02, 0xD0,
+ 0x2F, 0x20, 0xFF, 0xF7, 0xDC, 0xF8, 0xFF, 0xF7, 0x8D, 0xFE, 0x00, 0xF0, 0x5B, 0xF8, 0xFF, 0xF7,
+ 0x10, 0xFF, 0x20, 0x68, 0x90, 0xF8, 0x60, 0x03, 0xC1, 0x07, 0x0F, 0xD0, 0x81, 0x07, 0x0D, 0xD5,
+ 0x00, 0x21, 0x01, 0x23, 0x40, 0x09, 0x1A, 0x46, 0x00, 0x91, 0x04, 0xF0, 0xD6, 0xFB, 0x20, 0x68,
+ 0x00, 0x21, 0x90, 0xF8, 0x60, 0x03, 0x40, 0x09, 0x04, 0xF0, 0xF7, 0xFB, 0x0D, 0xB0, 0xBD, 0xE8,
+ 0x30, 0x40, 0xFF, 0xF7, 0x9F, 0xB8, 0x00, 0x21, 0x2D, 0x20, 0xFF, 0xF7, 0x05, 0xF9, 0xDA, 0xE7,
+ 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20,
+ 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09,
+ 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0x49, 0x07, 0x09, 0x0E,
+ 0x00, 0x28, 0x06, 0xDA, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0x80, 0xF8, 0x14, 0x1D,
+ 0x70, 0x47, 0x00, 0xF1, 0xE0, 0x20, 0x80, 0xF8, 0x00, 0x14, 0x70, 0x47, 0x70, 0xB5, 0x0D, 0x46,
+ 0x04, 0x46, 0xFF, 0xF7, 0xE0, 0xFF, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xE7, 0xFF, 0x04, 0xF0,
+ 0x1F, 0x01, 0x01, 0x20, 0x88, 0x40, 0x61, 0x09, 0x89, 0x00, 0x01, 0xF1, 0xE0, 0x21, 0xC1, 0xF8,
+ 0x00, 0x01, 0x70, 0xBD, 0x10, 0xB5, 0x04, 0xF0, 0x2B, 0xFE, 0x00, 0x23, 0x01, 0x22, 0x19, 0x46,
+ 0x18, 0x46, 0x05, 0xF0, 0xCB, 0xF9, 0x00, 0x23, 0x01, 0x22, 0x19, 0x46, 0x10, 0x46, 0x05, 0xF0,
+ 0xC5, 0xF9, 0x00, 0x23, 0x1A, 0x46, 0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0xBF, 0xF9, 0x00, 0x23,
+ 0x1A, 0x46, 0x01, 0x21, 0x03, 0x20, 0x05, 0xF0, 0xB9, 0xF9, 0x00, 0x23, 0x1A, 0x46, 0x01, 0x21,
+ 0x04, 0x20, 0x05, 0xF0, 0xB3, 0xF9, 0x17, 0x48, 0x00, 0x68, 0x01, 0x7C, 0xA5, 0x29, 0x08, 0xD0,
+ 0x4F, 0xF4, 0xFA, 0x40, 0x05, 0xF0, 0x94, 0xF9, 0x00, 0x21, 0x28, 0x20, 0xFF, 0xF7, 0x9C, 0xF8,
+ 0x02, 0xE0, 0x40, 0x69, 0x05, 0xF0, 0x8C, 0xF9, 0x04, 0x21, 0x02, 0x20, 0xFF, 0xF7, 0xB6, 0xFF,
+ 0x04, 0x21, 0x03, 0x20, 0xFF, 0xF7, 0xB2, 0xFF, 0x04, 0x21, 0x08, 0x46, 0xFF, 0xF7, 0xAE, 0xFF,
+ 0x04, 0x21, 0x05, 0x20, 0xFF, 0xF7, 0xAA, 0xFF, 0x04, 0x21, 0x06, 0x20, 0xFF, 0xF7, 0xA6, 0xFF,
+ 0x01, 0x21, 0x09, 0x20, 0xFF, 0xF7, 0xA2, 0xFF, 0x04, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x0F, 0x20,
+ 0x9C, 0xE7, 0x00, 0x00, 0x24, 0x07, 0x10, 0x00, 0x88, 0x42, 0x00, 0xD3, 0x08, 0x46, 0x90, 0x42,
+ 0x00, 0xD3, 0x10, 0x46, 0x70, 0x47, 0x88, 0x42, 0x00, 0xD8, 0x08, 0x46, 0x90, 0x42, 0x00, 0xD8,
+ 0x10, 0x46, 0x70, 0x47, 0x88, 0x42, 0x00, 0xD3, 0x08, 0x46, 0x70, 0x47, 0x88, 0x42, 0x00, 0xD8,
+ 0x08, 0x46, 0x70, 0x47, 0x02, 0x46, 0x00, 0x20, 0x4F, 0xF0, 0x80, 0x41, 0x00, 0xE0, 0x89, 0x08,
+ 0x91, 0x42, 0xFC, 0xD8, 0x07, 0xE0, 0x43, 0x18, 0x93, 0x42, 0x02, 0xD8, 0xD2, 0x1A, 0x00, 0xEB,
+ 0x41, 0x00, 0x40, 0x08, 0x89, 0x08, 0x00, 0x29, 0xF5, 0xD1, 0x82, 0x42, 0x00, 0xD9, 0x40, 0x1C,
+ 0x70, 0x47, 0x10, 0xB5, 0x5A, 0x43, 0x02, 0x9C, 0x06, 0xE0, 0x00, 0xBF, 0x50, 0xF8, 0x22, 0x30,
+ 0x93, 0xFB, 0xF4, 0xF3, 0x41, 0xF8, 0x22, 0x30, 0x52, 0x1E, 0xF7, 0xD2, 0x10, 0xBD, 0x10, 0xB5,
+ 0x5A, 0x43, 0x02, 0x9C, 0x05, 0xE0, 0x00, 0xBF, 0x50, 0xF8, 0x22, 0x30, 0x63, 0x43, 0x41, 0xF8,
+ 0x22, 0x30, 0x52, 0x1E, 0xF8, 0xD2, 0x10, 0xBD, 0x30, 0xB5, 0x03, 0x9C, 0x63, 0x43, 0x06, 0xE0,
+ 0x50, 0xF8, 0x23, 0x40, 0x51, 0xF8, 0x23, 0x50, 0x2C, 0x44, 0x42, 0xF8, 0x23, 0x40, 0x5B, 0x1E,
+ 0xF6, 0xD2, 0x30, 0xBD, 0x30, 0xB5, 0x03, 0x9C, 0x63, 0x43, 0x06, 0xE0, 0x50, 0xF8, 0x23, 0x40,
+ 0x51, 0xF8, 0x23, 0x50, 0x64, 0x1B, 0x42, 0xF8, 0x23, 0x40, 0x5B, 0x1E, 0xF6, 0xD2, 0x30, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0x46, 0xDD, 0xE9, 0x09, 0x06, 0xDD, 0xF8, 0x34, 0xE0, 0x8A, 0x46,
+ 0x82, 0x42, 0x26, 0xD1, 0x00, 0x20, 0x22, 0xE0, 0x00, 0xFB, 0x02, 0xF1, 0x0B, 0xEB, 0x81, 0x09,
+ 0x0B, 0x9D, 0x00, 0xFB, 0x0E, 0xF1, 0x00, 0x24, 0x05, 0xEB, 0x81, 0x05, 0x14, 0xE0, 0x00, 0x21,
+ 0x0F, 0xE0, 0x00, 0xBF, 0x01, 0xFB, 0x06, 0xF8, 0x03, 0xEB, 0x88, 0x08, 0x59, 0xF8, 0x21, 0xC0,
+ 0x55, 0xF8, 0x24, 0x70, 0x58, 0xF8, 0x24, 0x80, 0x49, 0x1C, 0x0C, 0xFB, 0x08, 0x77, 0x45, 0xF8,
+ 0x24, 0x70, 0x91, 0x42, 0xEE, 0xDB, 0x64, 0x1C, 0xB4, 0x42, 0xE8, 0xDB, 0x40, 0x1C, 0x50, 0x45,
+ 0xDA, 0xDB, 0xBD, 0xE8, 0xF0, 0x8F, 0x10, 0xB5, 0x00, 0x23, 0x1C, 0x46, 0x42, 0xB1, 0x02, 0x78,
+ 0x52, 0x1C, 0xD2, 0xB2, 0x02, 0x70, 0x8A, 0x42, 0x03, 0xD9, 0x04, 0x70, 0x01, 0x23, 0x00, 0xE0,
+ 0x04, 0x70, 0x18, 0x46, 0x10, 0xBD, 0x30, 0xB5, 0x00, 0x24, 0x01, 0x23, 0x05, 0xE0, 0x0C, 0x44,
+ 0xE4, 0x1C, 0x04, 0xF0, 0x03, 0x05, 0x64, 0x1B, 0x5B, 0x1C, 0x93, 0x42, 0xF7, 0xDD, 0x00, 0xEB,
+ 0x44, 0x00, 0x30, 0xBD, 0x70, 0xB5, 0x05, 0x46, 0x18, 0x46, 0x00, 0x24, 0x0E, 0xE0, 0x2B, 0x5D,
+ 0x58, 0x40, 0x08, 0x23, 0x06, 0x06, 0x02, 0xD5, 0x82, 0xEA, 0x40, 0x00, 0x00, 0xE0, 0x40, 0x00,
+ 0x5B, 0x1E, 0xC0, 0xB2, 0x13, 0xF0, 0xFF, 0x03, 0xF4, 0xD1, 0x64, 0x1C, 0x8C, 0x42, 0xEE, 0xD3,
+ 0x70, 0xBD, 0x00, 0x00, 0x88, 0x42, 0x01, 0xDD, 0x08, 0x46, 0x70, 0x47, 0x00, 0x28, 0xFC, 0xDA,
+ 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x04, 0xE0, 0x00, 0xEB, 0x82, 0x03, 0x53, 0xF8, 0x04, 0x4C,
+ 0x1C, 0x60, 0x52, 0x1E, 0xF8, 0xD1, 0x09, 0x68, 0x01, 0x60, 0x10, 0xBD, 0x10, 0xB5, 0x03, 0xE0,
+ 0x00, 0xEB, 0x82, 0x03, 0x0C, 0x68, 0x1C, 0x60, 0x52, 0x1E, 0xF9, 0xD2, 0x10, 0xBD, 0x30, 0xB5,
+ 0x06, 0xE0, 0x00, 0xBF, 0x00, 0xEB, 0xC2, 0x03, 0x73, 0xE9, 0x02, 0x45, 0xC3, 0xE9, 0x02, 0x45,
+ 0x52, 0x1E, 0xF7, 0xD1, 0xD1, 0xE9, 0x00, 0x21, 0xC0, 0xE9, 0x00, 0x21, 0x30, 0xBD, 0x10, 0xB5,
+ 0x53, 0x88, 0x4C, 0x88, 0x1B, 0x1B, 0x43, 0x80, 0x12, 0x88, 0x09, 0x88, 0x51, 0x1A, 0x01, 0x80,
+ 0x10, 0xBD, 0x08, 0xB5, 0x0A, 0x46, 0x01, 0x46, 0x68, 0x46, 0xFF, 0xF7, 0xF0, 0xFF, 0xBD, 0xF9,
+ 0x00, 0x10, 0xBD, 0xF9, 0x02, 0x00, 0x49, 0x43, 0x00, 0xFB, 0x00, 0x10, 0x08, 0xBD, 0x10, 0xB5,
+ 0x88, 0x42, 0x02, 0x9C, 0x01, 0xDC, 0x20, 0x46, 0x10, 0xBD, 0x90, 0x42, 0x01, 0xDB, 0x18, 0x46,
+ 0x10, 0xBD, 0x8A, 0x42, 0x00, 0xD1, 0x52, 0x1C, 0x40, 0x1A, 0xE3, 0x1A, 0x58, 0x43, 0x51, 0x1A,
+ 0x90, 0xFB, 0xF1, 0xF0, 0x20, 0x1A, 0x10, 0xBD, 0x10, 0xB5, 0x00, 0x2A, 0x03, 0xD0, 0x43, 0x1A,
+ 0x93, 0x42, 0x01, 0xDD, 0x88, 0x18, 0x10, 0xBD, 0x54, 0x42, 0xA3, 0x42, 0xFB, 0xDA, 0x88, 0x1A,
+ 0x10, 0xBD, 0x91, 0x42, 0x01, 0xD1, 0x00, 0xB2, 0x70, 0x47, 0x50, 0x43, 0xB0, 0xFB, 0xF1, 0xF0,
+ 0x00, 0xB2, 0x90, 0x42, 0xF7, 0xD9, 0x10, 0x46, 0xF5, 0xE7, 0x70, 0xB5, 0x0B, 0x00, 0x02, 0x46,
+ 0x3D, 0xD0, 0x1F, 0x4C, 0x20, 0x68, 0x46, 0x8E, 0x85, 0x8E, 0xB2, 0xF9, 0x02, 0x00, 0x31, 0xB2,
+ 0xFF, 0xF7, 0x80, 0xFF, 0x58, 0x80, 0xB2, 0xF9, 0x00, 0x00, 0x29, 0xB2, 0xFF, 0xF7, 0x7A, 0xFF,
+ 0x18, 0x80, 0x21, 0x68, 0x91, 0xF8, 0x36, 0x10, 0x49, 0x07, 0x02, 0xD5, 0x59, 0x88, 0x71, 0x1A,
+ 0x59, 0x80, 0x21, 0x68, 0x91, 0xF8, 0x36, 0x10, 0x89, 0x07, 0x01, 0xD5, 0x28, 0x1A, 0x18, 0x80,
+ 0x20, 0x68, 0x90, 0xF8, 0x36, 0x10, 0x09, 0x07, 0x10, 0xD5, 0xB0, 0xF8, 0x37, 0x20, 0xB3, 0xF9,
+ 0x02, 0x00, 0x31, 0x46, 0xFF, 0xF7, 0xC5, 0xFF, 0x58, 0x80, 0x20, 0x68, 0x29, 0x46, 0xB0, 0xF8,
+ 0x39, 0x20, 0xB3, 0xF9, 0x00, 0x00, 0xFF, 0xF7, 0xBC, 0xFF, 0x18, 0x80, 0x20, 0x68, 0x90, 0xF8,
+ 0x36, 0x00, 0xC0, 0x07, 0x03, 0xD0, 0x58, 0x88, 0x19, 0x88, 0x59, 0x80, 0x18, 0x80, 0x70, 0xBD,
+ 0x20, 0x07, 0x10, 0x00, 0x73, 0xB5, 0x1D, 0x24, 0xDD, 0xE9, 0x00, 0x56, 0x22, 0x46, 0x01, 0x20,
+ 0x00, 0x21, 0x05, 0xF0, 0x18, 0xF9, 0x28, 0x40, 0x31, 0x40, 0x08, 0x43, 0x01, 0xD1, 0x64, 0x1E,
+ 0xF4, 0xD5, 0x08, 0x21, 0x68, 0x46, 0x03, 0xF0, 0x85, 0xFE, 0xFF, 0x49, 0xC0, 0xB2, 0x09, 0x68,
+ 0x91, 0xF8, 0xE7, 0x10, 0xC1, 0xF3, 0x41, 0x11, 0x02, 0x29, 0x0E, 0xD3, 0x10, 0xF0, 0x03, 0x00,
+ 0x05, 0xD0, 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x1F, 0x20, 0x0A, 0xE0, 0x0F, 0x20,
+ 0x08, 0xE0, 0x7F, 0x20, 0x06, 0xE0, 0x3F, 0x20, 0x04, 0xE0, 0xC0, 0x07, 0x01, 0xD0, 0x07, 0x20,
+ 0x00, 0xE0, 0x03, 0x20, 0x00, 0x21, 0x62, 0x1C, 0x05, 0xF0, 0xED, 0xF8, 0xDD, 0xE9, 0x00, 0x23,
+ 0x10, 0x43, 0x19, 0x43, 0xCD, 0xE9, 0x00, 0x01, 0x7C, 0xBD, 0x10, 0xB5, 0xEB, 0x4C, 0x50, 0x28,
+ 0x14, 0xD0, 0x08, 0xDC, 0x10, 0x28, 0x11, 0xD0, 0x11, 0x28, 0x25, 0xD0, 0x12, 0x28, 0x23, 0xD0,
+ 0x13, 0x28, 0x06, 0xD1, 0x20, 0xE0, 0x51, 0x28, 0x1E, 0xD0, 0x52, 0x28, 0x1C, 0xD0, 0x53, 0x28,
+ 0x1A, 0xD0, 0x00, 0x20, 0xC4, 0xE9, 0x02, 0x00, 0x01, 0x46, 0x1B, 0xE0, 0x02, 0xF0, 0x5D, 0xFC,
+ 0xC4, 0xE9, 0x02, 0x01, 0x02, 0xF0, 0x5B, 0xFC, 0xC4, 0xE9, 0x04, 0x01, 0xDA, 0x48, 0x00, 0x68,
+ 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0, 0x60, 0x0F, 0x0E, 0xD0, 0xD4, 0xE9, 0x02, 0x01, 0xFF, 0xF7,
+ 0x99, 0xFF, 0xC4, 0xE9, 0x02, 0x01, 0x07, 0xE0, 0x02, 0xF0, 0x47, 0xFC, 0xC4, 0xE9, 0x02, 0x01,
+ 0x02, 0xF0, 0x45, 0xFC, 0xC4, 0xE9, 0x04, 0x01, 0xD0, 0x48, 0x08, 0x21, 0x08, 0x30, 0x03, 0xF0,
+ 0x21, 0xFE, 0x20, 0x60, 0xCD, 0x48, 0x08, 0x21, 0x10, 0x30, 0x03, 0xF0, 0x1B, 0xFE, 0x60, 0x60,
+ 0x10, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x08, 0x21, 0xDD, 0xE9, 0x0F, 0xBA, 0x68, 0x46, 0x03, 0xF0,
+ 0x11, 0xFE, 0x81, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x03, 0xF0, 0x0C, 0xFE, 0x07, 0x46, 0x00, 0x24,
+ 0x20, 0x46, 0x3A, 0xE0, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, 0x05, 0xF0, 0x8C, 0xF8, 0xDD, 0xE9,
+ 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x2D, 0xD0, 0x00, 0x25, 0x2E, 0x46, 0x27, 0xE0,
+ 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x05, 0xF0, 0x7E, 0xF8, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40,
+ 0x19, 0x40, 0x08, 0x43, 0x1B, 0xD0, 0x11, 0x98, 0x60, 0xB1, 0x04, 0xFB, 0x07, 0xF0, 0x0B, 0xEB,
+ 0x05, 0x01, 0x41, 0x56, 0x32, 0x46, 0x01, 0xEB, 0x0A, 0x03, 0x21, 0x46, 0x0E, 0x98, 0x03, 0xF0,
+ 0x5C, 0xFA, 0x0B, 0xE0, 0x32, 0x46, 0x21, 0x46, 0x0E, 0x98, 0x03, 0xF0, 0x4B, 0xFA, 0x04, 0xFB,
+ 0x07, 0xF1, 0x0B, 0xEB, 0x05, 0x02, 0xA0, 0xEB, 0x0A, 0x00, 0x88, 0x54, 0x6D, 0x1C, 0x76, 0x1C,
+ 0xBD, 0x42, 0xD5, 0xDB, 0x64, 0x1C, 0x08, 0xF1, 0x01, 0x00, 0x80, 0x46, 0x4C, 0x45, 0xC1, 0xDB,
+ 0xBD, 0xE8, 0xFF, 0x9F, 0x2D, 0xE9, 0xFF, 0x5F, 0x84, 0xB0, 0x08, 0x21, 0xDD, 0xE9, 0x12, 0xAB,
+ 0x04, 0xA8, 0x03, 0xF0, 0xBF, 0xFD, 0x81, 0x46, 0x08, 0x21, 0x06, 0xA8, 0x03, 0xF0, 0xBA, 0xFD,
+ 0x80, 0x46, 0x00, 0x25, 0x0A, 0xF1, 0x48, 0x00, 0x02, 0x90, 0x20, 0x30, 0x01, 0x90, 0x48, 0x38,
+ 0x2C, 0x46, 0x2F, 0x46, 0x2E, 0x46, 0x00, 0x90, 0x34, 0xE0, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x05, 0xF0, 0x31, 0xF8, 0xDD, 0xE9, 0x04, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x27, 0xD0,
+ 0x16, 0x98, 0x90, 0xB1, 0x1B, 0xF8, 0x05, 0x10, 0x14, 0x98, 0x08, 0x44, 0xC2, 0xB2, 0x39, 0x46,
+ 0x02, 0x98, 0x03, 0xF0, 0x7E, 0xFA, 0x05, 0xEB, 0x09, 0x01, 0x41, 0x44, 0x1B, 0xF9, 0x01, 0x20,
+ 0x39, 0x46, 0x50, 0x46, 0x03, 0xF0, 0x4D, 0xFA, 0x10, 0xE0, 0x39, 0x46, 0x02, 0x98, 0x03, 0xF0,
+ 0x6E, 0xFA, 0x14, 0x99, 0x40, 0x1A, 0x0B, 0xF8, 0x05, 0x00, 0x39, 0x46, 0x50, 0x46, 0x03, 0xF0,
+ 0x39, 0xFA, 0x05, 0xEB, 0x09, 0x02, 0x42, 0x44, 0x0B, 0xF8, 0x02, 0x00, 0x6D, 0x1C, 0xED, 0xB2,
+ 0x7F, 0x1C, 0xFF, 0xB2, 0x4D, 0x45, 0xC8, 0xDB, 0x38, 0xE0, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x04, 0xF0, 0xF9, 0xFF, 0xDD, 0xE9, 0x06, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x2B, 0xD0,
+ 0x16, 0x98, 0xA0, 0xB1, 0x04, 0xEB, 0x09, 0x01, 0x15, 0x98, 0x1B, 0xF8, 0x01, 0x10, 0x08, 0x44,
+ 0xC2, 0xB2, 0x31, 0x46, 0x01, 0x98, 0x03, 0xF0, 0x44, 0xFA, 0x04, 0xEB, 0x49, 0x01, 0x41, 0x44,
+ 0x1B, 0xF9, 0x01, 0x20, 0x31, 0x46, 0x00, 0x98, 0x03, 0xF0, 0x13, 0xFA, 0x12, 0xE0, 0x31, 0x46,
+ 0x01, 0x98, 0x03, 0xF0, 0x34, 0xFA, 0x15, 0x99, 0x04, 0xEB, 0x09, 0x02, 0x40, 0x1A, 0x0B, 0xF8,
+ 0x02, 0x00, 0x31, 0x46, 0x00, 0x98, 0x03, 0xF0, 0xFD, 0xF9, 0x04, 0xEB, 0x49, 0x02, 0x42, 0x44,
+ 0x0B, 0xF8, 0x02, 0x00, 0x64, 0x1C, 0xE4, 0xB2, 0x76, 0x1C, 0xF6, 0xB2, 0x44, 0x45, 0xC4, 0xDB,
+ 0x08, 0xB0, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFF, 0x5F, 0x08, 0x21, 0xDD, 0xE9, 0x0E, 0xBA,
+ 0x68, 0x46, 0x03, 0xF0, 0x2F, 0xFD, 0x81, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x03, 0xF0, 0x2A, 0xFD,
+ 0x07, 0x46, 0x00, 0x24, 0x20, 0x46, 0x29, 0xE0, 0x42, 0x46, 0x01, 0x20, 0x00, 0x21, 0x04, 0xF0,
+ 0xAA, 0xFF, 0xDD, 0xE9, 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x1C, 0xD0, 0x00, 0x25,
+ 0x2E, 0x46, 0x16, 0xE0, 0x32, 0x46, 0x01, 0x20, 0x00, 0x21, 0x04, 0xF0, 0x9C, 0xFF, 0xDD, 0xE9,
+ 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x0A, 0xD0, 0x32, 0x46, 0x21, 0x46, 0x58, 0x46,
+ 0x03, 0xF0, 0x78, 0xF9, 0x04, 0xFB, 0x07, 0x52, 0x80, 0x00, 0x2A, 0xF8, 0x12, 0x00, 0x6D, 0x1C,
+ 0x76, 0x1C, 0xBD, 0x42, 0xE6, 0xDB, 0x64, 0x1C, 0x08, 0xF1, 0x01, 0x00, 0x80, 0x46, 0x4C, 0x45,
+ 0xD2, 0xDB, 0x2D, 0xE7, 0x2D, 0xE9, 0xFF, 0x5F, 0x08, 0x21, 0xDD, 0xE9, 0x0E, 0x9B, 0x68, 0x46,
+ 0x03, 0xF0, 0xF0, 0xFC, 0x82, 0x46, 0x08, 0x21, 0x02, 0xA8, 0x03, 0xF0, 0xEB, 0xFC, 0x00, 0x25,
+ 0x80, 0x46, 0x2C, 0x46, 0x2F, 0x46, 0x2E, 0x46, 0x3D, 0xE0, 0x3A, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x04, 0xF0, 0x69, 0xFF, 0xDD, 0xE9, 0x00, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43, 0x30, 0xD0,
+ 0x39, 0x46, 0x09, 0xF1, 0x48, 0x00, 0x03, 0xF0, 0xBA, 0xF9, 0x27, 0x49, 0x99, 0xF8, 0x92, 0xC0,
+ 0x0A, 0x68, 0x92, 0xF8, 0x43, 0x31, 0x92, 0xF8, 0x42, 0x21, 0x03, 0xF0, 0x0F, 0x01, 0x49, 0x1C,
+ 0x0C, 0xFB, 0x01, 0xFC, 0x01, 0x21, 0x01, 0xEB, 0x13, 0x13, 0x00, 0xFB, 0x03, 0xC3, 0x99, 0xF8,
+ 0x90, 0x00, 0x01, 0xEB, 0x12, 0x11, 0x00, 0xFB, 0x01, 0x30, 0x10, 0x99, 0x19, 0xB9, 0x4F, 0xF6,
+ 0xFF, 0x71, 0x01, 0xEA, 0x80, 0x00, 0x2B, 0xF8, 0x15, 0x00, 0x39, 0x46, 0x48, 0x46, 0x03, 0xF0,
+ 0x69, 0xF9, 0x05, 0xEB, 0x0A, 0x02, 0x80, 0x00, 0x42, 0x44, 0x6D, 0x1C, 0x2B, 0xF8, 0x12, 0x00,
+ 0xED, 0xB2, 0x7F, 0x1C, 0xFF, 0xB2, 0x55, 0x45, 0xBF, 0xDB, 0x44, 0xE0, 0x32, 0x46, 0x01, 0x20,
+ 0x00, 0x21, 0x04, 0xF0, 0x28, 0xFF, 0xDD, 0xE9, 0x02, 0x23, 0x10, 0x40, 0x19, 0x40, 0x08, 0x43,
+ 0x37, 0xD0, 0x31, 0x46, 0x09, 0xF1, 0x68, 0x00, 0x03, 0xF0, 0x79, 0xF9, 0x06, 0x49, 0x99, 0xF8,
+ 0x93, 0x50, 0x0B, 0x68, 0x93, 0xF8, 0x48, 0x11, 0x01, 0xF0, 0x0F, 0x02, 0x52, 0x1C, 0x55, 0x43,
+ 0x01, 0x22, 0x02, 0xEB, 0x11, 0x11, 0x03, 0xE0, 0x20, 0x07, 0x10, 0x00, 0x70, 0x07, 0x10, 0x00,
+ 0x00, 0xFB, 0x01, 0x51, 0x93, 0xF8, 0x47, 0x31, 0x99, 0xF8, 0x91, 0x00, 0x02, 0xEB, 0x13, 0x12,
+ 0x00, 0xFB, 0x02, 0x10, 0x10, 0x99, 0x19, 0xB9, 0x4F, 0xF6, 0xFF, 0x71, 0x01, 0xEA, 0x80, 0x00,
+ 0x04, 0xEB, 0x0A, 0x02, 0x31, 0x46, 0x2B, 0xF8, 0x12, 0x00, 0x09, 0xF1, 0x20, 0x00, 0x03, 0xF0,
+ 0x21, 0xF9, 0x04, 0xEB, 0x4A, 0x02, 0x80, 0x00, 0x42, 0x44, 0x64, 0x1C, 0x2B, 0xF8, 0x12, 0x00,
+ 0xE4, 0xB2, 0x76, 0x1C, 0xF6, 0xB2, 0x44, 0x45, 0xB8, 0xDB, 0x91, 0xE6, 0x2D, 0xE9, 0xF0, 0x43,
+ 0x89, 0x46, 0x00, 0x27, 0x85, 0xB0, 0x90, 0x46, 0x04, 0x46, 0x3E, 0x46, 0xFC, 0x21, 0x04, 0xF0,
+ 0x90, 0xFF, 0xFE, 0x4D, 0xB8, 0xF1, 0x01, 0x0F, 0x28, 0x78, 0x20, 0x71, 0x28, 0x79, 0x60, 0x71,
+ 0xFB, 0x48, 0x90, 0xF8, 0x82, 0x1B, 0xA1, 0x71, 0x90, 0xF8, 0x83, 0x1B, 0xE1, 0x71, 0x90, 0xF8,
+ 0x84, 0x1B, 0xA1, 0x72, 0x90, 0xF8, 0x85, 0x1B, 0xE1, 0x72, 0x90, 0xF8, 0x80, 0x1B, 0x21, 0x73,
+ 0x90, 0xF8, 0x81, 0x0B, 0x60, 0x73, 0x08, 0xD1, 0xF2, 0x48, 0x00, 0x68, 0x81, 0x7F, 0xA5, 0x29,
+ 0x03, 0xD1, 0x90, 0xF9, 0x1F, 0x70, 0x90, 0xF9, 0x20, 0x60, 0x04, 0xF1, 0x10, 0x00, 0xCD, 0xE9,
+ 0x01, 0x07, 0xED, 0x48, 0x00, 0x90, 0x00, 0x21, 0xCD, 0xE9, 0x03, 0x61, 0x05, 0xF1, 0x08, 0x00,
+ 0x0F, 0xC8, 0xFF, 0xF7, 0x57, 0xFE, 0xA5, 0x20, 0x20, 0x70, 0x12, 0x20, 0x60, 0x70, 0xA4, 0xF8,
+ 0x02, 0x90, 0xD5, 0xE9, 0x00, 0x01, 0x08, 0x44, 0x13, 0x30, 0x80, 0x08, 0x05, 0xB0, 0xBD, 0xE8,
+ 0xF0, 0x83, 0x2D, 0xE9, 0xF0, 0x43, 0x89, 0x46, 0x00, 0x27, 0x85, 0xB0, 0x90, 0x46, 0x04, 0x46,
+ 0x3E, 0x46, 0xFC, 0x21, 0x04, 0xF0, 0x45, 0xFF, 0xD8, 0x4D, 0xB8, 0xF1, 0x01, 0x0F, 0x28, 0x78,
+ 0x20, 0x71, 0x28, 0x79, 0x60, 0x71, 0xD6, 0x48, 0x90, 0xF8, 0x1A, 0x1C, 0xA1, 0x71, 0x90, 0xF8,
+ 0x1B, 0x1C, 0xE1, 0x71, 0x90, 0xF8, 0x1C, 0x1C, 0xA1, 0x72, 0x90, 0xF8, 0x1D, 0x1C, 0xE1, 0x72,
+ 0x90, 0xF8, 0x18, 0x1C, 0x21, 0x73, 0x90, 0xF8, 0x19, 0x0C, 0x60, 0x73, 0x09, 0xD1, 0xCD, 0x48,
+ 0x00, 0x68, 0x90, 0xF8, 0x21, 0x10, 0xA5, 0x29, 0x03, 0xD1, 0x10, 0xF9, 0x22, 0x7F, 0x90, 0xF9,
+ 0x01, 0x60, 0x04, 0xF1, 0x10, 0x00, 0xCD, 0xE9, 0x01, 0x07, 0xC7, 0x48, 0x00, 0x21, 0x98, 0x30,
+ 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x61, 0x05, 0xF1, 0x08, 0x00, 0x0F, 0xC8, 0xFF, 0xF7, 0x0A, 0xFE,
+ 0xA5, 0x20, 0x20, 0x70, 0x13, 0x20, 0x60, 0x70, 0xA4, 0xF8, 0x02, 0x90, 0xD5, 0xE9, 0x00, 0x01,
+ 0x08, 0x44, 0x13, 0x30, 0x80, 0x08, 0xB1, 0xE7, 0x70, 0xB5, 0x0E, 0x46, 0x04, 0x46, 0x00, 0x25,
+ 0xFF, 0xF7, 0x63, 0xFD, 0x10, 0x2C, 0x06, 0xD0, 0x11, 0x2C, 0x08, 0xD0, 0x12, 0x2C, 0x0C, 0xD0,
+ 0x13, 0x2C, 0x08, 0xD1, 0x0D, 0xE0, 0x30, 0x46, 0x00, 0xF0, 0x7D, 0xF8, 0x02, 0xE0, 0x30, 0x46,
+ 0x00, 0xF0, 0x9C, 0xF8, 0x05, 0x46, 0x28, 0x46, 0x70, 0xBD, 0x30, 0x46, 0x00, 0xF0, 0xB8, 0xF8,
+ 0xF8, 0xE7, 0x30, 0x46, 0x00, 0xF0, 0xEE, 0xF8, 0xF4, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x1E, 0x46,
+ 0x17, 0x46, 0x88, 0x46, 0x05, 0x46, 0x00, 0x24, 0xFF, 0xF7, 0x3F, 0xFD, 0x10, 0x2D, 0x06, 0xD0,
+ 0x11, 0x2D, 0x0A, 0xD0, 0x12, 0x2D, 0x11, 0xD0, 0x13, 0x2D, 0x0C, 0xD1, 0x14, 0xE0, 0x32, 0x46,
+ 0x39, 0x46, 0x40, 0x46, 0x00, 0xF0, 0x11, 0xF9, 0x04, 0xE0, 0x32, 0x46, 0x39, 0x46, 0x40, 0x46,
+ 0x00, 0xF0, 0x4A, 0xF9, 0x04, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x32, 0x46, 0x39, 0x46,
+ 0x40, 0x46, 0xFF, 0xF7, 0x23, 0xFF, 0xF5, 0xE7, 0x32, 0x46, 0x39, 0x46, 0x40, 0x46, 0xFF, 0xF7,
+ 0x68, 0xFF, 0xEF, 0xE7, 0xFE, 0xB5, 0x17, 0x46, 0x06, 0x46, 0x0D, 0x46, 0xFF, 0xF7, 0x15, 0xFD,
+ 0x8E, 0x48, 0x05, 0xF1, 0x10, 0x04, 0x50, 0x2E, 0x01, 0x78, 0x29, 0x71, 0x01, 0x79, 0x69, 0x71,
+ 0x07, 0xD0, 0x51, 0x2E, 0x07, 0xD0, 0x8D, 0x49, 0x52, 0x2E, 0x0F, 0xD0, 0x53, 0x2E, 0x25, 0xD1,
+ 0x13, 0xE0, 0x87, 0x49, 0x00, 0xE0, 0x8A, 0x49, 0xCD, 0xE9, 0x00, 0x14, 0x84, 0x68, 0x0C, 0x30,
+ 0x90, 0xE8, 0x0E, 0x00, 0x20, 0x46, 0xFF, 0xF7, 0x1E, 0xFE, 0x17, 0xE0, 0x09, 0x68, 0x82, 0x4A,
+ 0x91, 0xF8, 0x42, 0x11, 0x01, 0xF0, 0x01, 0x01, 0x06, 0xE0, 0x09, 0x68, 0x7E, 0x4A, 0x91, 0xF8,
+ 0x92, 0x19, 0x98, 0x32, 0x01, 0xF0, 0x01, 0x01, 0x00, 0x92, 0xCD, 0xE9, 0x01, 0x41, 0x84, 0x68,
+ 0x0C, 0x30, 0x90, 0xE8, 0x0E, 0x00, 0x20, 0x46, 0xFF, 0xF7, 0x44, 0xFE, 0xA5, 0x20, 0x28, 0x70,
+ 0x6E, 0x70, 0x6F, 0x80, 0xFE, 0xBD, 0x1F, 0xB5, 0x70, 0x49, 0x02, 0x79, 0x0B, 0x68, 0x9A, 0x42,
+ 0x03, 0xD1, 0x42, 0x79, 0x4B, 0x68, 0x9A, 0x42, 0x02, 0xD0, 0x00, 0x20, 0x04, 0xB0, 0x10, 0xBD,
+ 0x6C, 0x4B, 0x00, 0x22, 0x1B, 0x68, 0x9C, 0x7E, 0xA5, 0x2C, 0x01, 0xD1, 0x93, 0xF9, 0x1B, 0x20,
+ 0x67, 0x4C, 0x0D, 0xF1, 0x04, 0x0C, 0x01, 0x23, 0x10, 0x30, 0x00, 0x94, 0x8C, 0xE8, 0x0D, 0x00,
+ 0x08, 0x31, 0x0F, 0xC9, 0xFF, 0xF7, 0xFD, 0xFC, 0x01, 0x20, 0xE7, 0xE7, 0x1F, 0xB5, 0x5F, 0x49,
+ 0x02, 0x79, 0x0B, 0x68, 0x9A, 0x42, 0x03, 0xD1, 0x42, 0x79, 0x4B, 0x68, 0x9A, 0x42, 0x01, 0xD0,
+ 0x00, 0x20, 0xDB, 0xE7, 0x5B, 0x4B, 0x00, 0x22, 0x1B, 0x68, 0x1C, 0x7F, 0xA5, 0x2C, 0x01, 0xD1,
+ 0x93, 0xF9, 0x1D, 0x20, 0x5A, 0x4B, 0x0D, 0xF1, 0x04, 0x0C, 0x01, 0x24, 0x10, 0x30, 0x00, 0x93,
+ 0x8C, 0xE8, 0x15, 0x00, 0x08, 0x31, 0x0F, 0xC9, 0xFF, 0xF7, 0xDB, 0xFC, 0x01, 0x20, 0xC5, 0xE7,
+ 0x30, 0xB5, 0x4E, 0x49, 0x02, 0x79, 0x85, 0xB0, 0x0B, 0x68, 0x9A, 0x42, 0x03, 0xD1, 0x42, 0x79,
+ 0x4B, 0x68, 0x9A, 0x42, 0x02, 0xD0, 0x00, 0x20, 0x05, 0xB0, 0x30, 0xBD, 0x48, 0x4A, 0x85, 0x79,
+ 0x00, 0x24, 0x82, 0xF8, 0x82, 0x5B, 0xC5, 0x79, 0x82, 0xF8, 0x83, 0x5B, 0x85, 0x7A, 0x82, 0xF8,
+ 0x84, 0x5B, 0xC5, 0x7A, 0x82, 0xF8, 0x85, 0x5B, 0x05, 0x7B, 0x82, 0xF8, 0x80, 0x5B, 0x45, 0x7B,
+ 0x82, 0xF8, 0x81, 0x5B, 0x3F, 0x4A, 0x23, 0x46, 0x12, 0x68, 0x95, 0x7F, 0xA5, 0x2D, 0x03, 0xD1,
+ 0x92, 0xF9, 0x1F, 0x40, 0x92, 0xF9, 0x20, 0x30, 0x10, 0x30, 0xCD, 0xE9, 0x01, 0x04, 0x3A, 0x48,
+ 0x01, 0x22, 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x32, 0x08, 0x31, 0x0F, 0xC9, 0xFF, 0xF7, 0xF2, 0xFC,
+ 0x01, 0x20, 0xD1, 0xE7, 0x30, 0xB5, 0x31, 0x49, 0x02, 0x79, 0x85, 0xB0, 0x0B, 0x68, 0x9A, 0x42,
+ 0x03, 0xD1, 0x42, 0x79, 0x4B, 0x68, 0x9A, 0x42, 0x01, 0xD0, 0x00, 0x20, 0xC4, 0xE7, 0x2C, 0x4A,
+ 0x85, 0x79, 0x00, 0x24, 0x82, 0xF8, 0x1A, 0x5C, 0xC5, 0x79, 0x82, 0xF8, 0x1B, 0x5C, 0x85, 0x7A,
+ 0x82, 0xF8, 0x1C, 0x5C, 0xC5, 0x7A, 0x82, 0xF8, 0x1D, 0x5C, 0x05, 0x7B, 0x82, 0xF8, 0x18, 0x5C,
+ 0x45, 0x7B, 0x82, 0xF8, 0x19, 0x5C, 0x23, 0x4A, 0x23, 0x46, 0x12, 0x68, 0x92, 0xF8, 0x21, 0x50,
+ 0xA5, 0x2D, 0x03, 0xD1, 0x12, 0xF9, 0x22, 0x4F, 0x92, 0xF9, 0x01, 0x30, 0x10, 0x30, 0xCD, 0xE9,
+ 0x01, 0x04, 0x1D, 0x48, 0x01, 0x22, 0x98, 0x30, 0x00, 0x90, 0xCD, 0xE9, 0x03, 0x32, 0x08, 0x31,
+ 0x0F, 0xC9, 0xFF, 0xF7, 0xB7, 0xFC, 0x01, 0x20, 0x96, 0xE7, 0x2D, 0xE9, 0xFF, 0x41, 0x0F, 0x46,
+ 0x15, 0x46, 0x04, 0x46, 0x00, 0x26, 0x40, 0xF2, 0x7A, 0x31, 0x04, 0xF0, 0xB2, 0xFD, 0x0F, 0x48,
+ 0x01, 0x2D, 0x01, 0x78, 0x21, 0x71, 0x01, 0x79, 0x61, 0x71, 0x06, 0xD1, 0x0D, 0x49, 0x09, 0x68,
+ 0x8A, 0x7E, 0xA5, 0x2A, 0x01, 0xD1, 0x91, 0xF9, 0x1B, 0x60, 0x04, 0xF1, 0x10, 0x01, 0x08, 0x4B,
+ 0xCD, 0xE9, 0x00, 0x31, 0x00, 0x22, 0xCD, 0xE9, 0x02, 0x62, 0x00, 0xF1, 0x08, 0x01, 0x05, 0x46,
+ 0x0F, 0xC9, 0xFF, 0xF7, 0x3E, 0xFC, 0xA5, 0x20, 0x20, 0x70, 0x0B, 0xE0, 0x70, 0x07, 0x10, 0x00,
+ 0xFC, 0x4C, 0x01, 0x20, 0x24, 0x07, 0x10, 0x00, 0xEC, 0x57, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00,
+ 0x24, 0x52, 0x01, 0x20, 0x10, 0x20, 0x60, 0x70, 0x67, 0x80, 0xD5, 0xE9, 0x00, 0x01, 0x48, 0x43,
+ 0x13, 0x30, 0x80, 0x08, 0x04, 0xB0, 0xB7, 0xE6, 0x2D, 0xE9, 0xFF, 0x41, 0x0F, 0x46, 0x15, 0x46,
+ 0x04, 0x46, 0x00, 0x26, 0x40, 0xF2, 0x7A, 0x31, 0x04, 0xF0, 0x73, 0xFD, 0x13, 0x48, 0x01, 0x2D,
+ 0x01, 0x78, 0x21, 0x71, 0x01, 0x79, 0x61, 0x71, 0x06, 0xD1, 0x11, 0x49, 0x09, 0x68, 0x0A, 0x7F,
+ 0xA5, 0x2A, 0x01, 0xD1, 0x91, 0xF9, 0x1D, 0x60, 0x04, 0xF1, 0x10, 0x01, 0x0D, 0x4A, 0xCD, 0xE9,
+ 0x00, 0x21, 0x00, 0x23, 0xCD, 0xE9, 0x02, 0x63, 0x00, 0xF1, 0x08, 0x01, 0x05, 0x46, 0x0F, 0xC9,
+ 0xFF, 0xF7, 0xFF, 0xFB, 0xA5, 0x20, 0x20, 0x70, 0x11, 0x20, 0x60, 0x70, 0x67, 0x80, 0xD5, 0xE9,
+ 0x00, 0x01, 0x48, 0x43, 0x13, 0x30, 0x80, 0x08, 0xCC, 0xE7, 0x00, 0x00, 0x70, 0x07, 0x10, 0x00,
+ 0x24, 0x07, 0x10, 0x00, 0x24, 0x52, 0x01, 0x20, 0x2D, 0xE9, 0xF0, 0x4F, 0x47, 0xF6, 0xFF, 0x77,
+ 0xDD, 0xE9, 0x09, 0xB5, 0x81, 0x46, 0xFE, 0x43, 0x01, 0x20, 0x9A, 0x46, 0x84, 0x46, 0x2C, 0x46,
+ 0x15, 0xE0, 0x00, 0xBF, 0x32, 0xF8, 0x14, 0x30, 0x31, 0xF8, 0x14, 0x80, 0xA3, 0xEB, 0x08, 0x03,
+ 0x1B, 0xB2, 0xBB, 0x42, 0x00, 0xDA, 0x1F, 0x46, 0xB3, 0x42, 0x00, 0xDD, 0x1E, 0x46, 0x00, 0x2B,
+ 0x02, 0xDD, 0x4F, 0xF0, 0x00, 0x0C, 0x02, 0xE0, 0x01, 0xDA, 0x4F, 0xF0, 0x00, 0x00, 0x64, 0x1E,
+ 0xE8, 0xD2, 0x20, 0xB1, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x00, 0x23, 0x09, 0xE0, 0x50, 0xEA,
+ 0x0C, 0x03, 0x06, 0xD0, 0x20, 0xB9, 0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x33, 0x46, 0x00, 0xE0,
+ 0x3B, 0x46, 0x00, 0x27, 0x3C, 0x46, 0x28, 0x46, 0xCB, 0xF1, 0x00, 0x0C, 0x0E, 0xE0, 0x00, 0xBF,
+ 0x32, 0xF8, 0x10, 0x60, 0x31, 0xF8, 0x10, 0x80, 0xA6, 0xEB, 0x08, 0x06, 0xF6, 0x1A, 0x36, 0xB2,
+ 0x56, 0x45, 0x03, 0xDA, 0x66, 0x45, 0x01, 0xDD, 0x37, 0x44, 0x64, 0x1C, 0x40, 0x1E, 0xEF, 0xD2,
+ 0x04, 0xB9, 0x01, 0x24, 0x97, 0xFB, 0xF4, 0xF0, 0x18, 0x44, 0x04, 0xE0, 0x31, 0xF8, 0x15, 0x20,
+ 0x02, 0x44, 0x29, 0xF8, 0x15, 0x20, 0x6D, 0x1E, 0xF8, 0xD2, 0xBD, 0xE8, 0xF0, 0x8F, 0xF0, 0xB5,
+ 0x00, 0x23, 0x06, 0x46, 0x1D, 0x46, 0x18, 0x46, 0x0E, 0xE0, 0x00, 0xBF, 0x36, 0xF9, 0x11, 0x40,
+ 0x00, 0x2C, 0x01, 0xDB, 0x27, 0x46, 0x00, 0xE0, 0x67, 0x42, 0x97, 0x42, 0x04, 0xDD, 0x00, 0x2C,
+ 0x01, 0xDD, 0x25, 0x44, 0x00, 0xE0, 0x23, 0x44, 0x49, 0x1E, 0xEF, 0xD2, 0x00, 0x2B, 0x00, 0xDA,
+ 0x5B, 0x42, 0xAB, 0x42, 0x00, 0xDD, 0x01, 0x20, 0xF0, 0xBD, 0x30, 0xB5, 0x07, 0xE0, 0x00, 0xBF,
+ 0x32, 0xF8, 0x13, 0x40, 0x31, 0xF8, 0x13, 0x50, 0x64, 0x1B, 0x20, 0xF8, 0x13, 0x40, 0x5B, 0x1E,
+ 0xF6, 0xD2, 0x30, 0xBD, 0x70, 0xB5, 0x04, 0x9C, 0x09, 0xE0, 0x00, 0xBF, 0x31, 0xF9, 0x14, 0x50,
+ 0x32, 0xF9, 0x14, 0x60, 0x75, 0x43, 0x95, 0xFB, 0xF3, 0xF5, 0x20, 0xF8, 0x14, 0x50, 0x64, 0x1E,
+ 0xF4, 0xD2, 0x70, 0xBD, 0xF0, 0xB4, 0x04, 0x9C, 0x1C, 0xB9, 0x13, 0xB1, 0xC3, 0xF1, 0x10, 0x04,
+ 0x0E, 0xE0, 0xF0, 0xBC, 0x52, 0x00, 0x04, 0xF0, 0x25, 0xBC, 0x00, 0xBF, 0x30, 0xF9, 0x12, 0x50,
+ 0x31, 0xF9, 0x12, 0x60, 0x5D, 0x43, 0x06, 0xFB, 0x04, 0x55, 0x2D, 0x11, 0x20, 0xF8, 0x12, 0x50,
+ 0x52, 0x1E, 0xF3, 0xD2, 0xF0, 0xBC, 0x70, 0x47, 0xF0, 0xB4, 0x04, 0x9C, 0x1C, 0xB9, 0x13, 0xB1,
+ 0xC3, 0xF1, 0x80, 0x04, 0x0E, 0xE0, 0xF0, 0xBC, 0x52, 0x00, 0x04, 0xF0, 0x0B, 0xBC, 0x00, 0xBF,
+ 0x30, 0xF9, 0x12, 0x50, 0x31, 0xF9, 0x12, 0x60, 0x5D, 0x43, 0x06, 0xFB, 0x04, 0x55, 0xED, 0x11,
+ 0x20, 0xF8, 0x12, 0x50, 0x52, 0x1E, 0xF3, 0xD2, 0xE4, 0xE7, 0xF0, 0xB5, 0x00, 0x2B, 0x19, 0xD0,
+ 0x14, 0x46, 0x15, 0xE0, 0x00, 0x27, 0x3E, 0x46, 0xE5, 0x1A, 0x04, 0xEB, 0x03, 0x0C, 0x08, 0xE0,
+ 0x00, 0x2D, 0x05, 0xDB, 0x95, 0x42, 0x03, 0xDA, 0x31, 0xF9, 0x15, 0xE0, 0x76, 0x1C, 0x77, 0x44,
+ 0x6D, 0x1C, 0xAC, 0x45, 0xF4, 0xDA, 0x1E, 0xB1, 0x97, 0xFB, 0xF6, 0xF5, 0x20, 0xF8, 0x14, 0x50,
+ 0x64, 0x1E, 0xE7, 0xD2, 0xF0, 0xBD, 0x70, 0xB5, 0x0C, 0x46, 0x15, 0x46, 0xA0, 0x42, 0x04, 0xD0,
+ 0x01, 0x46, 0x6A, 0x00, 0x20, 0x46, 0x04, 0xF0, 0xD5, 0xFB, 0x00, 0x20, 0x17, 0xE0, 0x01, 0x46,
+ 0x42, 0x1C, 0x07, 0xE0, 0x34, 0xF9, 0x12, 0x60, 0x34, 0xF9, 0x11, 0x30, 0x9E, 0x42, 0x00, 0xDA,
+ 0x11, 0x46, 0x52, 0x1C, 0xAA, 0x42, 0xF5, 0xD3, 0x88, 0x42, 0x07, 0xD0, 0x34, 0xF8, 0x10, 0x20,
+ 0x34, 0xF8, 0x11, 0x30, 0x24, 0xF8, 0x10, 0x30, 0x24, 0xF8, 0x11, 0x20, 0x40, 0x1C, 0xB0, 0xEB,
+ 0x55, 0x0F, 0xE4, 0xD9, 0xE9, 0x07, 0x25, 0xF0, 0x01, 0x00, 0x01, 0xD0, 0x20, 0x5E, 0x70, 0xBD,
+ 0x21, 0x5E, 0x20, 0x44, 0x30, 0xF9, 0x02, 0x0C, 0x08, 0x44, 0x40, 0x10, 0x70, 0xBD, 0x03, 0x46,
+ 0x00, 0x20, 0x04, 0xE0, 0x33, 0xF9, 0x11, 0x20, 0x82, 0x42, 0x00, 0xDD, 0x10, 0x46, 0x49, 0x1E,
+ 0xF8, 0xD2, 0x70, 0x47, 0x03, 0x46, 0x47, 0xF6, 0xFF, 0x70, 0x04, 0xE0, 0x33, 0xF9, 0x11, 0x20,
+ 0x82, 0x42, 0x00, 0xDA, 0x10, 0x46, 0x49, 0x1E, 0xF8, 0xD2, 0x00, 0x28, 0x00, 0xDA, 0x00, 0x20,
+ 0x70, 0x47, 0x02, 0x46, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xE0, 0x00, 0xBF, 0x32, 0xF9, 0x11, 0x30,
+ 0x83, 0x42, 0x00, 0xDD, 0x18, 0x46, 0x49, 0x1E, 0xF8, 0xD2, 0x70, 0x47, 0x70, 0xB5, 0x05, 0x00,
+ 0x03, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0xF0, 0xBE, 0xBE, 0xFE, 0x4C, 0x21, 0x46, 0x60, 0x78,
+ 0x09, 0x79, 0x30, 0xB1, 0x0A, 0x46, 0xFC, 0x49, 0x01, 0xF1, 0x98, 0x00, 0x01, 0xF0, 0x00, 0xFF,
+ 0x0B, 0xE0, 0x20, 0x78, 0x01, 0xF0, 0xCA, 0xFF, 0x21, 0x79, 0x4A, 0x00, 0xF6, 0x49, 0x01, 0xEB,
+ 0x40, 0x01, 0xF5, 0x48, 0x98, 0x30, 0x04, 0xF0, 0x65, 0xFB, 0xA0, 0x78, 0xF3, 0x4E, 0x28, 0xB1,
+ 0xF1, 0x48, 0x21, 0x79, 0x98, 0x30, 0x01, 0xF0, 0xB7, 0xFF, 0x01, 0xE0, 0xEE, 0x48, 0x98, 0x30,
+ 0xB0, 0x62, 0xE0, 0x78, 0x86, 0xF8, 0x31, 0x00, 0x28, 0x46, 0xD2, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F,
+ 0xDF, 0xF8, 0xAC, 0xA3, 0x83, 0x46, 0x01, 0x27, 0xDA, 0xF8, 0x00, 0x00, 0xB8, 0x46, 0x00, 0xF2,
+ 0x5E, 0x64, 0x90, 0xF8, 0xA6, 0x19, 0x90, 0xF8, 0xA2, 0x59, 0x01, 0xF0, 0x1F, 0x06, 0x90, 0xF8,
+ 0xA3, 0x19, 0x01, 0xF0, 0x0F, 0x09, 0x90, 0xF8, 0x82, 0x19, 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8,
+ 0x58, 0x16, 0x90, 0xF8, 0x59, 0x06, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xFC, 0xFE,
+ 0x07, 0x46, 0xDA, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x82, 0x19, 0x49, 0x06, 0x09, 0xD5, 0x90, 0xF8,
+ 0x68, 0x18, 0x90, 0xF8, 0x69, 0x08, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xEC, 0xFE,
+ 0x80, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x85, 0x42, 0x00, 0xD9, 0x05, 0x46, 0x1F, 0x2E, 0x00, 0xD9,
+ 0x1F, 0x26, 0x76, 0x1C, 0x75, 0x43, 0x09, 0xF1, 0x01, 0x00, 0x45, 0x43, 0xC5, 0xEB, 0x45, 0x20,
+ 0x78, 0x43, 0xDA, 0xF8, 0x00, 0x20, 0x00, 0xFB, 0x08, 0xF0, 0xC0, 0x13, 0x92, 0xF8, 0x50, 0x1A,
+ 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x20, 0x00, 0x89, 0x06, 0x11, 0xD5, 0x00, 0x21, 0xBB, 0xF1,
+ 0x01, 0x0F, 0x06, 0xD1, 0x92, 0xF8, 0x56, 0x1A, 0x0A, 0x07, 0x01, 0xF0, 0x07, 0x01, 0x00, 0xD5,
+ 0x49, 0x42, 0x40, 0x18, 0x01, 0xD5, 0x00, 0x20, 0x02, 0xE0, 0x1F, 0x28, 0x00, 0xDD, 0x1F, 0x20,
+ 0xC0, 0xB2, 0xBD, 0xE8, 0xF0, 0x9F, 0xF8, 0xB5, 0x04, 0x46, 0x02, 0xF0, 0xD7, 0xFB, 0xB6, 0x48,
+ 0x02, 0xF0, 0xD9, 0xFB, 0xA4, 0xF8, 0x76, 0x00, 0x01, 0xF0, 0x98, 0xFE, 0xB1, 0x4A, 0x0B, 0x46,
+ 0x12, 0x78, 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x02, 0xF0, 0x97, 0xFE, 0x01, 0xF0, 0x93, 0xFE,
+ 0x02, 0x46, 0x0B, 0x46, 0x20, 0x46, 0x02, 0xF0, 0xC6, 0xFE, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xFF,
+ 0xAB, 0x4D, 0xB4, 0xF8, 0x56, 0x10, 0x28, 0x68, 0xB0, 0xF8, 0xC0, 0x20, 0x62, 0xF3, 0x09, 0x01,
+ 0xA4, 0xF8, 0x56, 0x10, 0x90, 0xF8, 0xBF, 0x00, 0x94, 0xF8, 0x55, 0x10, 0x60, 0xF3, 0x03, 0x01,
+ 0x84, 0xF8, 0x55, 0x10, 0x05, 0x21, 0x20, 0x46, 0x02, 0xF0, 0xD6, 0xFB, 0x28, 0x68, 0x90, 0xF8,
+ 0xA2, 0x09, 0xA0, 0x70, 0x28, 0x68, 0x21, 0x8E, 0xB0, 0xF8, 0xA7, 0x29, 0x62, 0xF3, 0x08, 0x01,
+ 0x21, 0x86, 0x90, 0xF8, 0xA3, 0x09, 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x02, 0xF0, 0x3B, 0xFC,
+ 0x28, 0x68, 0x34, 0xF8, 0x1A, 0x1F, 0xB0, 0xF8, 0x8E, 0x29, 0x62, 0xF3, 0x0B, 0x01, 0x24, 0xF8,
+ 0x14, 0x19, 0xB0, 0xF8, 0x8C, 0x29, 0x61, 0x89, 0x62, 0xF3, 0x0B, 0x01, 0x61, 0x81, 0xB0, 0xF8,
+ 0x8A, 0x19, 0xE0, 0x88, 0x61, 0xF3, 0x0B, 0x00, 0xE0, 0x80, 0x14, 0xF8, 0x05, 0x0C, 0x20, 0xF0,
+ 0x0C, 0x00, 0x04, 0xF8, 0x05, 0x0C, 0x29, 0x68, 0x20, 0x7B, 0x91, 0xF8, 0xA4, 0x29, 0x62, 0xF3,
+ 0x01, 0x00, 0x20, 0x73, 0x91, 0xF8, 0xA4, 0x29, 0x92, 0x08, 0x62, 0xF3, 0x87, 0x10, 0x20, 0x73,
+ 0x91, 0xF8, 0x82, 0x09, 0x62, 0x78, 0x60, 0xF3, 0x00, 0x02, 0x62, 0x70, 0x91, 0xF8, 0x85, 0x09,
+ 0xE0, 0x70, 0x80, 0x48, 0x90, 0xF8, 0x18, 0x1C, 0x21, 0x76, 0x90, 0xF8, 0x19, 0x1C, 0xA1, 0x77,
+ 0x90, 0xF8, 0x1A, 0x1C, 0x61, 0x76, 0x90, 0xF8, 0x1B, 0x1C, 0xE1, 0x77, 0x90, 0xF8, 0x1C, 0x1C,
+ 0xA1, 0x76, 0x90, 0xF8, 0x1D, 0x0C, 0x84, 0xF8, 0x20, 0x00, 0x77, 0x48, 0x02, 0xF0, 0x53, 0xFB,
+ 0xA4, 0xF8, 0x7A, 0x00, 0x74, 0x48, 0x20, 0x30, 0x02, 0xF0, 0x4D, 0xFB, 0xA4, 0xF8, 0x7E, 0x00,
+ 0x28, 0x68, 0x90, 0xF8, 0x92, 0x19, 0x0A, 0x09, 0x14, 0xF8, 0x16, 0x1F, 0x62, 0xF3, 0x07, 0x11,
+ 0x04, 0xF8, 0x06, 0x1B, 0x90, 0xF8, 0x97, 0x29, 0x13, 0x09, 0x22, 0x78, 0x63, 0xF3, 0x07, 0x12,
+ 0x22, 0x70, 0x90, 0xF8, 0x93, 0x69, 0x14, 0xF8, 0x05, 0x3C, 0x66, 0xF3, 0x03, 0x03, 0x04, 0xF8,
+ 0x05, 0x3C, 0x90, 0xF8, 0x98, 0x79, 0x66, 0x78, 0x67, 0xF3, 0x03, 0x06, 0x66, 0x70, 0x90, 0xF8,
+ 0x93, 0x79, 0x3F, 0x09, 0x67, 0xF3, 0x07, 0x13, 0x04, 0xF8, 0x05, 0x3C, 0x90, 0xF8, 0x98, 0x39,
+ 0x1B, 0x09, 0x63, 0xF3, 0x07, 0x16, 0x66, 0x70, 0x90, 0xF8, 0x92, 0x39, 0x63, 0xF3, 0x00, 0x01,
+ 0x04, 0xF8, 0x06, 0x1C, 0x90, 0xF8, 0x97, 0x19, 0x61, 0xF3, 0x00, 0x02, 0x04, 0xF8, 0x22, 0x29,
+ 0x90, 0xF8, 0x87, 0x09, 0x01, 0x09, 0x20, 0x46, 0x02, 0xF0, 0xB9, 0xFB, 0x52, 0x48, 0x48, 0x38,
+ 0x02, 0xF0, 0x09, 0xFB, 0xA4, 0xF8, 0x7E, 0x00, 0x4F, 0x48, 0x27, 0x34, 0x28, 0x38, 0x02, 0xF0,
+ 0x02, 0xFB, 0xA4, 0xF8, 0x5B, 0x00, 0x29, 0x68, 0x91, 0xF8, 0x84, 0x09, 0xC2, 0x08, 0x20, 0x78,
+ 0x62, 0xF3, 0x83, 0x00, 0x20, 0x70, 0x91, 0xF8, 0x84, 0x29, 0x52, 0x08, 0x62, 0xF3, 0x00, 0x00,
+ 0x20, 0x70, 0x91, 0xF8, 0x84, 0x29, 0x92, 0x08, 0x62, 0xF3, 0x41, 0x00, 0x04, 0xF8, 0x27, 0x09,
+ 0x91, 0xF8, 0x83, 0x09, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x02, 0xF0, 0x71, 0xFB, 0x28, 0x68,
+ 0x90, 0xF8, 0x83, 0x09, 0x01, 0x09, 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, 0x04, 0x10, 0x20, 0x70,
+ 0x3A, 0x48, 0x02, 0xF0, 0xD8, 0xFA, 0xA4, 0xF8, 0x60, 0x00, 0x38, 0x48, 0x20, 0x30, 0x02, 0xF0,
+ 0xD2, 0xFA, 0xA4, 0xF8, 0x62, 0x00, 0x28, 0x68, 0x90, 0xF8, 0x82, 0x19, 0xCA, 0x08, 0xE1, 0x7A,
+ 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, 0x90, 0xF8, 0x83, 0x09, 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3,
+ 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x18, 0xFE, 0x28, 0x68, 0x90, 0xF8,
+ 0x86, 0x09, 0x81, 0x09, 0x20, 0x46, 0x02, 0xF0, 0x30, 0xFB, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0,
+ 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, 0xF0, 0x00, 0xA0, 0x30, 0x04, 0xF8, 0x1C, 0x09, 0x29, 0x68,
+ 0x91, 0xF8, 0x82, 0x09, 0x82, 0x09, 0x60, 0x7F, 0x62, 0xF3, 0x00, 0x00, 0x60, 0x77, 0x91, 0xF8,
+ 0x82, 0x29, 0x52, 0x09, 0x62, 0xF3, 0x41, 0x00, 0x60, 0x77, 0x91, 0xF8, 0x88, 0x29, 0x62, 0xF3,
+ 0x82, 0x00, 0x60, 0x77, 0x91, 0xF8, 0xA5, 0x09, 0xE2, 0x7D, 0x60, 0xF3, 0x04, 0x02, 0xE2, 0x75,
+ 0x91, 0xF8, 0xA6, 0x09, 0xA1, 0x7D, 0x60, 0xF3, 0x04, 0x01, 0x0F, 0x48, 0xA1, 0x75, 0x08, 0x38,
+ 0x94, 0xF8, 0x49, 0x10, 0x40, 0x78, 0x60, 0xF3, 0x04, 0x01, 0x0F, 0x48, 0x84, 0xF8, 0x49, 0x10,
+ 0xE8, 0x30, 0x02, 0xF0, 0x80, 0xFA, 0xA4, 0xF8, 0x64, 0x00, 0x28, 0x68, 0x21, 0x8B, 0xB0, 0xF8,
+ 0x90, 0x29, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x83, 0x90, 0xF8, 0x86, 0x19, 0xCA, 0x08, 0x94, 0xF8,
+ 0x22, 0x10, 0x0D, 0xE0, 0x88, 0x07, 0x10, 0x00, 0x00, 0x5D, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xFC, 0x4C, 0x01, 0x20, 0xCC, 0x58, 0x01, 0x20, 0xB0, 0x5C, 0x01, 0x20,
+ 0x62, 0xF3, 0x02, 0x01, 0x84, 0xF8, 0x22, 0x10, 0x10, 0xF8, 0xE3, 0x2F, 0x21, 0x7D, 0x62, 0xF3,
+ 0x03, 0x01, 0x21, 0x75, 0x10, 0xF8, 0xE3, 0x1B, 0x0A, 0x09, 0x61, 0x7D, 0x62, 0xF3, 0x03, 0x01,
+ 0x61, 0x75, 0x90, 0xF8, 0xC1, 0x17, 0xE2, 0x7C, 0x61, 0xF3, 0x02, 0x02, 0xE2, 0x74, 0x90, 0xF8,
+ 0xBC, 0x17, 0xCA, 0x09, 0xA1, 0x7F, 0x62, 0xF3, 0x00, 0x01, 0xA1, 0x77, 0x94, 0xF8, 0x49, 0x10,
+ 0x41, 0xF0, 0x20, 0x01, 0x84, 0xF8, 0x49, 0x10, 0x90, 0xF8, 0xBE, 0x27, 0xD2, 0x09, 0x62, 0xF3,
+ 0xC7, 0x11, 0x84, 0xF8, 0x49, 0x10, 0xB0, 0xF8, 0xD6, 0x27, 0xB4, 0xF8, 0x4A, 0x10, 0x62, 0xF3,
+ 0x08, 0x01, 0xA4, 0xF8, 0x4A, 0x10, 0x00, 0x21, 0xE1, 0x64, 0x90, 0xF8, 0xC1, 0x17, 0xCA, 0x08,
+ 0x61, 0x7F, 0x62, 0xF3, 0xC3, 0x01, 0x61, 0x77, 0x90, 0xF8, 0xBC, 0x27, 0x12, 0x09, 0x62, 0xF3,
+ 0x04, 0x11, 0x61, 0x77, 0x90, 0xF8, 0xDF, 0x17, 0x4A, 0x09, 0x14, 0xF8, 0x0E, 0x1C, 0x62, 0xF3,
+ 0x06, 0x11, 0x04, 0xF8, 0x0E, 0x1C, 0x90, 0xF8, 0xBD, 0x17, 0x4A, 0x09, 0xA1, 0x78, 0x62, 0xF3,
+ 0xC3, 0x01, 0xA1, 0x70, 0x90, 0xF8, 0xBC, 0x27, 0x52, 0x08, 0x62, 0xF3, 0x04, 0x11, 0xA1, 0x70,
+ 0x90, 0xF8, 0xBE, 0x07, 0x80, 0x09, 0x60, 0xF3, 0x86, 0x11, 0xA1, 0x70, 0xF8, 0xBD, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x04, 0x46, 0x54, 0x4D, 0x01, 0x20, 0x01, 0x29, 0xA8, 0x70, 0x08, 0xD0, 0x00, 0x26,
+ 0x52, 0x4F, 0x02, 0x29, 0x08, 0xD0, 0x03, 0x29, 0x14, 0xD0, 0x04, 0x29, 0x2C, 0xD1, 0x3D, 0xE0,
+ 0x20, 0x46, 0x00, 0xF0, 0x94, 0xF8, 0x27, 0xE0, 0x4D, 0x48, 0xFF, 0xF7, 0x0C, 0xFE, 0x20, 0x46,
+ 0x00, 0xF0, 0x8D, 0xF8, 0xB8, 0x78, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8,
+ 0x5F, 0x10, 0x14, 0xE0, 0x46, 0x48, 0xFF, 0xF7, 0xFE, 0xFD, 0x20, 0x46, 0x00, 0xF0, 0x7F, 0xF8,
+ 0xF8, 0x78, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0x94, 0xF8,
+ 0x27, 0x00, 0x20, 0xF0, 0x02, 0x00, 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x00, 0x21,
+ 0x20, 0x46, 0x02, 0xF0, 0x68, 0xFA, 0xAE, 0x70, 0x20, 0x46, 0x01, 0xF0, 0x83, 0xFE, 0x94, 0xF8,
+ 0x27, 0x00, 0x40, 0xF3, 0x00, 0x00, 0x40, 0x1C, 0xE8, 0x70, 0x36, 0x48, 0x00, 0x68, 0x90, 0xF8,
+ 0x83, 0x09, 0xC0, 0xF3, 0x80, 0x10, 0x68, 0x70, 0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x46, 0x00, 0xF0,
+ 0x56, 0xF8, 0x20, 0x46, 0x01, 0xF0, 0x67, 0xFD, 0xE5, 0xE7, 0x7C, 0xB5, 0x01, 0xF0, 0x6E, 0xFC,
+ 0xCD, 0xE9, 0x00, 0x01, 0x08, 0x21, 0x68, 0x46, 0x02, 0xF0, 0xF4, 0xFD, 0x26, 0x49, 0x27, 0x4D,
+ 0x08, 0x71, 0x00, 0x20, 0x28, 0x60, 0x28, 0x71, 0x01, 0x24, 0xE0, 0xB2, 0xFF, 0xF7, 0x56, 0xFD,
+ 0x28, 0x55, 0x64, 0x1C, 0x05, 0x2C, 0xF8, 0xDB, 0x21, 0x48, 0xFF, 0xF7, 0xB4, 0xFD, 0x7C, 0xBD,
+ 0x30, 0xB5, 0x01, 0x7A, 0xA9, 0xB0, 0x79, 0xB3, 0x68, 0x46, 0xFF, 0xF7, 0x88, 0xFF, 0x9D, 0xF8,
+ 0x12, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0xB1, 0xFC, 0x1A, 0x4C, 0x20, 0x68, 0x00, 0xF2,
+ 0x5E, 0x63, 0x00, 0xF6, 0x6E, 0x05, 0x90, 0xF8, 0x58, 0x16, 0x90, 0xF8, 0x59, 0x06, 0x03, 0xEB,
+ 0x40, 0x00, 0x01, 0xF0, 0x74, 0xFC, 0x20, 0x68, 0x90, 0xF8, 0x68, 0x18, 0x90, 0xF8, 0x69, 0x08,
+ 0x05, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0x82, 0xFC, 0x0B, 0x48, 0x41, 0x78, 0x01, 0xB1, 0x02, 0x21,
+ 0x01, 0x70, 0xC9, 0xB2, 0x68, 0x46, 0x02, 0xF0, 0x80, 0xFC, 0x0B, 0x49, 0x68, 0x46, 0x02, 0xF0,
+ 0xB1, 0xFC, 0x00, 0x20, 0x29, 0xB0, 0x30, 0xBD, 0xFF, 0xE7, 0x01, 0x20, 0xFA, 0xE7, 0xA4, 0x22,
+ 0x03, 0x49, 0x04, 0xF0, 0x67, 0xB8, 0x00, 0x00, 0x88, 0x07, 0x10, 0x00, 0xF8, 0x5C, 0x01, 0x20,
+ 0x48, 0x7F, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0xBD, 0x20, 0x01, 0x00, 0x10, 0xB5, 0x04, 0x00,
+ 0x03, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x96, 0xBB, 0x26, 0x48, 0x26, 0x49, 0x00, 0x78,
+ 0x42, 0x00, 0x01, 0xEB, 0x40, 0x01, 0x24, 0x48, 0x98, 0x30, 0x04, 0xF0, 0x4B, 0xF8, 0x22, 0x48,
+ 0x22, 0x49, 0x98, 0x30, 0x48, 0x62, 0x20, 0x46, 0xEB, 0xE7, 0x1C, 0xB5, 0x01, 0xF0, 0xF6, 0xFB,
+ 0xCD, 0xE9, 0x00, 0x01, 0x08, 0x21, 0x68, 0x46, 0x02, 0xF0, 0x7C, 0xFD, 0x19, 0x49, 0x1C, 0x4C,
+ 0x08, 0x70, 0x20, 0x46, 0x00, 0xF0, 0x39, 0xFB, 0x17, 0x48, 0x02, 0xF0, 0x24, 0xF9, 0xA4, 0xF8,
+ 0x76, 0x00, 0x18, 0x48, 0x01, 0x68, 0xA0, 0x7C, 0x91, 0xF8, 0x50, 0x21, 0x62, 0xF3, 0x01, 0x00,
+ 0xA0, 0x74, 0x91, 0xF8, 0x50, 0x11, 0x89, 0x08, 0x61, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0x1C, 0xBD,
+ 0x10, 0xB5, 0x0F, 0x4C, 0xC0, 0x79, 0x98, 0xB1, 0x20, 0x46, 0x01, 0xF0, 0xCB, 0xFD, 0xA0, 0x7C,
+ 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0x32, 0xFC, 0x00, 0xF0, 0x7B, 0xFB, 0x04, 0x21, 0x20, 0x46,
+ 0x02, 0xF0, 0x1B, 0xFC, 0x08, 0x49, 0x20, 0x46, 0x02, 0xF0, 0x4C, 0xFC, 0x00, 0x20, 0x10, 0xBD,
+ 0x01, 0x20, 0x10, 0xBD, 0x8D, 0x07, 0x10, 0x00, 0xE4, 0x5D, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00,
+ 0xEC, 0x7F, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00, 0x0D, 0x27, 0x01, 0x00, 0xFE, 0x49, 0xC8, 0x68,
+ 0x40, 0x1C, 0xC8, 0x60, 0x02, 0x28, 0x03, 0xD2, 0xFC, 0x49, 0x51, 0xF8, 0x20, 0x00, 0x00, 0x47,
+ 0x00, 0x20, 0x01, 0xF0, 0x30, 0xBB, 0x00, 0x28, 0x01, 0xD1, 0x02, 0xF0, 0x1C, 0xBC, 0x70, 0x47,
+ 0xF5, 0x49, 0x10, 0xB5, 0x0A, 0x79, 0x01, 0x20, 0x52, 0x1C, 0xD2, 0xB2, 0x0A, 0x71, 0x0B, 0x7A,
+ 0x9A, 0x42, 0x0A, 0xD8, 0x48, 0x7A, 0x48, 0xB1, 0x02, 0xF0, 0x5E, 0xFB, 0x03, 0x20, 0xED, 0xF7,
+ 0xCF, 0xFD, 0xEF, 0x48, 0x02, 0xF0, 0x4C, 0xFB, 0x00, 0x20, 0x10, 0xBD, 0x02, 0xF0, 0x03, 0xFC,
+ 0xFA, 0xE7, 0x70, 0xB5, 0x18, 0xB1, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0xF0, 0x0C, 0xBB, 0xE6, 0x4C,
+ 0x20, 0x7A, 0x08, 0xB1, 0xE7, 0x4D, 0x01, 0xE0, 0xE6, 0x4D, 0x76, 0x3D, 0xA0, 0x78, 0xE6, 0x49,
+ 0x82, 0x00, 0x01, 0xF5, 0xAE, 0x70, 0x04, 0xF0, 0x02, 0xF8, 0x60, 0x79, 0x28, 0xB1, 0xA2, 0x78,
+ 0xE1, 0x49, 0x28, 0x46, 0x01, 0xF0, 0x44, 0xFB, 0x0C, 0xE0, 0xA1, 0x78, 0x60, 0x78, 0x01, 0xF0,
+ 0x0D, 0xFC, 0xA1, 0x78, 0xC0, 0xB2, 0x4A, 0x00, 0xDB, 0x49, 0x01, 0xEB, 0x40, 0x01, 0x28, 0x46,
+ 0x03, 0xF0, 0xA8, 0xFF, 0xD7, 0x48, 0x23, 0x79, 0xA2, 0x78, 0x29, 0x46, 0x76, 0x38, 0x01, 0xF0,
+ 0x40, 0xFB, 0xFF, 0xF7, 0xB5, 0xFF, 0x00, 0x28, 0x15, 0xD0, 0xA0, 0x79, 0xD3, 0x4D, 0x01, 0x28,
+ 0x0B, 0xD0, 0xD0, 0x48, 0x76, 0x38, 0xA8, 0x61, 0xE0, 0x79, 0x85, 0xF8, 0x30, 0x00, 0x20, 0x79,
+ 0x85, 0xF8, 0x20, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x90, 0xE7, 0xCA, 0x48, 0xA1, 0x78, 0x76, 0x38,
+ 0x01, 0xF0, 0xE2, 0xFB, 0xEF, 0xE7, 0x70, 0xBD, 0x70, 0xB5, 0x18, 0xB1, 0xBD, 0xE8, 0x70, 0x40,
+ 0x01, 0xF0, 0xC1, 0xBA, 0xC0, 0x4C, 0x20, 0x7A, 0x08, 0xB1, 0xC2, 0x4D, 0x01, 0xE0, 0xC1, 0x4D,
+ 0x4C, 0x3D, 0xE0, 0x78, 0xC0, 0x49, 0x82, 0x00, 0x01, 0xF5, 0xD8, 0x70, 0x03, 0xF0, 0xB7, 0xFF,
+ 0x60, 0x79, 0x28, 0xB1, 0xE2, 0x78, 0xBC, 0x49, 0x28, 0x46, 0x01, 0xF0, 0xF9, 0xFA, 0x0C, 0xE0,
+ 0xE1, 0x78, 0x60, 0x78, 0x01, 0xF0, 0xC8, 0xFB, 0xE1, 0x78, 0xC0, 0xB2, 0x4A, 0x00, 0xB6, 0x49,
+ 0x01, 0xEB, 0x40, 0x01, 0x28, 0x46, 0x03, 0xF0, 0x5D, 0xFF, 0xB2, 0x48, 0x23, 0x79, 0xE2, 0x78,
+ 0x29, 0x46, 0x4C, 0x38, 0x01, 0xF0, 0xF5, 0xFA, 0xFF, 0xF7, 0x6A, 0xFF, 0x00, 0x28, 0x15, 0xD0,
+ 0xA0, 0x79, 0xAE, 0x4D, 0x01, 0x28, 0x0B, 0xD0, 0xAA, 0x48, 0x4C, 0x38, 0xE8, 0x61, 0xE0, 0x79,
+ 0x85, 0xF8, 0x30, 0x00, 0x20, 0x79, 0x85, 0xF8, 0x21, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x45, 0xE7,
+ 0xA4, 0x48, 0xE1, 0x78, 0x4C, 0x38, 0x01, 0xF0, 0x98, 0xFB, 0xEF, 0xE7, 0x70, 0xBD, 0x2D, 0xE9,
+ 0xF1, 0x4F, 0xDF, 0xF8, 0x8C, 0xB2, 0x01, 0x27, 0xB8, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0x00, 0xF2,
+ 0x5E, 0x64, 0x90, 0xF8, 0x55, 0x11, 0x90, 0xF8, 0x4E, 0x51, 0x01, 0xF0, 0x03, 0x0A, 0x90, 0xF8,
+ 0x52, 0x11, 0x01, 0xF0, 0x1F, 0x06, 0x90, 0xF8, 0x4F, 0x11, 0x01, 0xF0, 0x0F, 0x09, 0x90, 0xF8,
+ 0x32, 0x11, 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x56, 0x16, 0x90, 0xF8, 0x57, 0x06, 0x0A, 0x22,
+ 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xE0, 0xFA, 0x07, 0x46, 0xDB, 0xF8, 0x00, 0x00, 0x90, 0xF8,
+ 0x32, 0x11, 0x49, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x66, 0x18, 0x90, 0xF8, 0x67, 0x08, 0x0A, 0x22,
+ 0x04, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0xD0, 0xFA, 0x80, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x85, 0x42,
+ 0x00, 0xD9, 0x05, 0x46, 0x1F, 0x2E, 0x00, 0xD9, 0x1F, 0x26, 0x76, 0x1C, 0x75, 0x43, 0x09, 0xF1,
+ 0x01, 0x00, 0x45, 0x43, 0xC5, 0xEB, 0x45, 0x20, 0x78, 0x43, 0x00, 0xFB, 0x08, 0xF0, 0x0A, 0xF1,
+ 0x01, 0x01, 0x48, 0x43, 0xDB, 0xF8, 0x00, 0x20, 0xC0, 0x13, 0xB0, 0xFA, 0x80, 0xF0, 0x92, 0xF8,
+ 0x50, 0x1A, 0xC0, 0xF1, 0x20, 0x00, 0xC9, 0x06, 0x11, 0xD5, 0x00, 0x9B, 0x00, 0x21, 0x01, 0x2B,
+ 0x06, 0xD1, 0x92, 0xF8, 0x55, 0x1A, 0x0A, 0x07, 0x01, 0xF0, 0x07, 0x01, 0x00, 0xD5, 0x49, 0x42,
+ 0x40, 0x18, 0x01, 0xD5, 0x00, 0x20, 0x02, 0xE0, 0x1F, 0x28, 0x00, 0xDD, 0x1F, 0x20, 0xC0, 0xB2,
+ 0xBD, 0xE8, 0xF8, 0x8F, 0xF8, 0xB5, 0x04, 0x46, 0x01, 0xF0, 0xB8, 0xFF, 0x6A, 0x48, 0x01, 0xF0,
+ 0xBA, 0xFF, 0xA4, 0xF8, 0x76, 0x00, 0x01, 0xF0, 0x79, 0xFA, 0x63, 0x4D, 0x0B, 0x46, 0x6A, 0x78,
+ 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x02, 0xF0, 0x78, 0xFA, 0x01, 0xF0, 0x74, 0xFA, 0x02, 0x46,
+ 0x0B, 0x46, 0x20, 0x46, 0x02, 0xF0, 0xA7, 0xFA, 0x20, 0x46, 0x01, 0xF0, 0x1B, 0xFB, 0x60, 0x4E,
+ 0xB4, 0xF8, 0x56, 0x10, 0x30, 0x68, 0xB0, 0xF8, 0xC0, 0x20, 0x62, 0xF3, 0x09, 0x01, 0xA4, 0xF8,
+ 0x56, 0x10, 0x90, 0xF8, 0xBF, 0x00, 0x94, 0xF8, 0x55, 0x10, 0x60, 0xF3, 0x03, 0x01, 0x84, 0xF8,
+ 0x55, 0x10, 0x05, 0x21, 0x20, 0x46, 0x01, 0xF0, 0xB7, 0xFF, 0x30, 0x68, 0x90, 0xF8, 0x4E, 0x01,
+ 0xA0, 0x70, 0x30, 0x68, 0x21, 0x8E, 0xB0, 0xF8, 0x53, 0x21, 0x62, 0xF3, 0x08, 0x01, 0x21, 0x86,
+ 0x90, 0xF8, 0x4F, 0x01, 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x02, 0xF0, 0x1C, 0xF8, 0x30, 0x68,
+ 0x34, 0xF8, 0x1A, 0x1F, 0xB0, 0xF8, 0x3E, 0x21, 0x62, 0xF3, 0x0B, 0x01, 0x24, 0xF8, 0x12, 0x19,
+ 0xB0, 0xF8, 0x3C, 0x21, 0x21, 0x89, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x81, 0xB0, 0xF8, 0x3A, 0x21,
+ 0xA1, 0x88, 0x62, 0xF3, 0x0B, 0x01, 0xA1, 0x80, 0x90, 0xF8, 0x50, 0x21, 0xA1, 0x7A, 0x62, 0xF3,
+ 0x01, 0x01, 0xA1, 0x72, 0x90, 0xF8, 0x50, 0x21, 0x92, 0x08, 0x62, 0xF3, 0x87, 0x11, 0xA1, 0x72,
+ 0x90, 0xF8, 0x32, 0x11, 0x14, 0xF8, 0x01, 0x2C, 0x61, 0xF3, 0x00, 0x02, 0x04, 0xF8, 0x01, 0x2C,
+ 0x90, 0xF8, 0x35, 0x01, 0x60, 0x70, 0x37, 0x48, 0x90, 0xF8, 0x80, 0x1B, 0xA1, 0x75, 0x90, 0xF8,
+ 0x81, 0x1B, 0x21, 0x77, 0x90, 0xF8, 0x82, 0x1B, 0xE1, 0x75, 0x90, 0xF8, 0x83, 0x1B, 0x61, 0x77,
+ 0x90, 0xF8, 0x84, 0x1B, 0x21, 0x76, 0x90, 0xF8, 0x85, 0x0B, 0xA0, 0x77, 0x2E, 0x48, 0x01, 0xF0,
+ 0x3A, 0xFF, 0xA4, 0xF8, 0x78, 0x00, 0x2C, 0x48, 0x20, 0x30, 0x01, 0xF0, 0x34, 0xFF, 0xA4, 0xF8,
+ 0x7C, 0x00, 0x30, 0x68, 0x14, 0xF8, 0x14, 0x2F, 0x90, 0xF8, 0x42, 0x11, 0x09, 0x09, 0x61, 0xF3,
+ 0x07, 0x12, 0x04, 0xF8, 0x06, 0x2B, 0x90, 0xF8, 0x47, 0x11, 0x0B, 0x09, 0x21, 0x78, 0x63, 0xF3,
+ 0x07, 0x11, 0x21, 0x70, 0x90, 0xF8, 0x43, 0x31, 0x14, 0xF8, 0x05, 0x7C, 0x63, 0xF3, 0x03, 0x07,
+ 0x04, 0xF8, 0x05, 0x7C, 0x90, 0xF8, 0x48, 0xC1, 0x63, 0x78, 0x6C, 0xF3, 0x03, 0x03, 0x63, 0x70,
+ 0x90, 0xF8, 0x43, 0xC1, 0x4F, 0xEA, 0x1C, 0x1C, 0x6C, 0xF3, 0x07, 0x17, 0x04, 0xF8, 0x05, 0x7C,
+ 0x90, 0xF8, 0x48, 0x71, 0x3F, 0x09, 0x67, 0xF3, 0x07, 0x13, 0x63, 0x70, 0x90, 0xF8, 0x42, 0x31,
+ 0x63, 0xF3, 0x00, 0x02, 0x04, 0xF8, 0x06, 0x2C, 0x90, 0xF8, 0x47, 0x21, 0x62, 0xF3, 0x00, 0x01,
+ 0x04, 0xF8, 0x22, 0x19, 0x90, 0xF8, 0x37, 0x01, 0x01, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x9F, 0xFF,
+ 0x09, 0x48, 0x48, 0x38, 0x12, 0xE0, 0x00, 0x00, 0x90, 0x07, 0x10, 0x00, 0x44, 0x6F, 0x01, 0x00,
+ 0xE7, 0x27, 0x01, 0x00, 0xDE, 0x5F, 0x01, 0x20, 0xD0, 0x5E, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xFC, 0x4C, 0x01, 0x20, 0x34, 0x58, 0x01, 0x20, 0x01, 0xF0, 0xDB, 0xFE,
+ 0xA4, 0xF8, 0x7E, 0x00, 0xF7, 0x48, 0x27, 0x34, 0x01, 0xF0, 0xD5, 0xFE, 0xA4, 0xF8, 0x5B, 0x00,
+ 0x31, 0x68, 0x91, 0xF8, 0x34, 0x01, 0xC2, 0x08, 0x20, 0x78, 0x62, 0xF3, 0x83, 0x00, 0x20, 0x70,
+ 0x91, 0xF8, 0x34, 0x21, 0x52, 0x08, 0x62, 0xF3, 0x00, 0x00, 0x20, 0x70, 0x91, 0xF8, 0x34, 0x21,
+ 0x92, 0x08, 0x62, 0xF3, 0x41, 0x00, 0x04, 0xF8, 0x27, 0x09, 0x91, 0xF8, 0x33, 0x01, 0xC0, 0xF3,
+ 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, 0x44, 0xFF, 0x30, 0x68, 0x90, 0xF8, 0x33, 0x01, 0x01, 0x09,
+ 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, 0x04, 0x10, 0x20, 0x70, 0xE3, 0x48, 0x01, 0xF0, 0xAB, 0xFE,
+ 0xA4, 0xF8, 0x60, 0x00, 0xE0, 0x48, 0x20, 0x30, 0x01, 0xF0, 0xA5, 0xFE, 0xA4, 0xF8, 0x62, 0x00,
+ 0x30, 0x68, 0x90, 0xF8, 0x32, 0x11, 0xCA, 0x08, 0xE1, 0x7A, 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72,
+ 0x90, 0xF8, 0x33, 0x01, 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09,
+ 0x20, 0x46, 0x01, 0xF0, 0xD9, 0xF9, 0x30, 0x68, 0x90, 0xF8, 0x36, 0x01, 0x81, 0x09, 0x20, 0x46,
+ 0x01, 0xF0, 0x03, 0xFF, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0,
+ 0xF0, 0x00, 0xA0, 0x30, 0x04, 0xF8, 0x1C, 0x09, 0x31, 0x68, 0x91, 0xF8, 0x32, 0x01, 0x82, 0x09,
+ 0x60, 0x7F, 0x62, 0xF3, 0x00, 0x00, 0x60, 0x77, 0x91, 0xF8, 0x32, 0x21, 0x52, 0x09, 0x62, 0xF3,
+ 0x41, 0x00, 0x60, 0x77, 0x91, 0xF8, 0x38, 0x21, 0x62, 0xF3, 0x82, 0x00, 0x60, 0x77, 0x91, 0xF8,
+ 0x51, 0x01, 0xE2, 0x7D, 0x60, 0xF3, 0x04, 0x02, 0xE2, 0x75, 0x91, 0xF8, 0x52, 0x01, 0xA1, 0x7D,
+ 0x60, 0xF3, 0x04, 0x01, 0xBD, 0x48, 0xA1, 0x75, 0x94, 0xF8, 0x49, 0x10, 0x40, 0x78, 0x60, 0xF3,
+ 0x04, 0x01, 0x84, 0xF8, 0x49, 0x10, 0xBA, 0x48, 0x01, 0xF0, 0x55, 0xFE, 0xA4, 0xF8, 0x64, 0x00,
+ 0x30, 0x68, 0x21, 0x8B, 0xB0, 0xF8, 0x40, 0x21, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x83, 0x90, 0xF8,
+ 0x36, 0x11, 0xCA, 0x08, 0x94, 0xF8, 0x22, 0x10, 0x62, 0xF3, 0x02, 0x01, 0x84, 0xF8, 0x22, 0x10,
+ 0x10, 0xF8, 0xE3, 0x1F, 0x22, 0x7D, 0x61, 0xF3, 0x03, 0x02, 0x22, 0x75, 0x10, 0xF8, 0x4F, 0x1B,
+ 0x0A, 0x09, 0x61, 0x7D, 0x62, 0xF3, 0x03, 0x01, 0x61, 0x75, 0x42, 0x79, 0xE1, 0x7C, 0x62, 0xF3,
+ 0x02, 0x01, 0xE1, 0x74, 0x01, 0x78, 0xCA, 0x09, 0xA1, 0x7F, 0x62, 0xF3, 0x00, 0x01, 0xA1, 0x77,
+ 0x94, 0xF8, 0x49, 0x10, 0x41, 0xF0, 0x20, 0x01, 0x84, 0xF8, 0x49, 0x10, 0x82, 0x78, 0xD2, 0x09,
+ 0x62, 0xF3, 0xC7, 0x11, 0x84, 0xF8, 0x49, 0x10, 0x42, 0x8B, 0xB4, 0xF8, 0x4A, 0x10, 0x62, 0xF3,
+ 0x08, 0x01, 0xA4, 0xF8, 0x4A, 0x10, 0x00, 0x21, 0xE1, 0x64, 0x41, 0x79, 0xCA, 0x08, 0x61, 0x7F,
+ 0x62, 0xF3, 0xC3, 0x01, 0x61, 0x77, 0x02, 0x78, 0x12, 0x09, 0x62, 0xF3, 0x04, 0x11, 0x61, 0x77,
+ 0xC1, 0x7F, 0x4A, 0x09, 0x14, 0xF8, 0x0E, 0x1C, 0x62, 0xF3, 0x06, 0x11, 0x04, 0xF8, 0x0E, 0x1C,
+ 0x41, 0x78, 0x4A, 0x09, 0xA1, 0x78, 0x62, 0xF3, 0xC3, 0x01, 0xA1, 0x70, 0x02, 0x78, 0x52, 0x08,
+ 0x62, 0xF3, 0x04, 0x11, 0xA1, 0x70, 0x82, 0x78, 0x92, 0x09, 0x62, 0xF3, 0x86, 0x11, 0xA1, 0x70,
+ 0x40, 0x78, 0xC0, 0xF3, 0x80, 0x10, 0x68, 0x71, 0xF8, 0xBD, 0xA4, 0x22, 0x85, 0x49, 0x03, 0xF0,
+ 0xF9, 0xBC, 0x2D, 0xE9, 0xF0, 0x41, 0x84, 0x4D, 0x00, 0x26, 0x01, 0x27, 0x2E, 0x71, 0xAF, 0x71,
+ 0x2E, 0x72, 0x0C, 0x46, 0x6E, 0x72, 0x01, 0x28, 0x07, 0xD0, 0x7C, 0x4F, 0x02, 0x28, 0x2C, 0xD0,
+ 0x03, 0x28, 0x14, 0xD0, 0x04, 0x28, 0x3A, 0xD1, 0x44, 0xE0, 0x08, 0x46, 0xFF, 0xF7, 0xE5, 0xFF,
+ 0x7A, 0x48, 0x01, 0x68, 0x91, 0xF8, 0x38, 0x01, 0x42, 0x06, 0x30, 0xD5, 0x91, 0xF8, 0x55, 0x11,
+ 0x00, 0x06, 0x01, 0xF0, 0x03, 0x01, 0x29, 0x72, 0x29, 0xD5, 0x6F, 0x72, 0x27, 0xE0, 0x71, 0x48,
+ 0xFF, 0xF7, 0x00, 0xFE, 0x20, 0x46, 0xFF, 0xF7, 0xD0, 0xFF, 0xF8, 0x78, 0x94, 0xF8, 0x5F, 0x10,
+ 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0x94, 0xF8, 0x27, 0x00, 0x20, 0xF0, 0x02, 0x00,
+ 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x0C, 0xE0, 0x66, 0x48, 0xFF, 0xF7, 0xEA, 0xFD,
+ 0x20, 0x46, 0xFF, 0xF7, 0xBA, 0xFF, 0xB8, 0x78, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01,
+ 0x84, 0xF8, 0x5F, 0x10, 0x00, 0x21, 0x20, 0x46, 0x01, 0xF0, 0x3D, 0xFE, 0xAE, 0x71, 0x20, 0x46,
+ 0x01, 0xF0, 0x58, 0xFA, 0x94, 0xF8, 0x27, 0x00, 0x40, 0xF3, 0x00, 0x00, 0x40, 0x1C, 0xE8, 0x71,
+ 0xBD, 0xE8, 0xF0, 0x81, 0x08, 0x46, 0xFF, 0xF7, 0xA0, 0xFF, 0x20, 0x46, 0x01, 0xF0, 0x43, 0xF9,
+ 0xEC, 0xE7, 0x70, 0xB5, 0x55, 0x4D, 0x28, 0x68, 0x00, 0xF2, 0x5E, 0x62, 0x00, 0xF6, 0x6E, 0x04,
+ 0x90, 0xF8, 0x56, 0x16, 0x90, 0xF8, 0x57, 0x06, 0x02, 0xEB, 0x40, 0x00, 0x01, 0xF0, 0x77, 0xF8,
+ 0x28, 0x68, 0x90, 0xF8, 0x66, 0x18, 0x90, 0xF8, 0x67, 0x08, 0x04, 0xEB, 0x40, 0x00, 0xBD, 0xE8,
+ 0x70, 0x40, 0x01, 0xF0, 0x83, 0xB8, 0x70, 0xB5, 0x47, 0x4D, 0x46, 0x4C, 0x68, 0x79, 0xA4, 0x34,
+ 0x00, 0xB1, 0x02, 0x20, 0x68, 0x70, 0x21, 0x46, 0x28, 0x78, 0xFF, 0xF7, 0x7A, 0xFF, 0x43, 0x48,
+ 0x01, 0x68, 0xA0, 0x7C, 0x91, 0xF8, 0x50, 0x21, 0x62, 0xF3, 0x01, 0x00, 0xA0, 0x74, 0x91, 0xF8,
+ 0x50, 0x11, 0x89, 0x08, 0x61, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0x69, 0x78, 0x20, 0x46, 0x02, 0xF0,
+ 0x6C, 0xF8, 0xA0, 0x7C, 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0x78, 0xF8, 0xFF, 0xF7, 0xC1, 0xFF,
+ 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x36, 0x49, 0x02, 0xF0, 0x94, 0xB8, 0x70, 0xB5, 0x32, 0x4D,
+ 0x30, 0x4C, 0x68, 0x79, 0xA4, 0x34, 0x08, 0xB1, 0x03, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x68, 0x70,
+ 0x21, 0x46, 0x28, 0x78, 0xFF, 0xF7, 0x4D, 0xFF, 0x2C, 0x48, 0x01, 0x68, 0x91, 0xF8, 0x50, 0x01,
+ 0x02, 0x09, 0xA0, 0x7C, 0x62, 0xF3, 0x01, 0x00, 0xA0, 0x74, 0x91, 0xF8, 0x50, 0x11, 0x89, 0x09,
+ 0x61, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0x69, 0x78, 0x20, 0x46, 0x02, 0xF0, 0x3E, 0xF8, 0xA0, 0x7C,
+ 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF0, 0x4A, 0xF8, 0xFF, 0xF7, 0x93, 0xFF, 0x20, 0x46, 0xBD, 0xE8,
+ 0x70, 0x40, 0x20, 0x49, 0x02, 0xF0, 0x66, 0xB8, 0x7F, 0xB5, 0x00, 0xF0, 0xD7, 0xFF, 0xCD, 0xE9,
+ 0x00, 0x01, 0x00, 0xF0, 0xD8, 0xFF, 0xCD, 0xE9, 0x02, 0x01, 0x08, 0x21, 0x68, 0x46, 0x02, 0xF0,
+ 0x59, 0xF9, 0x15, 0x4C, 0x08, 0x21, 0xA0, 0x70, 0x02, 0xA8, 0x02, 0xF0, 0x53, 0xF9, 0xE0, 0x70,
+ 0x0E, 0x4D, 0x01, 0x24, 0xE0, 0xB2, 0xFF, 0xF7, 0xD2, 0xFC, 0x28, 0x55, 0x64, 0x1C, 0x05, 0x2C,
+ 0xF8, 0xDB, 0x0C, 0x48, 0xFF, 0xF7, 0x36, 0xFD, 0x7F, 0xBD, 0x10, 0xB5, 0x80, 0x79, 0xD8, 0xB1,
+ 0x09, 0x49, 0x08, 0x70, 0x4F, 0xF0, 0xFF, 0x30, 0xC8, 0x60, 0xFF, 0xF7, 0xFF, 0xFB, 0x00, 0x20,
+ 0x10, 0xBD, 0x00, 0x00, 0x0C, 0x58, 0x01, 0x20, 0xB0, 0x5C, 0x01, 0x20, 0xC8, 0x5E, 0x01, 0x20,
+ 0xB4, 0x59, 0x01, 0x20, 0x90, 0x80, 0x10, 0x00, 0x90, 0x07, 0x10, 0x00, 0x20, 0x07, 0x10, 0x00,
+ 0x23, 0x28, 0x01, 0x00, 0xB9, 0x28, 0x01, 0x00, 0x01, 0x20, 0xE9, 0xE7, 0x10, 0xB9, 0x77, 0x4A,
+ 0x75, 0x49, 0x11, 0x61, 0x00, 0xF0, 0x1F, 0xBF, 0x70, 0xB5, 0x75, 0x4D, 0x04, 0x46, 0x28, 0x68,
+ 0x90, 0xF8, 0xF1, 0x01, 0xC0, 0xF3, 0x01, 0x12, 0xC0, 0xF3, 0x81, 0x01, 0x00, 0xF0, 0x03, 0x00,
+ 0xFE, 0xF7, 0xF9, 0xF8, 0x40, 0x1C, 0xC6, 0xB2, 0x20, 0x46, 0x00, 0xF0, 0xAA, 0xFC, 0x6A, 0x48,
+ 0x01, 0xF0, 0xB9, 0xFC, 0xA4, 0xF8, 0x76, 0x00, 0x00, 0x22, 0x31, 0x46, 0x20, 0x46, 0x01, 0xF0,
+ 0xB7, 0xFE, 0xA0, 0x79, 0x40, 0xF0, 0x02, 0x00, 0xA0, 0x71, 0x94, 0xF8, 0x6F, 0x00, 0x66, 0xF3,
+ 0x02, 0x00, 0x84, 0xF8, 0x6F, 0x00, 0x94, 0xF8, 0x6E, 0x00, 0x20, 0xF0, 0x0F, 0x00, 0x84, 0xF8,
+ 0x6E, 0x00, 0x29, 0x68, 0xA0, 0x7C, 0x91, 0xF8, 0x08, 0x21, 0x62, 0xF3, 0x01, 0x00, 0xA0, 0x74,
+ 0x91, 0xF8, 0x08, 0x21, 0x92, 0x08, 0x62, 0xF3, 0x87, 0x10, 0xA0, 0x74, 0xA0, 0x89, 0x6F, 0xF3,
+ 0x0B, 0x00, 0xA0, 0x81, 0x91, 0xF8, 0x07, 0x01, 0xA0, 0x70, 0x94, 0xF8, 0x5E, 0x00, 0x00, 0x21,
+ 0x20, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, 0x20, 0x46, 0x01, 0xF0, 0x24, 0xFD, 0x28, 0x68,
+ 0x90, 0xF8, 0xF2, 0x11, 0x84, 0xF8, 0x66, 0x10, 0x90, 0xF8, 0xF3, 0x11, 0x84, 0xF8, 0x68, 0x10,
+ 0x90, 0xF8, 0xF4, 0x11, 0x84, 0xF8, 0x6A, 0x10, 0x90, 0xF8, 0xF5, 0x01, 0x84, 0xF8, 0x6C, 0x00,
+ 0x45, 0x48, 0x94, 0xF8, 0x5F, 0x10, 0x00, 0x1F, 0x40, 0x78, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8,
+ 0x5F, 0x10, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, 0xA2, 0xBF, 0x10, 0xB5, 0x3E, 0x4C,
+ 0x00, 0x20, 0x24, 0x1F, 0x20, 0x80, 0x01, 0x20, 0x00, 0xF0, 0x3B, 0xF8, 0x60, 0x70, 0x3D, 0x48,
+ 0xFF, 0xF7, 0x8A, 0xFF, 0x3B, 0x48, 0x3C, 0x49, 0xB0, 0xF8, 0x4E, 0x00, 0x08, 0x80, 0x10, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x37, 0x4E, 0x40, 0x79, 0x48, 0xB3, 0x37, 0x49, 0x30, 0x46, 0x09, 0x88,
+ 0xA6, 0xF8, 0x4E, 0x10, 0x01, 0xF0, 0x06, 0xF9, 0xB0, 0x7C, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF0,
+ 0x6D, 0xFF, 0x2F, 0x4F, 0x3C, 0x68, 0x04, 0xF2, 0x5E, 0x60, 0x94, 0xF8, 0x51, 0x26, 0x04, 0xF6,
+ 0x6E, 0x05, 0x94, 0xF8, 0x50, 0x16, 0x00, 0xEB, 0x42, 0x00, 0x00, 0xF0, 0x30, 0xFF, 0x38, 0x68,
+ 0x90, 0xF8, 0x60, 0x18, 0x90, 0xF8, 0x61, 0x08, 0x05, 0xEB, 0x40, 0x00, 0x00, 0xF0, 0x3E, 0xFF,
+ 0x26, 0x49, 0x30, 0x46, 0x01, 0xF0, 0x6C, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x01, 0x20,
+ 0xFB, 0xE7, 0x30, 0xB5, 0x1E, 0x49, 0x4F, 0xF4, 0x80, 0x75, 0x0A, 0x68, 0x92, 0xF8, 0x07, 0x11,
+ 0x92, 0xF8, 0xF5, 0x30, 0x92, 0xF8, 0xF2, 0x40, 0x03, 0xF0, 0x1F, 0x03, 0x04, 0xF0, 0x0F, 0x04,
+ 0xA9, 0x42, 0x00, 0xD9, 0x29, 0x46, 0x1F, 0x2B, 0x00, 0xD9, 0x1F, 0x23, 0x5B, 0x1C, 0x59, 0x43,
+ 0x49, 0x00, 0x64, 0x1C, 0x61, 0x43, 0xC1, 0xEB, 0x41, 0x21, 0xC9, 0x13, 0x92, 0xF8, 0x50, 0x3A,
+ 0xB1, 0xFA, 0x81, 0xF1, 0xC1, 0xF1, 0x20, 0x01, 0x9B, 0x07, 0x13, 0xD5, 0x00, 0x23, 0x01, 0x28,
+ 0x09, 0xD1, 0x92, 0xF8, 0x54, 0x0A, 0x02, 0x07, 0x03, 0xD5, 0x00, 0xF0, 0x07, 0x00, 0x43, 0x42,
+ 0x01, 0xE0, 0x00, 0xF0, 0x07, 0x03, 0xC9, 0x18, 0x01, 0xD5, 0x00, 0x21, 0x02, 0xE0, 0x1F, 0x29,
+ 0x00, 0xDD, 0x1F, 0x21, 0xC8, 0xB2, 0x30, 0xBD, 0x1C, 0x61, 0x01, 0x20, 0xD4, 0x83, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0xD8, 0x81, 0x10, 0x00, 0xA0, 0x07, 0x10, 0x00, 0xFD, 0x2F, 0x01, 0x00,
+ 0x2D, 0xE9, 0xF0, 0x5F, 0xDF, 0xF8, 0xA4, 0x85, 0x83, 0x46, 0x4F, 0xF0, 0x01, 0x09, 0xD8, 0xF8,
+ 0x00, 0x00, 0x00, 0x27, 0xAB, 0xF1, 0x02, 0x01, 0x00, 0xF2, 0x5E, 0x64, 0xCA, 0x46, 0x06, 0x29,
+ 0x50, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x4F, 0x09, 0x2C, 0x4F, 0x2C, 0x03, 0x10, 0xF8, 0xD5, 0x6F,
+ 0x00, 0x79, 0x00, 0xF0, 0x1F, 0x05, 0x6D, 0xE0, 0x90, 0xF8, 0xF5, 0x10, 0x90, 0xF8, 0x01, 0x61,
+ 0x01, 0xF0, 0x1F, 0x05, 0x90, 0xF8, 0xF2, 0x10, 0x01, 0xF0, 0x0F, 0x07, 0x90, 0xF8, 0xE6, 0x10,
+ 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x52, 0x16, 0x90, 0xF8, 0x53, 0x06, 0x0A, 0x22, 0x04, 0xEB,
+ 0x40, 0x00, 0x00, 0xF0, 0x81, 0xFE, 0x81, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE6, 0x10,
+ 0x49, 0x06, 0x4F, 0xD5, 0x90, 0xF8, 0x62, 0x18, 0x90, 0xF8, 0x63, 0x08, 0x44, 0xE0, 0x90, 0xF8,
+ 0xFC, 0x10, 0x90, 0xF8, 0xF8, 0x60, 0x01, 0xF0, 0x1F, 0x05, 0x90, 0xF8, 0xF9, 0x10, 0x01, 0xF0,
+ 0x0F, 0x07, 0x90, 0xF8, 0xE6, 0x10, 0x89, 0x06, 0x09, 0xD5, 0x90, 0xF8, 0x54, 0x16, 0x90, 0xF8,
+ 0x55, 0x06, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x00, 0xF0, 0x5E, 0xFE, 0x81, 0x46, 0xD8, 0xF8,
+ 0x00, 0x00, 0x90, 0xF8, 0xE6, 0x10, 0x49, 0x06, 0x2C, 0xD5, 0x90, 0xF8, 0x64, 0x18, 0x90, 0xF8,
+ 0x65, 0x08, 0x21, 0xE0, 0x90, 0xF8, 0xF5, 0x10, 0x90, 0xF8, 0xF1, 0x60, 0x01, 0xF0, 0x1F, 0x05,
+ 0x90, 0xF8, 0xF2, 0x10, 0x01, 0xF0, 0x0F, 0x07, 0x90, 0xF8, 0xE6, 0x10, 0x89, 0x06, 0x09, 0xD5,
+ 0x90, 0xF8, 0x50, 0x16, 0x90, 0xF8, 0x51, 0x06, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x00, 0xF0,
+ 0x3B, 0xFE, 0x81, 0x46, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0xE6, 0x10, 0x49, 0x06, 0x09, 0xD5,
+ 0x90, 0xF8, 0x60, 0x18, 0x90, 0xF8, 0x61, 0x08, 0x0A, 0x22, 0x04, 0xEB, 0x40, 0x00, 0x00, 0xF0,
+ 0x2B, 0xFE, 0x82, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x86, 0x42, 0x00, 0xD9, 0x06, 0x46, 0x1F, 0x2D,
+ 0x00, 0xD9, 0x1F, 0x25, 0x6D, 0x1C, 0x6E, 0x43, 0x70, 0x00, 0x7F, 0x1C, 0x78, 0x43, 0xC0, 0xEB,
+ 0x40, 0x20, 0x00, 0xFB, 0x09, 0xF0, 0x00, 0xFB, 0x0A, 0xF0, 0xC0, 0x13, 0xD8, 0xF8, 0x00, 0x20,
+ 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x20, 0x01, 0x92, 0xF8, 0x50, 0x0A, 0xC0, 0x07, 0x23, 0xD0,
+ 0x00, 0x20, 0xBB, 0xF1, 0x05, 0x0F, 0x11, 0xD2, 0xDF, 0xE8, 0x0B, 0xF0, 0x10, 0x03, 0x06, 0x09,
+ 0x14, 0x00, 0x92, 0xF8, 0x51, 0x0A, 0x04, 0xE0, 0x92, 0xF8, 0x51, 0x0A, 0x0C, 0xE0, 0x92, 0xF8,
+ 0x52, 0x0A, 0x02, 0x07, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xD5, 0x40, 0x42, 0x09, 0x18, 0x08, 0xD5,
+ 0x00, 0x21, 0x09, 0xE0, 0x92, 0xF8, 0x52, 0x0A, 0x02, 0x06, 0xC0, 0xF3, 0x02, 0x10, 0xF4, 0xD4,
+ 0xF4, 0xE7, 0x1F, 0x29, 0x00, 0xDD, 0x1F, 0x21, 0xC8, 0xB2, 0xBD, 0xE8, 0xF0, 0x9F, 0x70, 0xB5,
+ 0x06, 0x00, 0x03, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, 0x55, 0xBD, 0x00, 0xF0, 0x18, 0xF8,
+ 0x01, 0x28, 0x14, 0xD1, 0xFE, 0x4D, 0xFF, 0x4C, 0x28, 0x78, 0x01, 0x28, 0x09, 0xD0, 0xFE, 0x48,
+ 0xA0, 0x60, 0x68, 0x78, 0xE0, 0x73, 0xE8, 0x78, 0xA0, 0x73, 0xE8, 0x88, 0xA0, 0x81, 0x30, 0x46,
+ 0xE8, 0xE7, 0x6A, 0x79, 0x29, 0x79, 0xF8, 0x48, 0x00, 0xF0, 0x55, 0xFE, 0xF0, 0xE7, 0x70, 0xBD,
+ 0xF3, 0x4B, 0x10, 0xB5, 0xD9, 0x78, 0xF5, 0x4C, 0x49, 0x1C, 0xCA, 0xB2, 0xDA, 0x70, 0x99, 0x78,
+ 0x01, 0x20, 0x8A, 0x42, 0x11, 0xD8, 0x19, 0x79, 0x58, 0x79, 0x41, 0x43, 0xEE, 0x48, 0xFD, 0xF7,
+ 0xB2, 0xFF, 0x01, 0xF0, 0xD8, 0xFA, 0xA4, 0xF8, 0x76, 0x00, 0x20, 0x46, 0x00, 0xF0, 0x92, 0xFF,
+ 0xEB, 0x49, 0x20, 0x46, 0x01, 0xF0, 0x14, 0xFD, 0x00, 0x20, 0x10, 0xBD, 0x38, 0xB5, 0x04, 0x46,
+ 0x01, 0xF0, 0xC4, 0xFA, 0xE4, 0x48, 0x01, 0xF0, 0xC6, 0xFA, 0xA4, 0xF8, 0x76, 0x00, 0x00, 0xF0,
+ 0x85, 0xFD, 0xDE, 0x4D, 0x0B, 0x46, 0x2A, 0x68, 0x92, 0xF8, 0xE7, 0x20, 0xC2, 0xF3, 0x41, 0x12,
+ 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x9A, 0xFC, 0x00, 0xF0, 0x7C, 0xFD, 0x02, 0x46,
+ 0x0B, 0x46, 0x20, 0x46, 0x01, 0xF0, 0xBF, 0xFC, 0xA0, 0x79, 0x20, 0xF0, 0x02, 0x00, 0xA0, 0x71,
+ 0x94, 0xF8, 0x6F, 0x00, 0x20, 0xF0, 0x07, 0x00, 0x84, 0xF8, 0x6F, 0x00, 0x94, 0xF8, 0x6E, 0x00,
+ 0x20, 0xF0, 0x0F, 0x00, 0x84, 0xF8, 0x6E, 0x00, 0x28, 0x68, 0x90, 0xF8, 0xE7, 0x00, 0xC0, 0xF3,
+ 0x41, 0x11, 0x20, 0x46, 0x01, 0xF0, 0xC1, 0xFC, 0x28, 0x68, 0x90, 0xF8, 0xE7, 0x00, 0x10, 0xF0,
+ 0x60, 0x0F, 0x94, 0xF8, 0x5E, 0x00, 0x7D, 0xD0, 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00,
+ 0x20, 0x46, 0x00, 0xF0, 0xFF, 0xFD, 0x05, 0x21, 0x20, 0x46, 0x01, 0xF0, 0xAD, 0xFA, 0x28, 0x68,
+ 0x90, 0xF8, 0xF1, 0x00, 0xA0, 0x70, 0x28, 0x68, 0x21, 0x8E, 0xB0, 0xF8, 0xF6, 0x20, 0x62, 0xF3,
+ 0x08, 0x01, 0x21, 0x86, 0x90, 0xF8, 0xF2, 0x00, 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x01, 0xF0,
+ 0x12, 0xFB, 0x28, 0x68, 0x62, 0x7D, 0x90, 0xF8, 0xEA, 0x10, 0x61, 0xF3, 0x03, 0x02, 0x62, 0x75,
+ 0xB0, 0xF8, 0xED, 0x20, 0x21, 0x8A, 0x62, 0xF3, 0x0B, 0x01, 0x21, 0x82, 0x90, 0xF8, 0xF3, 0x10,
+ 0xA2, 0x7D, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x75, 0x10, 0xF8, 0xF2, 0x1F, 0x0A, 0x09, 0xA1, 0x7C,
+ 0x62, 0xF3, 0x01, 0x01, 0xA1, 0x74, 0x10, 0xF8, 0x0C, 0x29, 0x92, 0x09, 0x62, 0xF3, 0x87, 0x11,
+ 0xA1, 0x74, 0x01, 0x78, 0xE2, 0x79, 0x61, 0xF3, 0x00, 0x02, 0xE2, 0x71, 0xC1, 0x78, 0x61, 0x72,
+ 0x80, 0x79, 0x01, 0x09, 0x20, 0x46, 0x01, 0xF0, 0xF2, 0xFA, 0xA6, 0x48, 0x01, 0xF0, 0x43, 0xFA,
+ 0xA4, 0xF8, 0x7C, 0x00, 0x29, 0x68, 0x11, 0xF8, 0xE8, 0x0F, 0xC2, 0x08, 0x94, 0xF8, 0x27, 0x00,
+ 0x62, 0xF3, 0x83, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x11, 0xF8, 0x01, 0x29, 0x52, 0x08, 0x62, 0xF3,
+ 0x00, 0x00, 0x84, 0xF8, 0x27, 0x00, 0x4A, 0x78, 0x92, 0x08, 0x62, 0xF3, 0x41, 0x00, 0x84, 0xF8,
+ 0x27, 0x00, 0x08, 0x78, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0, 0xB1, 0xFA, 0x28, 0x68,
+ 0x90, 0xF8, 0xE7, 0x00, 0x01, 0x09, 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3, 0x04, 0x10, 0x20, 0x70,
+ 0x91, 0x48, 0x01, 0xF0, 0x18, 0xFA, 0xA4, 0xF8, 0x5E, 0x00, 0x28, 0x68, 0x10, 0xF8, 0xE6, 0x1F,
+ 0xCA, 0x08, 0x00, 0xE0, 0x8F, 0xE0, 0xE1, 0x7A, 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, 0x40, 0x78,
+ 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, 0x20, 0x46, 0x00, 0xF0,
+ 0x3F, 0xFD, 0x28, 0x68, 0x90, 0xF8, 0xEC, 0x00, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0,
+ 0x74, 0xFA, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, 0xF0, 0x00,
+ 0xA0, 0x30, 0x04, 0xF8, 0x0A, 0x09, 0x29, 0x68, 0x11, 0xF8, 0xE6, 0x0F, 0x82, 0x09, 0xE0, 0x7A,
+ 0x62, 0xF3, 0x00, 0x00, 0xE0, 0x72, 0x0A, 0x78, 0x52, 0x09, 0x62, 0xF3, 0x41, 0x00, 0xE0, 0x72,
+ 0x4A, 0x79, 0xD2, 0x09, 0x62, 0xF3, 0x82, 0x00, 0xE0, 0x72, 0x88, 0x7B, 0x62, 0x79, 0x60, 0xF3,
+ 0x04, 0x02, 0x62, 0x71, 0xC8, 0x7B, 0x21, 0x79, 0x60, 0xF3, 0x04, 0x01, 0x6F, 0x48, 0x21, 0x71,
+ 0x94, 0xF8, 0x37, 0x10, 0x40, 0x78, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x37, 0x10, 0x6C, 0x48,
+ 0x01, 0xF0, 0xC9, 0xF9, 0xA4, 0xF8, 0x52, 0x00, 0x28, 0x68, 0xE1, 0x88, 0xB0, 0xF8, 0xEF, 0x20,
+ 0x62, 0xF3, 0x0B, 0x01, 0xE1, 0x80, 0x90, 0xF8, 0xEB, 0x10, 0xCA, 0x08, 0x21, 0x7C, 0x62, 0xF3,
+ 0x02, 0x01, 0x21, 0x74, 0x10, 0xF8, 0xE2, 0x1F, 0xA2, 0x78, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x70,
+ 0x01, 0x78, 0x0A, 0x09, 0xE1, 0x78, 0x62, 0xF3, 0x03, 0x01, 0xE1, 0x70, 0x01, 0x7A, 0x0A, 0x09,
+ 0x61, 0x78, 0x62, 0xF3, 0x02, 0x01, 0x61, 0x70, 0x81, 0x79, 0x8A, 0x09, 0x21, 0x78, 0x62, 0xF3,
+ 0x00, 0x01, 0x21, 0x70, 0x01, 0x79, 0xCA, 0x09, 0x21, 0x7B, 0x62, 0xF3, 0x00, 0x01, 0x21, 0x73,
+ 0x94, 0xF8, 0x37, 0x10, 0x41, 0xF0, 0x20, 0x01, 0x84, 0xF8, 0x37, 0x10, 0x21, 0x8F, 0x6F, 0xF3,
+ 0x08, 0x01, 0x01, 0xF5, 0x80, 0x71, 0x21, 0x87, 0x00, 0x21, 0xC4, 0xF8, 0x3A, 0x10, 0x41, 0x7A,
+ 0x8A, 0x09, 0xE1, 0x7A, 0x62, 0xF3, 0xC3, 0x01, 0xE1, 0x72, 0x00, 0x79, 0x00, 0x09, 0x60, 0xF3,
+ 0x04, 0x11, 0xE1, 0x72, 0x38, 0xBD, 0x20, 0xF0, 0x01, 0x00, 0xEF, 0xE6, 0x38, 0xB5, 0x04, 0x46,
+ 0x01, 0xF0, 0x74, 0xF9, 0x3C, 0x48, 0x01, 0xF0, 0x76, 0xF9, 0xA4, 0xF8, 0x76, 0x00, 0x00, 0xF0,
+ 0x35, 0xFC, 0x36, 0x4D, 0x0B, 0x46, 0x2A, 0x68, 0x92, 0xF8, 0xC9, 0x20, 0xC2, 0xF3, 0x41, 0x12,
+ 0x00, 0x92, 0x02, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x4A, 0xFB, 0x00, 0xF0, 0x2C, 0xFC, 0x02, 0x46,
+ 0x0B, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x6F, 0xFB, 0xA0, 0x79, 0x20, 0xF0, 0x02, 0x00, 0xA0, 0x71,
+ 0x94, 0xF8, 0x6F, 0x00, 0x20, 0xF0, 0x07, 0x00, 0x84, 0xF8, 0x6F, 0x00, 0x94, 0xF8, 0x6E, 0x00,
+ 0x20, 0xF0, 0x0F, 0x00, 0x84, 0xF8, 0x6E, 0x00, 0x28, 0x68, 0x90, 0xF8, 0xC9, 0x00, 0xC0, 0xF3,
+ 0x41, 0x11, 0x20, 0x46, 0x01, 0xF0, 0x71, 0xFB, 0x28, 0x68, 0x90, 0xF8, 0xC9, 0x00, 0x10, 0xF0,
+ 0x60, 0x0F, 0x94, 0xF8, 0x5E, 0x00, 0x7D, 0xD0, 0x40, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00,
+ 0x20, 0x46, 0x00, 0xF0, 0xAF, 0xFC, 0x28, 0x68, 0x90, 0xF8, 0xD5, 0x00, 0xA0, 0x70, 0x28, 0x68,
+ 0x21, 0x8E, 0xB0, 0xF8, 0xDA, 0x20, 0x62, 0xF3, 0x08, 0x01, 0x21, 0x86, 0x90, 0xF8, 0xD6, 0x00,
+ 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x01, 0xF0, 0xC6, 0xF9, 0x28, 0x68, 0x62, 0x7D, 0x90, 0xF8,
+ 0xCC, 0x10, 0x61, 0xF3, 0x03, 0x02, 0x62, 0x75, 0xB0, 0xF8, 0xCF, 0x20, 0x21, 0x8A, 0x62, 0xF3,
+ 0x0B, 0x01, 0x21, 0x82, 0x90, 0xF8, 0xD7, 0x10, 0xA2, 0x7D, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x75,
+ 0xB0, 0xF8, 0xD1, 0x20, 0xA1, 0x89, 0x62, 0xF3, 0x0B, 0x01, 0xA1, 0x81, 0x10, 0xF8, 0xD6, 0x1F,
+ 0x0A, 0x09, 0xA1, 0x7C, 0x62, 0xF3, 0x01, 0x01, 0xA1, 0x74, 0x13, 0xE0, 0x20, 0x07, 0x10, 0x00,
+ 0xA2, 0x07, 0x10, 0x00, 0xD4, 0x83, 0x10, 0x00, 0x4C, 0x62, 0x01, 0x20, 0x20, 0x83, 0x10, 0x00,
+ 0x8F, 0x33, 0x01, 0x00, 0xFC, 0x4C, 0x01, 0x20, 0x88, 0x5C, 0x01, 0x20, 0x4E, 0x7B, 0x01, 0x20,
+ 0xB4, 0x59, 0x01, 0x20, 0x10, 0xF8, 0x0D, 0x29, 0x92, 0x09, 0x62, 0xF3, 0x87, 0x11, 0xA1, 0x74,
+ 0x10, 0xF8, 0x01, 0x1C, 0xE2, 0x79, 0x61, 0xF3, 0x00, 0x02, 0xE2, 0x71, 0x81, 0x78, 0x61, 0x72,
+ 0x40, 0x79, 0x01, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x8A, 0xF9, 0xFB, 0x48, 0x01, 0xF0, 0xDB, 0xF8,
+ 0xA4, 0xF8, 0x7C, 0x00, 0x28, 0x68, 0x10, 0xF8, 0xCA, 0x1F, 0xCA, 0x08, 0x94, 0xF8, 0x27, 0x10,
+ 0x62, 0xF3, 0x83, 0x01, 0x84, 0xF8, 0x27, 0x10, 0x10, 0xF8, 0x01, 0x29, 0x52, 0x08, 0x62, 0xF3,
+ 0x00, 0x01, 0x84, 0xF8, 0x27, 0x10, 0x42, 0x78, 0x92, 0x08, 0x62, 0xF3, 0x41, 0x01, 0x84, 0xF8,
+ 0x27, 0x10, 0x00, 0xE0, 0xAA, 0xE0, 0x00, 0x78, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0,
+ 0x47, 0xF9, 0x28, 0x68, 0x90, 0xF8, 0xC9, 0x00, 0x01, 0x09, 0x14, 0xF8, 0x28, 0x0F, 0x61, 0xF3,
+ 0x04, 0x10, 0x20, 0x70, 0xE5, 0x48, 0x01, 0xF0, 0xAE, 0xF8, 0xA4, 0xF8, 0x5E, 0x00, 0x28, 0x68,
+ 0x10, 0xF8, 0xC8, 0x1F, 0xCA, 0x08, 0xE1, 0x7A, 0x62, 0xF3, 0x45, 0x11, 0xE1, 0x72, 0x40, 0x78,
+ 0x41, 0x08, 0x20, 0x78, 0x61, 0xF3, 0x45, 0x10, 0x04, 0xF8, 0x28, 0x09, 0x20, 0x46, 0x00, 0xF0,
+ 0xD7, 0xFB, 0x28, 0x68, 0x90, 0xF8, 0xCE, 0x00, 0xC0, 0xF3, 0x81, 0x01, 0x20, 0x46, 0x01, 0xF0,
+ 0x0C, 0xF9, 0x14, 0xF8, 0x32, 0x0F, 0x20, 0xF0, 0x0F, 0x00, 0x0A, 0x30, 0x20, 0xF0, 0xF0, 0x00,
+ 0xA0, 0x30, 0x04, 0xF8, 0x0A, 0x09, 0x29, 0x68, 0x11, 0xF8, 0xC8, 0x0F, 0x82, 0x09, 0xE0, 0x7A,
+ 0x62, 0xF3, 0x00, 0x00, 0xE0, 0x72, 0x0A, 0x78, 0x52, 0x09, 0x62, 0xF3, 0x41, 0x00, 0xE0, 0x72,
+ 0x4A, 0x79, 0xD2, 0x09, 0x62, 0xF3, 0x82, 0x00, 0xE0, 0x72, 0x08, 0x7C, 0x62, 0x79, 0x60, 0xF3,
+ 0x04, 0x02, 0x62, 0x71, 0x48, 0x7C, 0x21, 0x79, 0x60, 0xF3, 0x04, 0x01, 0xC4, 0x48, 0x21, 0x71,
+ 0x94, 0xF8, 0x37, 0x10, 0xC0, 0x79, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x37, 0x10, 0xC1, 0x48,
+ 0x01, 0xF0, 0x61, 0xF8, 0xA4, 0xF8, 0x52, 0x00, 0x28, 0x68, 0xE1, 0x88, 0xB0, 0xF8, 0xD3, 0x20,
+ 0x62, 0xF3, 0x0B, 0x01, 0xE1, 0x80, 0x10, 0xF8, 0xCD, 0x1F, 0xCA, 0x08, 0x21, 0x7C, 0x62, 0xF3,
+ 0x02, 0x01, 0x21, 0x74, 0x10, 0xF8, 0x15, 0x1F, 0xA2, 0x78, 0x61, 0xF3, 0x03, 0x02, 0xA2, 0x70,
+ 0x10, 0xF8, 0x1A, 0x19, 0x0A, 0x09, 0xE1, 0x78, 0x62, 0xF3, 0x03, 0x01, 0xE1, 0x70, 0x01, 0x79,
+ 0x0A, 0x09, 0x61, 0x78, 0x62, 0xF3, 0x02, 0x01, 0x61, 0x70, 0x81, 0x78, 0x8A, 0x09, 0x21, 0x78,
+ 0x62, 0xF3, 0x00, 0x01, 0x21, 0x70, 0x01, 0x78, 0xCA, 0x09, 0x21, 0x7B, 0x62, 0xF3, 0x00, 0x01,
+ 0x21, 0x73, 0x01, 0x79, 0xCA, 0x09, 0x94, 0xF8, 0x37, 0x10, 0x62, 0xF3, 0x45, 0x11, 0x84, 0xF8,
+ 0x37, 0x10, 0x21, 0x8F, 0x6F, 0xF3, 0x08, 0x01, 0x01, 0xF5, 0x80, 0x71, 0x21, 0x87, 0x00, 0x21,
+ 0xC4, 0xF8, 0x3A, 0x10, 0x41, 0x79, 0x8A, 0x09, 0xE1, 0x7A, 0x62, 0xF3, 0xC3, 0x01, 0xE1, 0x72,
+ 0x00, 0x78, 0x00, 0x09, 0x60, 0xF3, 0x04, 0x11, 0xE1, 0x72, 0x38, 0xBD, 0x20, 0xF0, 0x01, 0x00,
+ 0xD4, 0xE6, 0x10, 0xB5, 0x04, 0x46, 0xA4, 0x22, 0x97, 0x49, 0x02, 0xF0, 0x1B, 0xFF, 0x97, 0x48,
+ 0xC1, 0x78, 0xA0, 0x89, 0x61, 0xF3, 0x0B, 0x00, 0xA0, 0x81, 0x10, 0xBD, 0x38, 0xB5, 0x04, 0x46,
+ 0xFF, 0xF7, 0xEF, 0xFF, 0x00, 0xF0, 0xC2, 0xFA, 0x00, 0x22, 0x00, 0x92, 0x02, 0x46, 0x0B, 0x46,
+ 0x20, 0x46, 0x01, 0xF0, 0xDC, 0xF9, 0x8E, 0x48, 0x00, 0xF0, 0xF5, 0xFF, 0x8D, 0x4D, 0xA4, 0xF8,
+ 0x7C, 0x00, 0x28, 0x68, 0x90, 0xF8, 0xF8, 0x00, 0xA0, 0x70, 0x28, 0x68, 0x90, 0xF8, 0xF9, 0x00,
+ 0x00, 0xF0, 0x0F, 0x01, 0x20, 0x46, 0x01, 0xF0, 0x86, 0xF8, 0x28, 0x68, 0x10, 0xF8, 0xF9, 0x1F,
+ 0x0A, 0x09, 0xA1, 0x7C, 0x62, 0xF3, 0x01, 0x01, 0xA1, 0x74, 0x02, 0x78, 0x92, 0x09, 0x62, 0xF3,
+ 0x87, 0x11, 0xA1, 0x74, 0x81, 0x78, 0x94, 0xF8, 0x2D, 0x20, 0x61, 0xF3, 0x04, 0x02, 0x84, 0xF8,
+ 0x2D, 0x20, 0xC1, 0x78, 0x94, 0xF8, 0x2C, 0x20, 0x61, 0xF3, 0x04, 0x02, 0x84, 0xF8, 0x2C, 0x20,
+ 0x40, 0x78, 0xA1, 0x7D, 0x60, 0xF3, 0x03, 0x01, 0xA1, 0x75, 0x00, 0x21, 0x20, 0x46, 0x01, 0xF0,
+ 0xEC, 0xF9, 0x14, 0xF8, 0x5E, 0x0F, 0x20, 0xF0, 0x01, 0x00, 0x04, 0xF8, 0x01, 0x0B, 0x6C, 0x48,
+ 0x01, 0x79, 0x20, 0x78, 0x61, 0xF3, 0x04, 0x00, 0x04, 0xF8, 0x2F, 0x09, 0x28, 0x68, 0xB0, 0xF8,
+ 0xFD, 0x10, 0x20, 0x88, 0x61, 0xF3, 0x08, 0x00, 0x20, 0x80, 0x38, 0xBD, 0x70, 0xB5, 0x69, 0x4E,
+ 0x03, 0x28, 0x34, 0x68, 0x04, 0xF2, 0x5E, 0x62, 0x04, 0xF6, 0x6E, 0x05, 0x14, 0xD0, 0x04, 0x28,
+ 0x20, 0xD0, 0x94, 0xF8, 0x51, 0x06, 0x94, 0xF8, 0x50, 0x16, 0x02, 0xEB, 0x40, 0x00, 0x00, 0xF0,
+ 0x96, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0x60, 0x18, 0x90, 0xF8, 0x61, 0x08, 0x05, 0xEB, 0x40, 0x00,
+ 0xBD, 0xE8, 0x70, 0x40, 0x00, 0xF0, 0xA2, 0xBA, 0x94, 0xF8, 0x53, 0x06, 0x94, 0xF8, 0x52, 0x16,
+ 0x02, 0xEB, 0x40, 0x00, 0x00, 0xF0, 0x83, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0x62, 0x18, 0x90, 0xF8,
+ 0x63, 0x08, 0xEB, 0xE7, 0x94, 0xF8, 0x55, 0x06, 0x94, 0xF8, 0x54, 0x16, 0x02, 0xEB, 0x40, 0x00,
+ 0x00, 0xF0, 0x75, 0xFA, 0x30, 0x68, 0x90, 0xF8, 0x64, 0x18, 0x90, 0xF8, 0x65, 0x08, 0xDD, 0xE7,
+ 0x2D, 0xE9, 0xF8, 0x43, 0x4C, 0x4D, 0x4F, 0xF0, 0x01, 0x09, 0x00, 0x26, 0x85, 0xF8, 0x00, 0x90,
+ 0xAE, 0x70, 0x43, 0x4F, 0xDF, 0xF8, 0x1C, 0x81, 0x04, 0x46, 0xEE, 0x70, 0x09, 0x29, 0x72, 0xD2,
+ 0xDF, 0xE8, 0x01, 0xF0, 0x71, 0x05, 0x09, 0x18, 0x44, 0x2F, 0x48, 0x5E, 0x62, 0x00, 0x20, 0x46,
+ 0xFF, 0xF7, 0x47, 0xFF, 0x67, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x43, 0xFF, 0xB8, 0x78, 0x94, 0xF8,
+ 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8,
+ 0xFF, 0x00, 0x12, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x34, 0xFF, 0xD8, 0xF8, 0x00, 0x10, 0x91, 0xF8,
+ 0x01, 0x11, 0xA1, 0x70, 0xF9, 0x78, 0x94, 0xF8, 0x5F, 0x20, 0x61, 0xF3, 0x04, 0x02, 0x84, 0xF8,
+ 0x5F, 0x20, 0xD8, 0xF8, 0x00, 0x00, 0x90, 0xF8, 0x00, 0x01, 0x00, 0xF0, 0x03, 0x00, 0xA8, 0x70,
+ 0x41, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x1D, 0xFF, 0x00, 0x21, 0x20, 0x46, 0x00, 0xF0, 0xCB, 0xFF,
+ 0x94, 0xF8, 0x5E, 0x00, 0x20, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, 0x78, 0x79, 0x94, 0xF8,
+ 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10, 0x17, 0xE0, 0x20, 0x46, 0xFF, 0xF7,
+ 0x15, 0xFF, 0x28, 0xE0, 0x20, 0x46, 0xFF, 0xF7, 0x11, 0xFF, 0x00, 0x21, 0x20, 0x46, 0x00, 0xF0,
+ 0xB2, 0xFF, 0xB8, 0x79, 0x94, 0xF8, 0x5F, 0x10, 0x60, 0xF3, 0x04, 0x01, 0x84, 0xF8, 0x5F, 0x10,
+ 0x94, 0xF8, 0x5E, 0x00, 0x20, 0xF0, 0x01, 0x00, 0x84, 0xF8, 0x5E, 0x00, 0x2E, 0x70, 0x12, 0xE0,
+ 0x20, 0x46, 0xFF, 0xF7, 0x83, 0xFD, 0xF9, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0xEA, 0xFE, 0x01, 0x22,
+ 0x00, 0x23, 0x20, 0x46, 0x00, 0x96, 0x01, 0xF0, 0xDA, 0xF8, 0x20, 0x46, 0x00, 0xF0, 0xAB, 0xFA,
+ 0x20, 0x46, 0x00, 0xF0, 0x2D, 0xFA, 0x20, 0x46, 0x00, 0xF0, 0xAC, 0xFB, 0x94, 0xF8, 0x27, 0x00,
+ 0xC0, 0x07, 0x13, 0xD0, 0x6E, 0x70, 0x13, 0xE0, 0xFC, 0x4C, 0x01, 0x20, 0x88, 0x5C, 0x01, 0x20,
+ 0x4E, 0x7B, 0x01, 0x20, 0xB4, 0x59, 0x01, 0x20, 0x7C, 0x82, 0x10, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0x24, 0x52, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0xA2, 0x07, 0x10, 0x00, 0x85, 0xF8, 0x01, 0x90,
+ 0xA0, 0x89, 0xC0, 0xF3, 0x0B, 0x00, 0xE8, 0x80, 0xBD, 0xE8, 0xF8, 0x83, 0x7F, 0xB5, 0x00, 0xF0,
+ 0x8D, 0xF9, 0xCD, 0xE9, 0x00, 0x01, 0x00, 0xF0, 0x8E, 0xF9, 0xCD, 0xE9, 0x02, 0x01, 0x08, 0x21,
+ 0x68, 0x46, 0x01, 0xF0, 0x0F, 0xFB, 0x1E, 0x4C, 0x08, 0x21, 0x20, 0x71, 0x02, 0xA8, 0x01, 0xF0,
+ 0x09, 0xFB, 0x60, 0x71, 0x1B, 0x48, 0x00, 0x21, 0x1A, 0x4D, 0x40, 0xF8, 0x02, 0x1F, 0x01, 0x24,
+ 0x41, 0x60, 0x01, 0x72, 0xAD, 0x1C, 0xE0, 0xB2, 0xFF, 0xF7, 0xD2, 0xFA, 0x28, 0x55, 0x64, 0x1C,
+ 0x09, 0x2C, 0xF8, 0xDB, 0x14, 0x48, 0xFF, 0xF7, 0xD9, 0xFB, 0x7F, 0xBD, 0x70, 0xB5, 0x12, 0x4D,
+ 0x04, 0x79, 0xA4, 0x35, 0x8C, 0xB1, 0x21, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x29, 0xFF, 0xA8, 0x7C,
+ 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF0, 0xC2, 0xF9, 0x20, 0x46, 0xFF, 0xF7, 0xE7, 0xFE, 0x0B, 0x49,
+ 0x28, 0x46, 0x01, 0xF0, 0xD5, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0x01, 0x20, 0x70, 0xBD, 0x40, 0xF2,
+ 0xFF, 0x10, 0xC1, 0xEB, 0x41, 0x21, 0x91, 0xFB, 0xF0, 0xF0, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00,
+ 0xA2, 0x07, 0x10, 0x00, 0x4C, 0x7B, 0x01, 0x20, 0x7C, 0x82, 0x10, 0x00, 0x8F, 0x33, 0x01, 0x00,
+ 0x10, 0xB5, 0x00, 0xF0, 0x7D, 0xFA, 0xFF, 0xF7, 0xA9, 0xFF, 0xFF, 0xF7, 0x0F, 0xFA, 0xFF, 0xF7,
+ 0x5B, 0xF9, 0xFE, 0xF7, 0xC2, 0xFC, 0xFE, 0xF7, 0x38, 0xFD, 0x00, 0xF0, 0x8D, 0xFA, 0x7F, 0x49,
+ 0x00, 0x20, 0x48, 0x60, 0x70, 0x21, 0x7E, 0x48, 0x02, 0xF0, 0xF3, 0xFD, 0x7D, 0x48, 0x04, 0x68,
+ 0x94, 0xF8, 0xE7, 0x00, 0xC0, 0x06, 0x05, 0xD5, 0x28, 0x22, 0x04, 0xF5, 0x0F, 0x61, 0x78, 0x48,
+ 0x02, 0xF0, 0x68, 0xFD, 0x94, 0xF8, 0x33, 0x01, 0xC0, 0x06, 0x0F, 0xD5, 0x74, 0x48, 0x20, 0x22,
+ 0x04, 0xF6, 0x16, 0x11, 0x28, 0x30, 0x02, 0xF0, 0x5D, 0xFD, 0x04, 0xF6, 0x3F, 0x11, 0x70, 0x48,
+ 0x28, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x48, 0x30, 0x02, 0xF0, 0x54, 0xBD, 0x10, 0xBD, 0x38, 0xB1,
+ 0x01, 0x28, 0x07, 0xD0, 0x02, 0x28, 0x07, 0xD0, 0x17, 0x20, 0x00, 0x21, 0xFC, 0xF7, 0x97, 0xBA,
+ 0x14, 0x20, 0xFA, 0xE7, 0x15, 0x20, 0xF8, 0xE7, 0x16, 0x20, 0xF6, 0xE7, 0x00, 0x21, 0x01, 0x60,
+ 0x41, 0x60, 0x81, 0x60, 0xC1, 0x60, 0x70, 0x47, 0x70, 0xB5, 0x60, 0x4C, 0x62, 0x4D, 0x20, 0x68,
+ 0x09, 0xE0, 0x00, 0xBF, 0x55, 0xF8, 0x20, 0x10, 0x60, 0x48, 0x88, 0x47, 0x00, 0x28, 0x11, 0xD0,
+ 0x20, 0x68, 0x40, 0x1C, 0x20, 0x60, 0x07, 0x28, 0xF4, 0xD3, 0x60, 0x68, 0x5B, 0x49, 0x40, 0x1C,
+ 0x10, 0x31, 0x00, 0x22, 0x60, 0x60, 0x0A, 0x70, 0x48, 0x60, 0x58, 0x48, 0x01, 0x68, 0x10, 0x30,
+ 0x88, 0x47, 0x01, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0x04, 0x46, 0x00, 0x79, 0x00, 0x25, 0x40, 0xB9,
+ 0xE0, 0x79, 0x30, 0xB9, 0xA0, 0x79, 0x20, 0xB9, 0x20, 0x7A, 0x10, 0xB9, 0x60, 0x79, 0x00, 0x28,
+ 0x17, 0xD0, 0x4E, 0x48, 0x34, 0x21, 0x10, 0x30, 0x02, 0xF0, 0xAD, 0xFD, 0x1E, 0xCC, 0x4B, 0x48,
+ 0x80, 0xE8, 0x1E, 0x00, 0x45, 0x48, 0x05, 0x60, 0x46, 0x48, 0x00, 0x68, 0x90, 0xF8, 0xB0, 0x00,
+ 0xC0, 0x07, 0x02, 0xD0, 0x00, 0xF0, 0x18, 0xFA, 0x02, 0xE0, 0x44, 0x48, 0xFF, 0xF7, 0xBC, 0xFF,
+ 0x01, 0x20, 0x70, 0xBD, 0x10, 0xB5, 0x01, 0x20, 0x00, 0xF0, 0x62, 0xF8, 0x07, 0x20, 0x00, 0xF0,
+ 0x5F, 0xF8, 0x08, 0x20, 0x00, 0xF0, 0x5C, 0xF8, 0x05, 0x20, 0x00, 0xF0, 0x59, 0xF8, 0x0D, 0x20,
+ 0x00, 0xF0, 0x56, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x53, 0xF8, 0x01, 0x20, 0x00, 0xF0, 0x5B, 0xF8,
+ 0x07, 0x20, 0x00, 0xF0, 0x58, 0xF8, 0x08, 0x20, 0x00, 0xF0, 0x55, 0xF8, 0x05, 0x20, 0x00, 0xF0,
+ 0x52, 0xF8, 0x0D, 0x20, 0x00, 0xF0, 0x4F, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x4C, 0xF8, 0x02, 0xF0,
+ 0x86, 0xF9, 0x00, 0xF0, 0xB3, 0xFD, 0x00, 0xF0, 0xDF, 0xF9, 0x01, 0x20, 0x00, 0xF0, 0x2D, 0xF8,
+ 0x07, 0x20, 0x00, 0xF0, 0x2A, 0xF8, 0x08, 0x20, 0x00, 0xF0, 0x27, 0xF8, 0xBD, 0xE8, 0x10, 0x40,
+ 0x05, 0x20, 0x00, 0xF0, 0x22, 0xB8, 0x70, 0xB5, 0x20, 0x4C, 0x05, 0x00, 0x0E, 0xD0, 0xFF, 0xF7,
+ 0xC1, 0xFF, 0x60, 0x68, 0x21, 0x49, 0x40, 0x1C, 0x10, 0x31, 0x60, 0x60, 0x0D, 0x70, 0x48, 0x60,
+ 0x1E, 0x48, 0x01, 0x68, 0xBD, 0xE8, 0x70, 0x40, 0x10, 0x30, 0x08, 0x47, 0x20, 0x68, 0x40, 0x1C,
+ 0x20, 0x60, 0xBD, 0xE8, 0x70, 0x40, 0x19, 0x48, 0x66, 0xE7, 0x00, 0xF0, 0x57, 0xB8, 0x00, 0xF0,
+ 0x5A, 0xB8, 0x00, 0xF0, 0x5D, 0xB8, 0x00, 0xF0, 0x61, 0xB8, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21,
+ 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x00, 0x11, 0x70, 0x47,
+ 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20,
+ 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09,
+ 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0xAC, 0x07, 0x10, 0x00,
+ 0x88, 0x5C, 0x01, 0x20, 0x20, 0x07, 0x10, 0x00, 0x4C, 0x6F, 0x01, 0x00, 0xC4, 0x83, 0x10, 0x00,
+ 0x70, 0xB5, 0x00, 0x23, 0x14, 0x46, 0x09, 0xE0, 0x31, 0xF9, 0x13, 0x50, 0x31, 0xF9, 0x14, 0x60,
+ 0x35, 0x44, 0x6D, 0x10, 0x20, 0xF8, 0x13, 0x50, 0x5B, 0x1C, 0x64, 0x1C, 0x93, 0x42, 0xF3, 0xDB,
+ 0x70, 0xBD, 0x30, 0xB4, 0x00, 0x24, 0x4B, 0xB9, 0x0C, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x14, 0x30,
+ 0x31, 0xF8, 0x14, 0x50, 0x2B, 0x44, 0x20, 0xF8, 0x14, 0x30, 0x64, 0x1C, 0x94, 0x42, 0xF5, 0xDB,
+ 0x30, 0xBC, 0x70, 0x47, 0x30, 0xBC, 0x52, 0x00, 0x02, 0xF0, 0x4C, 0xBC, 0x99, 0x48, 0x00, 0x68,
+ 0xC1, 0x6A, 0x80, 0x6A, 0x70, 0x47, 0x97, 0x48, 0x00, 0x68, 0x41, 0x6A, 0x00, 0x6A, 0x70, 0x47,
+ 0x94, 0x48, 0x00, 0x68, 0x00, 0xF6, 0x38, 0x20, 0x03, 0xC8, 0x70, 0x47, 0x91, 0x48, 0x00, 0x68,
+ 0x00, 0xF5, 0x23, 0x60, 0x03, 0xC8, 0x70, 0x47, 0xF0, 0xB5, 0x00, 0x24, 0x25, 0x46, 0x8E, 0x4E,
+ 0x4F, 0xF4, 0x00, 0x67, 0x14, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x15, 0x30, 0xC3, 0xF3, 0x0B, 0x03,
+ 0x5F, 0xEA, 0xD3, 0x2C, 0x00, 0xD0, 0x33, 0x43, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, 0x9C, 0x42,
+ 0x00, 0xDA, 0x9C, 0xB2, 0xBC, 0x42, 0x02, 0xD3, 0x40, 0xF2, 0xFF, 0x74, 0x02, 0xE0, 0x6D, 0x1C,
+ 0x8D, 0x42, 0xE9, 0xDB, 0xD4, 0x40, 0x01, 0x20, 0xA0, 0x40, 0x80, 0xB2, 0xF0, 0xBD, 0x30, 0xB5,
+ 0x7F, 0x4B, 0x7E, 0x4C, 0x5A, 0x68, 0x82, 0x42, 0x02, 0xD1, 0xDA, 0x68, 0x8A, 0x42, 0x0A, 0xD0,
+ 0x00, 0x22, 0x06, 0xE0, 0x30, 0xF8, 0x12, 0x50, 0xC5, 0xF3, 0x0B, 0x05, 0x24, 0xF8, 0x12, 0x50,
+ 0x52, 0x1C, 0x8A, 0x42, 0xF6, 0xDB, 0xD9, 0x60, 0x58, 0x60, 0x30, 0xBD, 0x30, 0xB5, 0x74, 0x4B,
+ 0x74, 0x4C, 0x9A, 0x68, 0x82, 0x42, 0x02, 0xD1, 0x1A, 0x69, 0x8A, 0x42, 0x0D, 0xD0, 0x00, 0x22,
+ 0x07, 0xE0, 0x00, 0xBF, 0x30, 0xF8, 0x12, 0x50, 0xC5, 0xF3, 0x0B, 0x05, 0x24, 0xF8, 0x12, 0x50,
+ 0x52, 0x1C, 0x8A, 0x42, 0xF6, 0xDB, 0x19, 0x61, 0x98, 0x60, 0x30, 0xBD, 0x70, 0xB5, 0x04, 0x46,
+ 0x69, 0x48, 0x01, 0x68, 0x02, 0x29, 0x0A, 0xD1, 0x65, 0x4D, 0x29, 0x78, 0x8C, 0x42, 0x06, 0xD0,
+ 0x00, 0xEB, 0x84, 0x00, 0xD0, 0xF8, 0x9C, 0x00, 0x00, 0xF0, 0xD7, 0xFC, 0x2C, 0x70, 0x70, 0xBD,
+ 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x28, 0x00, 0x80, 0x06, 0x04, 0xD5, 0x5F, 0x48, 0x00, 0xF0,
+ 0xBA, 0xFC, 0xA4, 0xF8, 0x8C, 0x00, 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x28, 0x00,
+ 0x80, 0x06, 0x0A, 0xD5, 0x59, 0x48, 0x28, 0x30, 0x00, 0xF0, 0xAD, 0xFC, 0x24, 0xF8, 0x8E, 0x0F,
+ 0x56, 0x48, 0x48, 0x30, 0x00, 0xF0, 0xA7, 0xFC, 0x60, 0x80, 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46,
+ 0x90, 0xF8, 0x28, 0x00, 0x80, 0x06, 0x05, 0xD5, 0x50, 0x48, 0x70, 0x30, 0x00, 0xF0, 0x9B, 0xFC,
+ 0xA4, 0xF8, 0x8E, 0x00, 0x10, 0xBD, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x02, 0x00, 0x4F, 0xF0,
+ 0x00, 0x00, 0x00, 0xD1, 0x08, 0x46, 0x70, 0x47, 0x02, 0x46, 0x00, 0x20, 0x01, 0x2A, 0x00, 0xD1,
+ 0x08, 0x46, 0x70, 0x47, 0x3F, 0x49, 0x0A, 0x68, 0x92, 0xF8, 0xB0, 0x20, 0x93, 0x09, 0x10, 0xF8,
+ 0x3E, 0x2B, 0x63, 0xF3, 0x82, 0x02, 0x00, 0xF8, 0x3E, 0x2C, 0x0B, 0x68, 0x93, 0xF8, 0xB0, 0x30,
+ 0x5B, 0x09, 0x63, 0xF3, 0x45, 0x12, 0x00, 0xF8, 0x3E, 0x2C, 0x09, 0x68, 0xB1, 0xF8, 0xB7, 0x20,
+ 0x02, 0x82, 0x91, 0xF8, 0xB6, 0x20, 0x83, 0x7F, 0x62, 0xF3, 0x07, 0x13, 0x83, 0x77, 0x91, 0xF8,
+ 0xB3, 0x20, 0x13, 0x09, 0x02, 0x7D, 0x63, 0xF3, 0x06, 0x12, 0x02, 0x75, 0x31, 0xF8, 0xB1, 0x3F,
+ 0x02, 0x8B, 0x63, 0xF3, 0x09, 0x02, 0x02, 0x83, 0x11, 0xF8, 0x01, 0x2C, 0x93, 0x08, 0x82, 0x7D,
+ 0x63, 0xF3, 0x86, 0x12, 0x82, 0x75, 0x8A, 0x78, 0xC3, 0x7D, 0x62, 0xF3, 0x03, 0x03, 0xC3, 0x75,
+ 0xB1, 0xF8, 0x03, 0x30, 0xB0, 0xF8, 0x1B, 0x20, 0x63, 0xF3, 0x08, 0x02, 0xA0, 0xF8, 0x1B, 0x20,
+ 0x09, 0x89, 0x41, 0x82, 0x70, 0x47, 0x10, 0xF8, 0x37, 0x1F, 0x41, 0xF0, 0x10, 0x01, 0x00, 0xF8,
+ 0x1F, 0x19, 0x30, 0xF8, 0x0C, 0x2C, 0xC1, 0x7E, 0x6F, 0xF3, 0x0B, 0x02, 0x10, 0x32, 0x20, 0xF8,
+ 0x0C, 0x2C, 0x30, 0xF8, 0x08, 0x2C, 0x21, 0xF0, 0x23, 0x01, 0x6F, 0xF3, 0x0B, 0x02, 0x40, 0x32,
+ 0x20, 0xF8, 0x08, 0x2C, 0x08, 0x22, 0x00, 0xF8, 0x16, 0x2C, 0x90, 0xF8, 0x47, 0x20, 0x41, 0xF0,
+ 0x0C, 0x01, 0x22, 0xF0, 0x1F, 0x02, 0x80, 0xF8, 0x47, 0x20, 0x02, 0x8B, 0x6F, 0xF3, 0x08, 0x02,
+ 0x02, 0x83, 0xC1, 0x76, 0xC1, 0x8A, 0x6F, 0xF3, 0x0B, 0x01, 0x3F, 0x31, 0xC1, 0x82, 0x41, 0x7D,
+ 0x21, 0xF0, 0x1F, 0x01, 0x41, 0x75, 0x01, 0x7D, 0x21, 0xF0, 0x1F, 0x01, 0x01, 0x75, 0x90, 0xF8,
+ 0x46, 0x10, 0x21, 0xF0, 0x01, 0x01, 0x80, 0xF8, 0x46, 0x10, 0x01, 0x7C, 0x41, 0xF0, 0x20, 0x01,
+ 0x01, 0x74, 0x70, 0x47, 0x20, 0x07, 0x10, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xB4, 0x59, 0x01, 0x20,
+ 0xB4, 0x07, 0x10, 0x00, 0xB4, 0x5B, 0x01, 0x20, 0x08, 0x84, 0x10, 0x00, 0xF8, 0x5B, 0x01, 0x20,
+ 0x70, 0x47, 0x10, 0xB5, 0x00, 0xF0, 0x93, 0xFE, 0x08, 0xB1, 0x01, 0x20, 0x10, 0xBD, 0x08, 0x48,
+ 0x00, 0xF0, 0x76, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x06, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x90, 0xF8,
+ 0x70, 0x00, 0x40, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x77, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x00,
+ 0x47, 0x3E, 0x01, 0x00, 0x20, 0x07, 0x10, 0x00, 0x7B, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x70,
+ 0x81, 0x70, 0xC1, 0x70, 0x01, 0x71, 0x70, 0x47, 0x70, 0xB5, 0x0D, 0x20, 0x00, 0xF0, 0xD5, 0xF8,
+ 0x0D, 0x20, 0x00, 0xF0, 0xDD, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0xCF, 0xF8, 0x0C, 0x20, 0x00, 0xF0,
+ 0xD7, 0xF8, 0x71, 0x4C, 0x71, 0x48, 0xA5, 0x78, 0xC0, 0x7A, 0xA0, 0x70, 0xEC, 0xF7, 0xC6, 0xF8,
+ 0xA2, 0x78, 0x01, 0x21, 0x00, 0x20, 0xA2, 0xB1, 0x23, 0x78, 0xAB, 0xB1, 0x95, 0x42, 0x20, 0xD1,
+ 0x01, 0x2A, 0x1E, 0xD0, 0x02, 0x2A, 0xE2, 0x78, 0x1E, 0xD0, 0x02, 0xB1, 0xE0, 0x70, 0x22, 0x79,
+ 0x52, 0x1C, 0xD2, 0xB2, 0x22, 0x71, 0x04, 0x2A, 0x1E, 0xD3, 0x20, 0x71, 0xE1, 0x70, 0x04, 0x20,
+ 0x1B, 0xE0, 0x21, 0x70, 0xE0, 0x70, 0x02, 0xE0, 0x02, 0x22, 0x22, 0x70, 0xE1, 0x70, 0x20, 0x71,
+ 0xEC, 0xF7, 0xA2, 0xF8, 0xE0, 0x78, 0x60, 0x70, 0xBD, 0xE8, 0x70, 0x40, 0x5B, 0x48, 0xFF, 0xF7,
+ 0x6B, 0xBD, 0xE1, 0x70, 0x20, 0x71, 0xEA, 0xE7, 0x0A, 0xB1, 0xE0, 0x70, 0x00, 0xE0, 0xE1, 0x70,
+ 0x20, 0x71, 0xE0, 0x78, 0x00, 0x28, 0xE2, 0xD1, 0x05, 0x20, 0x20, 0x70, 0xBD, 0xE8, 0x70, 0x40,
+ 0xEC, 0xF7, 0x8A, 0xB8, 0x70, 0xB5, 0x50, 0x4C, 0x20, 0x78, 0x04, 0x28, 0x06, 0xD0, 0x20, 0x78,
+ 0x00, 0x25, 0x05, 0x28, 0x07, 0xD0, 0x25, 0x70, 0x65, 0x70, 0x70, 0xBD, 0x02, 0x20, 0x20, 0x70,
+ 0x01, 0x20, 0x60, 0x70, 0x0C, 0xE0, 0x4A, 0x48, 0xA1, 0x78, 0x00, 0x68, 0x02, 0x29, 0x0C, 0xD0,
+ 0x90, 0xF8, 0xBE, 0x00, 0x47, 0x49, 0x01, 0xF0, 0x0F, 0xFF, 0x03, 0x20, 0x20, 0x70, 0x65, 0x70,
+ 0xBD, 0xE8, 0x70, 0x40, 0x41, 0x48, 0xFF, 0xF7, 0x37, 0xBD, 0x90, 0xF8, 0xBD, 0x00, 0xF1, 0xE7,
+ 0x10, 0xB5, 0x0D, 0x20, 0x00, 0xF0, 0x61, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x5E, 0xF8, 0x3A, 0x4C,
+ 0x3B, 0x49, 0xA0, 0x78, 0x03, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x06, 0xD0, 0x01, 0x28, 0x08, 0xD0,
+ 0x0D, 0xE0, 0x08, 0x68, 0x90, 0xF8, 0xBE, 0x00, 0x06, 0xE0, 0x08, 0x68, 0x90, 0xF8, 0xBC, 0x00,
+ 0x02, 0xE0, 0x08, 0x68, 0x90, 0xF8, 0xBB, 0x00, 0x32, 0x49, 0x01, 0xF0, 0xE5, 0xFE, 0x03, 0x20,
+ 0x20, 0x70, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x2D, 0x4C, 0x07, 0x46, 0x2A, 0x4D, 0x20, 0x68,
+ 0x4F, 0xF0, 0x00, 0x06, 0x90, 0xF8, 0xB0, 0x10, 0xC9, 0x07, 0x0E, 0xD0, 0x69, 0x78, 0x01, 0x29,
+ 0x0E, 0xD0, 0xA7, 0xF8, 0x4E, 0x60, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0xF3, 0xC1, 0x00, 0x02, 0x28,
+ 0x1E, 0xD0, 0x00, 0x21, 0x38, 0x46, 0x00, 0xF0, 0x4F, 0xFB, 0x6E, 0x70, 0xBD, 0xE8, 0xF0, 0x81,
+ 0x0D, 0x20, 0x00, 0xF0, 0x2D, 0xF8, 0x0C, 0x20, 0x00, 0xF0, 0x2A, 0xF8, 0x20, 0x68, 0x90, 0xF8,
+ 0xB0, 0x00, 0xC0, 0xF3, 0xC1, 0x00, 0x02, 0x28, 0x08, 0xD0, 0x0D, 0x20, 0x00, 0xF0, 0x0A, 0xF8,
+ 0x20, 0x68, 0x90, 0xF8, 0xB0, 0x00, 0xC0, 0xF3, 0xC1, 0x01, 0xE3, 0xE7, 0x0C, 0x20, 0xF5, 0xE7,
+ 0x02, 0x21, 0xDF, 0xE7, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00,
+ 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x00, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21,
+ 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47,
+ 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20,
+ 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0x00, 0x00, 0xC8, 0x07, 0x10, 0x00, 0xC4, 0x83, 0x10, 0x00,
+ 0x20, 0x07, 0x10, 0x00, 0x95, 0x42, 0x01, 0x00, 0x46, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x04, 0x01,
+ 0x01, 0x60, 0x00, 0xF0, 0xFB, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xF6, 0xFF, 0x10, 0xBD, 0x10, 0xB5,
+ 0xFF, 0xF7, 0xF2, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xEE, 0xFF, 0x10, 0xBD, 0x10, 0xB5,
+ 0xFF, 0xF7, 0xEA, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x57, 0xBC, 0x10, 0xB5, 0xFF, 0xF7,
+ 0xE3, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xDC, 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0xDC, 0xFF,
+ 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x5F, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xD5, 0xFF, 0xBD, 0xE8,
+ 0x10, 0x40, 0x01, 0xF0, 0xC3, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xCE, 0xFF, 0xBD, 0xE8, 0x10, 0x40,
+ 0x01, 0xF0, 0x27, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xC7, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0,
+ 0x8D, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xC0, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x05, 0xBF,
+ 0x10, 0xB5, 0xFF, 0xF7, 0xB9, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0x6B, 0xBF, 0x10, 0xB5,
+ 0xFF, 0xF7, 0xB2, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0xD1, 0xBF, 0x10, 0xB5, 0xFF, 0xF7,
+ 0xAB, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0x95, 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0xA4, 0xFF,
+ 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0x6A, 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0x9D, 0xFF, 0xBD, 0xE8,
+ 0x10, 0x40, 0xFF, 0xF7, 0x15, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, 0x96, 0xFF, 0xBD, 0xE8, 0x10, 0x40,
+ 0xFF, 0xF7, 0x0E, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, 0x8F, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7,
+ 0x8B, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0xF0, 0xEE, 0xBF, 0x10, 0xB5, 0xFF, 0xF7, 0x84, 0xFF,
+ 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x80, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x7C, 0xFF,
+ 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x78, 0xFF, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0x74, 0xFF,
+ 0x10, 0xBD, 0x70, 0x47, 0x10, 0xED, 0x00, 0xE0, 0x0E, 0xB5, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90,
+ 0x02, 0x90, 0x09, 0x48, 0x00, 0xF0, 0x13, 0xFE, 0x68, 0x46, 0x00, 0xF0, 0x14, 0xFE, 0xFC, 0xF7,
+ 0x38, 0xFD, 0xFC, 0xF7, 0x39, 0xFB, 0x00, 0xF0, 0x31, 0xF8, 0x00, 0x21, 0x47, 0x20, 0xFB, 0xF7,
+ 0x96, 0xFE, 0x01, 0x20, 0x0E, 0xBD, 0x00, 0x00, 0x10, 0x00, 0x32, 0x02, 0x1A, 0x49, 0x10, 0xB5,
+ 0x01, 0x20, 0x08, 0x70, 0x19, 0x49, 0x00, 0x20, 0x08, 0x60, 0x19, 0x49, 0x08, 0x60, 0x19, 0x49,
+ 0x08, 0x60, 0x19, 0x49, 0x08, 0x60, 0x00, 0xF0, 0x7F, 0xF9, 0x00, 0xF0, 0x19, 0xF9, 0x00, 0xF0,
+ 0x7D, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x12, 0x48, 0x02, 0xF0, 0x31, 0xF8, 0x10, 0x49,
+ 0x08, 0x60, 0x0E, 0x49, 0x09, 0x68, 0x88, 0x42, 0x07, 0xD0, 0x0B, 0x48, 0x00, 0x78, 0x02, 0x28,
+ 0x03, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0xEB, 0xF7, 0xC9, 0xBE, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7,
+ 0xEA, 0xFF, 0x05, 0x49, 0x02, 0x20, 0x08, 0x70, 0xEB, 0xF7, 0xA4, 0xFE, 0x4F, 0xF0, 0xFF, 0x30,
+ 0x10, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00,
+ 0x20, 0x08, 0x10, 0x00, 0x24, 0x08, 0x10, 0x00, 0x28, 0x08, 0x10, 0x00, 0x70, 0xB5, 0x0D, 0x46,
+ 0x04, 0x46, 0xC1, 0x69, 0x80, 0x68, 0xCC, 0x22, 0x02, 0xF0, 0x73, 0xF9, 0xE1, 0x69, 0xA0, 0x68,
+ 0x00, 0x22, 0x08, 0x44, 0x4F, 0xF0, 0x80, 0x71, 0x40, 0xF8, 0x04, 0x1C, 0x21, 0x6A, 0x40, 0xE9,
+ 0x03, 0x21, 0x40, 0xF8, 0x10, 0x2C, 0x40, 0xF8, 0x14, 0x2C, 0x40, 0xF8, 0x18, 0x2C, 0x40, 0xF8,
+ 0x1C, 0x2C, 0x4F, 0xF0, 0x0B, 0x31, 0x40, 0xE9, 0x09, 0x15, 0x4F, 0xF0, 0x0A, 0x31, 0x40, 0xF8,
+ 0x28, 0x1C, 0x4F, 0xF0, 0x09, 0x31, 0x40, 0xF8, 0x2C, 0x1C, 0x4F, 0xF0, 0x08, 0x31, 0x40, 0xF8,
+ 0x30, 0x1C, 0x4F, 0xF0, 0x07, 0x31, 0x40, 0xF8, 0x34, 0x1C, 0x4F, 0xF0, 0x06, 0x31, 0x40, 0xF8,
+ 0x38, 0x1C, 0x4F, 0xF0, 0x05, 0x31, 0x40, 0xF8, 0x3C, 0x1C, 0x4F, 0xF0, 0x04, 0x31, 0x40, 0xF8,
+ 0x40, 0x1D, 0x70, 0xBD, 0x81, 0x69, 0x4F, 0xF0, 0xCC, 0x33, 0x0A, 0x68, 0x9A, 0x42, 0x08, 0xD1,
+ 0x4A, 0x68, 0x9A, 0x42, 0x05, 0xD1, 0x8A, 0x68, 0x9A, 0x42, 0x02, 0xD1, 0xC9, 0x68, 0x99, 0x42,
+ 0x02, 0xD0, 0x40, 0x68, 0xFC, 0xF7, 0xE7, 0xBA, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0xA0, 0x21,
+ 0x49, 0x48, 0x02, 0xF0, 0x50, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x06, 0x46, 0x46, 0x48,
+ 0x00, 0xEB, 0x06, 0x14, 0xEB, 0xF7, 0x8A, 0xFE, 0x05, 0x46, 0x20, 0x78, 0x28, 0xB1, 0x28, 0x46,
+ 0xEB, 0xF7, 0x8C, 0xFE, 0x6F, 0xF0, 0x01, 0x00, 0x70, 0xBD, 0x03, 0x20, 0x20, 0x70, 0x00, 0x20,
+ 0x66, 0x60, 0xE0, 0x60, 0x04, 0xF1, 0x08, 0x00, 0x01, 0xF0, 0x74, 0xFF, 0x28, 0x46, 0xEB, 0xF7,
+ 0x7D, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x46, 0x36, 0x49, 0x00, 0x25,
+ 0x01, 0xEB, 0x00, 0x14, 0x2E, 0x46, 0xEB, 0xF7, 0x69, 0xFE, 0x80, 0x46, 0xE0, 0x68, 0x38, 0x43,
+ 0xE0, 0x60, 0x04, 0xF1, 0x08, 0x00, 0x07, 0x46, 0x01, 0xF0, 0x82, 0xFF, 0x0C, 0xE0, 0xE1, 0x68,
+ 0xC2, 0x6A, 0x11, 0x42, 0x03, 0xD0, 0x00, 0xF0, 0x0F, 0xF9, 0x01, 0x26, 0x00, 0xE0, 0x6D, 0x1C,
+ 0x29, 0x46, 0x38, 0x46, 0x01, 0xF0, 0x6A, 0xFF, 0x00, 0x28, 0xF0, 0xD1, 0x0E, 0xB1, 0xFF, 0xF7,
+ 0x3A, 0xFF, 0x40, 0x46, 0xEB, 0xF7, 0x52, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x70, 0xB5,
+ 0x0D, 0x46, 0x21, 0x49, 0x01, 0xEB, 0x00, 0x14, 0xEB, 0xF7, 0x40, 0xFE, 0xE1, 0x68, 0xA9, 0x43,
+ 0xE1, 0x60, 0xEB, 0xF7, 0x43, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0x0C, 0x46, 0x1A, 0x49,
+ 0x01, 0xEB, 0x00, 0x15, 0x00, 0x20, 0x20, 0x60, 0xEB, 0xF7, 0x30, 0xFE, 0xE9, 0x68, 0x21, 0x60,
+ 0xEB, 0xF7, 0x34, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x46, 0x12, 0x49,
+ 0x1E, 0x46, 0x90, 0x46, 0x01, 0xEB, 0x00, 0x14, 0xEB, 0xF7, 0x20, 0xFE, 0x07, 0x46, 0x0F, 0x48,
+ 0x00, 0x68, 0xC5, 0x62, 0xE1, 0x68, 0x29, 0x42, 0x03, 0xD1, 0x04, 0xF1, 0x08, 0x01, 0x00, 0xF0,
+ 0xDD, 0xF8, 0x38, 0x46, 0xEB, 0xF7, 0x1A, 0xFE, 0xEB, 0xF7, 0x10, 0xFE, 0xE1, 0x68, 0x29, 0x40,
+ 0x31, 0x60, 0xB8, 0xF1, 0x01, 0x0F, 0x02, 0xD1, 0xE1, 0x68, 0xA9, 0x43, 0xE1, 0x60, 0xEB, 0xF7,
+ 0x0D, 0xFE, 0x00, 0x20, 0xB9, 0xE7, 0x00, 0x00, 0xB4, 0x84, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00,
+ 0x10, 0xB5, 0xC8, 0x21, 0x2E, 0x48, 0x02, 0xF0, 0xB6, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x06, 0x46, 0x2A, 0x49, 0x00, 0xEB, 0x86, 0x00, 0x17, 0x46, 0x01, 0xEB, 0x80, 0x04,
+ 0xEB, 0xF7, 0xEC, 0xFD, 0x05, 0x46, 0x20, 0x78, 0x30, 0xB1, 0x28, 0x46, 0xEB, 0xF7, 0xEE, 0xFD,
+ 0x6F, 0xF0, 0x01, 0x00, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x20, 0x20, 0x70, 0x00, 0x20, 0x66, 0x60,
+ 0xC4, 0xE9, 0x02, 0x70, 0x04, 0xF1, 0x10, 0x00, 0x01, 0xF0, 0xD4, 0xFE, 0x28, 0x46, 0xEB, 0xF7,
+ 0xDD, 0xFD, 0x00, 0x20, 0xEE, 0xE7, 0x70, 0xB5, 0x19, 0x49, 0x00, 0xEB, 0x80, 0x00, 0x01, 0xEB,
+ 0x80, 0x04, 0xEB, 0xF7, 0xCB, 0xFD, 0x05, 0x46, 0xD4, 0xE9, 0x02, 0x01, 0x81, 0x42, 0x05, 0xDB,
+ 0x14, 0x48, 0x04, 0xF1, 0x10, 0x01, 0x00, 0x68, 0x00, 0xF0, 0x88, 0xF8, 0xE0, 0x68, 0x40, 0x1C,
+ 0xE0, 0x60, 0x28, 0x46, 0xEB, 0xF7, 0xC2, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x70, 0xB5, 0x0C, 0x49,
+ 0x00, 0xEB, 0x80, 0x00, 0x01, 0xEB, 0x80, 0x04, 0xEB, 0xF7, 0xB0, 0xFD, 0x05, 0x46, 0xE0, 0x68,
+ 0x08, 0xB1, 0x40, 0x1E, 0xE0, 0x60, 0x04, 0xF1, 0x10, 0x00, 0x01, 0xF0, 0xC9, 0xFE, 0x10, 0xB1,
+ 0x20, 0x69, 0x00, 0xF0, 0x11, 0xF8, 0x28, 0x46, 0xEB, 0xF7, 0xA8, 0xFD, 0x00, 0x20, 0x70, 0xBD,
+ 0x54, 0x85, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0xF0, 0x71, 0x3C, 0x48,
+ 0x02, 0xF0, 0x51, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x24, 0x00,
+ 0x02, 0x28, 0x0B, 0xD0, 0x20, 0x46, 0x01, 0xF0, 0xAD, 0xFE, 0x02, 0x20, 0x84, 0xF8, 0x24, 0x00,
+ 0x34, 0x49, 0x20, 0x46, 0x01, 0xF0, 0x82, 0xFE, 0xFF, 0xF7, 0x6D, 0xFE, 0x00, 0x20, 0x10, 0xBD,
+ 0x2D, 0xE9, 0xF0, 0x5F, 0x06, 0x46, 0x0A, 0xA8, 0x06, 0xEB, 0x46, 0x01, 0x90, 0xE8, 0x00, 0x0E,
+ 0x2B, 0x48, 0x1D, 0x46, 0x00, 0xEB, 0x01, 0x14, 0x90, 0x46, 0x20, 0x78, 0x18, 0xB1, 0x6F, 0xF0,
+ 0x01, 0x00, 0xBD, 0xE8, 0xF0, 0x9F, 0xEB, 0xF7, 0x69, 0xFD, 0x07, 0x46, 0x01, 0x20, 0x20, 0x70,
+ 0xC4, 0xF8, 0x14, 0x80, 0xC4, 0xE9, 0x01, 0x65, 0x04, 0xF1, 0x18, 0x01, 0x00, 0x20, 0x81, 0xE8,
+ 0x20, 0x06, 0x84, 0xF8, 0x24, 0x00, 0xE0, 0x60, 0x20, 0x61, 0xC4, 0xE9, 0x0A, 0x80, 0x59, 0x46,
+ 0x20, 0x46, 0xFF, 0xF7, 0x6B, 0xFE, 0xA0, 0x60, 0x20, 0x46, 0xFF, 0xF7, 0xBD, 0xFF, 0x38, 0x46,
+ 0xEB, 0xF7, 0x54, 0xFD, 0x00, 0x20, 0xDC, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x90, 0xF8, 0x24, 0x00,
+ 0x02, 0x28, 0x09, 0xD0, 0x20, 0x46, 0x01, 0xF0, 0x65, 0xFE, 0x02, 0x20, 0x84, 0xF8, 0x24, 0x00,
+ 0x10, 0x49, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x04, 0x46,
+ 0x90, 0xF8, 0x24, 0x00, 0x0D, 0x46, 0x02, 0x28, 0x0B, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0x52, 0xFE,
+ 0x03, 0x20, 0x84, 0xF8, 0x24, 0x00, 0x29, 0x46, 0x20, 0x46, 0x01, 0xF0, 0x27, 0xFE, 0xFF, 0xF7,
+ 0x12, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x04, 0x48, 0x00, 0x68, 0x40, 0x68, 0x70, 0x47, 0x00, 0x00,
+ 0x1C, 0x86, 0x10, 0x00, 0x24, 0x08, 0x10, 0x00, 0x1C, 0x08, 0x10, 0x00, 0x6D, 0x48, 0x00, 0x21,
+ 0x01, 0x60, 0x01, 0x22, 0x02, 0x60, 0x01, 0x60, 0x70, 0x47, 0x10, 0xB5, 0xFF, 0xF7, 0xF6, 0xFF,
+ 0x69, 0x48, 0x00, 0x21, 0x01, 0x70, 0x41, 0x60, 0x00, 0xF0, 0xF5, 0xF9, 0xBD, 0xE8, 0x10, 0x40,
+ 0x00, 0xF0, 0xD7, 0xBA, 0x01, 0xF0, 0xBF, 0xBC, 0x01, 0xF0, 0x2A, 0xBD, 0x10, 0xB5, 0x01, 0xF0,
+ 0x27, 0xFD, 0x01, 0xF0, 0xB8, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0xE6, 0xE7, 0xA4, 0x22, 0x5F, 0x49,
+ 0x01, 0xF0, 0x10, 0xBF, 0x70, 0x47, 0x10, 0xB5, 0x04, 0x46, 0x80, 0x07, 0x02, 0xD0, 0x02, 0x20,
+ 0xFF, 0xF7, 0xB5, 0xF9, 0x4F, 0xF4, 0x80, 0x30, 0x20, 0x44, 0xC0, 0xF3, 0x4F, 0x00, 0x10, 0xBD,
+ 0x01, 0x46, 0x98, 0x22, 0x56, 0x48, 0x01, 0xF0, 0xFD, 0xBE, 0x55, 0x4A, 0x00, 0x21, 0x42, 0xF8,
+ 0x21, 0x00, 0x49, 0x1C, 0x26, 0x29, 0xFA, 0xDB, 0x70, 0x47, 0x01, 0xF0, 0xDE, 0xBC, 0x01, 0xF0,
+ 0x5C, 0xBC, 0x4D, 0x48, 0x10, 0xB5, 0x40, 0x68, 0x10, 0xB1, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x47,
+ 0x00, 0x20, 0xFF, 0xF7, 0x94, 0xF9, 0x10, 0xBD, 0x06, 0x29, 0x37, 0xD2, 0xDF, 0xE8, 0x01, 0xF0,
+ 0x11, 0x24, 0x37, 0x24, 0x36, 0x03, 0x01, 0x78, 0x21, 0xF0, 0x12, 0x01, 0x00, 0xF8, 0x4D, 0x1B,
+ 0x01, 0x78, 0x21, 0xF0, 0x03, 0x01, 0x00, 0xF8, 0x07, 0x1B, 0x01, 0x78, 0x21, 0xF0, 0x80, 0x01,
+ 0x0C, 0xE0, 0x01, 0x78, 0x21, 0xF0, 0x02, 0x01, 0x41, 0xF0, 0x10, 0x01, 0x00, 0xF8, 0x4D, 0x1B,
+ 0x01, 0x78, 0x21, 0xF0, 0x03, 0x01, 0x00, 0xF8, 0x07, 0x1B, 0x12, 0xE0, 0x00, 0xF8, 0x44, 0x1B,
+ 0x01, 0x78, 0x21, 0xF0, 0x01, 0x01, 0x10, 0xE0, 0x02, 0x78, 0x01, 0x29, 0x42, 0xF0, 0x12, 0x02,
+ 0x02, 0x70, 0x00, 0xD0, 0x03, 0x21, 0x10, 0xF8, 0x4D, 0x2F, 0x61, 0xF3, 0x01, 0x02, 0x00, 0xF8,
+ 0x07, 0x2B, 0x01, 0x78, 0x41, 0xF0, 0x80, 0x01, 0xE8, 0xE7, 0x01, 0x70, 0x70, 0x47, 0x01, 0x78,
+ 0x21, 0xF0, 0x02, 0x01, 0x41, 0xF0, 0x10, 0x01, 0x00, 0xF8, 0x4D, 0x1B, 0x01, 0x78, 0x21, 0xF0,
+ 0x03, 0x01, 0x89, 0x1C, 0x00, 0xF8, 0x07, 0x1B, 0x01, 0x78, 0x41, 0xF0, 0x80, 0x01, 0x00, 0xF8,
+ 0x44, 0x1B, 0x01, 0x78, 0x41, 0xF0, 0x01, 0x01, 0xE7, 0xE7, 0x90, 0xF8, 0x29, 0x20, 0x02, 0x29,
+ 0x04, 0xD0, 0x03, 0x29, 0x22, 0xF0, 0x40, 0x01, 0x02, 0xD1, 0x04, 0xE0, 0x42, 0xF0, 0x40, 0x01,
+ 0x21, 0xF0, 0x80, 0x01, 0x01, 0xE0, 0x41, 0xF0, 0x80, 0x01, 0x80, 0xF8, 0x29, 0x10, 0x70, 0x47,
+ 0x90, 0xF8, 0x29, 0x20, 0x01, 0x29, 0x04, 0xD0, 0x02, 0x29, 0x07, 0xD0, 0x22, 0xF0, 0x10, 0x01,
+ 0x01, 0xE0, 0x42, 0xF0, 0x10, 0x01, 0x21, 0xF0, 0x20, 0x01, 0x01, 0xE0, 0x42, 0xF0, 0x30, 0x01,
+ 0x80, 0xF8, 0x29, 0x10, 0x70, 0x47, 0xC2, 0x78, 0x00, 0x29, 0x61, 0xF3, 0x03, 0x02, 0xC2, 0x70,
+ 0x04, 0xD0, 0x10, 0xF8, 0x5E, 0x1F, 0x41, 0xF0, 0x04, 0x01, 0x01, 0x70, 0x70, 0x47, 0xC2, 0x7A,
+ 0x01, 0x29, 0x61, 0xF3, 0x03, 0x02, 0xC2, 0x72, 0x02, 0xD9, 0x42, 0xF0, 0x10, 0x01, 0xC1, 0x72,
+ 0x70, 0x47, 0x00, 0x00, 0x90, 0x04, 0x00, 0x22, 0xD0, 0x07, 0x10, 0x00, 0x68, 0x6F, 0x01, 0x00,
+ 0xA4, 0x00, 0x03, 0x20, 0x01, 0xEB, 0x81, 0x01, 0x02, 0xEB, 0xC1, 0x01, 0x40, 0x5C, 0x01, 0x06,
+ 0x02, 0xD5, 0x00, 0xF0, 0x7F, 0x00, 0x40, 0x42, 0x70, 0x47, 0x00, 0x2B, 0x04, 0xDA, 0x5B, 0x42,
+ 0xDB, 0xB2, 0x43, 0xF0, 0x80, 0x03, 0x01, 0xE0, 0x03, 0xF0, 0x7F, 0x03, 0x01, 0xEB, 0x81, 0x01,
+ 0x02, 0xEB, 0xC1, 0x01, 0x43, 0x54, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x5F, 0x00, 0x25, 0xDD, 0xE9,
+ 0x0A, 0x78, 0x91, 0x46, 0x9A, 0x46, 0x83, 0x46, 0x2E, 0x46, 0x2A, 0x46, 0x01, 0x20, 0x00, 0x21,
+ 0x01, 0xF0, 0xF1, 0xFD, 0x00, 0xEA, 0x09, 0x00, 0x01, 0xEA, 0x0A, 0x01, 0x08, 0x43, 0x14, 0xD0,
+ 0x00, 0x24, 0x22, 0x46, 0x01, 0x20, 0x00, 0x21, 0x01, 0xF0, 0xE5, 0xFD, 0x38, 0x40, 0x01, 0xEA,
+ 0x08, 0x01, 0x08, 0x43, 0x05, 0xD0, 0x00, 0x23, 0x22, 0x46, 0x31, 0x46, 0x58, 0x46, 0xFF, 0xF7,
+ 0xCC, 0xFF, 0x64, 0x1C, 0x28, 0x2C, 0xEC, 0xDB, 0x76, 0x1C, 0x6D, 0x1C, 0x38, 0x2D, 0xDC, 0xDB,
+ 0xBD, 0xE8, 0xF0, 0x9F, 0x40, 0x5C, 0x01, 0x06, 0x02, 0xD5, 0x00, 0xF0, 0x7F, 0x00, 0x40, 0x42,
+ 0x70, 0x47, 0x00, 0x2A, 0x04, 0xDA, 0x52, 0x42, 0xD2, 0xB2, 0x42, 0xF0, 0x80, 0x02, 0x01, 0xE0,
+ 0x02, 0xF0, 0x7F, 0x02, 0x42, 0x54, 0x70, 0x47, 0xF0, 0xB5, 0x00, 0x24, 0x15, 0x46, 0x0E, 0x46,
+ 0x84, 0x46, 0x23, 0x46, 0x01, 0x27, 0x0F, 0xE0, 0x06, 0xEB, 0xE3, 0x00, 0x03, 0xF0, 0x07, 0x01,
+ 0x00, 0x78, 0x07, 0xFA, 0x01, 0xF2, 0x02, 0x42, 0x05, 0xD0, 0x00, 0x22, 0x19, 0x46, 0x60, 0x46,
+ 0xFF, 0xF7, 0xDF, 0xFF, 0x64, 0x1C, 0x5B, 0x1C, 0xAC, 0x42, 0xED, 0xDB, 0xF0, 0xBD, 0x40, 0x5C,
+ 0x70, 0x47, 0x42, 0x54, 0x70, 0x47, 0xF0, 0xB5, 0x00, 0x24, 0x23, 0x46, 0x01, 0x26, 0x0D, 0xE0,
+ 0x01, 0xEB, 0xE3, 0x05, 0x03, 0xF0, 0x07, 0x07, 0x2D, 0x78, 0x06, 0xFA, 0x07, 0xFC, 0x1C, 0xEA,
+ 0x05, 0x0F, 0x02, 0xD0, 0x00, 0x25, 0xC5, 0x54, 0x64, 0x1C, 0x5B, 0x1C, 0x94, 0x42, 0xEF, 0xDB,
+ 0xF0, 0xBD, 0x40, 0x5C, 0x70, 0x47, 0x42, 0x54, 0x70, 0x47, 0x40, 0x5C, 0x70, 0x47, 0x42, 0x54,
+ 0x70, 0x47, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x33, 0x4C, 0x54, 0xF8, 0x3C, 0x8F, 0x67, 0x68,
+ 0xE6, 0x68, 0x25, 0x7C, 0xDF, 0xF8, 0xC4, 0x90, 0x01, 0x21, 0xC9, 0xF8, 0x00, 0x10, 0x4F, 0xF4,
+ 0x20, 0x70, 0xEB, 0xF7, 0x9D, 0xFB, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x10, 0xC4, 0xF8, 0x00, 0x80,
+ 0x67, 0x60, 0xE6, 0x60, 0x25, 0x74, 0xBD, 0xE8, 0xF0, 0x87, 0x27, 0x48, 0x00, 0x21, 0xC1, 0x63,
+ 0x01, 0x64, 0x81, 0x64, 0x80, 0xF8, 0x4C, 0x10, 0x70, 0x47, 0x70, 0xB5, 0x00, 0x24, 0x0D, 0x46,
+ 0x02, 0x46, 0x01, 0x20, 0x21, 0x46, 0x01, 0xF0, 0x56, 0xFD, 0x35, 0xB3, 0x1E, 0x4A, 0x48, 0x32,
+ 0x10, 0x60, 0x11, 0x71, 0xFF, 0xF7, 0xCE, 0xFF, 0x00, 0x20, 0x00, 0xF0, 0x23, 0xF8, 0x00, 0xB1,
+ 0x01, 0x24, 0xFF, 0xF7, 0xC7, 0xFF, 0x01, 0x20, 0x00, 0xF0, 0x1C, 0xF8, 0x08, 0xB1, 0x44, 0xF0,
+ 0x02, 0x04, 0xFF, 0xF7, 0xBF, 0xFF, 0x02, 0x20, 0x00, 0xF0, 0x14, 0xF8, 0x08, 0xB1, 0x44, 0xF0,
+ 0x04, 0x04, 0xFF, 0xF7, 0xB7, 0xFF, 0x03, 0x20, 0x00, 0xF0, 0x0C, 0xF8, 0x08, 0xB1, 0x44, 0xF0,
+ 0x08, 0x04, 0xFF, 0xF7, 0xAF, 0xFF, 0x20, 0x46, 0x70, 0xBD, 0x0B, 0x4A, 0x3C, 0x32, 0xC2, 0xE9,
+ 0x00, 0x01, 0xD7, 0xE7, 0x40, 0xF0, 0x20, 0x01, 0x07, 0x48, 0x10, 0xB5, 0x80, 0xF8, 0xA3, 0x10,
+ 0xE5, 0x21, 0x81, 0x71, 0x4F, 0xF4, 0x20, 0x70, 0xEB, 0xF7, 0x4A, 0xFB, 0x04, 0x48, 0xD0, 0xF8,
+ 0xC0, 0x02, 0xC0, 0xB2, 0x10, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x68, 0x14, 0x60, 0x22,
+ 0x00, 0x10, 0x60, 0x22, 0x4E, 0x48, 0x01, 0x68, 0x00, 0x29, 0x01, 0xD0, 0x01, 0x20, 0x08, 0x47,
+ 0x70, 0x47, 0x10, 0xB5, 0xFF, 0xF7, 0x20, 0xFE, 0x4A, 0x49, 0x02, 0x20, 0x08, 0x70, 0x4A, 0x49,
+ 0x00, 0x20, 0x08, 0x60, 0x46, 0x48, 0x01, 0x68, 0x00, 0x29, 0x03, 0xD0, 0xBD, 0xE8, 0x10, 0x40,
+ 0x00, 0x20, 0x08, 0x47, 0x10, 0xBD, 0x42, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x7F, 0xB5,
+ 0x04, 0x46, 0x03, 0x99, 0x08, 0x9D, 0xC1, 0xF3, 0x14, 0x01, 0x03, 0x91, 0x08, 0x21, 0x02, 0xA8,
+ 0x00, 0xF0, 0x60, 0xFA, 0x01, 0x2D, 0x02, 0xD0, 0x02, 0x2D, 0x04, 0xD0, 0x06, 0xE0, 0xC0, 0x1C,
+ 0x20, 0xF0, 0x01, 0x00, 0x02, 0xE0, 0xC0, 0x1D, 0x20, 0xF0, 0x03, 0x00, 0xDD, 0xE9, 0x02, 0x12,
+ 0x44, 0xF8, 0x3C, 0x1F, 0x62, 0x60, 0x21, 0x7A, 0x60, 0xF3, 0x06, 0x01, 0x21, 0x72, 0x7F, 0xBD,
+ 0x01, 0x23, 0x40, 0xF8, 0x3C, 0x3F, 0x00, 0x23, 0x43, 0x60, 0x51, 0x43, 0x02, 0x7A, 0x61, 0xF3,
+ 0x06, 0x02, 0x02, 0x72, 0x70, 0x47, 0x1F, 0xB5, 0x04, 0x46, 0x03, 0x99, 0x02, 0xA8, 0x01, 0xF0,
+ 0x3F, 0x01, 0x03, 0x91, 0x08, 0x21, 0x00, 0xF0, 0x35, 0xFA, 0xDD, 0xE9, 0x02, 0x12, 0xA1, 0x64,
+ 0x84, 0xF8, 0x4C, 0x20, 0x14, 0xF8, 0x70, 0x1F, 0x60, 0xF3, 0x05, 0x01, 0x04, 0xF8, 0x1E, 0x19,
+ 0xE1, 0x7F, 0x60, 0xF3, 0x05, 0x01, 0xE1, 0x77, 0x1F, 0xBD, 0x08, 0xB5, 0x1F, 0xA2, 0x12, 0x68,
+ 0x00, 0x92, 0x1D, 0xF8, 0x01, 0x20, 0x10, 0xF8, 0x5D, 0x1F, 0x62, 0xF3, 0x01, 0x01, 0x01, 0x70,
+ 0x08, 0xBD, 0x18, 0x49, 0x03, 0x20, 0x08, 0x70, 0x17, 0x49, 0x19, 0x48, 0x08, 0x60, 0x19, 0x49,
+ 0x01, 0x20, 0xC1, 0xF8, 0xC0, 0x00, 0x18, 0x49, 0x4F, 0xF4, 0xFA, 0x70, 0xFF, 0xF7, 0xD5, 0xBD,
+ 0x10, 0xB5, 0x0A, 0x46, 0x81, 0x79, 0x21, 0xF0, 0x0D, 0x01, 0x41, 0xF0, 0xE0, 0x01, 0x81, 0x71,
+ 0x0B, 0x49, 0x0A, 0x60, 0x0B, 0x4A, 0x03, 0x21, 0x11, 0x70, 0x0B, 0x4A, 0x0C, 0x49, 0x11, 0x60,
+ 0x01, 0x46, 0xA4, 0x22, 0x0D, 0x48, 0x01, 0xF0, 0xB5, 0xFC, 0x0A, 0x49, 0x01, 0x20, 0xC1, 0xF8,
+ 0xC0, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x49, 0x4F, 0xF4, 0xFA, 0x70, 0xFF, 0xF7, 0xB5, 0xBD,
+ 0xD8, 0x07, 0x10, 0x00, 0xD0, 0x07, 0x10, 0x00, 0xD4, 0x07, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00,
+ 0x43, 0x4D, 0x01, 0x00, 0x00, 0x00, 0x60, 0x22, 0x35, 0x4D, 0x01, 0x00, 0x00, 0x00, 0x03, 0x20,
+ 0x16, 0x48, 0x01, 0x78, 0x01, 0x29, 0x08, 0xD1, 0x02, 0x21, 0x01, 0x70, 0x14, 0x48, 0x01, 0x68,
+ 0x19, 0xB1, 0x00, 0x22, 0x02, 0x60, 0x10, 0x46, 0x08, 0x47, 0x01, 0x20, 0xFE, 0xF7, 0x37, 0xBF,
+ 0x0E, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x0E, 0x49, 0x08, 0x60, 0x0E, 0x49, 0xE8, 0x20, 0x88, 0x71,
+ 0x0D, 0x49, 0x0C, 0x20, 0xFF, 0xF7, 0x8B, 0xBD, 0x0A, 0x49, 0x08, 0x20, 0x88, 0x71, 0x0B, 0x49,
+ 0x00, 0x20, 0x08, 0x62, 0x05, 0x49, 0x08, 0x70, 0x05, 0x49, 0x08, 0x60, 0x70, 0x47, 0x03, 0x48,
+ 0x00, 0x78, 0x00, 0x28, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0xD0, 0x07, 0x10, 0x00,
+ 0xDC, 0x07, 0x10, 0x00, 0x00, 0x00, 0x03, 0x20, 0x91, 0x4E, 0x01, 0x00, 0x00, 0x00, 0x60, 0x22,
+ 0x63, 0x48, 0x01, 0x68, 0x00, 0x29, 0x01, 0xD0, 0x01, 0x20, 0x08, 0x47, 0x70, 0x47, 0x10, 0xB5,
+ 0xFF, 0xF7, 0x3A, 0xFD, 0x5F, 0x49, 0x02, 0x20, 0x08, 0x70, 0x5F, 0x49, 0x00, 0x20, 0x08, 0x60,
+ 0x5B, 0x48, 0x01, 0x68, 0x00, 0x29, 0x03, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x20, 0x08, 0x47,
+ 0x10, 0xBD, 0x57, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x7F, 0xB5, 0x04, 0x46, 0x03, 0x99,
+ 0x08, 0x9D, 0xC1, 0xF3, 0x14, 0x01, 0x03, 0x91, 0x08, 0x21, 0x02, 0xA8, 0x00, 0xF0, 0x7A, 0xF9,
+ 0xDD, 0xE9, 0x02, 0x12, 0xE1, 0x63, 0x22, 0x64, 0x94, 0xF8, 0x44, 0x20, 0xC1, 0xB2, 0x61, 0xF3,
+ 0x06, 0x02, 0x84, 0xF8, 0x44, 0x20, 0x0A, 0x2D, 0x0F, 0xD0, 0x0B, 0x2D, 0x0D, 0xD0, 0x14, 0xF8,
+ 0x72, 0x0F, 0x61, 0xF3, 0x05, 0x00, 0x20, 0x70, 0x60, 0x78, 0x61, 0xF3, 0x05, 0x00, 0x60, 0x70,
+ 0xA0, 0x78, 0x20, 0xF0, 0x08, 0x00, 0xA0, 0x70, 0x7F, 0xBD, 0x14, 0xF8, 0x72, 0x1F, 0x40, 0x1C,
+ 0x60, 0xF3, 0x05, 0x01, 0x21, 0x70, 0x61, 0x78, 0x60, 0xF3, 0x05, 0x01, 0x61, 0x70, 0xA0, 0x78,
+ 0x40, 0xF0, 0x08, 0x00, 0xEF, 0xE7, 0x1F, 0xB5, 0x04, 0x46, 0x03, 0x99, 0x02, 0xA8, 0x01, 0xF0,
+ 0x3F, 0x01, 0x03, 0x91, 0x08, 0x21, 0x00, 0xF0, 0x45, 0xF9, 0xDD, 0xE9, 0x02, 0x12, 0xA1, 0x64,
+ 0x84, 0xF8, 0x4C, 0x20, 0x14, 0xF8, 0x70, 0x1F, 0x60, 0xF3, 0x05, 0x01, 0x04, 0xF8, 0x1E, 0x19,
+ 0xE1, 0x7F, 0x60, 0xF3, 0x05, 0x01, 0xE1, 0x77, 0x1F, 0xBD, 0x30, 0xB5, 0x2F, 0xA2, 0x8C, 0xB0,
+ 0x3C, 0xCA, 0x8D, 0xE8, 0x3C, 0x00, 0x31, 0xA2, 0x0D, 0xF1, 0x10, 0x0C, 0x3C, 0xCA, 0x8C, 0xE8,
+ 0x3C, 0x00, 0x32, 0xA2, 0x0D, 0xF1, 0x20, 0x0C, 0x3C, 0xCA, 0x8C, 0xE8, 0x3C, 0x00, 0x04, 0xAA,
+ 0x53, 0x5C, 0x42, 0x7E, 0x63, 0xF3, 0x05, 0x02, 0x42, 0x76, 0x1D, 0xF8, 0x01, 0x30, 0x02, 0x7E,
+ 0x63, 0xF3, 0x42, 0x02, 0x02, 0x76, 0x08, 0xAA, 0x52, 0x5C, 0x81, 0x79, 0x62, 0xF3, 0x83, 0x01,
+ 0x81, 0x71, 0x0C, 0xB0, 0x30, 0xBD, 0x1B, 0x49, 0x04, 0x20, 0x08, 0x70, 0x1A, 0x49, 0x27, 0x48,
+ 0x08, 0x60, 0x27, 0x49, 0x01, 0x20, 0xC1, 0xF8, 0xC0, 0x00, 0x26, 0x49, 0x4F, 0xF4, 0xFA, 0x70,
+ 0xFF, 0xF7, 0xCB, 0xBC, 0x10, 0xB5, 0x0A, 0x46, 0xB0, 0xF8, 0x56, 0x10, 0x41, 0xF0, 0x01, 0x01,
+ 0xA0, 0xF8, 0x56, 0x10, 0x81, 0x79, 0x21, 0xF0, 0x01, 0x01, 0x41, 0xF0, 0xE0, 0x01, 0x81, 0x71,
+ 0x0B, 0x49, 0x0A, 0x60, 0x0B, 0x4A, 0x04, 0x21, 0x11, 0x70, 0x0B, 0x4A, 0x17, 0x49, 0x11, 0x60,
+ 0x01, 0x46, 0xA4, 0x22, 0x18, 0x48, 0x01, 0xF0, 0xA5, 0xFB, 0x15, 0x49, 0x01, 0x20, 0xC1, 0xF8,
+ 0xC0, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0x49, 0x4F, 0xF4, 0xFA, 0x70, 0xFF, 0xF7, 0xA5, 0xBC,
+ 0xE0, 0x07, 0x10, 0x00, 0xD0, 0x07, 0x10, 0x00, 0xD4, 0x07, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,
+ 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x02, 0x03, 0x02, 0x03,
+ 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x0F, 0x4F, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x22, 0x01, 0x4F, 0x01, 0x00, 0x00, 0x00, 0x03, 0x20, 0x44, 0x49, 0x01, 0x20,
+ 0x08, 0x60, 0x17, 0x22, 0x41, 0x07, 0x01, 0xF8, 0x27, 0x2F, 0x0B, 0x22, 0x81, 0xF8, 0x41, 0x20,
+ 0x3F, 0x49, 0x18, 0x39, 0x08, 0x60, 0x4F, 0xF0, 0x08, 0x51, 0xC1, 0xF8, 0xC4, 0x03, 0x3C, 0x4B,
+ 0x00, 0x22, 0xB0, 0x33, 0x1A, 0x60, 0x3B, 0x4A, 0x10, 0x60, 0x12, 0x1D, 0x10, 0x60, 0x38, 0x4A,
+ 0x94, 0x3A, 0x10, 0x60, 0xC1, 0xF8, 0x74, 0x03, 0x70, 0x47, 0x35, 0x49, 0x01, 0x20, 0x94, 0x39,
+ 0x08, 0x60, 0x70, 0x47, 0x32, 0x49, 0x00, 0x20, 0x94, 0x39, 0x08, 0x60, 0x70, 0x47, 0x4F, 0xF0,
+ 0x00, 0x50, 0x00, 0x88, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x50, 0x80, 0x78, 0x70, 0x47, 0x4F, 0xF0,
+ 0x00, 0x51, 0x48, 0x60, 0x70, 0x47, 0x2C, 0x49, 0x02, 0x68, 0x0A, 0x60, 0x42, 0x68, 0x4A, 0x60,
+ 0x80, 0x68, 0x88, 0x60, 0x70, 0x47, 0x28, 0x49, 0x0A, 0x68, 0x02, 0x60, 0x4A, 0x68, 0x42, 0x60,
+ 0x89, 0x68, 0x81, 0x60, 0x70, 0x47, 0x22, 0x49, 0x01, 0x20, 0x30, 0x39, 0x08, 0x60, 0x70, 0x47,
+ 0x4F, 0xF0, 0x00, 0x50, 0x10, 0xF8, 0x22, 0x1F, 0x21, 0xF0, 0x03, 0x01, 0x01, 0x70, 0x70, 0x47,
+ 0x4F, 0xF0, 0x00, 0x53, 0x03, 0xF8, 0x1F, 0x0F, 0x59, 0x70, 0x98, 0x78, 0x62, 0xF3, 0x03, 0x00,
+ 0x98, 0x70, 0x70, 0x47, 0x19, 0x48, 0x00, 0x68, 0x70, 0x47, 0x18, 0x49, 0x08, 0x60, 0x70, 0x47,
+ 0x10, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0xE2, 0x7E, 0x20, 0x23, 0x22, 0xF0, 0xAF, 0x02, 0x03, 0xEA,
+ 0x40, 0x13, 0x13, 0x43, 0x04, 0x22, 0x02, 0xEA, 0x80, 0x00, 0x03, 0x43, 0x01, 0xF0, 0x03, 0x00,
+ 0x03, 0x43, 0xE3, 0x76, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0x90, 0xF8, 0x22, 0x00, 0x10, 0xF0,
+ 0x03, 0x00, 0x05, 0xD0, 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x08, 0x48, 0x70, 0x47,
+ 0x08, 0x48, 0x70, 0x47, 0x08, 0x48, 0x70, 0x47, 0x08, 0x48, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47,
+ 0xCC, 0x04, 0x00, 0x22, 0x80, 0x1E, 0x00, 0x22, 0x08, 0x00, 0x00, 0x20, 0xE4, 0x07, 0x10, 0x00,
+ 0x00, 0x12, 0x7A, 0x00, 0x00, 0x90, 0xD0, 0x03, 0x00, 0x48, 0xE8, 0x01, 0x00, 0x24, 0xF4, 0x00,
+ 0xF0, 0xB5, 0x07, 0x46, 0x00, 0x20, 0x03, 0x46, 0x2F, 0x4E, 0x10, 0xE0, 0x57, 0xF8, 0x23, 0x50,
+ 0x03, 0x22, 0x4F, 0xEA, 0xC2, 0x0C, 0x45, 0xFA, 0x0C, 0xF4, 0x84, 0xEA, 0x20, 0x64, 0xE4, 0xB2,
+ 0x52, 0x1E, 0x56, 0xF8, 0x24, 0x40, 0x84, 0xEA, 0x00, 0x20, 0xF2, 0xD5, 0x5B, 0x1C, 0x8B, 0x42,
+ 0xEC, 0xDB, 0xF0, 0xBD, 0x30, 0xB5, 0x04, 0x46, 0x23, 0x4B, 0x00, 0x20, 0x10, 0x3B, 0x08, 0xE0,
+ 0x62, 0x5C, 0x02, 0xF0, 0x0F, 0x05, 0x03, 0xEB, 0x12, 0x12, 0x5D, 0x5D, 0x12, 0x78, 0x28, 0x44,
+ 0x10, 0x44, 0x49, 0x1E, 0xF4, 0xD2, 0x30, 0xBD, 0x10, 0xB5, 0x84, 0x68, 0x03, 0x68, 0xE4, 0x43,
+ 0xA3, 0x42, 0x0A, 0xD1, 0xC4, 0x68, 0x43, 0x68, 0xE4, 0x43, 0xA3, 0x42, 0x05, 0xD1, 0x5B, 0x1C,
+ 0x0B, 0x60, 0x00, 0x68, 0x10, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x3C, 0xB5,
+ 0x04, 0x46, 0x00, 0x25, 0x01, 0xAA, 0x69, 0x46, 0xFF, 0xF7, 0xE6, 0xFF, 0x01, 0x28, 0x09, 0xD1,
+ 0x00, 0x99, 0x04, 0xF1, 0x10, 0x00, 0x09, 0x1F, 0xFF, 0xF7, 0xB2, 0xFF, 0x01, 0x99, 0x88, 0x42,
+ 0x00, 0xD1, 0x01, 0x25, 0x28, 0x46, 0x3C, 0xBD, 0x30, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x09, 0x1F,
+ 0x10, 0x30, 0xFF, 0xF7, 0xA5, 0xFF, 0x6D, 0x1E, 0x65, 0x60, 0xE9, 0x43, 0xE1, 0x60, 0x20, 0x60,
+ 0xC0, 0x43, 0xA0, 0x60, 0x30, 0xBD, 0x00, 0x00, 0x1C, 0x70, 0x01, 0x00, 0x01, 0x46, 0x80, 0x00,
+ 0xB1, 0xF5, 0x80, 0x3F, 0x02, 0xD2, 0x10, 0x38, 0xC0, 0xF3, 0x10, 0x00, 0x70, 0x47, 0xC0, 0xF3,
+ 0x87, 0x20, 0x70, 0x47, 0xB0, 0xF5, 0x80, 0x2F, 0x02, 0xD2, 0x10, 0x30, 0xC0, 0xF3, 0x10, 0x00,
+ 0xC0, 0xF3, 0x8F, 0x00, 0x70, 0x47, 0x30, 0xB5, 0xFE, 0x4C, 0x01, 0x25, 0x25, 0x60, 0xE5, 0x06,
+ 0x03, 0xF0, 0x1F, 0x03, 0x85, 0xF8, 0x6B, 0x30, 0x00, 0x23, 0x04, 0xE0, 0x51, 0xF8, 0x23, 0x50,
+ 0x40, 0xF8, 0x23, 0x50, 0x5B, 0x1C, 0x93, 0x42, 0xF8, 0xDB, 0x00, 0x20, 0x20, 0x60, 0x30, 0xBD,
+ 0xF0, 0xB5, 0xF4, 0x4F, 0x01, 0x23, 0x3B, 0x60, 0x5C, 0x07, 0x84, 0xF8, 0x6B, 0x30, 0x9B, 0x1E,
+ 0x03, 0x60, 0x00, 0x23, 0x12, 0xE0, 0x51, 0xF8, 0x23, 0x40, 0x40, 0xF8, 0x23, 0x40, 0x00, 0x24,
+ 0x50, 0xF8, 0x23, 0x50, 0x51, 0xF8, 0x23, 0x60, 0xB5, 0x42, 0x06, 0xD0, 0x6D, 0x1C, 0x04, 0xD1,
+ 0x64, 0x1C, 0x40, 0xF8, 0x23, 0x60, 0x03, 0x2C, 0xF2, 0xD3, 0x5B, 0x1C, 0x93, 0x42, 0xEA, 0xDB,
+ 0x00, 0x20, 0x38, 0x60, 0xF0, 0xBD, 0xF0, 0xB5, 0x13, 0x46, 0x0A, 0x46, 0x05, 0x46, 0x00, 0x24,
+ 0x98, 0x18, 0x4F, 0xF4, 0x83, 0x26, 0x60, 0x28, 0x01, 0xD9, 0x01, 0x24, 0x11, 0xE0, 0x00, 0x21,
+ 0x07, 0xE0, 0x5F, 0x18, 0x56, 0xF8, 0x27, 0x00, 0x40, 0x1C, 0x01, 0xD0, 0x11, 0x46, 0x02, 0x24,
+ 0x49, 0x1C, 0x91, 0x42, 0xF5, 0xD3, 0x24, 0xB9, 0x06, 0xEB, 0x83, 0x00, 0x29, 0x46, 0xFF, 0xF7,
+ 0xBF, 0xFF, 0x20, 0x46, 0xF0, 0xBD, 0x10, 0xB5, 0x03, 0x46, 0x08, 0x46, 0xFF, 0xF7, 0x8E, 0xFF,
+ 0x01, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x92, 0x00, 0x18, 0x46, 0x01, 0xF0, 0x40, 0xBA, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x4F, 0xF0, 0x00, 0x58, 0x0C, 0x46, 0xD8, 0xF8, 0x14, 0x70, 0x01, 0x25, 0xC0, 0xF3,
+ 0x8F, 0x06, 0x6F, 0xF4, 0x80, 0x41, 0xC8, 0xF8, 0x14, 0x10, 0x0E, 0x20, 0x00, 0xF0, 0x13, 0xFA,
+ 0x20, 0x46, 0x00, 0xF0, 0x1B, 0xFA, 0x02, 0x00, 0xC3, 0x48, 0x4F, 0xF0, 0x01, 0x01, 0x18, 0xD0,
+ 0x01, 0x60, 0xA4, 0xF5, 0x80, 0x34, 0x40, 0x46, 0x20, 0xF8, 0x72, 0x6F, 0x44, 0x80, 0x60, 0x22,
+ 0x00, 0xF8, 0x01, 0x2C, 0xBD, 0x4A, 0x11, 0x60, 0xBB, 0x4A, 0xC4, 0x32, 0x11, 0x60, 0x30, 0xBF,
+ 0x81, 0x79, 0x72, 0x38, 0x89, 0x07, 0x00, 0xD0, 0x00, 0x25, 0x47, 0x61, 0x28, 0x46, 0xBD, 0xE8,
+ 0xF0, 0x81, 0x00, 0x22, 0x02, 0x60, 0xE6, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, 0x15, 0x46, 0xDF, 0xF8,
+ 0xC4, 0xB2, 0x00, 0x26, 0x01, 0x27, 0x0A, 0x46, 0x04, 0x46, 0x4F, 0xF0, 0x00, 0x5C, 0xB1, 0xF5,
+ 0x88, 0x2F, 0x15, 0xD3, 0xA3, 0x0A, 0xFF, 0xF7, 0x41, 0xFF, 0x59, 0x46, 0xCB, 0xF8, 0x00, 0x70,
+ 0x03, 0xF0, 0x1F, 0x03, 0x8C, 0xF8, 0x6B, 0x30, 0x00, 0x23, 0x04, 0xE0, 0x52, 0xF8, 0x23, 0x40,
+ 0x40, 0xF8, 0x23, 0x40, 0x5B, 0x1C, 0xAB, 0x42, 0xF8, 0xDB, 0x0E, 0x60, 0xBD, 0xE8, 0xF0, 0x9F,
+ 0xDC, 0xF8, 0x14, 0x90, 0xC1, 0xF3, 0x8F, 0x08, 0xE2, 0x46, 0x6F, 0xF4, 0x80, 0x41, 0xCC, 0xF8,
+ 0x14, 0x10, 0x0E, 0x20, 0x00, 0xF0, 0xBF, 0xF9, 0xCB, 0xF8, 0x00, 0x70, 0x20, 0x46, 0x00, 0xF0,
+ 0xC5, 0xF9, 0x01, 0x00, 0x98, 0x48, 0x19, 0xD0, 0x07, 0x60, 0xA4, 0xF5, 0x80, 0x34, 0xAA, 0xF8,
+ 0x72, 0x80, 0xAA, 0xF8, 0x74, 0x40, 0x6D, 0x1E, 0xAA, 0xF8, 0x76, 0x50, 0x40, 0x21, 0x8A, 0xF8,
+ 0x71, 0x10, 0x92, 0x49, 0x0E, 0x60, 0x90, 0x49, 0xC4, 0x31, 0x0F, 0x60, 0x0A, 0xF1, 0x52, 0x00,
+ 0x30, 0xBF, 0xCB, 0xF8, 0x00, 0x60, 0x40, 0xF8, 0x3E, 0x9C, 0xCF, 0xE7, 0x06, 0x60, 0xE6, 0xE7,
+ 0x2D, 0xE9, 0xF0, 0x41, 0x4F, 0xF0, 0x00, 0x54, 0x0F, 0x46, 0x54, 0xF8, 0x14, 0x6F, 0x85, 0x08,
+ 0x6F, 0xF4, 0x80, 0x40, 0x20, 0x60, 0x0E, 0x20, 0x00, 0xF0, 0x8D, 0xF9, 0x00, 0x20, 0xA0, 0x66,
+ 0xA4, 0xF8, 0x5E, 0x50, 0x7F, 0x1E, 0xA4, 0xF8, 0x62, 0x70, 0x84, 0xF8, 0x5D, 0x00, 0x7F, 0x49,
+ 0x08, 0x60, 0x7D, 0x49, 0x01, 0x20, 0xC4, 0x31, 0x08, 0x60, 0x30, 0xBF, 0xE0, 0x6E, 0x26, 0x60,
+ 0x85, 0xE7, 0x70, 0xB5, 0x06, 0x46, 0x0C, 0x46, 0x01, 0xF1, 0x10, 0x00, 0x11, 0x1F, 0x15, 0x46,
+ 0x89, 0xB2, 0xFF, 0xF7, 0xD5, 0xFF, 0x20, 0x60, 0x68, 0x1E, 0x60, 0x60, 0x20, 0x68, 0x2A, 0x46,
+ 0xC0, 0x43, 0xA0, 0x60, 0x60, 0x68, 0x21, 0x46, 0xC0, 0x43, 0xE0, 0x60, 0x30, 0x46, 0xBD, 0xE8,
+ 0x70, 0x40, 0x71, 0xE7, 0xF0, 0xB5, 0x07, 0x46, 0x00, 0x20, 0x04, 0x46, 0x6C, 0x4E, 0x15, 0xE0,
+ 0x57, 0xF8, 0x24, 0x50, 0x03, 0x23, 0x4F, 0xEA, 0xC3, 0x0C, 0x45, 0xFA, 0x0C, 0xF2, 0x80, 0xEA,
+ 0x02, 0x60, 0x08, 0x22, 0x00, 0x28, 0x02, 0xDA, 0x86, 0xEA, 0x40, 0x00, 0x00, 0xE0, 0x40, 0x00,
+ 0x52, 0x1E, 0x00, 0x2A, 0xF6, 0xDC, 0x5B, 0x1E, 0xED, 0xD5, 0x64, 0x1C, 0x8C, 0x42, 0xE7, 0xDB,
+ 0xF0, 0xBD, 0x30, 0xB5, 0x50, 0xF8, 0x08, 0x4B, 0x50, 0xF8, 0x08, 0x5B, 0x30, 0xF8, 0x0C, 0x1C,
+ 0x49, 0x1C, 0x89, 0xB2, 0xFF, 0xF7, 0xD6, 0xFF, 0x84, 0x42, 0x04, 0xD1, 0xE0, 0x43, 0x85, 0x42,
+ 0x01, 0xD1, 0x01, 0x20, 0x30, 0xBD, 0x00, 0x20, 0x30, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x01, 0x26,
+ 0x75, 0x07, 0x04, 0x46, 0x6F, 0x69, 0x6F, 0xF4, 0x80, 0x40, 0x68, 0x61, 0x0E, 0x20, 0x00, 0xF0,
+ 0x22, 0xF9, 0x4F, 0xF0, 0x00, 0x08, 0xC5, 0xF8, 0x7C, 0x80, 0x20, 0x46, 0x00, 0xF0, 0x26, 0xF9,
+ 0x02, 0x00, 0x49, 0x49, 0x4F, 0xF0, 0x01, 0x00, 0x15, 0xD0, 0x08, 0x60, 0xA4, 0xF5, 0x80, 0x34,
+ 0xA5, 0xF8, 0x74, 0x40, 0x20, 0x21, 0x85, 0xF8, 0x71, 0x10, 0x44, 0x49, 0x08, 0x60, 0x42, 0x49,
+ 0xC4, 0x31, 0x08, 0x60, 0x30, 0xBF, 0x95, 0xF8, 0x78, 0x00, 0x80, 0x07, 0x00, 0xD0, 0x00, 0x26,
+ 0x6F, 0x61, 0x30, 0x46, 0x0B, 0xE7, 0xC1, 0xF8, 0x00, 0x80, 0xE9, 0xE7, 0x00, 0xB5, 0x0B, 0x46,
+ 0xFF, 0xF7, 0x5C, 0xFE, 0x82, 0x68, 0x01, 0x68, 0xD2, 0x43, 0x91, 0x42, 0x08, 0xD1, 0x42, 0x68,
+ 0xC0, 0x68, 0xC0, 0x43, 0x82, 0x42, 0x03, 0xD1, 0x52, 0x1C, 0x1A, 0x80, 0x01, 0x20, 0x00, 0xBD,
+ 0x00, 0x20, 0x00, 0xBD, 0xF8, 0xB5, 0x04, 0x46, 0x10, 0x30, 0x0D, 0x46, 0x06, 0x46, 0xFF, 0xF7,
+ 0xBE, 0xFE, 0x01, 0x28, 0x01, 0xD0, 0x00, 0x20, 0xF8, 0xBD, 0x69, 0x46, 0x28, 0x46, 0xFF, 0xF7,
+ 0xDD, 0xFF, 0xBD, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0x81, 0xB2, 0x30, 0x46, 0xFF, 0xF7, 0x38, 0xFF,
+ 0x20, 0x60, 0xBD, 0xF8, 0x00, 0x10, 0xC0, 0x43, 0x49, 0x1E, 0x61, 0x60, 0xA0, 0x60, 0xC8, 0x43,
+ 0xE0, 0x60, 0x01, 0x20, 0xF8, 0xBD, 0xF0, 0xB5, 0xB1, 0xB0, 0x07, 0x46, 0x6D, 0x46, 0x21, 0x4E,
+ 0x01, 0x24, 0xC0, 0x21, 0x28, 0x46, 0x01, 0xF0, 0x36, 0xF9, 0x00, 0x20, 0x56, 0xF8, 0x20, 0x10,
+ 0x45, 0xF8, 0x20, 0x10, 0x40, 0x1C, 0x30, 0x28, 0xF8, 0xD3, 0x1B, 0x49, 0x00, 0x98, 0x88, 0x42,
+ 0x10, 0xD1, 0x02, 0x98, 0x81, 0xB2, 0x05, 0xA8, 0x04, 0x46, 0xFF, 0xF7, 0x4B, 0xFF, 0x01, 0x99,
+ 0x81, 0x42, 0x06, 0xD1, 0xAC, 0x22, 0x21, 0x46, 0x38, 0x46, 0x01, 0xF0, 0xC0, 0xF8, 0x00, 0x24,
+ 0x00, 0xE0, 0x03, 0x24, 0x31, 0xB0, 0x20, 0x46, 0xF0, 0xBD, 0x70, 0xB5, 0x94, 0xB0, 0x04, 0x46,
+ 0x6D, 0x46, 0x0E, 0x4E, 0x50, 0x21, 0x28, 0x46, 0x01, 0xF0, 0x0D, 0xF9, 0x00, 0x20, 0x56, 0xF8,
+ 0x20, 0x10, 0x45, 0xF8, 0x20, 0x10, 0x40, 0x1C, 0x14, 0x28, 0xF8, 0xD3, 0x08, 0x48, 0x6F, 0xF0,
+ 0x02, 0x05, 0x0F, 0xE0, 0xC4, 0x1B, 0x00, 0x22, 0x78, 0x0D, 0x00, 0x22, 0x1C, 0x0F, 0x00, 0x22,
+ 0x1B, 0x00, 0x00, 0x80, 0x48, 0x1D, 0x04, 0x00, 0xB2, 0x57, 0x0E, 0x70, 0xAC, 0x1E, 0x04, 0x00,
+ 0x5C, 0x00, 0x0D, 0x60, 0x00, 0x99, 0x81, 0x42, 0x2E, 0xD1, 0xA8, 0x10, 0x20, 0x60, 0x60, 0x60,
+ 0xA0, 0x60, 0xE0, 0x60, 0x20, 0x61, 0x02, 0x98, 0x81, 0xB2, 0x05, 0xA8, 0xFF, 0xF7, 0x0A, 0xFF,
+ 0x01, 0x99, 0x81, 0x42, 0x20, 0xD1, 0xBD, 0xF8, 0x38, 0x10, 0x45, 0xF2, 0xAA, 0x50, 0x81, 0x42,
+ 0x0C, 0xD1, 0x9D, 0xF8, 0x1D, 0x10, 0x21, 0x60, 0x9D, 0xF8, 0x1C, 0x10, 0x01, 0xF0, 0x0F, 0x01,
+ 0x61, 0x60, 0x9D, 0xF8, 0x1E, 0x10, 0x01, 0xF0, 0x0F, 0x01, 0xA1, 0x60, 0xBD, 0xF8, 0x3C, 0x10,
+ 0x81, 0x42, 0x01, 0xD1, 0x08, 0x99, 0xE1, 0x60, 0xBD, 0xF8, 0x40, 0x10, 0x81, 0x42, 0x01, 0xD1,
+ 0x09, 0x98, 0x20, 0x61, 0x14, 0xB0, 0x70, 0xBD, 0x25, 0x60, 0x65, 0x60, 0xA5, 0x60, 0xE5, 0x60,
+ 0x25, 0x61, 0xF7, 0xE7, 0x70, 0xB5, 0x86, 0xB0, 0x04, 0x46, 0x6D, 0x46, 0x27, 0x4E, 0x14, 0x21,
+ 0x28, 0x46, 0x01, 0xF0, 0xB0, 0xF8, 0x00, 0x21, 0x56, 0xF8, 0x21, 0x00, 0x45, 0xF8, 0x21, 0x00,
+ 0x49, 0x1C, 0x05, 0x29, 0xF8, 0xD3, 0x00, 0x98, 0x20, 0x60, 0x01, 0x98, 0x60, 0x60, 0x02, 0x98,
+ 0xC0, 0xB2, 0xA0, 0x60, 0x03, 0x98, 0xC0, 0xB2, 0xE0, 0x60, 0x04, 0x98, 0xC0, 0xB2, 0x20, 0x61,
+ 0x06, 0xB0, 0x70, 0xBD, 0x1C, 0xB5, 0x00, 0x20, 0x18, 0x4A, 0x00, 0x90, 0x84, 0x3A, 0x6B, 0x46,
+ 0x01, 0x46, 0x01, 0x90, 0x52, 0xF8, 0x21, 0x40, 0x43, 0xF8, 0x21, 0x40, 0x49, 0x1C, 0x02, 0x29,
+ 0xF8, 0xD3, 0xBD, 0xF8, 0x00, 0x10, 0xA1, 0xF5, 0xAA, 0x42, 0xAA, 0x3A, 0x0A, 0xD1, 0xBD, 0xF8,
+ 0x04, 0x20, 0x11, 0x42, 0x06, 0xD1, 0x9D, 0xF8, 0x02, 0x10, 0x9D, 0xF8, 0x06, 0x20, 0x11, 0x42,
+ 0x00, 0xD1, 0x08, 0x46, 0x1C, 0xBD, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09,
+ 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12, 0x70, 0x47, 0xB0, 0xF5, 0x80, 0x3F,
+ 0x01, 0xD2, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00, 0x60, 0x1F, 0x04, 0x00,
+ 0x4F, 0xF0, 0x00, 0x50, 0x00, 0x21, 0x80, 0xF8, 0x3D, 0x10, 0x80, 0xF8, 0x3E, 0x10, 0x80, 0xF8,
+ 0x3F, 0x10, 0x3F, 0x22, 0x80, 0xF8, 0x32, 0x20, 0x00, 0xF8, 0x30, 0x1F, 0x02, 0x71, 0x41, 0x71,
+ 0x42, 0x70, 0x01, 0x72, 0x41, 0x72, 0x81, 0x72, 0xC1, 0x72, 0xC1, 0x71, 0x70, 0x47, 0x99, 0x4A,
+ 0x10, 0x60, 0x98, 0x48, 0x0C, 0x30, 0x01, 0x60, 0x70, 0x47, 0x30, 0xB5, 0x01, 0x24, 0x84, 0x40,
+ 0xE0, 0xB2, 0x4F, 0xF0, 0x00, 0x54, 0x00, 0x29, 0x03, 0x9D, 0x94, 0xF8, 0x32, 0x10, 0x01, 0xD0,
+ 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x84, 0xF8, 0x32, 0x10, 0x94, 0xF8, 0x30, 0x10, 0x0A, 0xB1,
+ 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x84, 0xF8, 0x30, 0x10, 0x94, 0xF8, 0x34, 0x10, 0x0B, 0xB1,
+ 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x84, 0xF8, 0x34, 0x10, 0x14, 0xF8, 0x35, 0x1F, 0x0D, 0xB1,
+ 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x21, 0x70, 0x30, 0xBD, 0x4F, 0xF0, 0x00, 0x52, 0x06, 0x28,
+ 0x17, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x06, 0x09, 0x0F, 0x17, 0x1A, 0x12, 0xF8, 0x3D, 0x0F,
+ 0x04, 0xE0, 0x12, 0xF8, 0x3D, 0x0F, 0x07, 0xE0, 0x12, 0xF8, 0x3E, 0x0F, 0x20, 0xF0, 0x0F, 0x00,
+ 0x08, 0x43, 0x05, 0xE0, 0x12, 0xF8, 0x3E, 0x0F, 0x20, 0xF0, 0xF0, 0x00, 0x40, 0xEA, 0x01, 0x10,
+ 0x10, 0x70, 0x70, 0x47, 0x12, 0xF8, 0x3F, 0x0F, 0xF0, 0xE7, 0x12, 0xF8, 0x3F, 0x0F, 0xF3, 0xE7,
+ 0x01, 0x23, 0x83, 0x40, 0xD8, 0xB2, 0x4F, 0xF0, 0x00, 0x53, 0x00, 0x29, 0x93, 0xF8, 0x38, 0x10,
+ 0x01, 0xD0, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x83, 0xF8, 0x38, 0x10, 0x13, 0xF8, 0x39, 0x1F,
+ 0x0A, 0xB1, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x19, 0x70, 0x70, 0x47, 0x01, 0x23, 0x83, 0x40,
+ 0xD8, 0xB2, 0x4F, 0xF0, 0x00, 0x53, 0x00, 0x29, 0x93, 0xF8, 0x3A, 0x10, 0x01, 0xD0, 0x01, 0x43,
+ 0x00, 0xE0, 0x81, 0x43, 0x83, 0xF8, 0x3A, 0x10, 0x13, 0xF8, 0x3A, 0x1F, 0x0A, 0xB1, 0x01, 0x43,
+ 0x00, 0xE0, 0x81, 0x43, 0x19, 0x70, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x01, 0x20,
+ 0xA8, 0x40, 0xC4, 0xB2, 0x1E, 0x46, 0x90, 0x46, 0x0F, 0x46, 0x0A, 0x20, 0x00, 0xF0, 0x93, 0xF8,
+ 0x0B, 0x20, 0x00, 0xF0, 0x90, 0xF8, 0x0A, 0x20, 0x00, 0xF0, 0x98, 0xF8, 0x0B, 0x20, 0x00, 0xF0,
+ 0x95, 0xF8, 0x4F, 0xF0, 0x00, 0x50, 0x8F, 0xB1, 0x90, 0xF8, 0x2E, 0x10, 0xA1, 0x43, 0x80, 0xF8,
+ 0x2E, 0x10, 0x90, 0xF8, 0x38, 0x10, 0x21, 0x43, 0x80, 0xF8, 0x38, 0x10, 0x90, 0xF8, 0x3A, 0x10,
+ 0x21, 0x43, 0x80, 0xF8, 0x3A, 0x10, 0x48, 0x49, 0x41, 0xF8, 0x25, 0x60, 0xB8, 0xF1, 0x00, 0x0F,
+ 0x0D, 0xD0, 0x10, 0xF8, 0x2F, 0x1F, 0xA1, 0x43, 0x01, 0x70, 0x81, 0x7A, 0x21, 0x43, 0x81, 0x72,
+ 0x01, 0x7B, 0x21, 0x43, 0x01, 0x73, 0x40, 0x48, 0x20, 0x30, 0x40, 0xF8, 0x25, 0x60, 0x0A, 0x20,
+ 0x00, 0xF0, 0x56, 0xF8, 0xBD, 0xE8, 0xF0, 0x41, 0x0B, 0x20, 0x00, 0xF0, 0x51, 0xB8, 0x2D, 0xE9,
+ 0xF0, 0x41, 0x05, 0x46, 0x01, 0x20, 0xA8, 0x40, 0xC4, 0xB2, 0x17, 0x46, 0x0E, 0x46, 0x0A, 0x20,
+ 0x00, 0xF0, 0x51, 0xF8, 0x0B, 0x20, 0x00, 0xF0, 0x4E, 0xF8, 0x0A, 0x20, 0x00, 0xF0, 0x56, 0xF8,
+ 0x0B, 0x20, 0x00, 0xF0, 0x53, 0xF8, 0x31, 0x00, 0x4F, 0xF0, 0x00, 0x02, 0x4F, 0xF0, 0x00, 0x56,
+ 0x11, 0xD0, 0x96, 0xF8, 0x38, 0x00, 0xA0, 0x43, 0x86, 0xF8, 0x38, 0x00, 0x96, 0xF8, 0x2E, 0x00,
+ 0xA0, 0x43, 0x86, 0xF8, 0x2E, 0x00, 0x96, 0xF8, 0x3A, 0x00, 0xA0, 0x43, 0x86, 0xF8, 0x3A, 0x00,
+ 0x25, 0x48, 0x40, 0xF8, 0x25, 0x20, 0x97, 0xB1, 0x96, 0xF8, 0x39, 0x00, 0xA0, 0x43, 0x86, 0xF8,
+ 0x39, 0x00, 0x96, 0xF8, 0x2F, 0x00, 0xA0, 0x43, 0x86, 0xF8, 0x2F, 0x00, 0x96, 0xF8, 0x3B, 0x00,
+ 0xA0, 0x43, 0x86, 0xF8, 0x3B, 0x00, 0x1C, 0x48, 0x20, 0x30, 0x40, 0xF8, 0x25, 0x20, 0x96, 0xF8,
+ 0x38, 0x00, 0x10, 0xB1, 0x0A, 0x20, 0x00, 0xF0, 0x0B, 0xF8, 0x96, 0xF8, 0x39, 0x00, 0x00, 0x28,
+ 0x04, 0xD0, 0xBD, 0xE8, 0xF0, 0x41, 0x0B, 0x20, 0x00, 0xF0, 0x02, 0xB8, 0xBD, 0xE8, 0xF0, 0x81,
+ 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20,
+ 0xC0, 0xF8, 0x00, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09,
+ 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02,
+ 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12,
+ 0x70, 0x47, 0x00, 0x00, 0x38, 0x05, 0x00, 0x22, 0xFC, 0x87, 0x10, 0x00, 0xF0, 0xB5, 0x63, 0x4D,
+ 0xD0, 0xE9, 0x00, 0x23, 0x01, 0x21, 0xEC, 0x1D, 0xFF, 0x27, 0x4E, 0x07, 0x00, 0x7A, 0x86, 0xF8,
+ 0xE5, 0x70, 0x86, 0xF8, 0xE4, 0x70, 0x00, 0x27, 0xC6, 0xF8, 0xC0, 0x70, 0xC6, 0xF8, 0xE8, 0x70,
+ 0x86, 0xF8, 0xE1, 0x70, 0x86, 0xF8, 0xE3, 0x70, 0x8E, 0x46, 0x58, 0xE0, 0x17, 0x78, 0x05, 0xF8,
+ 0x01, 0x7B, 0x1F, 0x88, 0x24, 0xF8, 0x02, 0x7B, 0xD7, 0x78, 0x01, 0x2F, 0x02, 0xD0, 0x02, 0x2F,
+ 0x09, 0xD0, 0x10, 0xE0, 0x96, 0xF8, 0xE4, 0x70, 0x0E, 0xFA, 0x01, 0xFC, 0x27, 0xEA, 0x0C, 0x07,
+ 0x86, 0xF8, 0xE4, 0x70, 0x07, 0xE0, 0x96, 0xF8, 0xE5, 0x70, 0x0E, 0xFA, 0x01, 0xFC, 0x27, 0xEA,
+ 0x0C, 0x07, 0x86, 0xF8, 0xE5, 0x70, 0x4F, 0x1E, 0x07, 0xEB, 0x47, 0x0C, 0x27, 0xF0, 0x01, 0x07,
+ 0xBC, 0x44, 0x57, 0x78, 0x07, 0xF0, 0x07, 0x07, 0x07, 0xFA, 0x0C, 0xF7, 0xD6, 0xF8, 0xC0, 0xC0,
+ 0x47, 0xEA, 0x0C, 0x07, 0xC6, 0xF8, 0xC0, 0x70, 0x97, 0x78, 0x4F, 0xEA, 0x81, 0x0C, 0x07, 0xF0,
+ 0x0F, 0x07, 0xAC, 0xF1, 0x04, 0x0C, 0x07, 0xFA, 0x0C, 0xF7, 0xD6, 0xF8, 0xE8, 0xC0, 0x47, 0xEA,
+ 0x0C, 0x07, 0xC6, 0xF8, 0xE8, 0x70, 0x17, 0x79, 0xFF, 0x07, 0x07, 0xD0, 0x96, 0xF8, 0xE1, 0x70,
+ 0x0E, 0xFA, 0x01, 0xFC, 0x47, 0xEA, 0x0C, 0x07, 0x86, 0xF8, 0xE1, 0x70, 0x17, 0x79, 0xFF, 0x06,
+ 0x07, 0xD5, 0x96, 0xF8, 0xE3, 0x70, 0x0E, 0xFA, 0x01, 0xFC, 0x47, 0xEA, 0x0C, 0x07, 0x86, 0xF8,
+ 0xE3, 0x70, 0x49, 0x1C, 0x08, 0x29, 0x04, 0xD2, 0x40, 0x1E, 0x52, 0x1D, 0x9B, 0x1C, 0x00, 0x28,
+ 0xA4, 0xD1, 0xD6, 0xF8, 0xE8, 0x00, 0x70, 0x64, 0xF0, 0xBD, 0xF0, 0xB5, 0x27, 0x4D, 0x28, 0x4F,
+ 0x01, 0x26, 0xEC, 0x1D, 0xC2, 0x79, 0x00, 0x21, 0x03, 0x68, 0x79, 0x60, 0x27, 0x07, 0x4F, 0xF0,
+ 0xFF, 0x0E, 0x87, 0xF8, 0xE5, 0xE0, 0x87, 0xF8, 0xE4, 0x60, 0xC7, 0xF8, 0xC0, 0x10, 0x87, 0xF8,
+ 0xE1, 0x10, 0x87, 0xF8, 0xE3, 0x10, 0x18, 0xE0, 0x93, 0xF8, 0x00, 0xC0, 0x05, 0xF8, 0x01, 0xCB,
+ 0xB0, 0xF8, 0x04, 0xC0, 0x24, 0xF8, 0x02, 0xCB, 0x90, 0xF8, 0x06, 0xC0, 0x4F, 0xEA, 0x86, 0x0E,
+ 0x0C, 0xF0, 0x0F, 0x0C, 0xAE, 0xF1, 0x04, 0x0E, 0x0C, 0xFA, 0x0E, 0xFC, 0x76, 0x1C, 0x4C, 0xEA,
+ 0x01, 0x01, 0x08, 0x2E, 0x03, 0xD2, 0x52, 0x1E, 0x5B, 0x1C, 0x00, 0x2A, 0xE4, 0xD1, 0xC7, 0xF8,
+ 0xE8, 0x10, 0x79, 0x64, 0xF0, 0xBD, 0x0D, 0x4A, 0xD2, 0x1D, 0x22, 0xF8, 0x10, 0x10, 0x70, 0x47,
+ 0x10, 0xB5, 0x04, 0x46, 0x0B, 0x48, 0x00, 0x68, 0x38, 0xB1, 0xA0, 0x68, 0xFF, 0xF7, 0x46, 0xFF,
+ 0x20, 0x68, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x0F, 0xB8, 0xE0, 0x68, 0xFF, 0xF7, 0x3E, 0xFF,
+ 0x60, 0x68, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xCB, 0xBC, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x22, 0xBC, 0x05, 0x00, 0x22, 0x10, 0xB5, 0x4F, 0x4B, 0x01, 0x68, 0x00, 0x24,
+ 0x99, 0x60, 0x81, 0x88, 0x59, 0x80, 0x02, 0x89, 0x9A, 0x80, 0x1C, 0x70, 0x4F, 0xF0, 0x00, 0x53,
+ 0xA3, 0xF8, 0x1A, 0x21, 0xA3, 0xF8, 0x1E, 0x11, 0xC0, 0x88, 0xA3, 0xF8, 0x20, 0x01, 0x47, 0x48,
+ 0x01, 0x22, 0xC0, 0xF8, 0xD8, 0x21, 0xC0, 0xF8, 0xDC, 0x21, 0xC0, 0xF8, 0xC4, 0x21, 0xC0, 0xF8,
+ 0xCC, 0x21, 0xC0, 0xF8, 0xD4, 0x21, 0xC0, 0xF8, 0x80, 0x21, 0x72, 0xB6, 0xD0, 0xF8, 0x08, 0x12,
+ 0x00, 0x29, 0xFB, 0xD1, 0x42, 0x60, 0x62, 0xB6, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x3B, 0x4D,
+ 0xD5, 0xF8, 0x5C, 0x01, 0x38, 0x4F, 0x2E, 0x04, 0x01, 0x24, 0xBA, 0x68, 0x50, 0xB3, 0xB6, 0xF8,
+ 0x1C, 0x81, 0x5F, 0xEA, 0x08, 0x00, 0x0F, 0xD0, 0xD5, 0xF8, 0x54, 0x01, 0x10, 0xB9, 0xD5, 0xF8,
+ 0x00, 0x01, 0x48, 0xB1, 0x41, 0x46, 0x01, 0x20, 0x90, 0x47, 0xC5, 0xF8, 0xD8, 0x42, 0xD5, 0xF8,
+ 0x54, 0x01, 0x08, 0xB1, 0xC5, 0xF8, 0xD4, 0x42, 0xBA, 0x68, 0x41, 0x46, 0x02, 0x20, 0x90, 0x47,
+ 0x01, 0x78, 0x02, 0x29, 0x02, 0xD0, 0x03, 0x29, 0x02, 0xD0, 0x08, 0xE0, 0x41, 0x88, 0x00, 0xE0,
+ 0x79, 0x88, 0xA6, 0xF8, 0x1E, 0x11, 0x80, 0x88, 0xA6, 0xF8, 0x1A, 0x01, 0x3C, 0x70, 0xC5, 0xF8,
+ 0xDC, 0x42, 0x38, 0xE0, 0xD5, 0xF8, 0x44, 0x01, 0x80, 0xB1, 0xB6, 0xF8, 0x1C, 0x11, 0x03, 0x20,
+ 0x90, 0x47, 0x38, 0x78, 0x38, 0xB1, 0x78, 0x88, 0xA6, 0xF8, 0x1E, 0x01, 0xB8, 0x88, 0xA6, 0xF8,
+ 0x1A, 0x01, 0x00, 0x20, 0x38, 0x70, 0xC5, 0xF8, 0xC4, 0x42, 0x24, 0xE0, 0xD5, 0xF8, 0x58, 0x01,
+ 0x30, 0xB1, 0xB6, 0xF8, 0x1C, 0x11, 0x01, 0x20, 0x90, 0x47, 0xC5, 0xF8, 0xD8, 0x42, 0x1A, 0xE0,
+ 0xD5, 0xF8, 0x4C, 0x01, 0x28, 0xB9, 0xD5, 0xF8, 0x54, 0x01, 0x10, 0xB9, 0xD5, 0xF8, 0x00, 0x01,
+ 0x88, 0xB1, 0xB6, 0xF8, 0x1C, 0x11, 0x19, 0xB1, 0x01, 0x20, 0x90, 0x47, 0xC5, 0xF8, 0xD8, 0x42,
+ 0xD5, 0xF8, 0x4C, 0x01, 0x10, 0xB1, 0xC5, 0xF8, 0xCC, 0x42, 0x04, 0xE0, 0xD5, 0xF8, 0x54, 0x01,
+ 0x08, 0xB1, 0xC5, 0xF8, 0xD4, 0x42, 0xD5, 0xF8, 0x00, 0x01, 0x00, 0x28, 0x01, 0xD0, 0xC5, 0xF8,
+ 0x80, 0x42, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, 0xE8, 0x07, 0x10, 0x00, 0x00, 0x20, 0x00, 0x22,
+ 0xF6, 0x49, 0x00, 0x20, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D,
+ 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D, 0x08, 0x60, 0x09, 0x1D,
+ 0x08, 0x60, 0xEF, 0x49, 0x01, 0x22, 0x0A, 0x60, 0xED, 0x49, 0x14, 0x31, 0x08, 0x60, 0x51, 0x07,
+ 0x01, 0xF8, 0x50, 0x0F, 0xFF, 0x23, 0x4B, 0x70, 0x01, 0xF8, 0x05, 0x0C, 0x10, 0x23, 0x4B, 0x80,
+ 0x8A, 0x80, 0xE8, 0x49, 0x08, 0x60, 0x48, 0x60, 0x88, 0x60, 0xC8, 0x60, 0x08, 0x61, 0x48, 0x61,
+ 0x88, 0x61, 0xC8, 0x61, 0x08, 0x62, 0x70, 0x47, 0x70, 0x47, 0xE2, 0x4A, 0x11, 0x60, 0xDF, 0x49,
+ 0x00, 0x22, 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00,
+ 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8, 0x58, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0xD9, 0x4B,
+ 0x10, 0xB5, 0xD6, 0x4A, 0x19, 0x60, 0x00, 0x21, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8,
+ 0x51, 0x40, 0xE4, 0x07, 0x07, 0xD0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x58, 0x00,
+ 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6,
+ 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, 0xF1, 0xE7, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x58, 0x00,
+ 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x50, 0x90, 0xF8, 0x22, 0x00, 0xC0, 0xF3, 0x81, 0x00, 0x28, 0xB1,
+ 0x01, 0x28, 0x05, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xC3, 0x48, 0x70, 0x47, 0xC3, 0x48, 0x70, 0x47,
+ 0xC3, 0x48, 0x70, 0x47, 0xC3, 0x48, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8,
+ 0x51, 0x00, 0xBA, 0x49, 0xC2, 0x07, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0xD0, 0x08, 0x60, 0x70, 0xBD,
+ 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x04, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8,
+ 0x58, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x58, 0x00, 0xFF, 0xF7, 0x75, 0xF9, 0x01, 0x46, 0xFF, 0xF7,
+ 0xD0, 0xFF, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0x63, 0xFA, 0x65, 0x61, 0x02, 0x20, 0x00, 0xF0,
+ 0x35, 0xFB, 0x62, 0xB6, 0x70, 0xBD, 0xAB, 0x48, 0x10, 0xB5, 0x00, 0x21, 0x04, 0x68, 0x01, 0x60,
+ 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x00, 0x20,
+ 0xFF, 0xF7, 0x82, 0xFF, 0x10, 0xBD, 0xA3, 0x4A, 0x51, 0x60, 0xA0, 0x49, 0x00, 0x22, 0x09, 0x1D,
+ 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0xCA, 0x06,
+ 0xA2, 0xF8, 0x5A, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x9A, 0x4B, 0x10, 0xB5, 0x59, 0x60,
+ 0x96, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0xD1, 0x06, 0x91, 0xF8, 0x51, 0x40, 0xA4, 0x07,
+ 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA,
+ 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x5A, 0x00, 0x01, 0x20,
+ 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x5A, 0x00, 0x70, 0x47, 0x70, 0xB5,
+ 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x8B, 0x49, 0x82, 0x07, 0x4F, 0xF0, 0x00, 0x00,
+ 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x08, 0x02, 0x62, 0x61, 0x08, 0x60,
+ 0xB4, 0xF8, 0x5A, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x5A, 0x00, 0xFF, 0xF7, 0x0C, 0xF9, 0x01, 0x46,
+ 0xFF, 0xF7, 0x67, 0xFF, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0xFA, 0xF9, 0x65, 0x61, 0x03, 0x20,
+ 0x00, 0xF0, 0xCC, 0xFA, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0x75, 0x48, 0x10, 0xB5,
+ 0x00, 0x21, 0x44, 0x68, 0x41, 0x60, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8,
+ 0x10, 0x40, 0x60, 0x47, 0x01, 0x20, 0xFF, 0xF7, 0x17, 0xFF, 0x10, 0xBD, 0x6D, 0x4A, 0x91, 0x60,
+ 0x71, 0x49, 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72,
+ 0x02, 0xEA, 0x40, 0x00, 0x8A, 0x06, 0xA2, 0xF8, 0x5C, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47,
+ 0x64, 0x4B, 0x10, 0xB5, 0x99, 0x60, 0x68, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x91, 0x06,
+ 0x91, 0xF8, 0x51, 0x40, 0x64, 0x07, 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10,
+ 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09,
+ 0xA1, 0xF8, 0x5C, 0x00, 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8,
+ 0x5C, 0x00, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x57, 0x49,
+ 0x42, 0x07, 0x4F, 0xF0, 0x00, 0x00, 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0,
+ 0x10, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8, 0x5C, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x5C, 0x00,
+ 0xFF, 0xF7, 0xA1, 0xF8, 0x01, 0x46, 0xFF, 0xF7, 0xFC, 0xFE, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7,
+ 0x8F, 0xF9, 0x65, 0x61, 0x04, 0x20, 0x00, 0xF0, 0x61, 0xFA, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60,
+ 0x70, 0xBD, 0x40, 0x48, 0x10, 0xB5, 0x00, 0x21, 0x84, 0x68, 0x81, 0x60, 0xFF, 0xF7, 0xD2, 0xFF,
+ 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x02, 0x20, 0xFF, 0xF7, 0xAC, 0xFE,
+ 0x10, 0xBD, 0x38, 0x4A, 0xD1, 0x60, 0x3D, 0x49, 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, 0x00, 0xEB,
+ 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8,
+ 0x5E, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x2E, 0x4B, 0x10, 0xB5, 0xD9, 0x60, 0x33, 0x4A,
+ 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, 0x24, 0x07,
+ 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA,
+ 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x5E, 0x00, 0x01, 0x20,
+ 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x5E, 0x00, 0x70, 0x47, 0x70, 0xB5,
+ 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x21, 0x49, 0x02, 0x07, 0x4F, 0xF0, 0x00, 0x00,
+ 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x20, 0x02, 0x62, 0x61, 0x08, 0x60,
+ 0xB4, 0xF8, 0x5E, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x5E, 0x00, 0xFF, 0xF7, 0x34, 0xF8, 0x01, 0x46,
+ 0xFF, 0xF7, 0x8F, 0xFE, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0x22, 0xF9, 0x65, 0x61, 0x05, 0x20,
+ 0x00, 0xF0, 0xF4, 0xF9, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0x09, 0x48, 0x10, 0xB5,
+ 0x00, 0x21, 0xC4, 0x68, 0xC1, 0x60, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8,
+ 0x10, 0x40, 0x60, 0x47, 0x03, 0x20, 0xFF, 0xF7, 0x3F, 0xFE, 0x10, 0xBD, 0x40, 0x09, 0x00, 0x22,
+ 0xC0, 0x04, 0x00, 0x22, 0xF4, 0x07, 0x10, 0x00, 0x00, 0x09, 0x3D, 0x00, 0x00, 0x48, 0xE8, 0x01,
+ 0x00, 0x24, 0xF4, 0x00, 0x00, 0x12, 0x7A, 0x00, 0x44, 0x09, 0x00, 0x22, 0x48, 0x09, 0x00, 0x22,
+ 0x4C, 0x09, 0x00, 0x22, 0xEB, 0x4A, 0x11, 0x61, 0xEB, 0x49, 0x00, 0x22, 0x0A, 0x60, 0x00, 0xEB,
+ 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8,
+ 0x60, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0xE2, 0x4B, 0x10, 0xB5, 0xE2, 0x4A, 0x19, 0x61,
+ 0x00, 0x21, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, 0xE4, 0x06, 0x08, 0xD4,
+ 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00,
+ 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x60, 0x00, 0x01, 0x20, 0x10, 0x60,
+ 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x60, 0x00, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0,
+ 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0xD0, 0x49, 0xC2, 0x06, 0x4F, 0xF0, 0x00, 0x00, 0x1A, 0xD4,
+ 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF0, 0x40, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8,
+ 0x60, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x60, 0x00, 0xFE, 0xF7, 0xB5, 0xFF, 0x01, 0x46, 0xFF, 0xF7,
+ 0x10, 0xFE, 0xB1, 0xFB, 0xF0, 0xF0, 0xEA, 0xF7, 0xA3, 0xF8, 0x65, 0x61, 0x06, 0x20, 0x00, 0xF0,
+ 0x75, 0xF9, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0xBE, 0x48, 0x10, 0xB5, 0x00, 0x21,
+ 0x04, 0x69, 0x01, 0x61, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40,
+ 0x60, 0x47, 0x04, 0x20, 0xFF, 0xF7, 0xC0, 0xFD, 0x10, 0xBD, 0xB6, 0x4A, 0x51, 0x61, 0xB6, 0x49,
+ 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60, 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA,
+ 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52, 0xA2, 0xF8, 0x62, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47,
+ 0xAC, 0x4B, 0x10, 0xB5, 0x59, 0x61, 0xAC, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x4F, 0xF0,
+ 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40, 0xA4, 0x06, 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB,
+ 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73, 0x03, 0xEA, 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43,
+ 0x80, 0x09, 0xA1, 0xF8, 0x62, 0x00, 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50,
+ 0xB0, 0xF8, 0x62, 0x00, 0x70, 0x47, 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00,
+ 0x9A, 0x49, 0x82, 0x06, 0x4F, 0xF0, 0x00, 0x00, 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69,
+ 0x42, 0xF0, 0x80, 0x02, 0x62, 0x61, 0x08, 0x60, 0xB4, 0xF8, 0x62, 0x10, 0x09, 0xB1, 0xA4, 0xF8,
+ 0x62, 0x00, 0xFE, 0xF7, 0x48, 0xFF, 0x01, 0x46, 0xFF, 0xF7, 0xA3, 0xFD, 0xB1, 0xFB, 0xF0, 0xF0,
+ 0xEA, 0xF7, 0x36, 0xF8, 0x65, 0x61, 0x07, 0x20, 0x00, 0xF0, 0x08, 0xF9, 0x62, 0xB6, 0x70, 0xBD,
+ 0x08, 0x60, 0x70, 0xBD, 0x87, 0x48, 0x10, 0xB5, 0x00, 0x21, 0x44, 0x69, 0x41, 0x61, 0xFF, 0xF7,
+ 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x05, 0x20, 0xFF, 0xF7,
+ 0x53, 0xFD, 0x10, 0xBD, 0x7F, 0x4A, 0x91, 0x61, 0x80, 0x49, 0x00, 0x22, 0x09, 0x1D, 0x0A, 0x60,
+ 0x00, 0xEB, 0x80, 0x00, 0x4F, 0xF6, 0xFF, 0x72, 0x02, 0xEA, 0x40, 0x00, 0x4F, 0xF0, 0x00, 0x52,
+ 0xA2, 0xF8, 0x64, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x76, 0x4B, 0x10, 0xB5, 0x99, 0x61,
+ 0x76, 0x4A, 0x00, 0x21, 0x12, 0x1D, 0x11, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x51, 0x40,
+ 0x64, 0x06, 0x08, 0xD4, 0x00, 0xEB, 0xC0, 0x03, 0x03, 0xEB, 0x00, 0x10, 0x4F, 0xF6, 0xFF, 0x73,
+ 0x03, 0xEA, 0x80, 0x00, 0x02, 0xE0, 0x1B, 0x6A, 0x58, 0x43, 0x80, 0x09, 0xA1, 0xF8, 0x64, 0x00,
+ 0x01, 0x20, 0x10, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0xB0, 0xF8, 0x64, 0x00, 0x70, 0x47,
+ 0x70, 0xB5, 0x4F, 0xF0, 0x00, 0x54, 0x94, 0xF8, 0x51, 0x00, 0x65, 0x49, 0x42, 0x06, 0x4F, 0xF0,
+ 0x00, 0x00, 0x1A, 0xD4, 0x65, 0x69, 0x72, 0xB6, 0x62, 0x69, 0x42, 0xF4, 0x80, 0x72, 0x62, 0x61,
+ 0x08, 0x60, 0xB4, 0xF8, 0x64, 0x10, 0x09, 0xB1, 0xA4, 0xF8, 0x64, 0x00, 0xFE, 0xF7, 0xDB, 0xFE,
+ 0x01, 0x46, 0xFF, 0xF7, 0x36, 0xFD, 0xB1, 0xFB, 0xF0, 0xF0, 0xE9, 0xF7, 0xC9, 0xFF, 0x65, 0x61,
+ 0x08, 0x20, 0x00, 0xF0, 0x9B, 0xF8, 0x62, 0xB6, 0x70, 0xBD, 0x08, 0x60, 0x70, 0xBD, 0x51, 0x48,
+ 0x10, 0xB5, 0x00, 0x21, 0x84, 0x69, 0x81, 0x61, 0xFF, 0xF7, 0xD2, 0xFF, 0x1C, 0xB1, 0xA4, 0x46,
+ 0xBD, 0xE8, 0x10, 0x40, 0x60, 0x47, 0x06, 0x20, 0xFF, 0xF7, 0xE6, 0xFC, 0x10, 0xBD, 0x10, 0xB5,
+ 0xFE, 0xF7, 0xA0, 0xFE, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x22, 0x20, 0x42, 0xF2, 0x10, 0x73,
+ 0xB0, 0xFB, 0xF3, 0xF0, 0xC2, 0xF3, 0x81, 0x02, 0x52, 0x1C, 0xD0, 0x40, 0xB1, 0xF8, 0x54, 0x20,
+ 0xC9, 0x6C, 0x51, 0x43, 0x89, 0x09, 0xB0, 0xFB, 0xF1, 0xF0, 0x10, 0xBD, 0x40, 0x49, 0x00, 0x22,
+ 0x09, 0x1D, 0x0A, 0x60, 0x3B, 0x4A, 0x12, 0x6A, 0x50, 0x43, 0x4F, 0xF0, 0x00, 0x52, 0x80, 0x09,
+ 0xA2, 0xF8, 0x66, 0x00, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47, 0x39, 0x49, 0x00, 0x20, 0x09, 0x1D,
+ 0x08, 0x60, 0x70, 0x47, 0x33, 0x49, 0xC8, 0x61, 0x35, 0x49, 0x01, 0x20, 0xA0, 0x31, 0x08, 0x60,
+ 0x09, 0x1D, 0x08, 0x60, 0x70, 0x47, 0x2F, 0x4A, 0x10, 0xB5, 0x00, 0x20, 0xD1, 0x69, 0xD0, 0x61,
+ 0x51, 0xB1, 0x2F, 0x4A, 0xA0, 0x32, 0x10, 0x60, 0x4F, 0xF0, 0x00, 0x50, 0xC0, 0x6C, 0xBD, 0xE8,
+ 0x10, 0x40, 0x20, 0xF0, 0x7F, 0x40, 0x08, 0x47, 0xFF, 0x20, 0xFF, 0xF7, 0x9D, 0xFC, 0x10, 0xBD,
+ 0x10, 0xB5, 0x04, 0x46, 0xFE, 0xF7, 0x56, 0xFE, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x22, 0x10,
+ 0x42, 0xF2, 0x10, 0x72, 0xB0, 0xFB, 0xF2, 0xF0, 0xC1, 0xF3, 0x81, 0x01, 0x49, 0x1C, 0xC8, 0x40,
+ 0x00, 0x03, 0xB0, 0xFB, 0xF4, 0xF0, 0x1B, 0x49, 0x08, 0x62, 0x10, 0xBD, 0x30, 0xB5, 0x4F, 0xF0,
+ 0x00, 0x55, 0x01, 0x24, 0x84, 0x40, 0x95, 0xF8, 0x51, 0x00, 0x09, 0xB1, 0x20, 0x43, 0x00, 0xE0,
+ 0xA0, 0x43, 0x85, 0xF8, 0x51, 0x00, 0x95, 0xF8, 0x4B, 0x00, 0x0A, 0xB1, 0x20, 0x43, 0x00, 0xE0,
+ 0xA0, 0x43, 0x85, 0xF8, 0x4B, 0x00, 0x15, 0xF8, 0x50, 0x0F, 0x0B, 0xB1, 0x20, 0x43, 0x00, 0xE0,
+ 0xA0, 0x43, 0x28, 0x70, 0x30, 0xBD, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0xF8, 0x4A, 0x1F, 0xC0, 0x79,
+ 0x81, 0x43, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02,
+ 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x12,
+ 0x70, 0x47, 0x00, 0x00, 0xF4, 0x07, 0x10, 0x00, 0x50, 0x09, 0x00, 0x22, 0x54, 0x09, 0x00, 0x22,
+ 0x58, 0x09, 0x00, 0x22, 0x00, 0x21, 0x01, 0x60, 0x08, 0x46, 0x70, 0x47, 0x30, 0xB5, 0x0A, 0x68,
+ 0x12, 0xB1, 0x0B, 0x46, 0x84, 0x6A, 0x08, 0xE0, 0x00, 0x22, 0x08, 0x60, 0xC0, 0xE9, 0x03, 0x21,
+ 0x0A, 0xE0, 0x02, 0xF1, 0x0C, 0x03, 0xD2, 0x68, 0x12, 0xB1, 0x95, 0x6A, 0xA5, 0x42, 0xF8, 0xDC,
+ 0x1A, 0x68, 0xC0, 0xE9, 0x03, 0x21, 0x18, 0x60, 0x00, 0x20, 0x30, 0xBD, 0x00, 0x68, 0x00, 0x22,
+ 0x01, 0xE0, 0xC0, 0x68, 0x52, 0x1C, 0x8A, 0x42, 0x01, 0xD0, 0x00, 0x28, 0xF9, 0xD1, 0x70, 0x47,
+ 0x00, 0x68, 0x70, 0x47, 0x02, 0x69, 0x0A, 0xB1, 0x11, 0x68, 0x31, 0xB9, 0x6F, 0xF0, 0x04, 0x00,
+ 0x70, 0x47, 0x01, 0xF1, 0x0C, 0x02, 0xC9, 0x68, 0x39, 0xB1, 0x81, 0x42, 0xF9, 0xD1, 0xC9, 0x68,
+ 0x11, 0x60, 0x00, 0x21, 0x01, 0x61, 0x08, 0x46, 0x70, 0x47, 0x6F, 0xF0, 0x03, 0x00, 0x70, 0x47,
+ 0xC1, 0x7D, 0x01, 0x29, 0x05, 0xD1, 0x49, 0x07, 0x11, 0xF8, 0x2D, 0x2F, 0x42, 0xF0, 0x02, 0x02,
+ 0x0A, 0x70, 0x14, 0x49, 0x02, 0x68, 0x4A, 0x60, 0x42, 0x68, 0x8A, 0x60, 0x80, 0x7D, 0x08, 0x70,
+ 0x70, 0x47, 0x30, 0xB4, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0xF8, 0xE2, 0x1F, 0xC2, 0x89, 0x0D, 0x48,
+ 0xCC, 0x07, 0x43, 0x68, 0x03, 0xD0, 0x02, 0x24, 0x44, 0x70, 0x20, 0x46, 0x04, 0xE0, 0x01, 0x24,
+ 0x44, 0x70, 0x52, 0x1C, 0x92, 0xB2, 0x20, 0x46, 0x30, 0xBC, 0x18, 0x47, 0x4F, 0xF0, 0x00, 0x50,
+ 0x90, 0xF8, 0xE2, 0x10, 0x03, 0x48, 0x02, 0x78, 0x91, 0x42, 0x01, 0xD1, 0x80, 0x68, 0x00, 0x47,
+ 0x70, 0x47, 0x00, 0x00, 0x2C, 0x08, 0x10, 0x00, 0x53, 0xEA, 0x02, 0x0C, 0x00, 0xF0, 0x69, 0x80,
+ 0x2D, 0xE9, 0xF0, 0x4B, 0x4F, 0xF0, 0x00, 0x06, 0x00, 0x2B, 0x1F, 0xBF, 0xB3, 0xFA, 0x83, 0xF5,
+ 0x03, 0xFA, 0x05, 0xF4, 0x24, 0xFA, 0x05, 0xF6, 0x5E, 0x40, 0x12, 0xBF, 0x16, 0x43, 0xB2, 0xFA,
+ 0x82, 0xF5, 0x02, 0xFA, 0x05, 0xF4, 0xC5, 0xF1, 0x20, 0x05, 0x1E, 0xBF, 0x22, 0xFA, 0x05, 0xFC,
+ 0x44, 0xEA, 0x0C, 0x04, 0x20, 0x35, 0x56, 0xEA, 0x04, 0x4C, 0x4F, 0xEA, 0x14, 0x44, 0x18, 0xBF,
+ 0x64, 0x1C, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x00, 0x09, 0x90, 0x42, 0x71, 0xEB, 0x03, 0x0C,
+ 0x39, 0xD3, 0x00, 0x29, 0x19, 0xBF, 0xB1, 0xFA, 0x81, 0xF7, 0x01, 0xFA, 0x07, 0xF6, 0xB0, 0xFA,
+ 0x80, 0xF7, 0x00, 0xFA, 0x07, 0xF6, 0xC7, 0xF1, 0x20, 0x07, 0x1E, 0xBF, 0x20, 0xFA, 0x07, 0xFC,
+ 0x46, 0xEA, 0x0C, 0x06, 0x20, 0x37, 0xB6, 0xFB, 0xF4, 0xFC, 0xA7, 0xEB, 0x05, 0x07, 0x10, 0x3F,
+ 0x07, 0xF0, 0x1F, 0x0B, 0xCB, 0xF1, 0x20, 0x06, 0x0C, 0xFA, 0x0B, 0xFB, 0x2C, 0xFA, 0x06, 0xF6,
+ 0x44, 0xBF, 0xB3, 0x46, 0x00, 0x26, 0x20, 0x2F, 0xA4, 0xBF, 0x5E, 0x46, 0x4F, 0xF0, 0x00, 0x0B,
+ 0x5B, 0xEA, 0x06, 0x0C, 0x08, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, 0x19, 0xEB, 0x0B, 0x09, 0xAB, 0xFB,
+ 0x02, 0x7C, 0x48, 0xEB, 0x06, 0x08, 0xC0, 0x1B, 0x06, 0xFB, 0x02, 0xCC, 0x0B, 0xFB, 0x03, 0xCC,
+ 0x71, 0xEB, 0x0C, 0x01, 0xC1, 0xE7, 0x0B, 0x46, 0x02, 0x46, 0x41, 0x46, 0x48, 0x46, 0xBD, 0xE8,
+ 0xF0, 0x8B, 0x13, 0xB5, 0x4F, 0xF0, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x01, 0xAF, 0xF3, 0x00, 0x80,
+ 0xBD, 0xE8, 0x1C, 0x40, 0x70, 0x47, 0xB2, 0xF1, 0x20, 0x03, 0x0A, 0xD5, 0xC2, 0xF1, 0x20, 0x03,
+ 0x01, 0xFA, 0x02, 0xF1, 0x20, 0xFA, 0x03, 0xF3, 0x00, 0xFA, 0x02, 0xF0, 0x41, 0xEA, 0x03, 0x01,
+ 0x70, 0x47, 0x00, 0xFA, 0x03, 0xF1, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0x10, 0xB5, 0x4C, 0x10,
+ 0x84, 0xEA, 0x53, 0x04, 0x04, 0xD5, 0x40, 0x42, 0xC1, 0xF1, 0x00, 0x01, 0x38, 0xBF, 0x49, 0x1E,
+ 0x1B, 0x42, 0x04, 0xD5, 0x52, 0x42, 0xC3, 0xF1, 0x00, 0x03, 0x38, 0xBF, 0x5B, 0x1E, 0xFF, 0xF7,
+ 0x63, 0xFF, 0x14, 0xF0, 0x80, 0x4F, 0x04, 0xD0, 0x40, 0x42, 0xC1, 0xF1, 0x00, 0x01, 0x38, 0xBF,
+ 0x49, 0x1E, 0x14, 0xF0, 0x00, 0x4F, 0x04, 0xD0, 0x52, 0x42, 0xC3, 0xF1, 0x00, 0x03, 0x38, 0xBF,
+ 0x5B, 0x1E, 0x10, 0xBD, 0x03, 0x2A, 0x40, 0xF2, 0x30, 0x80, 0x10, 0xF0, 0x03, 0x0C, 0x00, 0xF0,
+ 0x15, 0x80, 0x11, 0xF8, 0x01, 0x3B, 0xBC, 0xF1, 0x02, 0x0F, 0x62, 0x44, 0x98, 0xBF, 0x11, 0xF8,
+ 0x01, 0xCB, 0x00, 0xF8, 0x01, 0x3B, 0x38, 0xBF, 0x11, 0xF8, 0x01, 0x3B, 0xA2, 0xF1, 0x04, 0x02,
+ 0x98, 0xBF, 0x00, 0xF8, 0x01, 0xCB, 0x38, 0xBF, 0x00, 0xF8, 0x01, 0x3B, 0x11, 0xF0, 0x03, 0x03,
+ 0x00, 0xF0, 0x25, 0x80, 0x08, 0x3A, 0xC0, 0xF0, 0x08, 0x80, 0x51, 0xF8, 0x04, 0x3B, 0x08, 0x3A,
+ 0x51, 0xF8, 0x04, 0xCB, 0xA0, 0xE8, 0x08, 0x10, 0xF5, 0xE7, 0x12, 0x1D, 0x5C, 0xBF, 0x51, 0xF8,
+ 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0xAF, 0xF3, 0x00, 0x80, 0xD2, 0x07, 0x24, 0xBF, 0x11, 0xF8,
+ 0x01, 0x3B, 0x11, 0xF8, 0x01, 0xCB, 0x48, 0xBF, 0x11, 0xF8, 0x01, 0x2B, 0x24, 0xBF, 0x00, 0xF8,
+ 0x01, 0x3B, 0x00, 0xF8, 0x01, 0xCB, 0x48, 0xBF, 0x00, 0xF8, 0x01, 0x2B, 0x70, 0x47, 0x10, 0xB5,
+ 0x20, 0x3A, 0xC0, 0xF0, 0x0B, 0x80, 0xB1, 0xE8, 0x18, 0x50, 0x20, 0x3A, 0xA0, 0xE8, 0x18, 0x50,
+ 0xB1, 0xE8, 0x18, 0x50, 0xA0, 0xE8, 0x18, 0x50, 0xBF, 0xF4, 0xF5, 0xAF, 0x5F, 0xEA, 0x02, 0x7C,
+ 0x24, 0xBF, 0xB1, 0xE8, 0x18, 0x50, 0xA0, 0xE8, 0x18, 0x50, 0x44, 0xBF, 0x18, 0xC9, 0x18, 0xC0,
+ 0xBD, 0xE8, 0x10, 0x40, 0x5F, 0xEA, 0x82, 0x7C, 0x24, 0xBF, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8,
+ 0x04, 0x3B, 0x08, 0xBF, 0x70, 0x47, 0xD2, 0x07, 0x28, 0xBF, 0x31, 0xF8, 0x02, 0x3B, 0x48, 0xBF,
+ 0x11, 0xF8, 0x01, 0x2B, 0x28, 0xBF, 0x20, 0xF8, 0x02, 0x3B, 0x48, 0xBF, 0x00, 0xF8, 0x01, 0x2B,
+ 0x70, 0x47, 0x02, 0xF0, 0xFF, 0x03, 0x43, 0xEA, 0x03, 0x22, 0x42, 0xEA, 0x02, 0x42, 0x00, 0xF0,
+ 0x02, 0xB8, 0x4F, 0xF0, 0x00, 0x02, 0x04, 0x29, 0xC0, 0xF0, 0x12, 0x80, 0x10, 0xF0, 0x03, 0x0C,
+ 0x00, 0xF0, 0x1B, 0x80, 0xCC, 0xF1, 0x04, 0x0C, 0xBC, 0xF1, 0x02, 0x0F, 0x18, 0xBF, 0x00, 0xF8,
+ 0x01, 0x2B, 0xA8, 0xBF, 0x20, 0xF8, 0x02, 0x2B, 0xA1, 0xEB, 0x0C, 0x01, 0x00, 0xF0, 0x0D, 0xB8,
+ 0x5F, 0xEA, 0xC1, 0x7C, 0x24, 0xBF, 0x00, 0xF8, 0x01, 0x2B, 0x00, 0xF8, 0x01, 0x2B, 0x48, 0xBF,
+ 0x00, 0xF8, 0x01, 0x2B, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x02, 0x00, 0xB5, 0x13, 0x46, 0x94, 0x46,
+ 0x96, 0x46, 0x20, 0x39, 0x22, 0xBF, 0xA0, 0xE8, 0x0C, 0x50, 0xA0, 0xE8, 0x0C, 0x50, 0xB1, 0xF1,
+ 0x20, 0x01, 0xBF, 0xF4, 0xF7, 0xAF, 0x09, 0x07, 0x28, 0xBF, 0xA0, 0xE8, 0x0C, 0x50, 0x48, 0xBF,
+ 0x0C, 0xC0, 0x5D, 0xF8, 0x04, 0xEB, 0x89, 0x00, 0x28, 0xBF, 0x40, 0xF8, 0x04, 0x2B, 0x08, 0xBF,
+ 0x70, 0x47, 0x48, 0xBF, 0x20, 0xF8, 0x02, 0x2B, 0x11, 0xF0, 0x80, 0x4F, 0x18, 0xBF, 0x00, 0xF8,
+ 0x01, 0x2B, 0x70, 0x47, 0x04, 0x46, 0xAF, 0xF3, 0x00, 0x80, 0x20, 0x46, 0xE9, 0xF7, 0x36, 0xFC,
+ 0x01, 0x49, 0x18, 0x20, 0xAB, 0xBE, 0xFE, 0xE7, 0x26, 0x00, 0x02, 0x00, 0x70, 0x47, 0x00, 0x00,
+ 0x01, 0x49, 0x00, 0x20, 0x08, 0x60, 0x70, 0x47, 0x3C, 0x05, 0x00, 0x22, 0x2D, 0xE9, 0xF0, 0x41,
+ 0x0F, 0x4F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0x4F, 0xF0, 0x00, 0x56, 0x08, 0xFA, 0x04, 0xF0,
+ 0xC5, 0xB2, 0x96, 0xF8, 0x2F, 0x00, 0x28, 0x42, 0x0C, 0xD0, 0x96, 0xF8, 0x39, 0x00, 0x28, 0x42,
+ 0x08, 0xD0, 0x57, 0xF8, 0x24, 0x00, 0x00, 0xB1, 0x80, 0x47, 0x96, 0xF8, 0x2F, 0x00, 0xA8, 0x43,
+ 0x86, 0xF8, 0x2F, 0x00, 0x64, 0x1C, 0x06, 0x2C, 0xE8, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00,
+ 0x1C, 0x88, 0x10, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0F, 0x4F, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08,
+ 0x4F, 0xF0, 0x00, 0x56, 0x08, 0xFA, 0x04, 0xF0, 0xC5, 0xB2, 0x96, 0xF8, 0x2E, 0x00, 0x28, 0x42,
+ 0x0C, 0xD0, 0x96, 0xF8, 0x38, 0x00, 0x28, 0x42, 0x08, 0xD0, 0x57, 0xF8, 0x24, 0x00, 0x00, 0xB1,
+ 0x80, 0x47, 0x96, 0xF8, 0x2E, 0x00, 0xA8, 0x43, 0x86, 0xF8, 0x2E, 0x00, 0x64, 0x1C, 0x06, 0x2C,
+ 0xE8, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x00, 0xFC, 0x87, 0x10, 0x00, 0x01, 0x21, 0x81, 0x40,
+ 0xC8, 0xB2, 0x4F, 0xF0, 0x00, 0x51, 0x91, 0xF8, 0x33, 0x10, 0x01, 0x42, 0x01, 0xD0, 0x01, 0x20,
+ 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x01, 0x49, 0x01, 0x20, 0x08, 0x60, 0x70, 0x47,
+ 0x3C, 0x05, 0x00, 0x22, 0x00, 0x48, 0x70, 0x47, 0x59, 0x07, 0x10, 0x00, 0x07, 0x48, 0x41, 0x78,
+ 0x49, 0xB1, 0x80, 0x78, 0x38, 0xB1, 0x06, 0x48, 0x80, 0x79, 0x01, 0x28, 0x03, 0xD1, 0x05, 0x48,
+ 0x00, 0x78, 0x01, 0x28, 0x00, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x4C, 0x07, 0x10, 0x00,
+ 0xEC, 0x06, 0x10, 0x00, 0x04, 0x05, 0x10, 0x00, 0x03, 0x48, 0x41, 0x78, 0x11, 0xB9, 0x80, 0x78,
+ 0x00, 0x28, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x4C, 0x07, 0x10, 0x00, 0x01, 0x48, 0x00, 0x78,
+ 0x70, 0x47, 0x00, 0x00, 0x50, 0x06, 0x10, 0x00, 0xC0, 0x6E, 0x70, 0x47, 0x90, 0xF8, 0x73, 0x00,
+ 0x70, 0x47, 0x90, 0xF8, 0x72, 0x00, 0x70, 0x47, 0x05, 0x48, 0x41, 0x78, 0x82, 0x78, 0x11, 0x44,
+ 0x02, 0x78, 0xC0, 0x78, 0x10, 0x44, 0x08, 0x18, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x00, 0x00,
+ 0x0C, 0x06, 0x10, 0x00, 0x70, 0xB5, 0xD0, 0xE9, 0x00, 0x21, 0x4C, 0x08, 0x4F, 0xEA, 0x32, 0x03,
+ 0x96, 0x18, 0x41, 0xEB, 0x01, 0x05, 0x33, 0x43, 0x2C, 0x43, 0x13, 0x43, 0x0C, 0x43, 0xC0, 0xE9,
+ 0x00, 0x34, 0x70, 0xBD, 0x01, 0xEB, 0x81, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0x29, 0x30, 0x70, 0x47,
+ 0x02, 0x4A, 0x12, 0x78, 0x51, 0x43, 0x00, 0xEB, 0x41, 0x00, 0x70, 0x47, 0xBA, 0x06, 0x10, 0x00,
+ 0x01, 0xEB, 0x81, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0x29, 0x30, 0x70, 0x47, 0x02, 0x4A, 0x12, 0x78,
+ 0x51, 0x43, 0x00, 0xEB, 0x41, 0x00, 0x70, 0x47, 0xBA, 0x06, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xBE, 0x94, 0xFE, 0xFF, 0x27, 0xC4,
+ 0xFE, 0xFF, 0x59, 0xF2, 0xFE, 0xFF, 0x6B, 0x1F, 0xFF, 0xFF, 0x81, 0x4B, 0xFF, 0xFF, 0xC5, 0x76,
+ 0xFF, 0xFF, 0x67, 0xA1, 0xFF, 0xFF, 0x97, 0xCB, 0xFF, 0xFF, 0x88, 0xF5, 0xFF, 0xFF, 0x6C, 0x1F,
+ 0x00, 0x00, 0x76, 0x49, 0x00, 0x00, 0xD9, 0x73, 0x00, 0x00, 0xC6, 0x9E, 0x00, 0x00, 0x6D, 0xCA,
+ 0x00, 0x00, 0xFC, 0xF6, 0x00, 0x00, 0x9A, 0x24, 0x01, 0x00, 0x66, 0x53, 0x01, 0x00, 0xA3, 0x8D,
+ 0x00, 0x00, 0x71, 0x74, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0xA2, 0x4F, 0x00, 0x00, 0xC8, 0x42,
+ 0x00, 0x00, 0x0C, 0x39, 0x00, 0x00, 0x21, 0x32, 0x00, 0x00, 0xD2, 0x2D, 0x00, 0x00, 0x00, 0x2C,
+ 0x00, 0x00, 0x9B, 0x2C, 0x00, 0x00, 0xA9, 0x2F, 0x00, 0x00, 0x40, 0x35, 0x00, 0x00, 0x8B, 0x3D,
+ 0x00, 0x00, 0xCB, 0x48, 0x00, 0x00, 0x59, 0x57, 0x00, 0x00, 0xAD, 0x69, 0x00, 0x00, 0x65, 0x80,
+ 0x00, 0x00, 0x30, 0x11, 0x00, 0x00, 0x4C, 0x1C, 0x00, 0x00, 0x2D, 0x29, 0x00, 0x00, 0x86, 0x37,
+ 0x00, 0x00, 0x24, 0x47, 0x00, 0x00, 0xE8, 0x57, 0x00, 0x00, 0xC4, 0x69, 0x00, 0x00, 0xB5, 0x7C,
+ 0x00, 0x00, 0xC4, 0x90, 0x00, 0x00, 0x03, 0xA6, 0x00, 0x00, 0x8F, 0xBC, 0x00, 0x00, 0x8C, 0xD4,
+ 0x00, 0x00, 0x29, 0xEE, 0x00, 0x00, 0x9C, 0x09, 0x01, 0x00, 0x2B, 0x27, 0x01, 0x00, 0x24, 0x47,
+ 0x01, 0x00, 0xE6, 0x69, 0x01, 0x00, 0x98, 0x08, 0x00, 0x00, 0x26, 0x0E, 0x00, 0x00, 0x97, 0x14,
+ 0x00, 0x00, 0xC3, 0x1B, 0x00, 0x00, 0x92, 0x23, 0x00, 0x00, 0xF4, 0x2B, 0x00, 0x00, 0xE2, 0x34,
+ 0x00, 0x00, 0x5A, 0x3E, 0x00, 0x00, 0x62, 0x48, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x48, 0x5E,
+ 0x00, 0x00, 0x46, 0x6A, 0x00, 0x00, 0x14, 0x77, 0x00, 0x00, 0xCE, 0x84, 0x00, 0x00, 0x95, 0x93,
+ 0x00, 0x00, 0x92, 0xA3, 0x00, 0x00, 0xF3, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x0C, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE4, 0x40, 0x10, 0x00, 0x30, 0x46, 0x10, 0x00, 0x2B, 0xF5, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xF4, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x21, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xF4, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x4B, 0xF4, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xAD, 0xF4, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xC3, 0xF4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF7, 0xF4, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xF9, 0xF4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFB, 0xF4, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xFD, 0xF4, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xF4, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0xF5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0xF5, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x29, 0xF5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6F, 0xF5, 0x00, 0x00,
+ 0x6B, 0xF5, 0x00, 0x00, 0xD5, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x31, 0xF7, 0x00, 0x00,
+ 0x6B, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00,
+ 0x6B, 0xF5, 0x00, 0x00, 0x9F, 0xF5, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC1, 0xF5, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF6, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x25, 0xF6, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x49, 0xF6, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x7F, 0xF6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2D, 0xF7, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x5D, 0xF7, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xBB, 0xF7, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xD1, 0xF7, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0xF8, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xA7, 0xF8, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x8B, 0xF9, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0xCB, 0xF9, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5F, 0xF8, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x25, 0xF9, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x6B, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xF7, 0x00, 0x00,
+ 0x81, 0xF7, 0x00, 0x00, 0x8B, 0xF7, 0x00, 0x00, 0x9B, 0xF7, 0x00, 0x00, 0xAB, 0xF7, 0x00, 0x00,
+ 0x61, 0xFB, 0x00, 0x00, 0x83, 0xFB, 0x00, 0x00, 0x8B, 0xFB, 0x00, 0x00, 0xAB, 0xFB, 0x00, 0x00,
+ 0x0D, 0xFC, 0x00, 0x00, 0x33, 0xFC, 0x00, 0x00, 0x43, 0xFC, 0x00, 0x00, 0x55, 0xFC, 0x00, 0x00,
+ 0x67, 0xFC, 0x00, 0x00, 0x79, 0xFC, 0x00, 0x00, 0x8B, 0xFC, 0x00, 0x00, 0x9D, 0xFC, 0x00, 0x00,
+ 0xAF, 0xFC, 0x00, 0x00, 0xC1, 0xFC, 0x00, 0x00, 0xD3, 0xFC, 0x00, 0x00, 0xE5, 0xFC, 0x00, 0x00,
+ 0x85, 0x86, 0x60, 0x61, 0xD0, 0x02, 0x0F, 0x01, 0x00, 0xA6, 0x02, 0x0F, 0x03, 0x00, 0xA8, 0x02,
+ 0x0B, 0x03, 0x00, 0x72, 0x00, 0x0B, 0x01, 0x00, 0x73, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x49, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xF3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0xB4, 0x6C, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x41, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB4, 0x70, 0x10, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xB4, 0x74, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x19, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xB4, 0x7C, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x61, 0xFA, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0xB4, 0x7E, 0x10, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF1, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x1D, 0x2F, 0x01, 0x00, 0xC7, 0x2E, 0x01, 0x00, 0xB3, 0x41, 0x01, 0x00,
+ 0x81, 0x26, 0x01, 0x00, 0x01, 0x31, 0x01, 0x00, 0x5D, 0x3C, 0x01, 0x00, 0x81, 0x27, 0x01, 0x00,
+ 0xBB, 0x2F, 0x01, 0x00, 0xC9, 0x41, 0x01, 0x00, 0x00, 0x04, 0x40, 0x00, 0x10, 0x21, 0x00, 0x00,
+ 0x00, 0x1F, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x04, 0x06, 0x00,
+ 0x08, 0x02, 0x50, 0x00, 0x60, 0x02, 0x0C, 0x0C, 0x00, 0x00, 0x60, 0x02, 0x0C, 0x30, 0x0C, 0x1A,
+ 0x31, 0x10, 0x0F, 0x0F, 0x00, 0x00, 0x2F, 0x00, 0x01, 0x00, 0xAA, 0x2C, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00,
+ 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x07, 0x01, 0x26, 0x26, 0x12, 0x12, 0x11, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x00, 0x3C, 0x20, 0x3D, 0xD0, 0x41, 0xEC, 0x41, 0x08, 0x42, 0x1C, 0x42, 0x30, 0x42,
+ 0x44, 0x42, 0x60, 0x42, 0x74, 0x42, 0x88, 0x42, 0xA4, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x01, 0x02,
+ 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x1B, 0x00, 0x00, 0x80, 0x2D, 0x00, 0x00, 0x80, 0x36, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x80,
+ 0x5A, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x80,
+ 0x82, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0xAF, 0x00, 0x00, 0x80, 0xD8, 0x00, 0x00, 0x00,
+ 0xC3, 0x00, 0x00, 0x80, 0xF5, 0x00, 0x00, 0x80, 0xEE, 0x00, 0x00, 0x00, 0x29, 0x01, 0x00, 0x80,
+ 0x32, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x80, 0x68, 0x01, 0x00, 0x00,
+ 0x73, 0x01, 0x00, 0x80, 0x45, 0x01, 0x00, 0x80, 0x5E, 0x01, 0x00, 0x00, 0xB0, 0x01, 0x00, 0x00,
+ 0xAB, 0x01, 0x00, 0x80, 0x9D, 0x01, 0x00, 0x80, 0x86, 0x01, 0x00, 0x00, 0xF1, 0x01, 0x00, 0x80,
+ 0xEA, 0x01, 0x00, 0x00, 0xDC, 0x01, 0x00, 0x00, 0xC7, 0x01, 0x00, 0x80, 0x49, 0x02, 0x00, 0x80,
+ 0x52, 0x02, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x7F, 0x02, 0x00, 0x80, 0x08, 0x02, 0x00, 0x00,
+ 0x13, 0x02, 0x00, 0x80, 0x25, 0x02, 0x00, 0x80, 0x3E, 0x02, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00,
+ 0xCB, 0x02, 0x00, 0x80, 0xFD, 0x02, 0x00, 0x80, 0xE6, 0x02, 0x00, 0x00, 0x91, 0x02, 0x00, 0x80,
+ 0x8A, 0x02, 0x00, 0x00, 0xBC, 0x02, 0x00, 0x00, 0xA7, 0x02, 0x00, 0x80, 0x60, 0x03, 0x00, 0x00,
+ 0x7B, 0x03, 0x00, 0x80, 0x4D, 0x03, 0x00, 0x80, 0x56, 0x03, 0x00, 0x00, 0x21, 0x03, 0x00, 0x80,
+ 0x3A, 0x03, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x17, 0x03, 0x00, 0x80, 0xF9, 0x03, 0x00, 0x80,
+ 0xE2, 0x03, 0x00, 0x00, 0xD4, 0x03, 0x00, 0x00, 0xCF, 0x03, 0x00, 0x80, 0xB8, 0x03, 0x00, 0x00,
+ 0xA3, 0x03, 0x00, 0x80, 0x95, 0x03, 0x00, 0x80, 0x8E, 0x03, 0x00, 0x00, 0x89, 0x04, 0x00, 0x80,
+ 0x92, 0x04, 0x00, 0x00, 0xA4, 0x04, 0x00, 0x00, 0xBF, 0x04, 0x00, 0x80, 0xC8, 0x04, 0x00, 0x00,
+ 0xD3, 0x04, 0x00, 0x80, 0xE5, 0x04, 0x00, 0x80, 0xFE, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00,
+ 0x0B, 0x04, 0x00, 0x80, 0x3D, 0x04, 0x00, 0x80, 0x26, 0x04, 0x00, 0x00, 0x51, 0x04, 0x00, 0x80,
+ 0x4A, 0x04, 0x00, 0x00, 0x7C, 0x04, 0x00, 0x00, 0x67, 0x04, 0x00, 0x80, 0xA0, 0x05, 0x00, 0x00,
+ 0xBB, 0x05, 0x00, 0x80, 0x8D, 0x05, 0x00, 0x80, 0x96, 0x05, 0x00, 0x00, 0xE1, 0x05, 0x00, 0x80,
+ 0xFA, 0x05, 0x00, 0x00, 0xCC, 0x05, 0x00, 0x00, 0xD7, 0x05, 0x00, 0x80, 0x39, 0x05, 0x00, 0x80,
+ 0x22, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x00, 0x0F, 0x05, 0x00, 0x80, 0x78, 0x05, 0x00, 0x00,
+ 0x63, 0x05, 0x00, 0x80, 0x55, 0x05, 0x00, 0x80, 0x4E, 0x05, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x00,
+ 0xDB, 0x06, 0x00, 0x80, 0xED, 0x06, 0x00, 0x80, 0xF6, 0x06, 0x00, 0x00, 0x81, 0x06, 0x00, 0x80,
+ 0x9A, 0x06, 0x00, 0x00, 0xAC, 0x06, 0x00, 0x00, 0xB7, 0x06, 0x00, 0x80, 0x59, 0x06, 0x00, 0x80,
+ 0x42, 0x06, 0x00, 0x00, 0x74, 0x06, 0x00, 0x00, 0x6F, 0x06, 0x00, 0x80, 0x18, 0x06, 0x00, 0x00,
+ 0x03, 0x06, 0x00, 0x80, 0x35, 0x06, 0x00, 0x80, 0x2E, 0x06, 0x00, 0x00, 0xE9, 0x07, 0x00, 0x80,
+ 0xF2, 0x07, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0xDF, 0x07, 0x00, 0x80, 0xA8, 0x07, 0x00, 0x00,
+ 0xB3, 0x07, 0x00, 0x80, 0x85, 0x07, 0x00, 0x80, 0x9E, 0x07, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00,
+ 0x6B, 0x07, 0x00, 0x80, 0x5D, 0x07, 0x00, 0x80, 0x46, 0x07, 0x00, 0x00, 0x31, 0x07, 0x00, 0x80,
+ 0x2A, 0x07, 0x00, 0x00, 0x1C, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x80, 0x09, 0x09, 0x00, 0x80,
+ 0x12, 0x09, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00, 0x3F, 0x09, 0x00, 0x80, 0x48, 0x09, 0x00, 0x00,
+ 0x53, 0x09, 0x00, 0x80, 0x65, 0x09, 0x00, 0x80, 0x7E, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00,
+ 0x8B, 0x09, 0x00, 0x80, 0xBD, 0x09, 0x00, 0x80, 0xA6, 0x09, 0x00, 0x00, 0xD1, 0x09, 0x00, 0x80,
+ 0xCA, 0x09, 0x00, 0x00, 0xFC, 0x09, 0x00, 0x00, 0xE7, 0x09, 0x00, 0x80, 0x20, 0x08, 0x00, 0x00,
+ 0x3B, 0x08, 0x00, 0x80, 0x0D, 0x08, 0x00, 0x80, 0x16, 0x08, 0x00, 0x00, 0x61, 0x08, 0x00, 0x80,
+ 0x7A, 0x08, 0x00, 0x00, 0x4C, 0x08, 0x00, 0x00, 0x57, 0x08, 0x00, 0x80, 0xB9, 0x08, 0x00, 0x80,
+ 0xA2, 0x08, 0x00, 0x00, 0x94, 0x08, 0x00, 0x00, 0x8F, 0x08, 0x00, 0x80, 0xF8, 0x08, 0x00, 0x00,
+ 0xE3, 0x08, 0x00, 0x80, 0xD5, 0x08, 0x00, 0x80, 0xCE, 0x08, 0x00, 0x00, 0x40, 0x0B, 0x00, 0x00,
+ 0x5B, 0x0B, 0x00, 0x80, 0x6D, 0x0B, 0x00, 0x80, 0x76, 0x0B, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x80,
+ 0x1A, 0x0B, 0x00, 0x00, 0x2C, 0x0B, 0x00, 0x00, 0x37, 0x0B, 0x00, 0x80, 0xD9, 0x0B, 0x00, 0x80,
+ 0xC2, 0x0B, 0x00, 0x00, 0xF4, 0x0B, 0x00, 0x00, 0xEF, 0x0B, 0x00, 0x80, 0x98, 0x0B, 0x00, 0x00,
+ 0x83, 0x0B, 0x00, 0x80, 0xB5, 0x0B, 0x00, 0x80, 0xAE, 0x0B, 0x00, 0x00, 0x69, 0x0A, 0x00, 0x80,
+ 0x72, 0x0A, 0x00, 0x00, 0x44, 0x0A, 0x00, 0x00, 0x5F, 0x0A, 0x00, 0x80, 0x28, 0x0A, 0x00, 0x00,
+ 0x33, 0x0A, 0x00, 0x80, 0x05, 0x0A, 0x00, 0x80, 0x1E, 0x0A, 0x00, 0x00, 0xF0, 0x0A, 0x00, 0x00,
+ 0xEB, 0x0A, 0x00, 0x80, 0xDD, 0x0A, 0x00, 0x80, 0xC6, 0x0A, 0x00, 0x00, 0xB1, 0x0A, 0x00, 0x80,
+ 0xAA, 0x0A, 0x00, 0x00, 0x9C, 0x0A, 0x00, 0x00, 0x87, 0x0A, 0x00, 0x80, 0x80, 0x0D, 0x00, 0x00,
+ 0x9B, 0x0D, 0x00, 0x80, 0xAD, 0x0D, 0x00, 0x80, 0xB6, 0x0D, 0x00, 0x00, 0xC1, 0x0D, 0x00, 0x80,
+ 0xDA, 0x0D, 0x00, 0x00, 0xEC, 0x0D, 0x00, 0x00, 0xF7, 0x0D, 0x00, 0x80, 0x19, 0x0D, 0x00, 0x80,
+ 0x02, 0x0D, 0x00, 0x00, 0x34, 0x0D, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x80, 0x58, 0x0D, 0x00, 0x00,
+ 0x43, 0x0D, 0x00, 0x80, 0x75, 0x0D, 0x00, 0x80, 0x6E, 0x0D, 0x00, 0x00, 0xA9, 0x0C, 0x00, 0x80,
+ 0xB2, 0x0C, 0x00, 0x00, 0x84, 0x0C, 0x00, 0x00, 0x9F, 0x0C, 0x00, 0x80, 0xE8, 0x0C, 0x00, 0x00,
+ 0xF3, 0x0C, 0x00, 0x80, 0xC5, 0x0C, 0x00, 0x80, 0xDE, 0x0C, 0x00, 0x00, 0x30, 0x0C, 0x00, 0x00,
+ 0x2B, 0x0C, 0x00, 0x80, 0x1D, 0x0C, 0x00, 0x80, 0x06, 0x0C, 0x00, 0x00, 0x71, 0x0C, 0x00, 0x80,
+ 0x6A, 0x0C, 0x00, 0x00, 0x5C, 0x0C, 0x00, 0x00, 0x47, 0x0C, 0x00, 0x80, 0xC9, 0x0F, 0x00, 0x80,
+ 0xD2, 0x0F, 0x00, 0x00, 0xE4, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x80, 0x88, 0x0F, 0x00, 0x00,
+ 0x93, 0x0F, 0x00, 0x80, 0xA5, 0x0F, 0x00, 0x80, 0xBE, 0x0F, 0x00, 0x00, 0x50, 0x0F, 0x00, 0x00,
+ 0x4B, 0x0F, 0x00, 0x80, 0x7D, 0x0F, 0x00, 0x80, 0x66, 0x0F, 0x00, 0x00, 0x11, 0x0F, 0x00, 0x80,
+ 0x0A, 0x0F, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, 0x27, 0x0F, 0x00, 0x80, 0xE0, 0x0E, 0x00, 0x00,
+ 0xFB, 0x0E, 0x00, 0x80, 0xCD, 0x0E, 0x00, 0x80, 0xD6, 0x0E, 0x00, 0x00, 0xA1, 0x0E, 0x00, 0x80,
+ 0xBA, 0x0E, 0x00, 0x00, 0x8C, 0x0E, 0x00, 0x00, 0x97, 0x0E, 0x00, 0x80, 0x79, 0x0E, 0x00, 0x80,
+ 0x62, 0x0E, 0x00, 0x00, 0x54, 0x0E, 0x00, 0x00, 0x4F, 0x0E, 0x00, 0x80, 0x38, 0x0E, 0x00, 0x00,
+ 0x23, 0x0E, 0x00, 0x80, 0x15, 0x0E, 0x00, 0x80, 0x0E, 0x0E, 0x00, 0x00, 0x4C, 0x74, 0x01, 0x00,
+ 0x00, 0x04, 0x10, 0x00, 0x38, 0x04, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x84, 0x74, 0x01, 0x00,
+ 0x00, 0xFC, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x84, 0x74, 0x01, 0x00,
+ 0x38, 0x08, 0x10, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0x01, 0xFF, 0x01, 0x75,
+ 0x14, 0x90, 0x5F, 0x01, 0x32, 0x01, 0x32, 0x02, 0x29, 0x08, 0x41, 0xA9, 0x08, 0x09, 0x1A, 0x0C,
+ 0xB2, 0x64, 0x29, 0x0C, 0x69, 0x48, 0x29, 0x04, 0x0A, 0x11, 0x04, 0x10, 0x01, 0xFF, 0x01, 0x42,
+ 0x07, 0x8D, 0xF0, 0x01, 0x20, 0x04, 0x49, 0x10, 0xAA, 0xFF, 0x0C, 0x59, 0x01, 0x01, 0x1D, 0x04,
+ 0x50, 0x90, 0xD0, 0x03, 0x30, 0xB5, 0x72, 0xB6, 0x01, 0x23, 0x0C, 0x4D, 0x2B, 0x60, 0x0C, 0x4A,
+ 0x00, 0x24, 0x81, 0xB1, 0x13, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x00, 0xF0, 0x1F, 0x00, 0x81, 0xF8,
+ 0x6A, 0x00, 0x07, 0x48, 0x1C, 0x38, 0x03, 0x60, 0x01, 0x68, 0x00, 0x29, 0xFC, 0xD1, 0x14, 0x60,
+ 0x2C, 0x60, 0x62, 0xB6, 0x30, 0xBD, 0x14, 0x60, 0xED, 0xE7, 0x00, 0x00, 0xC0, 0x1B, 0x00, 0x22,
+ 0x78, 0x0D, 0x00, 0x22, 0xF6, 0x63, 0xE8, 0xA2, 0x97, 0x02, 0x00, 0x00, 0x09, 0x9C, 0x17, 0x5D,
+ 0x68, 0xFD, 0xFF, 0xFF, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1E, 0x0F, 0x6F, 0x08, 0x37, 0x04, 0x0F, 0x6F, 0x08, 0x37, 0x04, 0xB8,
+ 0x01, 0x01, 0x00, 0x01, 0x01, 0x20, 0x20, 0x50, 0xAA, 0x99, 0x00, 0x05, 0x00, 0x05, 0xC8, 0x00,
+ 0xC8, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x70, 0x00, 0x70, 0x00, 0x08, 0xB0,
+ 0x00, 0xB0, 0x00, 0x00, 0x03, 0xAA, 0x38, 0xC8, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x08, 0x0F, 0x0F, 0x1F, 0x0F, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0B, 0x01, 0xA0, 0x00, 0x64, 0x00, 0x64, 0x00, 0xD0, 0x0F, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x16, 0x08, 0x00, 0x02, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xA0,
+ 0x50, 0x4C, 0x26, 0x01, 0x08, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x06, 0x52, 0x4F,
+ 0x04, 0xD8, 0x00, 0x50, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x08, 0xB0, 0x06, 0x03, 0x03, 0x00, 0x00,
+ 0xBB, 0xBB, 0xC8, 0x00, 0xC8, 0x00, 0x88, 0x88, 0x00, 0x00, 0xE9, 0xA6, 0x1A, 0x1F, 0x04, 0xD8,
+ 0x18, 0x32, 0x00, 0x20, 0x00, 0x24, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x24, 0x60, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x16, 0x50, 0x4F, 0x04, 0x18, 0x00, 0x30, 0x00, 0x06,
+ 0x00, 0x2F, 0x00, 0x40, 0x10, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x66, 0x9E, 0x1F, 0x98, 0x18, 0x01, 0x01, 0x30, 0x00,
+ 0x30, 0x00, 0x40, 0x00, 0x10, 0x00, 0x21, 0x03, 0x00, 0x00, 0x1F, 0x21, 0x01, 0x00, 0x00, 0x1F,
+ 0x00, 0x01, 0x28, 0x00, 0x99, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x64, 0x00, 0x64, 0x00, 0xD0, 0x00, 0x80, 0x0C, 0xF0, 0x0A,
+ 0xD0, 0x00, 0x00, 0x15, 0x00, 0x12, 0x50, 0x01, 0x50, 0x01, 0x00, 0x15, 0x00, 0x12, 0x50, 0x01,
+ 0x80, 0x0C, 0xF0, 0x0A, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x33, 0x0E, 0x02, 0x0B, 0x14, 0x0F, 0x02, 0x64, 0x90, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0x14, 0x14, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x80, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0x02, 0x40, 0x90, 0x01,
+ 0x90, 0x01, 0x80, 0x00, 0x80, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x64, 0x00, 0x80, 0x01, 0x64, 0x00, 0x80, 0x01, 0x96, 0x00,
+ 0x64, 0x00, 0x20, 0x00, 0x02, 0x00, 0x96, 0x00, 0x64, 0x00, 0x64, 0x00, 0xC8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x64, 0x00, 0x05, 0x01, 0xF4, 0x01, 0x2C, 0x01, 0x02, 0xFF, 0x7F, 0xFF, 0x7F, 0x02,
+ 0x32, 0x64, 0x00, 0x00, 0x02, 0x02, 0xA2, 0x20, 0x00, 0x29, 0x64, 0x00, 0x64, 0x00, 0xC8, 0x00,
+ 0x58, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x64, 0x00, 0x32, 0x00, 0x20, 0x00, 0x14, 0x0A, 0x84, 0x03,
+ 0x64, 0x00, 0x00, 0x04, 0x02, 0x00, 0x20, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x0E,
+ 0x10, 0x00, 0x40, 0x00, 0x18, 0x00, 0x00, 0x01, 0x62, 0x84, 0x40, 0x01, 0x20, 0x00, 0x10, 0x00,
+ 0x64, 0x00, 0x64, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0x02, 0x00, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x0C, 0x04, 0x20, 0x00, 0x10, 0x10, 0x20, 0x00, 0x20, 0x00, 0x96, 0x00,
+ 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x00, 0x40, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x28, 0x02, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x14, 0x00, 0x01, 0x03, 0x01, 0x0A, 0x00, 0x10,
+ 0x11, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50, 0x00, 0x70, 0x00, 0x32, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7D, 0x03, 0x64, 0x00, 0x00, 0x02, 0x10, 0x01, 0x00, 0x02, 0x64, 0x00,
+ 0x06, 0x64, 0x00, 0x64, 0x00, 0x0E, 0x00, 0x05, 0x00, 0x10, 0x50, 0x00, 0x32, 0x00, 0x10, 0x21,
+ 0x0F, 0x02, 0x10, 0x1F, 0x00, 0x0A, 0x00, 0x14, 0x81, 0x11, 0x1A, 0x00, 0x16, 0x00, 0x00, 0x10,
+ 0x0A, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x0A, 0xE8, 0x10, 0x00, 0x40, 0x00, 0x40, 0x94, 0x94,
+ 0x28, 0x88, 0x62, 0x10, 0x00, 0x64, 0x00, 0x10, 0x00, 0x30, 0x00, 0x0A, 0x00, 0x18, 0x00, 0x05,
+ 0x20, 0x05, 0x20, 0x18, 0x20, 0xD8, 0x05, 0x32, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0xC8, 0x00, 0xC8, 0x00, 0x0A, 0x0A, 0x64, 0x00, 0x64, 0x00,
+ 0x01, 0x03, 0x64, 0x00, 0x64, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x96, 0x00, 0x0A, 0x06, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x32, 0x1A,
+ 0xFA, 0x00, 0x20, 0x05, 0x20, 0x0A, 0x05, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
+ 0x00, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2E, 0x03, 0x50, 0x00, 0x50, 0x00, 0x2C, 0x01, 0x32, 0xFF, 0x7F, 0x0B,
+ 0x01, 0x32, 0x00, 0x20, 0x03, 0x00, 0x0A, 0x20, 0x14, 0x05, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x01, 0x02, 0x03, 0x50, 0x01,
+ 0x50, 0x01, 0x50, 0x01, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x96, 0x7D, 0x6E, 0x67, 0x65, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+ 0x64, 0x65, 0x67, 0x6E, 0x7D, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x13, 0x22, 0x22,
+ 0x22, 0x00, 0x00, 0x0F, 0x00, 0x28, 0x00, 0x3C, 0x00, 0x50, 0x00, 0xA0, 0x00, 0x40, 0x01, 0xE0,
+ 0x01, 0xD0, 0x02, 0xBF, 0x03, 0x5F, 0x04, 0xFF, 0x04, 0x4F, 0x05, 0x63, 0x05, 0x77, 0x05, 0x90,
+ 0x05, 0x0F, 0x00, 0x28, 0x00, 0x3C, 0x00, 0x50, 0x00, 0xA0, 0x00, 0x40, 0x01, 0xE0, 0x01, 0xD0,
+ 0x02, 0xC0, 0x03, 0x00, 0x05, 0x3F, 0x06, 0x2F, 0x07, 0x1F, 0x08, 0xBF, 0x08, 0x5F, 0x09, 0xAF,
+ 0x09, 0xC3, 0x09, 0xD7, 0x09, 0xF5, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x19, 0x00, 0x28, 0x00, 0x6C,
+ 0x00, 0x27, 0x01, 0xD1, 0x01, 0xD0, 0x02, 0xC6, 0x03, 0x72, 0x04, 0x21, 0x05, 0x69, 0x05, 0x86,
+ 0x05, 0x95, 0x05, 0x9F, 0x05, 0x00, 0x00, 0x0F, 0x00, 0x1C, 0x00, 0x28, 0x00, 0x78, 0x00, 0x1C,
+ 0x01, 0xC6, 0x01, 0xBE, 0x02, 0xAE, 0x03, 0x00, 0x05, 0x4F, 0x06, 0x44, 0x07, 0x39, 0x08, 0xDE,
+ 0x08, 0x8A, 0x09, 0xD8, 0x09, 0xE3, 0x09, 0xF1, 0x09, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x64, 0x80, 0x10, 0xE5, 0x00, 0x00,
+ 0x64, 0x80, 0xA4, 0x00, 0xA7, 0x00, 0xB2, 0x00, 0xC3, 0x00, 0xDB, 0x00, 0xFA, 0x00, 0x1F, 0x01,
+ 0x4A, 0x01, 0x7A, 0x01, 0xB0, 0x01, 0xEC, 0x01, 0x2B, 0x02, 0x6F, 0x02, 0xB6, 0x02, 0x01, 0x03,
+ 0x4D, 0x03, 0x9C, 0x03, 0xEC, 0x03, 0x3D, 0x04, 0x8E, 0x04, 0xDF, 0x04, 0x2E, 0x05, 0x7C, 0x05,
+ 0xC8, 0x05, 0x11, 0x06, 0x56, 0x06, 0x98, 0x06, 0xD5, 0x06, 0x0E, 0x07, 0x42, 0x07, 0x6F, 0x07,
+ 0x97, 0x07, 0xB9, 0x07, 0xD5, 0x07, 0xE9, 0x07, 0xF7, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xF7, 0x07,
+ 0xE9, 0x07, 0xD5, 0x07, 0xB9, 0x07, 0x97, 0x07, 0x6F, 0x07, 0x42, 0x07, 0x0E, 0x07, 0xD5, 0x06,
+ 0x98, 0x06, 0x56, 0x06, 0x11, 0x06, 0xC8, 0x05, 0x7C, 0x05, 0x2E, 0x05, 0xDF, 0x04, 0x8E, 0x04,
+ 0x3D, 0x04, 0xEC, 0x03, 0x9C, 0x03, 0x4D, 0x03, 0x01, 0x03, 0xB6, 0x02, 0x6F, 0x02, 0x2B, 0x02,
+ 0xEC, 0x01, 0xB0, 0x01, 0x7A, 0x01, 0x4A, 0x01, 0x1F, 0x01, 0xFA, 0x00, 0xDB, 0x00, 0xC3, 0x00,
+ 0xB2, 0x00, 0xA7, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6A, 0x00, 0x6C, 0x00, 0x72, 0x00, 0x7C, 0x00, 0x89, 0x00, 0x9A, 0x00, 0xAF, 0x00,
+ 0xC7, 0x00, 0xE2, 0x00, 0x01, 0x01, 0x22, 0x01, 0x46, 0x01, 0x6D, 0x01, 0x95, 0x01, 0xC0, 0x01,
+ 0xED, 0x01, 0x1B, 0x02, 0x4A, 0x02, 0x7A, 0x02, 0xAA, 0x02, 0xDB, 0x02, 0x0B, 0x03, 0x3B, 0x03,
+ 0x6B, 0x03, 0x99, 0x03, 0xC7, 0x03, 0xF2, 0x03, 0x1C, 0x04, 0x44, 0x04, 0x69, 0x04, 0x8C, 0x04,
+ 0xAC, 0x04, 0xC9, 0x04, 0xE3, 0x04, 0xF9, 0x04, 0x0C, 0x05, 0x1B, 0x05, 0x26, 0x05, 0x2E, 0x05,
+ 0x32, 0x05, 0x32, 0x05, 0x2E, 0x05, 0x26, 0x05, 0x1B, 0x05, 0x0C, 0x05, 0xF9, 0x04, 0xE3, 0x04,
+ 0xC9, 0x04, 0xAC, 0x04, 0x8C, 0x04, 0x69, 0x04, 0x44, 0x04, 0x1C, 0x04, 0xF2, 0x03, 0xC7, 0x03,
+ 0x99, 0x03, 0x6B, 0x03, 0x3B, 0x03, 0x0B, 0x03, 0xDB, 0x02, 0xAA, 0x02, 0x7A, 0x02, 0x4A, 0x02,
+ 0x1B, 0x02, 0xED, 0x01, 0xC0, 0x01, 0x95, 0x01, 0x6D, 0x01, 0x46, 0x01, 0x22, 0x01, 0x01, 0x01,
+ 0xE2, 0x00, 0xC7, 0x00, 0xAF, 0x00, 0x9A, 0x00, 0x89, 0x00, 0x7C, 0x00, 0x72, 0x00, 0x6C, 0x00,
+ 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06,
+ 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06,
+ 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xCD, 0x00, 0xCD, 0x00, 0xCD, 0x00, 0xCD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x08, 0x0C, 0x0D, 0x0F, 0x0F, 0x0F, 0x0E, 0x0E,
+ 0x0E, 0x0D, 0x0D, 0x0D, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x64, 0x9A, 0x1F, 0x18, 0x18, 0x01, 0x01, 0x30, 0x00,
+ 0x30, 0x00, 0x40, 0x00, 0x10, 0x00, 0x21, 0x07, 0x00, 0x00, 0x1F, 0x20, 0x03, 0x00, 0x00, 0x1F,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x99, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x50, 0x10, 0x10, 0xB0, 0x20, 0xFF, 0xD0, 0x00, 0x06, 0x14,
+ 0x14, 0x2A, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x6E, 0x6E,
+ 0x47, 0x1A, 0x38, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x1E, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x24, 0x94, 0x1F, 0x18, 0x18, 0x01, 0x00, 0x25, 0x00,
+ 0x25, 0x00, 0x50, 0x00, 0x24, 0x00, 0x70, 0x01, 0x00, 0x00, 0x1F, 0x80, 0x01, 0x00, 0x00, 0x1F,
+ 0x00, 0x01, 0x10, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x4E, 0xD3, 0x25, 0xD2,
+};
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.c b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.c
new file mode 100644
index 00000000000..53ce7d0087e
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.c
@@ -0,0 +1,953 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS functions for getting Initialization Data *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+/*!
+ * \file ftsCompensation.c
+ * \brief Contains all the function to work with Initialization Data
+ */
+
+#include "ftsCompensation.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsFrame.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+
+/**
+ * Request to the FW to load the specified Initialization Data
+ * @param type type of Initialization data to load @link load_opt Load Host
+ * Data Option @endlink
+ * @return OK if success or an error code which specify the type of error
+ */
+int requestCompensationData(u8 type)
+{
+ int ret = ERROR_OP_NOT_ALLOW;
+ int retry = 0;
+
+ pr_info("%s: Requesting compensation data...\n", __func__);
+ while (retry < RETRY_COMP_DATA_READ) {
+ ret = writeSysCmd(SYS_CMD_LOAD_DATA, &type, 1);
+ /* send request to load in memory the Compensation Data */
+ if (ret < OK) {
+ pr_err("%s: failed at %d attemp!\n",
+ __func__, retry + 1);
+ retry += 1;
+ } else {
+ pr_info("%s: Request Compensation data FINISHED!\n",
+ __func__);
+ return OK;
+ }
+ }
+
+ pr_err("%s: Requesting compensation data... ERROR %08X\n",
+ __func__, ret | ERROR_REQU_COMP_DATA);
+ return ret | ERROR_REQU_COMP_DATA;
+}
+
+
+/**
+ * Read Initialization Data Header and check that the type loaded match
+ * with the one previously requested
+ * @param type type of Initialization data requested @link load_opt Load Host
+ * Data Option @endlink
+ * @param header pointer to DataHeader variable which will contain the header
+ * @param address pointer to a variable which will contain the updated address
+ * to the next data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readCompensationDataHeader(u8 type, DataHeader *header, u64 *address)
+{
+ u64 offset = ADDR_FRAMEBUFFER;
+ u8 data[COMP_DATA_HEADER];
+ int ret;
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data,
+ COMP_DATA_HEADER, DUMMY_FRAMEBUFFER);
+ if (ret < OK) { /* i2c function have already a retry mechanism */
+ pr_err("%s: error while reading data header ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_info("Read Data Header done!\n");
+
+ if (data[0] != HEADER_SIGNATURE) {
+ pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n",
+ __func__, data[0], HEADER_SIGNATURE,
+ ERROR_WRONG_DATA_SIGN);
+ return ERROR_WRONG_DATA_SIGN;
+ }
+
+
+ if (data[1] != type) {
+ pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n",
+ __func__, data[1], type, ERROR_DIFF_DATA_TYPE);
+ return ERROR_DIFF_DATA_TYPE;
+ }
+
+ pr_info("Type = %02X of Compensation data OK!\n", type);
+
+ header->type = type;
+
+ *address = offset + COMP_DATA_HEADER;
+
+ return OK;
+}
+
+
+/**
+ * Read MS Global Initialization data from the buffer such as Cx1
+ * @param address pointer to a variable which contain the address from where
+ * to read the data and will contain the updated address to the next data
+ * @param global pointer to MutualSenseData variable which will contain the MS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readMutualSenseGlobalData(u64 *address, MutualSenseData *global)
+{
+ u8 data[COMP_DATA_GLOBAL];
+ int ret;
+
+ pr_info("Address for Global data= %llx\n", *address);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data,
+ COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading info data ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+ pr_info("Global data Read !\n");
+
+ global->header.force_node = data[0];
+ global->header.sense_node = data[1];
+ global->cx1 = data[2];
+ /* all other bytes are reserved atm */
+
+ pr_info("force_len = %d sense_len = %d CX1 = %d\n",
+ global->header.force_node, global->header.sense_node,
+ global->cx1);
+
+ *address += COMP_DATA_GLOBAL;
+ return OK;
+}
+
+
+/**
+ * Read MS Initialization data for each node from the buffer
+ * @param address a variable which contain the address from where to read the
+ * data
+ * @param node pointer to MutualSenseData variable which will contain the MS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readMutualSenseNodeData(u64 address, MutualSenseData *node)
+{
+ int ret;
+ int size = node->header.force_node * node->header.sense_node;
+
+ pr_info("Address for Node data = %llx\n", address);
+
+ node->node_data = (i8 *)kmalloc(size * (sizeof(i8)), GFP_KERNEL);
+
+ if (node->node_data == NULL) {
+ pr_err("%s: can not allocate node_data... ERROR %08X",
+ __func__, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ pr_info("Node Data to read %d bytes\n", size);
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address,
+ node->node_data, size, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading node data ERROR %08X\n",
+ __func__, ret);
+ kfree(node->node_data);
+ return ret;
+ }
+ node->node_data_size = size;
+
+ pr_info("Read node data OK!\n");
+
+ return size;
+}
+
+/**
+ * Perform all the steps to read the necessary info for MS Initialization data
+ * from the buffer and store it in a MutualSenseData variable
+ * @param type type of MS Initialization data to read @link load_opt Load Host
+ * Data Option @endlink
+ * @param data pointer to MutualSenseData variable which will contain the MS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readMutualSenseCompensationData(u8 type, MutualSenseData *data)
+{
+ int ret;
+ u64 address;
+
+ data->node_data = NULL;
+
+ if (!(type == LOAD_CX_MS_TOUCH || type == LOAD_CX_MS_LOW_POWER ||
+ type == LOAD_CX_MS_KEY || type == LOAD_CX_MS_FORCE)) {
+ pr_err("%s: Choose a MS type of compensation data ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_REQU_COMP_DATA);
+ return ret | ERROR_REQU_COMP_DATA;
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_HEADER);
+ return ret | ERROR_COMP_DATA_HEADER;
+ }
+
+ ret = readMutualSenseGlobalData(&address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL);
+ return ret | ERROR_COMP_DATA_GLOBAL;
+ }
+
+ ret = readMutualSenseNodeData(address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE);
+ return ret | ERROR_COMP_DATA_NODE;
+ }
+
+ return OK;
+}
+
+/**
+ * Read SS Global Initialization data from the buffer such as Ix1/Cx1 for force
+ * and sense
+ * @param address pointer to a variable which contain the address from where
+ * to read the data and will contain the updated address to the next data
+ * @param global pointer to MutualSenseData variable which will contain the SS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSelfSenseGlobalData(u64 *address, SelfSenseData *global)
+{
+ int ret;
+ u8 data[COMP_DATA_GLOBAL];
+
+ pr_info("Address for Global data= %llx\n", *address);
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data,
+ COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading the data... ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_info("Global data Read !\n");
+
+
+ global->header.force_node = data[0];
+ global->header.sense_node = data[1];
+ global->f_ix1 = data[2];
+ global->s_ix1 = data[3];
+ global->f_cx1 = (i8)data[4];
+ global->s_cx1 = (i8)data[5];
+ global->f_max_n = data[6];
+ global->s_max_n = data[7];
+
+ pr_info("force_len = %d sense_len = %d f_ix1 = %d s_ix1 = %d f_cx1 = %d s_cx1 = %d\n",
+ global->header.force_node, global->header.sense_node,
+ global->f_ix1, global->s_ix1, global->f_cx1, global->s_cx1);
+ pr_info("max_n = %d s_max_n = %d\n", global->f_max_n,
+ global->s_max_n);
+
+
+ *address += COMP_DATA_GLOBAL;
+
+ return OK;
+}
+
+/**
+ * Read SS Initialization data for each node of force and sense channels from
+ * the buffer
+ * @param address a variable which contain the address from where to read the
+ * data
+ * @param node pointer to SelfSenseData variable which will contain the SS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSelfSenseNodeData(u64 address, SelfSenseData *node)
+{
+ int size = node->header.force_node * 2 + node->header.sense_node * 2;
+ u8 data[size];
+ int ret;
+
+ node->ix2_fm = (u8 *)kmalloc(node->header.force_node * (sizeof(u8)),
+ GFP_KERNEL);
+ if (node->ix2_fm == NULL) {
+ pr_err("%s: can not allocate memory for ix2_fm... ERROR %08X",
+ __func__, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ node->cx2_fm = (i8 *)kmalloc(node->header.force_node * (sizeof(i8)),
+ GFP_KERNEL);
+ if (node->cx2_fm == NULL) {
+ pr_err("%s: can not allocate memory for cx2_fm ... ERROR %08X",
+ __func__, ERROR_ALLOC);
+ kfree(node->ix2_fm);
+ return ERROR_ALLOC;
+ }
+ node->ix2_sn = (u8 *)kmalloc(node->header.sense_node * (sizeof(u8)),
+ GFP_KERNEL);
+ if (node->ix2_sn == NULL) {
+ pr_err("%s: can not allocate memory for ix2_sn ERROR %08X",
+ __func__, ERROR_ALLOC);
+ kfree(node->ix2_fm);
+ kfree(node->cx2_fm);
+ return ERROR_ALLOC;
+ }
+ node->cx2_sn = (i8 *)kmalloc(node->header.sense_node * (sizeof(i8)),
+ GFP_KERNEL);
+ if (node->cx2_sn == NULL) {
+ pr_err("%s: can not allocate memory for cx2_sn ERROR %08X",
+ __func__, ERROR_ALLOC);
+ kfree(node->ix2_fm);
+ kfree(node->cx2_fm);
+ kfree(node->ix2_sn);
+ return ERROR_ALLOC;
+ }
+
+
+ pr_info("Address for Node data = %llx\n", address);
+
+ pr_info("Node Data to read %d bytes\n", size);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data,
+ size, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading data... ERROR %08X\n",
+ __func__, ret);
+ kfree(node->ix2_fm);
+ kfree(node->cx2_fm);
+ kfree(node->ix2_sn);
+ kfree(node->cx2_sn);
+ return ret;
+ }
+
+ pr_info("Read node data ok!\n");
+
+ memcpy(node->ix2_fm, data, node->header.force_node);
+ memcpy(node->ix2_sn, &data[node->header.force_node],
+ node->header.sense_node);
+ memcpy(node->cx2_fm, &data[node->header.force_node +
+ node->header.sense_node],
+ node->header.force_node);
+ memcpy(node->cx2_sn, &data[node->header.force_node * 2 +
+ node->header.sense_node],
+ node->header.sense_node);
+
+ return OK;
+}
+
+/**
+ * Perform all the steps to read the necessary info for SS Initialization data
+ * from the buffer and store it in a SelfSenseData variable
+ * @param type type of SS Initialization data to read @link load_opt Load Host
+ * Data Option @endlink
+ * @param data pointer to SelfSenseData variable which will contain the SS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSelfSenseCompensationData(u8 type, SelfSenseData *data)
+{
+ int ret;
+ u64 address;
+
+ data->ix2_fm = NULL;
+ data->cx2_fm = NULL;
+ data->ix2_sn = NULL;
+ data->cx2_sn = NULL;
+
+ if (!(type == LOAD_CX_SS_TOUCH || type == LOAD_CX_SS_TOUCH_IDLE ||
+ type == LOAD_CX_SS_KEY || type == LOAD_CX_SS_FORCE)) {
+ pr_err("%s: Choose a SS type of compensation data ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ pr_err("%s: error while requesting data... ERROR %08X\n",
+ __func__, ERROR_REQU_COMP_DATA);
+ return ret | ERROR_REQU_COMP_DATA;
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ pr_err("%s: error while reading data header... ERROR %08X\n",
+ __func__, ERROR_COMP_DATA_HEADER);
+ return ret | ERROR_COMP_DATA_HEADER;
+ }
+
+ ret = readSelfSenseGlobalData(&address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL);
+ return ret | ERROR_COMP_DATA_GLOBAL;
+ }
+
+ ret = readSelfSenseNodeData(address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE);
+ return ret | ERROR_COMP_DATA_NODE;
+ }
+
+ return OK;
+}
+
+/**
+ * Read TOT MS Global Initialization data from the buffer such as number of
+ * force and sense channels
+ * @param address pointer to a variable which contain the address from where
+ * to read the data and will contain the updated address to the next data
+ * @param global pointer to a variable which will contain the TOT MS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readTotMutualSenseGlobalData(u64 *address, TotMutualSenseData *global)
+{
+ int ret;
+ u8 data[COMP_DATA_GLOBAL];
+
+ pr_info("Address for Global data= %llx\n", *address);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data,
+ COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading info data ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+ pr_info("Global data Read !\n");
+
+ global->header.force_node = data[0];
+ global->header.sense_node = data[1];
+ /* all other bytes are reserved atm */
+
+ pr_info("force_len = %d sense_len = %d\n",
+ global->header.force_node, global->header.sense_node);
+
+ *address += COMP_DATA_GLOBAL;
+ return OK;
+}
+
+
+/**
+ * Read TOT MS Initialization data for each node from the buffer
+ * @param address a variable which contain the address from where to read the
+ * data
+ * @param node pointer to MutualSenseData variable which will contain the TOT
+ * MS initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readTotMutualSenseNodeData(u64 address, TotMutualSenseData *node)
+{
+ int ret, i;
+ int size = node->header.force_node * node->header.sense_node;
+ int toRead = size * sizeof(u16);
+ u8 data[toRead];
+
+ pr_info("Address for Node data = %llx\n", address);
+
+ node->node_data = (short *)kmalloc(size * (sizeof(short)), GFP_KERNEL);
+
+ if (node->node_data == NULL) {
+ pr_err("%s: can not allocate node_data... ERROR %08X",
+ __func__, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ pr_info("Node Data to read %d bytes\n", size);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data,
+ toRead, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading node data ERROR %08X\n",
+ __func__, ret);
+ kfree(node->node_data);
+ return ret;
+ }
+ node->node_data_size = size;
+
+ for (i = 0; i < size; i++)
+ node->node_data[i] = ((short)data[i * 2 + 1]) << 8 |
+ data[i * 2];
+
+ pr_info("Read node data OK!\n");
+
+ return size;
+}
+
+/**
+ * Perform all the steps to read the necessary info for TOT MS Initialization
+ * data from the buffer and store it in a TotMutualSenseData variable
+ * @param type type of TOT MS Initialization data to read @link load_opt Load
+ * Host Data Option @endlink
+ * @param data pointer to a variable which will contain the TOT MS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readTotMutualSenseCompensationData(u8 type, TotMutualSenseData *data)
+{
+ int ret;
+ u64 address;
+
+ data->node_data = NULL;
+
+ if (!(type == LOAD_PANEL_CX_TOT_MS_TOUCH || type ==
+ LOAD_PANEL_CX_TOT_MS_LOW_POWER ||
+ type == LOAD_PANEL_CX_TOT_MS_KEY ||
+ type == LOAD_PANEL_CX_TOT_MS_FORCE)) {
+ pr_err("%s: Choose a TOT MS type of compensation data ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_REQU_COMP_DATA);
+ return ret | ERROR_REQU_COMP_DATA;
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_HEADER);
+ return ret | ERROR_COMP_DATA_HEADER;
+ }
+
+ ret = readTotMutualSenseGlobalData(&address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL);
+ return ret | ERROR_COMP_DATA_GLOBAL;
+ }
+
+ ret = readTotMutualSenseNodeData(address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE);
+ return ret | ERROR_COMP_DATA_NODE;
+ }
+
+ return OK;
+}
+
+/**
+ * Read TOT SS Global Initialization data from the buffer such as number of
+ * force and sense channels
+ * @param address pointer to a variable which contain the address from where
+ * to read the data and will contain the updated address to the next data
+ * @param global pointer to a variable which will contain the TOT SS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readTotSelfSenseGlobalData(u64 *address, TotSelfSenseData *global)
+{
+ int ret;
+ u8 data[COMP_DATA_GLOBAL];
+
+ pr_info("Address for Global data= %llx\n", *address);
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, *address, data,
+ COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading the data... ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_info("Global data Read !\n");
+
+
+ global->header.force_node = data[0];
+ global->header.sense_node = data[1];
+
+
+ pr_info("force_len = %d sense_len = %d\n",
+ global->header.force_node, global->header.sense_node);
+
+
+ *address += COMP_DATA_GLOBAL;
+
+ return OK;
+}
+
+/**
+ * Read TOT SS Global Initialization data from the buffer such as number of
+ * force and sense channels
+ * @param address pointer to a variable which contain the address from where
+ * to read the data and will contain the updated address to the next data
+ * @param node pointer to a variable which will contain the TOT SS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node)
+{
+ int size = node->header.force_node * 2 + node->header.sense_node * 2;
+ int toRead = size * 2; /* *2 2 bytes each node */
+ u8 data[toRead];
+ int ret, i, j = 0;
+
+ node->ix_fm = (u16 *)kmalloc(node->header.force_node * (sizeof(u16)),
+ GFP_KERNEL);
+ if (node->ix_fm == NULL) {
+ pr_err("%s: can not allocate memory for ix2_fm... ERROR %08X",
+ __func__, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ node->cx_fm = (short *)kmalloc(node->header.force_node *
+ (sizeof(short)), GFP_KERNEL);
+ if (node->cx_fm == NULL) {
+ pr_err("%s: can not allocate memory for cx2_fm ... ERROR %08X",
+ __func__, ERROR_ALLOC);
+ kfree(node->ix_fm);
+ return ERROR_ALLOC;
+ }
+ node->ix_sn = (u16 *)kmalloc(node->header.sense_node * (sizeof(u16)),
+ GFP_KERNEL);
+ if (node->ix_sn == NULL) {
+ pr_err("%s: can not allocate memory for ix2_sn ERROR %08X",
+ __func__, ERROR_ALLOC);
+ kfree(node->ix_fm);
+ kfree(node->cx_fm);
+ return ERROR_ALLOC;
+ }
+ node->cx_sn = (short *)kmalloc(node->header.sense_node *
+ (sizeof(short)), GFP_KERNEL);
+ if (node->cx_sn == NULL) {
+ pr_err("%s: can not allocate memory for cx2_sn ERROR %08X",
+ __func__, ERROR_ALLOC);
+ kfree(node->ix_fm);
+ kfree(node->cx_fm);
+ kfree(node->ix_sn);
+ return ERROR_ALLOC;
+ }
+
+
+ pr_info("Address for Node data = %llx\n", address);
+
+ pr_info("Node Data to read %d bytes\n", size);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data,
+ toRead, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading data... ERROR %08X\n",
+ __func__, ret);
+ kfree(node->ix_fm);
+ kfree(node->cx_fm);
+ kfree(node->ix_sn);
+ kfree(node->cx_sn);
+ return ret;
+ }
+
+ pr_info("Read node data ok!\n");
+
+ j = 0;
+ for (i = 0; i < node->header.force_node; i++) {
+ node->ix_fm[i] = ((u16)data[j + 1]) << 8 | data[j];
+ j += 2;
+ }
+
+ for (i = 0; i < node->header.sense_node; i++) {
+ node->ix_sn[i] = ((u16)data[j + 1]) << 8 | data[j];
+ j += 2;
+ }
+
+ for (i = 0; i < node->header.force_node; i++) {
+ node->cx_fm[i] = ((short)data[j + 1]) << 8 | data[j];
+ j += 2;
+ }
+
+ for (i = 0; i < node->header.sense_node; i++) {
+ node->cx_sn[i] = ((short)data[j + 1]) << 8 | data[j];
+ j += 2;
+ }
+
+ if (j != toRead)
+ pr_err("%s: parsed a wrong number of bytes %d!=%d\n",
+ __func__, j, toRead);
+
+ return OK;
+}
+
+/**
+ * Perform all the steps to read the necessary info for TOT SS Initialization
+ * data from the buffer and store it in a TotSelfSenseData variable
+ * @param type type of TOT MS Initialization data to read @link load_opt Load
+ * Host Data Option @endlink
+ * @param data pointer to a variable which will contain the TOT MS
+ * initialization data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readTotSelfSenseCompensationData(u8 type, TotSelfSenseData *data)
+{
+ int ret;
+ u64 address;
+
+ data->ix_fm = NULL;
+ data->cx_fm = NULL;
+ data->ix_sn = NULL;
+ data->cx_sn = NULL;
+
+ if (!(type == LOAD_PANEL_CX_TOT_SS_TOUCH || type ==
+ LOAD_PANEL_CX_TOT_SS_TOUCH_IDLE || type ==
+ LOAD_PANEL_CX_TOT_SS_KEY ||
+ type == LOAD_PANEL_CX_TOT_SS_FORCE)) {
+ pr_err("%s: Choose a TOT SS type of compensation data ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ ret = requestCompensationData(type);
+ if (ret < 0) {
+ pr_err("%s: error while requesting data... ERROR %08X\n",
+ __func__, ERROR_REQU_COMP_DATA);
+ return ret | ERROR_REQU_COMP_DATA;
+ }
+
+ ret = readCompensationDataHeader(type, &(data->header), &address);
+ if (ret < 0) {
+ pr_err("%s: error while reading data header... ERROR %08X\n",
+ __func__, ERROR_COMP_DATA_HEADER);
+ return ret | ERROR_COMP_DATA_HEADER;
+ }
+
+ ret = readTotSelfSenseGlobalData(&address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_GLOBAL);
+ return ret | ERROR_COMP_DATA_GLOBAL;
+ }
+
+ ret = readTotSelfSenseNodeData(address, data);
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE);
+ return ret | ERROR_COMP_DATA_NODE;
+ }
+
+ return OK;
+}
+
+
+/**
+ * Read Initialization Data Header for the Coefficients and check that the type
+ * loaded match with the one previously requested
+ * @param type type of Coefficients data requested @link load_opt Load Host
+ * Data Option @endlink
+ * @param msHeader pointer to DataHeader variable for the MS Coefficients
+ * @param ssHeader pointer to DataHeader variable for the SS Coefficients
+ * @param address pointer to a variable which will contain the updated address
+ * to the next data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSensitivityCoeffHeader(u8 type, DataHeader *msHeader,
+ DataHeader *ssHeader, u64 *address)
+{
+ u64 offset = ADDR_FRAMEBUFFER;
+ u8 data[SYNCFRAME_DATA_HEADER];
+ int ret;
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data,
+ SYNCFRAME_DATA_HEADER, DUMMY_FRAMEBUFFER);
+ if (ret < OK) { /* i2c function have already a retry mechanism */
+ pr_err("%s: error while reading data header ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_info("Read Data Header done!\n");
+
+ if (data[0] != HEADER_SIGNATURE) {
+ pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n",
+ __func__, data[0], HEADER_SIGNATURE,
+ ERROR_WRONG_DATA_SIGN);
+ return ERROR_WRONG_DATA_SIGN;
+ }
+
+
+ if (data[1] != type) {
+ pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n",
+ __func__, data[1], type, ERROR_DIFF_DATA_TYPE);
+ return ERROR_DIFF_DATA_TYPE;
+ }
+
+ pr_info("Type = %02X of Compensation data OK!\n", type);
+
+ msHeader->type = type;
+ ssHeader->type = type;
+
+ msHeader->force_node = data[5];
+ msHeader->sense_node = data[6];
+ pr_info("MS Force Len = %d Sense Len = %d\n",
+ msHeader->force_node, msHeader->sense_node);
+
+ ssHeader->force_node = data[7];
+ ssHeader->sense_node = data[8];
+ pr_info("SS Force Len = %d Sense Len = %d\n",
+ ssHeader->force_node, ssHeader->sense_node);
+
+ *address = offset + SYNCFRAME_DATA_HEADER;
+
+ return OK;
+}
+
+
+/**
+ * Read MS and SS Sensitivity Coefficients for from the IC
+ * @param address a variable which contain the address from where to read the
+ * data
+ * @param msCoeff pointer to MutualSenseCoeff variable which will contain the
+ * MS Coefficient data
+ * @param ssCoeff pointer to SelfSenseCoeff variable which will contain the SS
+ * Coefficient data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSensitivityCoeffNodeData(u64 address, MutualSenseCoeff *msCoeff,
+ SelfSenseCoeff *ssCoeff)
+{
+ int size = msCoeff->header.force_node * msCoeff->header.sense_node +
+ (ssCoeff->header.force_node + ssCoeff->header.sense_node);
+ u8 data[size];
+ int ret;
+
+ msCoeff->node_data_size = msCoeff->header.force_node *
+ msCoeff->header.sense_node;
+
+ msCoeff->ms_coeff = (u8 *)kmalloc(msCoeff->node_data_size *
+ (sizeof(u8)), GFP_KERNEL);
+
+ ssCoeff->ss_force_coeff = (u8 *)kmalloc(ssCoeff->header.force_node *
+ (sizeof(u8)), GFP_KERNEL);
+
+ ssCoeff->ss_sense_coeff = (u8 *)kmalloc(ssCoeff->header.sense_node *
+ (sizeof(u8)), GFP_KERNEL);
+ if (msCoeff->ms_coeff == NULL ||
+ ssCoeff->ss_force_coeff == NULL ||
+ ssCoeff->ss_sense_coeff == NULL) {
+
+ pr_err("%s: can not allocate memory for coeff ERROR %08X",
+ __func__, ERROR_ALLOC);
+
+ kfree(msCoeff->ms_coeff);
+ msCoeff->ms_coeff = NULL;
+
+ kfree(ssCoeff->ss_force_coeff);
+ ssCoeff->ss_force_coeff = NULL;
+
+ kfree(ssCoeff->ss_sense_coeff);
+ ssCoeff->ss_sense_coeff = NULL;
+
+ return ERROR_ALLOC;
+ }
+
+ pr_info("Address for Node data = %llx\n", address);
+
+ pr_info("Node Data to read %d bytes\n", size);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data,
+ size, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading data... ERROR %08X\n",
+ __func__, ret);
+ kfree(msCoeff->ms_coeff);
+ msCoeff->ms_coeff = NULL;
+ kfree(ssCoeff->ss_force_coeff);
+ ssCoeff->ss_force_coeff = NULL;
+ kfree(ssCoeff->ss_sense_coeff);
+ ssCoeff->ss_sense_coeff = NULL;
+ return ret;
+ }
+
+ pr_info("Read node data ok!\n");
+
+ memcpy(msCoeff->ms_coeff, data, msCoeff->node_data_size);
+ memcpy(ssCoeff->ss_force_coeff, &data[msCoeff->node_data_size],
+ ssCoeff->header.force_node);
+ memcpy(ssCoeff->ss_sense_coeff, &data[msCoeff->node_data_size +
+ ssCoeff->header.force_node],
+ ssCoeff->header.sense_node);
+
+ return OK;
+}
+
+
+/**
+ * Perform all the steps to read Sensitivity Coefficients and store into the
+ * corresponding variables
+ * @param msCoeff pointer to a variable which will contain the MS Sensitivity
+ * Coefficients
+ * @param ssCoeff pointer to a variable which will contain the SS Sensitivity
+ * Coefficients
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSensitivityCoefficientsData(MutualSenseCoeff *msCoeff,
+ SelfSenseCoeff *ssCoeff)
+{
+ int ret;
+ u64 address;
+
+ msCoeff->ms_coeff = NULL;
+ ssCoeff->ss_force_coeff = NULL;
+ ssCoeff->ss_sense_coeff = NULL;
+
+
+ ret = requestCompensationData(LOAD_SENS_CAL_COEFF);
+ if (ret < OK) {
+ pr_err("%s: error while requesting data... ERROR %08X\n",
+ __func__, ERROR_REQU_COMP_DATA);
+ return ret | ERROR_REQU_COMP_DATA;
+ }
+
+ ret = readSensitivityCoeffHeader(LOAD_SENS_CAL_COEFF,
+ &(msCoeff->header), &(ssCoeff->header),
+ &address);
+ if (ret < OK) {
+ pr_err("%s: error while reading data header... ERROR %08X\n",
+ __func__, ERROR_COMP_DATA_HEADER);
+ return ret | ERROR_COMP_DATA_HEADER;
+ }
+
+ ret = readSensitivityCoeffNodeData(address, msCoeff, ssCoeff);
+ if (ret < OK) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_COMP_DATA_NODE);
+ return ret | ERROR_COMP_DATA_NODE;
+ }
+
+ return OK;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.h b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.h
new file mode 100644
index 00000000000..34f4c972669
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsCompensation.h
@@ -0,0 +1,165 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS functions for getting Initialization Data **
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsCompensation.h
+ * \brief Contains all the definitions and structs to work with Initialization
+ * Data
+ */
+
+#ifndef FTS_COMPENSATION_H
+#define FTS_COMPENSATION_H
+
+#include "ftsCore.h"
+#include "ftsSoftware.h"
+
+
+
+#define RETRY_COMP_DATA_READ 2 /* /< max number of attempts to read
+ * initialization data */
+
+
+/* Bytes dimension of Compensation Data Format */
+
+#define COMP_DATA_HEADER DATA_HEADER /* /< size in bytes of
+ * initialization data header */
+#define COMP_DATA_GLOBAL (16 - COMP_DATA_HEADER) /* /< size in bytes
+ * of initialization
+ * data general info */
+
+
+#define HEADER_SIGNATURE 0xA5 /* /< signature used as starting byte of
+ * data loaded in memory */
+
+
+
+/**
+ * Struct which contains the general info about Frames and Initialization Data
+ */
+typedef struct {
+ int force_node; /* /< Number of Force Channels in the
+ * frame/Initialization data */
+ int sense_node; /* /< Number of Sense Channels in the
+ * frame/Initialization data */
+ int type; /* /< Type of frame/Initialization data */
+} DataHeader;
+
+/**
+ * Struct which contains the MS Initialization data
+ */
+typedef struct {
+ DataHeader header; /* /< Header */
+ i8 cx1; /* /< Cx1 value (can be negative)) */
+ i8 *node_data; /* /< Pointer to an array of bytes which contains the
+ * CX2 data (can be negative) */
+ int node_data_size; /* /< size of the data */
+} MutualSenseData;
+
+
+/**
+ * Struct which contains the SS Initialization data
+ */
+typedef struct {
+ DataHeader header; /* /< Header */
+ u8 f_ix1; /* /< IX1 Force */
+ u8 s_ix1; /* /< IX1 Sense */
+ i8 f_cx1; /* /< CX1 Force (can be negative) */
+ i8 s_cx1; /* /< CX1 Sense (can be negative) */
+ u8 f_max_n; /* /< Force MaxN */
+ u8 s_max_n; /* /< Sense MaxN */
+
+ u8 *ix2_fm; /* /< pointer to an array of bytes which contains Force
+ * Ix2 data node */
+ u8 *ix2_sn; /* /< pointer to an array of bytes which contains Sense
+ * Ix2 data node */
+ i8 *cx2_fm; /* /< pointer to an array of bytes which contains Force
+ * Cx2 data node
+ * (can be negative) */
+ i8 *cx2_sn; /* /< pointer to an array of bytes which contains Sense
+ * Cx2 data node
+ * (can be negative)) */
+} SelfSenseData;
+
+/**
+ * Struct which contains the TOT MS Initialization data
+ */
+typedef struct {
+ DataHeader header; /* /< Header */
+ short *node_data; /* /< pointer to an array of ushort which
+ * contains TOT MS Initialization data */
+ int node_data_size; /* /< size of data */
+} TotMutualSenseData;
+
+/**
+ * Struct which contains the TOT SS Initialization data
+ */
+typedef struct {
+ DataHeader header; /* /< Header */
+
+ u16 *ix_fm; /* /< pointer to an array of ushort which contains TOT
+ * SS IX Force data */
+ u16 *ix_sn; /* /< pointer to an array of ushort which contains TOT
+ * SS IX Sense data */
+ short *cx_fm; /* /< pointer to an array of ushort which contains TOT
+ * SS CX Force data
+ * (can be negative) */
+ short *cx_sn; /* /< pointer to an array of ushort which contains TOT
+ * SS CX Sense data
+ * (can be negative) */
+} TotSelfSenseData;
+
+/**
+ * Struct which contains the Mutual Sense Sensitivity Calibration Coefficients
+ */
+typedef struct {
+ DataHeader header; /* /< Header */
+ u8 *ms_coeff; /* /< Pointer to an array of bytes which contains the MS
+ * Sens coeff */
+ int node_data_size; /* /< size of coefficients */
+} MutualSenseCoeff;
+
+/**
+ * Struct which contains the Self Sense Sensitivity Calibration Coefficients
+ */
+typedef struct {
+ DataHeader header; /* /< Header */
+ u8 *ss_force_coeff; /* /< Pointer to an array of bytes which
+ * contains the SS Sens Force coeff */
+ u8 *ss_sense_coeff; /* /< Pointer to an array of bytes which
+ * contains the SS Sens Sense coeff */
+} SelfSenseCoeff;
+
+int requestCompensationData(u8 type);
+int readCompensationDataHeader(u8 type, DataHeader *header, u64 *address);
+int readMutualSenseGlobalData(u64 *address, MutualSenseData *global);
+int readMutualSenseNodeData(u64 address, MutualSenseData *node);
+int readMutualSenseCompensationData(u8 type, MutualSenseData *data);
+int readSelfSenseGlobalData(u64 *address, SelfSenseData *global);
+int readSelfSenseNodeData(u64 address, SelfSenseData *node);
+int readSelfSenseCompensationData(u8 type, SelfSenseData *data);
+int readToTMutualSenseGlobalData(u64 *address, TotMutualSenseData *global);
+int readToTMutualSenseNodeData(u64 address, TotMutualSenseData *node);
+int readTotMutualSenseCompensationData(u8 type, TotMutualSenseData *data);
+int readTotSelfSenseGlobalData(u64 *address, TotSelfSenseData *global);
+int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node);
+int readTotSelfSenseCompensationData(u8 type, TotSelfSenseData *data);
+int readSensitivityCoeffHeader(u8 type, DataHeader *msHeader,
+ DataHeader *ssHeader, u64 *address);
+int readSensitivityCoeffNodeData(u64 address, MutualSenseCoeff *msCoeff,
+ SelfSenseCoeff *ssCoeff);
+int readSensitivityCoefficientsData(MutualSenseCoeff *msData,
+ SelfSenseCoeff *ssData);
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCore.c b/drivers/input/touchscreen/stm/fts_lib/ftsCore.c
new file mode 100644
index 00000000000..0bd7576f7fc
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsCore.c
@@ -0,0 +1,1181 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Core functions *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsCore.c
+ * \brief Contains the implementation of the Core functions
+ */
+
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include "ftsCompensation.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsIO.h"
+#include "ftsTest.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "ftsFrame.h"
+
+/** @addtogroup system_info
+ * @{
+ */
+SysInfo systemInfo; /* Global System Info variable, accessible in all the
+ * driver */
+/** @}*/
+
+static int reset_gpio = GPIO_NOT_DEFINED;/* /< gpio number of the rest pin,
+ * the value is GPIO_NOT_DEFINED
+ * if the reset pin is not connected */
+static int system_reseted_up; /* /< flag checked during resume to understand
+ * if there was a system reset
+ * and restore the proper state */
+static int system_reseted_down; /* /< flag checked during suspend to understand
+ * if there was a system reset
+ * and restore the proper state */
+static int disable_irq_count = 1; /* /< count the number of call to
+ * disable_irq,
+ * start with 1 because at the boot IRQ
+ * are already disabled */
+spinlock_t fts_int; /* /< spinlock to control the access to the
+ * disable_irq_counter */
+
+
+/**
+ * Initialize core variables of the library.
+ * Must be called during the probe before any other lib function
+ * @param info pointer to fts_ts_info which contains info about the device and
+ * its hw setup
+ * @return OK if success or an error code which specify the type of error
+ */
+int initCore(struct fts_ts_info *info)
+{
+ int ret = OK;
+
+ pr_debug("%s: Initialization of the Core...\n", __func__);
+ ret |= openChannel(info->client);
+ ret |= resetErrorList();
+ ret |= initTestToDo();
+ setResetGpio(info->board->reset_gpio);
+ if (ret < OK)
+ pr_err("%s: Initialization Core ERROR %08X!\n",
+ __func__, ret);
+ else
+ pr_debug("%s: Initialization Finished!\n",
+ __func__);
+ return ret;
+}
+
+/**
+ * Set the reset_gpio variable with the actual gpio number of the board link to
+ * the reset pin
+ * @param gpio gpio number link to the reset pin of the IC
+ */
+void setResetGpio(int gpio)
+{
+ reset_gpio = gpio;
+ pr_debug("setResetGpio: reset_gpio = %d\n", reset_gpio);
+}
+
+/**
+ * Perform a system reset of the IC.
+ * If the reset pin is associated to a gpio, the function execute an hw reset
+ * (toggling of reset pin) otherwise send an hw command to the IC
+ * @return OK if success or an error code which specify the type of error
+ */
+int fts_system_reset(void)
+{
+ u8 readData[FIFO_EVENT_SIZE];
+ int event_to_search;
+ int res = -1;
+ int i;
+ u8 data[1] = { SYSTEM_RESET_VALUE };
+
+ event_to_search = (int)EVT_ID_CONTROLLER_READY;
+
+ pr_debug("System resetting...\n");
+ for (i = 0; i < RETRY_SYSTEM_RESET && res < 0; i++) {
+ resetErrorList();
+ fts_disableInterrupt();
+ /* disable interrupt before resetting to be able to get boot
+ * events */
+
+ if (reset_gpio == GPIO_NOT_DEFINED)
+ res = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG,
+ ADDR_SYSTEM_RESET, data, ARRAY_SIZE(
+ data));
+ else {
+ gpio_set_value(reset_gpio, 0);
+ mdelay(10);
+ gpio_set_value(reset_gpio, 1);
+ res = OK;
+ }
+ if (res < OK)
+ pr_err("fts_system_reset: ERROR %08X\n", ERROR_BUS_W);
+ else {
+ res = pollForEvent(&event_to_search, 1, readData,
+ GENERAL_TIMEOUT);
+ if (res < OK)
+ pr_err("fts_system_reset: ERROR %08X\n", res);
+ }
+ }
+ if (res < OK) {
+ pr_err("fts_system_reset...failed after 3 attempts: ERROR %08X\n",
+ (res | ERROR_SYSTEM_RESET_FAIL));
+ return res | ERROR_SYSTEM_RESET_FAIL;
+ } else {
+ pr_debug("System reset DONE!\n");
+ system_reseted_down = 1;
+ system_reseted_up = 1;
+ return OK;
+ }
+}
+
+/**
+ * Return the value of system_resetted_down.
+ * @return the flag value: 0 if not set, 1 if set
+ */
+int isSystemResettedDown(void)
+{
+ return system_reseted_down;
+}
+
+/**
+ * Return the value of system_resetted_up.
+ * @return the flag value: 0 if not set, 1 if set
+ */
+int isSystemResettedUp(void)
+{
+ return system_reseted_up;
+}
+
+
+/**
+ * Set the value of system_reseted_down flag
+ * @param val value to write in the flag
+ */
+void setSystemResetedDown(int val)
+{
+ system_reseted_down = val;
+}
+
+/**
+ * Set the value of system_reseted_up flag
+ * @param val value to write in the flag
+ */
+void setSystemResetedUp(int val)
+{
+ system_reseted_up = val;
+}
+
+
+/** @addtogroup events_group
+ * @{
+ */
+
+/**
+ * Poll the FIFO looking for a specified event within a timeout. Support a
+ * retry mechanism.
+ * @param event_to_search pointer to an array of int where each element
+ * correspond to a byte of the event to find.
+ * If the element of the array has value -1, the byte of the event,
+ * in the same position of the element is ignored.
+ * @param event_bytes size of event_to_search
+ * @param readData pointer to an array of byte which will contain the event
+ * found
+ * @param time_to_wait time to wait before going in timeout
+ * @return OK if success or an error code which specify the type of error
+ */
+int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int
+ time_to_wait)
+{
+ int i, find, retry, count_err;
+ int time_to_count;
+ int err_handling = OK;
+ StopWatch clock;
+
+ u8 cmd[1] = { FIFO_CMD_READONE };
+ char temp[128] = { 0 };
+
+ find = 0;
+ retry = 0;
+ count_err = 0;
+ time_to_count = time_to_wait / TIMEOUT_RESOLUTION;
+
+ startStopWatch(&clock);
+ while (find != 1 && retry < time_to_count &&
+ fts_writeReadU8UX(cmd[0], 0, 0, readData, FIFO_EVENT_SIZE,
+ DUMMY_FIFO)
+ >= OK) {
+ /* Log of errors */
+ if (readData[0] == EVT_ID_ERROR) {
+ pr_debug("%s\n",
+ printHex("ERROR EVENT = ",
+ readData,
+ FIFO_EVENT_SIZE,
+ temp,
+ sizeof(temp)));
+ memset(temp, 0, 128);
+ count_err++;
+ err_handling = errorHandler(readData, FIFO_EVENT_SIZE);
+ if ((err_handling & 0xF0FF0000) ==
+ ERROR_HANDLER_STOP_PROC) {
+ pr_err("pollForEvent: forced to be stopped! ERROR %08X\n",
+ err_handling);
+ return err_handling;
+ }
+ } else {
+ if (readData[0] != EVT_ID_NOEVENT) {
+ pr_debug("%s\n",
+ printHex("READ EVENT = ", readData,
+ FIFO_EVENT_SIZE,
+ temp,
+ sizeof(temp)));
+ memset(temp, 0, 128);
+ }
+ if (readData[0] == EVT_ID_CONTROLLER_READY &&
+ event_to_search[0] != EVT_ID_CONTROLLER_READY) {
+ pr_err("pollForEvent: Unmanned Controller Ready Event! Setting reset flags...\n");
+ setSystemResetedUp(1);
+ setSystemResetedDown(1);
+ }
+ }
+
+ find = 1;
+
+ for (i = 0; i < event_bytes; i++) {
+ if (event_to_search[i] != -1 && (int)readData[i] !=
+ event_to_search[i]) {
+ find = 0;
+ break;
+ }
+ }
+
+ retry++;
+ mdelay(TIMEOUT_RESOLUTION);
+ }
+ stopStopWatch(&clock);
+ if ((retry >= time_to_count) && find != 1) {
+ pr_err("pollForEvent: ERROR %08X\n", ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ } else if (find == 1) {
+ pr_debug("%s\n",
+ printHex("FOUND EVENT = ",
+ readData,
+ FIFO_EVENT_SIZE,
+ temp,
+ sizeof(temp)));
+ memset(temp, 0, 128);
+ pr_debug("Event found in %d ms (%d iterations)! Number of errors found = %d\n",
+ elapsedMillisecond(&clock), retry, count_err);
+ return count_err;
+ } else {
+ pr_err("pollForEvent: ERROR %08X\n", ERROR_BUS_R);
+ return ERROR_BUS_R;
+ }
+}
+
+/** @}*/
+
+/**
+ * Check that the FW sent the echo even after a command was sent
+ * @param cmd pointer to an array of byte which contain the command previously
+ * sent
+ * @param size size of cmd
+ * @return OK if success or an error code which specify the type of error
+ */
+int checkEcho(u8 *cmd, int size)
+{
+ int ret, i;
+ int event_to_search[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE];
+
+
+ if (size < 1) {
+ pr_err("checkEcho: Error Size = %d not valid!\n", size);
+ return ERROR_OP_NOT_ALLOW;
+ } else {
+ if ((size + 3) > FIFO_EVENT_SIZE)
+ size = FIFO_EVENT_SIZE - 3;
+ /* Echo event 0x43 0x01 xx xx xx xx xx fifo_status
+ * therefore command with more than 5 bytes will be trunked */
+
+ event_to_search[0] = EVT_ID_STATUS_UPDATE;
+ event_to_search[1] = EVT_TYPE_STATUS_ECHO;
+ for (i = 2; i < size + 2; i++)
+ event_to_search[i] = cmd[i - 2];
+ ret = pollForEvent(event_to_search, size + 2, readData,
+ TIEMOUT_ECHO);
+ if (ret < OK) {
+ pr_err("checkEcho: Echo Event not found! ERROR %08X\n",
+ ret);
+ return ret | ERROR_CHECK_ECHO_FAIL;
+ } else if (ret > OK) {
+ pr_err("checkEcho: Echo Event found but with some error events before! num_error = %d\n",
+ ret);
+ return ERROR_CHECK_ECHO_FAIL;
+ }
+
+ pr_debug("ECHO OK!\n");
+ return ret;
+ }
+}
+
+
+/** @addtogroup scan_mode
+ * @{
+ */
+/**
+ * Set a scan mode in the IC
+ * @param mode scan mode to set; possible values @link scan_opt Scan Mode
+ * Option @endlink
+ * @param settings option for the selected scan mode
+ * (for example @link active_bitmask Active Mode Bitmask @endlink)
+ * @return OK if success or an error code which specify the type of error
+ */
+int setScanMode(u8 mode, u8 settings)
+{
+ u8 cmd[3] = { FTS_CMD_SCAN_MODE, mode, settings };
+ int ret, size = 3;
+
+ pr_debug("%s: Setting scan mode: mode = %02X settings = %02X !\n",
+ __func__, mode, settings);
+ if (mode == SCAN_MODE_LOW_POWER)
+ size = 2;
+ ret = fts_write(cmd, size);
+ /* use write instead of writeFw because can be called while the
+ * interrupt are enabled */
+ if (ret < OK) {
+ pr_err("%s: write failed...ERROR %08X !\n",
+ __func__, ret);
+ return ret | ERROR_SET_SCAN_MODE_FAIL;
+ }
+ pr_debug("%s: Setting scan mode OK!\n", __func__);
+ return OK;
+}
+/** @}*/
+
+
+/** @addtogroup feat_sel
+ * @{
+ */
+/**
+ * Set a feature and its option in the IC
+ * @param feat feature to set; possible values @link feat_opt Feature Selection
+ * Option @endlink
+ * @param settings pointer to an array of byte which store the options for
+ * the selected feature (for example the gesture mask to activate
+ * @link gesture_opt Gesture IDs @endlink)
+ * @param size in bytes of settings
+ * @return OK if success or an error code which specify the type of error
+ */
+int setFeatures(u8 feat, u8 *settings, int size)
+{
+ u8 cmd[2 + size];
+ int i = 0;
+ int ret;
+ char buff[(2 + 1) * size + 1];
+ int buff_len = sizeof(buff);
+ int index = 0;
+
+ pr_debug("%s: Setting feature: feat = %02X !\n", __func__, feat);
+ cmd[0] = FTS_CMD_FEATURE;
+ cmd[1] = feat;
+ for (i = 0; i < size; i++) {
+ cmd[2 + i] = settings[i];
+ index += scnprintf(buff + index, buff_len - index,
+ "%02X ", settings[i]);
+ }
+ pr_debug("%s: Settings = %s\n", __func__, buff);
+ ret = fts_write(cmd, 2 + size);
+ /* use write instead of writeFw because can be called while the
+ * interrupts are enabled */
+ if (ret < OK) {
+ pr_err("%s: write failed...ERROR %08X !\n", __func__, ret);
+ return ret | ERROR_SET_FEATURE_FAIL;
+ }
+ pr_debug("%s: Setting feature OK!\n", __func__);
+ return OK;
+}
+/** @}*/
+
+/** @addtogroup sys_cmd
+ * @{
+ */
+/**
+ * Write a system command to the IC
+ * @param sys_cmd System Command to execute; possible values
+ * @link sys_opt System Command Option @endlink
+ * @param sett settings option for the selected system command
+ * (@link sys_special_opt Special Command Option @endlink, @link ito_opt
+ * ITO Test Option @endlink, @link load_opt Load Host Data Option @endlink)
+ * @param size in bytes of settings
+ * @return OK if success or an error code which specify the type of error
+ */
+int writeSysCmd(u8 sys_cmd, u8 *sett, int size)
+{
+ u8 cmd[2 + size];
+ int ret;
+ char buff[(2 + 1) * size + 1];
+ int buff_len = sizeof(buff);
+ int index = 0;
+
+ cmd[0] = FTS_CMD_SYSTEM;
+ cmd[1] = sys_cmd;
+
+ for (ret = 0; ret < size; ret++) {
+ cmd[2 + ret] = sett[ret];
+ index += scnprintf(buff + index, buff_len - index,
+ "%02X ", sett[ret]);
+ }
+ pr_debug("%s: Command = %02X %02X %s\n", __func__, cmd[0],
+ cmd[1], buff);
+ pr_debug("%s: Writing Sys command...\n", __func__);
+ if (sys_cmd != SYS_CMD_LOAD_DATA)
+ ret = fts_writeFwCmd(cmd, 2 + size);
+ else {
+ if (size >= 1)
+ ret = requestSyncFrame(sett[0]);
+ else {
+ pr_err("%s: No setting argument! ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+ }
+ if (ret < OK)
+ pr_err("%s: ERROR %08X\n", __func__, ret);
+ else
+ pr_debug("%s: FINISHED!\n", __func__);
+
+ return ret;
+}
+/** @}*/
+
+/** @addtogroup system_info
+ * @{
+ */
+/**
+ * Initialize the System Info Struct with default values according to the error
+ * found during the reading
+ * @param i2cError 1 if there was an I2C error while reading the System Info
+ * data from memory, other value if another error occurred
+ * @return OK if success or an error code which specify the type of error
+ */
+int defaultSysInfo(int i2cError)
+{
+ int i;
+
+ pr_debug("Setting default System Info...\n");
+
+ if (i2cError == 1) {
+ systemInfo.u16_fwVer = 0xFFFF;
+ systemInfo.u16_cfgProjectId = 0xFFFF;
+ for (i = 0; i < RELEASE_INFO_SIZE; i++)
+ systemInfo.u8_releaseInfo[i] = 0xFF;
+ systemInfo.u16_cxVer = 0xFFFF;
+ } else {
+ systemInfo.u16_fwVer = 0x0000;
+ systemInfo.u16_cfgProjectId = 0x0000;
+ for (i = 0; i < RELEASE_INFO_SIZE; i++)
+ systemInfo.u8_releaseInfo[i] = 0x00;
+ systemInfo.u16_cxVer = 0x0000;
+ }
+
+ systemInfo.u8_scrRxLen = 0;
+ systemInfo.u8_scrTxLen = 0;
+
+ pr_debug("default System Info DONE!\n");
+ return OK;
+}
+
+/**
+ * Read the System Info data from memory. System Info is loaded automatically
+ * after every system reset.
+ * @param request if 1, will be asked to the FW to reload the data, otherwise
+ * attempt to read it directly from memory
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSysInfo(int request)
+{
+ int ret, i, index = 0;
+ u8 sett = LOAD_SYS_INFO;
+ u8 data[SYS_INFO_SIZE] = { 0 };
+ char temp[256] = { 0 };
+
+ if (request == 1) {
+ pr_debug("%s: Requesting System Info...\n", __func__);
+
+ ret = writeSysCmd(SYS_CMD_LOAD_DATA, &sett, 1);
+ if (ret < OK) {
+ pr_err("%s: error while writing the sys cmd ERROR %08X\n",
+ __func__, ret);
+ goto FAIL;
+ }
+ }
+
+ pr_debug("%s: Reading System Info...\n", __func__);
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16,
+ ADDR_FRAMEBUFFER, data, SYS_INFO_SIZE,
+ DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: error while reading the system data ERROR %08X\n",
+ __func__, ret);
+ goto FAIL;
+ }
+
+ pr_debug("%s: Parsing System Info...\n", __func__);
+
+ if (data[0] != HEADER_SIGNATURE) {
+ pr_err("%s: The Header Signature is wrong! sign: %02X != %02X ERROR %08X\n",
+ __func__, data[0], HEADER_SIGNATURE,
+ ERROR_WRONG_DATA_SIGN);
+ ret = ERROR_WRONG_DATA_SIGN;
+ goto FAIL;
+ }
+
+
+ if (data[1] != LOAD_SYS_INFO) {
+ pr_err("%s: The Data ID is wrong! ids: %02X != %02X ERROR %08X\n",
+ __func__, data[3], LOAD_SYS_INFO,
+ ERROR_DIFF_DATA_TYPE);
+ ret = ERROR_DIFF_DATA_TYPE;
+ goto FAIL;
+ }
+
+ index += 4;
+ u8ToU16(&data[index], &systemInfo.u16_apiVer_rev);
+ index += 2;
+ systemInfo.u8_apiVer_minor = data[index++];
+ systemInfo.u8_apiVer_major = data[index++];
+ u8ToU16(&data[index], &systemInfo.u16_chip0Ver);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_chip0Id);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_chip1Ver);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_chip1Id);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_fwVer);
+ index += 2;
+ pr_debug("FW VER = %04X\n", systemInfo.u16_fwVer);
+ u8ToU16(&data[index], &systemInfo.u16_svnRev);
+ index += 2;
+ pr_debug("SVN REV = %04X\n", systemInfo.u16_svnRev);
+ u8ToU16(&data[index], &systemInfo.u16_cfgVer);
+ index += 2;
+ pr_debug("CONFIG VER = %04X\n", systemInfo.u16_cfgVer);
+ u8ToU16(&data[index], &systemInfo.u16_cfgProjectId);
+ index += 2;
+ pr_debug("CONFIG PROJECT ID = %04X\n", systemInfo.u16_cfgProjectId);
+ u8ToU16(&data[index], &systemInfo.u16_cxVer);
+ index += 2;
+ pr_debug("CX VER = %04X\n", systemInfo.u16_cxVer);
+ u8ToU16(&data[index], &systemInfo.u16_cxProjectId);
+ index += 2;
+ pr_debug("CX PROJECT ID = %04X\n", systemInfo.u16_cxProjectId);
+ systemInfo.u8_cfgAfeVer = data[index++];
+ systemInfo.u8_cxAfeVer = data[index++];
+ systemInfo.u8_panelCfgAfeVer = data[index++];
+ pr_debug("AFE VER: CFG = %02X - CX = %02X - PANEL = %02X\n",
+ systemInfo.u8_cfgAfeVer, systemInfo.u8_cxAfeVer,
+ systemInfo.u8_panelCfgAfeVer);
+ systemInfo.u8_protocol = data[index++];
+ pr_debug("Protocol = %02X\n", systemInfo.u8_protocol);
+ /* index+= 1; */
+ /* skip reserved area */
+
+ /* pr_err("Die Info = "); */
+ for (i = 0; i < DIE_INFO_SIZE; i++)
+ systemInfo.u8_dieInfo[i] = data[index++];
+
+ /* pr_err("\n"); */
+ pr_debug("%s\n",
+ printHex("Die Info = ",
+ systemInfo.u8_dieInfo,
+ DIE_INFO_SIZE, temp, sizeof(temp)));
+ memset(temp, 0, 256);
+
+
+ /* pr_err("Release Info = "); */
+ for (i = 0; i < RELEASE_INFO_SIZE; i++)
+ systemInfo.u8_releaseInfo[i] = data[index++];
+
+ /* pr_err("\n"); */
+
+ pr_debug("%s\n",
+ printHex("Release Info = ",
+ systemInfo.u8_releaseInfo,
+ RELEASE_INFO_SIZE,
+ temp,
+ sizeof(temp)));
+ memset(temp, 0, 256);
+
+ u8ToU32(&data[index], &systemInfo.u32_fwCrc);
+ index += 4;
+ u8ToU32(&data[index], &systemInfo.u32_cfgCrc);
+ index += 4;
+
+ index += 16; /* skip reserved area */
+
+ u8ToU16(&data[index], &systemInfo.u16_scrResX);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_scrResY);
+ index += 2;
+ pr_debug("Screen Resolution = %d x %d\n",
+ systemInfo.u16_scrResX, systemInfo.u16_scrResY);
+ systemInfo.u8_scrTxLen = data[index++];
+ pr_debug("TX Len = %d\n", systemInfo.u8_scrTxLen);
+ systemInfo.u8_scrRxLen = data[index++];
+ pr_debug("RX Len = %d\n", systemInfo.u8_scrRxLen);
+ systemInfo.u8_keyLen = data[index++];
+ pr_debug("Key Len = %d\n", systemInfo.u8_keyLen);
+ systemInfo.u8_forceLen = data[index++];
+ pr_debug("Force Len = %d\n", systemInfo.u8_forceLen);
+
+ index += 40; /* skip reserved area */
+
+ u8ToU16(&data[index], &systemInfo.u16_dbgInfoAddr);
+ index += 2;
+
+ index += 6; /* skip reserved area */
+
+ u8ToU16(&data[index], &systemInfo.u16_msTchRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_msTchFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_msTchStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_msTchBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_ssTchTxRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssTchTxFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssTchTxStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssTchTxBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_ssTchRxRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssTchRxFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssTchRxStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssTchRxBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_keyRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_keyFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_keyStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_keyBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_frcRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_frcFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_frcStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_frcBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrTxRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrTxFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrTxStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrTxBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrRxRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrRxFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrRxStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssHvrRxBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxTxRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxTxFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxTxStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxTxBaselineAddr);
+ index += 2;
+
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxRxRawAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxRxFilterAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxRxStrenAddr);
+ index += 2;
+ u8ToU16(&data[index], &systemInfo.u16_ssPrxRxBaselineAddr);
+ index += 2;
+
+ pr_debug("Parsed %d bytes!\n", index);
+
+
+ if (index != SYS_INFO_SIZE) {
+ pr_err("%s: index = %d different from %d ERROR %08X\n",
+ __func__, index, SYS_INFO_SIZE,
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ pr_debug("System Info Read DONE!\n");
+ return OK;
+
+FAIL:
+ defaultSysInfo(isI2cError(ret));
+ return ret;
+}
+/** @}*/
+
+
+/**
+ * Read data from the Config Memory
+ * @param offset Starting address in the Config Memory of data to read
+ * @param outBuf pointer of a byte array which contain the bytes to read
+ * @param len number of bytes to read
+ * @return OK if success or an error code which specify the type of error
+ */
+int readConfig(u16 offset, u8 *outBuf, int len)
+{
+ int ret;
+ u64 final_address = offset + ADDR_CONFIG_OFFSET;
+
+ pr_debug("%s: Starting to read config memory at %llx ...\n",
+ __func__, final_address);
+ ret = fts_writeReadU8UX(FTS_CMD_CONFIG_R, BITS_16, final_address,
+ outBuf, len, DUMMY_CONFIG);
+ if (ret < OK) {
+ pr_err("%s: Impossible to read Config Memory... ERROR %08X!\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_debug("%s: Read config memory FINISHED!\n", __func__);
+ return OK;
+}
+
+/**
+ * Write data into the Config Memory
+ * @param offset Starting address in the Config Memory where write the data
+ * @param data pointer of a byte array which contain the data to write
+ * @param len number of bytes to write
+ * @return OK if success or an error code which specify the type of error
+ */
+int writeConfig(u16 offset, u8 *data, int len)
+{
+ int ret;
+ u64 final_address = offset + ADDR_CONFIG_OFFSET;
+
+ pr_debug("%s: Starting to write config memory at %llx ...\n",
+ __func__, final_address);
+ ret = fts_writeU8UX(FTS_CMD_CONFIG_W, BITS_16, final_address, data,
+ len);
+ if (ret < OK) {
+ pr_err("%s: Impossible to write Config Memory... ERROR %08X!\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_debug("%s: Write config memory FINISHED!\n", __func__);
+ return OK;
+}
+
+/**
+ * Disable the interrupt so the ISR of the driver can not be called
+ * @return OK if success or an error code which specify the type of error
+ */
+int fts_disableInterrupt(void)
+{
+ unsigned long flag;
+
+ if (getClient() != NULL) {
+ spin_lock_irqsave(&fts_int, flag);
+ pr_debug("Number of disable = %d\n", disable_irq_count);
+ if (disable_irq_count == 0) {
+ pr_debug("Executing Disable...\n");
+ disable_irq_nosync(getClient()->irq);
+ disable_irq_count++;
+ }
+ /* disable_irq is re-entrant so it is required to keep track
+ * of the number of calls of this when reenabling */
+ spin_unlock_irqrestore(&fts_int, flag);
+ pr_debug("Interrupt Disabled!\n");
+ return OK;
+ } else {
+ pr_err("%s: Impossible get client irq... ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+
+/**
+ * Disable the interrupt async so the ISR of the driver can not be called
+ * @return OK if success or an error code which specify the type of error
+ */
+int fts_disableInterruptNoSync(void)
+{
+ if (getClient() != NULL) {
+ spin_lock_irq(&fts_int);
+ pr_debug("Number of disable = %d\n", disable_irq_count);
+ if (disable_irq_count == 0) {
+ pr_debug("Executing Disable...\n");
+ disable_irq_nosync(getClient()->irq);
+ disable_irq_count++;
+ }
+ /* disable_irq is re-entrant so it is required to keep track
+ * of the number of calls of this when reenabling */
+
+ spin_unlock(&fts_int);
+ pr_debug("Interrupt No Sync Disabled!\n");
+ return OK;
+ } else {
+ pr_err("%s: Impossible get client irq... ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Reset the disable_irq count
+ * @return OK
+ */
+int fts_resetDisableIrqCount(void)
+{
+ disable_irq_count = 0;
+ return OK;
+}
+
+/**
+ * Enable the interrupt so the ISR of the driver can be called
+ * @return OK if success or an error code which specify the type of error
+ */
+int fts_enableInterrupt(void)
+{
+ unsigned long flag;
+
+ if (getClient() != NULL) {
+ spin_lock_irqsave(&fts_int, flag);
+ pr_debug("Number of re-enable = %d\n", disable_irq_count);
+ while (disable_irq_count > 0) {
+ /* loop N times according on the pending number of
+ * disable_irq to truly re-enable the int */
+ pr_debug("Executing Enable...\n");
+ enable_irq(getClient()->irq);
+ disable_irq_count--;
+ }
+
+ spin_unlock_irqrestore(&fts_int, flag);
+ pr_debug("Interrupt Enabled!\n");
+ return OK;
+ } else {
+ pr_err("%s: Impossible get client irq... ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Check if there is a crc error in the IC which prevent the fw to run.
+ * @return OK if no CRC error, or a number >OK according the CRC error found
+ */
+int fts_crc_check(void)
+{
+ u8 val;
+ u8 crc_status;
+ int res;
+ u8 error_to_search[6] = { EVT_TYPE_ERROR_CRC_CFG_HEAD,
+ EVT_TYPE_ERROR_CRC_CFG,
+ EVT_TYPE_ERROR_CRC_CX,
+ EVT_TYPE_ERROR_CRC_CX_HEAD,
+ EVT_TYPE_ERROR_CRC_CX_SUB,
+ EVT_TYPE_ERROR_CRC_CX_SUB_HEAD };
+
+
+ res = fts_writeReadU8UX(FTS_CMD_HW_REG_R, ADDR_SIZE_HW_REG, ADDR_CRC,
+ &val, 1, DUMMY_HW_REG);
+ /* read 2 bytes because the first one is a dummy byte! */
+ if (res < OK) {
+ pr_err("%s Cannot read crc status ERROR %08X\n", __func__, res);
+ return res;
+ }
+
+ crc_status = val & CRC_MASK;
+ if (crc_status != OK) { /* CRC error if crc_status!=0 */
+ pr_err("%s CRC ERROR = %02X\n", __func__, crc_status);
+ return CRC_CODE;
+ }
+
+ pr_debug("%s: Verifying if Config CRC Error...\n", __func__);
+ res = fts_system_reset();
+ if (res >= OK) {
+ res = pollForErrorType(error_to_search, 2);
+ if (res < OK) {
+ pr_debug("%s: No Config CRC Error Found!\n", __func__);
+ pr_debug("%s: Verifying if Cx CRC Error...\n", __func__);
+ res = pollForErrorType(&error_to_search[2], 4);
+ if (res < OK) {
+ pr_debug("%s: No Cx CRC Error Found!\n",
+ __func__);
+ return OK;
+ } else {
+ pr_err("%s: Cx CRC Error found! CRC ERROR = %02X\n",
+ __func__, res);
+ return CRC_CX;
+ }
+ } else {
+ pr_err("%s: Config CRC Error found! CRC ERROR = %02X\n",
+ __func__, res);
+ return CRC_CONFIG;
+ }
+ } else {
+ pr_err("%s: Error while executing system reset! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ return OK;
+}
+
+/**
+ * Request a host data and use the sync method to understand when the FW load
+ * it
+ * @param type the type ID of host data to load (@link load_opt Load Host Data
+ * Option @endlink)
+ * @return OK if success or an error code which specify the type of error
+ */
+int requestSyncFrame(u8 type)
+{
+ u8 request[3] = { FTS_CMD_SYSTEM, SYS_CMD_LOAD_DATA, type };
+ u8 readData[DATA_HEADER] = { 0 };
+ int ret, retry = 0, retry2 = 0, time_to_count;
+ int count, new_count;
+
+ pr_debug("%s: Starting to get a sync frame...\n", __func__);
+
+ while (retry2 < RETRY_MAX_REQU_DATA) {
+ pr_debug("%s: Reading count...\n", __func__);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16,
+ ADDR_FRAMEBUFFER, readData, DATA_HEADER,
+ DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: Error while reading count! ERROR %08X\n",
+ __func__, ret | ERROR_REQU_DATA);
+ ret |= ERROR_REQU_DATA;
+ retry2++;
+ continue;
+ }
+
+ if (readData[0] != HEADER_SIGNATURE)
+ pr_err("%s: Invalid Signature while reading count! ERROR %08X\n",
+ __func__, ret | ERROR_REQU_DATA);
+
+ count = (readData[3] << 8) | readData[2];
+ new_count = count;
+ pr_debug("%s: Base count = %d\n", __func__, count);
+
+ pr_debug("%s: Requesting frame %02X attempt = %d\n",
+ __func__, type, retry2 + 1);
+ ret = fts_write(request, ARRAY_SIZE(request));
+ if (ret >= OK) {
+ pr_debug("%s: Polling for new count...\n", __func__);
+ time_to_count = TIMEOUT_REQU_DATA / TIMEOUT_RESOLUTION;
+ while (count == new_count && retry < time_to_count) {
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R,
+ BITS_16,
+ ADDR_FRAMEBUFFER,
+ readData,
+ DATA_HEADER,
+ DUMMY_FRAMEBUFFER);
+ if ((ret >= OK) && (readData[0] ==
+ HEADER_SIGNATURE) &&
+ (readData[1] == type))
+ new_count = ((readData[3] << 8) |
+ readData[2]);
+ else
+ pr_err("%s: invalid Signature or can not read count... ERROR %08X\n",
+ __func__, ret);
+ retry++;
+ mdelay(TIMEOUT_RESOLUTION);
+ }
+
+ if (count == new_count) {
+ pr_err("%s: New count not received! ERROR %08X\n",
+ __func__,
+ ERROR_TIMEOUT | ERROR_REQU_DATA);
+ ret = ERROR_TIMEOUT | ERROR_REQU_DATA;
+ } else {
+ pr_debug("%s: New count found! count = %d! Frame ready!\n",
+ __func__, new_count);
+ return OK;
+ }
+ }
+ retry2++;
+ }
+ pr_err("%s: Request Data failed! ERROR %08X\n", __func__, ret);
+ return ret;
+}
+
+/**
+ * Set the Active Scanning Frequency to a defined value
+ * @param freq scanning frequency to set in Hz
+ * @return OK if success or an error code which specify the type of error
+ * @warning The scan frequency can be set only for the MS scan!
+ */
+int setActiveScanFrequency(u32 freq)
+{
+ int res;
+ u8 temp[2] = { 0 };
+ u16 t_cycle;
+
+ pr_debug("%s: Setting the scanning frequency to %uHz...\n",
+ __func__, freq);
+
+ /* read MRN register */
+ res = readConfig(ADDR_CONFIG_MRN, temp, 1);
+ if (res < OK) {
+ pr_err("%s: error while reading mrn count! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ /* setting r count to 0 (= 1 R cycle used) and write it back */
+ temp[0] &= (~0x03);
+ res = writeConfig(ADDR_CONFIG_MRN, temp, 1);
+ if (res < OK) {
+ pr_err("%s: error while writing mrn count! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ /* set first R cycle slot according the specified frequency */
+ /* read T cycle */
+ res = readConfig(ADDR_CONFIG_T_CYCLE, temp, 2);
+ if (res < OK) {
+ pr_err("%s: error while reading T cycle! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+ t_cycle = ((u16)(temp[1] << 8)) | temp[0];
+
+
+ /* compute the value of R cycle according the formula
+ * scan_freq = 30Mhz/(2*(T_cycle+R_cycle)) */
+ temp[0] = (30000000) / (freq * 2) - t_cycle;
+ /* write R cycle in Config Area */
+ pr_debug("%s: T cycle = %d (0x%04X) => R0 cycle = %d (0x%02X)\n",
+ __func__, t_cycle, t_cycle, temp[0], temp[0]);
+ res = writeConfig(ADDR_CONFIG_R0_CYCLE, temp, 1);
+ if (res < OK) {
+ pr_err("%s: error while writing R0 cycle! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ pr_debug("%s: Saving Config into the flash ...\n", __func__);
+ /* save config */
+ temp[0] = SAVE_FW_CONF;
+ res = writeSysCmd(SYS_CMD_SAVE_FLASH, temp, 1);
+ if (res < OK) {
+ pr_err("%s: error while saving config into the flash! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ /* system reset */
+ res = fts_system_reset();
+ if (res < OK) {
+ pr_err("%s: error at system reset! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ pr_debug("%s: Setting the scanning frequency FINISHED!\n", __func__);
+ return OK;
+}
+
+/**
+ * Write Host Data Memory
+ * @param type type of data to write
+ * @param data pointer to the data which are written
+ * @param msForceLen number of force (Tx) channels used with Mutual
+ * @param msSenseLen number of sense (Rx) channels used with Mutual
+ * @param ssForceLen number of force (Tx) channel used with Self
+ * @param ssSenseLen number of sense (Rx) channel used with Self
+ * @param save if =1 will save the host data written into the flash
+ * @return OK if success or an error code which specify the type of error
+ */
+int writeHostDataMemory(u8 type, u8 *data, u8 msForceLen, u8 msSenseLen,
+ u8 ssForceLen, u8 ssSenseLen, int save)
+{
+ int res;
+ int size = (msForceLen * msSenseLen) + (ssForceLen + ssSenseLen);
+ u8 sett = SPECIAL_WRITE_HOST_MEM_TO_FLASH;
+ u8 temp[size + SYNCFRAME_DATA_HEADER];
+
+ memset(temp, 0, size + SYNCFRAME_DATA_HEADER);
+ pr_debug("%s: Starting to write Host Data Memory\n", __func__);
+
+ temp[0] = 0x5A;
+ temp[1] = type;
+ temp[5] = msForceLen;
+ temp[6] = msSenseLen;
+ temp[7] = ssForceLen;
+ temp[8] = ssSenseLen;
+
+ memcpy(&temp[16], data, size);
+
+ pr_debug("%s: Write Host Data Memory in buffer...\n", __func__);
+ res = fts_writeU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16,
+ ADDR_FRAMEBUFFER, temp, size +
+ SYNCFRAME_DATA_HEADER);
+
+ if (res < OK) {
+ pr_err("%s: error while writing the buffer! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+
+ /* save host data memory into the flash */
+ if (save == 1) {
+ pr_debug("%s: Trigger writing into the flash...\n", __func__);
+ res = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1);
+ if (res < OK) {
+ pr_err("%s: error while writing into the flash! ERROR %08X\n",
+ __func__, res);
+ return res;
+ }
+ }
+
+
+ pr_debug("%s: write Host Data Memory FINISHED!\n", __func__);
+ return OK;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsCore.h b/drivers/input/touchscreen/stm/fts_lib/ftsCore.h
new file mode 100644
index 00000000000..ea7608c8fe5
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsCore.h
@@ -0,0 +1,207 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Core definitions **
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsCore.h
+ * \brief Contains all the definitions and structs of Core functionalities
+ */
+
+#ifndef FTS_CORE_H
+#define FTS_CORE_H
+
+#include "ftsHardware.h"
+#include "ftsSoftware.h"
+#include "../fts.h"
+
+/* HW DATA */
+#define GPIO_NOT_DEFINED -1 /* /< value assumed by reset_gpio when
+ * the reset pin of the IC is not
+ * connected */
+
+
+#define ADDR_SIZE_HW_REG BITS_32 /* /< value of AddrSize for Hw register
+ * in FTI @see AddrSize */
+
+#define DATA_HEADER 4 /* /< size in byte of the header loaded
+ * with the data in the frambuffer */
+
+/**
+ * Type of CRC errors
+ */
+typedef enum {
+ CRC_CODE = 1, /* /< CRC in the code section */
+ CRC_CONFIG = 2, /* /< CRC in the config section */
+ CRC_CX = 3, /* /< CRC in the cx section */
+ CRC_PANEL = 4 /* /< CRC in the panel section */
+} CRC_Error;
+
+/* CHIP INFO */
+/** @defgroup system_info System Info
+ * System Info Data collect the most important information about hw and fw
+ * @{
+ */
+/* Size in bytes of System Info data */
+#define SYS_INFO_SIZE 208 /* Num bytes of die info */
+#define DIE_INFO_SIZE 16 /* Num bytes of external release
+ * in config */
+#define EXTERNAL_RELEASE_INFO_SIZE 8 /* Num bytes of release info in
+ * sys info
+ * (first bytes are external
+ * release) */
+#define RELEASE_INFO_SIZE (EXTERNAL_RELEASE_INFO_SIZE)
+/** @}*/
+
+/* RETRY MECHANISM */
+#define RETRY_MAX_REQU_DATA 2 /* /< Max number of attempts
+ * performed
+ * when requesting data */
+#define RETRY_SYSTEM_RESET 3 /* /< Max number of attempts
+ * performed
+ * to reset the IC */
+
+/** @addtogroup system_info
+ * @{
+ */
+
+/**
+ * Struct which contains fundamental information about the chip and its
+ * configuration
+ */
+typedef struct {
+ u16 u16_apiVer_rev; /* /< API revision version */
+ u8 u8_apiVer_minor; /* /< API minor version */
+ u8 u8_apiVer_major; /* /< API major version */
+ u16 u16_chip0Ver; /* /< Dev0 version */
+ u16 u16_chip0Id; /* /< Dev0 ID */
+ u16 u16_chip1Ver; /* /< Dev1 version */
+ u16 u16_chip1Id; /* /< Dev1 ID */
+ u16 u16_fwVer; /* /< Fw version */
+ u16 u16_svnRev; /* /< SVN Revision */
+ u16 u16_cfgVer; /* /< Config Version */
+ u16 u16_cfgProjectId; /* /< Config Project ID */
+ u16 u16_cxVer; /* /< Cx Version */
+ u16 u16_cxProjectId; /* /< Cx Project ID */
+ u8 u8_cfgAfeVer; /* /< AFE version in Config */
+ u8 u8_cxAfeVer; /* /< AFE version in CX */
+ u8 u8_panelCfgAfeVer; /* /< AFE version in PanelMem */
+ u8 u8_protocol; /* /< Touch Report Protocol */
+ u8 u8_dieInfo[DIE_INFO_SIZE]; /* /< Die information */
+ u8 u8_releaseInfo[RELEASE_INFO_SIZE]; /* /< Release information */
+ u32 u32_fwCrc; /* /< Crc of FW */
+ u32 u32_cfgCrc; /* /< Crc of config */
+
+ u16 u16_scrResX;/* /< X resolution on main screen */
+ u16 u16_scrResY;/* /< Y resolution on main screen */
+ u8 u8_scrTxLen; /* /< Tx length */
+ u8 u8_scrRxLen; /* /< Rx length */
+ u8 u8_keyLen; /* /< Key Len */
+ u8 u8_forceLen; /* /< Force Len */
+
+ u16 u16_dbgInfoAddr; /* /< Offset of debug Info structure */
+
+ u16 u16_msTchRawAddr; /* /< Offset of MS touch raw frame */
+ u16 u16_msTchFilterAddr;/* /< Offset of MS touch filter frame */
+ u16 u16_msTchStrenAddr; /* /< Offset of MS touch strength frame */
+ u16 u16_msTchBaselineAddr; /* /< Offset of MS touch baseline frame
+ * */
+
+ u16 u16_ssTchTxRawAddr; /* /< Offset of SS touch force raw frame */
+ u16 u16_ssTchTxFilterAddr; /* /< Offset of SS touch force filter
+ * frame */
+ u16 u16_ssTchTxStrenAddr;/* /< Offset of SS touch force strength frame
+ * */
+ u16 u16_ssTchTxBaselineAddr; /* /< Offset of SS touch force baseline
+ * frame */
+
+ u16 u16_ssTchRxRawAddr; /* /< Offset of SS touch sense raw frame */
+ u16 u16_ssTchRxFilterAddr; /* /< Offset of SS touch sense filter
+ * frame */
+ u16 u16_ssTchRxStrenAddr;/* /< Offset of SS touch sense strength frame
+ * */
+ u16 u16_ssTchRxBaselineAddr; /* /< Offset of SS touch sense baseline
+ * frame */
+
+ u16 u16_keyRawAddr; /* /< Offset of key raw frame */
+ u16 u16_keyFilterAddr; /* /< Offset of key filter frame */
+ u16 u16_keyStrenAddr; /* /< Offset of key strength frame */
+ u16 u16_keyBaselineAddr; /* /< Offset of key baseline frame */
+
+ u16 u16_frcRawAddr; /* /< Offset of force touch raw frame */
+ u16 u16_frcFilterAddr; /* /< Offset of force touch filter frame */
+ u16 u16_frcStrenAddr; /* /< Offset of force touch strength frame */
+ u16 u16_frcBaselineAddr;/* /< Offset of force touch baseline frame */
+
+ u16 u16_ssHvrTxRawAddr; /* /< Offset of SS hover Force raw frame */
+ u16 u16_ssHvrTxFilterAddr; /* /< Offset of SS hover Force filter
+ * frame */
+ u16 u16_ssHvrTxStrenAddr;/* /< Offset of SS hover Force strength frame
+ * */
+ u16 u16_ssHvrTxBaselineAddr; /* /< Offset of SS hover Force baseline
+ * frame */
+
+ u16 u16_ssHvrRxRawAddr; /* /< Offset of SS hover Sense raw frame */
+ u16 u16_ssHvrRxFilterAddr; /* /< Offset of SS hover Sense filter
+ * frame */
+ u16 u16_ssHvrRxStrenAddr; /* /< Offset of SS hover Sense strength
+ * frame */
+ u16 u16_ssHvrRxBaselineAddr; /* /< Offset of SS hover Sense baseline
+ * frame */
+
+ u16 u16_ssPrxTxRawAddr; /* /< Offset of SS proximity force raw frame */
+ u16 u16_ssPrxTxFilterAddr; /* /< Offset of SS proximity force
+ * filter frame */
+ u16 u16_ssPrxTxStrenAddr;/* /< Offset of SS proximity force strength
+ * frame */
+ u16 u16_ssPrxTxBaselineAddr; /* /< Offset of SS proximity force
+ * baseline frame */
+
+ u16 u16_ssPrxRxRawAddr; /* /< Offset of SS proximity sense raw frame */
+ u16 u16_ssPrxRxFilterAddr; /* /< Offset of SS proximity sense
+ * filter frame */
+ u16 u16_ssPrxRxStrenAddr;/* /< Offset of SS proximity sense strength
+ * frame */
+ u16 u16_ssPrxRxBaselineAddr; /* /< Offset of SS proximity sense
+ * baseline frame */
+} SysInfo;
+
+/** @}*/
+
+int initCore(struct fts_ts_info *info);
+void setResetGpio(int gpio);
+int fts_system_reset(void);
+int isSystemResettedUp(void);
+int isSystemResettedDown(void);
+void setSystemResetedUp(int val);
+void setSystemResetedDown(int val);
+int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int
+ time_to_wait);
+int checkEcho(u8 *cmd, int size);
+int setScanMode(u8 mode, u8 settings);
+int setFeatures(u8 feat, u8 *settings, int size);
+int defaultSysInfo(int i2cError);
+int writeSysCmd(u8 sys_cmd, u8 *sett, int size);
+int readSysInfo(int request);
+int readConfig(u16 offset, u8 *outBuf, int len);
+int writeConfig(u16 offset, u8 *data, int len);
+int fts_disableInterrupt(void);
+int fts_disableInterruptNoSync(void);
+int fts_resetDisableIrqCount(void);
+int fts_enableInterrupt(void);
+int fts_crc_check(void);
+int requestSyncFrame(u8 type);
+int setActiveScanFrequency(u32 freq);
+int writeHostDataMemory(u8 type, u8 *data, u8 msForceLen, u8 msSenseLen,
+ u8 ssForceLen, u8 ssSenseLen, int save);
+#endif /* FTS_CORE_H */
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsError.c b/drivers/input/touchscreen/stm/fts_lib/ftsError.c
new file mode 100644
index 00000000000..2ae433715bf
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsError.c
@@ -0,0 +1,349 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS error/info kernel log reporting *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsError.c
+ * \brief Contains all the function which handle with Error conditions
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+
+#include "../fts.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsIO.h"
+#include "ftsTool.h"
+#include "ftsCompensation.h"
+
+
+static ErrorList errors;/* /< private variable which implement the Error List */
+
+/**
+ * Check if an error code is related to an I2C failure
+ * @param error error code to check
+ * @return 1 if the first level error code is I2C related otherwise 0
+ */
+int isI2cError(int error)
+{
+ if (((error & 0x000000FF) >= (ERROR_BUS_R & 0x000000FF)) &&
+ ((error & 0x000000FF) <= (ERROR_BUS_O & 0x000000FF)))
+ return 1;
+ else
+ return 0;
+}
+
+
+/**
+ * Dump in the kernel log some debug info in case of FW hang
+ * @param outBuf (optional)pointer to bytes array where to copy the debug info,
+ * if NULL the data will just printed on the kernel log
+ * @param size dimension in bytes of outBuf,
+ * if > ERROR_DUMP_ROW_SIZE*ERROR_DUMP_COL_SIZE, only the first
+ * ERROR_DUMP_ROW_SIZE*ERROR_DUMP_COL_SIZE bytes will be copied
+ * @return OK if success or an error code which specify the type of error
+ */
+int dumpErrorInfo(u8 *outBuf, int size)
+{
+ int ret, i;
+ u8 data[ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE] = { 0 };
+ u32 sign = 0;
+
+ pr_err("%s: Starting dump of error info...\n", __func__);
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, ADDR_ERROR_DUMP,
+ data, ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE,
+ DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("%s: reading data ERROR %08X\n", __func__,
+ ret);
+ return ret;
+ } else {
+ int buff_len, index = 0;
+ char *buff;
+
+ buff_len = (2 + 1) * ERROR_DUMP_COL_SIZE + 1;
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (outBuf != NULL) {
+ sign = size > ERROR_DUMP_ROW_SIZE *
+ ERROR_DUMP_COL_SIZE ? ERROR_DUMP_ROW_SIZE *
+ ERROR_DUMP_COL_SIZE : size;
+ memcpy(outBuf, data, sign);
+ pr_err("%s: error info copied in the buffer!\n",
+ __func__);
+ }
+ pr_err("%s: Error Info =\n", __func__);
+ u8ToU32(data, &sign);
+ if (sign != ERROR_DUMP_SIGNATURE)
+ pr_err("%s: Wrong Error Signature! Data may be invalid!\n",
+ __func__);
+ else
+ pr_err("%s: Error Signature OK! Data are valid!\n",
+ __func__);
+
+ for (i = 0; i < ERROR_DUMP_ROW_SIZE * ERROR_DUMP_COL_SIZE;
+ i++) {
+ index += scnprintf(buff + index, buff_len - index,
+ "%02X ", data[i]);
+ if (i % ERROR_DUMP_COL_SIZE ==
+ (ERROR_DUMP_COL_SIZE - 1)) {
+ pr_err("%s: %d) %s\n", __func__,
+ i / ERROR_DUMP_COL_SIZE,
+ buff);
+ index = 0;
+ }
+ }
+
+ kfree(buff);
+ pr_err("%s: dump of error info FINISHED!\n", __func__);
+ return OK;
+ }
+}
+
+
+/**
+ * Implement recovery strategies to be used when an error event is found
+ * while polling the FIFO
+ * @param event error event found during the polling
+ * @param size size of event
+ * @return OK if the error event doesn't require any action or the recovery
+ * strategy doesn't have any impact in the possible procedure that trigger the
+ * error,
+ * otherwise return an error code which specify the kind of error.
+ * If ERROR_HANDLER_STOP_PROC the calling function must stop!
+ */
+int errorHandler(u8 *event, int size)
+{
+ int res = OK;
+ struct fts_ts_info *info = NULL;
+
+ if (getDev() != NULL)
+ info = dev_get_drvdata(getDev());
+
+ if (info != NULL && event != NULL && size > 1 &&
+ event[0] == EVT_ID_ERROR) {
+ pr_debug("errorHandler: Starting handling...\n");
+ addErrorIntoList(event, size);
+ switch (event[1]) { /* TODO: write an error log for
+ * undefined command subtype 0xBA */
+ case EVT_TYPE_ERROR_ESD: /* esd */
+ res = fts_chip_powercycle(info);
+ if (res < OK)
+ pr_err("errorHandler: Error performing powercycle ERROR %08X\n",
+ res);
+
+ res = fts_system_reset();
+ if (res < OK)
+ pr_err("errorHandler: Cannot reset the device ERROR %08X\n",
+ res);
+ res = (ERROR_HANDLER_STOP_PROC | res);
+ break;
+
+ case EVT_TYPE_ERROR_WATCHDOG: /* watchdog */
+ dumpErrorInfo(NULL, 0);
+ res = fts_system_reset();
+ if (res < OK)
+ pr_err("errorHandler: Cannot reset the device ERROR %08X\n",
+ res);
+ res = (ERROR_HANDLER_STOP_PROC | res);
+ break;
+
+ case EVT_TYPE_ERROR_ITO_FORCETOGND:
+ pr_err("errorHandler: Force Short to GND!\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_SENSETOGND:
+ pr_err("errorHandler: Sense short to GND!\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_FORCETOVDD:
+ pr_err("errorHandler: Force short to VDD!\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_SENSETOVDD:
+ pr_err("errorHandler: Sense short to VDD!\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_FORCE_P2P:
+ pr_err("errorHandler: Force Pin to Pin Short!\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_SENSE_P2P:
+ pr_err("errorHandler: Sense Pin to Pin Short!\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_FORCEOPEN:
+ pr_err("errorHandler: Force Open !\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_SENSEOPEN:
+ pr_err("errorHandler: Sense Open !\n");
+ break;
+ case EVT_TYPE_ERROR_ITO_KEYOPEN:
+ pr_err("errorHandler: Key Open !\n");
+ break;
+
+ case EVT_TYPE_ERROR_FLASH_FAILED:
+ pr_err("errorHandler: Previous flash failed!\n");
+ info->reflash_fw = 1;
+ break;
+
+ default:
+ pr_debug("errorHandler: No Action taken!\n");
+ break;
+ }
+ pr_debug("errorHandler: handling Finished! res = %08X\n",
+ res);
+ return res;
+ } else {
+ pr_err("errorHandler: event Null or not correct size! ERROR %08X\n",
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+
+/**
+ * Add an error event into the Error List
+ * @param event error event to add
+ * @param size size of event
+ * @return OK
+ */
+int addErrorIntoList(u8 *event, int size)
+{
+ int i = 0;
+
+ pr_debug("Adding error in to ErrorList...\n");
+
+ memcpy(&errors.list[errors.last_index * FIFO_EVENT_SIZE], event, size);
+ i = FIFO_EVENT_SIZE - size;
+ if (i > 0) {
+ pr_info("Filling last %d bytes of the event with zero...\n", i);
+ memset(&errors.list[errors.last_index * FIFO_EVENT_SIZE + size],
+ 0, i);
+ }
+ pr_debug("Adding error in to ErrorList... FINISHED!\n");
+
+ errors.count += 1;
+ if (errors.count > FIFO_DEPTH)
+ pr_err("ErrorList is going in overflow... the first %d event(s) were override!\n",
+ errors.count - FIFO_DEPTH);
+ errors.last_index = (errors.last_index + 1) % FIFO_DEPTH;
+
+ return OK;
+}
+
+/**
+ * Reset the Error List setting the count and last_index to 0.
+ * @return OK
+ */
+int resetErrorList(void)
+{
+ errors.count = 0;
+ errors.last_index = 0;
+ memset(errors.list, 0, FIFO_DEPTH * FIFO_EVENT_SIZE);
+ /* if count is not considered is better reset also the list in order to
+ * avoid to read data previously copied into the list */
+ return OK;
+}
+
+/**
+ * Get the number of error events copied into the Error List
+ * @return the number of error events into the Error List
+ */
+int getErrorListCount(void)
+{
+ if (errors.count > FIFO_DEPTH)
+ return FIFO_DEPTH;
+ else
+ return errors.count;
+}
+
+/* in case of success return the index of the event found */
+/**
+ * Scroll the Error List looking for the event specified
+ * @param event_to_search event_to_search pointer to an array of int where
+ * each element correspond to a byte of the event to find. If the element
+ * of the array has value -1, the byte of the event, in the same position
+ * of the element is ignored.
+ * @param event_bytes size of event_to_search
+ * @return a value >=0 if the event is found which represent the index of
+ * the Error List where the event is located otherwise an error code
+ */
+int pollErrorList(int *event_to_search, int event_bytes)
+{
+ int i = 0, j = 0, find = 0;
+ int count = getErrorListCount();
+
+ pr_debug("Starting to poll ErrorList...\n");
+ while (find != 1 && i < count) {
+ find = 1;
+ for (j = 0; j < event_bytes; j++) {
+ if ((event_to_search[i] != -1) &&
+ ((int)errors.list[i * FIFO_EVENT_SIZE + j] !=
+ event_to_search[i])) {
+ find = 0;
+ break;
+ }
+ }
+ i++;
+ }
+ if (find == 1) {
+ pr_debug("Error Found into ErrorList!\n");
+ return i - 1; /* there is i++ at the end of the while */
+ } else {
+ pr_err("Error Not Found into ErrorList! ERROR %08X\n",
+ ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+}
+
+
+
+/**
+ * Poll the Error List looking for any error types passed in the arguments.
+ * Return at the first match!
+ * @param list pointer to a list of error types to look for
+ * @param size size of list
+ * @return error type found if success or ERROR_TIMEOUT
+ */
+int pollForErrorType(u8 *list, int size)
+{
+ int i = 0, j = 0, find = 0;
+ int count = getErrorListCount();
+
+ pr_info("%s: Starting to poll ErrorList... count = %d\n",
+ __func__, count);
+ while (find != 1 && i < count) {
+ for (j = 0; j < size; j++) {
+ if (list[j] == errors.list[i * FIFO_EVENT_SIZE + 1]) {
+ find = 1;
+ break;
+ }
+ }
+ i++;
+ }
+ if (find == 1) {
+ pr_info("%s: Error Type %02X into ErrorList!\n",
+ __func__, list[j]);
+ return list[j];
+ } else {
+ pr_err("%s: Error Type Not Found into ErrorList! ERROR %08X\n",
+ __func__, ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsError.h b/drivers/input/touchscreen/stm/fts_lib/ftsError.h
new file mode 100644
index 00000000000..f12d9eed88c
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsError.h
@@ -0,0 +1,231 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS error/info kernel log reporting *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsError.h
+ * \brief Contains all the definitions and structs which refer to Error
+ * conditions
+ */
+
+#ifndef FTS_ERROR_H
+#define FTS_ERROR_H
+
+#include "ftsHardware.h"
+#include "ftsSoftware.h"
+
+
+/** @defgroup error_codes Error Codes
+ * Error codes that can be reported by the driver functions.
+ * An error code is made up by 4 bytes, each byte indicate a logic error
+ * level.\n
+ * From the LSB to the MSB, the logic level increase going from a low level
+ * error (I2C,TIMEOUT) to an high level error (flashing procedure fail,
+ * production test fail etc)
+ * @{
+ */
+
+/* FIRST LEVEL ERROR CODE */
+/** @defgroup first_level First Level Error Code
+ * @ingroup error_codes
+ * Errors related to low level operation which are not under control of driver,
+ * such as: communication protocol (I2C/SPI), timeout, file operations ...
+ * @{
+ */
+#define OK (0x00000000) /* /< No ERROR */
+#define ERROR_ALLOC (0x80000001) /* /< allocation of memory
+ * failed */
+#define ERROR_BUS_R (0x80000002) /* /< i2c/spi read failed */
+#define ERROR_BUS_W (0x80000003) /* /< i2c/spi write failed */
+#define ERROR_BUS_WR (0x80000004) /* /< i2c/spi write/read
+ * failed */
+#define ERROR_BUS_O (0x80000005) /* /< error during
+ * opening an i2c device */
+#define ERROR_OP_NOT_ALLOW (0x80000006) /* /< operation not allowed */
+#define ERROR_TIMEOUT (0x80000007) /* /< timeout expired!
+ * exceed the max number
+ * of retries or the max
+ * waiting time */
+#define ERROR_FILE_NOT_FOUND (0x80000008) /* /< the file that i
+ * want to open is not found */
+#define ERROR_FILE_PARSE (0x80000009) /* /< error during parsing
+ * the file */
+#define ERROR_FILE_READ (0x8000000A) /* /< error during
+ * reading the file */
+#define ERROR_LABEL_NOT_FOUND (0x8000000B) /* /< label not found */
+#define ERROR_FW_NO_UPDATE (0x8000000C) /* /< fw in the chip
+ * newer than the one in
+ * the memmh */
+#define ERROR_FLASH_UNKNOWN (0x8000000D) /* /< flash status busy
+ * or unknown */
+/** @}*/
+
+/* SECOND LEVEL ERROR CODE */
+/** @defgroup second_level Second Level Error Code
+ * @ingroup error_codes
+ * Errors related to simple logic operations in the IC which require one
+ * command or which are part of a more complex procedure
+ * @{
+ */
+#define ERROR_DISABLE_INTER (0x80000200) /* /< unable to
+ * disable the
+ * interrupt */
+#define ERROR_ENABLE_INTER (0x80000300) /* /< unable to activate
+ * the interrupt */
+#define ERROR_READ_CONFIG (0x80000400) /* /< failed to read
+ * config memory */
+#define ERROR_GET_OFFSET (0x80000500) /* /< unable to
+ * read an offset from
+ * memory */
+#define ERROR_GET_FRAME_DATA (0x80000600) /* /< unable to
+ * retrieve the data of
+ * a required frame */
+#define ERROR_DIFF_DATA_TYPE (0x80000700) /* /< FW answers
+ * with an event that
+ * has a different
+ * address respect the
+ * request done */
+#define ERROR_WRONG_DATA_SIGN (0x80000800) /* /< the signature of
+ * the host data is not
+ * HEADER_SIGNATURE */
+#define ERROR_SET_SCAN_MODE_FAIL (0x80000900) /* /< setting
+ * the scanning mode
+ * failed
+ * (sense on/off
+ * etc...) */
+#define ERROR_SET_FEATURE_FAIL (0x80000A00) /* /< setting a specific
+ * feature failed */
+#define ERROR_SYSTEM_RESET_FAIL (0x80000B00) /* /< the command
+ * SYSTEM RESET
+ * failed */
+#define ERROR_FLASH_NOT_READY (0x80000C00) /* /< flash status not
+ * ready within a
+ * timeout */
+#define ERROR_FW_VER_READ (0x80000D00) /* /< unable to retrieve
+ * fw_vers or the
+ * config_id */
+#define ERROR_GESTURE_ENABLE_FAIL (0x80000E00) /* /< unable to
+ * enable/disable
+ * the gesture */
+#define ERROR_GESTURE_START_ADD (0x80000F00) /* /< unable to start to
+ * add custom gesture */
+#define ERROR_GESTURE_FINISH_ADD (0x80001000) /* /< unable to finish
+ * to add custom gesture
+ */
+#define ERROR_GESTURE_DATA_ADD (0x80001100) /* /< unable to add
+ * custom gesture data
+ * */
+#define ERROR_GESTURE_REMOVE (0x80001200) /* /< unable to remove
+ * custom gesture data
+ * */
+#define ERROR_FEATURE_ENABLE_DISABLE (0x80001300) /* /< unable to
+ * enable/disable a
+ * feature mode in
+ * the IC */
+#define ERROR_NOISE_PARAMETERS (0x80001400) /* /< unable to set/read
+ * noise parameter in
+ * the IC */
+#define ERROR_CH_LEN (0x80001500) /* /< unable to retrieve
+ * the force and/or
+ * sense length */
+/** @}*/
+
+/* THIRD LEVEL ERROR CODE */
+/** @defgroup third_level Third Level Error Code
+ * @ingroup error_codes
+ * Errors related to logic operations in the IC which require more
+ * commands/steps or which are part of a more complex procedure
+ * @{
+ */
+#define ERROR_REQU_COMP_DATA (0x80010000) /* /< compensation data
+ * request failed */
+#define ERROR_REQU_DATA (0x80020000) /* /< data request
+ * failed */
+#define ERROR_COMP_DATA_HEADER (0x80030000) /* /< unable to retrieve
+ * the compensation data
+ * header */
+#define ERROR_COMP_DATA_GLOBAL (0x80040000) /* /< unable to retrieve
+ * the global
+ * compensation data */
+#define ERROR_COMP_DATA_NODE (0x80050000) /* /< unable to retrieve
+ * the compensation data
+ * for each node */
+#define ERROR_TEST_CHECK_FAIL (0x80060000) /* /< check of
+ * production limits or
+ * of fw answers failed */
+#define ERROR_MEMH_READ (0x80070000) /* /< memh reading
+ * failed */
+#define ERROR_FLASH_BURN_FAILED (0x80080000) /* /< flash burn failed */
+#define ERROR_MS_TUNING (0x80090000) /* /< ms tuning failed */
+#define ERROR_SS_TUNING (0x800A0000) /* /< ss tuning failed */
+#define ERROR_LP_TIMER_TUNING (0x800B0000) /* /< lp timer
+ * calibration failed */
+#define ERROR_SAVE_CX_TUNING (0x800C0000) /* /< save cx data to
+ * flash failed */
+#define ERROR_HANDLER_STOP_PROC (0x800D0000) /* /< stop the poll of the FIFO
+ * if particular errors are
+ * found */
+#define ERROR_CHECK_ECHO_FAIL (0x800E0000) /* /< unable to retrieve
+ * echo event */
+#define ERROR_GET_FRAME (0x800F0000) /* /< unable to get frame */
+/** @}*/
+
+/* FOURTH LEVEL ERROR CODE */
+/** @defgroup fourth_level Fourth Level Error Code
+ * @ingroup error_codes
+ * Errors related to the highest logic operations in the IC which have an
+ * important impact on the driver flow or which require several commands and
+ * steps to be executed
+ * @{
+ */
+#define ERROR_PROD_TEST_DATA (0x81000000) /* /< production data
+ * test failed */
+#define ERROR_FLASH_PROCEDURE (0x82000000) /* /< fw update
+ * procedure failed */
+#define ERROR_PROD_TEST_ITO (0x83000000) /* /< production
+ * ito test failed */
+#define ERROR_PROD_TEST_INITIALIZATION (0x84000000) /* /< production
+ * initialization
+ * test failed */
+#define ERROR_GET_INIT_STATUS (0x85000000) /* /< mismatch of the MS or
+ * SS tuning_version */
+/** @}*/
+
+/** @}*/ /* end of error_commands section */
+
+/**
+ * Struct which store an ordered list of the errors events encountered during
+ *the polling of a FIFO.
+ * The max number of error events that can be stored is equal to FIFO_DEPTH
+ */
+typedef struct {
+ u8 list[FIFO_DEPTH * FIFO_EVENT_SIZE]; /* /< byte array which contains
+ * the series of error events
+ * encountered from the last
+ * reset of the list. */
+ int count; /* /< number of error events stored in the list */
+ int last_index; /* /< index of the list where will be stored the next
+ * error event. Subtract -1 to have the index of the
+ * last error event! */
+} ErrorList;
+
+int isI2cError(int error);
+int dumpErrorInfo(u8 *outBuf, int size);
+int errorHandler(u8 *event, int size);
+int addErrorIntoList(u8 *event, int size);
+int getErrorListCount(void);
+int resetErrorList(void);
+int pollErrorList(int *event_to_search, int event_bytes);
+int pollForErrorType(u8 *list, int size);
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFlash.c b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.c
new file mode 100644
index 00000000000..1cafa1dcd5e
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.c
@@ -0,0 +1,991 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS API for Flashing the IC *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+
+/*!
+ * \file ftsFlash.c
+ * \brief Contains all the functions to handle the FW update process
+ */
+
+#include "ftsCore.h"
+#include "ftsCompensation.h"
+#include "ftsError.h"
+#include "ftsFlash.h"
+#include "ftsFrame.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTest.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "../fts.h" /* needed for including the define FW_H_FILE */
+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/firmware.h>
+
+
+#ifdef FW_H_FILE
+#include "../fts_fw.h"
+#endif
+
+
+extern SysInfo systemInfo; /* /< forward declaration of the global variable
+ * of containing System Info Data */
+
+
+/**
+ * Retrieve the actual FW data from the system (bin file or header file)
+ * @param pathToFile name of FW file to load or "NULL" if the FW data should be
+ * loaded by a .h file
+ * @param data pointer to the pointer which will contains the FW data
+ * @param size pointer to a variable which will contain the size of the loaded
+ * data
+ * @return OK if success or an error code which specify the type of error
+ */
+int getFWdata(const char *pathToFile, u8 **data, int *size)
+{
+ const struct firmware *fw = NULL;
+ struct device *dev = getDev();
+ struct fts_ts_info *info = NULL;
+ int res, from = 0;
+ char *path = (char *)pathToFile;
+
+ if (dev != NULL)
+ info = dev_get_drvdata(dev);
+
+ pr_info("getFWdata starting ...\n");
+ if (strncmp(pathToFile, "NULL", 4) == 0) {
+ from = 1;
+ if (info != NULL && info->board->fw_name)
+ path = (char *)info->board->fw_name;
+ else
+ path = PATH_FILE_FW;
+ }
+ /* keep the switch case because if the argument passed is null but
+ * the option from .h is not set we still try to load from bin */
+ switch (from) {
+#ifdef FW_H_FILE
+ case 1:
+ pr_debug("Read FW from .h file!\n");
+ *size = FW_SIZE_NAME;
+ *data = (u8 *)kmalloc((*size) * sizeof(u8), GFP_KERNEL);
+ if (*data == NULL) {
+ pr_err("getFWdata: Impossible to allocate memory! ERROR %08X\n",
+ ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+ memcpy(*data, (u8 *)FW_ARRAY_NAME, (*size));
+
+ break;
+#endif
+ default:
+ pr_debug("Read FW from BIN file %s !\n", path);
+
+ if (dev != NULL) {
+ res = request_firmware(&fw, path, dev);
+ if (res == 0) {
+ *size = fw->size;
+ *data = (u8 *)kmalloc((*size) * sizeof(u8),
+ GFP_KERNEL);
+ if (*data == NULL) {
+ pr_err("getFWdata: Impossible to allocate memory! ERROR %08X\n",
+ ERROR_ALLOC);
+ release_firmware(fw);
+ return ERROR_ALLOC;
+ }
+ memcpy(*data, (u8 *)fw->data, (*size));
+ release_firmware(fw);
+ } else {
+ pr_err("getFWdata: No File found! ERROR %08X\n",
+ ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+ } else {
+ pr_err("getFWdata: No device found! ERROR %08X\n",
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+ }
+
+ pr_debug("getFWdata Finished!\n");
+ return OK;
+}
+
+
+/**
+ * Perform all the steps to read the FW that should be burnt in the IC from
+ * the system and parse it in order to fill a Firmware struct with the relevant
+ * info
+ * @param path name of FW file to load or "NULL" if the FW data should be
+ * loaded by a .h file
+ * @param fw pointer to a Firmware variable which will contains the FW data and
+ * info
+ * @param keep_cx if 1, the CX area will be loaded otherwise will be skipped
+ * @return OK if success or an error code which specify the type of error
+ */
+int readFwFile(const char *path, Firmware *fw, int keep_cx)
+{
+ int res;
+ int orig_size;
+ u8 *orig_data = NULL;
+
+
+ res = getFWdata(path, &orig_data, &orig_size);
+ if (res < OK) {
+ pr_err("readFwFile: impossible retrieve FW... ERROR %08X\n",
+ ERROR_MEMH_READ);
+ return res | ERROR_MEMH_READ;
+ }
+ res = parseBinFile(orig_data, orig_size, fw, keep_cx);
+ if (res < OK) {
+ pr_err("readFwFile: impossible parse ERROR %08X\n",
+ ERROR_MEMH_READ);
+ return res | ERROR_MEMH_READ;
+ }
+
+ return OK;
+}
+
+/**
+ * Perform all the steps necessary to burn the FW into the IC
+ * @param path name of FW file to load or "NULL" if the FW data should be
+ * loaded by a .h file
+ * @param force if 1, the flashing procedure will be forced and executed
+ * regardless the additional info, otherwise the FW in the file will be burnt
+ * only if it is newer than the one running in the IC
+ * @param keep_cx if 1, the CX area will be loaded and burnt otherwise will be
+ * skipped and the area will be untouched
+ * @return OK if success or an error code which specify the type of error
+ */
+int flashProcedure(const char *path, int force, int keep_cx)
+{
+ Firmware fw;
+ int res;
+
+ fw.data = NULL;
+ pr_debug("Reading Fw file...\n");
+ res = readFwFile(path, &fw, keep_cx);
+ if (res < OK) {
+ pr_err("flashProcedure: ERROR %08X\n",
+ (res | ERROR_FLASH_PROCEDURE));
+ kfree(fw.data);
+ return res | ERROR_FLASH_PROCEDURE;
+ }
+ pr_debug("Fw file read COMPLETED!\n");
+
+ pr_info("Starting flashing procedure...\n");
+ res = flash_burn(fw, force, keep_cx);
+ if (res < OK && res != (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED)) {
+ pr_err("flashProcedure: ERROR %08X\n",
+ ERROR_FLASH_PROCEDURE);
+ kfree(fw.data);
+ return res | ERROR_FLASH_PROCEDURE;
+ }
+ pr_info("flashing procedure Finished!\n");
+ kfree(fw.data);
+
+ return res;
+}
+
+/**
+ * Poll the Flash Status Registers after the execution of a command to check
+ * if the Flash becomes ready within a timeout
+ * @param type register to check according to the previous command sent
+ * @return OK if success or an error code which specify the type of error
+ */
+int wait_for_flash_ready(u8 type)
+{
+ u8 cmd[5] = { FTS_CMD_HW_REG_R, 0x20, 0x00, 0x00, type };
+
+ u8 readData[2] = { 0 };
+ int i, res = -1;
+
+ pr_debug("Waiting for flash ready ...\n");
+ for (i = 0; i < FLASH_RETRY_COUNT && res != 0; i++) {
+ res = fts_writeRead(cmd, ARRAY_SIZE(cmd), readData, 2);
+ if (res < OK)
+ pr_err("wait_for_flash_ready: ERROR %08X\n",
+ ERROR_BUS_W);
+ else {
+#ifdef I2C_INTERFACE /* in case of spi there is a dummy byte */
+ res = readData[0] & 0x80;
+#else
+ res = readData[1] & 0x80;
+#endif
+
+ pr_debug("flash status = %d\n", res);
+ }
+ mdelay(FLASH_WAIT_BEFORE_RETRY);
+ }
+
+ if (i == FLASH_RETRY_COUNT && res != 0) {
+ pr_err("Wait for flash TIMEOUT! ERROR %08X\n",
+ ERROR_TIMEOUT);
+ return ERROR_TIMEOUT;
+ }
+
+ pr_debug("Flash READY!\n");
+ return OK;
+}
+
+
+/**
+ * Put the M3 in hold
+ * @return OK if success or an error code which specify the type of error
+ */
+int hold_m3(void)
+{
+ int ret;
+ u8 cmd[1] = { 0x01 };
+
+ pr_debug("Command m3 hold...\n");
+ ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG,
+ ADDR_SYSTEM_RESET, cmd, 1);
+ if (ret < OK) {
+ pr_err("hold_m3: ERROR %08X\n", ret);
+ return ret;
+ }
+ pr_debug("Hold M3 DONE!\n");
+
+#if !defined(I2C_INTERFACE) && defined(SPI4_WIRE)
+ /* configure manually SPI4 because when no fw is running the chip use
+ * SPI3 by default */
+ pr_debug("Setting SPI4 mode...\n");
+ cmd[0] = 0x10;
+ ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG,
+ ADDR_GPIO_DIRECTION, cmd, 1);
+ if (ret < OK) {
+ pr_err("hold_m3: can not set gpio dir ERROR %08X\n", ret);
+ return ret;
+ }
+
+ cmd[0] = 0x02;
+ ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG,
+ ADDR_GPIO_PULLUP, cmd, 1);
+ if (ret < OK) {
+ pr_err("hold_m3: can not set gpio pull-up ERROR %08X\n", ret);
+ return ret;
+ }
+
+ cmd[0] = 0x07;
+ ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG,
+ ADDR_GPIO_CONFIG_REG2, cmd, 1);
+ if (ret < OK) {
+ pr_err("hold_m3: can not set gpio config ERROR %08X\n", ret);
+ return ret;
+ }
+
+ cmd[0] = 0x30;
+ ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG,
+ ADDR_GPIO_CONFIG_REG0, cmd, 1);
+ if (ret < OK) {
+ pr_err("hold_m3: can not set gpio config ERROR %08X\n", ret);
+ return ret;
+ }
+
+ cmd[0] = SPI4_MASK;
+ ret = fts_writeU8UX(FTS_CMD_HW_REG_W, ADDR_SIZE_HW_REG, ADDR_ICR, cmd,
+ 1);
+ if (ret < OK) {
+ pr_err("hold_m3: can not set spi4 mode ERROR %08X\n", ret);
+ return ret;
+ }
+ mdelay(1); /* wait for the GPIO to stabilize */
+#endif
+
+ return OK;
+}
+
+
+
+
+/**
+ * Parse the raw data read from a FW file in order to fill properly the fields
+ * of a Firmware variable
+ * @param fw_data raw FW data loaded from system
+ * @param fw_size size of fw_data
+ * @param fwData pointer to a Firmware variable which will contain the
+ * processed data
+ * @param keep_cx if 1, the CX area will be loaded and burnt otherwise will be
+ * skipped and the area will be untouched
+ * @return OK if success or an error code which specify the type of error
+ */
+int parseBinFile(u8 *fw_data, int fw_size, Firmware *fwData, int keep_cx)
+{
+ int dimension, index = 0;
+ u32 temp;
+ int res, i;
+ char buff[(2 + 1) * EXTERNAL_RELEASE_INFO_SIZE + 1];
+ int buff_len = sizeof(buff);
+ int buff_index = 0;
+
+ /* the file should contain at least the header plus the content_crc */
+ if (fw_size < FW_HEADER_SIZE + FW_BYTES_ALIGN || fw_data == NULL) {
+ pr_err("parseBinFile: Read only %d instead of %d... ERROR %08X\n",
+ fw_size, FW_HEADER_SIZE + FW_BYTES_ALIGN,
+ ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ } else {
+ /* start parsing of bytes */
+ u8ToU32(&fw_data[index], &temp);
+ if (temp != FW_HEADER_SIGNATURE) {
+ pr_err("parseBinFile: Wrong Signature %08X ... ERROR %08X\n",
+ temp, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+ pr_debug("parseBinFile: Fw Signature OK!\n");
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ if (temp != FW_FTB_VER) {
+ pr_err("parseBinFile: Wrong ftb_version %08X ... ERROR %08X\n",
+ temp, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+ pr_debug("parseBinFile: ftb_version OK!\n");
+ index += FW_BYTES_ALIGN;
+ if (fw_data[index] != DCHIP_ID_0 || fw_data[index + 1] !=
+ DCHIP_ID_1) {
+ pr_err("parseBinFile: Wrong target %02X != %02X %02X != %02X ... ERROR %08X\n",
+ fw_data[index], DCHIP_ID_0,
+ fw_data[index + 1],
+ DCHIP_ID_1, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ pr_debug("parseBinFile: FILE SVN REV = %08X\n", temp);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ fwData->fw_ver = temp;
+ pr_debug("parseBinFile: FILE Fw Version = %04X\n",
+ fwData->fw_ver);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ pr_debug("parseBinFile: FILE Config Project ID = %08X\n", temp);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ fwData->config_ver = temp;
+ pr_debug("parseBinFile: FILE Config Version = %08X\n",
+ fwData->config_ver);
+
+ index += FW_BYTES_ALIGN * 2; /* skip reserved data */
+
+ index += FW_BYTES_ALIGN;
+ for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
+ fwData->externalRelease[i] = fw_data[index++];
+ buff_index += scnprintf(buff + buff_index,
+ buff_len - buff_index,
+ "%02X ",
+ fwData->externalRelease[i]);
+ }
+ pr_debug("parseBinFile: File External Release = %s\n", buff);
+
+ /* index+=FW_BYTES_ALIGN; */
+ u8ToU32(&fw_data[index], &temp);
+ fwData->sec0_size = temp;
+ pr_debug("parseBinFile: sec0_size = %08X (%d bytes)\n",
+ fwData->sec0_size, fwData->sec0_size);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ fwData->sec1_size = temp;
+ pr_debug("parseBinFile: sec1_size = %08X (%d bytes)\n",
+ fwData->sec1_size, fwData->sec1_size);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ fwData->sec2_size = temp;
+ pr_debug("parseBinFile: sec2_size = %08X (%d bytes)\n",
+ fwData->sec2_size, fwData->sec2_size);
+
+ index += FW_BYTES_ALIGN;
+ u8ToU32(&fw_data[index], &temp);
+ fwData->sec3_size = temp;
+ pr_debug("parseBinFile: sec3_size = %08X (%d bytes)\n",
+ fwData->sec3_size, fwData->sec3_size);
+
+ index += FW_BYTES_ALIGN;/* skip header crc */
+
+ /* if (!keep_cx) */
+ /* { */
+ dimension = fwData->sec0_size + fwData->sec1_size +
+ fwData->sec2_size + fwData->sec3_size;
+ temp = fw_size;
+ /*} else
+ * {
+ * dimension = fwData->sec0_size + fwData->sec1_size;
+ * temp = fw_size - fwData->sec2_size - fwData->sec3_size;
+ * fwData->sec2_size = 0;
+ * fwData->sec3_size = 0;
+ * }*/
+
+ if (dimension + FW_HEADER_SIZE + FW_BYTES_ALIGN != temp) {
+ pr_err("parseBinFile: Read only %d instead of %d... ERROR %08X\n",
+ fw_size, dimension + FW_HEADER_SIZE +
+ FW_BYTES_ALIGN, ERROR_FILE_PARSE);
+ res = ERROR_FILE_PARSE;
+ goto END;
+ }
+
+ fwData->data = (u8 *)kmalloc(dimension * sizeof(u8),
+ GFP_KERNEL);
+ if (fwData->data == NULL) {
+ pr_err("parseBinFile: ERROR %08X\n", ERROR_ALLOC);
+ res = ERROR_ALLOC;
+ goto END;
+ }
+
+ index += FW_BYTES_ALIGN;
+ memcpy(fwData->data, &fw_data[index], dimension);
+ if (fwData->sec2_size != 0)
+ u8ToU16(&fwData->data[fwData->sec0_size +
+ fwData->sec1_size +
+ FW_CX_VERSION], &fwData->cx_ver);
+
+ else {
+ pr_err("parseBinFile: Initialize cx_ver to default value!\n");
+ fwData->cx_ver = systemInfo.u16_cxVer;
+ }
+
+ pr_debug("parseBinFile: CX Version = %04X\n", fwData->cx_ver);
+
+ fwData->data_size = dimension;
+
+ pr_debug("READ FW DONE %d bytes!\n", fwData->data_size);
+ res = OK;
+ goto END;
+ }
+
+END:
+ kfree(fw_data);
+ return res;
+}
+
+/**
+ * Unlock the flash to be programmed
+ * @return OK if success or an error code which specify the type of error
+ */
+int flash_unlock(void)
+{
+ u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00,
+ FLASH_UNLOCK_CODE0, FLASH_UNLOCK_CODE1 };
+
+ pr_debug("Command unlock ...\n");
+ if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) {
+ pr_err("flash_unlock: ERROR %08X\n", ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ pr_debug("Unlock flash DONE!\n");
+
+ return OK;
+}
+
+/**
+ * Unlock the flash to be erased
+ * @return OK if success or an error code which specify the type of error
+ */
+int flash_erase_unlock(void)
+{
+ u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00,
+ 0x00,
+ FLASH_ERASE_UNLOCK_CODE0, FLASH_ERASE_UNLOCK_CODE1 };
+
+ pr_debug("Try to erase unlock flash...\n");
+
+ pr_debug("Command erase unlock ...\n");
+ if (fts_write(cmd, ARRAY_SIZE(cmd)) < 0) {
+ pr_err("flash_erase_unlock: ERROR %08X\n", ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ pr_debug("Erase Unlock flash DONE!\n");
+
+ return OK;
+}
+
+/**
+ * Erase the full flash
+ * @return OK if success or an error code which specify the type of error
+ */
+int flash_full_erase(void)
+{
+ int status;
+
+ u8 cmd1[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00,
+ FLASH_ERASE_CODE0 + 1, 0x00 };
+ u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00,
+ FLASH_ERASE_CODE0, FLASH_ERASE_CODE1 };
+
+ if (fts_write(cmd1, ARRAY_SIZE(cmd1)) < OK) {
+ pr_err("flash_erase_page_by_page: ERROR %08X\n", ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ pr_debug("Command full erase sent ...\n");
+ if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) {
+ pr_err("flash_full_erase: ERROR %08X\n", ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ status = wait_for_flash_ready(FLASH_ERASE_CODE0);
+
+ if (status != OK) {
+ pr_err("flash_full_erase: ERROR %08X\n", ERROR_FLASH_NOT_READY);
+ return status | ERROR_FLASH_NOT_READY;
+ /* Flash not ready within the chosen time, better exit! */
+ }
+
+ pr_debug("Full Erase flash DONE!\n");
+
+ return OK;
+}
+
+/**
+ * Erase the flash page by page, giving the possibility to skip the CX area and
+ * maintain therefore its value
+ * @param keep_cx if SKIP_PANEL_INIT the Panel Init pages will be skipped,
+ * if > SKIP_PANEL_CX_INIT Cx and Panel Init pages otherwise all the pages will
+ * be deleted
+ * @return OK if success or an error code which specify the type of error
+ */
+int flash_erase_page_by_page(ErasePage keep_cx)
+{
+ u8 status, i = 0;
+ u8 cmd1[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00,
+ FLASH_ERASE_CODE0 + 1, 0x00 };
+ u8 cmd[6] = { FTS_CMD_HW_REG_W, 0x20, 0x00, 0x00, FLASH_ERASE_CODE0,
+ 0xA0 };
+ u8 cmd2[9] = { FTS_CMD_HW_REG_W, 0x20, 0x00,
+ 0x01, 0x28,
+ 0xFF,
+ 0xFF, 0xFF, 0xFF };
+ u8 mask[4] = { 0 };
+ char buff[(2 + 1) * 4 + 1];
+ int buff_len = sizeof(buff);
+ int index = 0;
+
+ for (i = FLASH_CX_PAGE_START; i <= FLASH_CX_PAGE_END && keep_cx >=
+ SKIP_PANEL_CX_INIT; i++) {
+ pr_debug("Skipping erase CX page %d!\n", i);
+ fromIDtoMask(i, mask, 4);
+ }
+
+
+ for (i = FLASH_PANEL_PAGE_START; i <= FLASH_PANEL_PAGE_END && keep_cx >=
+ SKIP_PANEL_INIT; i++) {
+ pr_debug("Skipping erase Panel Init page %d!\n", i);
+ fromIDtoMask(i, mask, 4);
+ }
+
+ for (i = 0; i < 4; i++) {
+ cmd2[5 + i] = cmd2[5 + i] & (~mask[i]);
+ index += scnprintf(buff + index, buff_len - index,
+ "%02X ", cmd2[5 + i]);
+ }
+ pr_debug("Setting the page mask = %s\n", buff);
+
+ pr_debug("Writing page mask...\n");
+ if (fts_write(cmd2, ARRAY_SIZE(cmd2)) < OK) {
+ pr_err("flash_erase_page_by_page: Page mask ERROR %08X\n",
+ ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ if (fts_write(cmd1, ARRAY_SIZE(cmd1)) < OK) {
+ pr_err("flash_erase_page_by_page: Disable info ERROR %08X\n",
+ ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ pr_debug("Command erase pages sent ...\n");
+ if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) {
+ pr_err("flash_erase_page_by_page: Erase ERROR %08X\n",
+ ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ status = wait_for_flash_ready(FLASH_ERASE_CODE0);
+
+ if (status != OK) {
+ pr_err("flash_erase_page_by_page: ERROR %08X\n",
+ ERROR_FLASH_NOT_READY);
+ return status | ERROR_FLASH_NOT_READY;
+ /* Flash not ready within the chosen time, better exit! */
+ }
+
+ pr_debug("Erase flash page by page DONE!\n");
+
+ return OK;
+}
+
+/**
+ * Start the DMA procedure which actually transfer and burn the data loaded
+ * from memory into the Flash
+ * @return OK if success or an error code which specify the type of error
+ */
+int start_flash_dma(void)
+{
+ int status;
+ u8 cmd[6] = { FLASH_CMD_WRITE_REGISTER, 0x20, 0x00, 0x00,
+ FLASH_DMA_CODE0, FLASH_DMA_CODE1 };
+
+ /* write the command to erase the flash */
+
+ pr_debug("Command flash DMA ...\n");
+ if (fts_write(cmd, ARRAY_SIZE(cmd)) < OK) {
+ pr_err("start_flash_dma: ERROR %08X\n", ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ status = wait_for_flash_ready(FLASH_DMA_CODE0);
+
+ if (status != OK) {
+ pr_err("start_flash_dma: ERROR %08X\n", ERROR_FLASH_NOT_READY);
+ return status | ERROR_FLASH_NOT_READY;
+ /* Flash not ready within the chosen time, better exit! */
+ }
+
+ pr_debug("flash DMA DONE!\n");
+
+ return OK;
+}
+
+/**
+ * Copy the FW data that should be burnt in the Flash into the memory and then
+ * the DMA will take care about burning it into the Flash
+ * @param address address in memory where to copy the data, possible values
+ * are FLASH_ADDR_CODE, FLASH_ADDR_CONFIG, FLASH_ADDR_CX
+ * @param data pointer to an array of byte which contain the data that should
+ * be copied into the memory
+ * @param size size of data
+ * @return OK if success or an error code which specify the type of error
+ */
+int fillFlash(u32 address, u8 *data, int size)
+{
+ int remaining = size, index = 0;
+ int toWrite = 0;
+ int byteBlock = 0;
+ int wheel = 0;
+ u32 addr = 0;
+ int res;
+ int delta;
+ u8 *buff = NULL;
+
+ buff = kmalloc(max(DMA_CHUNK + 5, 12), GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("fillFlash: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ while (remaining > 0) {
+ byteBlock = 0;
+ addr = 0x00100000;
+
+ while (byteBlock < FLASH_CHUNK && remaining > 0) {
+ index = 0;
+ if (remaining >= DMA_CHUNK) {
+ if ((byteBlock + DMA_CHUNK) <= FLASH_CHUNK) {
+ /* pr_err("fillFlash: 1\n"); */
+ toWrite = DMA_CHUNK;
+ remaining -= DMA_CHUNK;
+ byteBlock += DMA_CHUNK;
+ } else {
+ /* pr_err("fillFlash: 2\n); */
+ delta = FLASH_CHUNK - byteBlock;
+ toWrite = delta;
+ remaining -= delta;
+ byteBlock += delta;
+ }
+ } else {
+ if ((byteBlock + remaining) <= FLASH_CHUNK) {
+ /* pr_err("fillFlash: 3\n"); */
+ toWrite = remaining;
+ byteBlock += remaining;
+ remaining = 0;
+ } else {
+ /* pr_err("fillFlash: 4\n"); */
+ delta = FLASH_CHUNK - byteBlock;
+ toWrite = delta;
+ remaining -= delta;
+ byteBlock += delta;
+ }
+ }
+
+ buff[index++] = FTS_CMD_HW_REG_W;
+ buff[index++] = (u8)((addr & 0xFF000000) >> 24);
+ buff[index++] = (u8)((addr & 0x00FF0000) >> 16);
+ buff[index++] = (u8)((addr & 0x0000FF00) >> 8);
+ buff[index++] = (u8)(addr & 0x000000FF);
+
+ memcpy(&buff[index], data, toWrite);
+ /* pr_err("Command = %02X , address = %02X %02X
+ * , bytes = %d, data = %02X %02X, %02X %02X\n",
+ * buff[0], buff[1], buff[2], toWrite, buff[3],
+ * buff[4], buff[3 + toWrite-2],
+ * buff[3 + toWrite-1]); */
+ if (fts_write_heap(buff, index + toWrite) < OK) {
+ pr_err("fillFlash: ERROR %08X\n", ERROR_BUS_W);
+ kfree(buff);
+ return ERROR_BUS_W;
+ }
+
+ /* mdelay(5); */
+ addr += toWrite;
+ data += toWrite;
+ }
+
+
+ /* configuring the DMA */
+ byteBlock = byteBlock / 4 - 1;
+ index = 0;
+
+ buff[index++] = FLASH_CMD_WRITE_REGISTER;
+ buff[index++] = 0x20;
+ buff[index++] = 0x00;
+ buff[index++] = 0x00;
+ buff[index++] = FLASH_DMA_CONFIG;
+ buff[index++] = 0x00;
+ buff[index++] = 0x00;
+
+ addr = address + ((wheel * FLASH_CHUNK) / 4);
+ buff[index++] = (u8)((addr & 0x000000FF));
+ buff[index++] = (u8)((addr & 0x0000FF00) >> 8);
+ buff[index++] = (u8)(byteBlock & 0x000000FF);
+ buff[index++] = (u8)((byteBlock & 0x0000FF00) >> 8);
+ buff[index++] = 0x00;
+
+ pr_debug("DMA Command = %02X , address = %02X %02X, words = %02X %02X\n",
+ buff[0], buff[8], buff[7], buff[10], buff[9]);
+
+ if (fts_write_heap(buff, index) < OK) {
+ pr_err("Error during filling Flash! ERROR %08X\n",
+ ERROR_BUS_W);
+ kfree(buff);
+ return ERROR_BUS_W;
+ }
+
+ res = start_flash_dma();
+ if (res < OK) {
+ pr_err("Error during flashing DMA! ERROR %08X\n", res);
+ kfree(buff);
+ return res;
+ }
+ wheel++;
+ }
+ kfree(buff);
+ return OK;
+}
+
+
+/*
+ * Execute the procedure to burn a FW on FTM5/FTI IC
+ *
+ * @param fw - structure which contain the FW to be burnt
+ * @param force_burn - if >0, the flashing procedure will be forced and
+ * executed
+ * regardless the additional info, otherwise the FW in the file will be
+ * burned only if it is different from the one running in the IC
+ * @param keep_cx - if 1, the function preserves the CX/Panel Init area.
+ * Otherwise, it will be cleared.
+ *
+ * @return OK if success or an error code which specifies the type of error
+ * encountered
+ */
+int flash_burn(Firmware fw, int force_burn, int keep_cx)
+{
+ int res;
+
+ if (!force_burn) {
+ /* Compare firmware, config, and CX versions */
+ if (fw.fw_ver != (uint32_t)systemInfo.u16_fwVer ||
+ fw.config_ver != (uint32_t)systemInfo.u16_cfgVer ||
+ fw.cx_ver != (uint32_t)systemInfo.u16_cxVer)
+ goto start;
+
+ for (res = EXTERNAL_RELEASE_INFO_SIZE - 1; res >= 0; res--) {
+ if (fw.externalRelease[res] !=
+ systemInfo.u8_releaseInfo[res])
+ goto start;
+ }
+
+ pr_debug("flash_burn: Firmware in the chip matches the firmware to flash! NO UPDATE ERROR %08X\n",
+ ERROR_FW_NO_UPDATE);
+ return ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED;
+ } else if (force_burn == CRC_CX && fw.sec2_size == 0) {
+ /* burn procedure to update the CX memory, if not present just
+ * skip it!
+ */
+ for (res = EXTERNAL_RELEASE_INFO_SIZE - 1; res >= 0; res--) {
+ if (fw.externalRelease[res] !=
+ systemInfo.u8_releaseInfo[res]) {
+ /* Avoid loading the CX because it is missing
+ * in the bin file, it just need to update
+ * to last fw+cfg because a new release */
+ force_burn = 0;
+ goto start;
+ }
+ }
+ pr_debug("flash_burn: CRC in CX but fw does not contain CX data! NO UPDATE ERROR %08X\n",
+ ERROR_FW_NO_UPDATE);
+ return ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED;
+ }
+
+ /* Programming procedure start */
+start:
+ pr_debug("Programming Procedure for flashing started:\n");
+
+ pr_debug(" 1) SYSTEM RESET:\n");
+ res = fts_system_reset();
+ if (res < 0) {
+ pr_err(" system reset FAILED!\n");
+ /* If there is no firmware, there is no controller ready event
+ * and there will be a timeout, we can keep going. But if
+ * there is an I2C error, we must exit.
+ */
+ if (res != (ERROR_SYSTEM_RESET_FAIL | ERROR_TIMEOUT))
+ return res | ERROR_FLASH_BURN_FAILED;
+ } else
+ pr_debug(" system reset COMPLETED!\n");
+
+ msleep(100); /* required by HW for safe flash procedure */
+
+ pr_debug(" 2) HOLD M3 :\n");
+
+ res = hold_m3();
+ if (res < OK) {
+ pr_err(" hold_m3 FAILED!\n");
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" hold_m3 COMPLETED!\n");
+
+ pr_debug(" 3) FLASH UNLOCK:\n");
+ res = flash_unlock();
+ if (res < OK) {
+ pr_err(" flash unlock FAILED! ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" flash unlock COMPLETED!\n");
+
+ pr_debug(" 4) FLASH ERASE UNLOCK:\n");
+ res = flash_erase_unlock();
+ if (res < 0) {
+ pr_err(" flash unlock FAILED! ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" flash unlock COMPLETED!\n");
+
+ pr_debug(" 5) FLASH ERASE:\n");
+ if (keep_cx > 0) {
+ if (fw.sec2_size != 0)
+ res = flash_erase_page_by_page(SKIP_PANEL_INIT);
+ else
+ res = flash_erase_page_by_page(SKIP_PANEL_CX_INIT);
+ } else {
+ res = flash_erase_page_by_page(SKIP_PANEL_INIT);
+ if (fw.sec2_size == 0)
+ pr_err("WARNING!!! Erasing CX memory but no CX in fw file! touch will not work right after fw update!\n");
+ }
+
+ if (res < OK) {
+ pr_err(" flash erase FAILED! ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" flash erase COMPLETED!\n");
+
+ pr_debug(" 6) LOAD PROGRAM:\n");
+ res = fillFlash(FLASH_ADDR_CODE, &fw.data[0], fw.sec0_size);
+ if (res < OK) {
+ pr_err(" load program ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" load program DONE!\n");
+
+ pr_debug(" 7) LOAD CONFIG:\n");
+ res = fillFlash(FLASH_ADDR_CONFIG, &(fw.data[fw.sec0_size]),
+ fw.sec1_size);
+ if (res < OK) {
+ pr_err(" load config ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" load config DONE!\n");
+
+ if (fw.sec2_size != 0 && (force_burn == CRC_CX || keep_cx <= 0)) {
+ pr_debug(" 7.1) LOAD CX:\n");
+ res = fillFlash(FLASH_ADDR_CX,
+ &(fw.data[fw.sec0_size + fw.sec1_size]),
+ fw.sec2_size);
+ if (res < OK) {
+ pr_err(" load cx ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" load cx DONE!\n");
+ }
+
+ pr_debug(" Flash burn COMPLETED!\n");
+
+ pr_debug(" 8) SYSTEM RESET:\n");
+ res = fts_system_reset();
+ if (res < 0) {
+ pr_err(" system reset FAILED! ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+ pr_debug(" system reset COMPLETED!\n");
+
+ pr_debug(" 9) FINAL CHECK:\n");
+ res = readSysInfo(0);
+ if (res < 0) {
+ pr_err("flash_burn: Unable to retrieve Chip INFO! ERROR %08X\n",
+ ERROR_FLASH_BURN_FAILED);
+ return res | ERROR_FLASH_BURN_FAILED;
+ }
+
+ for (res = 0; res < EXTERNAL_RELEASE_INFO_SIZE; res++) {
+ if (fw.externalRelease[res] != systemInfo.u8_releaseInfo[res]) {
+ /* External release is printed during readSysInfo */
+ pr_debug(" Firmware in the chip different from the one that was burn!\n");
+ return ERROR_FLASH_BURN_FAILED;
+ }
+ }
+
+ pr_debug(" Final check OK!\n");
+
+ return OK;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFlash.h b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.h
new file mode 100644
index 00000000000..708c8ba2ff7
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsFlash.h
@@ -0,0 +1,115 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS API for Flashing the IC *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsFlash.h
+ * \brief Contains all the definitions and structs to handle the FW update
+ *process
+ */
+
+#ifndef FTS_FLASH_H
+#define FTS_FLASH_H
+
+#include "ftsSoftware.h"
+
+/* Flash possible status */
+#define FLASH_READY 0 /* /< value to indicate that the flash
+ * is ready */
+#define FLASH_BUSY 1 /* /< value to indicate that the flash
+ * is busy */
+#define FLASH_UNKNOWN -1 /* /< value to indicate an unknown
+ * status of the flash */
+
+#define FLASH_STATUS_BYTES 1 /* /< number of bytes to check for read
+ * the flash status */
+
+
+
+/* Flash timing parameters */
+#define FLASH_RETRY_COUNT 200 /* /< number of attempts to read the
+ * flash status */
+#define FLASH_WAIT_BEFORE_RETRY 50 /* /< time to wait in ms between status
+ * readings */
+
+
+#ifdef FW_H_FILE
+#define PATH_FILE_FW "NULL"
+#else
+#define PATH_FILE_FW "ftm5_fw.ftb" /* new FW bin file name */
+#endif
+
+#define FLASH_CHUNK (64 * 1024) /* /< Max number of bytes that
+ * the DMA can burn on the flash
+ * in one shot in FTI */
+#define DMA_CHUNK 32 /* /< Max number of bytes that can be
+ * written in I2C to the DMA */
+
+/**
+ * Define which kind of erase page by page should be performed
+ */
+typedef enum {
+ ERASE_ALL = 0, /* /< erase all the pages */
+ SKIP_PANEL_INIT = 1, /* /< skip erase Panel Init Pages */
+ SKIP_PANEL_CX_INIT = 2 /* /< skip erase Panel Init and CX Pages */
+} ErasePage;
+
+/** @addtogroup fw_file
+ * @{
+ */
+
+/**
+ * Struct which contains information and data of the FW that should be burnt
+ *into the IC
+ */
+typedef struct {
+ u8 *data; /* /< pointer to an array of bytes which represent the
+ * FW data */
+ u16 fw_ver; /* /< FW version of the FW file */
+ u16 config_ver; /* Config version of the FW file */
+ u16 cx_ver; /* /< Cx version of the FW file */
+ u8 externalRelease[EXTERNAL_RELEASE_INFO_SIZE]; /* /< External Release
+ * Info of the FW file
+ * */
+ int data_size; /* /< dimension of data (the actual data to be burnt) */
+ u32 sec0_size; /* /< dimension of section 0 (FW) in .ftb file */
+ u32 sec1_size; /* /< dimension of section 1 (Config) in .ftb file */
+ u32 sec2_size; /* /< dimension of section 2 (Cx) in .ftb file */
+ u32 sec3_size; /* /< dimension of section 3 (TBD) in .ftb file */
+} Firmware;
+
+/** @}*/
+
+/** @addtogroup flash_command
+ * @{
+ */
+
+int wait_for_flash_ready(u8 type);
+int hold_m3(void);
+int flash_erase_unlock(void);
+int flash_full_erase(void);
+int flash_erase_page_by_page(ErasePage keep_cx);
+int start_flash_dma(void);
+int fillFlash(u32 address, u8 *data, int size);
+
+int flash_unlock(void);
+int getFWdata(const char *pathToFile, u8 **data, int *size);
+int parseBinFile(u8 *fw_data, int fw_size, Firmware *fw, int keep_cx);
+int readFwFile(const char *path, Firmware *fw, int keep_cx);
+int flash_burn(Firmware fw, int force_burn, int keep_cx);
+int flashProcedure(const char *path, int force, int keep_cx);
+
+#endif
+
+/** @}*/
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFrame.c b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.c
new file mode 100644
index 00000000000..1ca578954a2
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.c
@@ -0,0 +1,620 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS functions for getting frames *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsFrame.c
+ * \brief Contains all the functions to work with frames
+ */
+
+#include "ftsCompensation.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsFrame.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTool.h"
+#include "ftsTime.h"
+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+
+
+
+
+extern SysInfo systemInfo; /* /< forward declaration of the global variable
+ * of containing System Info Data */
+
+
+/**
+ * Read the channels lengths from the config memory
+ * @return OK if success or an error code which specify the type of error
+ */
+int getChannelsLength(void)
+{
+ int ret;
+ u8 data[2];
+
+ if (data == NULL) {
+ pr_err("getChannelsLength: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = readConfig(ADDR_CONFIG_SENSE_LEN, data, 2);
+ if (ret < OK) {
+ pr_err("getChannelsLength: ERROR %08X\n", ret);
+
+ return ret;
+ }
+
+ systemInfo.u8_scrRxLen = (int)data[0];
+ systemInfo.u8_scrTxLen = (int)data[1];
+
+ pr_info("Force_len = %d Sense_Len = %d\n",
+ systemInfo.u8_scrTxLen, systemInfo.u8_scrRxLen);
+
+ return OK;
+}
+
+
+
+/**
+ * Read and pack the frame data related to the nodes
+ * @param address address in memory when the frame data node start
+ * @param size amount of data to read
+ * @param frame pointer to an array of bytes which will contain the frame node
+ * data
+ * @return OK if success or an error code which specify the type of error
+ */
+int getFrameData(u16 address, int size, short *frame)
+{
+ int i, j, ret;
+ u8 *data = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL);
+
+ if (data == NULL) {
+ pr_err("getFrameData: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address, data,
+ size, DUMMY_FRAMEBUFFER);
+ if (ret < OK) {
+ pr_err("getFrameData: ERROR %08X\n", ERROR_BUS_R);
+ kfree(data);
+ return ERROR_BUS_R;
+ }
+ j = 0;
+ for (i = 0; i < size; i += 2) {
+ frame[j] = (short)((data[i + 1] << 8) + data[i]);
+ j++;
+ }
+ kfree(data);
+ return OK;
+}
+
+
+/**
+ * Return the number of Sense Channels (Rx)
+ * @return number of Rx channels
+ */
+int getSenseLen(void)
+{
+ if (systemInfo.u8_scrRxLen == 0)
+ getChannelsLength();
+ return systemInfo.u8_scrRxLen;
+}
+
+/**
+ * Return the number of Force Channels (Tx)
+ * @return number of Tx channels
+ */
+int getForceLen(void)
+{
+ if (systemInfo.u8_scrTxLen == 0)
+ getChannelsLength();
+ return systemInfo.u8_scrTxLen;
+}
+
+
+/******************** New API **************************/
+
+/**
+ * Read a MS Frame from frame buffer memory
+ * @param type type of MS frame to read
+ * @param frame pointer to MutualSenseFrame variable which will contain the
+ * data
+ * @return > 0 if success specifying the number of node into the frame or
+ * an error code which specify the type of error
+ */
+int getMSFrame3(MSFrameType type, MutualSenseFrame *frame)
+{
+ u16 offset;
+ int ret, force_len, sense_len;
+
+ force_len = getForceLen();
+ sense_len = getSenseLen();
+
+ frame->node_data = NULL;
+
+ pr_info("%s: Starting to get frame %02X\n", __func__,
+ type);
+ switch (type) {
+ case MS_RAW:
+ offset = systemInfo.u16_msTchRawAddr;
+ goto LOAD_NORM;
+ case MS_FILTER:
+ offset = systemInfo.u16_msTchFilterAddr;
+
+ goto LOAD_NORM;
+ case MS_STRENGTH:
+ offset = systemInfo.u16_msTchStrenAddr;
+ goto LOAD_NORM;
+ case MS_BASELINE:
+ offset = systemInfo.u16_msTchBaselineAddr;
+LOAD_NORM:
+ if (force_len == 0 || sense_len == 0) {
+ pr_err("%s: number of channels not initialized ERROR %08X\n",
+ __func__, ERROR_CH_LEN);
+ return ERROR_CH_LEN | ERROR_GET_FRAME;
+ }
+
+ break;
+
+ case MS_KEY_RAW:
+ offset = systemInfo.u16_keyRawAddr;
+ goto LOAD_KEY;
+ case MS_KEY_FILTER:
+ offset = systemInfo.u16_keyFilterAddr;
+ goto LOAD_KEY;
+ case MS_KEY_STRENGTH:
+ offset = systemInfo.u16_keyStrenAddr;
+ goto LOAD_KEY;
+ case MS_KEY_BASELINE:
+ offset = systemInfo.u16_keyBaselineAddr;
+LOAD_KEY:
+ if (systemInfo.u8_keyLen == 0) {
+ pr_err("%s: number of channels not initialized ERROR %08X\n",
+ __func__, ERROR_CH_LEN);
+ return ERROR_CH_LEN | ERROR_GET_FRAME;
+ }
+ force_len = 1;
+ sense_len = systemInfo.u8_keyLen;
+ break;
+
+ case FRC_RAW:
+ offset = systemInfo.u16_frcRawAddr;
+ goto LOAD_FRC;
+ case FRC_FILTER:
+ offset = systemInfo.u16_frcFilterAddr;
+ goto LOAD_FRC;
+ case FRC_STRENGTH:
+ offset = systemInfo.u16_frcStrenAddr;
+ goto LOAD_FRC;
+ case FRC_BASELINE:
+ offset = systemInfo.u16_frcBaselineAddr;
+LOAD_FRC:
+ if (force_len == 0) {
+ pr_err("%s: number of channels not initialized ERROR %08X\n",
+ __func__, ERROR_CH_LEN);
+ return ERROR_CH_LEN | ERROR_GET_FRAME;
+ }
+ sense_len = 1;
+ break;
+ default:
+ pr_err("%s: Invalid type ERROR %08X\n", __func__,
+ ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME);
+ return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME;
+ }
+
+ frame->node_data_size = ((force_len) * sense_len);
+ frame->header.force_node = force_len;
+ frame->header.sense_node = sense_len;
+ frame->header.type = type;
+
+ pr_info("%s: Force_len = %d Sense_len = %d Offset = %04X\n",
+ __func__, force_len, sense_len, offset);
+
+ frame->node_data = (short *)kmalloc(frame->node_data_size *
+ sizeof(short), GFP_KERNEL);
+ if (frame->node_data == NULL) {
+ pr_err("%s: ERROR %08X\n", __func__,
+ ERROR_ALLOC | ERROR_GET_FRAME);
+ return ERROR_ALLOC | ERROR_GET_FRAME;
+ }
+
+ ret = getFrameData(offset, frame->node_data_size * BYTES_PER_NODE,
+ (frame->node_data));
+ if (ret < OK) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_GET_FRAME_DATA);
+ kfree(frame->node_data);
+ frame->node_data = NULL;
+ return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME;
+ }
+ /* if you want to access one node i,j,
+ * compute the offset like: offset = i*columns + j = > frame[i, j] */
+
+ pr_info("Frame acquired!\n");
+ return frame->node_data_size;
+ /* return the number of data put inside frame */
+}
+
+/**
+ * Read a SS Frame from frame buffer
+ * @param type type of SS frame to read
+ * @param frame pointer to SelfSenseFrame variable which will contain the data
+ * @return > 0 if success specifying the number of node into frame or an
+ * error code which specify the type of error
+ */
+int getSSFrame3(SSFrameType type, SelfSenseFrame *frame)
+{
+ u16 offset_force, offset_sense;
+ int ret;
+
+ frame->force_data = NULL;
+ frame->sense_data = NULL;
+
+ frame->header.force_node = getForceLen(); /* use getForce/SenseLen
+ * because introduce
+ * a recover mechanism
+ * in case of len =0 */
+ frame->header.sense_node = getSenseLen();
+
+ if (frame->header.force_node == 0 || frame->header.sense_node == 0) {
+ pr_err("%s: number of channels not initialized ERROR %08X\n",
+ __func__, ERROR_CH_LEN);
+ return ERROR_CH_LEN | ERROR_GET_FRAME;
+ }
+
+
+ pr_info("%s: Starting to get frame %02X\n", __func__, type);
+ switch (type) {
+ case SS_RAW:
+ offset_force = systemInfo.u16_ssTchTxRawAddr;
+ offset_sense = systemInfo.u16_ssTchRxRawAddr;
+ break;
+ case SS_FILTER:
+ offset_force = systemInfo.u16_ssTchTxFilterAddr;
+ offset_sense = systemInfo.u16_ssTchRxFilterAddr;
+ break;
+ case SS_STRENGTH:
+ offset_force = systemInfo.u16_ssTchTxStrenAddr;
+ offset_sense = systemInfo.u16_ssTchRxStrenAddr;
+ break;
+ case SS_BASELINE:
+ offset_force = systemInfo.u16_ssTchTxBaselineAddr;
+ offset_sense = systemInfo.u16_ssTchRxBaselineAddr;
+ break;
+
+ case SS_HVR_RAW:
+ offset_force = systemInfo.u16_ssHvrTxRawAddr;
+ offset_sense = systemInfo.u16_ssHvrRxRawAddr;
+ break;
+ case SS_HVR_FILTER:
+ offset_force = systemInfo.u16_ssHvrTxFilterAddr;
+ offset_sense = systemInfo.u16_ssHvrRxFilterAddr;
+ break;
+ case SS_HVR_STRENGTH:
+ offset_force = systemInfo.u16_ssHvrTxStrenAddr;
+ offset_sense = systemInfo.u16_ssHvrRxStrenAddr;
+ break;
+ case SS_HVR_BASELINE:
+ offset_force = systemInfo.u16_ssHvrTxBaselineAddr;
+ offset_sense = systemInfo.u16_ssHvrRxBaselineAddr;
+ break;
+
+ case SS_PRX_RAW:
+ offset_force = systemInfo.u16_ssPrxTxRawAddr;
+ offset_sense = systemInfo.u16_ssPrxRxRawAddr;
+ break;
+ case SS_PRX_FILTER:
+ offset_force = systemInfo.u16_ssPrxTxFilterAddr;
+ offset_sense = systemInfo.u16_ssPrxRxFilterAddr;
+ break;
+ case SS_PRX_STRENGTH:
+ offset_force = systemInfo.u16_ssPrxTxStrenAddr;
+ offset_sense = systemInfo.u16_ssPrxRxStrenAddr;
+ break;
+ case SS_PRX_BASELINE:
+ offset_force = systemInfo.u16_ssPrxTxBaselineAddr;
+ offset_sense = systemInfo.u16_ssPrxRxBaselineAddr;
+ break;
+
+ default:
+ pr_err("%s: Invalid type ERROR %08X\n", __func__,
+ ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME);
+ return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME;
+ }
+
+ frame->header.type = type;
+
+ pr_info("%s: Force_len = %d Sense_len = %d Offset_force = %04X Offset_sense = %04X\n",
+ __func__, frame->header.force_node,
+ frame->header.sense_node,
+ offset_force, offset_sense);
+
+ frame->force_data = (short *)kmalloc(frame->header.force_node *
+ sizeof(short), GFP_KERNEL);
+ if (frame->force_data == NULL) {
+ pr_err("%s: can not allocate force_data ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ return ERROR_ALLOC | ERROR_GET_FRAME;
+ }
+
+ frame->sense_data = (short *)kmalloc(frame->header.sense_node *
+ sizeof(short), GFP_KERNEL);
+ if (frame->sense_data == NULL) {
+ kfree(frame->force_data);
+ frame->force_data = NULL;
+ pr_err("%s: can not allocate sense_data ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ return ERROR_ALLOC | ERROR_GET_FRAME;
+ }
+
+ ret = getFrameData(offset_force, frame->header.force_node *
+ BYTES_PER_NODE, (frame->force_data));
+ if (ret < OK) {
+ pr_err("%s: error while reading force data ERROR %08X\n",
+ __func__, ERROR_GET_FRAME_DATA);
+ kfree(frame->force_data);
+ frame->force_data = NULL;
+ kfree(frame->sense_data);
+ frame->sense_data = NULL;
+ return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME;
+ }
+
+ ret = getFrameData(offset_sense, frame->header.sense_node *
+ BYTES_PER_NODE, (frame->sense_data));
+ if (ret < OK) {
+ pr_err("%s: error while reading sense data ERROR %08X\n",
+ __func__, ERROR_GET_FRAME_DATA);
+ kfree(frame->force_data);
+ frame->force_data = NULL;
+ kfree(frame->sense_data);
+ frame->sense_data = NULL;
+ return ret | ERROR_GET_FRAME_DATA | ERROR_GET_FRAME;
+ }
+ /* if you want to access one node i,j,
+ * the offset like: offset = i*columns + j = > frame[i, j] */
+
+ pr_info("Frame acquired!\n");
+ return frame->header.force_node + frame->header.sense_node;
+ /* return the number of data put inside frame */
+}
+
+
+/**
+ * Read Initialization Data Header and check that the type loaded match with
+ * the one previously requested
+ * @param type type of Initialization data requested @link load_opt Load Host
+ * Data Option @endlink
+ * @param msHeader pointer to DataHeader variable which will contain the header
+ * info for the MS frame
+ * @param ssHeader pointer to DataHeader variable which will contain the header
+ * info for the SS frame
+ * @param address pointer to a variable which will contain the updated address
+ * to the next data
+ * @return OK if success or an error code which specify the type of error
+ */
+int readSyncDataHeader(u8 type, DataHeader *msHeader, DataHeader *ssHeader,
+ u64 *address)
+{
+ u64 offset = ADDR_FRAMEBUFFER;
+ u8 data[SYNCFRAME_DATA_HEADER];
+ int ret;
+
+ ret = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, offset, data,
+ SYNCFRAME_DATA_HEADER, DUMMY_FRAMEBUFFER);
+ if (ret < OK) { /* i2c function have already a retry mechanism */
+ pr_err("%s: error while reading data header ERROR %08X\n",
+ __func__, ret);
+ return ret;
+ }
+
+ pr_info("Read Data Header done!\n");
+
+ if (data[0] != HEADER_SIGNATURE) {
+ pr_err("%s: The Header Signature was wrong! %02X != %02X ERROR %08X\n",
+ __func__, data[0], HEADER_SIGNATURE,
+ ERROR_WRONG_DATA_SIGN);
+ return ERROR_WRONG_DATA_SIGN;
+ }
+
+
+ if (data[1] != type) {
+ pr_err("%s: Wrong type found! %02X!=%02X ERROR %08X\n",
+ __func__, data[1], type, ERROR_DIFF_DATA_TYPE);
+ return ERROR_DIFF_DATA_TYPE;
+ }
+
+ pr_info("Type = %02X of SyncFrame data OK!\n", type);
+
+ msHeader->force_node = data[5];
+ msHeader->sense_node = data[6];
+ pr_info("MS Frame force_node = %d, sense_node = %d\n",
+ msHeader->force_node, msHeader->sense_node);
+
+ ssHeader->force_node = data[7];
+ ssHeader->sense_node = data[8];
+ pr_info("SS Frame force_node = %d, sense_node = %d\n",
+ ssHeader->force_node, ssHeader->sense_node);
+
+ *address = offset + SYNCFRAME_DATA_HEADER + data[4];
+
+ return OK;
+}
+
+/**
+ * Read a Sync Frame from frame buffer which contain MS and SS data collected
+ * for the same scan
+ * @param type type of Sync frame to read, possible values:
+ * LOAD_SYNC_FRAME_RAW, LOAD_SYNC_FRAME_FILTER, LOAD_SYNC_FRAME_BASELINE,
+ * LOAD_SYNC_FRAME_STRENGTH
+ * @param msFrame pointer to MutualSenseFrame variable which will contain the
+ * MS data
+ * @param ssFrame pointer to SelfSenseFrame variable which will contain the SS
+ * data
+ * @return >0 if success specifying the total number of nodes copied into
+ * msFrame and ssFrame or an error code which specify the type of error
+ */
+int getSyncFrame(u8 type, MutualSenseFrame *msFrame, SelfSenseFrame *ssFrame)
+{
+ int res;
+ u64 address;
+
+ msFrame->node_data = NULL;
+ ssFrame->force_data = NULL;
+ ssFrame->sense_data = NULL;
+
+ pr_info("%s: Starting to get Sync Frame %02X...\n", __func__, type);
+ switch (type) {
+ case LOAD_SYNC_FRAME_RAW:
+ msFrame->header.type = MS_RAW;
+ ssFrame->header.type = SS_RAW;
+ break;
+
+ case LOAD_SYNC_FRAME_FILTER:
+ msFrame->header.type = MS_FILTER;
+ ssFrame->header.type = SS_FILTER;
+ break;
+
+ case LOAD_SYNC_FRAME_BASELINE:
+ msFrame->header.type = MS_BASELINE;
+ ssFrame->header.type = SS_BASELINE;
+ break;
+
+ case LOAD_SYNC_FRAME_STRENGTH:
+ msFrame->header.type = MS_STRENGTH;
+ ssFrame->header.type = SS_STRENGTH;
+ break;
+
+ default:
+ return ERROR_OP_NOT_ALLOW | ERROR_GET_FRAME;
+ }
+
+ pr_info("%s: Requesting Sync Frame %02X...\n", __func__, type);
+ res = requestSyncFrame(type);
+ if (res < OK) {
+ pr_err("%s: error while requesting Sync Frame ERROR %08X\n",
+ __func__, res | ERROR_GET_FRAME_DATA);
+ return res | ERROR_GET_FRAME_DATA;
+ }
+
+ res = readSyncDataHeader(type, &(msFrame->header), &(ssFrame->header),
+ &address);
+ if (res < OK) {
+ pr_err("%s: error while reading Sync Frame header... ERROR %08X\n",
+ __func__, res | ERROR_GET_FRAME_DATA);
+ return res | ERROR_GET_FRAME_DATA;
+ }
+
+ msFrame->node_data_size = msFrame->header.force_node *
+ msFrame->header.sense_node;
+
+ msFrame->node_data = (short *)kmalloc(msFrame->node_data_size *
+ sizeof(short), GFP_KERNEL);
+ if (msFrame->node_data == NULL) {
+ pr_err("%s: impossible allocate memory for MS frame... ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ return ERROR_ALLOC | ERROR_GET_FRAME;
+ }
+
+ pr_info("%s: Getting MS frame at %llx...\n", __func__, address);
+ res = getFrameData(address, (msFrame->node_data_size) * BYTES_PER_NODE,
+ (msFrame->node_data));
+ if (res < OK) {
+ pr_err("%s: error while getting MS data...ERROR %08X\n",
+ __func__, res);
+ res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ /* move the offset */
+ address += (msFrame->node_data_size) * BYTES_PER_NODE;
+
+ ssFrame->force_data = (short *)kmalloc(ssFrame->header.force_node *
+ sizeof(short), GFP_KERNEL);
+ if (ssFrame->force_data == NULL) {
+ pr_err("%s: impossible allocate memory for SS force frame...ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ res = ERROR_ALLOC | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ pr_info("%s: Getting SS force frame at %llx...\n", __func__, address);
+ res = getFrameData(address, (ssFrame->header.force_node) *
+ BYTES_PER_NODE, (ssFrame->force_data));
+ if (res < OK) {
+ pr_err("%s: error while getting SS force data...ERROR %08X\n",
+ __func__, res);
+ res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ /* move the offset */
+ address += (ssFrame->header.force_node) * BYTES_PER_NODE;
+
+ ssFrame->sense_data = (short *)kmalloc(ssFrame->header.sense_node *
+ sizeof(short), GFP_KERNEL);
+ if (ssFrame->sense_data == NULL) {
+ pr_err("%s: impossible allocate memory for SS sense frame...ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ res = ERROR_ALLOC | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ pr_info("%s: Getting SS sense frame at %llx...\n", __func__, address);
+ res = getFrameData(address, (ssFrame->header.sense_node) *
+ BYTES_PER_NODE, (ssFrame->sense_data));
+ if (res < OK) {
+ pr_err("%s: error while getting SS sense data...ERROR %08X\n",
+ __func__, res);
+ res |= ERROR_GET_FRAME_DATA | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ERROR:
+ if (res < OK) {
+ if (msFrame->node_data != NULL) {
+ kfree(msFrame->node_data);
+ msFrame->node_data = NULL;
+ }
+
+ if (ssFrame->force_data != NULL) {
+ kfree(ssFrame->force_data);
+ ssFrame->force_data = NULL;
+ }
+
+ if (ssFrame->sense_data != NULL) {
+ kfree(ssFrame->sense_data);
+ ssFrame->sense_data = NULL;
+ }
+ pr_err("Getting Sync Frame FAILED! ERROR %08X!\n", res);
+ } else {
+ pr_info("Getting Sync Frame FINISHED!\n");
+ res = msFrame->node_data_size + ssFrame->header.force_node +
+ ssFrame->header.sense_node;
+ }
+ return res;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsFrame.h b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.h
new file mode 100644
index 00000000000..bdd51256dd8
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsFrame.h
@@ -0,0 +1,113 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS functions for getting frames *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsFrame.h
+ * \brief Contains all the definitions and structs to work with frames
+ */
+
+
+#ifndef FTS_FRAME_H
+#define FTS_FRAME_H
+
+#include "ftsSoftware.h"
+#include "ftsCore.h"
+
+
+
+/* Number of data bytes for each node */
+#define BYTES_PER_NODE 2 /* /< number of data bytes for each node
+ * */
+
+
+#define RETRY_FRAME_DATA_READ 2 /* /< max number of attempts to read a
+ * frame */
+#define SYNCFRAME_DATA_HEADER (DATA_HEADER + 12) /* /< number of bytes of
+ * Sync Frame Header */
+
+/**
+ * Possible types of MS frames
+ */
+typedef enum {
+ MS_RAW = 0, /* /< Mutual Sense Raw Frame */
+ MS_FILTER = 1, /* /< Mutual Sense Filtered Frame */
+ MS_STRENGTH = 2, /* /< Mutual Sense Strength Frame (Baseline-Raw)
+ * */
+ MS_BASELINE = 3, /* /< Mutual Sense Baseline Frame */
+ MS_KEY_RAW = 4, /* /< Mutual Sense Key Raw Frame */
+ MS_KEY_FILTER = 5, /* /< Mutual Sense Key Filter Frame */
+ MS_KEY_STRENGTH = 6, /* /< Mutual Sense Key Strength Frame
+ * (Baseline-Raw) */
+ MS_KEY_BASELINE = 7, /* /< Mutual Sense Key Baseline Frame */
+ FRC_RAW = 8, /* /< Force Raw Frame */
+ FRC_FILTER = 9, /* /< Force Filtered Frame */
+ FRC_STRENGTH = 10, /* /< Force Strength Frame (Baseline-Raw) */
+ FRC_BASELINE = 11 /* /< Force Baseline Frame */
+} MSFrameType;
+
+
+/**
+ * Possible types of SS frames
+ */
+typedef enum {
+ SS_RAW = 0, /* /< Self Sense Raw Frame */
+ SS_FILTER = 1, /* /< Self Sense Filtered Frame */
+ SS_STRENGTH = 2, /* /< Self Sense Strength Frame (Baseline-Raw)
+ * */
+ SS_BASELINE = 3, /* /< Self Sense Baseline Frame */
+ SS_HVR_RAW = 4, /* /< Self Sense Hover Raw Frame */
+ SS_HVR_FILTER = 5, /* /< Self Sense Hover Filter Frame */
+ SS_HVR_STRENGTH = 6, /* /< Self Sense Hover Strength Frame
+ * (Baseline-Raw) */
+ SS_HVR_BASELINE = 7, /* /< Self Sense Hover Baseline Frame */
+ SS_PRX_RAW = 8, /* /< Self Sense Proximity Raw Frame */
+ SS_PRX_FILTER = 9, /* /< Self Sense Proximity Filtered Frame */
+ SS_PRX_STRENGTH = 10, /* /< Self Sense Proximity Strength Frame
+ * (Baseline-Raw) */
+ SS_PRX_BASELINE = 11 /* /< Self Sense Proximity Baseline Frame */
+} SSFrameType;
+
+
+/**
+ * Struct which contains the data of a MS Frame
+ */
+typedef struct {
+ DataHeader header; /* /< Header which contain basic info of the
+ * frame */
+ short *node_data; /* /< Data of the frame */
+ int node_data_size; /* /< Dimension of the data of the frame */
+} MutualSenseFrame;
+
+/**
+ * Struct which contains the data of a SS Frame
+ */
+typedef struct {
+ DataHeader header; /* /< Header which contain basic info of the
+ * frame */
+ short *force_data; /* /< Force Channels Data */
+ short *sense_data; /* /< Sense Channels Data */
+} SelfSenseFrame;
+
+
+int getChannelsLength(void);
+int getFrameData(u16 address, int size, short *frame);
+int getSenseLen(void);
+int getForceLen(void);
+int getMSFrame3(MSFrameType type, MutualSenseFrame *frame);
+int getSSFrame3(SSFrameType type, SelfSenseFrame *frame);
+int readSyncDataHeader(u8 type, DataHeader *msHeader, DataHeader *ssHeader,
+ u64 *address);
+int getSyncFrame(u8 type, MutualSenseFrame *msFrame, SelfSenseFrame *ssFrame);
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c
new file mode 100644
index 00000000000..904c2ef8c90
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.c
@@ -0,0 +1,376 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Gesture Utilities **
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsGesture.c
+ * \brief Contains all the functions and variable to handle the Gesture
+ * Detection features
+ */
+
+#include "ftsSoftware.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsGesture.h"
+#include "ftsIO.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+
+/* /< store the gesture bitmask which the host want to enable.
+ * If bit set 1 the corresponding gesture will be detected in Gesture Mode */
+static u8 gesture_mask[GESTURE_MASK_SIZE] = { 0 };
+/* /< store the x coordinates of the points draw by the user
+ * when a gesture is detected */
+u16 gesture_coordinates_x[GESTURE_MAX_COORDS_PAIRS_REPORT] = { 0 };
+/* /< store the y coordinates of the points draw by the user
+ * when a gesture is detected */
+u16 gesture_coordinates_y[GESTURE_MAX_COORDS_PAIRS_REPORT] = { 0 };
+/* /< number of coordinates pairs (points) reported with the detected gesture */
+int gesture_coords_reported = ERROR_OP_NOT_ALLOW;
+static u8 refreshGestureMask; /* /< flag which indicate if there is
+ * the need to set the gesture mask in the FW */
+struct mutex gestureMask_mutex; /* /< mutex used to control access on gesture
+ * shared variables */
+
+/**
+ * Update the gesture mask stored in the driver and have to be used in gesture
+ * mode
+ * @param mask pointer to a byte array which store the gesture mask update
+ * that want to be performed.
+ * @param size dimension in byte of mask. This size can be <=
+ * GESTURE_MASK_SIZE.
+ * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos
+ * and starting from the less significant byte.
+ * @param en 0 = enable the gestures set in mask, 1 = disable the gestures set
+ * in mask
+ * @return OK if success or an error code which specify the type of error
+ */
+int updateGestureMask(u8 *mask, int size, int en)
+{
+ u8 temp;
+ int i;
+
+ if (mask != NULL) {
+ if (size <= GESTURE_MASK_SIZE) {
+ if (en == FEAT_ENABLE) {
+ mutex_lock(&gestureMask_mutex);
+ pr_info("updateGestureMask: setting gesture mask to enable...\n");
+ if (mask != NULL)
+ for (i = 0; i < size; i++)
+ gesture_mask[i] =
+ gesture_mask[i] |
+ mask[i];
+ /* back up of the gesture enabled */
+ refreshGestureMask = 1;
+ pr_info("updateGestureMask: gesture mask to enable SET!\n");
+ mutex_unlock(&gestureMask_mutex);
+ return OK;
+ } else if (en == FEAT_DISABLE) {
+ mutex_lock(&gestureMask_mutex);
+ pr_info("updateGestureMask: setting gesture mask to disable...\n");
+ for (i = 0; i < size; i++) {
+ temp = gesture_mask[i] ^ mask[i];
+ /* enabled XOR disabled */
+ gesture_mask[i] = temp &
+ gesture_mask[i];
+ /* temp AND enabled
+ * disable the gestures that were
+ * enabled */
+ }
+ pr_info("updateGestureMask: gesture mask to disable SET!\n");
+ refreshGestureMask = 1;
+ mutex_unlock(&gestureMask_mutex);
+ return OK;
+ } else {
+ pr_err("updateGestureMask: Enable parameter Invalid! %d != %d or %d ERROR %08X",
+ en,
+ FEAT_DISABLE, FEAT_ENABLE,
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("updateGestureMask: Size not valid! %d > %d ERROR %08X\n",
+ size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("updateGestureMask: Mask NULL! ERROR %08X\n",
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Enable in the FW the gesture mask to be used in gesture mode
+ * @param mask pointer to a byte array which store the gesture mask update
+ * that want to be sent to the FW, if NULL, will be used gesture_mask
+ * set previously without any changes.
+ * @param size dimension in byte of mask. This size can be <=
+ * GESTURE_MASK_SIZE.
+ * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos and
+ * starting from the less significant byte.
+ * @return OK if success or an error code which specify the type of error
+ */
+int enableGesture(u8 *mask, int size)
+{
+ int i, res;
+
+ pr_info("Trying to enable gesture...\n");
+
+ if (size <= GESTURE_MASK_SIZE) {
+ mutex_lock(&gestureMask_mutex);
+ if (mask != NULL)
+ for (i = 0; i < size; i++)
+ gesture_mask[i] = gesture_mask[i] | mask[i];
+ /* back up of the gesture enabled */
+
+ res = setFeatures(FEAT_SEL_GESTURE, gesture_mask,
+ GESTURE_MASK_SIZE);
+ if (res < OK) {
+ pr_err("enableGesture: ERROR %08X\n", res);
+ goto END;
+ }
+
+ pr_info("enableGesture DONE!\n");
+ res = OK;
+
+END:
+ mutex_unlock(&gestureMask_mutex);
+ return res;
+ } else {
+ pr_err("enableGesture: Size not valid! %d > %d ERROR %08X\n",
+ size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Disable in the FW the gesture mask to be used in gesture mode
+ * @param mask pointer to a byte array which store the gesture mask update that
+ * want to be sent to the FW, if NULL, all the gestures will be disabled.
+ * @param size dimension in byte of mask. This size can be <=
+ * GESTURE_MASK_SIZE.
+ * If size < GESTURE_MASK_SIZE the bytes of mask are considering continuos and
+ * starting from the less significant byte.
+ * @return OK if success or an error code which specify the type of error
+ */
+int disableGesture(u8 *mask, int size)
+{
+ u8 temp;
+ int i, res;
+ u8 *pointer;
+
+
+ pr_info("Trying to disable gesture...\n");
+
+
+ if (size <= GESTURE_MASK_SIZE) {
+ mutex_lock(&gestureMask_mutex);
+ if (mask != NULL) {
+ for (i = 0; i < size; i++) {
+ temp = gesture_mask[i] ^ mask[i];
+ /* enabled mask XOR disabled mask */
+ gesture_mask[i] = temp & gesture_mask[i];
+ /* temp AND enabled
+ * disable the gestures that are specified and
+ * previously enabled */
+ }
+
+ pointer = gesture_mask;
+ } else {
+ i = 0; /* if NULL is passed disable all the possible
+ * gestures */
+ pointer = (u8 *)&i;
+ }
+
+ res = setFeatures(FEAT_SEL_GESTURE, pointer, GESTURE_MASK_SIZE);
+ if (res < OK) {
+ pr_err("disableGesture: ERROR %08X\n", res);
+ goto END;
+ }
+
+ pr_info("disableGesture DONE!\n");
+
+ res = OK;
+
+END:
+ mutex_unlock(&gestureMask_mutex);
+ return res;
+ } else {
+ pr_err("disableGesture: Size not valid! %d > %d ERROR %08X\n",
+ size, GESTURE_MASK_SIZE, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Perform all the steps required to put the chip in gesture mode
+ * @param reload if set to 1, before entering in gesture mode it will re-enable
+ * in the FW the last defined gesture mask
+ * @return OK if success or an error code which specify the type of error
+ */
+int enterGestureMode(int reload)
+{
+ int res, ret;
+
+ res = fts_disableInterrupt();
+ if (res < OK) {
+ pr_err("enterGestureMode: ERROR %08X\n",
+ res | ERROR_DISABLE_INTER);
+ return res | ERROR_DISABLE_INTER;
+ }
+
+ if (reload == 1 || refreshGestureMask == 1) {
+ res = enableGesture(NULL, 0);
+ if (res < OK) {
+ pr_err("enterGestureMode: enableGesture ERROR %08X\n",
+ res);
+ goto END;
+ }
+
+ refreshGestureMask = 0;
+ }
+
+ res = setScanMode(SCAN_MODE_LOW_POWER, 0);
+ if (res < OK) {
+ pr_err("enterGestureMode: enter gesture mode ERROR %08X\n",
+ res);
+ goto END;
+ }
+
+ res = OK;
+END:
+ ret = fts_enableInterrupt();
+ if (ret < OK) {
+ pr_err("enterGestureMode: fts_enableInterrupt ERROR %08X\n",
+ res | ERROR_ENABLE_INTER);
+ res |= ret | ERROR_ENABLE_INTER;
+ }
+
+
+ return res;
+}
+
+/**
+ * Check if one or more Gesture IDs are currently enabled in gesture_mask
+ * @return FEAT_ENABLE if one or more gesture ids are enabled, FEAT_DISABLE if
+ * all the gesture ids are currently disabled
+ */
+int isAnyGestureActive(void)
+{
+ int res = 0;
+
+ while (res < (GESTURE_MASK_SIZE - 1) && gesture_mask[res] == 0)
+ /* -1 because in any case the last gesture mask byte will
+ * be evaluated with the following if */
+ res++;
+
+ if (gesture_mask[res] != 0) {
+ pr_info("%s: Active Gestures Found! gesture_mask[%d] = %02X !\n",
+ __func__, res, gesture_mask[res]);
+ return FEAT_ENABLE;
+ } else {
+ pr_info("%s: All Gestures Disabled!\n", __func__);
+ return FEAT_DISABLE;
+ }
+}
+
+
+/**
+ * Read from the frame buffer the gesture coordinates pairs of the points draw
+ * by an user when a gesture is detected
+ * @param event pointer to a byte array which contains the gesture event
+ * reported
+ * by the fw when a gesture is detected
+ * @return OK if success or an error code which specify the type of error
+ */
+int readGestureCoords(u8 *event)
+{
+ int i = 0;
+ u64 address = 0;
+ int res;
+
+ u8 val[GESTURE_MAX_COORDS_PAIRS_REPORT * 4];
+
+ /* the max coordinates to read are GESTURE_COORDS_REPORT_MAX*4
+ * (because each coordinate is a short(*2) and we have x and y) */
+
+
+ if (event[0] == EVT_ID_USER_REPORT &&
+ event[1] == EVT_TYPE_USER_GESTURE) {
+ address = (event[4] << 8) | event[3]; /* Offset in framebuff */
+ gesture_coords_reported = event[5]; /* number of pairs
+ * coords reported */
+ if (gesture_coords_reported > GESTURE_MAX_COORDS_PAIRS_REPORT) {
+ pr_err("%s: FW reported more than %d points for the gestures! Decreasing to %d\n",
+ __func__, gesture_coords_reported,
+ GESTURE_MAX_COORDS_PAIRS_REPORT);
+ gesture_coords_reported =
+ GESTURE_MAX_COORDS_PAIRS_REPORT;
+ }
+
+ pr_info("%s: Offset: %llx , coords pairs = %d\n",
+ __func__, address, gesture_coords_reported);
+
+ res = fts_writeReadU8UX(FTS_CMD_FRAMEBUFFER_R, BITS_16, address,
+ val, (gesture_coords_reported * 2 * 2),
+ DUMMY_FRAMEBUFFER);
+ /* *2 because each coord is made by 2 bytes,
+ * *2 because there are x and y */
+ if (res < OK) {
+ pr_err("%s: Cannot read the coordinates! ERROR %08X\n",
+ __func__, res);
+ gesture_coords_reported = ERROR_OP_NOT_ALLOW;
+ return res;
+ }
+
+ /* all the points of the gesture are stored in val */
+ for (i = 0; i < gesture_coords_reported; i++) {
+ gesture_coordinates_x[i] =
+ (((u16)val[i * 2 + 1]) & 0x0F) << 8 |
+ (((u16)val[i * 2]) & 0xFF);
+ gesture_coordinates_y[i] =
+ (((u16)val[gesture_coords_reported *
+ 2 + i * 2 + 1]) & 0x0F) << 8 |
+ (((u16)val[gesture_coords_reported *
+ 2 + i * 2]) & 0xFF);
+ }
+
+
+ pr_info("%s: Reading Gesture Coordinates DONE!\n", __func__);
+ return OK;
+ } else {
+ pr_err("%s: The event passsed as argument is invalid! ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Return the coordinates of the points stored during the last detected gesture
+ * @param x output parameter which will store the address of the array
+ * containing the x coordinates
+ * @param y output parameter which will store the address of the array
+ * containing the y coordinates
+ * @return the number of points (x,y) stored and therefore the size of the x
+ * and y array returned.
+ */
+int getGestureCoords(u16 **x, u16 **y)
+{
+ *x = gesture_coordinates_x;
+ *y = gesture_coordinates_y;
+ pr_info("%s: Number of gesture coordinates pairs returned = %d\n",
+ __func__, gesture_coords_reported);
+ return gesture_coords_reported;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsGesture.h b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.h
new file mode 100644
index 00000000000..cb59737f76a
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsGesture.h
@@ -0,0 +1,47 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Gesture Utilities *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsGesture.h
+ * \brief Contains all the macro and prototypes to handle the Gesture Detection
+ * features
+ */
+
+
+#ifndef FTS_GESTURE_H_
+#define FTS_GESTURE_H_
+
+
+
+
+#include "ftsHardware.h"
+
+#define GESTURE_MASK_SIZE 4 /* /< number of bytes of the
+ * gesture mask */
+
+#define GESTURE_MAX_COORDS_PAIRS_REPORT 100 /* /< max number of gestures
+ * coordinates pairs reported */
+
+
+
+int updateGestureMask(u8 *mask, int size, int en);
+int disableGesture(u8 *mask, int size);
+int enableGesture(u8 *mask, int size);
+int enterGestureMode(int reload);
+int isAnyGestureActive(void);
+int readGestureCoords(u8 *event);
+int getGestureCoords(u16 **x, u16 **y);
+
+#endif /* ! _GESTURE_H_ */
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsHardware.h b/drivers/input/touchscreen/stm/fts_lib/ftsHardware.h
new file mode 100644
index 00000000000..845da2b711b
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsHardware.h
@@ -0,0 +1,282 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * HW related data *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsHardware.h
+ * \brief Contains all the definitions and information related to the IC
+ * from an hardware point of view
+ */
+
+#ifndef FTS_HARDWARE_H
+#define FTS_HARDWARE_H
+
+/* DIGITAL CHIP INFO */
+#define DCHIP_ID_0 0x36 /* /< LSB chip ID for FTM5 */
+#define DCHIP_ID_1 0x39 /* /< MSB chip ID for FTM5 */
+
+#define DCHIP_FW_VER_BYTE 2 /* /< number of bytes of the fw
+ * versions */
+
+/* CHUNKS */
+#define READ_CHUNK 1024 /* /< chunk dimension of
+ * a single i2c read,
+ * max allowed value is 2kB */
+#define WRITE_CHUNK 1024 /* /< chunk dimension of
+ * a single i2c write,
+ * max allowed value is 2kB */
+#define MEMORY_CHUNK 1024 /* /< chunk dimenasion of
+ * a single i2c write on mem,
+ * max allowed value is 2kB */
+
+/* PROTOCOL INFO */
+#define I2C_INTERFACE /* /< comment if the chip use SPI bus */
+#ifdef I2C_INTERFACE
+#define I2C_SAD 0x49 /* /< slave address of the IC */
+#else
+#define SPI4_WIRE /* /< comment if the master is SPI3
+ * wires
+ * (MOSI and MISO share same line) */
+#define SPI_DELAY_CS 10 /* /< time in usec to wait
+ * before rising the CS */
+#define SPI_CLOCK_FREQ 7000000 /* /< clock frequency in Hz of
+ * the SPI bus */
+#endif
+
+#define IER_ENABLE 0x41 /* /< value to write in IER_ADDR
+ * to enable the interrupts */
+#define IER_DISABLE 0x00 /* /< value to write in IER_ADDR
+ * to disable the interrupts
+ **/
+
+/* FLASH COMMAND */
+/** @defgroup flash_command Flash Commands
+ * All the commands that works with the flash of the IC
+ * @{
+ */
+#define FLASH_CMD_UNLOCK 0xF7
+
+#define FLASH_CMD_READ_REGISTER 0xFA
+#define FLASH_CMD_WRITE_REGISTER 0xFA
+
+/* FLASH UNLOCK PARAMETER */
+#define FLASH_UNLOCK_CODE0 0x25
+#define FLASH_UNLOCK_CODE1 0x20
+
+/* FLASH ERASE and DMA PARAMETER */
+#define FLASH_ERASE_START 0x80
+#define FLASH_ERASE_CODE1 0xC0
+#define FLASH_DMA_CODE1 0xC0
+#define FLASH_ERASE_UNLOCK_CODE0 0xDE
+#define FLASH_ERASE_UNLOCK_CODE1 0x03
+#define FLASH_ERASE_CODE0 0x6A
+#define FLASH_DMA_CODE0 0x71
+#define FLASH_DMA_CONFIG 0x72
+#define FLASH_NUM_PAGE 32 /* /< number of pages in main
+ * flash */
+#define FLASH_CX_PAGE_START 28 /* /< starting page which
+ * contain Cx data */
+#define FLASH_CX_PAGE_END 30 /* /< last page which contain Cx
+ * data */
+#define FLASH_PANEL_PAGE_START 26 /* /< starting page which
+ * contain Panel Init data */
+#define FLASH_PANEL_PAGE_END 27 /* /< last page which contain
+ * Panel Init data */
+/** @} */
+
+/* FLASH ADDRESS */
+#define FLASH_ADDR_CODE 0x00000000 /* /< address of code in
+ * FTI */
+#define FLASH_ADDR_CONFIG 0x00007C00 /* /< address of config
+ * in FTI */
+#define FLASH_ADDR_CX 0x00007000 /* /< address of Init
+ * data in FTI */
+
+/* SIZES FW, CODE, CONFIG, MEMH */
+/** @defgroup fw_file FW file info
+ * All the info related to the fw file
+ * @{
+ */
+#define FW_HEADER_SIZE 64 /* /< dimension of the header in
+ * .fts file */
+#define FW_HEADER_SIGNATURE 0xAA55AA55 /* /< header signature
+ * */
+#define FW_FTB_VER 0x00000001 /* /< .ftb version */
+#define FW_BYTES_ALIGN 4 /* /< allignment of the info */
+#define FW_BIN_VER_OFFSET 16 /* /< offset of the fw version
+ * in the .ftb file */
+#define FW_BIN_CONFIG_ID_OFFSET 20 /* /< offset of the config id in
+ * the .ftb file */
+#define FW_CX_VERSION (16 + 4)/* CX version offset in sec2 of
+ * FW */
+/** @} */
+
+/* FIFO */
+#define FIFO_EVENT_SIZE 8 /* /< number of bytes of one
+ * event */
+#define FIFO_DEPTH 32 /* /< max number of events that
+ * the FIFO can collect before
+ * going in overflow in FTM5 */
+
+#ifdef I2C_INTERFACE
+#define FIFO_CMD_READALL 0x86 /* /< command to read all
+ * the events in the FIFO */
+#else
+#define FIFO_CMD_READALL 0x87 /* /< command to read all
+ * the events in the FIFO */
+#endif
+#define FIFO_CMD_READONE FIFO_CMD_READALL/* /< commad to read
+ * one event from FIFO
+ **/
+
+
+/* OP CODES FOR MEMORY (based on protocol) */
+#ifdef I2C_INTERFACE
+#define FTS_CMD_HW_REG_R 0xFA /* /< command to read an hw register if
+ * FTI */
+#define FTS_CMD_HW_REG_W 0xFA /* /< command to write an hw register if
+ * FTI */
+#define FTS_CMD_FRAMEBUFFER_R 0xA6 /* /< command to read the framebuffer if
+ * FTI */
+#define FTS_CMD_CONFIG_R 0xA8 /* /< command to read the config memory
+ * if FTI */
+#define FTS_CMD_CONFIG_W 0xA8 /* /< command to write the config memory
+ * if FTI */
+#else
+#define FTS_CMD_HW_REG_R 0xFB /* /< command to read an hw register if
+ * FTI */
+#define FTS_CMD_HW_REG_W 0xFA /* /< command to write an hw register if
+ * FTI */
+#define FTS_CMD_FRAMEBUFFER_R 0xA7 /* /< command to read the framebuffer if
+ * FTI */
+#define FTS_CMD_CONFIG_R 0xA9 /* /< command to read the config memory
+ * if FTI */
+#define FTS_CMD_CONFIG_W 0xA8 /* /< command to write the config memory
+ * if FTI */
+#endif
+
+/* DUMMY BYTES DATA */
+#ifndef I2C_INTERFACE
+#define DUMMY_HW_REG 1 /* /< 1 if the first byte read from HW
+ * register is dummy */
+#define DUMMY_FRAMEBUFFER 1 /* /< 1 if the first byte read from
+ * Frame buffer is dummy */
+#define DUMMY_CONFIG 1 /* /< 1 if the first byte read from
+ * Config Memory is dummy */
+#define DUMMY_FIFO 1 /* /< 1 if the first byte read from FIFO
+ * is dummy */
+#else
+#define DUMMY_HW_REG 0 /* /< 1 if the first byte read from HW
+ * register is dummy */
+#define DUMMY_FRAMEBUFFER 0 /* /< 1 if the first byte read from
+ * Frame buffer is dummy */
+#define DUMMY_CONFIG 0 /* /< 1 if the first byte read from
+ * Config Memory is dummy */
+#define DUMMY_FIFO 0 /* /< 1 if the first byte read from FIFO
+ * is dummy */
+#endif
+
+/** @defgroup hw_adr HW Address
+ * @ingroup address
+ * Important addresses of hardware registers (and sometimes their important
+ * values)
+ * @{
+ */
+
+/* IMPORTANT HW ADDRESSES (u64) */
+#define ADDR_FRAMEBUFFER ((u64)0x0000000000000000) /* /< frame
+ * buffer
+ * address in
+ * memory */
+#define ADDR_ERROR_DUMP ((u64)0x000000000000EF80) /* /< start
+ * address dump
+ * error log */
+
+/* SYSTEM RESET INFO */
+#define ADDR_SYSTEM_RESET ((u64)0x0000000020000024) /* /< address of
+ * System
+ * control
+ * register in
+ * FTI */
+/* value to write in SYSTEM_RESET_ADDRESS to perform a system reset in FTM5 */
+#define SYSTEM_RESET_VALUE 0x80
+
+
+/* REMAP REGISTER */
+#define ADDR_BOOT_OPTION ((u64)0x0000000020000025) /* /< address of
+ * Boot option
+ * register */
+
+/* INTERRUPT INFO */
+#define ADDR_IER ((u64)0x0000000020000029) /* /< address of
+ * the Interrupt
+ * enable
+ * register in
+ * FTMI */
+
+/* Chip ID/Fw Version */
+#define ADDR_DCHIP_ID ((u64)0x0000000020000000) /* /< chip id
+ * address for
+ * FTI */
+#define ADDR_DCHIP_FW_VER ((u64)0x0000000020000004) /* /< fw version
+ * address for
+ * FTI */
+
+/* INTERFACE REGISTER */
+#define ADDR_ICR ((u64)0x000000002000002D) /* /< address of
+ * Device
+ * control
+ * register
+ * to set the
+ * communication
+ * protocol
+ * (SPI/I2C) */
+
+#define SPI4_MASK 0x02 /* /< bit to set spi4 */
+
+/* CRC ADDR */
+#define ADDR_CRC ((u64)0x0000000020000078) /* /< address of
+ * the CRC
+ * control
+ * register in
+ * FTI */
+#define CRC_MASK 0x03 /* /< bitmask which reveal if
+ * there is a CRC error in the flash */
+
+#define ADDR_CONFIG_OFFSET ((u64)0x0000000000000000) /* /< config
+ * address in
+ * memory if FTI
+ * */
+
+#define ADDR_GPIO_INPUT ((u64)0x0000000020000030) /* /< address of
+ * GPIO input
+ * register */
+#define ADDR_GPIO_DIRECTION ((u64)0x0000000020000032) /* /< address of
+ * GPIO
+ * direction
+ * register */
+#define ADDR_GPIO_PULLUP ((u64)0x0000000020000034) /* /< address of
+ * GPIO pullup
+ * register */
+#define ADDR_GPIO_CONFIG_REG0 ((u64)0x000000002000003D) /* /< address of
+ * GPIO config
+ * register */
+#define ADDR_GPIO_CONFIG_REG2 ((u64)0x000000002000003F) /* /< address of
+ * GPIO config
+ * register */
+
+/**@}*/
+
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsIO.c b/drivers/input/touchscreen/stm/fts_lib/ftsIO.c
new file mode 100644
index 00000000000..0c7623c6934
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsIO.c
@@ -0,0 +1,925 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * I2C/SPI Communication *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsIO.c
+ * \brief Contains all the functions which handle with the I2C/SPI
+ *communication
+ */
+
+
+#include "ftsSoftware.h"
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/of_gpio.h>
+
+#ifdef I2C_INTERFACE
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+static u16 I2CSAD; /* /< slave address of the IC in the i2c bus */
+#else
+#include <linux/spi/spidev.h>
+#endif
+
+static void *client; /* /< bus client retrived by the OS and
+ * used to execute the bus transfers */
+
+
+
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+
+
+/**
+ * Initialize the static client variable of the fts_lib library in order
+ * to allow any i2c/spi transaction in the driver (Must be called in the probe)
+ * @param clt pointer to i2c_client or spi_device struct which identify the bus
+ * slave device
+ * @return OK
+ */
+int openChannel(void *clt)
+{
+ client = clt;
+#ifdef I2C_INTERFACE
+ I2CSAD = ((struct i2c_client *)clt)->addr;
+ pr_info("openChannel: SAD: %02X\n", I2CSAD);
+#else
+ pr_info("%s: spi_master: flags = %04X !\n", __func__,
+ ((struct spi_device *)client)->master->flags);
+ pr_info("%s: spi_device: max_speed = %d chip select = %02X bits_per_words = %d mode = %04X !\n",
+ __func__, ((struct spi_device *)client)->max_speed_hz,
+ ((struct spi_device *)client)->chip_select,
+ ((struct spi_device *)client)->bits_per_word,
+ ((struct spi_device *)client)->mode);
+ pr_info("openChannel: completed!\n");
+#endif
+ return OK;
+}
+
+#ifdef I2C_INTERFACE
+/**
+ * Change the I2C slave address which will be used during the transaction
+ * (For Debug Only)
+ * @param sad new slave address id
+ * @return OK
+ */
+int changeSAD(u8 sad)
+{
+ I2CSAD = sad;
+ return OK;
+}
+#endif
+
+
+/**
+ * Retrieve the pointer to the device struct of the IC
+ * @return a the device struct pointer if client was previously set
+ * or NULL in all the other cases
+ */
+struct device *getDev(void)
+{
+ if (client != NULL)
+ return &(getClient()->dev);
+ else
+ return NULL;
+}
+
+
+#ifdef I2C_INTERFACE
+struct i2c_client *getClient(void);
+/**
+ * Retrieve the pointer of the i2c_client struct representing the IC as i2c
+ * slave
+ * @return client if it was previously set or NULL in all the other cases
+ */
+struct i2c_client *getClient(void)
+{
+ if (client != NULL)
+ return (struct i2c_client *)client;
+ else
+ return NULL;
+}
+#else
+/**
+ * Retrieve the pointer of the spi_device struct representing the IC as spi
+ * slave
+ * @return client if it was previously set or NULL in all the other cases
+ */
+struct spi_device *getClient()
+{
+ if (client != NULL)
+ return (struct spi_device *)client;
+ else
+ return NULL;
+}
+#endif
+
+struct fts_ts_info *getDrvInfo(void)
+{
+ struct device *dev = getDev();
+ struct fts_ts_info *info = NULL;
+
+ if (dev != NULL)
+ info = dev_get_drvdata(dev);
+ return info;
+}
+
+/****************** New I2C API *********************/
+
+/**
+ * Perform a direct bus read
+ * @param outBuf pointer of a byte array which should contain the byte read
+ * from the IC
+ * @param byteToRead number of bytes to read
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_read_internal(u8 *outBuf, int byteToRead, bool dma_safe)
+{
+ int ret = -1;
+ int retry = 0;
+ struct fts_ts_info *info = getDrvInfo();
+#ifdef I2C_INTERFACE
+ struct i2c_msg I2CMsg[1];
+#else
+ struct spi_message msg;
+ struct spi_transfer transfer[1] = { { 0 } };
+#endif
+
+ if (dma_safe == false && byteToRead > sizeof(info->io_read_buf)) {
+ pr_err("%s: preallocated buffers are too small!\n", __func__);
+ return ERROR_ALLOC;
+ }
+
+#ifdef I2C_INTERFACE
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)I2C_M_RD;
+ I2CMsg[0].len = (__u16)byteToRead;
+ if (dma_safe == false)
+ I2CMsg[0].buf = (__u8 *)info->io_read_buf;
+ else
+ I2CMsg[0].buf = (__u8 *)outBuf;
+#else
+ spi_message_init(&msg);
+
+ transfer[0].len = byteToRead;
+ transfer[0].delay_usecs = SPI_DELAY_CS;
+ transfer[0].tx_buf = NULL;
+ if (dma_safe == false)
+ transfer[0].rx_buf = info->io_read_buf;
+ else
+ transfer[0].rx_buf = outBuf;
+ spi_message_add_tail(&transfer[0], &msg);
+#endif
+
+ if (client == NULL)
+ return ERROR_BUS_O;
+ while (retry < I2C_RETRY && ret < OK) {
+#ifdef I2C_INTERFACE
+ ret = i2c_transfer(getClient()->adapter, I2CMsg, 1);
+#else
+ ret = spi_sync(getClient(), &msg);
+#endif
+
+ retry++;
+ if (ret < OK)
+ mdelay(I2C_WAIT_BEFORE_RETRY);
+ /* pr_err("fts_writeCmd: attempt %d\n", retry); */
+ }
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_R);
+ return ERROR_BUS_R;
+ }
+
+ if (dma_safe == false)
+ memcpy(outBuf, info->io_read_buf, byteToRead);
+
+ return OK;
+}
+
+
+/**
+ * Perform a bus write followed by a bus read without a stop condition
+ * @param cmd byte array containing the command to write
+ * @param cmdLength size of cmd
+ * @param outBuf pointer of a byte array which should contain the bytes read
+ * from the IC
+ * @param byteToRead number of bytes to read
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_writeRead_internal(u8 *cmd, int cmdLength, u8 *outBuf,
+ int byteToRead, bool dma_safe)
+{
+ int ret = -1;
+ int retry = 0;
+ struct fts_ts_info *info = getDrvInfo();
+#ifdef I2C_INTERFACE
+ struct i2c_msg I2CMsg[2];
+#else
+ struct spi_message msg;
+ struct spi_transfer transfer[2] = { { 0 }, { 0 } };
+#endif
+
+ if (dma_safe == false && (cmdLength > sizeof(info->io_write_buf) ||
+ byteToRead > sizeof(info->io_read_buf))) {
+ pr_err("%s: preallocated buffers are too small!\n", __func__);
+ return ERROR_ALLOC;
+ }
+
+#ifdef I2C_INTERFACE
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, cmd, cmdLength);
+ cmd = info->io_write_buf;
+ }
+
+ /* write msg */
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)cmdLength;
+ I2CMsg[0].buf = (__u8 *)cmd;
+
+ /* read msg */
+ I2CMsg[1].addr = (__u16)I2CSAD;
+ I2CMsg[1].flags = I2C_M_RD;
+ I2CMsg[1].len = byteToRead;
+ if (dma_safe == false)
+ I2CMsg[1].buf = (__u8 *)info->io_read_buf;
+ else
+ I2CMsg[1].buf = (__u8 *)outBuf;
+#else
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, cmd, cmdLength);
+ cmd = info->io_write_buf;
+ }
+
+ spi_message_init(&msg);
+
+ transfer[0].len = cmdLength;
+ transfer[0].tx_buf = cmd;
+ transfer[0].rx_buf = NULL;
+ spi_message_add_tail(&transfer[0], &msg);
+
+ transfer[1].len = byteToRead;
+ transfer[1].delay_usecs = SPI_DELAY_CS;
+ transfer[1].tx_buf = NULL;
+ if (dma_safe == false)
+ transfer[1].rx_buf = info->io_read_buf;
+ else
+ transfer[1].rx_buf = outBuf;
+ spi_message_add_tail(&transfer[1], &msg);
+
+#endif
+
+ if (client == NULL)
+ return ERROR_BUS_O;
+
+ while (retry < I2C_RETRY && ret < OK) {
+#ifdef I2C_INTERFACE
+ ret = i2c_transfer(getClient()->adapter, I2CMsg, 2);
+#else
+ ret = spi_sync(getClient(), &msg);
+#endif
+
+ retry++;
+ if (ret < OK)
+ mdelay(I2C_WAIT_BEFORE_RETRY);
+ }
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_WR);
+ return ERROR_BUS_WR;
+ }
+
+ if (dma_safe == false)
+ memcpy(outBuf, info->io_read_buf, byteToRead);
+
+ return OK;
+}
+
+
+/**
+ * Perform a bus write
+ * @param cmd byte array containing the command to write
+ * @param cmdLength size of cmd
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_write_internal(u8 *cmd, int cmdLength, bool dma_safe)
+{
+ int ret = -1;
+ int retry = 0;
+ struct fts_ts_info *info = getDrvInfo();
+#ifdef I2C_INTERFACE
+ struct i2c_msg I2CMsg[1];
+#else
+ struct spi_message msg;
+ struct spi_transfer transfer[1] = { { 0 } };
+#endif
+
+ if (dma_safe == false && cmdLength > sizeof(info->io_write_buf)) {
+ pr_err("%s: preallocated buffers are too small!\n", __func__);
+ return ERROR_ALLOC;
+ }
+
+#ifdef I2C_INTERFACE
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, cmd, cmdLength);
+ cmd = info->io_write_buf;
+ }
+
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)cmdLength;
+ I2CMsg[0].buf = (__u8 *)cmd;
+#else
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, cmd, cmdLength);
+ cmd = info->io_write_buf;
+ }
+
+ spi_message_init(&msg);
+
+ transfer[0].len = cmdLength;
+ transfer[0].delay_usecs = SPI_DELAY_CS;
+ transfer[0].tx_buf = cmd;
+ transfer[0].rx_buf = NULL;
+ spi_message_add_tail(&transfer[0], &msg);
+#endif
+
+
+ if (client == NULL)
+ return ERROR_BUS_O;
+ while (retry < I2C_RETRY && ret < OK) {
+#ifdef I2C_INTERFACE
+ ret = i2c_transfer(getClient()->adapter, I2CMsg, 1);
+#else
+ ret = spi_sync(getClient(), &msg);
+#endif
+
+ retry++;
+ if (ret < OK)
+ mdelay(I2C_WAIT_BEFORE_RETRY);
+ /* pr_err("fts_writeCmd: attempt %d\n", retry); */
+ }
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+ return OK;
+}
+
+/**
+ * Write a FW command to the IC and check automatically the echo event
+ * @param cmd byte array containing the command to send
+ * @param cmdLength size of cmd
+ * @return OK if success, or an error code which specify the type of error
+ */
+static int fts_writeFwCmd_internal(u8 *cmd, int cmdLength, bool dma_safe)
+{
+ int ret = -1;
+ int ret2 = -1;
+ int retry = 0;
+ struct fts_ts_info *info = getDrvInfo();
+#ifdef I2C_INTERFACE
+ struct i2c_msg I2CMsg[1];
+#else
+ struct spi_message msg;
+ struct spi_transfer transfer[1] = { { 0 } };
+#endif
+
+ if (dma_safe == false && cmdLength > sizeof(info->io_write_buf)) {
+ pr_err("%s: preallocated buffers are too small!\n", __func__);
+ return ERROR_ALLOC;
+ }
+
+#ifdef I2C_INTERFACE
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, cmd, cmdLength);
+ cmd = info->io_write_buf;
+ }
+
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)cmdLength;
+ I2CMsg[0].buf = (__u8 *)cmd;
+#else
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, cmd, cmdLength);
+ cmd = info->io_write_buf;
+ }
+
+ spi_message_init(&msg);
+
+ transfer[0].len = cmdLength;
+ transfer[0].delay_usecs = SPI_DELAY_CS;
+ transfer[0].tx_buf = cmd;
+ transfer[0].rx_buf = NULL;
+ spi_message_add_tail(&transfer[0], &msg);
+#endif
+
+ if (client == NULL)
+ return ERROR_BUS_O;
+ resetErrorList();
+ while (retry < I2C_RETRY && (ret < OK || ret2 < OK)) {
+#ifdef I2C_INTERFACE
+ ret = i2c_transfer(getClient()->adapter, I2CMsg, 1);
+#else
+ ret = spi_sync(getClient(), &msg);
+#endif
+ retry++;
+ if (ret >= 0)
+ ret2 = checkEcho(cmd, cmdLength);
+ if (ret < OK || ret2 < OK)
+ mdelay(I2C_WAIT_BEFORE_RETRY);
+ /* pr_err("fts_writeCmd: attempt %d\n", retry); */
+ }
+ if (ret < 0) {
+ pr_err("fts_writeFwCmd: ERROR %08X\n", ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+ if (ret2 < OK) {
+ pr_err("fts_writeFwCmd: check echo ERROR %08X\n", ret2);
+ return ret2;
+ }
+ return OK;
+}
+
+
+/**
+ * Perform two bus write and one bus read without any stop condition
+ * In case of FTI this function is not supported and the same sequence
+ * can be achieved calling fts_write followed by an fts_writeRead.
+ * @param writeCmd1 byte array containing the first command to write
+ * @param writeCmdLength size of writeCmd1
+ * @param readCmd1 byte array containing the second command to write
+ * @param readCmdLength size of readCmd1
+ * @param outBuf pointer of a byte array which should contain the bytes read
+ * from the IC
+ * @param byteToRead number of bytes to read
+ * @return OK if success or an error code which specify the type of error
+ */
+static int fts_writeThenWriteRead_internal(u8 *writeCmd1, int writeCmdLength,
+ u8 *readCmd1, int readCmdLength,
+ u8 *outBuf, int byteToRead,
+ bool dma_safe)
+{
+ int ret = -1;
+ int retry = 0;
+ struct fts_ts_info *info = getDrvInfo();
+#ifdef I2C_INTERFACE
+ struct i2c_msg I2CMsg[3];
+#else
+ struct spi_message msg;
+ struct spi_transfer transfer[3] = { { 0 }, { 0 }, { 0 } };
+#endif
+
+ if (dma_safe == false && (writeCmdLength > sizeof(info->io_write_buf) ||
+ readCmdLength > sizeof(info->io_extra_write_buf) ||
+ byteToRead > sizeof(info->io_read_buf))) {
+ pr_err("%s: preallocated buffers are too small!\n", __func__);
+ return ERROR_ALLOC;
+ }
+
+#ifdef I2C_INTERFACE
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, writeCmd1, writeCmdLength);
+ writeCmd1 = info->io_write_buf;
+ memcpy(info->io_extra_write_buf, readCmd1, readCmdLength);
+ readCmd1 = info->io_extra_write_buf;
+ }
+
+ /* write msg */
+ I2CMsg[0].addr = (__u16)I2CSAD;
+ I2CMsg[0].flags = (__u16)0;
+ I2CMsg[0].len = (__u16)writeCmdLength;
+ I2CMsg[0].buf = (__u8 *)writeCmd1;
+
+ /* write msg */
+ I2CMsg[1].addr = (__u16)I2CSAD;
+ I2CMsg[1].flags = (__u16)0;
+ I2CMsg[1].len = (__u16)readCmdLength;
+ I2CMsg[1].buf = (__u8 *)readCmd1;
+
+ /* read msg */
+ I2CMsg[2].addr = (__u16)I2CSAD;
+ I2CMsg[2].flags = I2C_M_RD;
+ I2CMsg[2].len = byteToRead;
+ if (dma_safe == false)
+ I2CMsg[2].buf = (__u8 *)info->io_read_buf;
+ else
+ I2CMsg[2].buf = (__u8 *)outBuf;
+#else
+ if (dma_safe == false) {
+ memcpy(info->io_write_buf, writeCmd1, writeCmdLength);
+ writeCmd1 = info->io_write_buf;
+ memcpy(info->io_extra_write_buf, readCmd1, readCmdLength);
+ readCmd1 = info->io_extra_write_buf;
+ }
+
+ spi_message_init(&msg);
+
+ transfer[0].len = writeCmdLength;
+ transfer[0].tx_buf = writeCmd1;
+ transfer[0].rx_buf = NULL;
+ spi_message_add_tail(&transfer[0], &msg);
+
+ transfer[1].len = readCmdLength;
+ transfer[1].tx_buf = readCmd1;
+ transfer[1].rx_buf = NULL;
+ spi_message_add_tail(&transfer[1], &msg);
+
+ transfer[2].len = byteToRead;
+ transfer[2].delay_usecs = SPI_DELAY_CS;
+ transfer[2].tx_buf = NULL;
+ if (dma_safe == false)
+ transfer[2].rx_buf = info->io_read_buf;
+ else
+ transfer[2].rx_buf = outBuf;
+ spi_message_add_tail(&transfer[2], &msg);
+#endif
+
+ if (client == NULL)
+ return ERROR_BUS_O;
+ while (retry < I2C_RETRY && ret < OK) {
+#ifdef I2C_INTERFACE
+ ret = i2c_transfer(getClient()->adapter, I2CMsg, 3);
+#else
+ ret = spi_sync(getClient(), &msg);
+#endif
+ retry++;
+ if (ret < OK)
+ mdelay(I2C_WAIT_BEFORE_RETRY);
+ }
+
+ if (ret < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_BUS_WR);
+ return ERROR_BUS_WR;
+ }
+
+ if (dma_safe == false)
+ memcpy(outBuf, info->io_read_buf, byteToRead);
+
+ return OK;
+}
+
+/* Wrapper API for i2c read and write */
+int fts_read(u8 *outBuf, int byteToRead)
+{
+ return fts_read_internal(outBuf, byteToRead, false);
+}
+
+int fts_read_heap(u8 *outBuf, int byteToRead)
+{
+ return fts_read_internal(outBuf, byteToRead, true);
+}
+
+int fts_writeRead(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead)
+{
+ return fts_writeRead_internal(cmd, cmdLength, outBuf, byteToRead,
+ false);
+}
+
+int fts_writeRead_heap(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead)
+{
+ return fts_writeRead_internal(cmd, cmdLength, outBuf, byteToRead, true);
+}
+
+int fts_write(u8 *cmd, int cmdLength)
+{
+ return fts_write_internal(cmd, cmdLength, false);
+}
+
+int fts_write_heap(u8 *cmd, int cmdLength)
+{
+ return fts_write_internal(cmd, cmdLength, true);
+}
+
+int fts_writeFwCmd(u8 *cmd, int cmdLength)
+{
+ return fts_writeFwCmd_internal(cmd, cmdLength, false);
+}
+
+int fts_writeFwCmd_heap(u8 *cmd, int cmdLength)
+{
+ return fts_writeFwCmd_internal(cmd, cmdLength, true);
+}
+
+int fts_writeThenWriteRead(u8 *writeCmd1, int writeCmdLength,
+ u8 *readCmd1, int readCmdLength,
+ u8 *outBuf, int byteToRead)
+{
+ return fts_writeThenWriteRead_internal(writeCmd1, writeCmdLength,
+ readCmd1, readCmdLength,
+ outBuf, byteToRead, false);
+}
+
+int fts_writeThenWriteRead_heap(u8 *writeCmd1, int writeCmdLength,
+ u8 *readCmd1, int readCmdLength,
+ u8 *outBuf, int byteToRead)
+{
+ return fts_writeThenWriteRead_internal(writeCmd1, writeCmdLength,
+ readCmd1, readCmdLength,
+ outBuf, byteToRead, true);
+}
+
+/**
+ * Perform a chunked write with one byte op code and 1 to 8 bytes address
+ * @param cmd byte containing the op code to write
+ * @param addrSize address size in byte
+ * @param address the starting address
+ * @param data pointer of a byte array which contain the bytes to write
+ * @param dataSize size of data
+ * @return OK if success or an error code which specify the type of error
+ */
+/* this function works only if the address is max 8 bytes */
+int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data,
+ int dataSize)
+{
+ u8 *finalCmd;
+ int remaining = dataSize;
+ int toWrite = 0, i = 0;
+ struct fts_ts_info *info = getDrvInfo();
+
+ finalCmd = info->io_write_buf;
+
+ if (addrSize <= sizeof(u64)) {
+ while (remaining > 0) {
+ if (remaining >= WRITE_CHUNK) {
+ toWrite = WRITE_CHUNK;
+ remaining -= WRITE_CHUNK;
+ } else {
+ toWrite = remaining;
+ remaining = 0;
+ }
+
+ finalCmd[0] = cmd;
+ pr_debug("%s: addrSize = %d\n", __func__, addrSize);
+ for (i = 0; i < addrSize; i++) {
+ finalCmd[i + 1] = (u8)((address >> ((addrSize -
+ 1 - i) *
+ 8)) & 0xFF);
+ pr_debug("%s: cmd[%d] = %02X\n",
+ __func__, i + 1, finalCmd[i + 1]);
+ }
+
+ memcpy(&finalCmd[addrSize + 1], data, toWrite);
+
+ if (fts_write_heap(finalCmd, 1 + addrSize + toWrite)
+ < OK) {
+ pr_err(" %s: ERROR %08X\n",
+ __func__, ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ address += toWrite;
+
+ data += toWrite;
+ }
+ } else
+ pr_err("%s: address size bigger than max allowed %lu... ERROR %08X\n",
+ __func__, sizeof(u64), ERROR_OP_NOT_ALLOW);
+
+ return OK;
+}
+
+/**
+ * Perform a chunked write read with one byte op code and 1 to 8 bytes address
+ * and dummy byte support.
+ * @param cmd byte containing the op code to write
+ * @param addrSize address size in byte
+ * @param address the starting address
+ * @param outBuf pointer of a byte array which contain the bytes to read
+ * @param byteToRead number of bytes to read
+ * @param hasDummyByte if the first byte of each reading is dummy (must be
+ * skipped)
+ * set to 1, otherwise if it is valid set to 0 (or any other value)
+ * @return OK if success or an error code which specify the type of error
+ */
+int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf,
+ int byteToRead, int hasDummyByte)
+{
+ u8 *finalCmd;
+ u8 *buff;
+ int remaining = byteToRead;
+ int toRead = 0, i = 0;
+ struct fts_ts_info *info = getDrvInfo();
+
+ finalCmd = info->io_write_buf;
+ buff = info->io_read_buf;
+
+ while (remaining > 0) {
+ if (remaining >= READ_CHUNK) {
+ toRead = READ_CHUNK;
+ remaining -= READ_CHUNK;
+ } else {
+ toRead = remaining;
+ remaining = 0;
+ }
+
+ finalCmd[0] = cmd;
+ for (i = 0; i < addrSize; i++)
+ finalCmd[i + 1] = (u8)((address >> ((addrSize - 1 - i) *
+ 8)) & 0xFF);
+
+ if (hasDummyByte == 1) {
+ if (fts_writeRead_heap(finalCmd, 1 + addrSize, buff,
+ toRead + 1) < OK) {
+ pr_err("%s: read error... ERROR %08X\n",
+ __func__, ERROR_BUS_WR);
+ return ERROR_BUS_WR;
+ }
+ memcpy(outBuf, buff + 1, toRead);
+ } else {
+ if (fts_writeRead_heap(finalCmd, 1 + addrSize, buff,
+ toRead) < OK) {
+ pr_err("%s: read error... ERROR %08X\n",
+ __func__, ERROR_BUS_WR);
+ return ERROR_BUS_WR;
+ }
+ memcpy(outBuf, buff, toRead);
+ }
+
+ address += toRead;
+
+ outBuf += toRead;
+ }
+
+ return OK;
+}
+
+/**
+ * Perform a chunked write followed by a second write with one byte op code
+ * for each write and 1 to 8 bytes address (the sum of the 2 address size of
+ * the two writes can not exceed 8 bytes)
+ * @param cmd1 byte containing the op code of first write
+ * @param addrSize1 address size in byte of first write
+ * @param cmd2 byte containing the op code of second write
+ * @param addrSize2 address size in byte of second write
+ * @param address the starting address
+ * @param data pointer of a byte array which contain the bytes to write
+ * @param dataSize size of data
+ * @return OK if success or an error code which specify the type of error
+ */
+/* this function works only if the sum of two addresses in the two commands is
+ * max 8 bytes */
+int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2,
+ AddrSize addrSize2, u64 address, u8 *data,
+ int dataSize)
+{
+ u8 *finalCmd1;
+ u8 *finalCmd2;
+ int remaining = dataSize;
+ int toWrite = 0, i = 0;
+ struct fts_ts_info *info = getDrvInfo();
+
+ finalCmd1 = info->io_write_buf;
+ finalCmd2 = info->io_extra_write_buf;
+
+ while (remaining > 0) {
+ if (remaining >= WRITE_CHUNK) {
+ toWrite = WRITE_CHUNK;
+ remaining -= WRITE_CHUNK;
+ } else {
+ toWrite = remaining;
+ remaining = 0;
+ }
+
+ finalCmd1[0] = cmd1;
+ for (i = 0; i < addrSize1; i++)
+ finalCmd1[i + 1] = (u8)((address >> ((addrSize1 +
+ addrSize2 - 1 -
+ i) * 8)) & 0xFF);
+
+ finalCmd2[0] = cmd2;
+ for (i = addrSize1; i < addrSize1 + addrSize2; i++)
+ finalCmd2[i - addrSize1 + 1] = (u8)((address >>
+ ((addrSize1 +
+ addrSize2 - 1 -
+ i) * 8)) & 0xFF);
+
+ memcpy(&finalCmd2[addrSize2 + 1], data, toWrite);
+
+ if (fts_write_heap(finalCmd1, 1 + addrSize1) < OK) {
+ pr_err("%s: first write error... ERROR %08X\n",
+ __func__, ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ if (fts_write_heap(finalCmd2, 1 + addrSize2 + toWrite) < OK) {
+ pr_err("%s: second write error... ERROR %08X\n",
+ __func__, ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ address += toWrite;
+
+ data += toWrite;
+ }
+
+ return OK;
+}
+
+/**
+ * Perform a chunked write followed by a write read with one byte op code
+ * and 1 to 8 bytes address for each write and dummy byte support.
+ * @param cmd1 byte containing the op code of first write
+ * @param addrSize1 address size in byte of first write
+ * @param cmd2 byte containing the op code of second write read
+ * @param addrSize2 address size in byte of second write read
+ * @param address the starting address
+ * @param outBuf pointer of a byte array which contain the bytes to read
+ * @param byteToRead number of bytes to read
+ * @param hasDummyByte if the first byte of each reading is dummy (must be
+ * skipped) set to 1,
+ * otherwise if it is valid set to 0 (or any other value)
+ * @return OK if success or an error code which specify the type of error
+ */
+/* this function works only if the sum of two addresses in the two commands is
+ * max 8 bytes */
+int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2,
+ AddrSize addrSize2, u64 address, u8 *outBuf,
+ int byteToRead, int hasDummyByte)
+{
+ u8 *finalCmd1;
+ u8 *finalCmd2;
+ u8 *buff;
+ int remaining = byteToRead;
+ int toRead = 0, i = 0;
+ struct fts_ts_info *info = getDrvInfo();
+
+ finalCmd1 = info->io_write_buf;
+ finalCmd2 = info->io_extra_write_buf;
+ buff = info->io_read_buf;
+
+ while (remaining > 0) {
+ if (remaining >= READ_CHUNK) {
+ toRead = READ_CHUNK;
+ remaining -= READ_CHUNK;
+ } else {
+ toRead = remaining;
+ remaining = 0;
+ }
+
+
+ finalCmd1[0] = cmd1;
+ for (i = 0; i < addrSize1; i++)
+ finalCmd1[i + 1] = (u8)((address >> ((addrSize1 +
+ addrSize2 - 1 -
+ i) * 8)) & 0xFF);
+
+ finalCmd2[0] = cmd2;
+ for (i = addrSize1; i < addrSize1 + addrSize2; i++)
+ finalCmd2[i - addrSize1 + 1] = (u8)((address >>
+ ((addrSize1 +
+ addrSize2 - 1 -
+ i) * 8)) & 0xFF);
+
+ if (fts_write_heap(finalCmd1, 1 + addrSize1) < OK) {
+ pr_err("%s: first write error... ERROR %08X\n",
+ __func__, ERROR_BUS_W);
+ return ERROR_BUS_W;
+ }
+
+ if (hasDummyByte == 1) {
+ if (fts_writeRead_heap(finalCmd2, 1 + addrSize2, buff,
+ toRead + 1) < OK) {
+ pr_err("%s: read error... ERROR %08X\n",
+ __func__, ERROR_BUS_WR);
+ return ERROR_BUS_WR;
+ }
+ memcpy(outBuf, buff + 1, toRead);
+ } else {
+ if (fts_writeRead_heap(finalCmd2, 1 + addrSize2, buff,
+ toRead) < OK) {
+ pr_err("%s: read error... ERROR %08X\n",
+ __func__, ERROR_BUS_WR);
+ return ERROR_BUS_WR;
+ }
+ memcpy(outBuf, buff, toRead);
+ }
+
+ address += toRead;
+
+ outBuf += toRead;
+ }
+
+ return OK;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsIO.h b/drivers/input/touchscreen/stm/fts_lib/ftsIO.h
new file mode 100644
index 00000000000..f470991b05c
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsIO.h
@@ -0,0 +1,78 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * I2C/SPI Communication *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+/*!
+ * \file ftsIO.h
+ * \brief Contains all the definitions and prototypes used and implemented in
+ * ftsIO.c
+ */
+
+#ifndef FTS_IO_H
+#define FTS_IO_H
+
+#include "ftsSoftware.h"
+
+#define I2C_RETRY 3 /* /< number of retry in case of i2c
+ * failure */
+#define I2C_WAIT_BEFORE_RETRY 2 /* /< wait in ms before retry an i2c
+ * transaction */
+
+#ifdef I2C_INTERFACE
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+struct i2c_client *getClient(void);
+#else
+#include <linux/spi/spi.h>
+struct spi_device *getClient(void);
+#endif
+
+
+
+int openChannel(void *clt);
+struct device *getDev(void);
+
+
+
+/*************** NEW I2C API ****************/
+int changeSAD(u8 sad);
+int fts_read(u8 *outBuf, int byteToRead);
+int fts_read_heap(u8 *outBuf, int byteToRead);
+int fts_writeRead(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead);
+int fts_writeRead_heap(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead);
+int fts_write(u8 *cmd, int cmdLength);
+int fts_write_heap(u8 *cmd, int cmdLength);
+int fts_writeFwCmd(u8 *cmd, int cmdLength);
+int fts_writeFwCmd_heap(u8 *cmd, int cmdLength);
+int fts_writeThenWriteRead(u8 *writeCmd1, int writeCmdLength,
+ u8 *readCmd1, int readCmdLength,
+ u8 *outBuf, int byteToRead);
+int fts_writeThenWriteRead_heap(u8 *writeCmd1, int writeCmdLength,
+ u8 *readCmd1, int readCmdLength,
+ u8 *outBuf, int byteToRead);
+
+/* chunked version of fts_write */
+int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data,
+ int dataSize);
+/* chunked version of fts_writeRead */
+int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf,
+ int byteToRead, int hasDummyByte);
+/* chunked, write followed by another write */
+int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2,
+ AddrSize addrSize2, u64 address, u8 *data,
+ int dataSize);
+/* chunked, write followed by a writeRead */
+int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2,
+ AddrSize addrSize2, u64 address, u8 *outBuf,
+ int count, int hasDummyByte);
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsSoftware.h b/drivers/input/touchscreen/stm/fts_lib/ftsSoftware.h
new file mode 100644
index 00000000000..d00fdc85b3e
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsSoftware.h
@@ -0,0 +1,510 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FW related data *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsSoftware.h
+ * \brief Contains all the definitions and information related to the IC
+ * from a fw/driver point of view
+ */
+
+
+#ifndef FTS_SOFTWARE_H
+#define FTS_SOFTWARE_H
+#include <linux/types.h>
+#include "ftsHardware.h"
+
+/* signed type */
+typedef signed char i8; /* /< basic type that represent one signed byte (or 8
+ * bits) */
+
+/**
+ * Enumerator which contains all the possible address length expressed in
+ *bytes.
+ */
+typedef enum {
+ NO_ADDR = 0,
+ BITS_8 = 1,
+ BITS_16 = 2,
+ BITS_24 = 3,
+ BITS_32 = 4,
+ BITS_40 = 5,
+ BITS_48 = 6,
+ BITS_56 = 7,
+ BITS_64 = 8
+} AddrSize;
+
+
+/******************** NEW API *********************/
+
+/* HOST COMMAND */
+/** @defgroup host_command Fw Host op codes
+ * Valid op codes for fw commands
+ * @{
+ */
+
+/** @defgroup scan_mode Scan Mode
+ * @ingroup host_command
+ * Set the scanning mode required according to the parameters
+ * @{
+ */
+#define FTS_CMD_SCAN_MODE 0xA0 /* /< OP Code to set scan mode */
+/** @} */
+
+/** @defgroup feat_sel Feature Select
+ * @ingroup host_command
+ * Set the system defined features to enable/disable according the parameters
+ * @{
+ */
+#define FTS_CMD_FEATURE 0xA2 /* /< OP code to set features */
+/** @} */
+
+/** @defgroup sys_cmd System Command
+ * @ingroup host_command
+ * Execute a system command to perform core tasks
+ * @{
+ */
+#define FTS_CMD_SYSTEM 0xA4 /* /< OP code to write s system command
+ * */
+/** @} */
+
+/** @} */ /* end host_command group */
+
+/* SCAN MODE OPTION (0xA0) */
+/* Scan mode selection */
+/** @defgroup scan_opt Scan Mode Option
+ * @ingroup scan_mode
+ * Valid scanning modes and their options
+ * @{
+ */
+#define SCAN_MODE_ACTIVE 0x00 /* /< Select the Active scanning mode */
+#define SCAN_MODE_LOW_POWER 0x01 /* /< Select the low power scanning mode
+ * */
+#define SCAN_MODE_JIG_1 0x02 /* /< Select the Jig test 1 */
+#define SCAN_MODE_LOCKED 0x03 /* /< Select the Scan mode which will be
+ * locked */
+/** @}*/
+
+/* Active mode option (bitmask) */
+/** @defgroup active_bitmask Active Mode Bitmask
+ * @ingroup scan_opt
+ * Bitmask to use to enables the specific scanning with the SCAN_MODE_ACTIVE
+ * option
+ * @{
+ */
+#define ACTIVE_MULTI_TOUCH 0x01 /* /< Bit 0 MS/SS scan */
+#define ACTIVE_KEY 0x02 /* /< Bit 1 Key scan */
+#define ACTIVE_HOVER 0x04 /* /< Bit 2 Hover scan */
+#define ACTIVE_PROXIMITY 0x08 /* /< Bit 3 Proximity scan */
+#define ACTIVE_FORCE 0x10 /* /< Bit 4 Force scan */
+/** @}*/
+
+/* Locked mode option (locked mode) */
+/** @defgroup locked_opt Locked Mode Option
+ * @ingroup scan_opt
+ * Options to enable and lock specific scanning with the SCAN_MODE_LOCKED
+ * option
+ * @{
+ */
+#define LOCKED_ACTIVE 0x00 /* /< Active Scan Mode */
+#define LOCKED_HOVER 0x01 /* /< Hover Scan Mode */
+#define LOCKED_IDLE 0x02 /* /< Idle Scan Mode */
+#define LOCKED_ONLY_SELF 0x03 /* /< Only Self Sense scan mode */
+#define LOCKED_ONLY_MUTUAL_0 0x04 /* /< Only Mutual Sense scan mode at
+ * lowest freq */
+#define LOCKED_ONLY_MUTUAL_1 0x05 /* /< Only Mutual Sense scan mode */
+#define LOCKED_ONLY_MUTUAL_2 0x06 /* /< Only Mutual Sense scan mode */
+#define LOCKED_ONLY_MUTUAL_3 0x07 /* /< Only Mutual Sense scan mode at
+ * highest freq */
+#define LOCKED_LP_DETECT 0x10 /* /< Low Power SS */
+#define LOCKED_LP_ACTIVE 0x11 /* /< Low Power MS */
+/** @}*/
+
+/* FEATURE SELECT OPTION (0xA2) */
+/* Feature Selection */
+/** @defgroup feat_opt Feature Selection Option
+ * @ingroup feat_sel
+ * System defined features that can be enable/disable
+ * @{
+ */
+#define FEAT_SEL_GLOVE 0x00 /* /< Glove Mode */
+#define FEAT_SEL_COVER 0x01 /* /< Cover Mode */
+#define FEAT_SEL_CHARGER 0x02 /* /< Charger Mode */
+#define FEAT_SEL_GESTURE 0x03 /* /< Gesture Mode */
+#define FEAT_SEL_GRIP 0x04 /* /< Grip Detection */
+#define FEAT_SEL_STYLUS 0x07 /* /< Stylus Mode
+ * (this is a driver define, not
+ * available in FW) */
+/** @}*/
+
+/* Feature Settings */
+#define FEAT_ENABLE 1 /* /< General value to enable a feature
+ * */
+#define FEAT_DISABLE 0 /* /< General value to disable a feature
+ * */
+
+
+/* Charger */
+/** @defgroup charger_opt Charger Mode Option
+ * @ingroup feat_sel
+ * Option for Charger Mode, it is a bitmask where the each bit indicate a
+ * different kind of chager
+ * @{
+ */
+#define CHARGER_CABLE 0x01 /* /< normal usb charger */
+#define CHARGER_WIRLESS 0x02 /* /< wireless charger */
+/** @}*/
+
+/* Gestures */
+/** @defgroup gesture_opt Gesture Mode Option
+ * @ingroup feat_sel
+ * Gesture IDs of the predefined gesture recognized by the fw.
+ * The ID represent also the position of the corresponding bit in the gesture
+ * mask
+ * @{
+ */
+#define GEST_ID_UP_1F 0x01 /* /< Bottom to Top line */
+#define GEST_ID_DOWN_1F 0x02 /* /< Top to bottom line */
+#define GEST_ID_LEFT_1F 0x03 /* /< Right to left line */
+#define GEST_ID_RIGHT_1F 0x04 /* /< Left to right line */
+#define GEST_ID_DBLTAP 0x05 /* /< Double Tap */
+#define GEST_ID_O 0x06 /* /< 'O' */
+#define GEST_ID_C 0x07 /* /< 'C' */
+#define GEST_ID_M 0x08 /* /< 'M' */
+#define GEST_ID_W 0x09 /* /< 'W' */
+#define GEST_ID_E 0x0A /* /< 'e' */
+#define GEST_ID_L 0x0B /* /< 'L' */
+#define GEST_ID_F 0x0C /* /< 'F' */
+#define GEST_ID_V 0x0D /* /< 'V' */
+#define GEST_ID_AT 0x0E /* /< '@' */
+#define GEST_ID_S 0x0F /* /< 'S' */
+#define GEST_ID_Z 0x10 /* /< 'Z' */
+#define GEST_ID_LEFTBRACE 0x11 /* /< '<' */
+#define GEST_ID_RIGHTBRACE 0x12 /* /< '>' */
+#define GEST_ID_CARET 0x13 /* /< '^' */
+/** @}*/
+
+/* WRYTE SYSTEM COMMAND (0xA4) */
+/* System command */
+/** @defgroup sys_opt System Command Option
+ * @ingroup sys_cmd
+ * Valid System Command Parameters
+ * @{
+ */
+#define SYS_CMD_SPECIAL 0x00 /* /< Special Commands */
+#define SYS_CMD_INT 0x01 /* /< FW Interrupt Control */
+#define SYS_CMD_FORCE_CAL 0x02 /* /< Force Calibration */
+#define SYS_CMD_CX_TUNING 0x03 /* /< CX initialization */
+#define SYS_CMD_ITO 0x04 /* /< ITO test */
+#define SYS_CMD_SAVE_FLASH 0x05 /* /< Saving to flash */
+#define SYS_CMD_LOAD_DATA 0x06 /* /< Load Host data memory */
+#define SYS_CMD_SPECIAL_TUNING 0x08 /* /< Perform some special tuning */
+/** @} */
+
+/* System command settings */
+/* Special commands */
+/** @defgroup sys_special_opt Special Command Option
+ * @ingroup sys_cmd
+ * Valid special command
+ * @{
+ */
+#define SPECIAL_SYS_RESET 0x00 /* /< System Reset triggered by
+ * the FW */
+#define SPECIAL_FIFO_FLUSH 0x01 /* /< Flush of the FIFO */
+#define SPECIAL_PANEL_INIT 0x02 /* /< Panel Initialization */
+#define SPECIAL_FULL_PANEL_INIT 0x03 /* /< Full panel initialization
+ * */
+#define SPECIAL_WRITE_HOST_MEM_TO_FLASH 0x04 /* /< Write */
+/** @} */
+
+
+/* Force Cal and Cx auto tuning */
+/** @defgroup forcecal_cx_opt Force Cal and Tuning Option
+ * @ingroup sys_cmd
+ * Valid bitmask for triggering forcecal or performing manual autotune
+ * @{
+ */
+#define CAL_MS_TOUCH 0x01 /* /< Mutual Sense Touch */
+#define CAL_MS_LOW_POWER 0x02 /* /< Mutual Sense Touch in low power
+ * mode */
+#define CAL_SS_TOUCH 0x04 /* /< Self Sense Touch */
+#define CAL_SS_IDLE 0x08 /* /< Self Sense Touch in idle mode */
+#define CAL_MS_KEY 0x10 /* /< Mutual Sense Key */
+#define CAL_SS_KEY 0x20 /* /< Self Sense Key */
+#define CAL_MS_FORCE 0x40 /* /< Mutual Sense Force */
+#define CAL_SS_FORCE 0x80 /* /< Self Sense Force */
+/** @} */
+
+/* ITO checks (position of the bit in the mask) */
+/** @defgroup ito_opt ITO Test Option
+ * @ingroup sys_cmd
+ * Valid option for the ITO test
+ * @{
+ */
+#define ITO_FORCE_OPEN 0x00 /* /< Check if some force channels is
+ * open */
+#define ITO_SENSE_OPEN 0x01 /* /< Check if some sense channels is
+ * open */
+#define ITO_FORCE_GROUND 0x02 /* /< Check if some force channels is
+ * short to ground */
+#define ITO_SENSE_GROUND 0x03 /* /< Check if some sense channels is
+ * short to ground */
+#define ITO_FORCE_VDD 0x04 /* /< Check if some force channels is
+ * short to VDD */
+#define ITO_SENSE_VDD 0x05 /* /< Check if some sense channels is
+ * short to VDD */
+#define ITO_FORCE_FORCE 0x06 /* /< Check force to force channels */
+#define ITO_FORCE_SENSE 0x07 /* /< Check force to sense channels */
+#define ITO_SENSE_SENSE 0x08 /* /< Check sense to sense channels */
+#define ITO_KEY_FORCE_OPEN 0x09 /* /< Check if some force channels used
+ * for the key is open */
+#define ITO_KEY_SENSE_OPEN 0x0A /* /< Check if some sense channels used
+ * for the key is open */
+/** @}*/
+
+/* Save flash */
+/** @defgroup save_opt Save to Flash Option
+ * @ingroup sys_cmd
+ * Valid option for saving data to the Flash
+ * @{
+ */
+#define SAVE_FW_CONF 0x01 /* /< Save the confing to the flash */
+#define SAVE_CX 0x02 /* /< Save the CX to the flash */
+#define SAVE_PANEL_CONF 0x04 /* /< Save the Panel configuration to the flash
+ * */
+/** @}*/
+
+/* Load Data */
+/** @defgroup load_opt Load Host Data Option
+ * @ingroup sys_cmd
+ * Valid option to ask to the FW to load host data into the memory
+ * @{
+ */
+#define LOAD_SYS_INFO 0x01 /* /< Load System Info */
+#define LOAD_CX_MS_TOUCH 0x10 /* /< Load MS Init Data for
+ * Active Mode */
+#define LOAD_CX_MS_LOW_POWER 0x11 /* /< Load MS Init Data for Low
+ * Power Mode */
+#define LOAD_CX_SS_TOUCH 0x12 /* /< Load SS Init Data for
+ * Active Mode */
+#define LOAD_CX_SS_TOUCH_IDLE 0x13 /* /< Load SS Init Data for Low
+ * Power Mode */
+#define LOAD_CX_MS_KEY 0x14 /* /< Load MS Init Data for Key
+ * */
+#define LOAD_CX_SS_KEY 0x15 /* /< Load SS Init Data for Key
+ * */
+#define LOAD_CX_MS_FORCE 0x16 /* /< Load MS Init Data for
+ * Force */
+#define LOAD_CX_SS_FORCE 0x17 /* /< Load SS Init Data for
+ * Force */
+#define LOAD_SYNC_FRAME_RAW 0x30 /* /< Load a Synchronized Raw
+ * Frame */
+#define LOAD_SYNC_FRAME_FILTER 0x31 /* /< Load a Synchronized Filter
+ * Frame */
+#define LOAD_SYNC_FRAME_STRENGTH 0x33 /* /< Load a Synchronized
+ * Strength Frame */
+#define LOAD_SYNC_FRAME_BASELINE 0x32 /* /< Load a Synchronized
+ * Baseline Frame */
+#define LOAD_PANEL_CX_TOT_MS_TOUCH 0x50 /* /< Load TOT MS Init Data for
+ * Active Mode */
+#define LOAD_PANEL_CX_TOT_MS_LOW_POWER 0x51 /* /< Load TOT MS Init Data for
+ * Low Power Mode */
+#define LOAD_PANEL_CX_TOT_SS_TOUCH 0x52 /* /< Load TOT SS Init Data for
+ * Active Mode */
+#define LOAD_PANEL_CX_TOT_SS_TOUCH_IDLE 0x53 /* /< Load TOT SS Init Data for
+ * Low Power Mode */
+#define LOAD_PANEL_CX_TOT_MS_KEY 0x54 /* /< Load TOT MS Init Data for
+ * Key */
+#define LOAD_PANEL_CX_TOT_SS_KEY 0x55 /* /< Load TOT SS Init Data for
+ * Key */
+#define LOAD_PANEL_CX_TOT_MS_FORCE 0x56 /* /< Load TOT MS Init Data for
+ * Force */
+#define LOAD_PANEL_CX_TOT_SS_FORCE 0x57 /* /< Load TOT SS Init Data for
+ * Force */
+#define LOAD_SENS_CAL_COEFF 0xC0 /* /< Load Sesitivity
+ * Calibration Coefficients */
+/** @}*/
+
+/* Special Tuning */
+/** @defgroup spcl_tun_opt Special Tuning Option
+ * @ingroup sys_cmd
+ * Valid special tuning operations which the fw can perform (bitmask)
+ * @{
+ */
+#define SPECIAL_TUNING_LP_TIMER 0x01 /* /< Perform LP Timer calibration */
+#define SPECIAL_TUNING_IOFF 0x02 /* /< Perform Ioff calibration */
+
+/** @}*/
+
+/* EVENT ID */
+/** @defgroup events_group FW Event IDs and Types
+ * Event IDs and Types pushed by the FW into the FIFO
+ * @{
+ */
+#define EVT_ID_NOEVENT 0x00 /* /< No Events */
+#define EVT_ID_CONTROLLER_READY 0x03 /* /< Controller ready, issued after a
+ * system reset. */
+#define EVT_ID_ENTER_POINT 0x13 /* /< Touch enter in the sensing area */
+#define EVT_ID_MOTION_POINT 0x23 /* /< Touch motion (a specific touch
+ * changed position) */
+#define EVT_ID_LEAVE_POINT 0x33 /* /< Touch leave the sensing area */
+#define EVT_ID_STATUS_UPDATE 0x43 /* /< FW report a system condition
+ * change */
+#define EVT_ID_USER_REPORT 0x53 /* /< User related events triggered
+ * (keys, gestures, proximity etc) */
+#define EVT_ID_DEBUG 0xE3 /* /< Debug Info */
+#define EVT_ID_ERROR 0xF3 /* /< Error Event */
+
+/* /< Max number of unique event IDs supported */
+#define NUM_EVT_ID (((EVT_ID_ERROR & 0xF0) >> 4) + 1)
+
+/** @}*/
+
+/* STATUS TYPE */
+/** @defgroup status_type Status Event Types
+ * @ingroup events_group
+ * Types of EVT_ID_STATUS_UPDATE events
+ * @{
+ */
+#define EVT_TYPE_STATUS_ECHO 0x01 /* /< Echo event,
+ * contain the first 5 bytes of
+ * the FW command sent */
+#define EVT_TYPE_STATUS_FRAME_DROP 0x03 /* /< Some frame was skipped
+ * during the elaboration */
+#define EVT_TYPE_STATUS_FORCE_CAL 0x05 /* /< Force Calibration has
+ * triggered */
+#define EVT_TYPE_STATUS_WATER 0x06 /* /< Water Mode */
+#define EVT_TYPE_STATUS_SS_RAW_SAT 0x07 /* /< Self Sense data saturated
+ * */
+/** @} */
+
+/* USER TYPE */
+/** @defgroup user_type User Event Types
+ * @ingroup events_group
+ * Types of EVT_ID_USER_REPORT events generated by thw FW
+ * @{
+ */
+#define EVT_TYPE_USER_KEY 0x00 /* /< Keys pressed/relesed event report
+ * */
+#define EVT_TYPE_USER_PROXIMITY 0x01 /* /< Proximity detection event report
+ * */
+#define EVT_TYPE_USER_GESTURE 0x02 /* /< Gesture detection event report */
+/** @}*/
+
+/* ERROR TYPE */
+/** @defgroup error_type Error Event Types
+ * @ingroup events_group
+ * Types of EVT_ID_ERROR events reported by the FW
+ * @{
+ */
+#define EVT_TYPE_ERROR_WATCHDOG 0x06 /* /< Watchdog timer expired */
+
+#define EVT_TYPE_ERROR_CRC_CFG_HEAD 0x20 /* /< CRC error in the Config
+ * Area Header */
+#define EVT_TYPE_ERROR_CRC_CFG 0x21 /* /< CRC error in the Config
+ * Area */
+#define EVT_TYPE_ERROR_CRC_PANEL_HEAD 0x22 /* /< CRC error in the Panel
+ * Area Header */
+#define EVT_TYPE_ERROR_CRC_PANEL 0x23 /* /< CRC error in the Panel
+ * Area */
+
+#define EVT_TYPE_ERROR_ITO_FORCETOGND 0x60 /* /< Force channel/s short to
+ * ground */
+#define EVT_TYPE_ERROR_ITO_SENSETOGND 0x61 /* /< Sense channel/s short to
+ * ground */
+#define EVT_TYPE_ERROR_ITO_FORCETOVDD 0x62 /* /< Force channel/s short to
+ * VDD */
+#define EVT_TYPE_ERROR_ITO_SENSETOVDD 0x63 /* /< Sense channel/s short to
+ * VDD */
+#define EVT_TYPE_ERROR_ITO_FORCE_P2P 0x64 /* /< Pin to Pin short Force
+ * channel/s */
+#define EVT_TYPE_ERROR_ITO_SENSE_P2P 0x65 /* /< Pin to Pin short Sense
+ * channel/s */
+#define EVT_TYPE_ERROR_ITO_FORCEOPEN 0x66 /* /< Force Panel open */
+#define EVT_TYPE_ERROR_ITO_SENSEOPEN 0x67 /* /< Sense Panel open */
+#define EVT_TYPE_ERROR_ITO_KEYOPEN 0x68 /* /< Key open */
+
+#define EVT_TYPE_ERROR_CRC_CX_HEAD 0xA0 /* /< CRC error in the CX Area
+ * Header */
+#define EVT_TYPE_ERROR_CRC_CX 0xA1 /* /< CRC error in the CX Area
+ * */
+#define EVT_TYPE_ERROR_FLASH_FAILED 0xA4 /* Flash error, cause unknown */
+#define EVT_TYPE_ERROR_CRC_CX_SUB_HEAD 0xA5 /* /< CRC error in the CX
+ * Subsection Area Header */
+#define EVT_TYPE_ERROR_CRC_CX_SUB 0xA6 /* /< CRC error in the CX
+ * Subsection Area */
+
+#define EVT_TYPE_ERROR_ESD 0xF0 /* /< ESD error */
+/** @}*/
+
+
+/** @defgroup address Chip Address
+ * Collection of HW and SW Addresses useful to collect different kind of data
+ * @{
+ */
+
+/** @defgroup config_adr SW Address
+ * @ingroup address
+ * Important addresses of data stored into Config memory (and sometimes their
+ * dimensions)
+ * @{
+ */
+#define ADDR_CONFIG_ID 0x0010 /* /< Starting Address of the config ID
+ * */
+#define CONFIG_ID_BYTE 2 /* /< Number of bytes of config ID */
+#define ADDR_CONFIG_SENSE_LEN 0x0030 /* /< Address where is stored the number
+ * of sense channels */
+#define ADDR_CONFIG_FORCE_LEN 0x0031 /* /< Address where is stored the number
+ * of force channels */
+#define ADDR_CONFIG_AUTOCAL 0x0040 /* /< Address where is stored the Auto
+ * Calibration register */
+#define ADDR_CONFIG_T_CYCLE 0x00ED /* /< Address where is stored the MS T
+ * cycle */
+#define ADDR_CONFIG_MNM 0x01F0 /* /< Address where is stored the MNM
+ * register */
+#define ADDR_CONFIG_MRN 0x01F1 /* /< Address where is stored the MRN
+ * register */
+#define ADDR_CONFIG_R0_CYCLE 0x01F2 /* /< Address where is stored the first
+ * R cycle */
+/** @}*/
+
+/** @}*/
+
+/* ERROR INFO */
+#define ERROR_DUMP_ROW_SIZE 32 /* /< number of rows of the error memory
+ * */
+#define ERROR_DUMP_COL_SIZE 4 /* /< number of bytes for each row of
+ * the error memory */
+#define ERROR_DUMP_SIGNATURE 0xFA5005AF /* /< first row signature of a
+ * proper dump */
+
+/* Touch Types */
+#define TOUCH_TYPE_INVALID 0x00 /* /< Invalid touch type */
+#define TOUCH_TYPE_FINGER 0x01 /* /< Finger touch */
+#define TOUCH_TYPE_GLOVE 0x02 /* /< Glove touch */
+#define TOUCH_TYPE_STYLUS 0x03 /* /< Stylus touch */
+#define TOUCH_TYPE_PALM 0x04 /* /< Palm touch */
+#define TOUCH_TYPE_HOVER 0x05 /* /< Hovering touch */
+
+/* Keys code */
+#define FTS_KEY_0 0x01 /* /< Key 0 bit */
+#define FTS_KEY_1 0x02 /* /< Key 1 bit */
+#define FTS_KEY_2 0x04 /* /< Key 2 bit */
+#define FTS_KEY_3 0x08 /* /< Key 3 bit */
+#define FTS_KEY_4 0x10 /* /< Key 4 bit */
+#define FTS_KEY_5 0x20 /* /< Key 5 bit */
+#define FTS_KEY_6 0x40 /* /< Key 6 bit */
+#define FTS_KEY_7 0x80 /* /< Key 7 bit */
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTest.c b/drivers/input/touchscreen/stm/fts_lib/ftsTest.c
new file mode 100644
index 00000000000..4e1ec9f45cd
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsTest.c
@@ -0,0 +1,5268 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS API for MP test *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsTest.c
+ * \brief Contains all the functions related to the Mass Production Test
+ */
+
+#include "ftsCompensation.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsFrame.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTest.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "../fts.h"
+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/serio.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/firmware.h>
+
+
+#ifdef LIMITS_H_FILE
+#include "../fts_limits.h"
+#endif
+
+
+TestToDo tests; /* /< global variable that specify the tests to perform during
+ * the Mass Production Test */
+static LimitFile limit_file; /* /< variable which contains the limit file
+ * during test */
+
+/**
+ * Initialize the testToDo variable with the default tests to perform during
+ * the Mass Production Test
+ * @return OK
+ */
+int initTestToDo(void)
+{
+ /*** Initialize Limit File ***/
+ limit_file.size = 0;
+ limit_file.data = NULL;
+ strlcpy(limit_file.name, " ", MAX_LIMIT_FILE_NAME);
+
+
+ tests.MutualRawAdjITO = 1;
+
+ tests.MutualRaw = 1;
+ tests.MutualRawGap = 0;
+ tests.MutualRawAdj = 0;
+
+ tests.MutualRawLP = 1;
+ tests.MutualRawGapLP = 0;
+ tests.MutualRawAdjLP = 0;
+
+ tests.MutualCx1 = 0;
+ tests.MutualCx2 = 0;
+ tests.MutualCx2Adj = 0;
+ tests.MutualCxTotal = 0;
+ tests.MutualCxTotalAdj = 0;
+
+#ifdef PHONE_KEY
+ tests.MutualKeyRaw = 1;
+#else
+ tests.MutualKeyRaw = 0;
+#endif
+ tests.MutualKeyCx1 = 0;
+ tests.MutualKeyCx2 = 0;
+#ifdef PHONE_KEY
+ tests.MutualKeyCxTotal = 0;
+#else
+ tests.MutualKeyCxTotal = 0;
+#endif
+
+ tests.SelfForceRaw = 1;
+ tests.SelfForceRawGap = 0;
+
+ tests.SelfForceRawLP = 1;
+ tests.SelfForceRawGapLP = 0;
+
+ tests.SelfForceIx1 = 0;
+ tests.SelfForceIx2 = 0;
+ tests.SelfForceIx2Adj = 0;
+ tests.SelfForceIxTotal = 0;
+ tests.SelfForceIxTotalAdj = 0;
+ tests.SelfForceCx1 = 0;
+ tests.SelfForceCx2 = 0;
+ tests.SelfForceCx2Adj = 0;
+ tests.SelfForceCxTotal = 0;
+ tests.SelfForceCxTotalAdj = 0;
+
+ tests.SelfSenseRaw = 1;
+ tests.SelfSenseRawGap = 0;
+
+ tests.SelfSenseRawLP = 1;
+ tests.SelfSenseRawGapLP = 0;
+
+ tests.SelfSenseIx1 = 0;
+ tests.SelfSenseIx2 = 0;
+ tests.SelfSenseIx2Adj = 0;
+ tests.SelfSenseIxTotal = 0;
+ tests.SelfSenseIxTotalAdj = 0;
+ tests.SelfSenseCx1 = 0;
+ tests.SelfSenseCx2 = 0;
+ tests.SelfSenseCx2Adj = 0;
+ tests.SelfSenseCxTotal = 0;
+ tests.SelfSenseCxTotalAdj = 0;
+
+ return OK;
+}
+
+/**
+ * Compute the Horizontal adjacent matrix doing the abs of the difference
+ * between the column i with the i-1 one. \n
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of signed bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjHoriz(i8 *data, int row, int column, u8 **result)
+{
+ int i, j;
+ int size = row * (column - 1);
+
+ if (column < 2) {
+ pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++)
+ for (j = 1; j < column; j++)
+ *(*result + (i * (column - 1) + (j - 1))) =
+ abs(data[i * column + j] - data[i * column +
+ (j - 1)]);
+
+ return OK;
+}
+
+/**
+ * Compute the Horizontal adjacent matrix of short values doing the abs of
+ * the difference between the column i with the i-1 one.
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of signed bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which
+ * will contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjHorizTotal(short *data, int row, int column, u16 **result)
+{
+ int i, j;
+ int size = row * (column - 1);
+
+ if (column < 2) {
+ pr_err("computeAdjHorizTotal: ERROR %08X\n",
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjHorizTotal: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++)
+ for (j = 1; j < column; j++)
+ *(*result + (i * (column - 1) + (j - 1))) =
+ abs(data[i * column + j] - data[i * column +
+ (j - 1)]);
+
+ return OK;
+}
+
+/**
+ * Compute the Vertical adjacent matrix doing the abs of the difference between
+ * the row i with the i-1 one.
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other. \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of signed bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjVert(i8 *data, int row, int column, u8 **result)
+{
+ int i, j;
+ int size = (row - 1) * (column);
+
+ if (row < 2) {
+ pr_err("computeAdjVert: ERROR %08X\n", ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjVert: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 1; i < row; i++)
+ for (j = 0; j < column; j++)
+ *(*result + ((i - 1) * column + j)) =
+ abs(data[i * column + j] - data[(i - 1) *
+ column + j]);
+
+ return OK;
+}
+
+/**
+ * Compute the Vertical adjacent matrix of short values doing the abs of
+ * the difference between the row i with the i-1 one.
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other. \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of signed bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjVertTotal(short *data, int row, int column, u16 **result)
+{
+ int i, j;
+ int size = (row - 1) * (column);
+
+ if (row < 2) {
+ pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 1; i < row; i++)
+ for (j = 0; j < column; j++)
+ *(*result + ((i - 1) * column + j)) =
+ abs(data[i * column + j] - data[(i - 1) *
+ column + j]);
+
+ return OK;
+}
+
+/**
+ * Compute the Horizontal adjacent matrix doing the abs of the difference
+ * between the column i with the i-1 one. \n
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of unsigned bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjHorizFromU(u8 *data, int row, int column, u8 **result)
+{
+ int i, j;
+ int size = row * (column - 1);
+
+ if (column < 2) {
+ pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjHoriz: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++)
+ for (j = 1; j < column; j++)
+ *(*result + (i * (column - 1) + (j - 1))) =
+ abs(data[i * column + j] - data[i * column +
+ (j - 1)]);
+
+ return OK;
+}
+
+/**
+ * Compute the Horizontal adjacent matrix of u16 values doing the abs of
+ * the difference between the column i with the i-1 one.
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of unsigned bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjHorizTotalFromU(u16 *data, int row, int column, u16 **result)
+{
+ int i, j;
+ int size = row * (column - 1);
+
+ if (column < 2) {
+ pr_err("computeAdjHorizTotal: ERROR %08X\n",
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjHorizTotal: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 0; i < row; i++)
+ for (j = 1; j < column; j++)
+ *(*result + (i * (column - 1) + (j - 1))) =
+ abs(data[i * column + j] - data[i * column +
+ (j - 1)]);
+
+ return OK;
+}
+
+/**
+ * Compute the Vertical adjacent matrix doing the abs of the difference between
+ * the row i with the i-1 one.
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other. \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of unsigned bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjVertFromU(u8 *data, int row, int column, u8 **result)
+{
+ int i, j;
+ int size = (row - 1) * (column);
+
+ if (row < 2) {
+ pr_err("computeAdjVert: ERROR %08X\n", ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u8 *)kmalloc(size * sizeof(u8), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjVert: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 1; i < row; i++)
+ for (j = 0; j < column; j++)
+ *(*result + ((i - 1) * column + j)) =
+ abs(data[i * column + j] - data[(i - 1) *
+ column + j]);
+
+ return OK;
+}
+
+/**
+ * Compute the Vertical adjacent matrix of u16 values doing the abs of
+ * the difference between the row i with the i-1 one.
+ * Both the original data matrix and the adj matrix are disposed as 1 dimension
+ * array one row after the other. \n
+ * The resulting matrix has one column less than the starting original one \n
+ * @param data pointer to the array of unsigned bytes containing the original
+ * data
+ * @param row number of rows of the original data
+ * @param column number of columns of the original data
+ * @param result pointer of a pointer to an array of unsigned bytes which will
+ * contain the adj matrix
+ * @return OK if success or an error code which specify the type of error
+ */
+int computeAdjVertTotalFromU(u16 *data, int row, int column, u16 **result)
+{
+ int i, j;
+ int size = (row - 1) * (column);
+
+ if (row < 2) {
+ pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *result = (u16 *)kmalloc(size * sizeof(u16), GFP_KERNEL);
+ if (*result == NULL) {
+ pr_err("computeAdjVertTotal: ERROR %08X\n", ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+
+ for (i = 1; i < row; i++)
+ for (j = 0; j < column; j++)
+ *(*result + ((i - 1) * column + j)) =
+ abs(data[i * column + j] - data[(i - 1) *
+ column + j]);
+
+ return OK;
+}
+
+
+
+/**
+ * Check that each value of a matrix of short doesn't exceed a min and a Max
+ * value
+ * (these values are included in the interval). \n
+ * The matrix is stored as 1 dimension array one row after the other. \n
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param min minimum value allowed
+ * @param max Maximum value allowed
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMinMax(short *data, int row, int column, int min, int max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min || data[i * column + j] >
+ max) {
+ pr_err("checkLimitsMinMax: Node[%d,%d] = %d exceed limit [%d, %d]\n",
+ i, j, data[i * column + j], min, max);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Check that the difference between the max and min of a matrix of short
+ * is less or equal to a threshold.\n
+ * The matrix is stored as 1 dimension array one row after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param threshold threshold value allowed
+ * @return OK if the difference is <= to threshold otherwise
+ * ERROR_TEST_CHECK_FAIL
+ */
+int checkLimitsGap(short *data, int row, int column, int threshold)
+{
+ int i, j;
+ int min_node;
+ int max_node;
+
+ if (row == 0 || column == 0) {
+ pr_err("checkLimitsGap: invalid number of rows = %d or columns = %d ERROR %08X\n",
+ row, column, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ min_node = data[0];
+ max_node = data[0];
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min_node)
+ min_node = data[i * column + j];
+ else if (data[i * column + j] > max_node)
+ max_node = data[i * column + j];
+ }
+ }
+
+ if (max_node - min_node > threshold) {
+ pr_err("checkLimitsGap: GAP = %d exceed limit %d\n",
+ max_node - min_node, threshold);
+ return ERROR_TEST_CHECK_FAIL;
+ } else
+ return OK;
+}
+
+/**
+ * Check that each value of a matrix of i8 doesn't exceed a specific min and
+ * Max value set for each node (these values are included in the interval). \n
+ * The matrixes of data, min and max values are stored as 1 dimension arrays
+ * one row after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param min pointer to a matrix which specify the minimum value allowed for
+ * each node
+ * @param max pointer to a matrix which specify the Maximum value allowed for
+ * each node
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMap(i8 *data, int row, int column, int *min, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min[i * column + j] ||
+ data[i * column + j] > max[i * column + j]) {
+ pr_err("checkLimitsMap: Node[%d,%d] = %d exceed limit [%d, %d]\n",
+ i, j, data[i * column + j],
+ min[i * column + j],
+ max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Check that each value of a matrix of short doesn't exceed a specific min and
+ * Max value set for each node (these values are included in the interval).
+ * The matrixes of data, min and max values are stored as 1 dimension arrays
+ * one row after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param min pointer to a matrix which specify the minimum value allowed for
+ * each node
+ * @param max pointer to a matrix which specify the Maximum value allowed for
+ * each node
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMapTotal(short *data, int row, int column, int *min, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min[i * column + j] ||
+ data[i * column + j] > max[i * column + j]) {
+ pr_err("checkLimitsMapTotal: Node[%d,%d] = %d exceed limit [%d, %d]\n",
+ i, j, data[i * column + j],
+ min[i * column + j],
+ max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Check that each value of a matrix of u8 doesn't exceed a specific min and
+ * Max value set for each node (these values are included in the interval). \n
+ * The matrixes of data, min and max values are stored as 1 dimension arrays
+ * one row after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param min pointer to a matrix which specify the minimum value allowed for
+ * each node
+ * @param max pointer to a matrix which specify the Maximum value allowed for
+ * each node
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMapFromU(u8 *data, int row, int column, int *min, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min[i * column + j] ||
+ data[i * column + j] > max[i * column + j]) {
+ pr_err("checkLimitsMap: Node[%d,%d] = %d exceed limit [%d, %d]\n",
+ i, j, data[i * column + j],
+ min[i * column + j],
+ max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Check that each value of a matrix of u16 doesn't exceed a specific min and
+ * Max value set for each node (these values are included in the interval).
+ * The matrixes of data, min and max values are stored as 1 dimension arrays
+ * one row after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param min pointer to a matrix which specify the minimum value allowed for
+ * each node
+ * @param max pointer to a matrix which specify the Maximum value allowed for
+ * each node
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMapTotalFromU(u16 *data, int row, int column, int *min, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] < min[i * column + j] ||
+ data[i * column + j] > max[i * column + j]) {
+ pr_err("checkLimitsMapTotal: Node[%d,%d] = %d exceed limit [%d, %d]\n",
+ i, j, data[i * column + j],
+ min[i * column + j],
+ max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Check that each value of a matrix of u8 doesn't exceed a specific Max value
+ * set for each node (max value is included in the interval).
+ * The matrixes of data and max values are stored as 1 dimension arrays one row
+ * after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param max pointer to a matrix which specify the Maximum value allowed for
+ * each node
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMapAdj(u8 *data, int row, int column, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] > max[i * column + j]) {
+ pr_err("checkLimitsMapAdj: Node[%d,%d] = %d exceed limit > %d\n",
+ i, j,
+ data[i * column + j],
+ max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Check that each value of a matrix of u16 doesn't exceed a specific Max value
+ * set for each node (max value is included in the interval).
+ * The matrixes of data and max values are stored as 1 dimension arrays one row
+ * after the other.
+ * @param data pointer to the array of short containing the data to check
+ * @param row number of rows of data
+ * @param column number of columns of data
+ * @param max pointer to a matrix which specify the Maximum value allowed for
+ * each node
+ * @return the number of elements that overcome the specified interval (0 = OK)
+ */
+int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max)
+{
+ int i, j;
+ int count = 0;
+
+ for (i = 0; i < row; i++) {
+ for (j = 0; j < column; j++) {
+ if (data[i * column + j] > max[i * column + j]) {
+ pr_err("checkLimitsMapAdjTotal: Node[%d,%d] = %d exceed limit > %d\n",
+ i, j,
+ data[i * column + j],
+ max[i * column + j]);
+ count++;
+ }
+ }
+ }
+
+ return count; /* if count is 0 = OK, test completed successfully */
+}
+
+/**
+ * Perform an ITO test setting all the possible options
+ * (see @link ito_opt ITO Options @endlink) and checking MS Raw ADJ if enabled
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ito(char *path_limits, TestToDo *todo)
+{
+ int res = OK;
+ u8 sett[2] = { 0x00, 0x00 };
+ MutualSenseFrame msRawFrame;
+ int *thresholds = NULL;
+ u16 *adj = NULL;
+ int trows, tcolumns;
+
+ pr_info("ITO Production test is starting...\n");
+
+ res = fts_system_reset();
+ if (res < 0) {
+ pr_err("%s: ERROR %08X\n", __func__, ERROR_PROD_TEST_ITO);
+ return res | ERROR_PROD_TEST_ITO;
+ }
+
+ sett[0] = SPECIAL_TUNING_IOFF;
+ pr_info("Trimming Ioff...\n");
+ res = writeSysCmd(SYS_CMD_SPECIAL_TUNING, sett, 2);
+ if (res < OK) {
+ pr_err("production_test_ito: Trimm Ioff ERROR %08X\n",
+ (res | ERROR_PROD_TEST_ITO));
+ return res | ERROR_PROD_TEST_ITO;
+ }
+
+ sett[0] = 0xFF;
+ sett[1] = 0xFF;
+ pr_info("ITO Check command sent...\n");
+ res = writeSysCmd(SYS_CMD_ITO, sett, 2);
+ if (res < OK) {
+ pr_err("production_test_ito: ERROR %08X\n",
+ (res | ERROR_PROD_TEST_ITO));
+ return res | ERROR_PROD_TEST_ITO;
+ }
+
+ pr_info("ITO Command = OK!\n");
+
+ pr_info("MS RAW ITO ADJ TEST:\n");
+ if (todo->MutualRawAdjITO == 1) {
+ pr_info("Collecting MS Raw data...\n");
+ res |= getMSFrame3(MS_RAW, &msRawFrame);
+ if (res < OK) {
+ pr_err("%s: getMSFrame failed... ERROR %08X\n",
+ __func__, ERROR_PROD_TEST_ITO);
+ goto ERROR;
+ }
+
+ print_frame_short("MS Raw ITO frame =",
+ array1dTo2d_short(
+ msRawFrame.node_data,
+ msRawFrame.node_data_size,
+ msRawFrame.header.sense_node),
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node);
+
+ pr_info("MS RAW ITO ADJ HORIZONTAL TEST:\n");
+ res = computeAdjHorizTotal(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ &adj);
+ if (res < OK) {
+ pr_err("%s: computeAdjHoriz failed... ERROR %08X\n",
+ __func__, ERROR_PROD_TEST_ITO);
+ goto ERROR;
+ }
+
+ res = parseProductionTestLimits(path_limits, &limit_file,
+ MS_RAW_ITO_ADJH, &thresholds,
+ &trows, &tcolumns);
+ if (res < OK || (trows != msRawFrame.header.force_node ||
+ tcolumns != msRawFrame.header.sense_node -
+ 1)) {
+ pr_err("%s: parseProductionTestLimits MS_RAW_ITO_ADJH failed... ERROR %08X\n",
+ __func__, ERROR_PROD_TEST_DATA);
+ goto ERROR;
+ }
+
+
+ res = checkLimitsMapAdjTotal(adj, msRawFrame.header.force_node,
+ msRawFrame.header.sense_node - 1,
+ thresholds);
+ if (res != OK) {
+ pr_err("production_test_data: checkLimitsAdj MS RAW ITO ADJH failed... ERROR COUNT = %d\n",
+ res);
+ pr_err("MS RAW ITO ADJ HORIZONTAL TEST:.................FAIL\n\n");
+ res = ERROR_PROD_TEST_ITO;
+ goto ERROR;
+ } else
+ pr_info("MS RAW ITO ADJ HORIZONTAL TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(adj);
+ adj = NULL;
+
+ pr_info("MS RAW ITO ADJ VERTICAL TEST:\n");
+ res = computeAdjVertTotal(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ &adj);
+ if (res < OK) {
+ pr_err("%s: computeAdjVert failed... ERROR %08X\n",
+ __func__, ERROR_PROD_TEST_ITO);
+ goto ERROR;
+ }
+
+ res = parseProductionTestLimits(path_limits, &limit_file,
+ MS_RAW_ITO_ADJV, &thresholds,
+ &trows, &tcolumns);
+ if (res < OK || (trows != msRawFrame.header.force_node - 1 ||
+ tcolumns != msRawFrame.header.sense_node)) {
+ pr_err("%s: parseProductionTestLimits MS_RAW_ITO_ADJV failed... ERROR %08X\n",
+ __func__, ERROR_PROD_TEST_ITO);
+ goto ERROR;
+ }
+
+
+ res = checkLimitsMapAdjTotal(adj, msRawFrame.header.force_node -
+ 1, msRawFrame.header.sense_node,
+ thresholds);
+ if (res != OK) {
+ pr_err("%s: checkLimitsAdj MS RAW ITO ADJV failed... ERROR COUNT = %d\n",
+ __func__, res);
+ pr_err("MS RAW ITO ADJ VERTICAL TEST:.................FAIL\n\n");
+ res = ERROR_PROD_TEST_ITO;
+ goto ERROR;
+ } else
+ pr_info("MS RAW ITO ADJ VERTICAL TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(adj);
+ adj = NULL;
+ } else
+ pr_info("MS RAW ITO ADJ TEST:.................SKIPPED\n");
+
+ERROR:
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (adj != NULL)
+ kfree(adj);
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ freeLimitsFile(&limit_file);
+ res |= fts_system_reset();
+ if (res < OK) {
+ pr_err("production_test_ito: ERROR %08X\n",
+ ERROR_PROD_TEST_ITO);
+ res = (res | ERROR_PROD_TEST_ITO);
+ }
+ return res;
+}
+
+/**
+ * Perform the Initialization of the IC
+ * @param type type of initialization to do
+ * (see @link sys_special_opt Initialization Options (Full or Panel) @endlink)
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_initialization(u8 type)
+{
+ int res;
+
+ pr_info("INITIALIZATION Production test is starting...\n");
+ if (type != SPECIAL_PANEL_INIT && type != SPECIAL_FULL_PANEL_INIT) {
+ pr_err("production_test_initialization: Type incompatible! Type = %02X ERROR %08X\n",
+ type, ERROR_OP_NOT_ALLOW |
+ ERROR_PROD_TEST_INITIALIZATION);
+ return ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_INITIALIZATION;
+ }
+
+ res = fts_system_reset();
+ if (res < 0) {
+ pr_err("production_test_initialization: ERROR %08X\n",
+ ERROR_PROD_TEST_INITIALIZATION);
+ return res | ERROR_PROD_TEST_INITIALIZATION;
+ }
+
+ pr_info("INITIALIZATION command sent... %02X\n", type);
+ res = writeSysCmd(SYS_CMD_SPECIAL, &type, 1);
+ if (res < OK) {
+ pr_err("production_test_initialization: ERROR %08X\n",
+ (res | ERROR_PROD_TEST_INITIALIZATION));
+ return res | ERROR_PROD_TEST_INITIALIZATION;
+ }
+
+
+ pr_info("Refresh Sys Info...\n");
+ res |= readSysInfo(1); /* need to update the chipInfo in order
+ * to refresh several versions */
+
+ if (res < 0) {
+ pr_err("production_test_initialization: read sys info ERROR %08X\n",
+ ERROR_PROD_TEST_INITIALIZATION);
+ res = (res | ERROR_PROD_TEST_INITIALIZATION);
+ }
+
+ return res;
+}
+
+
+// @param signature value of the MP flag to save if the Mass Production Test succeed
+/**
+ * Perform a FULL (ITO + INIT + DATA CHECK) Mass Production Test of the IC
+ * @param pathThresholds name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param saveInit if >0 (possible values: NO_INIT, SPECIAL_PANEL_INIT or
+ * SPECIAL_FULL_PANEL_INIT),
+ * the Initialization of the IC is executed otherwise it is skipped
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_main(char *pathThresholds, int stop_on_fail, int saveInit,
+ TestToDo *todo)
+{
+ int res, ret;
+
+ pr_info("MAIN Production test is starting...\n");
+
+ pr_info("ITO TEST:\n");
+ res = production_test_ito(pathThresholds, todo);
+ if (res < 0) {
+ pr_err("Error during ITO TEST! ERROR %08X\n", res);
+ goto END;/* in case of ITO TEST failure is no sense keep going
+ * */
+ } else
+ pr_info("ITO TEST OK!\n");
+
+ pr_info("INITIALIZATION TEST :\n");
+ if (saveInit != NO_INIT) {
+ res = production_test_initialization((u8)saveInit);
+ if (res < 0) {
+ pr_err("Error during INITIALIZATION TEST! ERROR %08X\n",
+ res);
+ if (stop_on_fail)
+ goto END;
+ } else
+ pr_info("INITIALIZATION TEST OK!\n");
+ } else
+ pr_info("INITIALIZATION TEST :................. SKIPPED\n");
+
+ if (saveInit == 1) {
+ pr_info("Cleaning up...\n");
+ ret = fts_system_reset();
+ if (ret < 0) {
+ pr_err("production_test_main: system reset ERROR %08X\n",
+ ret);
+ res |= ret;
+ if (stop_on_fail)
+ goto END;
+ }
+ }
+
+ pr_info("PRODUCTION DATA TEST:\n");
+ ret = production_test_data(pathThresholds, stop_on_fail, todo);
+ if (ret < 0)
+ pr_err("Error during PRODUCTION DATA TEST! ERROR %08X\n", ret);
+ else
+ pr_info("PRODUCTION DATA TEST OK!\n");
+
+ res |= ret;
+ /* the OR is important because if the data test is OK but
+ * the init test fail, the main production test result should = FAIL */
+
+END:
+ if (res < 0) {
+ pr_err("MAIN Production test finished.................FAILED\n");
+ return res;
+ } else {
+ pr_info("MAIN Production test finished.................OK\n");
+ return OK;
+ }
+}
+
+/**
+ * Perform all the test selected in a TestTodo variable related to MS raw data
+ * (touch, keys etc..)
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+ int ret, count_fail = 0;
+ MutualSenseFrame msRawFrame;
+
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ u16 *adj = NULL;
+
+ /************** Mutual Sense Test *************/
+ pr_info("MS RAW DATA TEST is starting...\n");
+ if (todo->MutualRaw == 1 || todo->MutualRawGap == 1 ||
+ todo->MutualRawAdj == 1) {
+ ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_ACTIVE);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ ret |= getMSFrame3(MS_RAW, &msRawFrame);
+ if (ret < OK) {
+ pr_err("production_test_data: getMSFrame failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ print_frame_short("MS Raw frame =",
+ array1dTo2d_short(
+ msRawFrame.node_data,
+ msRawFrame.node_data_size,
+ msRawFrame.header.sense_node),
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node);
+
+ pr_info("MS RAW MIN MAX TEST:\n");
+ if (todo->MutualRaw == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_MIN_MAX,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < OK || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+
+ ret = checkLimitsMinMax(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ thresholds[0],
+ thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax MS RAW failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS RAW MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW MIN MAX TEST:.................OK\n");
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("MS RAW MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("MS RAW GAP TEST:\n");
+ if (todo->MutualRawGap == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file, MS_RAW_GAP,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_GAP failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsGap(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ thresholds[0]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsGap MS RAW failed... ERROR = %08X\n",
+ ret);
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW GAP TEST:.................OK\n\n");
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("MS RAW GAP TEST:.................SKIPPED\n");
+
+ pr_info("MS RAW ADJ TEST:\n");
+ if (todo->MutualRawAdj == 1) {
+ pr_info("MS RAW ADJ HORIZONTAL TEST:\n");
+ ret = computeAdjHorizTotal(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ &adj);
+ if (ret < OK) {
+ pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_ADJH,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < OK || (trows !=
+ msRawFrame.header.force_node ||
+ tcolumns !=
+ msRawFrame.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_ADJH failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+
+ ret = checkLimitsMapAdjTotal(adj,
+ msRawFrame.header.
+ force_node,
+ msRawFrame.header.
+ sense_node - 1,
+ thresholds);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsAdj MS RAW ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS RAW ADJ HORIZONTAL TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW ADJ HORIZONTAL TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(adj);
+ adj = NULL;
+
+ pr_info("MS RAW ADJ VERTICAL TEST:\n");
+ ret = computeAdjVertTotal(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ &adj);
+ if (ret < OK) {
+ pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_ADJV,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < OK || (trows != msRawFrame.header.force_node -
+ 1 || tcolumns !=
+ msRawFrame.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_ADJV failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+
+ ret = checkLimitsMapAdjTotal(adj,
+ msRawFrame.header.
+ force_node - 1,
+ msRawFrame.header.
+ sense_node, thresholds);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsAdj MS RAW ADJV failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS RAW ADJ VERTICAL TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW ADJ VERTICAL TEST:.................OK\n");
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(adj);
+ adj = NULL;
+ } else
+ pr_info("MS RAW ADJ TEST:.................SKIPPED\n");
+ } else
+ pr_info("MS RAW FRAME TEST:.................SKIPPED\n");
+
+ pr_info("MS KEY RAW TEST:\n");
+ if (todo->MutualKeyRaw == 1) {
+ ret = production_test_ms_key_raw(path_limits);
+ if (ret < 0) {
+ pr_err("production_test_data: production_test_ms_key_raw failed... ERROR = %08X\n",
+ ret);
+ count_fail += 1;
+ if (count_fail == 1) {
+ pr_err("MS RAW DATA TEST:.................FAIL fails_count = %d\n\n",
+ count_fail);
+ goto ERROR_LIMITS;
+ }
+ }
+ } else
+ pr_info("MS KEY RAW TEST:.................SKIPPED\n");
+
+ ret = production_test_ms_raw_lp(path_limits, stop_on_fail, todo);
+ if (ret < 0) {
+ pr_err("production_test_data: production_test_ms_raw_lp failed... ERROR = %08X\n",
+ ret);
+ count_fail += 1;
+ if (count_fail == 1) {
+ pr_err("MS RAW DATA TEST:.................FAIL fails_count = %d\n\n",
+ count_fail);
+ goto ERROR_LIMITS;
+ }
+ }
+
+ERROR:
+
+ if (count_fail == 0) {
+ if (msRawFrame.node_data != NULL) {
+ kfree(msRawFrame.node_data);
+ msRawFrame.node_data = NULL;
+ }
+ pr_info("MS RAW DATA TEST finished!.................OK\n");
+ return OK;
+ } else {
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (adj != NULL)
+ kfree(adj);
+ pr_err("MS RAW DATA TEST:.................FAIL fails_count = %d\n\n",
+ count_fail);
+ return ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL;
+ }
+
+
+ERROR_LIMITS:
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ return ret;
+}
+
+
+/**
+ * Perform all the test selected in a TestTodo variable related to MS low power
+ * raw data
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ms_raw_lp(char *path_limits, int stop_on_fail,
+ TestToDo *todo)
+{
+ int ret, count_fail = 0;
+ MutualSenseFrame msRawFrame;
+
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ u16 *adj = NULL;
+
+ /************** Mutual Sense Test **************/
+ pr_info("MS RAW LP DATA TEST:\n");
+ if (todo->MutualRawLP == 1 || todo->MutualRawGapLP == 1 ||
+ todo->MutualRawAdjLP == 1) {
+ ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_LP_ACTIVE);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ ret |= getMSFrame3(MS_RAW, &msRawFrame);
+ if (ret < 0) {
+ pr_err("production_test_data: getMSFrame failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ print_frame_short("MS Raw LP frame =",
+ array1dTo2d_short(
+ msRawFrame.node_data,
+ msRawFrame.node_data_size,
+ msRawFrame.header.sense_node),
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node);
+
+ pr_info("MS RAW LP MIN MAX TEST:\n");
+ if (todo->MutualRawLP == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_LP_MIN_MAX,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_LP_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+
+ ret = checkLimitsMinMax(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ thresholds[0],
+ thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax MS RAW LP failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS RAW LP MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW LP MIN MAX TEST:.................OK\n");
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("MS RAW LP MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("MS RAW LP GAP TEST:\n");
+ if (todo->MutualRawGapLP == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_LP_GAP,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_LP_GAP failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsGap(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ thresholds[0]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsGap MS RAW LP failed... ERROR = %08X\n",
+ ret);
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW LP GAP TEST:.................OK\n\n");
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("MS RAW LP GAP TEST:.................SKIPPED\n");
+
+ pr_info("MS RAW LP ADJ TEST:\n");
+ if (todo->MutualRawAdjLP == 1) {
+ pr_info("MS RAW LP ADJ HORIZONTAL TEST:\n");
+ ret = computeAdjHorizTotal(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ &adj);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_LP_ADJH,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != msRawFrame.header.force_node ||
+ tcolumns !=
+ msRawFrame.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_LP_ADJH failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+
+ ret = checkLimitsMapAdjTotal(adj,
+ msRawFrame.header.
+ force_node,
+ msRawFrame.header.
+ sense_node - 1,
+ thresholds);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsAdj MS RAW LP ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS RAW LP ADJ HORIZONTAL TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW LP ADJ HORIZONTAL TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(adj);
+ adj = NULL;
+
+ pr_info("MS RAW LP ADJ VERTICAL TEST:\n");
+ ret = computeAdjVertTotal(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ &adj);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_RAW_LP_ADJV,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != msRawFrame.header.force_node -
+ 1 || tcolumns !=
+ msRawFrame.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_RAW_ADJV failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+
+ ret = checkLimitsMapAdjTotal(adj,
+ msRawFrame.header.
+ force_node - 1,
+ msRawFrame.header.
+ sense_node, thresholds);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsAdj MS RAW ADJV failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS RAW LP ADJ VERTICAL TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail == 1)
+ goto ERROR;
+ } else
+ pr_info("MS RAW LP ADJ VERTICAL TEST:.................OK\n");
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(adj);
+ adj = NULL;
+ } else
+ pr_info("MS RAW LP ADJ TEST:.................SKIPPED\n");
+ } else
+ pr_info("MS RAW LP FRAME TEST:.................SKIPPED\n");
+
+ERROR:
+ if (count_fail == 0) {
+ if (msRawFrame.node_data != NULL) {
+ kfree(msRawFrame.node_data);
+ msRawFrame.node_data = NULL;
+ }
+ pr_info("MS RAW DATA TEST finished!.................OK\n");
+ return OK;
+ } else {
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (adj != NULL)
+ kfree(adj);
+ pr_err("MS RAW LP DATA TEST:.................FAIL fails_count = %d\n\n",
+ count_fail);
+ return ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL;
+ }
+
+
+ERROR_LIMITS:
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ return ret;
+}
+
+/**
+ * Perform MS raw test for keys data
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ms_key_raw(char *path_limits)
+{
+ int ret;
+ MutualSenseFrame msRawFrame;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ /************** Mutual Sense Test **************/
+ pr_info("MS KEY RAW DATA TEST is starting...\n");
+ ret = setScanMode(SCAN_MODE_ACTIVE, 0xFF);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ ret |= getMSFrame3(MS_KEY_RAW, &msRawFrame);
+ if (ret < 0) {
+ pr_err("production_test_data: getMSKeyFrame failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_KEY_RAW_MIN_MAX, &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_KEY_RAW_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMinMax(msRawFrame.node_data,
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node,
+ thresholds[0], thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax MS KEY RAW failed... ERROR COUNT = %d\n",
+ ret);
+ goto ERROR;
+ } else
+ pr_info("MS KEY RAW TEST:.................OK\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ kfree(msRawFrame.node_data);
+ msRawFrame.node_data = NULL;
+ return OK;
+
+ERROR:
+ print_frame_short("MS Key Raw frame =", array1dTo2d_short(
+ msRawFrame.node_data,
+ msRawFrame.node_data_size,
+ msRawFrame.header.sense_node),
+ msRawFrame.header.force_node,
+ msRawFrame.header.sense_node);
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ pr_err("MS KEY RAW TEST:.................FAIL\n\n");
+ return ERROR_PROD_TEST_DATA | ERROR_TEST_CHECK_FAIL;
+
+ERROR_LIMITS:
+ if (msRawFrame.node_data != NULL)
+ kfree(msRawFrame.node_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ return ret;
+}
+
+/**
+ * Perform all the tests selected in a TestTodo variable related to MS Init
+ * data (touch, keys etc..)
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+ int ret;
+ int count_fail = 0;
+
+ int *thresholds = NULL;
+ int *thresholds_min = NULL;
+ int *thresholds_max = NULL;
+ int trows, tcolumns;
+
+ MutualSenseData msCompData;
+ TotMutualSenseData totCompData;
+
+ u8 *adjhor = NULL;
+
+ u8 *adjvert = NULL;
+
+ u16 container;
+ /* u16 *total_cx = NULL; */
+ u16 *total_adjhor = NULL;
+ u16 *total_adjvert = NULL;
+
+
+ /* MS CX TEST */
+ pr_info("MS CX Testes are starting...\n");
+
+ ret = readMutualSenseCompensationData(LOAD_CX_MS_TOUCH, &msCompData);
+ /* read MS compensation data */
+ if (ret < 0) {
+ pr_err("production_test_data: readMutualSenseCompensationData failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ ret = readTotMutualSenseCompensationData(LOAD_PANEL_CX_TOT_MS_TOUCH,
+ &totCompData);
+ /* read TOT MS compensation data */
+ if (ret < 0) {
+ pr_err("production_test_data: readTotMutualSenseCompensationData failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ kfree(msCompData.node_data);
+ msCompData.node_data = NULL;
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ pr_info("MS CX1 TEST:\n");
+ if (todo->MutualCx1 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_CX1_MIN_MAX, &thresholds,
+ &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_CX1_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ container = (u16)msCompData.cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0],
+ thresholds[1]);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax MS CX1 failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS CX1 TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS CX1 TEST:.................OK\n\n");
+ } else
+ pr_info("MS CX1 TEST:.................SKIPPED\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ pr_info("MS CX2 MIN MAX TEST:\n");
+ if (todo->MutualCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_CX2_MAP_MIN, &thresholds_min,
+ &trows, &tcolumns);
+ /* load min thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node ||
+ tcolumns != msCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_CX2_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_CX2_MAP_MAX, &thresholds_max,
+ &trows, &tcolumns);
+ /* load max thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node ||
+ tcolumns != msCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_CX2_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMap(msCompData.node_data,
+ msCompData.header.force_node,
+ msCompData.header.sense_node,
+ thresholds_min, thresholds_max);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap MS CX2 MIN MAX failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS CX2 MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS CX2 MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("MS CX2 MIN MAX TEST:.................SKIPPED\n\n");
+
+ pr_info("MS CX2 ADJ TEST:\n");
+ if (todo->MutualCx2Adj == 1) {
+ /* MS CX2 ADJ HORIZ */
+ pr_info("MS CX2 ADJ HORIZ TEST:\n");
+
+ ret = computeAdjHoriz(msCompData.node_data,
+ msCompData.header.force_node,
+ msCompData.header.sense_node,
+ &adjhor);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("MS CX2 ADJ HORIZ computed!\n");
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_CX2_ADJH_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != msCompData.header.force_node ||
+ tcolumns != msCompData.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_CX2_ADJH_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdj(adjhor, msCompData.header.force_node,
+ msCompData.header.sense_node - 1,
+ thresholds_max);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj CX2 ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS CX2 ADJ HORIZ TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS CX2 ADJ HORIZ TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(adjhor);
+ adjhor = NULL;
+
+ /* MS CX2 ADJ VERT */
+ pr_info("MS CX2 ADJ VERT TEST:\n");
+
+ ret = computeAdjVert(msCompData.node_data,
+ msCompData.header.force_node,
+ msCompData.header.sense_node,
+ &adjvert);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("MS CX2 ADJ VERT computed!\n");
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_CX2_ADJV_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != msCompData.header.force_node - 1 ||
+ tcolumns != msCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_CX2_ADJV_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdj(adjvert, msCompData.header.force_node -
+ 1, msCompData.header.sense_node - 1,
+ thresholds_max);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj CX2 ADJV failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS CX2 ADJ HORIZ TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS CX2 ADJ VERT TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(adjvert);
+ adjvert = NULL;
+ } else
+ pr_info("MS CX2 ADJ TEST:.................SKIPPED\n\n");
+
+ /* START OF TOTAL CHECK */
+ pr_info("MS TOTAL CX TEST:\n");
+
+ if (todo->MutualCxTotal == 1 || todo->MutualCxTotalAdj == 1) {
+ pr_info("MS TOTAL CX MIN MAX TEST:\n");
+ if (todo->MutualCxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_TOTAL_CX_MAP_MIN,
+ &thresholds_min,
+ &trows, &tcolumns);
+ /* load min thresholds */
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_TOTAL_CX_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ /* load max thresholds */
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapTotal(totCompData.node_data,
+ totCompData.header.force_node,
+ totCompData.header.sense_node,
+ thresholds_min,
+ thresholds_max);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap MS TOTAL CX TEST failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS TOTAL CX MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS TOTAL CX MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("MS TOTAL CX MIN MAX TEST:.................SKIPPED\n\n");
+
+
+ pr_info("MS TOTAL CX ADJ TEST:\n");
+ if (todo->MutualCxTotalAdj == 1) {
+ /* MS TOTAL CX ADJ HORIZ */
+ pr_info("MS TOTAL CX ADJ HORIZ TEST:\n");
+
+ ret = computeAdjHorizTotal(totCompData.node_data,
+ totCompData.header.force_node,
+ totCompData.header.sense_node,
+ &total_adjhor);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("MS TOTAL CX ADJ HORIZ computed!\n");
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_TOTAL_CX_ADJH_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns !=
+ totCompData.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_ADJH_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjhor,
+ totCompData.header.
+ force_node,
+ totCompData.header.
+ sense_node - 1,
+ thresholds_max);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj MS TOTAL CX ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS TOTAL CX ADJ HORIZ TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS TOTAL CX ADJ HORIZ TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(total_adjhor);
+ total_adjhor = NULL;
+
+ /* MS TOTAL CX ADJ VERT */
+ pr_info("MS TOTAL CX ADJ VERT TEST:\n");
+
+ ret = computeAdjVertTotal(totCompData.node_data,
+ totCompData.header.force_node,
+ totCompData.header.sense_node,
+ &total_adjvert);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("MS TOTAL CX ADJ VERT computed!\n");
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ MS_TOTAL_CX_ADJV_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ if (ret < 0 || (trows != totCompData.header.force_node -
+ 1 || tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_TOTAL_CX_ADJV_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjvert,
+ totCompData.header.
+ force_node - 1,
+ totCompData.header.
+ sense_node - 1,
+ thresholds_max);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj MS TOTAL CX ADJV failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS TOTAL CX ADJ HORIZ TEST:.................FAIL\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS TOTAL CX ADJ VERT TEST:.................OK\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(total_adjvert);
+ total_adjvert = NULL;
+ } else
+ pr_info("MS TOTAL CX ADJ TEST:.................SKIPPED\n");
+
+ kfree(totCompData.node_data);
+ totCompData.node_data = NULL;
+ } else
+ pr_info("MS TOTAL CX TEST:.................SKIPPED\n");
+
+
+
+ if ((todo->MutualKeyCx1 | todo->MutualKeyCx2 |
+ todo->MutualKeyCxTotal) == 1) {
+ ret = production_test_ms_key_cx(path_limits, stop_on_fail,
+ todo);
+ if (ret < 0) {
+ count_fail += 1;
+ pr_err("production_test_data: production_test_ms_key_cx failed... ERROR = %08X\n",
+ ret);
+ pr_err("MS CX testes finished!.................FAILED fails_count = %d\n\n",
+ count_fail);
+ return ret;
+ }
+ } else
+ pr_info("MS KEY CX TEST:.................SKIPPED\n");
+
+ERROR:
+
+ if (count_fail == 0) {
+ pr_info("MS CX testes finished!.................OK\n");
+ kfree(msCompData.node_data);
+ msCompData.node_data = NULL;
+ return OK;
+ } else {
+ print_frame_i8("MS Init Data (Cx2) =", array1dTo2d_i8(
+ msCompData.node_data,
+ msCompData.node_data_size,
+ msCompData.header.sense_node),
+ msCompData.header.force_node,
+ msCompData.header.sense_node);
+ print_frame_short(" TOT MS Init Data (Cx) =", array1dTo2d_short(
+ totCompData.node_data,
+ totCompData.node_data_size,
+ totCompData.header.sense_node),
+ totCompData.header.force_node,
+ totCompData.header.sense_node);
+ pr_err("MS CX testes finished!.................FAILED fails_count = %d\n\n",
+ count_fail);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (thresholds_min != NULL)
+ kfree(thresholds_min);
+ if (thresholds_max != NULL)
+ kfree(thresholds_max);
+ if (adjhor != NULL)
+ kfree(adjhor);
+ if (adjvert != NULL)
+ kfree(adjvert);
+ if (totCompData.node_data != NULL)
+ kfree(totCompData.node_data);
+ if (total_adjhor != NULL)
+ kfree(total_adjhor);
+ if (total_adjvert != NULL)
+ kfree(total_adjvert);
+ if (msCompData.node_data != NULL)
+ kfree(msCompData.node_data);
+ return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA;
+ }
+
+ERROR_LIMITS:
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (thresholds_min != NULL)
+ kfree(thresholds_min);
+ if (thresholds_max != NULL)
+ kfree(thresholds_max);
+ if (adjhor != NULL)
+ kfree(adjhor);
+ if (adjvert != NULL)
+ kfree(adjvert);
+ if (totCompData.node_data != NULL)
+ kfree(totCompData.node_data);
+ if (total_adjhor != NULL)
+ kfree(total_adjhor);
+ if (total_adjvert != NULL)
+ kfree(total_adjvert);
+ if (msCompData.node_data != NULL)
+ kfree(msCompData.node_data);
+ return ret;
+}
+
+/**
+ * Perform all the tests selected in a TestTodo variable related to MS Init
+ * data of the keys
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ms_key_cx(char *path_limits, int stop_on_fail,
+ TestToDo *todo)
+{
+ int ret;
+ int count_fail = 0;
+ int num_keys = 0;
+
+ int *thresholds = NULL;
+ int *thresholds_min = NULL;
+ int *thresholds_max = NULL;
+ int trows, tcolumns;
+
+ MutualSenseData msCompData;
+ TotMutualSenseData totCompData;
+
+
+ short container;
+
+
+ /* MS CX TEST */
+ pr_info("MS KEY CX Testes are starting...\n");
+
+ ret = readMutualSenseCompensationData(LOAD_CX_MS_KEY, &msCompData);
+ /* read MS compensation data */
+ if (ret < 0) {
+ pr_err("production_test_data: readMutualSenseCompensationData failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ if (msCompData.header.force_node > msCompData.header.sense_node)
+ /* the meaningful data are only in the first row,
+ * the other rows are only a copy of the first one */
+ num_keys = msCompData.header.force_node;
+ else
+ num_keys = msCompData.header.sense_node;
+
+ pr_info("MS KEY CX1 TEST:\n");
+ if (todo->MutualKeyCx1 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_KEY_CX1_MIN_MAX, &thresholds,
+ &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_KEY_CX1_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ container = (short)msCompData.cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0],
+ thresholds[1]);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax MS CX1 failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS KEY CX1 TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS KEY CX1 TEST:.................OK\n\n");
+ } else
+ pr_info("MS KEY CX1 TEST:.................SKIPPED\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+
+ pr_info("MS KEY CX2 TEST:\n");
+ if (todo->MutualKeyCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_KEY_CX2_MAP_MIN,
+ &thresholds_min, &trows,
+ &tcolumns);
+ /* load min thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node ||
+ tcolumns != msCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_KEY_CX2_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_KEY_CX2_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load max thresholds */
+ if (ret < 0 || (trows != msCompData.header.force_node ||
+ tcolumns != msCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_KEY_CX2_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMap(msCompData.node_data,
+ msCompData.header.force_node,
+ msCompData.header.sense_node,
+ thresholds_min, thresholds_max);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap MS KEY CX2 failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS KEY CX2 TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS KEY CX2 TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("MS CX2 TEST:.................SKIPPED\n\n");
+
+ /* START OF TOTAL CHECK */
+ pr_info("MS KEY TOTAL CX TEST:\n");
+
+ if (todo->MutualKeyCxTotal == 1) {
+ ret = readTotMutualSenseCompensationData(
+ LOAD_PANEL_CX_TOT_MS_KEY, &totCompData);
+ if (ret < 0) {
+ pr_err("production_test_data: computeTotalCx failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_KEY_TOTAL_CX_MAP_MIN,
+ &thresholds_min, &trows,
+ &tcolumns);
+ /* load min thresholds */
+ if (ret < 0 || (trows != totCompData.header.force_node ||
+ tcolumns != totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_KEY_TOTAL_CX_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ MS_KEY_TOTAL_CX_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load max thresholds */
+ if (ret < 0 || (trows != totCompData.header.force_node ||
+ tcolumns != totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits MS_KEY_TOTAL_CX_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapTotal(totCompData.node_data,
+ totCompData.header.force_node,
+ totCompData.header.sense_node,
+ thresholds_min, thresholds_max);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap MS TOTAL KEY CX TEST failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("MS KEY TOTAL CX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("MS KEY TOTAL CX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+
+ kfree(totCompData.node_data);
+ totCompData.node_data = NULL;
+ } else
+ pr_info("MS KEY TOTAL CX TEST:.................SKIPPED\n");
+
+
+ERROR:
+ if (count_fail == 0) {
+ pr_info("MS KEY CX testes finished!.................OK\n");
+ kfree(msCompData.node_data);
+ msCompData.node_data = NULL;
+ return OK;
+ } else {
+ print_frame_i8("MS Key Init Data (Cx2) =", array1dTo2d_i8(
+ msCompData.node_data,
+ msCompData.node_data_size,
+ msCompData.header.sense_node),
+ msCompData.header.force_node,
+ msCompData.header.sense_node);
+ pr_err("MS Key CX testes finished!.................FAILED fails_count = %d\n\n",
+ count_fail);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (thresholds_min != NULL)
+ kfree(thresholds_min);
+ if (thresholds_max != NULL)
+ kfree(thresholds_max);
+ if (msCompData.node_data != NULL)
+ kfree(msCompData.node_data);
+ if (totCompData.node_data != NULL)
+ kfree(totCompData.node_data);
+ return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA;
+ }
+
+ERROR_LIMITS:
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (thresholds_min != NULL)
+ kfree(thresholds_min);
+ if (thresholds_max != NULL)
+ kfree(thresholds_max);
+ if (msCompData.node_data != NULL)
+ kfree(msCompData.node_data);
+ if (totCompData.node_data != NULL)
+ kfree(totCompData.node_data);
+ return ret;
+}
+
+/**
+ * Perform all the test selected in a TestTodo variable related to SS raw data
+ *(touch, keys etc..)
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+ int ret;
+ int count_fail = 0;
+ int rows, columns;
+
+ SelfSenseFrame ssRawFrame;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ /* SS TEST */
+ pr_info("SS RAW Testes are starting...\n");
+
+ /************** Self Sense Test **************/
+
+ pr_info("Getting SS Frame...\n");
+ ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_ACTIVE);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ ret |= getSSFrame3(SS_RAW, &ssRawFrame);
+ if (ret < 0) {
+ pr_err("production_test_data: getSSFrame failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ print_frame_short("SS Raw force frame =",
+ array1dTo2d_short(
+ ssRawFrame.force_data,
+ ssRawFrame.header.force_node,
+ 1),
+ ssRawFrame.header.force_node, 1);
+ print_frame_short("SS Raw sense frame =",
+ array1dTo2d_short(
+ ssRawFrame.sense_data,
+ ssRawFrame.header.sense_node,
+ ssRawFrame.header.sense_node),
+ 1, ssRawFrame.header.sense_node);
+
+ /* SS RAW (PROXIMITY) FORCE TEST */
+ pr_info("SS RAW FORCE TEST:\n");
+
+
+
+ if (todo->SelfForceRaw == 1 || todo->SelfForceRawGap == 1) {
+ columns = 1; /* there are no data for the sense channels
+ * because is a force frame */
+ rows = ssRawFrame.header.force_node;
+
+ pr_info("SS RAW FORCE MIN MAX TEST:\n");
+ if (todo->SelfForceRaw == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_FORCE_MIN_MAX,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMinMax(ssRawFrame.force_data, rows,
+ columns, thresholds[0],
+ thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS RAW FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS RAW (PROXIMITY) FORCE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW FORCE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW FORCE MIN MAX TEST:.................SKIPPED\n\n");
+
+ pr_info("SS RAW FORCE GAP TEST:\n");
+ if (todo->SelfForceRawGap == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_FORCE_GAP,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_GAP failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsGap(ssRawFrame.force_data, rows,
+ columns, thresholds[0]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsGap SS RAW FORCE GAP failed... ERROR = %08X\n",
+ ret);
+ pr_err("SS RAW FORCE GAP TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW FORCE GAP TEST:.................OK\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW FORCE GAP TEST:.................SKIPPED\n\n");
+
+ kfree(ssRawFrame.force_data);
+ ssRawFrame.force_data = NULL;
+ } else
+ pr_info("SS RAW FORCE TEST:.................SKIPPED\n\n");
+
+ /* SS RAW (PROXIMITY) SENSE TEST */
+ pr_info("SS RAW SENSE TEST:\n");
+
+ if (todo->SelfSenseRaw == 1 || todo->SelfSenseRawGap == 1) {
+ columns = ssRawFrame.header.sense_node;
+ rows = 1;/* there are no data for the force channels
+ * because is a sense frame */
+
+ pr_info("SS RAW SENSE MIN MAX TEST:\n");
+ if (todo->SelfSenseRaw == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_SENSE_MIN_MAX,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMinMax(ssRawFrame.sense_data, rows,
+ columns, thresholds[0],
+ thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS RAW SENSE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS RAW SENSE MIN MAX TEST:.................FAIL\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW SENSE MIN MAX TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW SENSE MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("SS RAW SENSE GAP TEST:\n");
+ if (todo->SelfSenseRawGap == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_SENSE_GAP,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_GAP failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsGap(ssRawFrame.sense_data, rows,
+ columns, thresholds[0]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsGap SS RAW SENSE GAP failed... ERROR = %08X\n",
+ ret);
+ pr_err("SS RAW SENSE GAP TEST:.................FAIL\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW SENSE GAP TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW SENSE GAP TEST:.................SKIPPED\n");
+
+ kfree(ssRawFrame.sense_data);
+ ssRawFrame.sense_data = NULL;
+ }
+
+ ret = production_test_ss_raw_lp(path_limits, stop_on_fail, todo);
+ if (ret < OK) {
+ pr_err("production_test_data: production_test_ss_raw_lp failed... ERROR = %08X\n",
+ ret);
+ count_fail += 1;
+ }
+
+ if (count_fail == 0) {
+ pr_info("SS RAW testes finished!.................OK\n\n");
+ return OK;
+ } else {
+ pr_err("SS RAW testes finished!.................FAILED fails_count = %d\n\n",
+ count_fail);
+ return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA;
+ }
+
+ERROR_LIMITS:
+ if (ssRawFrame.force_data != NULL)
+ kfree(ssRawFrame.force_data);
+ if (ssRawFrame.sense_data != NULL)
+ kfree(ssRawFrame.sense_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ return ret;
+}
+
+
+/**
+ * Perform all the test selected in a TestTodo variable related to SS raw data
+ * low power
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ss_raw_lp(char *path_limits, int stop_on_fail,
+ TestToDo *todo)
+{
+ int ret;
+ int count_fail = 0;
+ int rows, columns;
+
+ SelfSenseFrame ssRawFrame;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+
+ /* SS TEST */
+ pr_info("SS RAW LP Testes are starting...\n");
+
+ /************** Self Sense Test **************/
+
+ pr_info("Getting SS LP Frame...\n");
+ ret = setScanMode(SCAN_MODE_LOCKED, LOCKED_LP_DETECT);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ ret |= setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ ret |= getSSFrame3(SS_RAW, &ssRawFrame);
+ if (ret < 0) {
+ pr_err("production_test_data: getSSFrame failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ print_frame_short("SS Raw LP force frame =",
+ array1dTo2d_short(
+ ssRawFrame.force_data,
+ ssRawFrame.header.force_node, 1),
+ ssRawFrame.header.force_node, 1);
+ print_frame_short("SS Raw LP sense frame =",
+ array1dTo2d_short(
+ ssRawFrame.sense_data,
+ ssRawFrame.header.sense_node,
+ ssRawFrame.header.sense_node),
+ 1, ssRawFrame.header.sense_node);
+
+ /* SS RAW (PROXIMITY) FORCE TEST */
+ pr_info("SS RAW LP FORCE TEST:\n");
+
+ if (todo->SelfForceRawLP == 1 || todo->SelfForceRawGapLP == 1) {
+ columns = 1; /* there are no data for the sense channels
+ * because is a force frame */
+ rows = ssRawFrame.header.force_node;
+
+ pr_info("SS RAW LP FORCE MIN MAX TEST:\n");
+ if (todo->SelfForceRawLP == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_LP_FORCE_MIN_MAX,
+ &thresholds,
+ &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMinMax(ssRawFrame.force_data, rows,
+ columns, thresholds[0],
+ thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS RAW FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS RAW LP FORCE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW LP FORCE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW LP FORCE MIN MAX TEST:.................SKIPPED\n\n");
+
+ pr_info("SS RAW LP FORCE GAP TEST:\n");
+ if (todo->SelfForceRawGapLP == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_LP_FORCE_GAP,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < OK || (trows != 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_FORCE_GAP failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsGap(ssRawFrame.force_data, rows,
+ columns, thresholds[0]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsGap SS RAW FORCE GAP failed... ERROR = %08X\n",
+ ret);
+ pr_err("SS RAW LP FORCE GAP TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW LP FORCE GAP TEST:.................OK\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW LP FORCE GAP TEST:.................SKIPPED\n\n");
+
+ kfree(ssRawFrame.force_data);
+ ssRawFrame.force_data = NULL;
+ } else
+ pr_info("SS RAW LP FORCE TEST:.................SKIPPED\n\n");
+
+ /* SS RAW (PROXIMITY) SENSE TEST */
+ pr_info("SS RAW LP SENSE TEST:\n");
+
+ if (todo->SelfSenseRawLP == 1 || todo->SelfSenseRawGapLP == 1) {
+ columns = ssRawFrame.header.sense_node;
+ rows = 1;/* there are no data for the force channels
+ * because is a sense frame */
+
+ pr_info("SS RAW LP SENSE MIN MAX TEST:\n");
+ if (todo->SelfSenseRawLP == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_LP_SENSE_MIN_MAX,
+ &thresholds,
+ &trows, &tcolumns);
+ if (ret < OK || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMinMax(ssRawFrame.sense_data, rows,
+ columns, thresholds[0],
+ thresholds[1]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS RAW SENSE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS RAW LP SENSE MIN MAX TEST:.................FAIL\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW SENSE MIN MAX TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW LP SENSE MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("SS RAW LP SENSE GAP TEST:\n");
+ if (todo->SelfSenseRawGapLP == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_RAW_LP_SENSE_GAP,
+ &thresholds, &trows,
+ &tcolumns);
+ if (ret < OK || (trows != 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_RAW_SENSE_GAP failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsGap(ssRawFrame.sense_data, rows,
+ columns, thresholds[0]);
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsGap SS RAW SENSE GAP failed... ERROR = %08X\n",
+ ret);
+ pr_err("SS RAW LP SENSE GAP TEST:.................FAIL\n");
+ count_fail += 1;
+ if (stop_on_fail) {
+ ret = ERROR_PROD_TEST_DATA |
+ ERROR_TEST_CHECK_FAIL;
+ goto ERROR_LIMITS;
+ }
+ } else
+ pr_info("SS RAW LP SENSE GAP TEST:.................OK\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS RAW LP SENSE GAP TEST:.................SKIPPED\n");
+
+ kfree(ssRawFrame.sense_data);
+ ssRawFrame.sense_data = NULL;
+ }
+
+ if (count_fail == 0) {
+ pr_info("SS RAW LP testes finished!.................OK\n\n");
+ return OK;
+ } else {
+ pr_err("SS RAW LP testes finished!.................FAILED fails_count = %d\n\n",
+ count_fail);
+ return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA;
+ }
+
+ERROR_LIMITS:
+ if (ssRawFrame.force_data != NULL)
+ kfree(ssRawFrame.force_data);
+ if (ssRawFrame.sense_data != NULL)
+ kfree(ssRawFrame.sense_data);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ return ret;
+}
+
+/**
+ * Perform all the tests selected in a TestTodo variable related to SS Init
+ * data (touch, keys etc..)
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_ss_ix_cx(char *path_limits, int stop_on_fail,
+ TestToDo *todo)
+{
+ int ret;
+ int count_fail = 0;
+
+ int *thresholds = NULL;
+ int trows, tcolumns;
+ int *thresholds_min = NULL;
+ int *thresholds_max = NULL;
+
+ SelfSenseData ssCompData;
+ TotSelfSenseData totCompData;
+
+ u8 *adjhor = NULL;
+ u8 *adjvert = NULL;
+
+ short container;
+
+ u16 *total_adjhor = NULL;
+ u16 *total_adjvert = NULL;
+
+ pr_info("SS IX CX testes are starting...\n");
+ ret = readSelfSenseCompensationData(LOAD_CX_SS_TOUCH, &ssCompData);
+ /* read the SS compensation data */
+ if (ret < 0) {
+ pr_err("production_test_data: readSelfSenseCompensationData failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ ret = readTotSelfSenseCompensationData(LOAD_PANEL_CX_TOT_SS_TOUCH,
+ &totCompData);
+ /* read the TOT SS compensation data */
+ if (ret < 0) {
+ pr_err("production_test_data: readTotSelfSenseCompensationData failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ kfree(ssCompData.ix2_fm);
+ kfree(ssCompData.ix2_sn);
+ kfree(ssCompData.cx2_fm);
+ kfree(ssCompData.cx2_sn);
+ return ret | ERROR_PROD_TEST_DATA;
+ }
+
+ /************* SS FORCE IX **************/
+ /* SS IX1 FORCE TEST */
+ pr_info("SS IX1 FORCE TEST:\n");
+ if (todo->SelfForceIx1 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX1_FORCE_MIN_MAX,
+ &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX1_FORCE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ container = (short)ssCompData.f_ix1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0],
+ thresholds[1]);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS IX1 FORCE TEST failed... ERROR COUNT = %d\n",
+ ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS IX1 FORCE TEST:.................OK\n\n");
+ } else
+ pr_info("SS IX1 FORCE TEST:.................SKIPPED\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ /* SS IX2 FORCE TEST */
+ pr_info("SS IX2 FORCE MIN MAX TEST:\n");
+ if (todo->SelfForceIx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX2_FORCE_MAP_MIN,
+ &thresholds_min, &trows,
+ &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_FORCE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX2_FORCE_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_FORCE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapFromU(ssCompData.ix2_fm,
+ ssCompData.header.force_node, 1,
+ thresholds_min,
+ thresholds_max); /* check the
+ * values with
+ * thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS IX2 FORCE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS IX2 FORCE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS IX2 FORCE MIN MAX TEST:.................SKIPPED\n\n");
+
+ pr_info("SS IX2 FORCE ADJ TEST:\n");
+ if (todo->SelfForceIx2Adj == 1) {
+ /* SS IX2 FORCE ADJV TEST */
+ pr_info("SS IX2 FORCE ADJVERT TEST:\n");
+ ret = computeAdjVertFromU(ssCompData.ix2_fm,
+ ssCompData.header.force_node, 1,
+ &adjvert);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert SS IX2 FORCE ADJV failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS IX2 FORCE ADJV computed!\n");
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX2_FORCE_ADJV_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns); /* load the max
+ * thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node - 1 ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_FORCE_ADJV_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdj(adjvert, ssCompData.header.force_node -
+ 1, 1, thresholds_max); /* check the
+ * values with
+ * thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS IX2 FORCE ADJV TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS IX2 FORCE ADJV TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(adjvert);
+ adjvert = NULL;
+ } else
+ pr_info("SS IX2 FORCE ADJ TEST:.................SKIPPED\n\n");
+
+ /* SS TOTAL FORCE IX */
+ pr_info("SS TOTAL IX FORCE TEST:\n");
+ if (todo->SelfForceIxTotal == 1 || todo->SelfForceIxTotalAdj == 1) {
+ pr_info("SS TOTAL IX FORCE MIN MAX TEST:\n");
+ if (todo->SelfForceIxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_IX_FORCE_MAP_MIN,
+ &thresholds_min,
+ &trows, &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_IX_FORCE_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapTotalFromU(totCompData.ix_fm,
+ totCompData.header.
+ force_node, 1,
+ thresholds_min,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS TOTAL IX FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL IX FORCE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL IX FORCE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS TOTAL IX FORCE MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("SS TOTAL IX FORCE ADJ TEST:\n");
+ if (todo->SelfForceIxTotalAdj == 1) {
+ /* SS TOTAL IX FORCE ADJV TEST */
+ pr_info("SS TOTAL IX FORCE ADJVERT TEST:\n");
+ ret = computeAdjVertTotalFromU(totCompData.ix_fm,
+ totCompData.header.
+ force_node, 1,
+ &total_adjvert);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert SS TOTAL IX FORCE ADJV failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS TOTAL IX FORCE ADJV computed!\n");
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_IX_FORCE_ADJV_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != totCompData.header.force_node -
+ 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_FORCE_ADJV_MAP_MAX... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjvert,
+ totCompData.header.
+ force_node - 1, 1,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS TOTAL IX FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL IX FORCE ADJV TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL IX FORCE ADJV TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(total_adjvert);
+ total_adjvert = NULL;
+ } else
+ pr_info("SS TOTAL IX FORCE ADJ TEST:.................SKIPPED\n");
+ } else
+ pr_info("SS TOTAL IX FORCE TEST:.................SKIPPED\n\n");
+
+
+ /************** SS SENSE IX **************/
+ /* SS IX1 SENSE TEST */
+ pr_info("SS IX1 SENSE TEST:\n");
+ if (todo->SelfSenseIx1 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX1_SENSE_MIN_MAX,
+ &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX1_SENSE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ container = (short)ssCompData.s_ix1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0],
+ thresholds[1]);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS IX1 SENSE TEST failed... ERROR COUNT = %d\n",
+ ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS IX1 SENSE TEST:.................OK\n\n");
+ } else
+ pr_info("SS IX1 SENSE TEST:.................SKIPPED\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ /* SS IX2 SENSE TEST */
+ pr_info("SS IX2 SENSE MIN MAX TEST:\n");
+ if (todo->SelfSenseIx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX2_SENSE_MAP_MIN,
+ &thresholds_min, &trows,
+ &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ ssCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX2_SENSE_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ ssCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapFromU(ssCompData.ix2_sn, 1,
+ ssCompData.header.sense_node,
+ thresholds_min, thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS IX2 SENSE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS IX2 SENSE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS IX2 SENSE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS IX2 SENSE MIN MAX TEST:.................SKIPPED\n\n");
+
+ pr_info("SS IX2 SENSE ADJ TEST:\n");
+ if (todo->SelfSenseIx2Adj == 1) {
+ /* SS IX2 SENSE ADJH TEST */
+ pr_info("SS IX2 SENSE ADJHORIZ TEST:\n");
+ ret = computeAdjHorizFromU(ssCompData.ix2_sn, 1,
+ ssCompData.header.sense_node,
+ &adjhor);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz SS IX2 SENSE ADJH failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS IX2 SENSE ADJ HORIZ computed!\n");
+
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_IX2_SENSE_ADJH_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ ssCompData.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_ADJH_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdj(adjhor, 1,
+ ssCompData.header.sense_node - 1,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj SS IX2 SENSE ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS IX2 SENSE ADJH TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS IX2 SENSE ADJH TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(adjhor);
+ adjhor = NULL;
+ } else
+ pr_info("SS IX2 SENSE ADJ TEST:.................SKIPPED\n");
+
+ /* SS TOTAL IX SENSE */
+ pr_info("SS TOTAL IX SENSE TEST:\n");
+ if (todo->SelfSenseIxTotal == 1 || todo->SelfSenseIxTotalAdj == 1) {
+ pr_info("SS TOTAL IX SENSE MIN MAX TEST:\n");
+ if (todo->SelfSenseIxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_IX_SENSE_MAP_MIN,
+ &thresholds_min,
+ &trows, &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_IX_SENSE_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapTotalFromU(totCompData.ix_sn, 1,
+ totCompData.header.
+ sense_node,
+ thresholds_min,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS TOTAL IX SENSE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL IX SENSE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL IX SENSE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS TOTAL IX SENSE MIN MAX TEST:.................SKIPPED\n");
+
+
+ pr_info("SS TOTAL IX SENSE ADJ TEST:\n");
+ if (todo->SelfSenseIxTotalAdj == 1) {
+ /* SS TOTAL IX SENSE ADJH TEST */
+ pr_info("SS TOTAL IX SENSE ADJHORIZ TEST:\n");
+ ret = computeAdjHorizTotalFromU(totCompData.ix_sn, 1,
+ totCompData.header.
+ sense_node,
+ &total_adjhor);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz SS TOTAL IX SENSE ADJH failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS TOTAL IX SENSE ADJ HORIZ computed!\n");
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_IX_SENSE_ADJH_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ totCompData.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_IX_SENSE_ADJH_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjhor, 1,
+ totCompData.header.
+ sense_node - 1,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj SS TOTAL IX SENSE ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL IX SENSE ADJH TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL IX SENSE ADJH TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(total_adjhor);
+ total_adjhor = NULL;
+ } else
+ pr_info("SS TOTAL IX SENSE ADJ TEST:.................SKIPPED\n");
+ } else
+ pr_info("SS TOTAL IX SENSE TEST:.................SKIPPED\n");
+
+ /************* SS SENSE CX **************/
+ /* SS CX1 FORCE TEST */
+ pr_info("SS CX1 FORCE TEST:\n");
+ if (todo->SelfForceCx1 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX1_FORCE_MIN_MAX,
+ &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX1_FORCE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ container = (short)ssCompData.f_cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0],
+ thresholds[1]);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS CX1 FORCE TEST failed... ERROR COUNT = %d\n",
+ ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS CX1 FORCE TEST:.................OK\n\n");
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS CX1 FORCE TEST:.................SKIPPED\n\n");
+
+ /* SS CX2 FORCE TEST */
+ pr_info("SS CX2 FORCE MIN MAX TEST:\n");
+ if (todo->SelfForceCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX2_FORCE_MAP_MIN,
+ &thresholds_min, &trows,
+ &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX2_FORCE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX2_FORCE_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX2_FORCE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMap(ssCompData.cx2_fm,
+ ssCompData.header.force_node, 1,
+ thresholds_min,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS CX2 FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS CX2 FORCE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS CX2 FORCE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS CX2 FORCE MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("SS CX2 FORCE ADJ TEST:\n");
+ if (todo->SelfForceCx2Adj == 1) {
+ /* SS CX2 FORCE ADJV TEST */
+ pr_info("SS CX2 FORCE ADJVERT TEST:\n");
+ ret = computeAdjVert(ssCompData.cx2_fm,
+ ssCompData.header.force_node, 1, &adjvert);
+ /* compute the ADJV for CX2 FORCE */
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert SS CX2 FORCE ADJV failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS CX2 FORCE ADJV computed!\n");
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX2_FORCE_ADJV_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != ssCompData.header.force_node - 1 ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX2_FORCE_ADJV_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdj(adjvert, ssCompData.header.force_node -
+ 1, 1, thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS IX2 FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS CX2 FORCE ADJV TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS CX2 FORCE ADJV TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(adjvert);
+ adjvert = NULL;
+ } else
+ pr_info("SS CX2 FORCE ADJ TEST:.................SKIPPED\n\n");
+
+ /* SS TOTAL CX FORCE */
+ pr_info("SS TOTAL CX FORCE TEST:\n");
+ if (todo->SelfForceCxTotal == 1 || todo->SelfForceCxTotalAdj == 1) {
+ pr_info("SS TOTAL CX FORCE MIN MAX TEST:\n");
+ if (todo->SelfForceCxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_CX_FORCE_MAP_MIN,
+ &thresholds_min,
+ &trows, &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_CX_FORCE_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows !=
+ totCompData.header.force_node ||
+ tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapTotal(totCompData.cx_fm,
+ totCompData.header.force_node,
+ 1, thresholds_min,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS TOTAL FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL FORCE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL FORCE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS TOTAL CX FORCE MIN MAX TEST:.................SKIPPED\n");
+
+ /* SS TOTAL CX FORCE ADJV TEST */
+ pr_info("SS TOTAL CX FORCE ADJ TEST:\n");
+ if (todo->SelfForceCxTotalAdj == 1) {
+ pr_info("SS TOTAL CX FORCE ADJVERT TEST:\n");
+ ret = computeAdjVertTotal(totCompData.cx_fm,
+ totCompData.header.force_node,
+ 1, &total_adjvert);
+ /* compute the ADJV for CX2 FORCE */
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjVert SS TOTAL CX FORCE ADJV failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS TOTAL CX FORCE ADJV computed!\n");
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_CX_FORCE_ADJV_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != totCompData.header.force_node -
+ 1 || tcolumns != 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_FORCE_ADJV_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjvert,
+ totCompData.header.
+ force_node - 1, 1,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS TOTAL CX FORCE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL CX FORCE ADJV TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL CX FORCE ADJV TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(total_adjvert);
+ total_adjvert = NULL;
+ } else
+ pr_info("SS TOTAL CX FORCE ADJ TEST:.................SKIPPED\n");
+ } else
+ pr_info("SS TOTAL CX FORCE TEST:.................SKIPPED\n\n");
+
+
+
+ /************* SS SENSE CX *************/
+ /* SS CX1 SENSE TEST */
+ pr_info("SS CX1 SENSE TEST:\n");
+ if (todo->SelfSenseCx1 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX1_SENSE_MIN_MAX,
+ &thresholds, &trows, &tcolumns);
+ if (ret < 0 || (trows != 1 || tcolumns != 2)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX1_SENSE_MIN_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ container = (short)ssCompData.s_cx1;
+ ret = checkLimitsMinMax(&container, 1, 1, thresholds[0],
+ thresholds[1]);
+ /* check the limits */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMinMax SS CX1 SENSE TEST failed... ERROR COUNT = %d\n",
+ ret);
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS CX1 SENSE TEST:.................OK\n\n");
+
+ kfree(thresholds);
+ thresholds = NULL;
+ } else
+ pr_info("SS CX1 SENSE TEST:.................SKIPPED\n\n");
+
+
+ /* SS CX2 SENSE TEST */
+ pr_info("SS CX2 SENSE MIN MAX TEST:\n");
+ if (todo->SelfSenseCx2 == 1) {
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX2_SENSE_MAP_MIN,
+ &thresholds_min, &trows,
+ &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ ssCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX2_SENSE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX2_SENSE_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ ssCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_CX2_SENSE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMap(ssCompData.cx2_sn, 1,
+ ssCompData.header.sense_node,
+ thresholds_min, thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS CX2 SENSE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS CX2 SENSE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS CX2 SENSE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS CX2 SENSE MIN MAX TEST:.................SKIPPED\n");
+
+ pr_info("SS CX2 SENSE ADJ TEST:\n");
+ if (todo->SelfSenseCx2Adj == 1) {
+ /* SS CX2 SENSE ADJH TEST */
+ pr_info("SS CX2 SENSE ADJHORIZ TEST:\n");
+ ret = computeAdjHoriz(ssCompData.cx2_sn, 1,
+ ssCompData.header.sense_node, &adjhor);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz SS CX2 SENSE ADJH failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS CX2 SENSE ADJH computed!\n");
+
+
+ ret = parseProductionTestLimits(path_limits, &limit_file,
+ SS_CX2_SENSE_ADJH_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ ssCompData.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_IX2_SENSE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdj(adjhor, 1,
+ ssCompData.header.sense_node - 1,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj SS CX2 SENSE ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS CX2 SENSE ADJH TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS CX2 SENSE ADJH TEST:.................OK\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(adjhor);
+ adjhor = NULL;
+ } else
+ pr_info("SS CX2 SENSE ADJ TEST:.................SKIPPED\n\n");
+
+ /* SS TOTAL CX SENSE */
+ pr_info("SS TOTAL CX SENSE TEST:\n");
+ if (todo->SelfSenseCxTotal == 1 || todo->SelfSenseCxTotalAdj == 1) {
+ pr_info("SS TOTAL CX SENSE MIN MAX TEST:\n");
+ if (todo->SelfSenseCxTotal == 1) {
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_CX_SENSE_MAP_MIN,
+ &thresholds_min,
+ &trows, &tcolumns);
+ /* load the min thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_MAP_MIN failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_CX_SENSE_MAP_MAX,
+ &thresholds_max,
+ &trows, &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ totCompData.header.sense_node)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapTotal(totCompData.cx_sn, 1,
+ totCompData.header.sense_node,
+ thresholds_min,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMap SS TOTAL CX SENSE failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL CX SENSE MIN MAX TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL CX SENSE MIN MAX TEST:.................OK\n\n");
+
+ kfree(thresholds_min);
+ thresholds_min = NULL;
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ } else
+ pr_info("SS TOTAL CX SENSE MIN MAX TEST:.................SKIPPED\n");
+
+
+ /* SS TOTAL IX SENSE ADJH TEST */
+ pr_info("SS TOTAL CX SENSE ADJ TEST:\n");
+ if (todo->SelfSenseCxTotalAdj == 1) {
+ pr_info("SS TOTAL CX SENSE ADJHORIZ TEST:\n");
+ ret = computeAdjHorizTotal(totCompData.cx_sn, 1,
+ totCompData.header.sense_node,
+ &total_adjhor);
+ if (ret < 0) {
+ pr_err("production_test_data: computeAdjHoriz SS TOTAL CX SENSE ADJH failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+ pr_info("SS TOTAL CX SENSE ADJ HORIZ computed!\n");
+
+
+ ret = parseProductionTestLimits(path_limits,
+ &limit_file,
+ SS_TOTAL_CX_SENSE_ADJH_MAP_MAX,
+ &thresholds_max, &trows,
+ &tcolumns);
+ /* load the max thresholds */
+ if (ret < 0 || (trows != 1 || tcolumns !=
+ totCompData.header.sense_node - 1)) {
+ pr_err("production_test_data: parseProductionTestLimits SS_TOTAL_CX_SENSE_ADJH_MAP_MAX failed... ERROR %08X\n",
+ ERROR_PROD_TEST_DATA);
+ ret |= ERROR_PROD_TEST_DATA;
+ goto ERROR_LIMITS;
+ }
+
+ ret = checkLimitsMapAdjTotal(total_adjhor, 1,
+ totCompData.header.
+ sense_node - 1,
+ thresholds_max);
+ /* check the values with thresholds */
+ if (ret != OK) {
+ pr_err("production_test_data: checkLimitsMapAdj SS TOTAL CX SENSE ADJH failed... ERROR COUNT = %d\n",
+ ret);
+ pr_err("SS TOTAL CX SENSE ADJH TEST:.................FAIL\n\n");
+ count_fail += 1;
+ if (stop_on_fail)
+ goto ERROR;
+ } else
+ pr_info("SS TOTAL CX SENSE ADJH TEST:.................OK\n\n");
+
+ kfree(thresholds_max);
+ thresholds_max = NULL;
+ kfree(total_adjhor);
+ total_adjhor = NULL;
+ } else
+ pr_info("SS TOTAL CX SENSE ADJ TEST:.................SKIPPED\n");
+ } else
+ pr_info("SS TOTAL CX SENSE TEST:.................SKIPPED\n");
+
+
+
+ERROR:
+ if (count_fail == 0) {
+ kfree(ssCompData.ix2_fm);
+ ssCompData.ix2_fm = NULL;
+ kfree(ssCompData.ix2_sn);
+ ssCompData.ix2_sn = NULL;
+ kfree(ssCompData.cx2_fm);
+ ssCompData.cx2_fm = NULL;
+ kfree(ssCompData.cx2_sn);
+ ssCompData.cx2_sn = NULL;
+ kfree(totCompData.ix_fm);
+ totCompData.ix_fm = NULL;
+ kfree(totCompData.ix_sn);
+ totCompData.ix_sn = NULL;
+ kfree(totCompData.cx_fm);
+ totCompData.cx_fm = NULL;
+ kfree(totCompData.cx_sn);
+ totCompData.cx_sn = NULL;
+ pr_info("SS IX CX testes finished!.................OK\n\n");
+ return OK;
+ } else {
+ /* print all kind of data in just one row for readability reason */
+ print_frame_u8("SS Init Data Ix2_fm = ", array1dTo2d_u8(
+ ssCompData.ix2_fm,
+ ssCompData.header.force_node, 1),
+ ssCompData.header.force_node, 1);
+ print_frame_i8("SS Init Data Cx2_fm = ", array1dTo2d_i8(
+ ssCompData.cx2_fm,
+ ssCompData.header.force_node, 1),
+ ssCompData.header.force_node, 1);
+ print_frame_u8("SS Init Data Ix2_sn = ", array1dTo2d_u8(
+ ssCompData.ix2_sn,
+ ssCompData.header.sense_node,
+ ssCompData.header.sense_node), 1,
+ ssCompData.header.sense_node);
+ print_frame_i8("SS Init Data Cx2_sn = ", array1dTo2d_i8(
+ ssCompData.cx2_sn,
+ ssCompData.header.sense_node,
+ ssCompData.header.sense_node), 1,
+ ssCompData.header.sense_node);
+ print_frame_u16("TOT SS Init Data Ix_fm = ", array1dTo2d_u16(
+ totCompData.ix_fm,
+ totCompData.header.force_node, 1),
+ totCompData.header.force_node, 1);
+ print_frame_short("TOT SS Init Data Cx_fm = ",
+ array1dTo2d_short(totCompData.cx_fm,
+ totCompData.header.
+ force_node, 1),
+ totCompData.header.force_node, 1);
+ print_frame_u16("TOT SS Init Data Ix_sn = ", array1dTo2d_u16(
+ totCompData.ix_sn,
+ totCompData.header.sense_node,
+ totCompData.header.sense_node), 1,
+ totCompData.header.sense_node);
+ print_frame_short("TOT SS Init Data Cx_sn = ",
+ array1dTo2d_short(totCompData.cx_sn,
+ totCompData.header.
+ sense_node,
+ totCompData.header.
+ sense_node),
+ 1, totCompData.header.sense_node);
+ pr_err("SS IX CX testes finished!.................FAILED fails_count = %d\n\n",
+ count_fail);
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (thresholds_min != NULL)
+ kfree(thresholds_min);
+ if (thresholds_max != NULL)
+ kfree(thresholds_max);
+ if (adjhor != NULL)
+ kfree(adjhor);
+ if (adjvert != NULL)
+ kfree(adjvert);
+ if (total_adjhor != NULL)
+ kfree(total_adjhor);
+ if (total_adjvert != NULL)
+ kfree(total_adjvert);
+ if (ssCompData.ix2_fm != NULL)
+ kfree(ssCompData.ix2_fm);
+ if (ssCompData.ix2_sn != NULL)
+ kfree(ssCompData.ix2_sn);
+ if (ssCompData.cx2_fm != NULL)
+ kfree(ssCompData.cx2_fm);
+ if (ssCompData.cx2_sn != NULL)
+ kfree(ssCompData.cx2_sn);
+ if (totCompData.ix_fm != NULL)
+ kfree(totCompData.ix_fm);
+ if (totCompData.ix_sn != NULL)
+ kfree(totCompData.ix_sn);
+ if (totCompData.cx_fm != NULL)
+ kfree(totCompData.cx_fm);
+ if (totCompData.cx_sn != NULL)
+ kfree(totCompData.cx_sn);
+ return ERROR_TEST_CHECK_FAIL | ERROR_PROD_TEST_DATA;
+ }
+
+ERROR_LIMITS:
+ if (thresholds != NULL)
+ kfree(thresholds);
+ if (thresholds_min != NULL)
+ kfree(thresholds_min);
+ if (thresholds_max != NULL)
+ kfree(thresholds_max);
+ if (adjhor != NULL)
+ kfree(adjhor);
+ if (adjvert != NULL)
+ kfree(adjvert);
+ if (total_adjhor != NULL)
+ kfree(total_adjhor);
+ if (total_adjvert != NULL)
+ kfree(total_adjvert);
+ if (ssCompData.ix2_fm != NULL)
+ kfree(ssCompData.ix2_fm);
+ if (ssCompData.ix2_sn != NULL)
+ kfree(ssCompData.ix2_sn);
+ if (ssCompData.cx2_fm != NULL)
+ kfree(ssCompData.cx2_fm);
+ if (ssCompData.cx2_sn != NULL)
+ kfree(ssCompData.cx2_sn);
+ if (totCompData.ix_fm != NULL)
+ kfree(totCompData.ix_fm);
+ if (totCompData.ix_sn != NULL)
+ kfree(totCompData.ix_sn);
+ if (totCompData.cx_fm != NULL)
+ kfree(totCompData.cx_fm);
+ if (totCompData.cx_sn != NULL)
+ kfree(totCompData.cx_sn);
+ return ret;
+}
+
+/**
+ * Perform a complete Data Test check of the IC
+ * @param path_limits name of Production Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param stop_on_fail if 1, the test flow stops at the first data check
+ * failure
+ * otherwise it keeps going performing all the selected test
+ * @param todo pointer to a TestToDo variable which select the test to do
+ * @return OK if success or an error code which specify the type of error
+ */
+int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo)
+{
+ int res = OK, ret;
+
+ if (todo == NULL) {
+ pr_err("production_test_data: No TestToDo specified!! ERROR = %08X\n",
+ (ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_DATA));
+ return ERROR_OP_NOT_ALLOW | ERROR_PROD_TEST_DATA;
+ }
+
+
+ pr_info("DATA Production test is starting...\n");
+
+
+ ret = production_test_ms_raw(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ pr_err("production_test_data: production_test_ms_raw failed... ERROR = %08X\n",
+ ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+
+
+ ret = production_test_ms_cx(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ pr_err("production_test_data: production_test_ms_cx failed... ERROR = %08X\n",
+ ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+
+ ret = production_test_ss_raw(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ pr_err("production_test_data: production_test_ss_raw failed... ERROR = %08X\n",
+ ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+ ret = production_test_ss_ix_cx(path_limits, stop_on_fail, todo);
+ res |= ret;
+ if (ret < 0) {
+ pr_err("production_test_data: production_test_ss_ix_cx failed... ERROR = %08X\n",
+ ret);
+ if (stop_on_fail == 1)
+ goto END;
+ }
+
+END:
+ freeLimitsFile(&limit_file); /* /< release the limit file loaded
+ * during the test */
+ if (res < OK)
+ pr_err("DATA Production test failed!\n");
+ else
+ pr_info("DATA Production test finished!\n");
+ return res;
+}
+
+
+/*************** TP Sensitivity calibration API ********************/
+
+/**
+ * Perform the Pre Calibration MS Test when the stimpad is down
+ * @param[out] frame pointer to the frame which will contain
+ * the average frame resulting from the test
+ * @param target reference value for the frame, each node should be
+ * around +-percentage% this value
+ * @param percentage percentage of the target value which define
+ * the valid interval for the frame, if <0 the test will be skipped
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_test_pre_cal_ms(MutualSenseFrame *finalFrame, short target,
+ int percentage)
+{
+ int ret = OK;
+ int count = 0, i = 0, j = 0;
+ short min, max;
+ MutualSenseFrame frame;
+
+ finalFrame->node_data = NULL;
+
+
+ pr_info("%s: Start TP sensitivity MS Pre Cal...\n", __func__);
+ pr_info("%s: IMPORTANT!!! Stimpad should be on the display of the device!\n",
+ __func__);
+ ret = getMSFrame3(MS_STRENGTH, &frame);
+ if (ret < OK) {
+ pr_err("%s: can not read MS Frame... ERROR %08X\n",
+ __func__, ret);
+ goto ERROR;
+ }
+
+ finalFrame->header = frame.header;
+ finalFrame->node_data_size = frame.node_data_size;
+
+ finalFrame->node_data = (short *)kzalloc(frame.node_data_size *
+ sizeof(short), GFP_KERNEL);
+ if (finalFrame->node_data == NULL) {
+ pr_err("%s: can not allocate node_data ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ ret = ERROR_ALLOC | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ /* collecting frames */
+ do {
+ for (i = 0; i < finalFrame->node_data_size; i++) {
+ finalFrame->node_data[i] += (frame.node_data[i] * 10) /
+ SENS_TEST_NUM_FRAMES;
+ }
+
+ if (frame.node_data != NULL) {
+ kfree(frame.node_data);
+ frame.node_data = NULL;
+ }
+
+ count++;
+
+ /* exclude one more reading at the end*/
+ if (count < SENS_TEST_NUM_FRAMES)
+ ret = getMSFrame3(MS_STRENGTH, &frame);
+ } while ((count < SENS_TEST_NUM_FRAMES) && (ret >= OK));
+
+ if (ret < OK) {
+ pr_err("%s: Error while capturing the frame %d! ERROR %08X\n",
+ __func__, count, ret);
+ goto ERROR;
+ }
+
+ ret = OK;
+ /* check against +-percentage% target */
+ pr_info("%s: Computing average frame...\n", __func__);
+
+ min = target - (target * percentage / 100);
+ max = target + (target * percentage / 100);
+
+ for (i = 0; i < finalFrame->header.force_node; i++) {
+ for (j = 0; j < finalFrame->header.sense_node; j++) {
+ finalFrame->node_data[i *
+ finalFrame->header.sense_node +
+ j] /= 10;
+ /*if percentage is <0 skip this test, just collect data */
+ if ((percentage > 0) &&
+ ((finalFrame->node_data[i * finalFrame->header.
+ sense_node
+ + j] >
+ max) ||
+ (finalFrame->node_data[i *
+ finalFrame->header.
+ sense_node
+ + j] <
+ min))) {
+ pr_err("%s: MS Force Node[%d, %d] = %d exceed limit [%d, %d]\n",
+ __func__, i, j,
+ finalFrame->node_data[i *
+ finalFrame
+ ->header.
+ sense_node + j],
+ min, max);
+ ret = ERROR_TEST_CHECK_FAIL;
+ }
+ }
+ }
+
+
+ /* print average frame in the log */
+ print_frame_short("MS FS Mean =",
+ array1dTo2d_short(
+ finalFrame->node_data,
+ finalFrame->node_data_size,
+ finalFrame->header.sense_node),
+ finalFrame->header.force_node,
+ finalFrame->header.sense_node);
+
+ if (ret != OK)
+ pr_err("%s: TP sensitivity MS Pre Cal test FAILED... ERROR %08X\n",
+ __func__, ret);
+ else
+ pr_info("%s: TP sensitivity MS Pre Cal FINISHED!\n",
+ __func__);
+
+ return ret;
+
+
+ERROR:
+ if (frame.node_data != NULL) {
+ kfree(frame.node_data);
+ frame.node_data = NULL;
+ }
+
+
+ if (finalFrame->node_data != NULL) {
+ kfree(finalFrame->node_data);
+ finalFrame->node_data = NULL;
+ }
+
+ return ret;
+}
+
+
+
+/**
+ * Perform the Pre Calibration SS Test when the stimpad is down
+ * @param[out] frame pointer to the frame which will contain the average frame
+ * resulting from the test
+ * @param target reference value for the frame, each node should be around
+ * +-percentage% this value
+ * @param percentage percentage of the target value which define the valid
+ * interval for the frame
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_test_pre_cal_ss(SelfSenseFrame *finalFrame, short target,
+ int percentage)
+{
+ int ret = OK;
+ int count = 0, i = 0;
+ short min, max;
+ SelfSenseFrame frame;
+ int *temp_force = NULL;
+ int *temp_sense = NULL;
+
+ finalFrame->force_data = NULL;
+ finalFrame->sense_data = NULL;
+
+ pr_info("%s: Start TP sensitivity SS Pre Cal...\n", __func__);
+ pr_info("%s: IMPORTANT!!! Stimpad should be on the display of the device!\n",
+ __func__);
+ ret = getSSFrame3(SS_STRENGTH, &frame);
+ if (ret < OK) {
+ pr_err("%s: can not read SS Frame... ERROR %08X\n",
+ __func__, ret);
+ goto ERROR;
+ }
+
+ finalFrame->header = frame.header;
+
+ finalFrame->force_data = (short *)kzalloc(frame.header.force_node *
+ sizeof(short), GFP_KERNEL);
+ temp_force = (int *)kzalloc(frame.header.force_node *
+ sizeof(int), GFP_KERNEL);
+ finalFrame->sense_data = (short *)kzalloc(frame.header.sense_node *
+ sizeof(short), GFP_KERNEL);
+ temp_sense = (int *)kzalloc(frame.header.sense_node *
+ sizeof(int), GFP_KERNEL);
+ if (finalFrame->force_data == NULL ||
+ temp_force == NULL ||
+ finalFrame->sense_data == NULL ||
+ temp_sense == NULL) {
+
+ pr_err("%s: can not allocate memory ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ ret = ERROR_ALLOC | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ /* collecting frames */
+ do {
+ for (i = 0; i < finalFrame->header.force_node; i++)
+ temp_force[i] += frame.force_data[i];
+
+ for (i = 0; i < finalFrame->header.sense_node; i++)
+ temp_sense[i] += frame.sense_data[i];
+
+ count++;
+
+ if (frame.force_data != NULL) {
+ kfree(frame.force_data);
+ frame.force_data = NULL;
+ }
+ if (frame.sense_data != NULL) {
+ kfree(frame.sense_data);
+ frame.sense_data = NULL;
+ }
+
+ /* exclude one more reading at the end*/
+ if (count < SENS_TEST_NUM_FRAMES)
+ ret = getSSFrame3(SS_STRENGTH, &frame);
+ } while ((count < SENS_TEST_NUM_FRAMES) && (ret >= OK));
+
+ if (ret < OK) {
+ pr_err("%s: Error while capturing the frame %d! ERROR %08X\n",
+ __func__, count, ret);
+ goto ERROR;
+ }
+
+ ret = OK;
+
+ /* compute the average and check against +-percentage% target */
+ min = target - (target * percentage / 100);
+ max = target + (target * percentage / 100);
+
+ for (i = 0; i < finalFrame->header.force_node; i++) {
+ finalFrame->force_data[i] = temp_force[i] /
+ SENS_TEST_NUM_FRAMES;
+ if ((percentage > 0) && ((finalFrame->force_data[i] > max) ||
+ (finalFrame->force_data[i] < min))) {
+ pr_err("%s: SS Force Node[%d] = %d exceed limit [%d, %d]\n",
+ __func__, i, finalFrame->force_data[i],
+ min, max);
+ ret = ERROR_TEST_CHECK_FAIL;
+ }
+ }
+
+ for (i = 0; i < finalFrame->header.sense_node; i++) {
+ finalFrame->sense_data[i] = temp_sense[i] /
+ SENS_TEST_NUM_FRAMES;
+ if ((finalFrame->sense_data[i] > max) ||
+ (finalFrame->sense_data[i] < min)) {
+ pr_err("%s: SS Sense Node[%d] = %d exceed limit [%d, %d]\n",
+ __func__, i, finalFrame->sense_data[i],
+ min, max);
+ ret = ERROR_TEST_CHECK_FAIL;
+ }
+ }
+
+ /* print average frame in the log */
+ print_frame_short("SS FS force Mean =",
+ array1dTo2d_short(
+ finalFrame->force_data,
+ finalFrame->header.force_node,
+ 1),
+ finalFrame->header.force_node, 1);
+ print_frame_short("SS FS sense Mean =",
+ array1dTo2d_short(
+ finalFrame->sense_data,
+ finalFrame->header.sense_node,
+ finalFrame->header.sense_node),
+ 1, finalFrame->header.sense_node);
+
+
+ kfree(temp_force);
+ temp_force = NULL;
+
+ kfree(temp_sense);
+ temp_sense = NULL;
+
+ if (ret < OK)
+ pr_err("%s: TP sensitivity SS Pre Cal test FAILED... ERROR %08X\n",
+ __func__, ret);
+ else {
+ pr_info("%s: TP sensitivity SS Pre Cal FINISHED!\n",
+ __func__);
+ ret = OK;
+ }
+
+ return ret;
+
+
+ERROR:
+
+ kfree(temp_force);
+ temp_force = NULL;
+
+ kfree(temp_sense);
+ temp_sense = NULL;
+
+ kfree(frame.force_data);
+ frame.force_data = NULL;
+
+ kfree(frame.sense_data);
+ frame.sense_data = NULL;
+
+ kfree(finalFrame->force_data);
+ finalFrame->force_data = NULL;
+
+ kfree(finalFrame->sense_data);
+ finalFrame->sense_data = NULL;
+
+ return ret;
+}
+
+/**
+ * Compute Digital gains for calibration
+ * @param frame pointer to the frame used as reference to compute the gains
+ * @param target reference target value for computing the gains
+ * @param saveGain if 1, will save the gain table into the chip otherwise will
+ * not save it
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_compute_gains(MutualSenseFrame *frame, short target,
+ int saveGain)
+{
+ int ret = OK;
+ int i = 0;
+ u8 gains[frame->node_data_size];
+
+ if ((frame->node_data == NULL) || (frame->node_data_size == 0)) {
+ pr_err("%s: Invalid frame data passed as argument! ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ memset(gains, 0, frame->node_data_size);
+
+ pr_info("%s: Start to compute Digital Gains...\n", __func__);
+ for (i = 0; i < frame->node_data_size; i++)
+ gains[i] = ((target * 100) / frame->node_data[i]) > 255 ?
+ (u8)(255) : (u8)(((target * 100) /
+ frame->node_data[i]));
+ /* clamp the max value to 255 because gain is only one byte */
+
+
+ /* print average frame in the log */
+ print_frame_u8("MS Digital Gain =",
+ array1dTo2d_u8(
+ gains,
+ frame->node_data_size,
+ frame->header.sense_node),
+ frame->header.force_node,
+ frame->header.sense_node);
+
+
+ /* if(saveGain==1){ */
+ /* write gains into the IC */
+ ret = writeHostDataMemory(LOAD_SENS_CAL_COEFF, gains,
+ frame->header.force_node,
+ frame->header.sense_node, 0, 0, saveGain);
+ if (ret != OK)
+ pr_err("%s: impossible to write digital gains! ERROR %08X\n",
+ __func__, ret);
+ /* } */
+
+ if (ret < OK)
+ pr_err("%s: compute Digital Gains FAILED! ERROR %08X\n",
+ __func__, ret);
+ else {
+ pr_info("%s: compute Digital Gains FINISHED!\n", __func__);
+ ret = OK;
+ }
+
+ return ret;
+}
+
+/**
+ * Perform the Post Calibration MS Test when the stimpad is down
+ * @param[out] finalFrame pointer to the frame which will contain
+ * the average frame resulting from the test
+ * @param[out] deltas pointer to the frame which will contain
+ * the FS Uniform frame (worst_neighborhood/mean)
+ * @param target reference value for the frame, each node should be
+ * around +-percentage% this value
+ * @param percentage percentage of the target value which define
+ * the valid interval for the frame, if <0 the test will be skipped
+ * @param[out] mean_normal pointer to the variable which will contain the mean
+ * of the normal area
+ * @param[out] mean_edge pointer to the variable which will contain the mean of
+ * the edge area
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_test_post_cal_ms(MutualSenseFrame *finalFrame,
+ MutualSenseFrame *deltas, short target,
+ int percentage, int *mean_normal,
+ int *mean_edge)
+{
+ short currentNode;
+ int final_force_num;
+ int final_sense_num;
+ short *final_node;
+ int delta_sense_num;
+ short *delta_node;
+ short *delta;
+ short adjNode;
+ int ret = OK;
+ int i = 0, j = 0, min, max;
+
+
+ if ((finalFrame == NULL) || (deltas == NULL) || (mean_normal == NULL) ||
+ (mean_edge == NULL)) {
+ pr_err("%s: Invalid arguments Passed! ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ *mean_normal = 0;
+ *mean_edge = 0;
+
+ finalFrame->node_data = NULL;
+ deltas->node_data = NULL;
+
+ pr_info("%s: Start TP sensitivity MS Post Cal...\n", __func__);
+ pr_info("%s: IMPORTANT!!! Stimpad should be on the display of the device!\n",
+ __func__);
+
+ /* collect frames skipping the tests + print on the log */
+ ret = tp_sensitivity_test_pre_cal_ms(finalFrame, target, -1);
+ if (ret < OK) {
+ pr_err("%s: can not collect MS Frame... ERROR %08X\n",
+ __func__, ret);
+ goto ERROR;
+ }
+
+
+ deltas->header = finalFrame->header;
+ deltas->node_data_size = finalFrame->node_data_size;
+
+ deltas->node_data = (short *)kzalloc(deltas->node_data_size *
+ sizeof(short), GFP_KERNEL);
+ if (deltas->node_data == NULL) {
+ pr_err("%s: can not allocate deltas node_data ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ ret = ERROR_ALLOC | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ /* compute the average of the whole panel and check against
+ * +-percentage% target */
+ pr_info("%s: Computing average of whole panel and delta for each node...\n",
+ __func__);
+
+ final_force_num = finalFrame->header.force_node;
+ final_sense_num = finalFrame->header.sense_node;
+ final_node = finalFrame->node_data;
+ delta_sense_num = deltas->header.sense_node;
+ delta_node = deltas->node_data;
+
+
+ for (i = 0; i < final_force_num; i++) {
+ for (j = 0; j < final_sense_num; j++) {
+ currentNode = finalFrame->node_data[i *
+ finalFrame->header.
+ sense_node + j];
+ delta = &delta_node[i * delta_sense_num + j];
+
+ if ((i == 0) ||
+ (i == (final_force_num - 1)) ||
+ (j == 0) ||
+ (j == (final_sense_num - 1))) {
+ /* edge nodes */
+ *mean_edge += currentNode;
+ if ((i == 0) ||
+ (i == final_force_num - 1)) {
+ /* need to check adj node up or down for
+ * nodes in the corners */
+ if ((i == 0) &&
+ ((j == 0) ||
+ (j == final_sense_num - 1))) {
+ adjNode = currentNode -
+ final_node[(i + 1) *
+ final_sense_num + j];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+
+ if ((i == (final_force_num - 1)) &&
+ ((j == 0) ||
+ (j == final_sense_num - 1))) {
+ adjNode = currentNode -
+ final_node[(i - 1) *
+ final_sense_num + j];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+
+ /* scan the row */
+ if ((j - 1) >= 0) {
+ adjNode = currentNode -
+ final_node[i *
+ final_sense_num +
+ (j - 1)];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+
+ if ((j + 1) < final_sense_num) {
+ adjNode = currentNode -
+ final_node[i *
+ final_sense_num +
+ (j + 1)];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+ }
+
+ if ((j == 0) ||
+ (j == final_sense_num - 1)) {
+ /* scan the column */
+ if ((i - 1) >= 0) {
+ adjNode = currentNode -
+ final_node[(i - 1) *
+ final_sense_num + j];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+
+ if ((i + 1) < final_force_num) {
+ adjNode = currentNode -
+ final_node[(i + 1) *
+ final_sense_num + j];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+ }
+ } else {
+ /*normal nodes */
+ *mean_normal += currentNode;
+
+ /* picking up the worst difference between
+ * one pixel and its neighbors */
+ if ((i - 1) >= 1) {
+ adjNode = currentNode -
+ final_node[(i - 1) *
+ final_sense_num + j];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+
+ if ((i + 1) < (final_force_num - 1)) {
+ adjNode = currentNode -
+ final_node[(i + 1) *
+ final_sense_num + j];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+ if ((j - 1) >= 1) {
+ adjNode = currentNode -
+ final_node[i *
+ final_sense_num + (j - 1)];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+
+ if ((j + 1) < (final_sense_num - 1)) {
+ adjNode = currentNode -
+ final_node[i *
+ final_sense_num + (j + 1)];
+ if (abs(adjNode) > *delta)
+ *delta = abs(adjNode);
+ }
+ }
+ }
+ }
+
+ *mean_normal /= (finalFrame->header.force_node - 2) *
+ (finalFrame->header.sense_node - 2);
+ *mean_edge /= (finalFrame->header.force_node * 2) +
+ (finalFrame->header.sense_node - 2) * 2;
+
+ pr_info("%s: Normal Frame average = %d\n", __func__, *mean_normal);
+ pr_info("%s: Edge Frame average = %d\n", __func__, *mean_edge);
+ /* compute the average and check against +-% target */
+ min = target - (target * percentage / 100);
+ max = target + (target * percentage / 100);
+
+ if ((percentage > 0) && ((*mean_normal < min) || (*mean_normal >
+ max))) {
+ pr_err("%s: Normal Frame average = %d exceed limit [%d, %d]\n",
+ __func__, *mean_normal, min, max);
+ ret = ERROR_TEST_CHECK_FAIL;
+ }
+
+ if ((percentage > 0) && ((*mean_edge < min) || (*mean_edge > max))) {
+ pr_err("%s: Edge Frame average = %d exceed limit [%d, %d]\n",
+ __func__, *mean_edge, min, max);
+ ret = ERROR_TEST_CHECK_FAIL;
+ }
+
+ for (i = 0; i < deltas->header.force_node; i++) {
+ for (j = 0; j < deltas->header.sense_node; j++) {
+ if ((i == 0) || (i == deltas->header.force_node) ||
+ (j == 0) || (j == deltas->header.sense_node))
+ deltas->node_data[i *
+ deltas->header.sense_node +
+ j] =
+ deltas->node_data[i *
+ deltas->header.
+ sense_node + j] *
+ 100 /
+ (*mean_edge);
+ else
+ deltas->node_data[i *
+ deltas->header.sense_node +
+ j] =
+ deltas->node_data[i *
+ deltas->header.
+ sense_node + j] *
+ 100 /
+ (*mean_normal);
+
+ if ((percentage > 0) && (deltas->node_data[i *
+ deltas->
+ header.
+ sense_node +
+ j] >
+ percentage)) {
+ pr_err("%s: Delta Node[%d, %d] = %d exceed limit [%d]\n",
+ __func__, i, j,
+ deltas->node_data[i *
+ deltas
+ ->header.sense_node +
+ j], percentage);
+ ret = ERROR_TEST_CHECK_FAIL;
+ }
+ }
+ }
+
+
+ /* print average frame in the log */
+ print_frame_short("FS Uniform (%) =",
+ array1dTo2d_short(
+ deltas->node_data,
+ deltas->node_data_size,
+ deltas->header.sense_node),
+ deltas->header.force_node,
+ deltas->header.sense_node);
+
+
+ if (ret < OK)
+ pr_err("%s: TP sensitivity MS Post Cal test FAILED... ERROR %08X\n",
+ __func__, ret);
+ else {
+ pr_info("%s: TP sensitivity MS Post Cal FINISHED!\n",
+ __func__);
+ ret = OK;
+ }
+
+ return ret;
+
+
+ERROR:
+ if (deltas->node_data != NULL) {
+ kfree(deltas->node_data);
+ deltas->node_data = NULL;
+ }
+
+
+ if (finalFrame->node_data != NULL) {
+ kfree(finalFrame->node_data);
+ finalFrame->node_data = NULL;
+ }
+
+ return ret;
+}
+
+
+/**
+ * Compute Digital gains for calibration
+ * @param enter if =1 turn on TP Sensitivity mode, otherwise will turn it off
+ * @param saveGain if 1, will save the gain table into the chip otherwise will
+ * not save it
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_mode(u8 enter, int saveGain)
+{
+ int res, ret = OK;
+ u8 cmd[4] = { 0xC0, 0x00, 0x00, 0x00 };
+ u8 sett = SPECIAL_WRITE_HOST_MEM_TO_FLASH;
+
+ pr_info("%s: Start TP Sensitivity Mode... enter = %02X\n",
+ __func__, enter);
+ if (enter == 1) {
+ /* enter TP Sensitivity mode*/
+ ret = fts_disableInterrupt();
+ pr_info("%s: Entering TP Sensitivity Mode disabling algos...\n",
+ __func__);
+ cmd[3] = 0x01;
+ res = fts_writeFwCmd(cmd, 4);
+ if (res < OK)
+ pr_err("%s: Error while turning on TP Sens Mode! ERROR %08X\n",
+ __func__, res);
+ } else {
+ /* exit TP Sensitivity mode*/
+ pr_info("%s: Exiting TP Sensitivity Mode enabling algos...\n",
+ __func__);
+ res = fts_writeFwCmd(cmd, 4);
+ if (res < OK)
+ pr_err("%s: Error while turning off TP Sens Mode! ERROR %08X\n",
+ __func__, res);
+
+ if (saveGain == 1) {
+ pr_info("%s: Trigger writing gains into the flash...\n",
+ __func__);
+ ret = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1);
+ if (ret < OK)
+ pr_err("%s: error while writing gains into the flash! ERROR %08X\n",
+ __func__, res);
+ }
+
+ res |= senseOn();
+ res |= fts_enableInterrupt();
+ }
+
+ res |= ret;
+
+ if (res < OK)
+ pr_err("%s: TP Sensitivity Mode... ERROR %08X!\n",
+ __func__, res);
+ else
+ pr_info("%s: TP Sensitivity Mode FINISHED!\n", __func__);
+
+ return res;
+}
+
+
+/**
+ * Compute Digital gains for calibration
+ * @param scan select the scan mode which should be enabled
+ * @param enableGains =1 apply gains when computing the strength otherwise
+ * the gains will be ignored
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_set_scan_mode(u8 scan, int enableGains)
+{
+ int res, ret = OK;
+ u8 cmd[4] = { 0xC0, 0x00, 0x01, 0x00 };
+
+
+ pr_info("%s: Set TP Sensitivity Scan Mode... scan = %02X, enableGains = %d\n",
+ __func__, scan, enableGains);
+
+
+ if (enableGains == 1) {
+ /* Consider Sensitivity Gains when computing Strength */
+ cmd[3] = 0x01;
+ ret = fts_writeFwCmd(cmd, 4);
+ if (ret < OK)
+ pr_err("%s: Error while enabling Gains in TP Sens Mode! ERROR %08X\n",
+ __func__, ret);
+ } else {
+ /* Exclude Sensitivity Gains when computing Strength */
+ ret = fts_writeFwCmd(cmd, 4);
+ if (ret < OK)
+ pr_err("%s: Error while disabling Gain in TP Sens Mode! ERROR %08X\n",
+ __func__, ret);
+ }
+
+ res = setScanMode(SCAN_MODE_LOCKED, scan);
+ if (res < OK)
+ pr_err("Error while setting the scan frequency... ERROR %08X\n",
+ res);
+
+ res |= ret;
+
+ if (res < OK)
+ pr_err("%s: Set TP Sensitivity Scan Mode... ERROR %08X!\n",
+ __func__, res);
+ else
+ pr_info("%s: Set TP Sensitivity Scan FINISHED!\n", __func__);
+
+ return res;
+}
+
+
+
+
+/**
+ * Compute the standard deviation for each node form a series of frames
+ * @param numFrames number of frames to collect to compute the standard
+ * deviation
+ * @param[out] std pointer to the frame which will contain the standard
+ * deviation for each node
+ * @return OK if success or an error code which specify the type of error
+ */
+int tp_sensitivity_test_std_ms(int numFrames, MutualSenseFrame *std)
+{
+ int ret = OK;
+ int i = 0, count = 0;
+ MutualSenseFrame frame;
+ int *mean = NULL;/* store the mean value for each node */
+ unsigned long *stdTemp = NULL;
+
+
+ if (std == NULL) {
+ pr_err("%s: Invalid arguments Passed! ERROR %08X\n",
+ __func__, ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+
+ std->node_data = NULL;
+
+ pr_info("%s: Start TP sensitivity STD... collecting %d frames!\n",
+ __func__, numFrames);
+
+ /* collect frames skipping the tests + print on the log */
+ ret = getMSFrame3(MS_STRENGTH, &frame);
+ if (ret < OK) {
+ pr_err("%s: can not read MS Frame... ERROR %08X\n",
+ __func__, ret);
+ goto ERROR;
+ }
+
+ std->header = frame.header;
+ std->node_data_size = frame.node_data_size;
+
+ std->node_data = (short *)kzalloc(std->node_data_size * sizeof(short),
+ GFP_KERNEL);
+ mean = (int *)kzalloc(std->node_data_size * sizeof(int), GFP_KERNEL);
+ stdTemp = (unsigned long *)kzalloc(std->node_data_size *
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (std->node_data == NULL ||
+ mean == NULL ||
+ stdTemp == NULL) {
+ pr_err("%s: can not allocate memory ERROR %08X\n",
+ __func__, ERROR_ALLOC | ERROR_GET_FRAME);
+ ret = ERROR_ALLOC | ERROR_GET_FRAME;
+ goto ERROR;
+ }
+
+ /* collecting frames */
+ do {
+ for (i = 0; i < frame.node_data_size; i++) {
+ mean[i] += frame.node_data[i];
+ stdTemp[i] += frame.node_data[i] * frame.node_data[i];
+ }
+ count++;
+
+ if (frame.node_data != NULL) {
+ kfree(frame.node_data);
+ frame.node_data = NULL;
+ }
+
+ /* exclude one more reading at the end*/
+ if (count < numFrames)
+ ret = getMSFrame3(MS_STRENGTH, &frame);
+ } while ((count < numFrames) && (ret >= OK));
+
+ if (ret < OK) {
+ pr_err("%s: error while collecting the frames! ERROR%08X\n",
+ __func__, ret);
+ goto ERROR;
+ }
+
+ /* compute the average for each node */
+ pr_info("%s: Computing std for each node...\n", __func__);
+
+ for (i = 0; i < std->node_data_size; i++) {
+ mean[i] /= numFrames;
+ stdTemp[i] = stdTemp[i] / numFrames - (mean[i] * mean[i]);
+ std->node_data[i] = (short)int_sqrt(stdTemp[i]);
+ }
+
+ kfree(stdTemp);
+ stdTemp = NULL;
+ kfree(mean);
+ mean = NULL;
+
+ /* print average frame in the log */
+ print_frame_short("STD =",
+ array1dTo2d_short(
+ std->node_data,
+ std->node_data_size,
+ std->header.sense_node),
+ std->header.force_node,
+ std->header.sense_node);
+
+ if (ret < OK)
+ pr_err("%s: TP sensitivity STD test FAILED... ERROR %08X\n",
+ __func__, ret);
+ else {
+ pr_info("%s: TP sensitivity STD FINISHED!\n",
+ __func__);
+ ret = OK;
+ }
+
+ return ret;
+
+ERROR:
+
+ kfree(frame.node_data);
+ frame.node_data = NULL;
+
+ kfree(std->node_data);
+ std->node_data = NULL;
+
+ kfree(stdTemp);
+ stdTemp = NULL;
+
+ kfree(mean);
+ mean = NULL;
+
+ return ret;
+}
+
+
+/**
+ * Retrieve the actual Test Limit data from the system (bin file or header
+ * file)
+ * @param path name of Production Test Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param file pointer to the LimitFile struct which will contains the limits
+ * data
+ * @return OK if success or an error code which specify the type of error
+ */
+int getLimitsFile(char *path, LimitFile *file)
+{
+ const struct firmware *fw = NULL;
+ struct device *dev = NULL;
+ int fd = -1;
+
+ pr_info("Get Limits File starting... %s\n", path);
+
+ if (file->data != NULL) {
+ /* to avoid memory leak on consecutive call of
+ * the function with the same pointer */
+ pr_err("Pointer to Limits Data already contains something... freeing its content!\n");
+ kfree(file->data);
+ file->data = NULL;
+ file->size = 0;
+ }
+
+ strlcpy(file->name, path, MAX_LIMIT_FILE_NAME);
+ if (strncmp(path, "NULL", 4) == 0) {
+#ifdef LIMITS_H_FILE
+ pr_info("Loading Limits File from .h!\n");
+ file->size = LIMITS_SIZE_NAME;
+ file->data = (char *)kmalloc((file->size) * sizeof(char),
+ GFP_KERNEL);
+ if (file->data != NULL) {
+ memcpy(file->data, (char *)(LIMITS_ARRAY_NAME),
+ file->size);
+ return OK;
+ } else {
+ pr_err("Error while allocating data... ERROR %08X\n",
+ path, ERROR_ALLOC);
+ return ERROR_ALLOC;
+ }
+#else
+ pr_err("limit file path NULL... ERROR %08X\n",
+ ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+#endif
+ } else {
+ dev = getDev();
+ if (dev != NULL) {
+ pr_info("Loading Limits File from .csv!\n");
+ fd = request_firmware(&fw, path, dev);
+ if (fd == 0) {
+ pr_info("Start to copy %s...\n", path);
+ file->size = fw->size;
+ file->data = (char *)kmalloc((file->size) *
+ sizeof(char),
+ GFP_KERNEL);
+ if (file->data != NULL) {
+ memcpy(file->data, (char *)fw->data,
+ file->size);
+ pr_info("Limit file Size = %d\n",
+ file->size);
+ release_firmware(fw);
+ return OK;
+ } else {
+ pr_err("Error while allocating data... ERROR %08X\n",
+ ERROR_ALLOC);
+ release_firmware(fw);
+ return ERROR_ALLOC;
+ }
+ } else {
+ pr_err("Request the file %s failed... ERROR %08X\n",
+ path, ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+ } else {
+ pr_err("Error while getting the device ERROR %08X\n",
+ ERROR_FILE_READ);
+ return ERROR_FILE_READ;
+ }
+ }
+}
+
+/**
+ * Reset and release the memory which store a Production Limit File previously
+ * loaded
+ * @param file pointer to the LimitFile struct to free
+ * @return OK if success or an error code which specify the type of error
+ */
+
+int freeLimitsFile(LimitFile *file)
+{
+ pr_info("Freeing Limit File ...\n");
+ if (file != NULL) {
+ if (file->data != NULL) {
+ kfree(file->data);
+ file->data = NULL;
+ } else
+ pr_err("Limit File was already freed!\n");
+ file->size = 0;
+ strlcpy(file->name, " ", MAX_LIMIT_FILE_NAME);
+ return OK;
+ } else {
+ pr_err("Passed a NULL argument! ERROR %08X\n",
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
+
+/**
+ * Reset and release the memory which store the current Limit File
+ * previously loaded
+ * @return OK if success or an error code which specify the type of error
+ */
+int freeCurrentLimitsFile(void)
+{
+ return freeLimitsFile(&limit_file);
+}
+
+/**
+ * Parse the raw data read from a Production test limit file in order
+ * to find the specified information
+ * If no limits file data are passed, the function loads and stores the limit
+ * file from the system
+ * @param path name of Production Test Limit file to load or
+ * "NULL" if the limits data should be loaded by a .h file
+ * @param file pointer to LimitFile struct that should be parsed or
+ * NULL if the limit file in the system should be loaded and then parsed
+ * @param label string which identify a particular set of data in the file that
+ * want to be loaded
+ * @param data pointer to the pointer which will contains the specified limits
+ * data
+ * as 1 dimension matrix with data arranged row after row
+ * @param row pointer to a int variable which will contain the number of row of
+ * data
+ * @param column pointer to a int variable which will contain the number of
+ * column of data
+ * @return OK if success or an error code which specify the type of error
+ */
+int parseProductionTestLimits(char *path, LimitFile *file, char *label,
+ int **data, int *row, int *column)
+{
+ int find = 0;
+ char *token = NULL;
+ int i = 0;
+ int j = 0;
+ int z = 0;
+
+ char *line2 = NULL;
+ char line[800];
+ char *buf = NULL;
+ int n, size, pointer = 0, ret = OK;
+ char *data_file = NULL;
+
+ if (file == NULL || strcmp(path, file->name) != 0 || file->size == 0) {
+ pr_info("No limit File data passed... try to get them from the system!\n");
+ ret = getLimitsFile(LIMITS_FILE, &limit_file);
+ if (ret < OK) {
+ pr_err("parseProductionTestLimits: ERROR %08X\n",
+ ERROR_FILE_NOT_FOUND);
+ return ERROR_FILE_NOT_FOUND;
+ }
+ size = limit_file.size;
+ data_file = limit_file.data;
+ } else {
+ pr_info("Limit File data passed as arguments!\n");
+ size = file->size;
+ data_file = file->data;
+ }
+
+
+
+ pr_info("The size of the limits file is %d bytes...\n", size);
+
+
+
+ while (find == 0) {
+ /* start to look for the wanted label */
+ if (readLine(&data_file[pointer], line, size - pointer, &n) <
+ 0) {
+ find = -1;
+ break;
+ }
+ pointer += n;
+ if (line[0] == '*') {
+ /* each header row start with * ex. *label,n_row,n_colum */
+ line2 = kstrdup(line, GFP_KERNEL);
+ if (line2 == NULL) {
+ pr_err("parseProductionTestLimits: kstrdup ERROR %08X\n",
+ ERROR_ALLOC);
+ ret = ERROR_ALLOC;
+ goto END;
+ }
+ buf = line2;
+ line2 += 1;
+ token = strsep(&line2, ",");
+ if (strcmp(token, label) == 0) {
+ /* if the row is the wanted one, r
+ * retrieve rows and columns info */
+ find = 1;
+ token = strsep(&line2, ",");
+ if (token != NULL) {
+ sscanf(token, "%d", row);
+ pr_info("Row = %d\n", *row);
+ } else {
+ pr_err("parseProductionTestLimits 1: ERROR %08X\n",
+ ERROR_FILE_PARSE);
+ ret = ERROR_FILE_PARSE;
+ goto END;
+ }
+ token = strsep(&line2, ",");
+ if (token != NULL) {
+ sscanf(token, "%d", column);
+ pr_info("Column = %d\n", *column);
+ } else {
+ pr_err("parseProductionTestLimits 2: ERROR %08X\n",
+ ERROR_FILE_PARSE);
+ ret = ERROR_FILE_PARSE;
+ goto END;
+ }
+
+ kfree(buf);
+ buf = NULL;
+ *data = (int *)kmalloc(((*row) * (*column)) *
+ sizeof(int), GFP_KERNEL);
+ /* allocate the memory for containing the data */
+ j = 0;
+ if (*data == NULL) {
+ pr_err("parseProductionTestLimits: ERROR %08X\n",
+ ERROR_ALLOC);
+ ret = ERROR_ALLOC;
+ goto END;
+ }
+
+
+ /* start to read the data */
+ for (i = 0; i < *row; i++) {
+ if (readLine(&data_file[pointer], line,
+ size - pointer, &n) < 0) {
+ pr_err("parseProductionTestLimits : ERROR %08X\n",
+ ERROR_FILE_READ);
+ ret = ERROR_FILE_READ;
+ goto END;
+ }
+ pointer += n;
+ line2 = kstrdup(line, GFP_KERNEL);
+ if (line2 == NULL) {
+ pr_err("parseProductionTestLimits: kstrdup ERROR %08X\n",
+ ERROR_ALLOC);
+ ret = ERROR_ALLOC;
+ goto END;
+ }
+ buf = line2;
+ token = strsep(&line2, ",");
+ for (z = 0; (z < *column) && (token !=
+ NULL);
+ z++) {
+ sscanf(token, "%d", ((*data) +
+ j));
+ j++;
+ token = strsep(&line2, ",");
+ }
+ kfree(buf);
+ buf = NULL;
+ }
+ if (j == ((*row) * (*column))) {
+ /* check that all the data are read */
+ pr_info("READ DONE!\n");
+ ret = OK;
+ goto END;
+ }
+ pr_err("parseProductionTestLimits 3: ERROR %08X\n",
+ ERROR_FILE_PARSE);
+ ret = ERROR_FILE_PARSE;
+ goto END;
+ }
+ kfree(buf);
+ buf = NULL;
+ }
+ }
+ pr_err("parseProductionTestLimits: ERROR %08X\n",
+ ERROR_LABEL_NOT_FOUND);
+ ret = ERROR_LABEL_NOT_FOUND;
+END:
+ if (buf != NULL)
+ kfree(buf);
+ return ret;
+}
+
+
+/**
+ * Read one line of a text file passed as array of byte and terminate it with
+ * a termination character '\0'
+ * @param data text file as array of bytes
+ * @param line pointer to an array of char that will contain the line read
+ * @param size size of data
+ * @param n pointer to a int variable which will contain the number of
+ * characters of the line
+ * @return OK if success or an error code which specify the type of error
+ */
+int readLine(char *data, char *line, int size, int *n)
+{
+ int i = 0;
+
+ if (size < 1)
+ return ERROR_OP_NOT_ALLOW;
+
+ while (data[i] != '\n' && i < size) {
+ line[i] = data[i];
+ i++;
+ }
+ *n = i + 1;
+ line[i] = '\0';
+
+ return OK;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTest.h b/drivers/input/touchscreen/stm/fts_lib/ftsTest.h
new file mode 100644
index 00000000000..7554709cdd1
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsTest.h
@@ -0,0 +1,343 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS API for MP test **
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsTest.h
+ * \brief Contains all the definitions and structs related to the Mass
+ *Production Test
+ */
+
+#ifndef FTS_TEST_H
+#define FTS_TEST_H
+
+#include "ftsSoftware.h"
+#include "ftsFrame.h"
+
+#ifndef LIMITS_H_FILE
+/* /< Name of the Production Test Limit File */
+#define LIMITS_FILE "stm_fts_production_limits.csv"
+#else
+#define LIMITS_FILE "NULL"
+#endif
+
+#define WAIT_FOR_FRESH_FRAMES 200 /* /< Time in ms to wait after
+ * start to sensing before
+ * reading a frame */
+#define WAIT_AFTER_SENSEOFF 50 /* /< Time in ms to wait after
+ * stop sensing and before
+ * reading a frame from
+ * memory */
+
+#define NO_INIT 0 /* /< No Initialization required
+ * during the MP */
+
+#define RETRY_INIT_BOOT 3 /* /< number of retry of the
+ * init process at boot */
+
+#define SENS_TEST_NUM_FRAMES 100 /* /< number of frames to read */
+#define SENS_TEST_PERC_TARGET_PRECAL 20 /* /< +-% of target value within
+ * all the node of the frames
+ * should be contained */
+#define SENS_TEST_PERC_TARGET_POSTCAL 4 /* /< +-% of target value within
+ * should be contained the
+ * avarege of the nodes and the
+ * deltas for each node */
+
+/** @defgroup mp_test Mass Production Test
+ * Mass production test API.
+ * Mass Production Test (MP) should be executed at least one time in the life
+ * of every device \n
+ * It used to verify that tit is not present any hardware damage and
+ * initialize some value of the chip in order to guarantee the working
+ * performance \n
+ * The MP test is made up by 3 steps:
+ * - ITO test = production_test_ito() \n
+ * - Initialization = production_test_initialization() \n
+ * - Data Test = production_test_data(),
+ * it is possible to select which items test thanks to the TestToDo struct\n
+ * To execute the Data Test it is mandatory load some thresholds that
+ * are stored in the Limit File.
+ * @{
+ */
+
+/** @defgroup limit_file Limit File
+ * @ingroup mp_test
+ * Production Test Limit File is a csv which contains thresholds of the data to
+ * test.
+ * This file can be loaded from the file system or stored as a header file
+ * according to the LIMITS_H_FILE define \n
+ * For each selectable test item there can be one or more associated labels
+ * which store the corresponding thresholds \n
+ * @{
+ */
+/* LABELS PRODUCTION TEST LIMITS FILE */
+/** @defgroup test_labels Test Items Labels
+ * @ingroup limit_file
+ * Labels present in the Limit File and associated to the test items of
+ * TestToDo
+ * @{
+ */
+#define MS_RAW_MIN_MAX "MS_RAW_DATA_MIN_MAX"
+#define MS_RAW_GAP "MS_RAW_DATA_GAP"
+#define MS_RAW_ADJH "MS_RAW_DATA_ADJ_HORIZONTAL"
+#define MS_RAW_ADJV "MS_RAW_DATA_ADJ_VERTICAL"
+#define MS_RAW_ITO_ADJH "MS_RAW_ITO_DATA_ADJ_HORIZONTAL"
+#define MS_RAW_ITO_ADJV "MS_RAW_ITO_DATA_ADJ_VERTICAL"
+#define MS_RAW_LP_MIN_MAX "MS_RAW_LOWPOWER_DATA_MIN_MAX"
+#define MS_RAW_LP_GAP "MS_RAW_LOWPOWER_DATA_GAP"
+#define MS_RAW_LP_ADJH "MS_RAW_LOWPOWER_DATA_ADJ_HORIZONTAL"
+#define MS_RAW_LP_ADJV "MS_RAW_LOWPOWER_DATA_ADJ_VERTICAL"
+#define MS_CX1_MIN_MAX "MS_TOUCH_ACTIVE_CX1_MIN_MAX"
+#define MS_CX2_MAP_MIN "MS_TOUCH_ACTIVE_CX2_MIN"
+#define MS_CX2_MAP_MAX "MS_TOUCH_ACTIVE_CX2_MAX"
+#define MS_CX2_ADJH_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL"
+#define MS_CX2_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL"
+#define MS_TOTAL_CX_MAP_MIN "MS_TOUCH_ACTIVE_TOTAL_CX_MIN"
+#define MS_TOTAL_CX_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_MAX"
+#define MS_TOTAL_CX_ADJH_MAP_MAX \
+ "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL"
+#define MS_TOTAL_CX_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL"
+#define SS_RAW_FORCE_MIN_MAX "SS_RAW_DATA_FORCE_MIN_MAX"
+#define SS_RAW_SENSE_MIN_MAX "SS_RAW_DATA_SENSE_MIN_MAX"
+#define SS_RAW_FORCE_GAP "SS_RAW_DATA_FORCE_GAP"
+#define SS_RAW_SENSE_GAP "SS_RAW_DATA_SENSE_GAP"
+#define SS_RAW_LP_FORCE_MIN_MAX "SS_RAW_LOWPOWER_DATA_FORCE_MIN_MAX"
+#define SS_RAW_LP_SENSE_MIN_MAX "SS_RAW_LOWPOWER_DATA_SENSE_MIN_MAX"
+#define SS_RAW_LP_FORCE_GAP "SS_RAW_LOWPOWER_DATA_FORCE_GAP"
+#define SS_RAW_LP_SENSE_GAP "SS_RAW_LOWPOWER_DATA_SENSE_GAP"
+#define SS_IX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_FORCE_MIN_MAX"
+#define SS_IX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_SENSE_MIN_MAX"
+#define SS_CX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_FORCE_MIN_MAX"
+#define SS_CX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_SENSE_MIN_MAX"
+#define SS_IX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_FORCE_MIN"
+#define SS_IX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_FORCE_MAX"
+#define SS_IX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_SENSE_MIN"
+#define SS_IX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_SENSE_MAX"
+#define SS_IX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_VERTICAL"
+#define SS_IX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_HORIZONTAL"
+#define SS_CX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_FORCE_MIN"
+#define SS_CX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_FORCE_MAX"
+#define SS_CX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_SENSE_MIN"
+#define SS_CX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_SENSE_MAX"
+#define SS_CX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL"
+#define SS_CX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL"
+
+/* TOTAL SS */
+#define SS_TOTAL_IX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MIN"
+#define SS_TOTAL_IX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MAX"
+#define SS_TOTAL_IX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MIN"
+#define SS_TOTAL_IX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MAX"
+#define SS_TOTAL_IX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_VERTICAL"
+#define SS_TOTAL_IX_SENSE_ADJH_MAP_MAX \
+ "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_HORIZONTAL"
+#define SS_TOTAL_CX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MIN"
+#define SS_TOTAL_CX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MAX"
+#define SS_TOTAL_CX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MIN"
+#define SS_TOTAL_CX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MAX"
+#define SS_TOTAL_CX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL"
+#define SS_TOTAL_CX_SENSE_ADJH_MAP_MAX \
+ "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL"
+
+/* KEYS */
+#define MS_KEY_RAW_MIN_MAX "MS_KEY_RAW_DATA_MIN_MAX"
+#define MS_KEY_CX1_MIN_MAX "MS_KEY_CX1_MIN_MAX"
+#define MS_KEY_CX2_MAP_MIN "MS_KEY_CX2_MIN"
+#define MS_KEY_CX2_MAP_MAX "MS_KEY_CX2_MAX"
+#define MS_KEY_TOTAL_CX_MAP_MIN "MS_KEY_TOTAL_CX_MIN"
+#define MS_KEY_TOTAL_CX_MAP_MAX "MS_KEY_TOTAL_CX_MAX"
+
+/* CONSTANT TOTAL IX */
+#define SS_IX1_FORCE_W "IX1_FORCE_W"
+#define SS_IX2_FORCE_W "IX2_FORCE_W"
+#define SS_IX1_SENSE_W "IX1_SENSE_W"
+#define SS_IX2_SENSE_W "IX2_SENSE_W"
+/** @}*/
+
+
+/**
+ * Struct used to specify which test perform during the Mass Production Test.
+ * For each test item selected in this structure, there should be one or
+ * more labels associated in the Limit file from where load the thresholds
+ */
+typedef struct {
+ int MutualRaw; /* /< MS Raw min/Max test */
+ int MutualRawGap; /* /< MS Raw Gap(max-min) test */
+ int MutualRawAdj; /* /< MS Raw Adjacent test */
+ int MutualRawLP; /* /< MS Low Power Raw min/Max test */
+ int MutualRawGapLP; /* /< MS Low Power Raw Gap(max-min) test */
+ int MutualRawAdjLP; /* /< MS Low Power Raw Adjacent test */
+ int MutualRawAdjITO; /* /< MS Raw Adjacent test during ITO test */
+
+ int MutualCx1; /* /< MS Cx1 min/Max test */
+ int MutualCx2; /* /< MS Cx2 min/Max (for each node) test */
+ int MutualCx2Adj; /* /< MS Vertical and Horizontal Adj Cx2 min/Max
+ * (for each node) test */
+ int MutualCxTotal; /* /< MS Total Cx min/Max (for each node) test
+ * */
+ int MutualCxTotalAdj; /* /< MS Total vertical and Horizontal Adj Cx2
+ * min/Max
+ * (for each node) test */
+
+ int MutualKeyRaw; /* /< MS Raw Key min/Max test */
+ int MutualKeyCx1; /* /< MS Cx1 Key min/Max test */
+ int MutualKeyCx2; /* /< MS Cx2 Key min/Max (for each node) test */
+ int MutualKeyCxTotal; /* /< MS Total Cx Key min/Max (for each node)
+ * test */
+
+ int SelfForceRaw; /* /< SS Force Raw min/Max test */
+ int SelfForceRawGap; /* /< SS Force Raw Gap(max-min) test */
+ int SelfForceRawLP; /* /< SS Low Power Force Raw min/Max test */
+ int SelfForceRawGapLP; /* /< SS Low Power Force Raw Gap(max-min) test */
+
+ int SelfForceIx1; /* /< SS Force Ix1 min/Max test */
+ int SelfForceIx2; /* /< SS Force Ix2 min/Max (for each node) test
+ * */
+ int SelfForceIx2Adj; /* /< SS Vertical Adj Force Ix2 min/Max
+ * (for each node) test */
+ int SelfForceIxTotal; /* /< SS Total Force Ix min/Max (for each node)
+ * test */
+ int SelfForceIxTotalAdj; /* /< SS Total Vertical Adj Force Ix
+ * min/Max
+ * (for each node) test */
+ int SelfForceCx1; /* /< SS Force Cx1 min/Max test */
+ int SelfForceCx2; /* /< SS Force Cx2 min/Max (for each node) test */
+ int SelfForceCx2Adj; /* /< SS Vertical Adj Force Cx2 min/Max (for
+ * each node) test */
+ int SelfForceCxTotal; /* /< SS Total Force Cx min/Max (for each node)
+ * test */
+ int SelfForceCxTotalAdj; /* /< SS Total Vertical Adj Force Cx
+ * min/Max
+ * (for each node) test */
+
+ int SelfSenseRaw; /* /< SS Sense Raw min/Max test */
+ int SelfSenseRawGap; /* /< SS Sense Raw Gap(max-min) test */
+ int SelfSenseRawLP; /* /< SS Low Power Sense Raw min/Max test */
+ int SelfSenseRawGapLP; /* /< SS Low Power Sense Raw Gap(max-min) test */
+
+ int SelfSenseIx1; /* /< SS Sense Ix1 min/Max test */
+ int SelfSenseIx2; /* /< SS Sense Ix2 min/Max (for each node) test */
+ int SelfSenseIx2Adj; /* /< SS Horizontal Adj Sense Ix2 min/Max
+ * (for each node) test */
+ int SelfSenseIxTotal; /* /< SS Total Horizontal Sense Ix min/Max
+ * (for each node) test */
+ int SelfSenseIxTotalAdj; /* /< SS Total Horizontal Adj Sense Ix
+ * min/Max
+ * (for each node) test */
+ int SelfSenseCx1; /* /< SS Sense Cx1 min/Max test */
+ int SelfSenseCx2; /* /< SS Sense Cx2 min/Max (for each node) test */
+ int SelfSenseCx2Adj; /* /< SS Horizontal Adj Sense Cx2 min/Max
+ * (for each node) test */
+ int SelfSenseCxTotal; /* /< SS Total Sense Cx min/Max (for each node)
+ * test */
+ int SelfSenseCxTotalAdj; /* /< SS Total Horizontal Adj Sense Cx
+ * min/Max
+ * (for each node) test */
+} TestToDo;
+
+
+#define MAX_LIMIT_FILE_NAME 100 /* /< max number of chars of the limit file name
+ * */
+
+/**
+ * Struct which store the data coming from a Production Limit File
+ */
+typedef struct {
+ char *data; /* /< pointer to an array of char which contains
+ * the content of the Production Limit File */
+ int size; /* /< size of data */
+ char name[MAX_LIMIT_FILE_NAME]; /* /< identifier of the source from
+ * where the limits data were loaded
+ * (if loaded from a file it will be
+ * the file name, while if loaded
+ * from .h will be "NULL") */
+} LimitFile;
+
+
+
+int initTestToDo(void);
+/**@}*/
+
+/**@}*/
+
+
+int computeAdjHoriz(i8 *data, int row, int column, u8 **result);
+int computeAdjHorizTotal(short *data, int row, int column, u16 **result);
+int computeAdjVert(i8 *data, int row, int column, u8 **result);
+int computeAdjVertTotal(short *data, int row, int column, u16 **result);
+int computeAdjHorizFromU(u8 *data, int row, int column, u8 **result);
+int computeAdjHorizTotalFromU(u16 *data, int row, int column, u16 **result);
+int computeAdjVertFromU(u8 *data, int row, int column, u8 **result);
+int computeAdjVertTotalFromU(u16 *data, int row, int column, u16 **result);
+int checkLimitsMinMax(short *data, int row, int column, int min, int max);
+int checkLimitsMap(i8 *data, int row, int column, int *min, int *max);
+int checkLimitsMapTotal(short *data, int row, int column, int *min, int *max);
+int checkLimitsMapFromU(u8 *data, int row, int column, int *min, int *max);
+int checkLimitsMapTotalFromU(u16 *data, int row, int column, int *min,
+ int *max);
+int checkLimitsMapAdj(u8 *data, int row, int column, int *max);
+int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max);
+
+/** @defgroup mp_api MP API
+ * @ingroup mp_test
+ * Functions to execute the MP test.
+ * The parameters of these functions allow to customize their behavior
+ * in order to satisfy different scenarios
+ * @{
+ */
+int production_test_ito(char *path_limits, TestToDo *todo);
+int production_test_initialization(u8 type);
+int production_test_main(char *pathThresholds, int stop_on_fail, int saveInit,
+ TestToDo *todo);
+int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ms_raw_lp(char *path_limits, int stop_on_fail,
+ TestToDo *todo);
+int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ss_raw_lp(char *path_limits, int stop_on_fail,
+ TestToDo *todo);
+int production_test_ss_ix_cx(char *path_limits, int stop_on_fail,
+ TestToDo *todo);
+int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo);
+int production_test_ms_key_cx(char *path_limits, int stop_on_fail,
+ TestToDo *todo);
+int production_test_ms_key_raw(char *path_limits);
+/** @}*/
+
+/**
+ * @addtogroup limit_file
+ * @{
+ */
+int parseProductionTestLimits(char *path, LimitFile *file, char *label,
+ int **data, int *row, int *column);
+int readLine(char *data, char *line, int size, int *n);
+int getLimitsFile(char *path, LimitFile *file);
+int freeLimitsFile(LimitFile *file);
+int freeCurrentLimitsFile(void);
+/**@}*/
+
+int tp_sensitivity_test_pre_cal_ms(MutualSenseFrame *finalFrame, short target,
+ int percentage);
+int tp_sensitivity_test_pre_cal_ss(SelfSenseFrame *finalFrame, short target,
+ int percentage);
+int tp_sensitivity_compute_gains(MutualSenseFrame *frame, short target,
+ int saveGain);
+int tp_sensitivity_test_post_cal_ms(MutualSenseFrame *finalFrame,
+ MutualSenseFrame *deltas, short target,
+ int percentage, int *mean_normal,
+ int *mean_edge);
+int tp_sensitivity_set_scan_mode(u8 scan, int enableGains);
+int tp_sensitivity_mode(u8 enter, int saveGain);
+int tp_sensitivity_test_std_ms(int numFrames, MutualSenseFrame *std);
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTime.c b/drivers/input/touchscreen/stm/fts_lib/ftsTime.c
new file mode 100644
index 00000000000..8c6e9f76795
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsTime.c
@@ -0,0 +1,84 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Utility for mesuring/handling the time *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsTime.c
+ * \brief Contains all functions to handle and measure the time in the driver
+ */
+
+#include "ftsTime.h"
+
+
+#include <linux/errno.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+
+/**
+ * Take the starting time and save it in a StopWatch variable
+ * @param w pointer of a StopWatch struct
+ */
+void startStopWatch(StopWatch *w)
+{
+ ktime_get_coarse_real_ts64(&w->start);
+}
+
+/**
+ * Take the stop time and save it in a StopWatch variable
+ * @param w pointer of a StopWatch struct
+ */
+void stopStopWatch(StopWatch *w)
+{
+ ktime_get_coarse_real_ts64(&w->end);
+}
+
+/**
+ * Compute the amount of time spent from when the startStopWatch and then
+ * the stopStopWatch were called on the StopWatch variable
+ * @param w pointer of a StopWatch struct
+ * @return amount of time in ms (the return value is meaningless
+ * if the startStopWatch and stopStopWatch were not called before)
+ */
+int elapsedMillisecond(StopWatch *w)
+{
+ int result;
+
+ result = ((w->end.tv_sec - w->start.tv_sec) * 1000) +
+ (w->end.tv_nsec - w->start.tv_nsec) / 1000000;
+ return result;
+}
+
+/**
+ * Compute the amount of time spent from when the startStopWatch and
+ * then the stopStopWatch were called on the StopWatch variable
+ * @param w pointer of a StopWatch struct
+ * @return amount of time in ns (the return value is meaningless
+ * if the startStopWatch and stopStopWatch were not called before)
+ */
+int elapsedNanosecond(StopWatch *w)
+{
+ int result;
+
+ result = ((w->end.tv_sec - w->start.tv_sec) * 1000000000) +
+ (w->end.tv_nsec - w->start.tv_nsec);
+ return result;
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTime.h b/drivers/input/touchscreen/stm/fts_lib/ftsTime.h
new file mode 100644
index 00000000000..b38b188d957
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsTime.h
@@ -0,0 +1,70 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Utility for measuring/handling the time *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsTime.h
+ * \brief Contains all the definitions and structs to handle and measure the
+ * time in the driver
+ */
+
+#ifndef FTS_TIME_H
+#define FTS_TIME_H
+
+
+#include <linux/time.h>
+
+/* TIMEOUT */
+/** @defgroup timeouts Timeouts
+ * Definitions of all the Timeout used in several operations
+ * @{
+ */
+#define TIMEOUT_RESOLUTION 2
+/* /< timeout resolution in ms (all timeout should be multiples of this unit) */
+#define GENERAL_TIMEOUT (50 * TIMEOUT_RESOLUTION)
+/* /< general timeout in ms */
+#define RELEASE_INFO_TIMEOUT (15 * TIMEOUT_RESOLUTION)
+/* /< timeout to request release info in ms */
+
+
+#define TIMEOUT_REQU_COMP_DATA (100 * TIMEOUT_RESOLUTION)
+/* /< timeout to request compensation data in ms */
+#define TIMEOUT_REQU_DATA (200 * TIMEOUT_RESOLUTION)
+/* /< timeout to request data in ms */
+#define TIMEOUT_ITO_TEST_RESULT (100 * TIMEOUT_RESOLUTION)
+/* /< timeout to perform ito test in ms */
+#define TIMEOUT_INITIALIZATION_TEST_RESULT (5000 * TIMEOUT_RESOLUTION)
+/* /< timeout to perform initialization test in ms */
+#define TIEMOUT_ECHO \
+ TIMEOUT_INITIALIZATION_TEST_RESULT
+/* /< timeout of the echo command, should be the max of
+ * all the possible commands (used in worst case) */
+/** @}*/
+
+
+/**
+ * Struct used to measure the time elapsed between a starting and ending point.
+ */
+typedef struct {
+ struct timespec64 start; /* /< store the starting time */
+ struct timespec64 end; /* /< store the finishing time */
+} StopWatch;
+
+
+void startStopWatch(StopWatch *w);
+void stopStopWatch(StopWatch *w);
+int elapsedMillisecond(StopWatch *w);
+int elapsedNanosecond(StopWatch *w);
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTool.c b/drivers/input/touchscreen/stm/fts_lib/ftsTool.c
new file mode 100644
index 00000000000..e359b1a0dcc
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsTool.c
@@ -0,0 +1,730 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Utility Functions *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsTool.c
+ * \brief Contains all the functions to support common operation inside the
+ * driver
+ */
+
+#include "ftsCompensation.h"
+#include "ftsCore.h"
+#include "ftsError.h"
+#include "ftsHardware.h"
+#include "ftsIO.h"
+#include "ftsSoftware.h"
+#include "ftsTime.h"
+#include "ftsTool.h"
+#include "../fts.h" /* needed for the tag define */
+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stdarg.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+
+/**
+ * Print an array of byte in a HEX string and attach at the beginning a label.
+ * The function allocate memory that should be free outside the function itself
+ * @param label string to attach at the beginning
+ * @param buff pointer to the byte array that should be printed as HEX string
+ * @param count size of buff
+ * @param result pointer to the array of characters that compose the HEX final
+ * string
+ * @param size size of result
+ * @return pointer to the array of characters that compose the HEX string,
+ * (same address of result)
+ * @warning result MUST be allocated outside the function and should be
+ * big enough to contain the data converted as HEX!
+ */
+char *printHex(char *label, u8 *buff, int count, u8 *result, int size)
+{
+ int i, offset = 0;
+
+ offset = scnprintf(result + offset, size - offset, "%s", label);
+ for (i = 0; i < count; i++) {
+ offset +=
+ scnprintf(result + offset,
+ size - offset, "%02X ", buff[i]);
+ /* this append automatically a null terminator char */
+ }
+ return result;
+}
+
+/**
+ * Clear the FIFO from any event
+ * @return OK if success or an error code which specify the type of error
+ */
+int flushFIFO(void)
+{
+ int ret;
+ u8 sett = SPECIAL_FIFO_FLUSH;
+
+ ret = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1); /* flush the FIFO */
+ if (ret < OK) {
+ pr_err("flushFIFO: ERROR %08X\n", ret);
+ return ret;
+ }
+
+ pr_info("FIFO flushed!\n");
+ return OK;
+}
+
+
+
+/**
+ * Convert an array of bytes to an array of u16 taking two bytes at time,
+ * src has LSB first.
+ * @param src pointer to the source byte array
+ * @param src_length size of src
+ * @param dst pointer to the destination array.
+ * @return the final size of dst (half of the source) or ERROR_OP_NOT_ALLOW
+ * if the size of src is not multiple of 2.
+ */
+int u8ToU16n(u8 *src, int src_length, u16 *dst)
+{
+ int i, j;
+
+ if (src_length % 2 != 0)
+ return ERROR_OP_NOT_ALLOW;
+ else {
+ j = 0;
+ dst = (u16 *)kmalloc((src_length / 2) * sizeof(u16),
+ GFP_KERNEL);
+ for (i = 0; i < src_length; i += 2) {
+ dst[j] = ((src[i + 1] & 0x00FF) << 8) +
+ (src[i] & 0x00FF);
+ j++;
+ }
+ }
+
+ return src_length / 2;
+}
+
+/**
+ * Convert an array of 2 bytes to a u16, src has LSB first (little endian).
+ * @param src pointer to the source byte array
+ * @param dst pointer to the destination u16.
+ * @return OK
+ */
+int u8ToU16(u8 *src, u16 *dst)
+{
+ *dst = (u16)(((src[1] & 0x00FF) << 8) + (src[0] & 0x00FF));
+ return OK;
+}
+
+/**
+ * Convert an array of 2 bytes to a u16, src has MSB first (big endian).
+ * @param src pointer to the source byte array
+ * @param dst pointer to the destination u16.
+ * @return OK
+ */
+int u8ToU16_be(u8 *src, u16 *dst)
+{
+ *dst = (u16)(((src[0] & 0x00FF) << 8) + (src[1] & 0x00FF));
+ return OK;
+}
+
+/**
+ * Convert an array of u16 to an array of u8, dst has MSB first (big endian).
+ * @param src pointer to the source array of u16
+ * @param src_length size of src
+ * @param dst pointer to the destination array of u8. This array should be free
+ * when no need anymore
+ * @return size of dst (src size multiply by 2)
+ */
+int u16ToU8n_be(u16 *src, int src_length, u8 *dst)
+{
+ int i, j;
+
+ dst = (u8 *)kmalloc((2 * src_length) * sizeof(u8), GFP_KERNEL);
+ j = 0;
+ for (i = 0; i < src_length; i++) {
+ dst[j] = (u8)(src[i] & 0xFF00) >> 8;
+ dst[j + 1] = (u8)(src[i] & 0x00FF);
+ j += 2;
+ }
+
+ return src_length * 2;
+}
+
+/**
+ * Convert a u16 to an array of 2 u8, dst has MSB first (big endian).
+ * @param src u16 to convert
+ * @param dst pointer to the destination array of 2 u8.
+ * @return OK
+ */
+int u16ToU8_be(u16 src, u8 *dst)
+{
+ dst[0] = (u8)((src & 0xFF00) >> 8);
+ dst[1] = (u8)(src & 0x00FF);
+ return OK;
+}
+
+
+/**
+ * Convert a u16 to an array of 2 u8, dst has LSB first (little endian).
+ * @param src u16 to convert
+ * @param dst pointer to the destination array of 2 u8.
+ * @return OK
+ */
+int u16ToU8(u16 src, u8 *dst)
+{
+ dst[1] = (u8)((src & 0xFF00) >> 8);
+ dst[0] = (u8)(src & 0x00FF);
+ return OK;
+}
+
+/**
+ * Convert an array of bytes to a u32, src has LSB first (little endian).
+ * @param src array of bytes to convert
+ * @param dst pointer to the destination u32 variable.
+ * @return OK
+ */
+int u8ToU32(u8 *src, u32 *dst)
+{
+ *dst = (u32)(((src[3] & 0xFF) << 24) + ((src[2] & 0xFF) << 16) +
+ ((src[1] & 0xFF) << 8) + (src[0] & 0xFF));
+ return OK;
+}
+
+/**
+ * Convert an array of bytes to a u32, src has MSB first (big endian).
+ * @param src array of bytes to convert
+ * @param dst pointer to the destination u32 variable.
+ * @return OK
+ */
+int u8ToU32_be(u8 *src, u32 *dst)
+{
+ *dst = (u32)(((src[0] & 0xFF) << 24) + ((src[1] & 0xFF) << 16) +
+ ((src[2] & 0xFF) << 8) + (src[3] & 0xFF));
+ return OK;
+}
+
+
+/**
+ * Convert a u32 to an array of 4 bytes, dst has LSB first (little endian).
+ * @param src u32 value to convert
+ * @param dst pointer to the destination array of 4 bytes.
+ * @return OK
+ */
+int u32ToU8(u32 src, u8 *dst)
+{
+ dst[3] = (u8)((src & 0xFF000000) >> 24);
+ dst[2] = (u8)((src & 0x00FF0000) >> 16);
+ dst[1] = (u8)((src & 0x0000FF00) >> 8);
+ dst[0] = (u8)(src & 0x000000FF);
+ return OK;
+}
+
+/**
+ * Convert a u32 to an array of 4 bytes, dst has MSB first (big endian).
+ * @param src u32 value to convert
+ * @param dst pointer to the destination array of 4 bytes.
+ * @return OK
+ */
+int u32ToU8_be(u32 src, u8 *dst)
+{
+ dst[0] = (u8)((src & 0xFF000000) >> 24);
+ dst[1] = (u8)((src & 0x00FF0000) >> 16);
+ dst[2] = (u8)((src & 0x0000FF00) >> 8);
+ dst[3] = (u8)(src & 0x000000FF);
+ return OK;
+}
+
+/**
+ * Execute a function passed as argment and retry it defined number of times if
+ * not successful
+ * @param code pointer to a function which return an int and doesn't have any
+ * parameters
+ * @param wait_before_retry interval of time in ms to wait between one trial
+ * and another one
+ * @param retry_count max number of retry to attemp
+ * @return last return value obtained from the last execution of the code
+ *function
+ */
+int attempt_function(int (*code)(void), unsigned long wait_before_retry, int
+ retry_count)
+{
+ int result;
+ int count = 0;
+
+ do {
+ result = code();
+ count++;
+ mdelay(wait_before_retry);
+ } while (count < retry_count && result < 0);
+
+
+ if (count == retry_count)
+ return result | ERROR_TIMEOUT;
+ else
+ return result;
+}
+
+/**
+ * Enable all the possible sensing mode supported by the FW
+ * @return OK if success or an error code which specify the type of error
+ */
+int senseOn(void)
+{
+ int ret;
+
+ ret = setScanMode(SCAN_MODE_ACTIVE, 0xFF); /* enable all */
+ if (ret < OK) {
+ pr_err("senseOn: ERROR %08X\n", ret);
+ return ret;
+ }
+
+ pr_info("senseOn: SENSE ON\n");
+ return OK;
+}
+
+/**
+ * Disable all the sensing mode
+ * @return OK if success or an error code which specify the type of error
+ */
+int senseOff(void)
+{
+ int ret;
+
+ ret = setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ if (ret < OK) {
+ pr_err("senseOff: ERROR %08X\n", ret);
+ return ret;
+ }
+
+ pr_info("senseOff: SENSE OFF\n");
+ return OK;
+}
+
+
+
+/**
+ * Clean up the IC status executing a system reset and giving
+ * the possibility to re-enabling the sensing
+ * @param enableTouch if 1, re-enable the sensing and the interrupt of the IC
+ * @return OK if success or an error code which specify the type of error
+ */
+int cleanUp(int enableTouch)
+{
+ int res;
+
+ pr_info("cleanUp: system reset...\n");
+ res = fts_system_reset();
+ if (res < OK)
+ return res;
+ if (enableTouch) {
+ pr_info("cleanUp: enabling touches...\n");
+ res = senseOn(); /* already enable everything */
+ if (res < OK)
+ return res;
+ pr_info("cleanUp: enabling interrupts...\n");
+ res = fts_enableInterrupt();
+ if (res < OK)
+ return res;
+ }
+ return OK;
+}
+
+/**
+ * Transform an array of short in a matrix of short with a defined number of
+ * columns and the resulting number of rows
+ * @param data array of bytes to convert
+ * @param size size of data
+ * @param columns number of columns that the resulting matrix should have.
+ * @return a reference to a matrix of short where for each row there are
+ * columns elements
+ */
+short **array1dTo2d_short(short *data, int size, int columns)
+{
+ int i;
+ short **matrix = (short **)kmalloc(((int)(size / columns)) *
+ sizeof(short *), GFP_KERNEL);
+
+ if (matrix != NULL) {
+ for (i = 0; i < (int)(size / columns); i++)
+ matrix[i] = (short *)kmalloc(columns * sizeof(short),
+ GFP_KERNEL);
+
+ for (i = 0; i < size; i++)
+ matrix[i / columns][i % columns] = data[i];
+ }
+
+ return matrix;
+}
+
+/**
+ * Transform an array of u16 in a matrix of u16 with a defined number of
+ * columns and the resulting number of rows
+ * @param data array of bytes to convert
+ * @param size size of data
+ * @param columns number of columns that the resulting matrix should have.
+ * @return a reference to a matrix of u16 where for each row there are columns
+ * elements
+ */
+u16 **array1dTo2d_u16(u16 *data, int size, int columns)
+{
+ int i;
+ u16 **matrix = (u16 **)kmalloc(((int)(size / columns)) * sizeof(u16 *),
+ GFP_KERNEL);
+
+ if (matrix != NULL) {
+ for (i = 0; i < (int)(size / columns); i++)
+ matrix[i] = (u16 *)kmalloc(columns * sizeof(u16),
+ GFP_KERNEL);
+
+ for (i = 0; i < size; i++)
+ matrix[i / columns][i % columns] = data[i];
+ }
+
+ return matrix;
+}
+
+/**
+ * Transform an array of u8 in a matrix of u8 with a defined number of
+ * columns and the resulting number of rows
+ * @param data array of bytes to convert
+ * @param size size of data
+ * @param columns number of columns that the resulting matrix should have.
+ * @return a reference to a matrix of short where for each row there are
+ * columns elements
+ */
+u8 **array1dTo2d_u8(u8 *data, int size, int columns)
+{
+ int i;
+ u8 **matrix = (u8 **)kmalloc(((int)(size / columns)) * sizeof(u8 *),
+ GFP_KERNEL);
+
+ if (matrix != NULL) {
+ for (i = 0; i < (int)(size / columns); i++)
+ matrix[i] = (u8 *)kmalloc(columns * sizeof(u8),
+ GFP_KERNEL);
+
+ for (i = 0; i < size; i++)
+ matrix[i / columns][i % columns] = data[i];
+ }
+
+ return matrix;
+}
+
+/**
+ * Transform an array of i8 in a matrix of i8 with a defined number of
+ * columns and the resulting number of rows
+ * @param data array of bytes to convert
+ * @param size size of data
+ * @param columns number of columns that the resulting matrix should have.
+ * @return a reference to a matrix of short where for each row there are
+ * columns elements
+ */
+i8 **array1dTo2d_i8(i8 *data, int size, int columns)
+{
+ int i;
+ i8 **matrix = (i8 **)kmalloc(((int)(size / columns)) * sizeof(i8 *),
+ GFP_KERNEL);
+
+ if (matrix != NULL) {
+ for (i = 0; i < (int)(size / columns); i++)
+ matrix[i] = (i8 *)kmalloc(columns * sizeof(i8),
+ GFP_KERNEL);
+
+ for (i = 0; i < size; i++)
+ matrix[i / columns][i % columns] = data[i];
+ }
+
+ return matrix;
+}
+
+/**
+ * Print in the kernel log a label followed by a matrix of short row x columns
+ * and free its memory
+ * @param label pointer to the string to print before the actual matrix
+ * @param matrix reference to the matrix of short which contain the actual data
+ * @param row number of rows on which the matrix should be print
+ * @param column number of columns for each row
+ */
+void print_frame_short(char *label, short **matrix, int row, int column)
+{
+ int i, j;
+ int buff_len, index;
+ char *buff;
+
+ buff_len = (6 + 1) * column + 1; /* -32768 str len: 6 */
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return;
+ }
+
+ pr_info("%s\n", label);
+ for (i = 0; i < row; i++) {
+ index = 0;
+ for (j = 0; j < column; j++)
+ index += scnprintf(buff + index, buff_len - index,
+ "%d ", matrix[i][j]);
+ pr_info("%s\n", buff);
+ kfree(matrix[i]);
+ }
+ kfree(matrix);
+ kfree(buff);
+}
+
+/**
+ * Print in the kernel log a label followed by a matrix of u16 row x columns
+ * and free its memory
+ * @param label pointer to the string to print before the actual matrix
+ * @param matrix reference to the matrix of u16 which contain the actual data
+ * @param row number of rows on which the matrix should be print
+ * @param column number of columns for each row
+ */
+void print_frame_u16(char *label, u16 **matrix, int row, int column)
+{
+ int i, j;
+ int buff_len, index;
+ char *buff;
+
+ buff_len = (5 + 1) * column + 1; /* 65535 str len: 5 */
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return;
+ }
+
+ pr_info("%s\n", label);
+ for (i = 0; i < row; i++) {
+ index = 0;
+ for (j = 0; j < column; j++)
+ index += scnprintf(buff + index, buff_len - index,
+ "%d ", matrix[i][j]);
+ pr_info("%s\n", buff);
+ kfree(matrix[i]);
+ }
+ kfree(matrix);
+ kfree(buff);
+}
+
+/**
+ * Print in the kernel log a label followed by a matrix of u8 row x columns and
+ * free its memory
+ * @param label pointer to the string to print before the actual matrix
+ * @param matrix reference to the matrix of u8 which contain the actual data
+ * @param row number of rows on which the matrix should be print
+ * @param column number of columns for each row
+ */
+void print_frame_u8(char *label, u8 **matrix, int row, int column)
+{
+ int i, j;
+ int buff_len, index;
+ char *buff;
+
+ buff_len = (3 + 1) * column + 1; /* 255 str len: 3 */
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return;
+ }
+
+ pr_info("%s\n", label);
+ for (i = 0; i < row; i++) {
+ index = 0;
+ for (j = 0; j < column; j++)
+ index += scnprintf(buff + index, buff_len - index,
+ "%d ", matrix[i][j]);
+ pr_info("%s\n", buff);
+ kfree(matrix[i]);
+ }
+ kfree(matrix);
+ kfree(buff);
+}
+
+/**
+ * Print in the kernel log a label followed by a matrix of i8 row x columns and
+ * free its memory
+ * @param label pointer to the string to print before the actual matrix
+ * @param matrix reference to the matrix of u8 which contain the actual data
+ * @param row number of rows on which the matrix should be print
+ * @param column number of columns for each row
+ */
+void print_frame_i8(char *label, i8 **matrix, int row, int column)
+{
+ int i, j;
+ int buff_len, index;
+ char *buff;
+
+ buff_len = (4 + 1) * column + 1; /* -128 str len: 4 */
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return;
+ }
+
+ pr_info("%s\n", label);
+ for (i = 0; i < row; i++) {
+ index = 0;
+ for (j = 0; j < column; j++)
+ index += scnprintf(buff + index, buff_len - index,
+ "%d ", matrix[i][j]);
+ pr_info("%s\n", buff);
+ kfree(matrix[i]);
+ }
+ kfree(matrix);
+ kfree(buff);
+}
+
+/**
+ * Print in the kernel log a label followed by a matrix of u32 row x columns
+ * and free its memory
+ * @param label pointer to the string to print before the actual matrix
+ * @param matrix reference to the matrix of u32 which contain the actual data
+ * @param row number of rows on which the matrix should be print
+ * @param column number of columns for each row
+ */
+void print_frame_u32(char *label, u32 **matrix, int row, int column)
+{
+ int i, j;
+ int buff_len, index;
+ char *buff;
+
+ buff_len = (10 + 1) * column + 1; /* 4294967295 str len: 10 */
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return;
+ }
+
+ pr_info("%s\n", label);
+ for (i = 0; i < row; i++) {
+ index = 0;
+ for (j = 0; j < column; j++)
+ index += scnprintf(buff + index, buff_len - index,
+ "%d ", matrix[i][j]);
+ pr_info("%s\n", buff);
+ kfree(matrix[i]);
+ }
+ kfree(matrix);
+ kfree(buff);
+}
+
+/**
+ * Print in the kernel log a label followed by a matrix of int row x columns
+ * and free its memory
+ * @param label pointer to the string to print before the actual matrix
+ * @param matrix reference to the matrix of int which contain the actual data
+ * @param row number of rows on which the matrix should be print
+ * @param column number of columns for each row
+ */
+void print_frame_int(char *label, int **matrix, int row, int column)
+{
+ int i, j;
+ int buff_len, index;
+ char *buff;
+
+ buff_len = (11 + 1) * column + 1; /* -2147483648 str len: 11 */
+ buff = kzalloc(buff_len, GFP_KERNEL);
+ if (buff == NULL) {
+ pr_err("%s: fail to allocate buffer\n", __func__);
+ return;
+ }
+
+ pr_info("%s\n", label);
+ for (i = 0; i < row; i++) {
+ index = 0;
+ for (j = 0; j < column; j++)
+ index += scnprintf(buff + index, buff_len - index,
+ "%d ", matrix[i][j]);
+ pr_info("%s\n", buff);
+ kfree(matrix[i]);
+ }
+ kfree(matrix);
+ kfree(buff);
+}
+
+
+/**
+ * Convert an array of bytes to an u64, src has MSB first (big endian).
+ * @param src array of bytes
+ * @param dest pointer to the destination u64.
+ * @param size size of src (can be <= 8)
+ * @return OK if success or ERROR_OP_NOT_ALLOW if size exceed 8
+ */
+int u8ToU64_be(u8 *src, u64 *dest, int size)
+{
+ int i = 0;
+
+ /* u64 temp =0; */
+ if (size > sizeof(u64))
+ return ERROR_OP_NOT_ALLOW;
+
+ *dest = 0;
+ for (i = 0; i < size; i++)
+ *dest |= (u64)(src[i]) << ((size - 1 - i) * 8);
+
+ return OK;
+}
+
+/**
+ * Convert an u64 to an array of bytes, dest has MSB first (big endian).
+ * @param src value of u64
+ * @param dest pointer to the destination array of bytes.
+ * @param size size of src (can be <= 8)
+ * @return OK if success or ERROR_OP_NOT_ALLOW if size exceed 8
+ */
+int u64ToU8_be(u64 src, u8 *dest, int size)
+{
+ int i = 0;
+
+ if (size > sizeof(u64))
+ return ERROR_OP_NOT_ALLOW;
+ else
+ for (i = 0; i < size; i++)
+ dest[i] = (u8)((src >> ((size - 1 - i) * 8)) & 0xFF);
+
+ return OK;
+}
+
+
+
+/*********** NEW API *************/
+
+/**
+ * Convert a value of an id in a bitmask with a 1 in the position of the value
+ * of the id
+ * @param id Value of the ID to convert
+ * @param mask pointer to the bitmask that will be updated with the value of id
+ * @param size dimension in bytes of mask
+ * @return OK if success or ERROR_OP_NOT_ALLOW if size of mask is not enough to
+ * contain ID
+ */
+int fromIDtoMask(u8 id, u8 *mask, int size)
+{
+ if (((int)((id) / 8)) < size) {
+ pr_info("%s: ID = %d Index = %d Position = %d !\n",
+ __func__, id, ((int)((id) / 8)), (id % 8));
+ mask[((int)((id) / 8))] |= 0x01 << (id % 8);
+ return OK;
+ } else {
+ pr_err("%s: Bitmask too small! Impossible contain ID = %d %d>=%d! ERROR %08X\n",
+ __func__, id, ((int)((id) / 8)), size,
+ ERROR_OP_NOT_ALLOW);
+ return ERROR_OP_NOT_ALLOW;
+ }
+}
diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTool.h b/drivers/input/touchscreen/stm/fts_lib/ftsTool.h
new file mode 100644
index 00000000000..284ef6c9cc9
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_lib/ftsTool.h
@@ -0,0 +1,58 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com **
+ **************************************************************************
+ * *
+ * FTS Utility Functions *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file ftsTool.h
+ * \brief Contains all the definitions to support common operations inside the
+ * driver
+ */
+
+#ifndef FTS_TOOL_H
+#define FTS_TOOL_H
+
+char *printHex(char *label, u8 *buff, int count, u8 *result, int size);
+int u8ToU16(u8 *src, u16 *dst);
+int u8ToU16_be(u8 *src, u16 *dst);
+int u8ToU16n(u8 *src, int src_length, u16 *dst);
+int u16ToU8(u16 src, u8 *dst);
+int u16ToU8_be(u16 src, u8 *dst);
+int u16ToU8n_be(u16 *src, int src_length, u8 *dst);
+int u8ToU32(u8 *src, u32 *dst);
+int u8ToU32_be(u8 *src, u32 *dst);
+int u32ToU8(u32 src, u8 *dst);
+int u32ToU8_be(u32 src, u8 *dst);
+int u8ToU64_be(u8 *src, u64 *dest, int size);
+int u64ToU8_be(u64 src, u8 *dest, int size);
+int attempt_function(int (*code)(void), unsigned long wait_before_retry, int
+ retry_count);
+int senseOn(void);
+int senseOff(void);
+void print_frame_short(char *label, short **matrix, int row, int column);
+short **array1dTo2d_short(short *data, int size, int columns);
+void print_frame_u16(char *label, u16 **matrix, int row, int column);
+u16 **array1dTo2d_u16(u16 *data, int size, int columns);
+u8 **array1dTo2d_u8(u8 *data, int size, int columns);
+i8 **array1dTo2d_i8(i8 *data, int size, int columns);
+void print_frame_u8(char *label, u8 **matrix, int row, int column);
+void print_frame_i8(char *label, i8 **matrix, int row, int column);
+void print_frame_u32(char *label, u32 **matrix, int row, int column);
+void print_frame_int(char *label, int **matrix, int row, int column);
+int cleanUp(int enableTouch);
+int flushFIFO(void);
+
+/* New API */
+int fromIDtoMask(u8 id, u8 *mask, int size);
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_limits.h b/drivers/input/touchscreen/stm/fts_limits.h
new file mode 100644
index 00000000000..5ecfa546b5b
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_limits.h
@@ -0,0 +1,1064 @@
+/*!
+* \file fts_limits.h
+* \brief Contains the size and the byte array of the production test limit file which contains thresholds used to test data
+*/
+
+#ifndef FTS_LIMITS_H
+#define FTS_LIMITS_H
+//This is an auto generated header file
+//--->Remember to change the name of the two variables!<---
+const uint32_t myArray2_size = 16725; ///< size of the array containing the production limit file
+
+/**
+ * Array containing the production limit file
+ */
+const uint8_t myArray2[] = {
+ 0x2A, 0x53, 0x54, 0x4F, 0x50, 0x5F, 0x4F, 0x4E, 0x5F, 0x46, 0x41, 0x49, 0x4C, 0x2C, 0x31, 0x2C,
+ 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x53, 0x54, 0x4F, 0x50, 0x5F, 0x4F, 0x4E, 0x5F, 0x45, 0x52, 0x52,
+ 0x4F, 0x52, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F,
+ 0x46, 0x57, 0x5F, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x30, 0x0A,
+ 0x2A, 0x53, 0x53, 0x5F, 0x49, 0x58, 0x31, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x57, 0x2C,
+ 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x46, 0x4F,
+ 0x52, 0x43, 0x45, 0x5F, 0x57, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x53, 0x53, 0x5F,
+ 0x49, 0x58, 0x31, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x57, 0x2C, 0x31, 0x2C, 0x31, 0x0A,
+ 0x32, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F,
+ 0x57, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x31, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x52, 0x41, 0x57, 0x5F,
+ 0x44, 0x41, 0x54, 0x41, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32,
+ 0x0A, 0x31, 0x30, 0x30, 0x30, 0x2C, 0x31, 0x35, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F,
+ 0x52, 0x41, 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x47, 0x41, 0x50, 0x2C, 0x31, 0x2C, 0x31,
+ 0x0A, 0x33, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F,
+ 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D,
+ 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, 0x2A, 0x4D, 0x53, 0x5F,
+ 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32,
+ 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A,
+ 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F,
+ 0x43, 0x58, 0x32, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x37, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52,
+ 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x36, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49,
+ 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49,
+ 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x32, 0x37, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A,
+ 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F,
+ 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C,
+ 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48,
+ 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58,
+ 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x37, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48,
+ 0x4F, 0x52, 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x32, 0x32, 0x2C, 0x32, 0x36, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44,
+ 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x32, 0x37,
+ 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36,
+ 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34,
+ 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C,
+ 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x52, 0x41,
+ 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31,
+ 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x38, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45,
+ 0x59, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C,
+ 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43,
+ 0x58, 0x32, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x0A, 0x2A, 0x4D, 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x4D, 0x41, 0x58,
+ 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A, 0x4D,
+ 0x53, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x4D,
+ 0x49, 0x4E, 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x4D, 0x53,
+ 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x4D, 0x41,
+ 0x58, 0x2C, 0x31, 0x2C, 0x33, 0x0A, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x2C, 0x36, 0x34, 0x0A, 0x2A,
+ 0x53, 0x53, 0x5F, 0x52, 0x41, 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x46, 0x4F, 0x52, 0x43,
+ 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x31, 0x30,
+ 0x30, 0x30, 0x2C, 0x31, 0x35, 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x52, 0x41, 0x57,
+ 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x47, 0x41, 0x50, 0x2C,
+ 0x31, 0x2C, 0x31, 0x0A, 0x33, 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43,
+ 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x31, 0x5F, 0x46, 0x4F, 0x52,
+ 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30,
+ 0x2C, 0x36, 0x33, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D,
+ 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A,
+ 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A,
+ 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A,
+ 0x30, 0x0A, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D,
+ 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
+ 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41,
+ 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32,
+ 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32,
+ 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32,
+ 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32,
+ 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32,
+ 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54,
+ 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41,
+ 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32,
+ 0x32, 0x2C, 0x31, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A,
+ 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A,
+ 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A,
+ 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
+ 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F,
+ 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56,
+ 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x45, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x5F,
+ 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, 0x2A, 0x53, 0x53,
+ 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58,
+ 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x31,
+ 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30,
+ 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30,
+ 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x2A, 0x53, 0x53,
+ 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58,
+ 0x32, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C, 0x31,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35,
+ 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55,
+ 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41, 0x44,
+ 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C, 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A,
+ 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x46, 0x4F,
+ 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x32, 0x32, 0x2C, 0x31, 0x0A, 0x30, 0x0A, 0x30,
+ 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30,
+ 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30,
+ 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55,
+ 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F,
+ 0x43, 0x58, 0x5F, 0x46, 0x4F, 0x52, 0x43, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x32, 0x32, 0x2C,
+ 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F,
+ 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C,
+ 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x56, 0x45, 0x52, 0x54, 0x49, 0x43, 0x41, 0x4C,
+ 0x2C, 0x32, 0x31, 0x2C, 0x31, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35,
+ 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x52, 0x41,
+ 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E,
+ 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x31, 0x30, 0x30, 0x30, 0x2C, 0x31, 0x35,
+ 0x30, 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x52, 0x41, 0x57, 0x5F, 0x44, 0x41, 0x54, 0x41,
+ 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x47, 0x41, 0x50, 0x2C, 0x31, 0x2C, 0x31, 0x0A, 0x33,
+ 0x30, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54,
+ 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x31, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49,
+ 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A, 0x2A,
+ 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F,
+ 0x49, 0x58, 0x32, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, 0x2C,
+ 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55,
+ 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x53, 0x45,
+ 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x37, 0x0A, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55,
+ 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x49, 0x58, 0x32, 0x5F, 0x41, 0x44,
+ 0x4A, 0x5F, 0x48, 0x4F, 0x52, 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, 0x32,
+ 0x36, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F,
+ 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C,
+ 0x5F, 0x49, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31, 0x2C,
+ 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30,
+ 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55,
+ 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F,
+ 0x49, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32,
+ 0x37, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53,
+ 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54,
+ 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x49, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52, 0x49,
+ 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, 0x32, 0x36, 0x0A, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C,
+ 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x31, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D,
+ 0x49, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x0A, 0x30, 0x2C, 0x36, 0x33, 0x0A,
+ 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
+ 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31,
+ 0x2C, 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C,
+ 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C,
+ 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C,
+ 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F,
+ 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x53,
+ 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C, 0x32, 0x37, 0x0A, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35,
+ 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F,
+ 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x43, 0x58, 0x32, 0x5F, 0x41,
+ 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52, 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C,
+ 0x32, 0x36, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54,
+ 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41,
+ 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x49, 0x4E, 0x2C, 0x31,
+ 0x2C, 0x32, 0x37, 0x0A, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C,
+ 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C,
+ 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C,
+ 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x2C, 0x30, 0x0A, 0x2A, 0x53, 0x53, 0x5F, 0x54, 0x4F,
+ 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F, 0x54, 0x4F, 0x54, 0x41, 0x4C,
+ 0x5F, 0x43, 0x58, 0x5F, 0x53, 0x45, 0x4E, 0x53, 0x45, 0x5F, 0x4D, 0x41, 0x58, 0x2C, 0x31, 0x2C,
+ 0x32, 0x37, 0x0A, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32,
+ 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x0A, 0x2A,
+ 0x53, 0x53, 0x5F, 0x54, 0x4F, 0x55, 0x43, 0x48, 0x5F, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5F,
+ 0x54, 0x4F, 0x54, 0x41, 0x4C, 0x5F, 0x43, 0x58, 0x5F, 0x41, 0x44, 0x4A, 0x5F, 0x48, 0x4F, 0x52,
+ 0x49, 0x5A, 0x4F, 0x4E, 0x54, 0x41, 0x4C, 0x2C, 0x31, 0x2C, 0x32, 0x36, 0x0A, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35, 0x2C, 0x32, 0x35, 0x35,
+ 0x2C, 0x32, 0x35, 0x35, 0x0A,
+};
+
+#endif
diff --git a/drivers/input/touchscreen/stm/fts_proc.c b/drivers/input/touchscreen/stm/fts_proc.c
new file mode 100644
index 00000000000..bd6ddf37f96
--- /dev/null
+++ b/drivers/input/touchscreen/stm/fts_proc.c
@@ -0,0 +1,3485 @@
+/*
+ *
+ **************************************************************************
+ ** STMicroelectronics **
+ **************************************************************************
+ ** marco.cali@st.com *
+ **************************************************************************
+ * *
+ * Utilities published in /proc/fts *
+ * *
+ **************************************************************************
+ **************************************************************************
+ *
+ */
+
+/*!
+ * \file fts_proc.c
+ * \brief contains the function and variables needed to publish a file node in
+ * the file system which allow to communicate with the IC from userspace
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include "fts.h"
+#include "fts_lib/ftsCompensation.h"
+#include "fts_lib/ftsCore.h"
+#include "fts_lib/ftsIO.h"
+#include "fts_lib/ftsError.h"
+#include "fts_lib/ftsFrame.h"
+#include "fts_lib/ftsFlash.h"
+#include "fts_lib/ftsTest.h"
+#include "fts_lib/ftsTime.h"
+#include "fts_lib/ftsTool.h"
+
+
+#define DRIVER_TEST_FILE_NODE "driver_test" /* /< name of file node
+ * published */
+#define CHUNK_PROC 1024 /* /< Max chunk of data printed on
+ * the sequential file in each
+ * iteration */
+#define DIAGNOSTIC_NUM_FRAME 10 /* /< number of frames reading
+ * iterations during the diagnostic
+ * test */
+
+
+
+/** @defgroup proc_file_code Proc File Node
+ * @ingroup file_nodes
+ * The /proc/fts/driver_test file node provide expose the most important API
+ * implemented into the driver to execute any possible operation into the IC \n
+ * Thanks to a series of Operation Codes, each of them, with a different set of
+ * parameter, it is possible to select a function to execute\n
+ * The result of the function is usually returned into the shell as an ASCII
+ * hex string where each byte is encoded in two chars.\n
+ * @{
+ */
+
+/* Bus operations */
+#define CMD_READ 0x00 /* /< I2C/SPI read: need
+ * to pass: byteToRead1
+ * byteToRead0
+ * (optional) dummyByte
+ * */
+#define CMD_WRITE 0x01 /* /< I2C/SPI write:
+ * need to pass: cmd[0]
+ * cmd[1] …
+ * cmd[cmdLength-1] */
+#define CMD_WRITEREAD 0x02 /* /< I2C/SPI writeRead:
+ * need to pass: cmd[0]
+ * cmd[1] …
+ * cmd[cmdLength-1]
+ * byteToRead1
+ * byteToRead0 dummyByte
+ * */
+#define CMD_WRITETHENWRITEREAD 0x03 /* /< I2C/SPI write then
+ * writeRead: need to
+ * pass: cmdSize1
+ * cmdSize2 cmd1[0]
+ * cmd1[1] …
+ * cmd1[cmdSize1-1]
+ * cmd2[0] cmd2[1] …
+ * cmd2[cmdSize2-1]
+ * byteToRead1
+ * byteToRead0 */
+#define CMD_WRITEU8UX 0x04
+ /* /< I2C/SPI
+ * writeU8UX:
+ * need to pass: cmd
+ * addrSize addr[0] …
+ * addr[addrSize-1]
+ * data[0] data[1] … */
+#define CMD_WRITEREADU8UX 0x05 /* /< I2C/SPI
+ * writeReadU8UX: need
+ * to pass: cmd addrSize
+ * addr[0] …
+ * addr[addrSize-1]
+ * byteToRead1
+ * byteToRead0
+ * hasDummyByte */
+#define CMD_WRITEU8UXTHENWRITEU8UX 0x06
+ /* /< I2C/SPI writeU8UX
+ * then writeU8UX: need
+ * to pass: cmd1
+ * addrSize1 cmd2
+ * addrSize2 addr[0] …
+ * addr[addrSize1+
+ * addrSize2-1]
+ * data[0] data[1] … */
+#define CMD_WRITEU8UXTHENWRITEREADU8UX 0x07 /* /< I2C/SPI writeU8UX
+ * then writeReadU8UX:
+ * need to pass: cmd1
+ * addrSize1 cmd2
+ * addrSize2 addr[0] …
+ * addr[addrSize1+
+ * addrSize2-1]
+ * byteToRead1
+ * byteToRead0
+ * hasDummybyte */
+#define CMD_GETLIMITSFILE 0x08 /* /< Get the Production
+ * Limits File and print
+ * its content into the
+ * shell: need to pass:
+ * path(optional)
+ * otherwise select the
+ * approach chosen at
+ * compile time */
+#define CMD_GETFWFILE 0x09 /* /< Get the FW file
+ * and print its content
+ * into the shell: need
+ * to pass: path
+ * (optional) otherwise
+ * select the approach
+ * chosen at compile
+ * time */
+#define CMD_VERSION 0x0A /* /< Get the driver
+ * version and other
+ * driver setting info
+ * */
+#define CMD_READCONFIG 0x0B /* /< Read The config
+ * memory, need to pass:
+ * addr[0] addr[1]
+ * byteToRead0
+ * byteToRead1 */
+
+
+/* GUI utils byte ver */
+#define CMD_READ_BYTE 0xF0 /* /< Byte output
+ * version of I2C/SPI
+ * read @see CMD_READ */
+#define CMD_WRITE_BYTE 0xF1 /* /< Byte output
+ * version of I2C/SPI
+ * write @see CMD_WRITE
+ * */
+#define CMD_WRITEREAD_BYTE 0xF2 /* /< Byte output
+ * version of I2C/SPI
+ * writeRead @see
+ * CMD_WRITEREAD */
+#define CMD_WRITETHENWRITEREAD_BYTE 0xF3
+ /* /< Byte output
+ * version of I2C/SPI
+ * write then writeRead
+ * @see
+ * CMD_WRITETHENWRITEREAD
+ * */
+#define CMD_WRITEU8UX_BYTE 0xF4 /* /< Byte output
+ * version of I2C/SPI
+ * writeU8UX @see
+ * CMD_WRITEU8UX */
+#define CMD_WRITEREADU8UX_BYTE 0xF5 /* /< Byte output
+ * version of I2C/SPI
+ * writeReadU8UX @see
+ * CMD_WRITEREADU8UX */
+#define CMD_WRITEU8UXTHENWRITEU8UX_BYTE 0xF6
+ /* /< Byte output
+ * version of I2C/SPI
+ * writeU8UX then
+ * writeU8UX @see
+ * CMD_WRITEU8UXTHENWRITEU8UX
+ * */
+#define CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE 0xF7
+ /* /< Byte output
+ * version of I2C/SPI
+ * writeU8UX then
+ * writeReadU8UX @see
+ * CMD_WRITEU8UXTHENWRITEREADU8UX
+ * */
+#define CMD_GETLIMITSFILE_BYTE 0xF8 /* /< Byte output
+ * version of Production
+ * Limits File @see
+ * CMD_GETLIMITSFILE */
+#define CMD_GETFWFILE_BYTE 0xF9 /* /< Byte output
+ * version of FW file
+ * need to pass: @see
+ * CMD_GETFWFILE */
+#define CMD_VERSION_BYTE 0xFA /* /< Byte output
+ * version of driver
+ * version and setting
+ * @see CMD_VERSION */
+#define CMD_CHANGE_OUTPUT_MODE 0xFF /* /< Select the output
+ * mode of the
+ * scriptless protocol,
+ * need to pass:
+ * bin_output = 1 data
+ * returned as binary,
+ * bin_output =0 data
+ * returned as hex
+ * string */
+
+/* Core/Tools */
+#define CMD_POLLFOREVENT 0x11 /* /< Poll the FIFO for
+ * an event: need to
+ * pass: eventLength
+ * event[0] event[1] …
+ * event[eventLength-1]
+ * timeToWait1
+ * timeToWait0 */
+#define CMD_SYSTEMRESET 0x12 /* /< System Reset */
+#define CMD_CLEANUP 0x13 /* /< Perform a system
+ * reset and optionally
+ * re-enable the
+ * scanning, need to
+ * pass: enableTouch */
+#define CMD_POWERCYCLE 0x14 /* /< Execute a power
+ * cycle toggling the
+ * regulators */
+#define CMD_READSYSINFO 0x15 /* /< Read the System
+ * Info information from
+ * the framebuffer, need
+ * to pass: doRequest */
+#define CMD_FWWRITE 0x16
+ /* /< Write a FW
+ * command: need to
+ * pass: cmd[0] cmd[1]
+ * … cmd[cmdLength-1] */
+#define CMD_INTERRUPT 0x17 /* /< Allow to enable or
+ * disable the
+ * interrupts, need to
+ * pass: enable (if 1
+ * will enable the
+ * interrupt) */
+
+/* Frame */
+#define CMD_GETFORCELEN 0x20 /* /< Get the number of
+ * Force channels */
+#define CMD_GETSENSELEN 0x21 /* /< Get the number of
+ * Sense channels */
+#define CMD_GETMSFRAME 0x23 /* /< Get a MS frame:
+ * need to pass:
+ * MSFrameType */
+#define CMD_GETSSFRAME 0x24 /* /< Get a SS frame:
+ * need to pass:
+ * SSFrameType */
+
+/* Compensation */
+#define CMD_REQCOMPDATA 0x30 /* /< Request Init data:
+ * need to pass: type */
+#define CMD_READCOMPDATAHEAD 0x31 /* /< Read Init data
+ * header: need to pass:
+ * type */
+#define CMD_READMSCOMPDATA 0x32 /* /< Read MS Init data:
+ * need to pass: type */
+#define CMD_READSSCOMPDATA 0x33 /* /< Read SS Init data:
+ * need to pass: type */
+#define CMD_READTOTMSCOMPDATA 0x35 /* /< Read Tot MS Init
+ * data: need to pass:
+ * type */
+#define CMD_READTOTSSCOMPDATA 0x36 /* /< Read Tot SS Init
+ * data: need to pass:
+ * type */
+#define CMD_READSENSCOEFF 0x37 /* /< Read MS and SS
+ * Sensitivity
+ * Calibration
+ * Coefficients */
+
+/* FW Update */
+#define CMD_GETFWVER 0x40 /* /< Get the FW version
+ * of the IC */
+#define CMD_FLASHUNLOCK 0x42 /* /< Unlock the flash
+ * */
+#define CMD_READFWFILE 0x43 /* /< Try to read the FW
+ * file, need to pass:
+ * keep_cx */
+#define CMD_FLASHPROCEDURE 0x44 /* /< Perform a full
+ * flashing procedure:
+ * need to pass: force
+ * keep_cx */
+#define CMD_FLASHERASEUNLOCK 0x45 /* /< Unlock the erase
+ * of the flash */
+#define CMD_FLASHERASEPAGE 0x46
+ /* /< Erase page by page
+ * the flash, need to
+ * pass: keep_cx, if
+ * keep_cx>SKIP_PANEL_INIT
+ * Panel Init Page will
+ * be skipped, if
+ * >SKIP_PANEL_CX_INIT
+ * Cx and Panel Init
+ * Pages will be skipped
+ * otherwise if
+ * =ERASE_ALL all the
+ * pages will be deleted
+ * */
+
+/* MP test */
+#define CMD_ITOTEST 0x50 /* /< Perform an ITO
+ * test */
+#define CMD_INITTEST 0x51 /* /< Perform an
+ * Initialization test:
+ * need to pass: type */
+#define CMD_MSRAWTEST 0x52 /* /< Perform MS raw
+ * test: need to pass
+ * stop_on_fail */
+#define CMD_MSINITDATATEST 0x53 /* /< Perform MS Init
+ * data test: need to
+ * pass stop_on_fail */
+#define CMD_SSRAWTEST 0x54 /* /< Perform SS raw
+ * test: need to pass
+ * stop_on_fail */
+#define CMD_SSINITDATATEST 0x55 /* /< Perform SS Init
+ * data test: need to
+ * pass stop_on_fail */
+#define CMD_MAINTEST 0x56 /* /< Perform a full
+ * Mass production test:
+ * need to pass
+ * stop_on_fail saveInit
+ * */
+#define CMD_FREELIMIT 0x57 /* /< Free (if any)
+ * limit file which was
+ * loaded during any
+ * test procedure */
+
+/* Diagnostic */
+#define CMD_DIAGNOSTIC 0x60 /* /< Perform a series
+ * of commands and
+ * collect severals data
+ * to detect any
+ * malfunction */
+
+#define CMD_CHANGE_SAD 0x70 /* /< Allow to change
+ * the SAD address (for
+ * debugging) */
+
+/* Debug functionalities requested by Google for B1 Project */
+#define CMD_TRIGGER_FORCECAL 0x80 /* /< Trigger manually
+ * forcecal for MS and
+ * SS */
+#define CMD_BASELINE_ADAPTATION 0x81 /* /< Enable/Disable
+ * Baseline adaptation,
+ * need to pass: enable
+ * */
+#define CMD_FREQ_HOP 0x82 /* /< Enable/Disable
+ * Frequency hopping,
+ * need to pass: enable
+ * */
+#define CMD_SET_OPERATING_FREQ 0x83 /* /< Set a defined
+ * scanning frequency in
+ * Hz passed as 4 bytes
+ * in big endian, need
+ * to pass: freq3 freq2
+ * freq1 freq0 */
+#define CMD_READ_SYNC_FRAME 0x84
+ /* /< Read Sync Frame
+ * which contain MS and
+ * SS data, need to
+ * pass: frameType (this
+ * parameter can be
+ * LOAD_SYNC_FRAME_STRENGTH
+ * or LOAD_SYNC_FRAME_BASELINE)
+ * */
+
+
+#define CMD_TP_SENS_MODE 0x90 /* /< Enter/Exit in the
+ * TP Sensitivity
+ * Calibration mode,
+ * need to pass: enter
+ * (optional)saveGain */
+#define CMD_TP_SENS_SET_SCAN_MODE 0x91 /* /< Set scan mode type
+ * which should be used
+ * for the test before
+ * the stimpad is down,
+ * need to pass: type */
+#define CMD_TP_SENS_PRECAL_SS 0x92 /* /< Perform Pre
+ * Calibration for SS
+ * steps when stimpad is
+ * down */
+#define CMD_TP_SENS_PRECAL_MS 0x93 /* /< Perform Pre
+ * Calibration for MS
+ * steps when stimpad is
+ * down */
+#define CMD_TP_SENS_POSTCAL_MS 0x94 /* /< Perform Post
+ * Calibration for MS
+ * steps when stimpad is
+ * down */
+#define CMD_TP_SENS_STD 0x95 /* /< Compute the
+ * Standard deviation of
+ * a certain number of
+ * frames, need to pass:
+ * numFrames */
+
+#define CMD_FORCE_TOUCH_ACTIVE 0xA0 /* /< Prevent the driver
+ * from transitioning
+ * the ownership of the
+ * bus to SLPI
+ */
+
+static u8 bin_output; /* /< Select the output type of the scriptless
+ * protocol (binary = 1 or hex string = 0) */
+/** @}*/
+
+/** @defgroup scriptless Scriptless Protocol
+ * @ingroup proc_file_code
+ * Scriptless Protocol allows ST Software (such as FingerTip Studio etc) to
+ * communicate with the IC from an user space.
+ * This mode gives access to common bus operations (write, read etc) and
+ * support additional functionalities. \n
+ * The protocol is based on exchange of binary messages included between a
+ * start and an end byte
+ * @{
+ */
+
+#define MESSAGE_START_BYTE 0x7B /* /< start byte of each message
+ * transferred in Scriptless Mode */
+#define MESSAGE_END_BYTE 0x7D /* /< end byte of each message
+ * transferred in Scriptless Mode */
+#define MESSAGE_MIN_HEADER_SIZE 8 /* /< minimun number of bytes of the
+ * structure of a messages exchanged
+ * with host (include start/end byte,
+ * counter, actions, msg_size) */
+
+/**
+ * Possible actions that can be requested by an host
+ */
+typedef enum {
+ ACTION_WRITE = (u16) 0x0001, /* /< Bus Write
+ * */
+ ACTION_READ = (u16) 0x0002, /* /< Bus Read
+ * */
+ ACTION_WRITE_READ = (u16) 0x0003, /* /< Bus Write
+ * followed by a
+ * Read */
+ ACTION_GET_VERSION = (u16) 0x0004, /* /< Get
+ * Version of
+ * the protocol
+ * (equal to the
+ * first 2 bye
+ * of driver
+ * version) */
+ ACTION_WRITEU8UX = (u16) 0x0011, /* /< Bus Write
+ * with support
+ * to different
+ * address size
+ * */
+ ACTION_WRITEREADU8UX = (u16) 0x0012, /* /< Bus
+ * writeRead
+ * with support
+ * to different
+ * address size
+ * */
+ ACTION_WRITETHENWRITEREAD = (u16) 0x0013, /* /< Bus write
+ * followed by a
+ * writeRead */
+ ACTION_WRITEU8XTHENWRITEREADU8UX = (u16) 0x0014, /* /< Bus write
+ * followed by a
+ * writeRead
+ * with support
+ * to different
+ * address size
+ * */
+ ACTION_WRITEU8UXTHENWRITEU8UX = (u16) 0x0015, /* /< Bus write
+ * followed by a
+ * write with
+ * support to
+ * different
+ * address size
+ * */
+ ACTION_GET_FW = (u16) 0x1000, /* /< Get Fw
+ * file content
+ * used by the
+ * driver */
+ ACTION_GET_LIMIT = (u16) 0x1001 /* /< Get Limit
+ * File content
+ * used by the
+ * driver */
+} Actions;
+
+/**
+ * Struct used to contain info of the message received by the host in
+ * Scriptless mode
+ */
+typedef struct {
+ u16 msg_size; /* /< total size of the message in bytes */
+ u16 counter; /* /< counter ID to identify a message */
+ Actions action; /* /< type of operation requested by the host @see
+ * Actions */
+ u8 dummy; /* /< (optional)in case of any kind of read operations,
+ * specify if the first byte is dummy */
+} Message;
+
+/** @}*/
+
+
+
+extern TestToDo tests;
+extern SysInfo systemInfo;
+
+static int limit; /* /< store the amount of data to print into the
+ * shell */
+static int chunk; /* /< store the chuk of data that should be printed in
+ * this iteration */
+static int printed; /* /< store the amount of data already printed in the
+ * shell */
+static struct proc_dir_entry *fts_dir; /* /< reference to the directory
+ * fts under /proc */
+static u8 *driver_test_buff; /* /< pointer to an array of bytes used
+ * to store the result of the function
+ * executed */
+char buf_chunk[CHUNK_PROC] = { 0 }; /* /< buffer used to store the message
+ * info received */
+static Message mess = { 0 }; /* /< store the information of the Scriptless
+ * message received */
+
+
+/************************ SEQUENTIAL FILE UTILITIES **************************/
+/**
+ * This function is called at the beginning of the stream to a sequential file
+ * or every time into the sequential were already written PAGE_SIZE bytes and
+ * the stream need to restart
+ * @param s pointer to the sequential file on which print the data
+ * @param pos pointer to the offset where write the data
+ * @return NULL if there is no data to print or the pointer to the beginning of
+ * the data that need to be printed
+ */
+static void *fts_seq_start(struct seq_file *s, loff_t *pos)
+{
+ pr_info("%s: Entering start(), pos = %lld limit = %d printed = %d\n",
+ __func__, *pos, limit, printed);
+
+ if (driver_test_buff == NULL && *pos == 0) {
+ int size = 13 * sizeof(u8);
+
+ pr_info("%s: No data to print!\n", __func__);
+ driver_test_buff = (u8 *)kmalloc(size, GFP_KERNEL);
+ limit = scnprintf(driver_test_buff,
+ size,
+ "{ %08X }\n", ERROR_OP_NOT_ALLOW);
+ /* pr_err("%s: len = %d driver_test_buff = %s\n",
+ * __func__, limit, driver_test_buff); */
+ } else {
+ if (*pos != 0)
+ *pos += chunk - 1;
+
+ if (*pos >= limit)
+ /* pr_err("%s: Apparently, we're done.\n", __func__); */
+ return NULL;
+ }
+
+ chunk = CHUNK_PROC;
+ if (limit - *pos < CHUNK_PROC)
+ chunk = limit - *pos;
+ /* pr_err("%s: In start(),
+ * updated pos = %Ld limit = %d printed = %d chunk = %d\n",
+ * __func__, *pos, limit, printed, chunk); */
+ memset(buf_chunk, 0, CHUNK_PROC);
+ memcpy(buf_chunk, &driver_test_buff[(int)*pos], chunk);
+
+ return buf_chunk;
+}
+
+/**
+ * This function actually print a chunk amount of data in the sequential file
+ * @param s pointer to the sequential file where to print the data
+ * @param v pointer to the data to print
+ * @return 0
+ */
+static int fts_seq_show(struct seq_file *s, void *v)
+{
+ /* pr_err("%s: In show()\n", __func__); */
+ seq_write(s, (u8 *)v, chunk);
+ printed += chunk;
+ return 0;
+}
+
+/**
+ * This function update the pointer and the counters to the next data to be
+ * printed
+ * @param s pointer to the sequential file where to print the data
+ * @param v pointer to the data to print
+ * @param pos pointer to the offset where write the next data
+ * @return NULL if there is no data to print or the pointer to the beginning of
+ * the next data that need to be printed
+ */
+static void *fts_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ /* int* val_ptr; */
+ /* pr_err("%s: In next(), v = %X, pos = %Ld.\n", __func__,
+ * v, *pos); */
+ (*pos) += chunk;/* increase my position counter */
+ chunk = CHUNK_PROC;
+
+ /* pr_err("%s: In next(),
+ * updated pos = %Ld limit = %d printed = %d\n",
+ * __func__, *pos, limit,printed); */
+ if (*pos >= limit) /* are we done? */
+ return NULL;
+ else if (limit - *pos < CHUNK_PROC)
+ chunk = limit - *pos;
+
+
+ memset(buf_chunk, 0, CHUNK_PROC);
+ memcpy(buf_chunk, &driver_test_buff[(int)*pos], chunk);
+ return buf_chunk;
+}
+
+
+/**
+ * This function is called when there are no more data to print the stream
+ *need to be terminated or when PAGE_SIZE data were already written into the
+ *sequential file
+ * @param s pointer to the sequential file where to print the data
+ * @param v pointer returned by fts_seq_next
+ */
+static void fts_seq_stop(struct seq_file *s, void *v)
+{
+ /* pr_err("%s: Entering stop().\n", __func__); */
+
+ if (v) {
+ /* pr_err("%s: v is %X.\n", __func__, v); */
+ } else {
+ /* pr_err("%s: v is null.\n", __func__); */
+ limit = 0;
+ chunk = 0;
+ printed = 0;
+ if (driver_test_buff != NULL) {
+ /* pr_err("%s: Freeing and clearing driver_test_buff.\n",
+ * __func__); */
+ kfree(driver_test_buff);
+ driver_test_buff = NULL;
+ } else {
+ /* pr_err("%s: driver_test_buff is already null.\n",
+ * __func__); */
+ }
+ }
+}
+
+/**
+ * Struct where define and specify the functions which implements the flow for
+ * writing on a sequential file
+ */
+static const struct seq_operations fts_seq_ops = {
+ .start = fts_seq_start,
+ .next = fts_seq_next,
+ .stop = fts_seq_stop,
+ .show = fts_seq_show
+};
+
+/**
+ * This function open a sequential file
+ * @param inode Inode in the file system that was called and triggered this
+ * function
+ * @param file file associated to the file node
+ * @return error code, 0 if success
+ */
+static int fts_driver_test_open(struct inode *inode, struct file *file)
+{
+ struct fts_ts_info *info = dev_get_drvdata(getDev());
+ int retval;
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ retval = -EBUSY;
+ goto exit;
+ }
+
+ /* Allowing only a single process to open diag procfs node */
+ if (info->diag_node_open == true) {
+ pr_err("%s: Blocking multiple open\n", __func__);
+ retval = -EBUSY;
+ goto unlock;
+ }
+
+ retval = seq_open(file, &fts_seq_ops);
+ if(!retval) {
+ info->diag_node_open = true;
+ }
+
+unlock:
+ mutex_unlock(&info->diag_cmd_lock);
+exit:
+ return retval;
+};
+
+/**
+ * This function closes a sequential file
+ * @param inode Inode in the file system that was called and triggered this
+ * function
+ * @param file file associated to the file node
+ * @return error code, 0 if success
+ */
+static int fts_driver_test_release(struct inode *inode, struct file *file)
+{
+ struct fts_ts_info *info = dev_get_drvdata(getDev());
+ int retval;
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ retval = -EBUSY;
+ goto exit;
+ }
+
+ retval = seq_release(inode, file);
+ info->diag_node_open = false;
+
+ mutex_unlock(&info->diag_cmd_lock);
+exit:
+ return retval;
+}
+
+
+/**
+ * This function reads a sequential file
+ * @param file file associated to the file node
+ * @param buf userspace buffer where the newly read data should be placed
+ * @param count size of the requested transfer.
+ * @param pos start position from which data should be written in the file.
+ * @return error code, 0 if success
+ */
+static ssize_t fts_driver_test_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct fts_ts_info *info = dev_get_drvdata(getDev());
+ ssize_t bytes_read = -EINVAL;
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ bytes_read = -ENODEV;
+ goto exit;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ bytes_read = -EBUSY;
+ goto exit;
+ }
+
+ bytes_read = seq_read(file, buf, count, pos);
+
+ mutex_unlock(&info->diag_cmd_lock);
+exit:
+ return bytes_read;
+}
+
+/**
+ * This function moves the cursor position within a file.
+ * @param file file associated to the file node
+ * @param offset offset relative to the current file position.
+ * @param whence defines where to seek from.
+ * @return error code, 0 if success
+ */
+static loff_t fts_driver_test_lseek(struct file *file, loff_t offset,
+ int whence)
+{
+ struct fts_ts_info *info = dev_get_drvdata(getDev());
+ loff_t retval;
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ retval = -EBUSY;
+ goto exit;
+ }
+
+ retval = seq_lseek(file, offset, whence);
+
+ mutex_unlock(&info->diag_cmd_lock);
+
+exit:
+ return retval;
+}
+
+/*****************************************************************************/
+
+/**************************** DRIVER TEST ************************************/
+
+/** @addtogroup proc_file_code
+ * @{
+ */
+
+/**
+ * Receive the OP code and the inputs from shell when the file node is called,
+ * parse it and then execute the corresponding function
+ * echo cmd+parameters > /proc/fts/driver_test to execute the select command
+ * cat /proc/fts/driver_test to obtain the result into the
+ * shell \n
+ * the string returned in the shell is made up as follow: \n
+ * { = start byte \n
+ * the answer content and format strictly depend on the cmd executed. In
+ * general can be: an HEX string or a byte array (e.g in case of 0xF- commands)
+ * \n
+ * } = end byte \n
+ */
+static ssize_t fts_driver_test_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ int numberParam = 0;
+ struct fts_ts_info *info = dev_get_drvdata(getDev());
+ char *p = NULL;
+ char *pbuf = NULL;
+ char path[100] = { 0 };
+ int res = -1, j, index = 0;
+ int size = 6;
+ int temp, byte_call = 0;
+ u16 byteToRead = 0;
+ u32 fileSize = 0;
+ u8 *readData = NULL;
+ u8 *cmd = NULL; /* worst case needs count bytes */
+ u32 *funcToTest = NULL;
+ u64 addr = 0;
+ MutualSenseFrame frameMS;
+ MutualSenseFrame deltas;
+ SelfSenseFrame frameSS;
+
+ DataHeader dataHead;
+ MutualSenseData compData;
+ SelfSenseData comData;
+ TotMutualSenseData totCompData;
+ TotSelfSenseData totComData;
+ MutualSenseCoeff msCoeff;
+ SelfSenseCoeff ssCoeff;
+ int meanNorm = 0, meanEdge = 0;
+
+ u64 address;
+
+ Firmware fw;
+ LimitFile lim;
+
+ if (!info) {
+ pr_err("%s: Unable to access driver data\n", __func__);
+ count = -ENODEV;
+ goto exit;
+ }
+
+ if (!mutex_trylock(&info->diag_cmd_lock)) {
+ pr_err("%s: Blocking concurrent access\n", __func__);
+ count = -EBUSY;
+ goto exit;
+ }
+
+ mess.dummy = 0;
+ mess.action = 0;
+ mess.msg_size = 0;
+
+ if (fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, true) < 0) {
+ res = ERROR_BUS_WR;
+ pr_err("%s: bus is not accessible.\n", __func__);
+ if (driver_test_buff)
+ limit = scnprintf(driver_test_buff, size, "{ %08X }\n",
+ res);
+ goto ERROR;
+ }
+
+ pbuf = kmalloc(count * sizeof(*pbuf), GFP_KERNEL);
+ if (!pbuf) {
+ res = ERROR_ALLOC;
+ goto ERROR;
+ }
+
+ funcToTest = kmalloc(((count + 1) / 3) * sizeof(*funcToTest),
+ GFP_KERNEL);
+ if (!funcToTest) {
+ res = ERROR_ALLOC;
+ goto ERROR;
+ }
+
+ /*for(temp = 0; temp<count; temp++){
+ * pr_err("p[%d] = %02X\n", temp, p[temp]);
+ * }*/
+ if (access_ok(buf, count) < OK ||
+ copy_from_user(pbuf, buf, count) != 0) {
+ res = ERROR_ALLOC;
+ goto END;
+ }
+
+ cmd = (u8 *)kmalloc_array(count, sizeof(u8), GFP_KERNEL);
+ if (cmd == NULL) {
+ res = ERROR_ALLOC;
+ pr_err("%s: Impossible allocate memory... ERROR %08X!\n",
+ __func__, res);
+ goto ERROR;
+ }
+
+ p = pbuf;
+ if (count > MESSAGE_MIN_HEADER_SIZE - 1 && p[0] == MESSAGE_START_BYTE) {
+ pr_info("Enter in Byte Mode!\n");
+ byte_call = 1;
+ mess.msg_size = (p[1] << 8) | p[2];
+ mess.counter = (p[3] << 8) | p[4];
+ mess.action = (p[5] << 8) | p[6];
+ pr_info("Message received: size = %d, counter_id = %d, action = %04X\n",
+ mess.msg_size, mess.counter, mess.action);
+ size = MESSAGE_MIN_HEADER_SIZE + 2; /* +2 error code */
+ if (count < mess.msg_size || p[count - 2] != MESSAGE_END_BYTE) {
+ pr_err("number of byte received or end byte wrong! msg_size = %d != %zu, last_byte = %02X != %02X ... ERROR %08X\n",
+ mess.msg_size, count, p[count - 1],
+ MESSAGE_END_BYTE, ERROR_OP_NOT_ALLOW);
+ res = ERROR_OP_NOT_ALLOW;
+ goto END;
+ } else {
+ numberParam = mess.msg_size - MESSAGE_MIN_HEADER_SIZE +
+ 1; /* +1 because put the internal
+ * op code */
+ size = MESSAGE_MIN_HEADER_SIZE + 2; /* +2 send also
+ * the first 2
+ * lsb of the
+ * error code */
+ switch (mess.action) {
+ case ACTION_READ:
+ /* numberParam =
+ * mess.msg_size-MESSAGE_MIN_HEADER_SIZE+1; */
+ cmd[0] = funcToTest[0] = CMD_READ_BYTE;
+ break;
+
+ case ACTION_WRITE:
+ cmd[0] = funcToTest[0] = CMD_WRITE_BYTE;
+ break;
+
+ case ACTION_WRITE_READ:
+ cmd[0] = funcToTest[0] = CMD_WRITEREAD_BYTE;
+ break;
+
+ case ACTION_GET_VERSION:
+ cmd[0] = funcToTest[0] = CMD_VERSION_BYTE;
+ break;
+
+ case ACTION_WRITETHENWRITEREAD:
+ cmd[0] = funcToTest[0] =
+ CMD_WRITETHENWRITEREAD_BYTE;
+ break;
+
+ case ACTION_WRITEU8UX:
+ cmd[0] = funcToTest[0] = CMD_WRITEU8UX_BYTE;
+ break;
+
+ case ACTION_WRITEREADU8UX:
+ cmd[0] = funcToTest[0] = CMD_WRITEREADU8UX_BYTE;
+ break;
+
+ case ACTION_WRITEU8UXTHENWRITEU8UX:
+ cmd[0] = funcToTest[0] =
+ CMD_WRITEU8UXTHENWRITEU8UX_BYTE;
+ break;
+
+ case ACTION_WRITEU8XTHENWRITEREADU8UX:
+ cmd[0] = funcToTest[0] =
+ CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE;
+ break;
+
+ case ACTION_GET_FW:
+ cmd[0] = funcToTest[0] = CMD_GETFWFILE_BYTE;
+ break;
+
+ case ACTION_GET_LIMIT:
+ cmd[0] = funcToTest[0] = CMD_GETLIMITSFILE_BYTE;
+ break;
+
+ default:
+ pr_err("Invalid Action = %d ... ERROR %08X\n",
+ mess.action, ERROR_OP_NOT_ALLOW);
+ res = ERROR_OP_NOT_ALLOW;
+ goto END;
+ }
+
+ if (numberParam - 1 != 0)
+ memcpy(&cmd[1], &p[7], numberParam - 1);
+ /* -1 because i need to exclude the cmd[0] */
+ }
+ } else {
+ if (((count + 1) / 3) >= 1) {
+ sscanf(p, "%02X ", &funcToTest[0]);
+ p += 3;
+ cmd[0] = (u8)funcToTest[0];
+ numberParam = 1;
+ } else {
+ res = ERROR_OP_NOT_ALLOW;
+ goto END;
+ }
+
+ pr_info("functionToTest[0] = %02X cmd[0]= %02X\n",
+ funcToTest[0], cmd[0]);
+ switch (funcToTest[0]) {
+ case CMD_GETFWFILE:
+ case CMD_GETLIMITSFILE:
+ if (count - 2 - 1 > 1) {
+ numberParam = 2;/** the first byte is an hex
+ * string coded in three byte
+ * (2 chars for hex and the
+ * space)
+ * and -1 for the space at the
+ * end */
+ sscanf(p, "%100s", path);
+ }
+ break;
+
+ default:
+ for (; numberParam < (count + 1) / 3; numberParam++) {
+ sscanf(p, "%02X ", &funcToTest[numberParam]);
+ p += 3;
+ cmd[numberParam] = (u8)funcToTest[numberParam];
+ pr_info("functionToTest[%d] = %02X cmd[%d]= %02X\n",
+ numberParam, funcToTest[numberParam],
+ numberParam, cmd[numberParam]);
+ }
+ }
+ }
+
+
+ fw.data = NULL;
+ lim.data = NULL;
+
+ pr_info("Number of Parameters = %d\n", numberParam);
+
+ /* elaborate input */
+ if (numberParam >= 1) {
+ switch (funcToTest[0]) {
+ case CMD_VERSION_BYTE:
+ pr_info("%s: Get Version Byte\n", __func__);
+ byteToRead = 2;
+ mess.dummy = 0;
+ readData = (u8 *)kmalloc(byteToRead * sizeof(u8),
+ GFP_KERNEL);
+ size += byteToRead;
+ if (readData != NULL) {
+ readData[0] = (u8)(FTS_TS_DRV_VER >> 24);
+ readData[1] = (u8)(FTS_TS_DRV_VER >> 16);
+ pr_info("%s: Version = %02X%02X\n",
+ __func__, readData[0], readData[1]);
+ res = OK;
+ } else {
+ res = ERROR_ALLOC;
+ pr_err("%s: Impossible allocate memory... ERROR %08X\n",
+ __func__, res);
+ }
+ break;
+
+
+ case CMD_VERSION:
+ byteToRead = 2 * sizeof(u32);
+ mess.dummy = 0;
+ readData = (u8 *)kmalloc(byteToRead * sizeof(u8),
+ GFP_KERNEL);
+ u32ToU8_be(FTS_TS_DRV_VER, readData);
+ fileSize = 0;
+ /* first two bytes bitmask of features enabled in the
+ * IC, second two bytes bitmask of features enabled in
+ * the driver */
+
+#ifdef FW_H_FILE
+ fileSize |= 0x00010000;
+#endif
+
+#ifdef LIMITS_H_FILE
+ fileSize |= 0x00020000;
+#endif
+
+#ifdef USE_ONE_FILE_NODE
+ fileSize |= 0x00040000;
+#endif
+
+#ifdef FW_UPDATE_ON_PROBE
+ fileSize |= 0x00080000;
+#endif
+
+#ifdef PRE_SAVED_METHOD
+ fileSize |= 0x00100000;
+#endif
+
+#ifdef USE_GESTURE_MASK
+ fileSize |= 0x00100000;
+#endif
+
+#ifdef I2C_INTERFACE
+ fileSize |= 0x00200000;
+#endif
+
+#ifdef PHONE_KEY /* it is a feature enabled in the config of the chip */
+ fileSize |= 0x00000100;
+#endif
+
+#ifdef GESTURE_MODE
+ fromIDtoMask(FEAT_SEL_GESTURE, (u8 *)&fileSize, 4);
+#endif
+
+
+#ifdef GRIP_MODE
+ fromIDtoMask(FEAT_SEL_GRIP, (u8 *)&fileSize, 4);
+#endif
+
+#ifdef CHARGER_MODE
+ fromIDtoMask(FEAT_SEL_CHARGER, (u8 *)&fileSize, 4);
+#endif
+
+#ifdef GLOVE_MODE
+ fromIDtoMask(FEAT_SEL_GLOVE, (u8 *)&fileSize, 4);
+#endif
+
+
+#ifdef COVER_MODE
+ fromIDtoMask(FEAT_SEL_COVER, (u8 *)&fileSize, 4);
+#endif
+
+#ifdef STYLUS_MODE
+ fromIDtoMask(FEAT_SEL_STYLUS, (u8 *)&fileSize, 4);
+#endif
+
+ u32ToU8_be(fileSize, &readData[4]);
+ res = OK;
+ size += (byteToRead * sizeof(u8));
+ break;
+
+ case CMD_WRITEREAD:
+ case CMD_WRITEREAD_BYTE:
+ if (numberParam >= 5) { /* need to pass: cmd[0] cmd[1]
+ * … cmd[cmdLength-1]
+ * byteToRead1 byteToRead0
+ * dummyByte */
+ temp = numberParam - 4;
+ if (cmd[numberParam - 1] == 0)
+ mess.dummy = 0;
+ else
+ mess.dummy = 1;
+
+ u8ToU16_be(&cmd[numberParam - 3], &byteToRead);
+ pr_info("bytesToRead = %d\n",
+ byteToRead + mess.dummy);
+
+ readData = (u8 *)kmalloc((byteToRead +
+ mess.dummy) *
+ sizeof(u8),
+ GFP_KERNEL);
+ res = fts_writeRead_heap(&cmd[1], temp,
+ readData, byteToRead + mess.dummy);
+ size += (byteToRead * sizeof(u8));
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_WRITE:
+ case CMD_WRITE_BYTE:
+ if (numberParam >= 2) { /* need to pass: cmd[0] cmd[1]
+ * … cmd[cmdLength-1] */
+ temp = numberParam - 1;
+
+ res = fts_write_heap(&cmd[1], temp);
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READ:
+ case CMD_READ_BYTE:
+ if (numberParam >= 3) { /* need to pass: byteToRead1
+ * byteToRead0 (optional)
+ * dummyByte */
+ if (numberParam == 3 ||
+ (numberParam == 4 &&
+ cmd[numberParam - 1] == 0))
+ mess.dummy = 0;
+ else
+ mess.dummy = 1;
+ u8ToU16_be(&cmd[1], &byteToRead);
+ readData = (u8 *)kmalloc((byteToRead +
+ mess.dummy) *
+ sizeof(u8),
+ GFP_KERNEL);
+ res = fts_read_heap(readData, byteToRead +
+ mess.dummy);
+ size += (byteToRead * sizeof(u8));
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_WRITETHENWRITEREAD:
+ case CMD_WRITETHENWRITEREAD_BYTE:
+ /* need to pass: cmdSize1 cmdSize2 cmd1[0] cmd1[1] …
+ * cmd1[cmdSize1-1] cmd2[0] cmd2[1] … cmd2[cmdSize2-1]
+ * byteToRead1 byteToRead0 */
+ if (numberParam >= 6) {
+ u8ToU16_be(&cmd[numberParam - 2], &byteToRead);
+ readData = (u8 *)kmalloc(byteToRead *
+ sizeof(u8),
+ GFP_KERNEL);
+ res = fts_writeThenWriteRead_heap(
+ &cmd[3], cmd[1],
+ &cmd[3 + (int)cmd[1]], cmd[2],
+ readData, byteToRead);
+ size += (byteToRead * sizeof(u8));
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_WRITEU8UX:
+ case CMD_WRITEU8UX_BYTE:
+ /* need to pass:
+ * cmd addrSize addr[0] … addr[addrSize-1]
+ * data[0] data[1] … */
+ if (numberParam >= 4) {
+ if (cmd[2] <= sizeof(u64)) {
+ u8ToU64_be(&cmd[3], &addr, cmd[2]);
+ pr_info("addr = %llx\n", addr);
+ res = fts_writeU8UX(cmd[1], cmd[2],
+ addr,
+ &cmd[3 + cmd[2]],
+ (numberParam - cmd[2] - 3));
+ } else {
+ pr_err("Wrong address size!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ case CMD_WRITEREADU8UX:
+ case CMD_WRITEREADU8UX_BYTE:
+ /* need to pass:
+ * cmd addrSize addr[0] … addr[addrSize-1]
+ * byteToRead1 byteToRead0 hasDummyByte */
+ if (numberParam >= 6) {
+ if (cmd[2] <= sizeof(u64)) {
+ u8ToU64_be(&cmd[3], &addr, cmd[2]);
+ u8ToU16_be(&cmd[numberParam - 3],
+ &byteToRead);
+ readData = (u8 *)kmalloc(byteToRead *
+ sizeof(u8),
+ GFP_KERNEL);
+ pr_info("addr = %llx byteToRead = %d\n",
+ addr, byteToRead);
+ res = fts_writeReadU8UX(cmd[1], cmd[2],
+ addr, readData,
+ byteToRead,
+ cmd[numberParam - 1]);
+ size += (byteToRead * sizeof(u8));
+ } else {
+ pr_err("Wrong address size!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_WRITEU8UXTHENWRITEU8UX:
+ case CMD_WRITEU8UXTHENWRITEU8UX_BYTE:
+ /* need to pass:
+ * cmd1 addrSize1 cmd2 addrSize2 addr[0] …
+ * addr[addrSize1+addrSize2-1] data[0] data[1] … */
+ if (numberParam >= 6) {
+ if ((cmd[2] + cmd[4]) <= sizeof(u64)) {
+ u8ToU64_be(&cmd[5], &addr, cmd[2] +
+ cmd[4]);
+
+ pr_info("addr = %llx\n", addr);
+ res = fts_writeU8UXthenWriteU8UX(cmd[1],
+ cmd[2], cmd[3],
+ cmd[4], addr,
+ &cmd[5 + cmd[2] + cmd[4]],
+ (numberParam - cmd[2]
+ - cmd[4] - 5));
+ } else {
+ pr_err("Wrong address size!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_WRITEU8UXTHENWRITEREADU8UX:
+ case CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE:
+ /* need to pass:
+ * cmd1 addrSize1 cmd2 addrSize2 addr[0] …
+ * addr[addrSize1+addrSize2-1] byteToRead1 byteToRead0
+ * hasDummybyte */
+ if (numberParam >= 8) {
+ if ((cmd[2] + cmd[4]) <= sizeof(u64)) {
+ u8ToU64_be(&cmd[5], &addr, cmd[2] +
+ cmd[4]);
+ pr_info("%s: cmd[5] = %02X, addr = %llx\n",
+ __func__, cmd[5], addr);
+ u8ToU16_be(&cmd[numberParam - 3],
+ &byteToRead);
+ readData = (u8 *)kmalloc(byteToRead *
+ sizeof(u8),
+ GFP_KERNEL);
+ res = fts_writeU8UXthenWriteReadU8UX(
+ cmd[1], cmd[2], cmd[3], cmd[4],
+ addr,
+ readData, byteToRead,
+ cmd[numberParam - 1]);
+ size += (byteToRead * sizeof(u8));
+ } else {
+ pr_err("Wrong total address size!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_CHANGE_OUTPUT_MODE:
+ /* need to pass: bin_output */
+ if (numberParam >= 2) {
+ bin_output = cmd[1];
+ pr_info("Setting Scriptless output mode: %d\n",
+ bin_output);
+ res = OK;
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FWWRITE:
+ if (numberParam >= 3) { /* need to pass: cmd[0] cmd[1]
+ * … cmd[cmdLength-1] */
+ if (numberParam >= 2) {
+ temp = numberParam - 1;
+ res = fts_writeFwCmd_heap(&cmd[1],
+ temp);
+ } else {
+ pr_err("Wrong parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_INTERRUPT:
+ /* need to pass: enable */
+ if (numberParam >= 2) {
+ if (cmd[1] == 1)
+ res = fts_enableInterrupt();
+ else
+ res = fts_disableInterrupt();
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ case CMD_READCONFIG:
+ if (numberParam == 5) { /* need to pass: addr[0]
+ * addr[1] byteToRead1
+ * byteToRead0 */
+ byteToRead = ((funcToTest[3] << 8) |
+ funcToTest[4]);
+ readData = (u8 *)kmalloc(byteToRead *
+ sizeof(u8),
+ GFP_KERNEL);
+ res = readConfig((u16)((((u8)funcToTest[1] &
+ 0x00FF) << 8) +
+ ((u8)funcToTest[2] &
+ 0x00FF)),
+ readData, byteToRead);
+ size += (byteToRead * sizeof(u8));
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_POLLFOREVENT:
+ if (numberParam >= 5) { /* need to pass: eventLength
+ * event[0] event[1] …
+ * event[eventLength-1]
+ * timeTowait1 timeTowait0 */
+ temp = (int)funcToTest[1];
+ if (numberParam == 5 + (temp - 1) &&
+ temp != 0) {
+ readData = (u8 *)kmalloc(
+ FIFO_EVENT_SIZE * sizeof(u8),
+ GFP_KERNEL);
+ res = pollForEvent(
+ (int *)&funcToTest[2], temp,
+ readData,
+ ((funcToTest[temp + 2] &
+ 0x00FF) << 8) +
+ (funcToTest[temp + 3] &
+ 0x00FF));
+ if (res >= OK)
+ res = OK; /* pollForEvent
+ * return the
+ * number of
+ * error found
+ * */
+ size += (FIFO_EVENT_SIZE * sizeof(u8));
+ byteToRead = FIFO_EVENT_SIZE;
+ } else {
+ pr_err("Wrong parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SYSTEMRESET:
+ res = fts_system_reset();
+
+ break;
+
+ case CMD_READSYSINFO:
+ if (numberParam == 2) /* need to pass: doRequest */
+ res = readSysInfo(funcToTest[1]);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_CLEANUP:/* TOUCH ENABLE/DISABLE */
+ if (numberParam == 2) /* need to pass: enableTouch */
+ res = cleanUp(funcToTest[1]);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_GETFORCELEN: /* read number Tx channels */
+ temp = getForceLen();
+ if (temp < OK)
+ res = temp;
+ else {
+ size += (1 * sizeof(u8));
+ res = OK;
+ }
+ break;
+
+ case CMD_GETSENSELEN: /* read number Rx channels */
+ temp = getSenseLen();
+ if (temp < OK)
+ res = temp;
+ else {
+ size += (1 * sizeof(u8));
+ res = OK;
+ }
+ break;
+
+
+ case CMD_GETMSFRAME:
+ if (numberParam == 2) {
+ pr_info("Get 1 MS Frame\n");
+ setScanMode(SCAN_MODE_ACTIVE, 0xFF);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ /* flushFIFO(); //delete the events related to
+ * some touch (allow to call this function while
+ * touching the screen without having a flooding
+ * of the FIFO) */
+ res = getMSFrame3((MSFrameType)cmd[1],
+ &frameMS);
+ if (res < 0)
+ pr_err("Error while taking the MS frame... ERROR %08X\n",
+ res);
+
+ else {
+ pr_info("The frame size is %d words\n",
+ res);
+ size += (res * sizeof(short) + 2);
+ /* +2 to add force and sense channels
+ * set res to OK because if getMSFrame
+ * is successful
+ * res = number of words read
+ */
+ res = OK;
+ print_frame_short("MS frame =",
+ array1dTo2d_short(
+ frameMS.node_data,
+ frameMS.node_data_size,
+ frameMS.header.sense_node),
+ frameMS.header.force_node,
+ frameMS.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ /*read self raw*/
+ case CMD_GETSSFRAME:
+ if (numberParam == 2) {
+ pr_info("Get 1 SS Frame\n");
+ /* flushFIFO(); //delete the events related to
+ * some touch (allow to call this function while
+ * touching the screen without having a flooding
+ * of the FIFO) */
+ setScanMode(SCAN_MODE_ACTIVE, 0xFF);
+ mdelay(WAIT_FOR_FRESH_FRAMES);
+ setScanMode(SCAN_MODE_ACTIVE, 0x00);
+ mdelay(WAIT_AFTER_SENSEOFF);
+ res = getSSFrame3((SSFrameType)cmd[1],
+ &frameSS);
+
+ if (res < OK)
+ pr_err("Error while taking the SS frame... ERROR %08X\n",
+ res);
+
+ else {
+ pr_info("The frame size is %d words\n",
+ res);
+ size += (res * sizeof(short) + 2);
+ /* +2 to add force and sense channels
+ * set res to OK because if getMSFrame
+ * is successful
+ * res = number of words read
+ */
+ res = OK;
+ print_frame_short("SS force frame =",
+ array1dTo2d_short(
+ frameSS.force_data,
+ frameSS.header.force_node,
+ 1),
+ frameSS.header.force_node, 1);
+ print_frame_short("SS sense frame =",
+ array1dTo2d_short(
+ frameSS.sense_data,
+ frameSS.header.sense_node,
+ frameSS.header.sense_node),
+ 1,
+ frameSS.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_REQCOMPDATA: /* request comp data */
+ if (numberParam == 2) {
+ pr_info("Requesting Compensation Data\n");
+ res = requestCompensationData(cmd[1]);
+
+ if (res < OK)
+ pr_err("Error requesting compensation data ERROR %08X\n",
+ res);
+ else
+ pr_info("Requesting Compensation Data Finished!\n");
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READCOMPDATAHEAD: /* read comp data header */
+ if (numberParam == 2) {
+ pr_info("Requesting Compensation Data\n");
+ res = requestCompensationData(cmd[1]);
+ if (res < OK)
+ pr_err("Error requesting compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_info("Requesting Compensation Data Finished!\n");
+ res = readCompensationDataHeader(
+ (u8)funcToTest[1], &dataHead,
+ &address);
+ if (res < OK)
+ pr_err("Read Compensation Data Header ERROR %08X\n",
+ res);
+ else {
+ pr_info("Read Compensation Data Header OK!\n");
+ size += (1 * sizeof(u8));
+ }
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ case CMD_READMSCOMPDATA:/* read mutual comp data */
+ if (numberParam == 2) {
+ pr_info("Get MS Compensation Data\n");
+ res = readMutualSenseCompensationData(cmd[1],
+ &compData);
+
+ if (res < OK)
+ pr_err("Error reading MS compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_info("MS Compensation Data Reading Finished!\n");
+ size = ((compData.node_data_size + 10) *
+ sizeof(i8));
+ print_frame_i8("MS Data (Cx2) =",
+ array1dTo2d_i8(
+ compData.node_data,
+ compData.node_data_size,
+ compData.header.sense_node),
+ compData.header.force_node,
+ compData.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READSSCOMPDATA:
+ if (numberParam == 2) { /* read self comp data */
+ pr_info("Get SS Compensation Data...\n");
+ res = readSelfSenseCompensationData(cmd[1],
+ &comData);
+ if (res < OK)
+ pr_err("Error reading SS compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_info("SS Compensation Data Reading Finished!\n");
+ size = ((comData.header.force_node +
+ comData.header.sense_node) *
+ 2 + 13) *
+ sizeof(i8);
+ print_frame_i8("SS Data Ix2_fm = ",
+ array1dTo2d_i8(
+ comData.ix2_fm,
+ comData.header.force_node,
+ comData.header.force_node),
+ 1,
+ comData.header.force_node);
+ print_frame_i8("SS Data Cx2_fm = ",
+ array1dTo2d_i8(
+ comData.cx2_fm,
+ comData.header.force_node,
+ comData.header.force_node),
+ 1,
+ comData.header.force_node);
+ print_frame_i8("SS Data Ix2_sn = ",
+ array1dTo2d_i8(
+ comData.ix2_sn,
+ comData.header.sense_node,
+ comData.header.sense_node),
+ 1,
+ comData.header.sense_node);
+ print_frame_i8("SS Data Cx2_sn = ",
+ array1dTo2d_i8(
+ comData.cx2_sn,
+ comData.header.sense_node,
+ comData.header.sense_node),
+ 1,
+ comData.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READTOTMSCOMPDATA: /* read mutual comp data */
+ if (numberParam == 2) {
+ pr_info("Get TOT MS Compensation Data\n");
+ res = readTotMutualSenseCompensationData(cmd[1],
+ &totCompData);
+
+ if (res < OK)
+ pr_err("Error reading TOT MS compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_info("TOT MS Compensation Data Reading Finished!\n");
+ size = (totCompData.node_data_size *
+ sizeof(short) + 9);
+ print_frame_short("MS Data (TOT Cx) =",
+ array1dTo2d_short(
+ totCompData.node_data,
+ totCompData.node_data_size,
+ totCompData.header.sense_node),
+ totCompData.header.force_node,
+ totCompData.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READTOTSSCOMPDATA:
+ if (numberParam == 2) { /* read self comp data */
+ pr_info("Get TOT SS Compensation Data...\n");
+ res = readTotSelfSenseCompensationData(cmd[1],
+ &totComData);
+ if (res < OK)
+ pr_err("Error reading TOT SS compensation data ERROR %08X\n",
+ res);
+ else {
+ pr_info("TOT SS Compensation Data Reading Finished!\n");
+ size = ((totComData.header.force_node +
+ totComData.header.sense_node) *
+ 2 *
+ sizeof(short) + 9);
+ print_frame_u16("SS Data TOT Ix_fm = ",
+ array1dTo2d_u16(
+ totComData.ix_fm,
+ totComData.header.force_node,
+ totComData.header.force_node),
+ 1,
+ totComData.header.force_node);
+ print_frame_short(
+ "SS Data TOT Cx_fm = ",
+ array1dTo2d_short(
+ totComData.cx_fm,
+ totComData.header.force_node,
+ totComData.header.force_node),
+ 1,
+ totComData.header.force_node);
+ print_frame_u16("SS Data TOT Ix_sn = ",
+ array1dTo2d_u16(
+ totComData.ix_sn,
+ totComData.header.sense_node,
+ totComData.header.sense_node),
+ 1,
+ totComData.header.sense_node);
+ print_frame_short(
+ "SS Data TOT Cx_sn = ",
+ array1dTo2d_short(
+ totComData.cx_sn,
+ totComData.header.sense_node,
+ totComData.header.sense_node),
+ 1,
+ totComData.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READSENSCOEFF:
+ /* read MS and SS Sensitivity Coefficients */
+ pr_info("Get Sensitivity Calibration Coefficients...\n");
+ res = readSensitivityCoefficientsData(&msCoeff,
+ &ssCoeff);
+ if (res < OK)
+ pr_err("Error reading Sensitivity Calibration Coefficients ERROR %08X\n",
+ res);
+ else {
+ pr_info("Sensitivity Calibration Coefficients Reading Finished!\n");
+ size += (((msCoeff.node_data_size) +
+ ssCoeff.header.force_node +
+ ssCoeff.header.sense_node) *
+ sizeof(u8) + 4);
+ print_frame_u8("MS Sensitivity Coeff = ",
+ array1dTo2d_u8(msCoeff.ms_coeff,
+ msCoeff.
+ node_data_size,
+ msCoeff.header.
+ sense_node),
+ msCoeff.header.force_node,
+ msCoeff.header.sense_node);
+ print_frame_u8("SS Sensitivity Coeff force = ",
+ array1dTo2d_u8(
+ ssCoeff.ss_force_coeff,
+ ssCoeff.header.
+ force_node, 1),
+ ssCoeff.header.force_node, 1);
+ print_frame_u8("SS Sensitivity Coeff sense = ",
+ array1dTo2d_u8(
+ ssCoeff.ss_sense_coeff,
+ ssCoeff.header.
+ sense_node,
+ ssCoeff.header.
+ sense_node), 1,
+ ssCoeff.header.sense_node);
+ }
+ break;
+
+ case CMD_GETFWVER:
+ size += (EXTERNAL_RELEASE_INFO_SIZE)*sizeof(u8);
+ break;
+
+ case CMD_FLASHUNLOCK:
+ res = flash_unlock();
+ if (res < OK)
+ pr_err("Impossible Unlock Flash ERROR %08X\n",
+ res);
+ else
+ pr_info("Flash Unlock OK!\n");
+ break;
+
+ case CMD_READFWFILE:
+ if (numberParam == 2) { /* read fw file */
+ pr_info("Reading FW File...\n");
+ res = readFwFile(info->board->fw_name, &fw,
+ funcToTest[1]);
+ if (res < OK)
+ pr_err("Error reading FW File ERROR %08X\n",
+ res);
+ else
+ pr_info("Read FW File Finished!\n");
+ kfree(fw.data);
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FLASHPROCEDURE:
+ if (numberParam == 3) { /* flashing procedure */
+ pr_info("Starting Flashing Procedure...\n");
+ res = flashProcedure(info->board->fw_name,
+ cmd[1],
+ cmd[2]);
+ if (res < OK)
+ pr_err("Error during flash procedure ERROR %08X\n",
+ res);
+ else
+ pr_info("Flash Procedure Finished!\n");
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FLASHERASEUNLOCK:
+ res = flash_erase_unlock();
+ if (res < OK)
+ pr_err("Error during flash erase unlock... ERROR %08X\n",
+ res);
+ else
+ pr_info("Flash Erase Unlock Finished!\n");
+ break;
+
+ case CMD_FLASHERASEPAGE:
+ if (numberParam == 2) { /* need to pass: keep_cx */
+ pr_info("Starting Flashing Page Erase...\n");
+ res = flash_erase_page_by_page(cmd[1]);
+ if (res < OK)
+ pr_err("Error during flash page erase... ERROR %08X\n",
+ res);
+ else
+ pr_info("Flash Page Erase Finished!\n");
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ /*ITO TEST*/
+ case CMD_ITOTEST:
+ res = production_test_ito(LIMITS_FILE, &tests);
+ break;
+
+ /*Initialization*/
+ case CMD_INITTEST:
+ if (numberParam == 2)
+ res = production_test_initialization(cmd[1]);
+
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ case CMD_MSRAWTEST: /* MS Raw DATA TEST */
+ if (numberParam == 2) /* need to specify if stopOnFail
+ * */
+ res = production_test_ms_raw(LIMITS_FILE,
+ cmd[1], &tests);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_MSINITDATATEST:/* MS CX DATA TEST */
+ if (numberParam == 2) /* need stopOnFail */
+ res = production_test_ms_cx(LIMITS_FILE, cmd[1],
+ &tests);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SSRAWTEST: /* SS RAW DATA TEST */
+ if (numberParam == 2) /* need stopOnFail */
+ res = production_test_ss_raw(LIMITS_FILE,
+ cmd[1], &tests);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SSINITDATATEST:/* SS IX CX DATA TEST */
+ if (numberParam == 2) /* need stopOnFail */
+ res = production_test_ss_ix_cx(LIMITS_FILE,
+ cmd[1], &tests);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ /*PRODUCTION TEST*/
+ case CMD_MAINTEST:
+ if (numberParam == 3) /* need to specify if stopOnFail
+ * and saveInit */
+ res = production_test_main(LIMITS_FILE, cmd[1],
+ cmd[2], &tests);
+ else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FREELIMIT:
+ res = freeCurrentLimitsFile();
+ break;
+
+ case CMD_POWERCYCLE:
+ res = fts_chip_powercycle(info);
+ break;
+
+ case CMD_GETLIMITSFILE:
+ /* need to pass: path(optional) return error code +
+ * number of byte read otherwise GUI could not now how
+ * many byte read */
+ if (numberParam >= 1) {
+ lim.data = NULL;
+ lim.size = 0;
+ if (numberParam == 1)
+ res = getLimitsFile(LIMITS_FILE, &lim);
+ else
+ res = getLimitsFile(path, &lim);
+ readData = lim.data;
+ fileSize = lim.size;
+ size += (fileSize * sizeof(u8));
+ if (byte_call == 1)
+ size += sizeof(u32); /* transmit as
+ * first 4 bytes
+ * the size */
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_GETLIMITSFILE_BYTE:
+ /* need to pass: byteToRead1 byteToRead0 */
+ if (numberParam >= 3) {
+ lim.data = NULL;
+ lim.size = 0;
+
+ u8ToU16_be(&cmd[1], &byteToRead);
+ addr = ((u64)byteToRead) * 4; /* number of
+ * words */
+
+ res = getLimitsFile(LIMITS_FILE, &lim);
+
+ readData = lim.data;
+ fileSize = lim.size;
+
+ if (fileSize > addr) {
+ pr_err("Limits dimension expected by Host is less than actual size: expected = %d, real = %d\n",
+ byteToRead, fileSize);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ size += (addr * sizeof(u8));
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_GETFWFILE:
+ /* need to pass: from (optional) otherwise select the
+ * approach chosen at compile time */
+ if (numberParam >= 1) {
+ if (numberParam == 1)
+ res = getFWdata(info->board->fw_name,
+ &readData, &fileSize);
+ else
+ res = getFWdata(path, &readData,
+ &fileSize);
+
+ size += (fileSize * sizeof(u8));
+ if (byte_call == 1)
+ size += sizeof(u32); /* transmit as
+ * first 4 bytes
+ * the size */
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_GETFWFILE_BYTE:
+ /* need to pass: byteToRead1 byteToRead0 */
+ if (numberParam == 3) {
+ u8ToU16_be(&cmd[1], &byteToRead);
+ addr = ((u64)byteToRead) * 4; /* number of
+ * words */
+ res = getFWdata(info->board->fw_name, &readData,
+ &fileSize);
+ if (fileSize > addr) {
+ pr_err("FW dimension expected by Host is less than actual size: expected = %d, real = %d\n",
+ byteToRead, fileSize);
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ size += (addr * sizeof(u8)); /* return always
+ * the amount
+ * requested by
+ * host, if real
+ * size is
+ * smaller, the
+ * data are
+ * padded to
+ * zero */
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ /* finish all the diagnostic command with a goto ERROR in order
+ * to skip the modification on driver_test_buff
+ * remember to set properly the limit and printed variables in
+ * order to make the seq_file logic to work */
+ case CMD_DIAGNOSTIC:
+ index = 0;
+ size = 0;
+ fileSize = 256 * 1024 * sizeof(char);
+ driver_test_buff = (u8 *)kzalloc(fileSize, GFP_KERNEL);
+ readData = (u8 *)kmalloc((ERROR_DUMP_ROW_SIZE *
+ ERROR_DUMP_COL_SIZE) *
+ sizeof(u8), GFP_KERNEL);
+ if (driver_test_buff == NULL || readData == NULL) {
+ res = ERROR_ALLOC;
+ pr_err("Impossible allocate memory for buffers! ERROR %08X!\n",
+ res);
+ goto END;
+ }
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "DIAGNOSTIC TEST:\n1) I2C Test: ");
+ index += j;
+
+ res = fts_writeReadU8UX(FTS_CMD_HW_REG_R,
+ ADDR_SIZE_HW_REG, ADDR_DCHIP_ID,
+ (u8 *)&temp, 2,
+ DUMMY_HW_REG);
+ if (res < OK) {
+ pr_err("Error during I2C test: ERROR %08X!\n",
+ res);
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index, "ERROR %08X\n",
+ res);
+ index += j;
+ res = ERROR_OP_NOT_ALLOW;
+ goto END_DIAGNOSTIC;
+ }
+
+ temp &= 0xFFFF;
+ pr_info("Chip ID = %04X!\n", temp);
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "DATA = %04X, expected = %02X%02X\n",
+ temp, DCHIP_ID_1,
+ DCHIP_ID_0);
+ index += j;
+ if (temp != ((DCHIP_ID_1 << 8) | DCHIP_ID_0)) {
+ pr_err("Wrong CHIP ID, Diagnostic failed!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ goto END_DIAGNOSTIC;
+ }
+
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "Present Driver Mode: %08X\n",
+ info->mode);
+ index += j;
+
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "2) FW running: Sensing On...");
+ index += j;
+ pr_info("Sensing On!\n");
+ readData[0] = FTS_CMD_SCAN_MODE;
+ readData[1] = SCAN_MODE_ACTIVE;
+ readData[2] = 0x1;
+ fts_write_heap(readData, 3);
+ res = checkEcho(readData, 3);
+ if (res < OK) {
+ pr_err("No Echo received.. ERROR %08X !\n",
+ res);
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "No echo found... ERROR %08X!\n",
+ res);
+ index += j;
+ goto END_DIAGNOSTIC;
+ } else {
+ pr_info("Echo FOUND... OK!\n");
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "Echo FOUND... OK!\n");
+ index += j;
+ }
+
+ pr_info("Reading Frames...!\n");
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "3) Read Frames:\n");
+ index += j;
+ for (temp = 0; temp < DIAGNOSTIC_NUM_FRAME; temp++) {
+ pr_info("Iteration n. %d...\n", temp + 1);
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "Iteration n. %d...\n",
+ temp + 1);
+ index += j;
+ for (addr = 0; addr < 3; addr++) {
+ switch (addr) {
+ case 0:
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "MS RAW FRAME =");
+ index += j;
+ res |= getMSFrame3(MS_RAW,
+ &frameMS);
+ break;
+ case 2:
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "MS STRENGTH FRAME =");
+ index += j;
+ res |= getMSFrame3(MS_STRENGTH,
+ &frameMS);
+ break;
+ case 1:
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "MS BASELINE FRAME =");
+ index += j;
+ res |= getMSFrame3(MS_BASELINE,
+ &frameMS);
+ break;
+ }
+ if (res < OK) {
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "No data! ERROR %08X\n",
+ res);
+ index += j;
+ } else {
+ for (address = 0; address <
+ frameMS.node_data_size;
+ address++) {
+ if (address %
+ frameMS.header.
+ sense_node == 0) {
+ j = scnprintf(
+ &driver_test_buff
+ [index],
+ fileSize -
+ index,
+ "\n");
+ index += j;
+ }
+ j = scnprintf(
+ &driver_test_buff
+ [index],
+ fileSize - index,
+ "%5d, ",
+ frameMS.
+ node_data[address]);
+ index += j;
+ }
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index, "\n");
+ index += j;
+ }
+ if (frameMS.node_data != NULL)
+ kfree(frameMS.node_data);
+ }
+ for (addr = 0; addr < 3; addr++) {
+ switch (addr) {
+ case 0:
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "SS RAW FRAME =\n");
+ index += j;
+ res |= getSSFrame3(SS_RAW,
+ &frameSS);
+ break;
+ case 2:
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "SS STRENGTH FRAME =\n");
+ index += j;
+ res |= getSSFrame3(SS_STRENGTH,
+ &frameSS);
+ break;
+ case 1:
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "SS BASELINE FRAME =\n");
+ index += j;
+ res |= getSSFrame3(SS_BASELINE,
+ &frameSS);
+ break;
+ }
+ if (res < OK) {
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "No data! ERROR %08X\n",
+ res);
+ index += j;
+ } else {
+ int num;
+ short *data;
+
+ num = frameSS.header.force_node;
+ data = frameSS.force_data;
+ for (address = 0;
+ address < num;
+ address++) {
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "%d\n",
+ data[address]);
+ index += j;
+ }
+
+ num = frameSS.header.sense_node;
+ data = frameSS.sense_data;
+ for (address = 0;
+ address < num;
+ address++) {
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "%d, ",
+ data[address]);
+ index += j;
+ }
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index, "\n");
+ index += j;
+ }
+ if (frameSS.force_data != NULL)
+ kfree(frameSS.force_data);
+ if (frameSS.sense_data != NULL)
+ kfree(frameSS.sense_data);
+ }
+ }
+
+
+ pr_info("Reading error info...\n");
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "4) FW INFO DUMP: ");
+ index += j;
+ temp = dumpErrorInfo(readData, ERROR_DUMP_ROW_SIZE *
+ ERROR_DUMP_COL_SIZE);
+ /* OR to detect if there are failures also in the
+ * previous reading of frames and write the correct
+ * result */
+ if (temp < OK) {
+ pr_err("Error during dump: ERROR %08X!\n",
+ res);
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index, "ERROR %08X\n",
+ temp);
+ index += j;
+ } else {
+ pr_info("DUMP OK!\n");
+ for (temp = 0; temp < ERROR_DUMP_ROW_SIZE *
+ ERROR_DUMP_COL_SIZE; temp++) {
+ if (temp % ERROR_DUMP_COL_SIZE == 0) {
+ j = scnprintf(
+ &driver_test_buff[index],
+ fileSize - index,
+ "\n%2d - ",
+ temp / ERROR_DUMP_COL_SIZE);
+ index += j;
+ }
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index, "%02X ",
+ readData[temp]);
+ index += j;
+ }
+ }
+ res |= temp;
+
+END_DIAGNOSTIC:
+ if (res < OK) {
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "\nRESULT = FAIL\n");
+ index += j;
+ } else {
+ j = scnprintf(&driver_test_buff[index],
+ fileSize - index,
+ "\nRESULT = FINISHED\n");
+ index += j;
+ }
+ /* the sting is already terminated with the null char by
+ * scnprintf */
+ limit = index;
+ printed = 0;
+ goto ERROR;
+ break;
+
+ case CMD_CHANGE_SAD:
+ res = changeSAD(cmd[1]);
+ break;
+
+ case CMD_TRIGGER_FORCECAL:
+ cmd[0] = CAL_MS_TOUCH | CAL_SS_TOUCH;
+ cmd[1] = 0x00;
+ fts_disableInterrupt();
+ res = writeSysCmd(SYS_CMD_FORCE_CAL, cmd, 2);
+ res |= fts_enableInterrupt();
+ if (res < OK)
+ pr_err("can not trigger Force Cal! ERROR %08X\n",
+ res);
+ else
+ pr_info("MS and SS force cal triggered!\n");
+ break;
+
+ case CMD_BASELINE_ADAPTATION:
+ /* need to pass: enable */
+ if (numberParam == 2) {
+ if (cmd[1] == 0x01)
+ pr_info("Enabling Baseline adaptation...\n");
+ else {
+ pr_info("Disabling Baseline adaptation...\n");
+ cmd[1] = 0x00; /* set to zero to
+ * disable baseline
+ * adaptation */
+ }
+
+ res = writeConfig(ADDR_CONFIG_AUTOCAL, &cmd[1],
+ 1);
+ if (res < OK)
+ pr_err("Baseline adaptation operation FAILED! ERROR %08X\n",
+ res);
+ else
+ pr_info("Baseline adaptation operation OK!\n");
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FREQ_HOP:
+ /* need to pass: enable */
+ if (numberParam == 2) {
+ pr_info("Reading MNM register...\n");
+ res = readConfig(ADDR_CONFIG_MNM, &cmd[2], 1);
+ if (res < OK) {
+ pr_err("Reading MNM register... ERROR %08X!\n",
+ res);
+ break;
+ }
+
+ if (cmd[1] == 0x01) {
+ pr_info("Enabling Frequency Hopping... %02X => %02X\n",
+ cmd[2], cmd[2] | 0x01);
+ cmd[2] |= 0x01; /* set bit 0 to enable
+ * Frequency Hopping */
+ } else {
+ pr_info("Disabling Frequency Hopping... %02X => %02X\n",
+ cmd[2], cmd[2] & (~0x01));
+ cmd[2] &= (~0x01); /* reset bit 0
+ * to disable
+ * Frequency
+ * Hopping */
+ }
+
+ res = writeConfig(ADDR_CONFIG_MNM, &cmd[2], 1);
+ if (res < OK)
+ pr_err("Frequency Hopping operation FAILED! ERROR %08X\n",
+ res);
+ else
+ pr_info("Frequency Hopping operation OK!\n");
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_READ_SYNC_FRAME:
+ /* need to pass: frameType (this parameter can be
+ * LOAD_SYNC_FRAME_STRENGTH or LOAD_SYNC_FRAME_BASELINE)
+ * */
+ if (numberParam == 2) {
+ pr_info("Reading Sync Frame...\n");
+ res = getSyncFrame(cmd[1], &frameMS, &frameSS);
+ if (res < OK)
+ pr_err("Error while taking the Sync Frame frame... ERROR %08X\n",
+ res);
+
+ else {
+ pr_info("The total frames size is %d words\n",
+ res);
+ size += (res * sizeof(short) + 4);
+ /* +4 to add force and sense channels
+ * for MS and SS
+ * set res to OK because if getSyncFrame
+ * is successful
+ * res = number of words read
+ */
+ res = OK;
+
+ print_frame_short("MS frame =",
+ array1dTo2d_short(
+ frameMS.node_data,
+ frameMS.node_data_size,
+ frameMS.header.sense_node),
+ frameMS.header.force_node,
+ frameMS.header.sense_node);
+ print_frame_short("SS force frame =",
+ array1dTo2d_short(
+ frameSS.force_data,
+ frameSS.header.force_node,
+ 1),
+ frameSS.header.force_node, 1);
+ print_frame_short("SS sense frame =",
+ array1dTo2d_short(
+ frameSS.sense_data,
+ frameSS.header.sense_node,
+ frameSS.header.sense_node),
+ 1,
+ frameSS.header.sense_node);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_SET_OPERATING_FREQ:
+ /* need to pass: freq3 freq2 freq1 freq0 */
+ if (numberParam == 5) {
+ res = fts_disableInterrupt();
+ if (res >= OK) {
+ pr_info("Setting Scan Freq...\n");
+ u8ToU32_be(&cmd[1], &fileSize);
+ /* fileSize is used just as container
+ * variable, sorry for the name! */
+
+ res = setActiveScanFrequency(fileSize);
+ if (res < OK)
+ pr_err("Error while setting the scan frequency... ERROR %08X\n",
+ res);
+ else {
+ /* setActiveScan Frequency leave
+ * the chip in reset state but
+ * with the new scan freq set */
+ /* need to enable the scan mode
+ * and re-enable the interrupts
+ * */
+ res |= setScanMode(
+ SCAN_MODE_LOCKED,
+ LOCKED_ACTIVE);
+ /* this is a choice to force
+ * the IC to use the freq set */
+ res |= fts_enableInterrupt();
+ pr_info("Setting Scan Freq... res = %08X\n",
+ res);
+ }
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_TP_SENS_MODE:
+ /* need to pass: enter (optional)saveGain */
+ if (numberParam >= 2) {
+ if (numberParam == 2)
+ cmd[2] = 0; /* by default never save
+ * the gain (used only
+ * when exit) */
+
+ res = tp_sensitivity_mode(cmd[1], cmd[2]);
+ if (res < OK)
+ pr_err("Error while setting TP Sens mode... ERROR %08X\n",
+ res);
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ case CMD_TP_SENS_SET_SCAN_MODE:
+ /* need to pass: scan_type, enableGains */
+ if (numberParam == 3) {
+ res = tp_sensitivity_set_scan_mode(cmd[1],
+ cmd[2]);
+ /* this force the IC to lock in a scan mode */
+ if (res < OK)
+ pr_err("Error while setting TP Sens scan mode... ERROR %08X\n",
+ res);
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+ break;
+
+ case CMD_TP_SENS_PRECAL_SS:
+ /* need to pass: target1 target0 percentage(optional) */
+ if (numberParam >= 3) {
+ if (numberParam > 3)
+ temp = cmd[3];
+ else
+ temp = SENS_TEST_PERC_TARGET_PRECAL;
+
+ pr_info("Setting target = %d and percentage = %d\n",
+ (cmd[1] << 8 | cmd[2]), temp);
+
+ res = tp_sensitivity_test_pre_cal_ss(&frameSS,
+ (cmd[1] << 8 |
+ cmd[2]),
+ temp);
+ if (res < OK)
+ pr_err("Error while setting the scan frequency... ERROR %08X\n",
+ res);
+
+ if ((frameSS.force_data != NULL) &&
+ (frameSS.sense_data != NULL)) {
+ size += ((frameSS.header.force_node +
+ frameSS.header.sense_node) *
+ sizeof(short) + 2);
+ /*make error code positive to print the
+ * frame*/
+ res &= (~0x80000000);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_TP_SENS_PRECAL_MS:
+ /* need to pass: target1 target0 calibrate
+ * percentage(optional) */
+ if (numberParam >= 4) {
+ if (numberParam > 4)
+ temp = cmd[4];
+ else
+ temp = SENS_TEST_PERC_TARGET_PRECAL;
+
+ pr_info("Setting target = %d and percentage = %d\n",
+ (cmd[1] << 8 | cmd[2]), temp);
+
+ res = tp_sensitivity_test_pre_cal_ms(&frameMS,
+ (cmd[1] << 8 |
+ cmd[2]),
+ temp);
+ if (res < OK)
+ pr_err("Error during TP Sensitivity Precal ... ERROR %08X\n",
+ res);
+
+ if (cmd[3] != 0) {
+ pr_info("Computing gains with target = %d and saveGain = %d\n",
+ (cmd[1] << 8 | cmd[2]), cmd[3]);
+ temp = tp_sensitivity_compute_gains(
+ &frameMS, (cmd[1] << 8 |
+ cmd[2]),
+ cmd[3]);
+ if (temp < OK)
+ pr_err("Error during TP Sensitivity Calibration... ERROR %08X\n",
+ temp);
+ res |= temp;
+ }
+
+ if (frameMS.node_data != NULL) {
+ size += (frameMS.node_data_size *
+ sizeof(short) + 2);
+ /*make error code positive to print the
+ * frame*/
+ res &= (~0x80000000);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_TP_SENS_POSTCAL_MS:
+ /* need to pass: target1 target0 executeTest
+ * percentage(optional) */
+ if (numberParam >= 4) {
+ if (cmd[3] != 0) {
+ if (numberParam > 4)
+ temp = cmd[4];
+ else
+ temp =
+ SENS_TEST_PERC_TARGET_POSTCAL;
+ } else
+ temp = -1;
+
+ pr_info("Setting target = %d and percentage = %d\n",
+ (cmd[1] << 8 | cmd[2]), temp);
+
+ res = tp_sensitivity_test_post_cal_ms(&frameMS,
+ &deltas,
+ (cmd[1] << 8 |
+ cmd[2]),
+ temp,
+ &meanNorm,
+ &meanEdge);
+ if (res < OK)
+ pr_err("Error during TP Sensitivity Post Cal ... ERROR %08X\n",
+ res);
+
+ /* processing for a proper printing on the shell
+ * */
+ if ((frameMS.node_data != NULL) &&
+ (deltas.node_data != NULL)) {
+ size += ((frameMS.node_data_size +
+ deltas.node_data_size) *
+ sizeof(short) +
+ 2 + 8);/* +2 force and
+ * sense len, +8
+ * mean_normal/edge
+ * */
+ /*make error code positive to print the
+ * frame*/
+ res &= (~0x80000000);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+
+ case CMD_TP_SENS_STD:
+ /* need to pass: numFrames */
+ if (numberParam >= 2) {
+ res = tp_sensitivity_test_std_ms(cmd[1],
+ &frameMS);
+ if (res < OK)
+ pr_err("Error during TP Sensitivity STD... ERROR %08X\n",
+ res);
+
+ /* processing for a proper printing on the shell
+ * */
+ if (frameMS.node_data != NULL) {
+ size += ((frameMS.node_data_size) *
+ sizeof(short) + 2);
+ /* +2 force and sense len */
+ /*make error code positive to print the
+ * frame*/
+ res &= (~0x80000000);
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ case CMD_FORCE_TOUCH_ACTIVE:
+ /* Single parameter indicates force touch state */
+ if (numberParam == 2) {
+ if (cmd[1] > 1) {
+ pr_err("Parameter should be 1 or 0\n");
+ res = ERROR_OP_NOT_ALLOW;
+ } else {
+ fts_set_bus_ref(info,
+ FTS_BUS_REF_FORCE_ACTIVE,
+ cmd[1]);
+ res = OK;
+ }
+ } else {
+ pr_err("Wrong number of parameters!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+ break;
+
+ default:
+ pr_err("COMMAND ID NOT VALID!!!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ break;
+ }
+
+ /* res2 = fts_enableInterrupt();
+ * the interrupt was disabled on purpose in this node because it
+ * can be used for testing procedure and between one step and
+ * another the interrupt wan to be kept disabled
+ * if (res2 < 0) {
+ * pr_err("stm_driver_test_show: ERROR %08X\n",
+ * (res2 | ERROR_ENABLE_INTER));
+ * }*/
+ } else {
+ pr_err("NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n");
+ res = ERROR_OP_NOT_ALLOW;
+ }
+
+END: /* here start the reporting phase, assembling the data to send in the
+ * file node */
+ if (driver_test_buff != NULL) {
+ pr_info("Consecutive echo on the file node, free the buffer with the previous result\n");
+ kfree(driver_test_buff);
+ }
+
+ if (byte_call == 0) {
+ size *= 2;
+ size += 2; /* add \n and \0 (terminator char) */
+ } else {
+ if (bin_output != 1) {
+ size *= 2; /* need to code each byte as HEX string */
+ size -= 1; /* start byte is just one, the extra
+ * byte of end byte taken by \n */
+ } else
+ size += 1; /* add \n */
+ }
+
+ pr_info("Size = %d\n", size);
+ driver_test_buff = (u8 *)kzalloc(size, GFP_KERNEL);
+ pr_info("Finish to allocate memory!\n");
+ if (driver_test_buff == NULL) {
+ pr_err("Unable to allocate driver_test_buff! ERROR %08X\n",
+ ERROR_ALLOC);
+ goto ERROR;
+ }
+
+ if (byte_call == 0) {
+ index = 0;
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "{ ");
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%08X", res);
+ if (res >= OK) {
+ /*all the other cases are already fine printing only the
+ * res.*/
+ switch (funcToTest[0]) {
+ case CMD_VERSION:
+ case CMD_READ:
+ case CMD_WRITEREAD:
+ case CMD_WRITETHENWRITEREAD:
+ case CMD_WRITEREADU8UX:
+ case CMD_WRITEU8UXTHENWRITEREADU8UX:
+ case CMD_READCONFIG:
+ case CMD_POLLFOREVENT:
+ /* pr_err("Data = "); */
+ if (mess.dummy == 1)
+ j = 1;
+ else
+ j = 0;
+ for (; j < byteToRead + mess.dummy; j++) {
+ /* pr_err("%02X ", readData[j]); */
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X", readData[j]);
+ /* this approach is much more faster */
+ }
+ /* pr_err("\n"); */
+ break;
+ case CMD_GETFWFILE:
+ case CMD_GETLIMITSFILE:
+ pr_info("Start To parse!\n");
+ for (j = 0; j < fileSize; j++) {
+ /* pr_err("%02X ", readData[j]); */
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X", readData[j]);
+ }
+ pr_info("Finish to parse!\n");
+ break;
+ case CMD_GETFORCELEN:
+ case CMD_GETSENSELEN:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)temp);
+ break;
+ case CMD_GETMSFRAME:
+ case CMD_TP_SENS_PRECAL_MS:
+ case CMD_TP_SENS_POSTCAL_MS:
+ case CMD_TP_SENS_STD:
+
+ if (res != OK)
+ driver_test_buff[2] = '8';
+ /* convert back error code to negative */
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameMS.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameMS.header.sense_node);
+
+ for (j = 0; j < frameMS.node_data_size; j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (frameMS.node_data[j] & 0xFF00) >> 8,
+ frameMS.node_data[j] & 0xFF);
+ }
+
+ kfree(frameMS.node_data);
+
+ if (funcToTest[0] == CMD_TP_SENS_POSTCAL_MS) {
+ /* print also mean and deltas */
+ for (j = 0; j < deltas.node_data_size;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (deltas.node_data[j] &
+ 0xFF00) >> 8,
+ deltas.node_data[j] &
+ 0xFF);
+ }
+ kfree(deltas.node_data);
+
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%08X", meanNorm);
+
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%08X", meanEdge);
+ }
+ break;
+ case CMD_GETSSFRAME:
+ case CMD_TP_SENS_PRECAL_SS:
+ if (res != OK)
+ driver_test_buff[2] = '8';
+ /* convert back error code to negative */
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameSS.header.force_node);
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameSS.header.sense_node);
+ /* Copying self raw data Force */
+ for (j = 0; j < frameSS.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (frameSS.force_data[j] & 0xFF00) >> 8,
+ frameSS.force_data[j] & 0xFF);
+ }
+
+ /* Copying self raw data Sense */
+ for (j = 0; j < frameSS.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (frameSS.sense_data[j] & 0xFF00) >> 8,
+ frameSS.sense_data[j] & 0xFF);
+ }
+
+ kfree(frameSS.force_data);
+ kfree(frameSS.sense_data);
+ break;
+
+ case CMD_READMSCOMPDATA:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)compData.header.type);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)compData.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)compData.header.sense_node);
+
+ /* Cpying CX1 value */
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ compData.cx1 & 0xFF);
+
+ /* Copying CX2 values */
+ for (j = 0; j < compData.node_data_size; j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ compData.node_data[j] & 0xFF);
+ }
+
+ kfree(compData.node_data);
+ break;
+
+ case CMD_READSSCOMPDATA:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)comData.header.type);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ comData.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ comData.header.sense_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ comData.f_ix1 & 0xFF);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ comData.s_ix1 & 0xFF);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ comData.f_cx1 & 0xFF);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ comData.s_cx1 & 0xFF);
+
+ /* Copying IX2 Force */
+ for (j = 0; j < comData.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ comData.ix2_fm[j] & 0xFF);
+ }
+
+ /* Copying IX2 Sense */
+ for (j = 0; j < comData.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ comData.ix2_sn[j] & 0xFF);
+ }
+
+ /* Copying CX2 Force */
+ for (j = 0; j < comData.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ comData.cx2_fm[j] & 0xFF);
+ }
+
+ /* Copying CX2 Sense */
+ for (j = 0; j < comData.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ comData.cx2_sn[j] & 0xFF);
+ }
+
+ kfree(comData.ix2_fm);
+ kfree(comData.ix2_sn);
+ kfree(comData.cx2_fm);
+ kfree(comData.cx2_sn);
+ break;
+
+
+
+ case CMD_READTOTMSCOMPDATA:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)totCompData.header.type);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)totCompData.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)totCompData.header.sense_node);
+
+ /* Copying TOT CX values */
+ for (j = 0; j < totCompData.node_data_size;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (totCompData.node_data[j] &
+ 0xFF00) >> 8,
+ totCompData.node_data[j] &
+ 0xFF);
+ }
+
+ kfree(totCompData.node_data);
+ break;
+
+ case CMD_READTOTSSCOMPDATA:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)totComData.header.type);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ totComData.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ totComData.header.sense_node);
+
+ /* Copying TOT IX Force */
+ for (j = 0; j < totComData.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (totComData.ix_fm[j] &
+ 0xFF00) >> 8,
+ totComData.ix_fm[j] &
+ 0xFF);
+ }
+
+ /* Copying TOT IX Sense */
+ for (j = 0; j < totComData.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (totComData.ix_sn[j] &
+ 0xFF00) >> 8,
+ totComData.ix_sn[j] &
+ 0xFF);
+ }
+
+ /* Copying TOT CX Force */
+ for (j = 0; j < totComData.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (totComData.cx_fm[j] &
+ 0xFF00) >> 8,
+ totComData.cx_fm[j] &
+ 0xFF);
+ }
+
+ /* Copying CX2 Sense */
+ for (j = 0; j < totComData.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (totComData.cx_sn[j] &
+ 0xFF00) >> 8,
+ totComData.cx_sn[j] &
+ 0xFF);
+ }
+
+ kfree(totComData.ix_fm);
+ kfree(totComData.ix_sn);
+ kfree(totComData.cx_fm);
+ kfree(totComData.cx_sn);
+ break;
+
+ case CMD_READSENSCOEFF:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)msCoeff.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)msCoeff.header.sense_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)ssCoeff.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)ssCoeff.header.sense_node);
+
+ /* Copying MS Coefficients */
+ for (j = 0; j < msCoeff.node_data_size; j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ msCoeff.ms_coeff[j] & 0xFF);
+ }
+
+ /* Copying SS force Coefficients */
+ for (j = 0; j < ssCoeff.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ ssCoeff.ss_force_coeff[j] &
+ 0xFF);
+ }
+
+ /* Copying SS sense Coefficients */
+ for (j = 0; j < ssCoeff.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ ssCoeff.ss_sense_coeff[j] &
+ 0xFF);
+ }
+
+ kfree(msCoeff.ms_coeff);
+ kfree(ssCoeff.ss_force_coeff);
+ kfree(ssCoeff.ss_sense_coeff);
+ break;
+
+ case CMD_GETFWVER:
+ for (j = 0; j < EXTERNAL_RELEASE_INFO_SIZE;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ systemInfo.u8_releaseInfo[j]);
+ }
+ break;
+
+ case CMD_READCOMPDATAHEAD:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ dataHead.type);
+ break;
+
+ case CMD_READ_SYNC_FRAME:
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameMS.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameMS.header.sense_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameSS.header.force_node);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%02X",
+ (u8)frameSS.header.sense_node);
+
+ /* Copying mutual data */
+ for (j = 0; j < frameMS.node_data_size; j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (frameMS.node_data[j] &
+ 0xFF00) >> 8,
+ frameMS.node_data[j] &
+ 0xFF);
+ }
+
+ /* Copying self data Force */
+ for (j = 0; j < frameSS.header.force_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (frameSS.force_data[j] &
+ 0xFF00) >> 8,
+ frameSS.force_data[j] &
+ 0xFF);
+ }
+
+
+ /* Copying self data Sense */
+ for (j = 0; j < frameSS.header.sense_node;
+ j++) {
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (frameSS.sense_data[j] &
+ 0xFF00) >> 8,
+ frameSS.sense_data[j] &
+ 0xFF);
+ }
+
+ kfree(frameMS.node_data);
+ kfree(frameSS.force_data);
+ kfree(frameSS.sense_data);
+ break;
+
+
+ default:
+ break;
+ }
+ }
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, " }\n");
+ limit = size - 1;/* avoid to print \0 in the shell */
+ printed = 0;
+ } else {
+ /* start byte */
+ driver_test_buff[index++] = MESSAGE_START_BYTE;
+ if (bin_output == 1) {
+ /* msg_size */
+ driver_test_buff[index++] = (size & 0xFF00) >> 8;
+ driver_test_buff[index++] = (size & 0x00FF);
+ /* counter id */
+ driver_test_buff[index++] =
+ (mess.counter & 0xFF00) >> 8;
+ driver_test_buff[index++] = (mess.counter & 0x00FF);
+ /* action */
+ driver_test_buff[index++] = (mess.action & 0xFF00) >> 8;
+ driver_test_buff[index++] = (mess.action & 0x00FF);
+ /* error */
+ driver_test_buff[index++] = (res & 0xFF00) >> 8;
+ driver_test_buff[index++] = (res & 0x00FF);
+ } else {
+ if (funcToTest[0] == CMD_GETLIMITSFILE_BYTE ||
+ funcToTest[0] == CMD_GETFWFILE_BYTE)
+ index += scnprintf(&driver_test_buff[index],
+ size - index,
+ "%02X%02X",
+ (((fileSize + 3) / 4) & 0xFF00) >> 8,
+ ((fileSize + 3) / 4) & 0x00FF);
+ else
+ index += scnprintf(&driver_test_buff[index],
+ size - index,
+ "%02X%02X", (size & 0xFF00) >> 8,
+ size & 0xFF);
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%04X",
+ (u16)mess.counter);
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%04X",
+ (u16)mess.action);
+ index += scnprintf(&driver_test_buff[index],
+ size - index,
+ "%02X%02X", (res & 0xFF00) >> 8,
+ res & 0xFF);
+ }
+
+ switch (funcToTest[0]) {
+ case CMD_VERSION_BYTE:
+ case CMD_READ_BYTE:
+ case CMD_WRITEREAD_BYTE:
+ case CMD_WRITETHENWRITEREAD_BYTE:
+ case CMD_WRITEREADU8UX_BYTE:
+ case CMD_WRITEU8UXTHENWRITEREADU8UX_BYTE:
+ if (bin_output == 1) {
+ if (mess.dummy == 1)
+ memcpy(&driver_test_buff[index],
+ &readData[1], byteToRead);
+ else
+ memcpy(&driver_test_buff[index],
+ readData, byteToRead);
+ index += byteToRead;
+ } else {
+ j = mess.dummy;
+ for (; j < byteToRead + mess.dummy; j++)
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ (u8)readData[j]);
+ }
+ break;
+
+ case CMD_GETLIMITSFILE_BYTE:
+ case CMD_GETFWFILE_BYTE:
+ if (bin_output == 1) {
+ /* override the msg_size with dimension in words
+ * */
+ driver_test_buff[1] = (
+ ((fileSize + 3) / 4) & 0xFF00) >> 8;
+ driver_test_buff[2] = (
+ ((fileSize + 3) / 4) & 0x00FF);
+
+ if (readData != NULL)
+ memcpy(&driver_test_buff[index],
+ readData, fileSize);
+ else
+ pr_err("readData = NULL... returning junk data!");
+ index += addr; /* in this case the byte to read
+ * are stored in addr because it
+ * is a u64 end byte need to be
+ * inserted at the end of the
+ * padded memory */
+ } else {
+ /* snprintf(&driver_test_buff[1], 3, "%02X",
+ * (((fileSize + 3) / 4)&0xFF00) >> 8); */
+ /* snprintf(&driver_test_buff[3], 3, "%02X",
+ * ((fileSize + 3) / 4)&0x00FF); */
+ for (j = 0; j < fileSize; j++)
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X",
+ (u8)readData[j]);
+ for (; j < addr; j++)
+ index += scnprintf(
+ &driver_test_buff[index],
+ size - index,
+ "%02X", 0); /* pad memory
+ * with 0x00 */
+ }
+ break;
+ default:
+ break;
+ }
+
+ index += scnprintf(&driver_test_buff[index],
+ size - index, "%c\n", MESSAGE_END_BYTE);
+ /*for(j=0; j<size; j++){
+ * pr_err("%c", driver_test_buff[j]);
+ * }*/
+ limit = size;
+ printed = 0;
+ }
+ERROR:
+ numberParam = 0;/* need to reset the number of parameters in order to
+ * wait the next command, comment if you want to repeat
+ * the last command sent just doing a cat */
+
+ /* pr_err(0,"numberParameters = %d\n", numberParam); */
+
+ kfree(readData);
+ kfree(cmd);
+ kfree(funcToTest);
+ kfree(pbuf);
+
+ fts_set_bus_ref(info, FTS_BUS_REF_SYSFS, false);
+
+ mutex_unlock(&info->diag_cmd_lock);
+exit:
+ return count;
+}
+
+/** @}*/
+
+/**
+ * file_operations struct which define the functions for the canonical
+ * operation on a device file node (open. read, write etc.)
+ */
+static struct proc_ops fts_driver_proc_ops = {
+ .proc_open = fts_driver_test_open,
+ .proc_read = fts_driver_test_read,
+ .proc_write = fts_driver_test_write,
+ .proc_lseek = fts_driver_test_lseek,
+ .proc_release = fts_driver_test_release
+};
+
+/*****************************************************************************/
+
+/**
+ * This function is called in the probe to initialize and create the directory
+ * proc/fts and the driver test file node DRIVER_TEST_FILE_NODE into the /proc
+ * file system
+ * @return OK if success or an error code which specify the type of error
+ */
+int fts_proc_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ int retval = 0;
+
+
+ fts_dir = proc_mkdir_data("fts", 0777, NULL, NULL);
+ if (fts_dir == NULL) { /* directory creation failed */
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ entry = proc_create(DRIVER_TEST_FILE_NODE, 0777, fts_dir,
+ &fts_driver_proc_ops);
+
+ if (entry)
+ pr_info("%s: proc entry CREATED!\n", __func__);
+ else {
+ pr_err("%s: error creating proc entry!\n", __func__);
+ retval = -ENOMEM;
+ goto badfile;
+ }
+ return OK;
+badfile:
+ remove_proc_entry("fts", NULL);
+out:
+ return retval;
+}
+
+/**
+ * Delete and Clean from the file system, all the references to the driver test
+ * file node
+ * @return OK
+ */
+int fts_proc_remove(void)
+{
+ remove_proc_entry(DRIVER_TEST_FILE_NODE, fts_dir);
+ remove_proc_entry("fts", NULL);
+ return OK;
+}
diff --git a/drivers/input/touchscreen/stm/i2c_fts.h b/drivers/input/touchscreen/stm/i2c_fts.h
new file mode 100644
index 00000000000..e13aa8d15b0
--- /dev/null
+++ b/drivers/input/touchscreen/stm/i2c_fts.h
@@ -0,0 +1,89 @@
+#ifndef _LINUX_FTS_I2C_H_
+#define _LINUX_FTS_I2C_H_
+
+extern struct fts_callbacks *fts_charger_callbacks;
+struct fts_callbacks {
+ void (*inform_charger) (struct fts_callbacks *, int);
+};
+
+#ifdef FTS_SUPPORT_NOISE_PARAM
+#define MAX_NOISE_PARAM 5
+struct fts_noise_param {
+ unsigned short pAddr[MAX_NOISE_PARAM];
+ unsigned short pData[MAX_NOISE_PARAM];
+};
+#endif
+
+#ifdef FTS_SUPPORT_TOUCH_KEY
+/* TSP Key Feature*/
+#define KEY_PRESS 1
+#define KEY_RELEASE 0
+#define TOUCH_KEY_NULL 0
+
+/* support 2 touch keys */
+#define TOUCH_KEY_RECENT 0x01
+#define TOUCH_KEY_BACK 0x02
+
+struct fts_touchkey {
+ unsigned int value;
+ unsigned int keycode;
+ char *name;
+};
+#endif
+
+struct fts_i2c_platform_data {
+ bool factory_flatform;
+ bool recovery_mode;
+ bool support_hover;
+ bool support_mshover;
+ int max_x;
+ int max_y;
+ int max_width;
+ int grip_area;
+ int SenseChannelLength;
+ int ForceChannelLength;
+ unsigned char panel_revision; /* to identify panel info */
+
+ const char *firmware_name;
+ const char *project_name;
+ const char *model_name;
+ const char *regulator_dvdd;
+ const char *regulator_avdd;
+
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_default;
+ struct pinctrl_state *pins_sleep;
+
+ int (*power)(void *data, bool on);
+ void (*register_cb)(void *);
+ void (*enable_sync)(bool on);
+ unsigned char (*get_ddi_type)(void); /* to indentify ddi type */
+
+ unsigned tspid;
+ unsigned tspid2;
+ unsigned gpio;
+ int vdd_gpio;
+ int vio_gpio;
+ int irq_type;
+
+#ifdef FTS_SUPPORT_TOUCH_KEY
+ bool support_mskey;
+ unsigned int num_touchkey;
+ struct fts_touchkey *touchkey;
+ const char *regulator_tk_led;
+ int (*led_power) (void *, bool);
+#endif
+ unsigned gpio_scl;
+ unsigned gpio_sda;
+ int switch_gpio;
+};
+
+// #define FTS_SUPPORT_TA_MODE // DE version don't need.
+
+extern unsigned int lcdtype;
+
+void fts_charger_infom(bool en);
+#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
+extern void trustedui_mode_on(void);
+#endif
+#endif
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 4c67e2c5a82..a9bacbe8938 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;
@@ -2255,6 +2258,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);
@@ -2297,6 +2302,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);
+
+ 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..ac8f3d8eb46
--- /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;
+}
+
+static 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;
+}
+
+static 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 7db0a29b5b8..1f2dce3373e 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 444212c0b5a..db217625de5 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/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 3011d33eccb..82b1cc434ea 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -226,6 +226,12 @@ static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
return -EINVAL;
}
+enum mipi_dsi_compression_algo {
+ MIPI_DSI_COMPRESSION_DSC = 0,
+ MIPI_DSI_COMPRESSION_VENDOR = 3,
+ /* other two values are reserved, DSI 1.3 */
+};
+
struct mipi_dsi_device *
mipi_dsi_device_register_full(struct mipi_dsi_host *host,
const struct mipi_dsi_device_info *info);
@@ -242,6 +248,9 @@ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
+int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable,
+ enum mipi_dsi_compression_algo algo,
+ unsigned int pps_selector);
int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
const struct drm_dsc_picture_parameter_set *pps);
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 03edf2ccdf6..54f1764e225 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -867,6 +867,7 @@
#define ABS_VOLUME 0x20
#define ABS_PROFILE 0x21
+#define ABS_SND_PROFILE 0x22
#define ABS_MISC 0x28
@@ -975,4 +976,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 f78ea2f86fa..d18683b0de9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -253,6 +253,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
@@ -340,6 +341,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
@@ -1919,6 +1921,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
@@ -2484,6 +2494,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 7c075539dc4..8a039245b29 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -287,6 +287,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
@@ -393,6 +397,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
@@ -679,6 +687,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..06cec92d862
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c
@@ -0,0 +1,3390 @@
+/*
+ * 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), /* 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 0e6218ed0e5..8fcacdb9a6d 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -69,6 +69,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 */
@@ -197,7 +198,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);
}
@@ -277,8 +278,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);
@@ -506,6 +509,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);
}
}
@@ -1298,8 +1302,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,
@@ -1527,6 +1533,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 a9767ef0e39..62ca35ea41e 100644
--- a/sound/soc/codecs/wsa884x.c
+++ b/sound/soc/codecs/wsa884x.c
@@ -1771,6 +1771,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;