dotfiles/system/hardware/oneplus-enchilada/linux_6_7.patch

67178 lines
2.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/arch/loongarch/introduction.rst b/Documentation/arch/loongarch/introduction.rst
index 8c568cfc210..5e6db78abea 100644
--- a/Documentation/arch/loongarch/introduction.rst
+++ b/Documentation/arch/loongarch/introduction.rst
@@ -375,9 +375,9 @@ Developer web site of Loongson and LoongArch (Software and Documentation):
Documentation of LoongArch ISA:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (in Chinese)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-CN.pdf (in Chinese)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (in English)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-EN.pdf (in English)
Documentation of LoongArch ELF psABI:
diff --git a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
index fa745a6f445..9d90cf72578 100644
--- a/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
+++ b/Documentation/devicetree/bindings/display/panel/visionox,rm69299.yaml
@@ -17,7 +17,9 @@ allOf:
properties:
compatible:
- const: visionox,rm69299-1080p-display
+ enum:
+ - visionox,rm69299-1080p-display
+ - visionox,rm69299-shift
reg: true
diff --git a/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml b/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
new file mode 100644
index 00000000000..8ef9b4ec3a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2020 Unisoc Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/qcom,spmi-haptics.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies Inc PMI8998 spmi haptics
+
+maintainers:
+ - Caleb Connolly <caleb@connolly.tech>
+
+description: |
+ Qualcomm SPMI haptics is a peripheral on some QTI PMICs. It supports linear resonant
+ actuators and eccentric rotating mass type haptics commonly found in mobile devices.
+ It supports multiple sources of wave data such as an internal buffer, direct play
+ (from kernel or userspace) as well as an audio output mode.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - qcom,pmi8998-haptics
+ - qcom,pmi8996-haptics
+ - qcom,pmi8941-haptics
+ - const: qcom,spmi-haptics
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: short circuit interrupt
+ - description: play interrupt
+
+ interrupt-names:
+ items:
+ - const: short
+ - const: play
+
+ qcom,actuator-type:
+ description: |
+ The type of actuator attached to the hardware.
+ Allowed values are,
+ 0 - HAP_TYPE_LRA
+ 1 - HAP_TYPE_ERM
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1 ]
+ default: 0
+
+ qcom,wave-shape:
+ description: |
+ Selects the wave shape to use.
+ Allowed values are,
+ 0 - HAP_WAVE_SINE
+ 1 - HAP_WAVE_SQUARE
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1 ]
+ default: 0
+
+ qcom,play-mode:
+ description: |
+ Selects the play mode to use.
+ Allowed values are,
+ 0 - HAP_PLAY_DIRECT
+ 1 - HAP_PLAY_BUFFER
+ 2 - HAP_PLAY_AUDIO
+ 3 - HAP_PLAY_PWM
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2, 3 ]
+ default: 2
+
+ qcom,wave-play-rate-us:
+ description: |
+ Wave sample durection in microseconds, 1/f where f
+ is the resonant frequency of the actuator.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 20475
+
+ qcom,brake-pattern:
+ minItems: 4
+ maxItems: 4
+ description: |
+ The brake pattern are the strengths of the pattern
+ used to brake the haptics. Allowed values are,
+ 0 - 0V
+ 1 - Vmax/4
+ 2 - Vmax/2
+ 3 - Vmax
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ default: [0x3, 0x3, 0x2, 0x1]
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - qcom,wave-play-rate-us
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/spmi/spmi.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/input/qcom,spmi-haptics.h>
+
+ pmi8998_lsid1: pmic@3 {
+ compatible = "qcom,pmi8998", "qcom,spmi-pmic";
+ reg = <0x3 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmi8998_haptics: haptics@c000 {
+ compatible = "qcom,pmi8998-haptics", "qcom,spmi-haptics";
+ reg = <0xc000>;
+
+ interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "short", "play";
+
+ qcom,wave-shape = <HAP_WAVE_SINE>;
+ qcom,play-mode = <HAP_PLAY_BUFFER>;
+ qcom,brake-pattern = <0x3 0x3 0x2 0x1>;
+
+ status = "disabled";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
index b522c8d3ce0..04ce256300c 100644
--- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
+++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
@@ -49,6 +49,16 @@ properties:
description:
Delay to wait after powering on the device.
+ syna,pdt-fallback-desc:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description:
+ An array of pairs of function number and version. These are used
+ on some devices with replacement displays that use unofficial touch
+ controllers. These controllers do report the properties of their PDT
+ entries, but leave the function_number and function_version registers
+ blank. These values should match exactly the 5th and 4th bytes of each
+ PDT entry from the original display's touch controller.
+
vdd-supply: true
vio-supply: true
diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
index f2808cb4d99..745e57c0517 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
@@ -39,7 +39,9 @@ properties:
- edt,edt-ft5406
- edt,edt-ft5506
- evervision,ev-ft5726
+ - focaltech,ft5452
- focaltech,ft6236
+ - focaltech,ft8719
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml b/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml
index a8736fd5a53..c389d1955bd 100644
--- a/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml
+++ b/Documentation/devicetree/bindings/leds/qcom,spmi-flash-led.yaml
@@ -23,11 +23,11 @@ properties:
items:
- enum:
- qcom,pm6150l-flash-led
+ - qcom,pmi8998-flash-led
- qcom,pm8150c-flash-led
- qcom,pm8150l-flash-led
- qcom,pm8350c-flash-led
- qcom,pm8550-flash-led
- - qcom,pmi8998-flash-led
- const: qcom,spmi-flash-led
reg:
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
index 7758a55dd32..874ca4157fb 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
@@ -138,6 +138,12 @@ properties:
description:
Quirk specifying that the firmware expects the 8bit version
of the host capability QMI request
+
+ qcom,snoc-host-cap-skip-quirk:
+ type: boolean
+ description:
+ Quirk specifying that the firmware wants to skip the host
+ capability QMI request
qcom,xo-cal-data:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/power/supply/lenovo,yoga-c630-ec.yaml b/Documentation/devicetree/bindings/power/supply/lenovo,yoga-c630-ec.yaml
new file mode 100644
index 00000000000..2dceb57a56b
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/lenovo,yoga-c630-ec.yaml
@@ -0,0 +1,88 @@
+# 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@\d$':
+ $ref: /schemas/connector/usb-connector.yaml#
+
+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";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@1 {
+ reg = <1>;
+ lenovo_ec_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp_out>;
+ };
+ };
+ };
+ };
+ };
+ };
+...
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/devicetree/bindings/usb/microchip,usb5744.yaml b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
index ff3a1707ef5..6d4cfd943f5 100644
--- a/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
+++ b/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
@@ -36,7 +36,11 @@ properties:
vdd-supply:
description:
- VDD power supply to the hub
+ 3V3 power supply to the hub
+
+ vdd2-supply:
+ description:
+ 1V2 power supply to the hub
peer-hub:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -62,6 +66,7 @@ allOf:
properties:
reset-gpios: false
vdd-supply: false
+ vdd2-supply: false
peer-hub: false
i2c-bus: false
else:
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index e889158ca20..915c8205623 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -521,8 +521,8 @@ examples:
interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 488 IRQ_TYPE_EDGE_BOTH>,
+ <GIC_SPI 489 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "hs_phy_irq", "ss_phy_irq",
"dm_hs_phy_irq", "dp_hs_phy_irq";
diff --git a/Documentation/devicetree/bindings/usb/usb-hcd.yaml b/Documentation/devicetree/bindings/usb/usb-hcd.yaml
index 692dd60e3f7..45a19d4928a 100644
--- a/Documentation/devicetree/bindings/usb/usb-hcd.yaml
+++ b/Documentation/devicetree/bindings/usb/usb-hcd.yaml
@@ -41,7 +41,7 @@ examples:
- |
usb {
phys = <&usb2_phy1>, <&usb3_phy1>;
- phy-names = "usb";
+ phy-names = "usb2", "usb3";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystems/erofs.rst
index 57c6ae23b3f..cc4626d6ee4 100644
--- a/Documentation/filesystems/erofs.rst
+++ b/Documentation/filesystems/erofs.rst
@@ -91,6 +91,10 @@ compatibility checking tool (fsck.erofs), and a debugging tool (dump.erofs):
- git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git
+For more information, please also refer to the documentation site:
+
+- https://erofs.docs.kernel.org
+
Bugs and patches are welcome, please kindly help us and send to the following
linux-erofs mailing list:
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/Documentation/process/maintainer-netdev.rst b/Documentation/process/maintainer-netdev.rst
index 7feacc20835..84ee60fceef 100644
--- a/Documentation/process/maintainer-netdev.rst
+++ b/Documentation/process/maintainer-netdev.rst
@@ -193,9 +193,23 @@ Review timelines
Generally speaking, the patches get triaged quickly (in less than
48h). But be patient, if your patch is active in patchwork (i.e. it's
listed on the project's patch list) the chances it was missed are close to zero.
-Asking the maintainer for status updates on your
-patch is a good way to ensure your patch is ignored or pushed to the
-bottom of the priority list.
+
+The high volume of development on netdev makes reviewers move on
+from discussions relatively quickly. New comments and replies
+are very unlikely to arrive after a week of silence. If a patch
+is no longer active in patchwork and the thread went idle for more
+than a week - clarify the next steps and/or post the next version.
+
+For RFC postings specifically, if nobody responded in a week - reviewers
+either missed the posting or have no strong opinions. If the code is ready,
+repost as a PATCH.
+
+Emails saying just "ping" or "bump" are considered rude. If you can't figure
+out the status of the patch from patchwork or where the discussion has
+landed - describe your best guess and ask if it's correct. For example::
+
+ I don't understand what the next steps are. Person X seems to be unhappy
+ with A, should I do B and repost the patches?
.. _Changes requested:
diff --git a/Documentation/translations/zh_CN/arch/loongarch/introduction.rst b/Documentation/translations/zh_CN/arch/loongarch/introduction.rst
index 59d6bf33050..bf463c5a4c5 100644
--- a/Documentation/translations/zh_CN/arch/loongarch/introduction.rst
+++ b/Documentation/translations/zh_CN/arch/loongarch/introduction.rst
@@ -338,9 +338,9 @@ Loongson与LoongArch的开发者网站软件与文档资源
LoongArch指令集架构的文档
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-CN.pdf (中文版)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.10-EN.pdf (英文版)
LoongArch的ELF psABI文档
diff --git a/MAINTAINERS b/MAINTAINERS
index ea790149af7..00e3beabbdf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6832,6 +6832,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
@@ -7855,6 +7860,7 @@ R: Yue Hu <huyue2@coolpad.com>
R: Jeffle Xu <jefflexu@linux.alibaba.com>
L: linux-erofs@lists.ozlabs.org
S: Maintained
+W: https://erofs.docs.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
F: Documentation/ABI/testing/sysfs-fs-erofs
F: Documentation/filesystems/erofs.rst
@@ -11024,7 +11030,6 @@ F: drivers/net/wireless/intel/iwlwifi/
INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER
M: Jithu Joseph <jithu.joseph@intel.com>
-R: Maurice Ma <maurice.ma@intel.com>
S: Maintained
W: https://slimbootloader.github.io/security/firmware-update.html
F: drivers/platform/x86/intel/wmi/sbl-fw-update.c
@@ -13778,7 +13783,6 @@ F: drivers/net/ethernet/mellanox/mlxfw/
MELLANOX HARDWARE PLATFORM SUPPORT
M: Hans de Goede <hdegoede@redhat.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M: Mark Gross <markgross@kernel.org>
M: Vadim Pasternak <vadimp@nvidia.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
@@ -14387,7 +14391,6 @@ F: drivers/platform/surface/surface_gpe.c
MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT
M: Hans de Goede <hdegoede@redhat.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M: Mark Gross <markgross@kernel.org>
M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
@@ -14994,6 +14997,7 @@ M: Jakub Kicinski <kuba@kernel.org>
M: Paolo Abeni <pabeni@redhat.com>
L: netdev@vger.kernel.org
S: Maintained
+P: Documentation/process/maintainer-netdev.rst
Q: https://patchwork.kernel.org/project/netdevbpf/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
@@ -15045,6 +15049,7 @@ M: Jakub Kicinski <kuba@kernel.org>
M: Paolo Abeni <pabeni@redhat.com>
L: netdev@vger.kernel.org
S: Maintained
+P: Documentation/process/maintainer-netdev.rst
Q: https://patchwork.kernel.org/project/netdevbpf/list/
B: mailto:netdev@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
@@ -15055,6 +15060,7 @@ F: Documentation/networking/
F: Documentation/process/maintainer-netdev.rst
F: Documentation/userspace-api/netlink/
F: include/linux/in.h
+F: include/linux/indirect_call_wrapper.h
F: include/linux/net.h
F: include/linux/netdevice.h
F: include/net/
@@ -22078,6 +22084,7 @@ F: drivers/watchdog/tqmx86_wdt.c
TRACING
M: Steven Rostedt <rostedt@goodmis.org>
M: Masami Hiramatsu <mhiramat@kernel.org>
+R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
L: linux-kernel@vger.kernel.org
L: linux-trace-kernel@vger.kernel.org
S: Maintained
@@ -23664,7 +23671,6 @@ F: drivers/platform/x86/x86-android-tablets/
X86 PLATFORM DRIVERS
M: Hans de Goede <hdegoede@redhat.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
-M: Mark Gross <markgross@kernel.org>
L: platform-driver-x86@vger.kernel.org
S: Maintained
Q: https://patchwork.kernel.org/project/platform-driver-x86/list/
diff --git a/Makefile b/Makefile
index 724c79bebe7..99db546fbb4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 6
PATCHLEVEL = 7
SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
NAME = Hurr durr I'ma ninja sloth
# *DOCUMENTATION*
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 9afdc4c4a5d..a395b6c0aae 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -484,7 +484,8 @@ static int __init xen_guest_init(void)
* for secondary CPUs as they are brought up.
* For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
*/
- xen_vcpu_info = alloc_percpu(struct vcpu_info);
+ xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
+ 1 << fls(sizeof(struct vcpu_info) - 1));
if (xen_vcpu_info == NULL)
return -ENOMEM;
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 4bd85cc0d32..9a2d3723cd0 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -158,7 +158,7 @@ endif
all: $(notdir $(KBUILD_IMAGE))
-
+vmlinuz.efi: Image
Image vmlinuz.efi: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index d6cb840b705..28f3a66dc2f 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -100,6 +100,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8540p-ride.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8775p-ride.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-acer-aspire1.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-tcl-b220g.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1-lte.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/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
index d46e591e72b..2b952a5b752 100644
--- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
@@ -5,12 +5,14 @@
* Based on sm6115.dtsi and previous efforts by Shawn Guo & Loic Poulain.
*/
+#include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
#include <dt-bindings/clock/qcom,gcc-qcm2290.h>
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interconnect/qcom,qcm2290.h>
#include <dt-bindings/power/qcom-rpmpd.h>
/ {
@@ -150,6 +152,7 @@ scm: scm {
clocks = <&rpmcc RPM_SMD_CE1_CLK>;
clock-names = "core";
#reset-cells = <1>;
+ interconnects = <&system_noc MASTER_CRYPTO_CORE0 0 &bimc SLAVE_EBI1 0>;
};
};
@@ -170,32 +173,35 @@ psci {
CPU_PD0: power-domain-cpu0 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
CPU_PD1: power-domain-cpu1 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
CPU_PD2: power-domain-cpu2 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
CPU_PD3: power-domain-cpu3 {
#power-domain-cells = <0>;
- power-domains = <&CLUSTER_PD>;
+ //power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_SLEEP>;
};
+#if 0
CLUSTER_PD: power-domain-cpu-cluster {
#power-domain-cells = <0>;
+ power-domains = <&mpm>;
domain-idle-states = <&CLUSTER_SLEEP>;
};
+#endif
};
rpm: remoteproc {
@@ -261,6 +267,24 @@ rpmpd_opp_turbo_plus: opp8 {
};
};
};
+
+ mpm: interrupt-controller {
+ compatible = "qcom,mpm";
+ qcom,rpm-msg-ram = <&apss_mpm>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&apcs_glb 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ #power-domain-cells = <0>;
+ interrupt-parent = <&intc>;
+ qcom,mpm-pin-count = <96>;
+ qcom,mpm-pin-map = <2 275>, /* TSENS0 uplow */
+ <5 296>, /* Soundwire master_irq */
+ <12 422>, /* DWC3 ss_phy_irq */
+ <24 79>, /* Soundwire wake_irq */
+ <86 183>, /* MPM wake, SPMI */
+ <90 260>; /* DWC3 dp/dm_hs_phy_irq */
+ };
};
reserved_memory: reserved-memory {
@@ -424,6 +448,7 @@ tlmm: pinctrl@500000 {
interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
gpio-ranges = <&tlmm 0 0 127>;
+ wakeup-parent = <&mpm>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -668,6 +693,33 @@ usb_qmpphy: phy@1615000 {
status = "disabled";
};
+ system_noc: interconnect@1880000 {
+ compatible = "qcom,qcm2290-snoc";
+ reg = <0x0 0x01880000 0x0 0x60200>;
+ #interconnect-cells = <2>;
+
+ qup_virt: interconnect-qup {
+ compatible = "qcom,qcm2290-qup-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mmnrt_virt: interconnect-mmnrt {
+ compatible = "qcom,qcm2290-mmnrt-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mmrt_virt: interconnect-mmrt {
+ compatible = "qcom,qcm2290-mmrt-virt";
+ #interconnect-cells = <2>;
+ };
+ };
+
+ config_noc: interconnect@1900000 {
+ compatible = "qcom,qcm2290-cnoc";
+ reg = <0x0 0x01900000 0x0 0x8200>;
+ #interconnect-cells = <2>;
+ };
+
qfprom@1b44000 {
compatible = "qcom,qcm2290-qfprom", "qcom,qfprom";
reg = <0x0 0x01b44000 0x0 0x3000>;
@@ -680,6 +732,60 @@ qusb2_hstx_trim: hstx-trim@25b {
};
};
+ pmu@1b8e300 {
+ compatible = "qcom,qcm2290-cpu-bwmon", "qcom,sdm845-bwmon";
+ reg = <0 0x01b8e300 0 0x600>;
+ interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>;
+
+ operating-points-v2 = <&cpu_bwmon_opp_table>;
+ interconnects = <&bimc MASTER_APPSS_PROC 1
+ &bimc SLAVE_EBI1 1>;
+
+ cpu_bwmon_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-0 {
+ opp-peak-kBps = <1525000>;
+ };
+
+ opp-1 {
+ opp-peak-kBps = <2288000>;
+ };
+
+ opp-2 {
+ opp-peak-kBps = <3440000>;
+ };
+
+ opp-3 {
+ opp-peak-kBps = <4173000>;
+ };
+
+ opp-4 {
+ opp-peak-kBps = <5195000>;
+ };
+
+ opp-5 {
+ opp-peak-kBps = <5859000>;
+ };
+
+ opp-6 {
+ opp-peak-kBps = <7759000>;
+ };
+
+ opp-7 {
+ opp-peak-kBps = <10322000>;
+ };
+
+ opp-8 {
+ opp-peak-kBps = <11863000>;
+ };
+
+ opp-9 {
+ opp-peak-kBps = <13763000>;
+ };
+ };
+ };
+
spmi_bus: spmi@1c40000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x0 0x01c40000 0x0 0x1100>,
@@ -692,7 +798,7 @@ spmi_bus: spmi@1c40000 {
"obsrvr",
"intr",
"cnfg";
- interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&mpm 86 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "periph_irq";
qcom,ee = <0>;
qcom,channel = <0>;
@@ -707,8 +813,8 @@ tsens0: thermal-sensor@4411000 {
reg = <0x0 0x04411000 0x0 0x1ff>,
<0x0 0x04410000 0x0 0x8>;
#qcom,sensors = <10>;
- interrupts = <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&mpm 2 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uplow", "critical";
#thermal-sensor-cells = <1>;
};
@@ -720,9 +826,22 @@ rng: rng@4453000 {
clock-names = "core";
};
+ bimc: interconnect@4480000 {
+ compatible = "qcom,qcm2290-bimc";
+ reg = <0x0 0x04480000 0x0 0x80000>;
+ #interconnect-cells = <2>;
+ };
+
rpm_msg_ram: sram@45f0000 {
- compatible = "qcom,rpm-msg-ram";
+ compatible = "qcom,rpm-msg-ram", "mmio-sram";
reg = <0x0 0x045f0000 0x0 0x7000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0x045f0000 0x7000>;
+
+ apss_mpm: sram@1b8 {
+ reg = <0x1b8 0x48>;
+ };
};
sram@4690000 {
@@ -755,13 +874,43 @@ sdhc_1: mmc@4744000 {
resets = <&gcc GCC_SDCC1_BCR>;
power-domains = <&rpmpd QCM2290_VDDCX>;
+ operating-points-v2 = <&sdhc1_opp_table>;
iommus = <&apps_smmu 0xc0 0x0>;
+ interconnects = <&system_noc MASTER_SDCC_1 0 &bimc SLAVE_EBI1 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_SDCC_1 0>;
+ interconnect-names = "sdhc-ddr",
+ "cpu-sdhc";
qcom,dll-config = <0x000f642c>;
qcom,ddr-config = <0x80040868>;
bus-width = <8>;
status = "disabled";
+
+ sdhc1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <250000 133320>;
+ opp-avg-kBps = <102400 65000>;
+ };
+
+ opp-192000000 {
+ opp-hz = /bits/ 64 <192000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <204800 200000>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <204800 200000>;
+ };
+ };
};
sdhc_2: mmc@4784000 {
@@ -785,6 +934,10 @@ sdhc_2: mmc@4784000 {
power-domains = <&rpmpd QCM2290_VDDCX>;
operating-points-v2 = <&sdhc2_opp_table>;
iommus = <&apps_smmu 0xa0 0x0>;
+ interconnects = <&system_noc MASTER_SDCC_2 0 &bimc SLAVE_EBI1 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_SDCC_2 0>;
+ interconnect-names = "sdhc-ddr",
+ "cpu-sdhc";
qcom,dll-config = <0x0007642c>;
qcom,ddr-config = <0x80040868>;
@@ -798,11 +951,15 @@ sdhc2_opp_table: opp-table {
opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <250000 133320>;
+ opp-avg-kBps = <261438 150000>;
};
opp-202000000 {
opp-hz = /bits/ 64 <202000000>;
required-opps = <&rpmpd_opp_svs_plus>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <261438 300000>;
};
};
};
@@ -850,6 +1007,12 @@ i2c0: i2c@4a80000 {
dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
<&gpi_dma0 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI1 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -866,6 +1029,10 @@ spi0: spi@4a80000 {
dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
<&gpi_dma0 1 0 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -879,6 +1046,10 @@ uart0: serial@4a80000 {
clock-names = "se";
pinctrl-0 = <&qup_uart0_default>;
pinctrl-names = "default";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -893,6 +1064,12 @@ i2c1: i2c@4a84000 {
dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
<&gpi_dma0 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI1 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -909,6 +1086,10 @@ spi1: spi@4a84000 {
dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
<&gpi_dma0 1 1 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -925,6 +1106,12 @@ i2c2: i2c@4a88000 {
dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
<&gpi_dma0 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI1 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -941,6 +1128,10 @@ spi2: spi@4a88000 {
dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>,
<&gpi_dma0 1 2 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -957,6 +1148,12 @@ i2c3: i2c@4a8c000 {
dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
<&gpi_dma0 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI1 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -973,6 +1170,10 @@ spi3: spi@4a8c000 {
dmas = <&gpi_dma0 0 3 QCOM_GPI_SPI>,
<&gpi_dma0 1 3 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -989,6 +1190,12 @@ i2c4: i2c@4a90000 {
dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
<&gpi_dma0 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI1 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1005,6 +1212,10 @@ spi4: spi@4a90000 {
dmas = <&gpi_dma0 0 4 QCOM_GPI_SPI>,
<&gpi_dma0 1 4 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1018,6 +1229,10 @@ uart4: serial@4a90000 {
clock-names = "se";
pinctrl-0 = <&qup_uart4_default>;
pinctrl-names = "default";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
status = "disabled";
};
@@ -1032,6 +1247,12 @@ i2c5: i2c@4a94000 {
dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
<&gpi_dma0 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI1 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1048,6 +1269,10 @@ spi5: spi@4a94000 {
dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>,
<&gpi_dma0 1 5 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc MASTER_APPSS_PROC 0>;
+ interconnect-names = "qup-core",
+ "qup-config";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1057,9 +1282,10 @@ spi5: spi@4a94000 {
usb: usb@4ef8800 {
compatible = "qcom,qcm2290-dwc3", "qcom,dwc3";
reg = <0x0 0x04ef8800 0x0 0x400>;
- interrupts = <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "hs_phy_irq", "ss_phy_irq";
+ interrupts-extended = <&intc GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
+ <&mpm 12 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq",
+ "ss_phy_irq";
clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
<&gcc GCC_USB30_PRIM_MASTER_CLK>,
@@ -1080,6 +1306,11 @@ usb: usb@4ef8800 {
resets = <&gcc GCC_USB30_PRIM_BCR>;
power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+ /* TODO: USB<->IPA path */
+ interconnects = <&system_noc MASTER_USB3_0 0 &bimc SLAVE_EBI1 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3 0>;
+ interconnect-names = "usb-ddr",
+ "apps-usb";
wakeup-source;
#address-cells = <2>;
@@ -1105,6 +1336,223 @@ usb_dwc3: usb@4e00000 {
};
};
+ mdss: display-subsystem@5e00000 {
+ compatible = "qcom,qcm2290-mdss";
+ reg = <0x0 0x05e00000 0x0 0x1000>;
+ reg-names = "mdss";
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface",
+ "bus",
+ "core";
+
+ resets = <&dispcc DISP_CC_MDSS_CORE_BCR>;
+
+ power-domains = <&dispcc MDSS_GDSC>;
+
+ iommus = <&apps_smmu 0x420 0x2>,
+ <&apps_smmu 0x421 0x0>;
+ interconnects = <&mmrt_virt MASTER_MDP0 0 &bimc SLAVE_EBI1 0>,
+ <&bimc MASTER_APPSS_PROC 0 &config_noc SLAVE_DISPLAY_CFG 0>;
+ interconnect-names = "mdp0-mem",
+ "cpu-cfg";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ status = "disabled";
+
+ mdp: display-controller@5e01000 {
+ compatible = "qcom,qcm2290-dpu";
+ reg = <0x0 0x05e01000 0x0 0x8f000>,
+ <0x0 0x05eb0000 0x0 0x2008>;
+ reg-names = "mdp",
+ "vbif";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus",
+ "iface",
+ "core",
+ "lut",
+ "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&mdss_dsi0_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-19200000 {
+ opp-hz = /bits/ 64 <19200000>;
+ required-opps = <&rpmpd_opp_min_svs>;
+ };
+
+ opp-192000000 {
+ opp-hz = /bits/ 64 <192000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-256000000 {
+ opp-hz = /bits/ 64 <256000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-307200000 {
+ opp-hz = /bits/ 64 <307200000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+ };
+
+ mdss_dsi0: dsi@5e94000 {
+ compatible = "qcom,qcm2290-dsi-ctrl", "qcom,mdss-dsi-ctrl";
+ reg = <0x0 0x05e94000 0x0 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&mdss_dsi0_phy 0>,
+ <&mdss_dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+ phys = <&mdss_dsi0_phy>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ dsi_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-19200000 {
+ opp-hz = /bits/ 64 <19200000>;
+ required-opps = <&rpmpd_opp_min_svs>;
+ };
+
+ opp-164000000 {
+ opp-hz = /bits/ 64 <164000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ mdss_dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ mdss_dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ mdss_dsi0_phy: phy@5e94400 {
+ compatible = "qcom,dsi-phy-14nm-2290";
+ reg = <0x0 0x05e94400 0x0 0x100>,
+ <0x0 0x05e94500 0x0 0x300>,
+ <0x0 0x05e94800 0x0 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface",
+ "ref";
+
+ power-domains = <&rpmpd QCM2290_VDDMX>;
+ required-opps = <&rpmpd_opp_nom>;
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+ };
+
+ dispcc: clock-controller@5f00000 {
+ compatible = "qcom,qcm2290-dispcc";
+ reg = <0x0 0x05f00000 0x0 0x20000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&rpmcc RPM_SMD_XO_A_CLK_SRC>,
+ <&gcc GCC_DISP_GPLL0_CLK_SRC>,
+ <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>,
+ <&mdss_dsi0_phy 0>,
+ <&mdss_dsi0_phy 1>;
+ clock-names = "bi_tcxo",
+ "bi_tcxo_ao",
+ "gcc_disp_gpll0_clk_src",
+ "gcc_disp_gpll0_div_clk_src",
+ "dsi0_phy_pll_out_byteclk",
+ "dsi0_phy_pll_out_dsiclk";
+ #power-domain-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
remoteproc_mpss: remoteproc@6080000 {
compatible = "qcom,qcm2290-mpss-pas", "qcom,sm6115-mpss-pas";
reg = <0x0 0x06080000 0x0 0x100>;
diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
index 94885b9c21c..b85339aeb51 100644
--- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
@@ -23,6 +23,14 @@ chosen {
stdout-path = "serial0:115200n8";
};
+ clocks {
+ clk40M: can-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <40000000>;
+ #clock-cells = <0>;
+ };
+ };
+
gpio-keys {
compatible = "gpio-keys";
label = "gpio-keys";
@@ -72,6 +80,49 @@ led-wlan {
};
};
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con: endpoint {
+ remote-endpoint = <&lt9611_out>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-bt {
+ label = "blue:bt";
+ function = LED_FUNCTION_BLUETOOTH;
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&tlmm 45 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "bluetooth-power";
+ default-state = "off";
+ };
+
+ led-user0 {
+ label = "green:user0";
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&tlmm 52 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "off";
+ panic-indicator;
+ };
+
+ led-wlan {
+ label = "yellow:wlan";
+ function = LED_FUNCTION_WLAN;
+ color = <LED_COLOR_ID_YELLOW>;
+ gpios = <&tlmm 47 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "phy0tx";
+ default-state = "off";
+ };
+ };
+
vreg_hdmi_out_1p2: regulator-hdmi-out-1p2 {
compatible = "regulator-fixed";
regulator-name = "VREG_HDMI_OUT_1P2";
@@ -158,6 +209,68 @@ vph_pwr: regulator-vph-pwr {
};
};
+&gpi_dma0 {
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ lt9611_codec: hdmi-bridge@2b {
+ compatible = "lontium,lt9611uxc";
+ reg = <0x2b>;
+ interrupts-extended = <&tlmm 46 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 41 GPIO_ACTIVE_HIGH>;
+
+ vdd-supply = <&vreg_hdmi_out_1p2>;
+ vcc-supply = <&lt9611_3v3>;
+
+ pinctrl-0 = <&lt9611_irq_pin &lt9611_rst_pin>;
+ pinctrl-names = "default";
+ #sound-dai-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lt9611_a: endpoint {
+ remote-endpoint = <&mdss_dsi0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+
+ lt9611_out: endpoint {
+ remote-endpoint = <&hdmi_con>;
+ };
+ };
+ };
+ };
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ vdda-supply = <&pm2250_l5>;
+ status = "okay";
+};
+
+&mdss_dsi0_out {
+ remote-endpoint = <&lt9611_a>;
+ data-lanes = <0 1 2 3>;
+};
+
+&mdss_dsi0_phy {
+ status = "okay";
+};
+
&pm2250_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -376,7 +489,34 @@ &sdhc_2 {
status = "okay";
};
+&spi5 {
+ status = "okay";
+
+ can@0 {
+ compatible = "microchip,mcp2518fd";
+ reg = <0>;
+ interrupts-extended = <&tlmm 39 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&clk40M>;
+ spi-max-frequency = <10000000>;
+ vdd-supply = <&vdc_5v>;
+ xceiver-supply = <&vdc_5v>;
+ };
+};
+
&tlmm {
+ lt9611_rst_pin: lt9611-rst-state {
+ pins = "gpio41";
+ function = "gpio";
+ input-disable;
+ output-high;
+ };
+
+ lt9611_irq_pin: lt9611-irq-state {
+ pins = "gpio46";
+ function = "gpio";
+ bias-disable;
+ };
+
sd_det_in_on: sd-det-in-on-state {
pins = "gpio88";
function = "gpio";
@@ -427,6 +567,7 @@ &wifi {
vdd-1.8-xo-supply = <&pm2250_l13>;
vdd-1.3-rfa-supply = <&pm2250_l10>;
vdd-3.3-ch0-supply = <&pm2250_l22>;
+ qcom,ath10k-calibration-variant = "Thundercomm_RB1";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
index a7278a9472e..0372551e3d8 100644
--- a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
+++ b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
@@ -280,6 +280,12 @@ &remoteproc_cdsp {
status = "okay";
};
+&remoteproc_mpss {
+ firmware-name = "qcom/qrb4210/modem.mbn";
+
+ status = "okay";
+};
+
&rpm_requests {
regulators {
compatible = "qcom,rpm-pm6125-regulators";
@@ -346,8 +352,8 @@ vreg_l7a_1p256: l7 {
};
vreg_l8a_0p664: l8 {
- regulator-min-microvolt = <400000>;
- regulator-max-microvolt = <728000>;
+ regulator-min-microvolt = <640000>;
+ regulator-max-microvolt = <640000>;
};
vreg_l9a_1p8: l9 {
@@ -424,8 +430,8 @@ vreg_l22a_2p96: l22 {
};
vreg_l23a_3p3: l23 {
- regulator-min-microvolt = <3200000>;
- regulator-max-microvolt = <3400000>;
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3312000>;
};
vreg_l24a_2p96: l24 {
@@ -518,7 +524,6 @@ &usb {
&usb_dwc3 {
maximum-speed = "super-speed";
- dr_mode = "peripheral";
};
&usb_hsphy {
@@ -536,6 +541,15 @@ &usb_qmpphy {
status = "okay";
};
+&wifi {
+ vdd-0.8-cx-mx-supply = <&vreg_l8a_0p664>;
+ vdd-1.8-xo-supply = <&vreg_l16a_1p3>;
+ vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l23a_3p3>;
+ qcom,ath10k-calibration-variant = "Thundercomm_RB2";
+ status = "okay";
+};
+
&xo_board {
clock-frequency = <19200000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-tcl-b220g.dts b/arch/arm64/boot/dts/qcom/sc7180-tcl-b220g.dts
new file mode 100644
index 00000000000..a22062a9fc8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-tcl-b220g.dts
@@ -0,0 +1,639 @@
+// SPDX-License-Identifier: BSD-3-Clause
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "sc7180.dtsi"
+
+#include "pm6150.dtsi"
+#include "pm6150l.dtsi"
+
+/delete-node/ &tz_mem;
+/delete-node/ &ipa_fw_mem;
+
+/ {
+ model = "TCL Book 14 Go";
+ compatible = "tcl,b220g", "qcom,sc7180";
+ chassis-type = "laptop";
+
+ aliases {
+ bluetooth0 = &bluetooth;
+ hsuart0 = &uart3;
+ serial0 = &uart8;
+ wifi0 = &wifi;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reserved-memory {
+ zap_mem: zap-shader@80840000 {
+ reg = <0x0 0x80840000 0 0x2000>;
+ no-map;
+ };
+
+ venus_mem: venus@85b00000 {
+ reg = <0x0 0x85b00000 0 0x500000>;
+ no-map;
+ };
+
+ mpss_mem: mpss@86000000 {
+ reg = <0x0 0x86000000 0x0 0x2000000>;
+ no-map;
+ };
+
+ adsp_mem: adsp@8e400000 {
+ reg = <0x0 0x8e400000 0x0 0x2800000>;
+ no-map;
+ };
+
+ wlan_mem: wlan@93900000 {
+ reg = <0x0 0x93900000 0x0 0x200000>;
+ no-map;
+ };
+ // zap_mem: zap-shader@80840000 {
+ // reg = <0x0 0x80840000 0 0x2000>;
+ // no-map;
+ // };
+
+ // venus_mem: venus@85b00000 {
+ // reg = <0x0 0x85b00000 0 0x500000>;
+ // no-map;
+ // };
+
+ // mpss_mem: mpss@86000000 {
+ // reg = <0x0 0x86000000 0x0 0x2000000>;
+ // no-map;
+ // };
+
+ // adsp_mem: adsp@8be00000 {
+ // reg = <0x0 0x8be00000 0x0 0x1a00000>;
+ // no-map;
+ // };
+
+ // cdsp_mem: cdsp@98900000 {
+ // reg = <0x0 0x98900000 0x0 0x800000>;
+ // no-map;
+ // };
+
+ // slpi_mem: slpi@93700000 {
+ // reg = <0x0 0x93700000 0x0 0x1400000>;
+ // no-map;
+ // };
+
+ // wlan_mem: wlan@93900000 {
+ // reg = <0x0 0x93900000 0x0 0x200000>;
+ // no-map;
+ // };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* embedded-controller@76 */
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /*
+ * NOTE: DSDT defines two possible touchpads, other one is
+ *
+ * reg = <0x15>;
+ * hid-descr-addr = <0x1>;
+ */
+
+ touchpad@2c {
+ compatible = "hid-over-i2c";
+ reg = <0x2c>;
+ hid-descr-addr = <0x20>;
+
+ //vdd-supply = <&reg_tp_3p3>;
+
+ interrupts-extended = <&tlmm 94 IRQ_TYPE_LEVEL_LOW>;
+
+ // pinctrl-0 = <&hid_touchpad_default>;
+ // pinctrl-names = "default";
+
+ wakeup-source;
+ };
+
+ keyboard@3a {
+ compatible = "hid-over-i2c";
+ reg = <0x3a>;
+ hid-descr-addr = <0x1>;
+
+ interrupts-extended = <&tlmm 33 IRQ_TYPE_LEVEL_LOW>;
+
+ // pinctrl-0 = <&hid_keyboard_default>;
+ // pinctrl-names = "default";
+
+ wakeup-source;
+ };
+};
+
+&i2c9 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+};
+
+&i2c10 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+};
+
+&gpu {
+ status = "okay";
+
+ zap-shader {
+ memory-region = <&zap_mem>;
+ firmware-name = "qcom/sc7180/acer/aspire1/qcdxkmsuc7180.mbn";
+ };
+};
+
+// &mdss {
+// status = "okay";
+// };
+
+// &mdss_dsi0 {
+// vdda-supply = <&vreg_l3c_1p2>;
+// status = "okay";
+// };
+
+// &mdss_dsi0_out {
+// remote-endpoint = <&sn65dsi86_in>;
+// data-lanes = <0 1 2 3>;
+// };
+
+// &mdss_dsi0_phy {
+// vdds-supply = <&vreg_l4a_0p8>;
+// status = "okay";
+// };
+
+&pm6150_adc {
+ channel@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "thermistor";
+ };
+
+ channel@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ label = "charger_thermistor";
+ };
+};
+
+&pm6150_adc_tm {
+ status = "okay";
+
+ charger-thermistor@0 {
+ reg = <0>;
+ io-channels = <&pm6150_adc ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ thermistor@1 {
+ reg = <1>;
+ io-channels = <&pm6150_adc ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pm6150_pon {
+ status = "disabled";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&remoteproc_mpss {
+ firmware-name = "qcom/sc7180/acer/aspire1/qcmpss7180_nm.mbn";
+ status = "okay";
+};
+
+&sdhc_1 {
+ pinctrl-0 = <&sdc1_default>;
+ pinctrl-1 = <&sdc1_sleep>;
+ pinctrl-names = "default", "sleep";
+ vmmc-supply = <&vreg_l19a_2p9>;
+ vqmmc-supply = <&vreg_l12a_1p8>;
+
+ status = "okay";
+};
+
+&uart3 {
+ /delete-property/interrupts;
+ interrupts-extended = <&intc GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>,
+ <&tlmm 41 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-1 = <&qup_uart3_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ status = "okay";
+
+ bluetooth: bluetooth {
+ compatible = "qcom,wcn3991-bt";
+ vddio-supply = <&vreg_l10a_1p8>;
+ vddxo-supply = <&vreg_l1c_1p8>;
+ vddrf-supply = <&vreg_l2c_1p3>;
+ vddch0-supply = <&vreg_l10c_3p3>;
+ max-speed = <3200000>;
+ };
+};
+
+&uart8 {
+ status = "okay";
+};
+
+&ufs_mem_hc {
+ status = "okay";
+
+ reset-gpios = <&tlmm 150 GPIO_ACTIVE_LOW>;
+
+ // vcc-supply = <&vreg_l20a_2p95>;
+ // vcc-max-microamp = <600000>;
+};
+
+&ufs_mem_phy {
+ status = "okay";
+
+ vdda-phy-supply = <&vdd_ufs1_core>;
+ vdda-pll-supply = <&vdd_ufs1_1p2>;
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb_hub_2_x: hub@1 {
+ compatible = "usbbda,5411";
+ reg = <1>;
+ peer-hub = <&usb_hub_3_x>;
+ };
+
+ usb_hub_3_x: hub@2 {
+ compatible = "usbbda,411";
+ reg = <2>;
+ peer-hub = <&usb_hub_2_x>;
+ };
+};
+
+&usb_1_hsphy {
+ vdd-supply = <&vreg_l4a_0p8>;
+ vdda-pll-supply = <&vreg_l11a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l17a_3p0>;
+ qcom,imp-res-offset-value = <8>;
+ qcom,preemphasis-level = <QUSB2_V2_PREEMPHASIS_15_PERCENT>;
+ qcom,preemphasis-width = <QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT>;
+ qcom,bias-ctrl-value = <0x22>;
+ qcom,charge-ctrl-value = <3>;
+ qcom,hsdisc-trim-value = <0>;
+
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vreg_l3c_1p2>;
+ vdda-pll-supply = <&vreg_l4a_0p8>;
+
+ status = "okay";
+};
+
+&venus {
+ firmware-name = "qcom/sc7180/acer/aspire1/qcvss7180.mbn";
+};
+
+&wifi {
+ vdd-0.8-cx-mx-supply = <&vreg_l9a_0p6>;
+ vdd-1.8-xo-supply = <&vreg_l1c_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l2c_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l10c_3p3>;
+ vdd-3.3-ch1-supply = <&vreg_l11c_3p3>;
+
+ status = "okay";
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm6150-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vreg_s1a_1p1: smps1 {
+ regulator-min-microvolt = <1128000>;
+ regulator-max-microvolt = <1128000>;
+ };
+
+ vdd_ufs1_core:
+ vreg_l4a_0p8: ldo4 {
+ regulator-min-microvolt = <824000>;
+ regulator-max-microvolt = <928000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9a_0p6: ldo9 {
+ regulator-min-microvolt = <488000>;
+ regulator-max-microvolt = <800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10a_1p8: ldo10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vreg_l11a_1p8: ldo11 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ 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_l13a_1p8: ldo13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14a_1p8: ldo14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15a_1p8: ldo15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16a_2p7: ldo16 {
+ regulator-min-microvolt = <2496000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17a_3p0: ldo17 {
+ regulator-min-microvolt = <2920000>;
+ regulator-max-microvolt = <3232000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18a_2p8: ldo18 {
+ regulator-min-microvolt = <2496000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l19a_2p9: ldo19 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm6150l-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_s8c_1p3: smps8 {
+ regulator-min-microvolt = <1120000>;
+ regulator-max-microvolt = <1408000>;
+ };
+
+ vreg_l1c_1p8: ldo1 {
+ regulator-min-microvolt = <1616000>;
+ regulator-max-microvolt = <1984000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c_1p3: ldo2 {
+ regulator-min-microvolt = <1168000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_ufs1_1p2:
+ vreg_l3c_1p2: ldo3 {
+ regulator-min-microvolt = <1144000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c_1p8: ldo4 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_LPM>;
+ };
+
+ vreg_l5c_1p8: ldo5 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_LPM>;
+ };
+
+ vreg_l6c_2p9: ldo6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7c_3p0: ldo7 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_LPM>;
+ };
+
+ vreg_l8c_1p8: ldo8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9c_2p9: ldo9 {
+ regulator-min-microvolt = <2952000>;
+ regulator-max-microvolt = <2952000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10c_3p3: ldo10 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11c_3p3: ldo11 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+ };
+};
+
+// &qup_i2c2_default {
+// drive-strength = <2>;
+
+// /* Has external pullup */
+// bias-disable;
+// };
+
+// &qup_i2c4_default {
+// drive-strength = <2>;
+
+// /* Has external pullup */
+// bias-disable;
+// };
+
+// &qup_i2c9_default {
+// drive-strength = <2>;
+
+// /* Has external pullup */
+// bias-disable;
+// };
+
+// &qup_i2c10_default {
+// drive-strength = <2>;
+
+// /* Has external pullup */
+// bias-disable;
+// };
+
+&tlmm {
+ /*
+ * The TZ seem to protect those because some boards can have
+ * fingerprint sensor connected to this range. Not connected
+ * on this board
+ */
+ gpio-reserved-ranges = <58 5>;
+
+ qup_uart3_sleep: qup-uart3-sleep-state {
+ cts-pins {
+ /*
+ * Configure a pull-down on CTS to match the pull of
+ * the Bluetooth module.
+ */
+ pins = "gpio38";
+ function = "gpio";
+ bias-pull-down;
+ };
+
+ rts-pins {
+ /*
+ * Configure pull-down on RTS. As RTS is active low
+ * signal, pull it low to indicate the BT SoC that it
+ * can wakeup the system anytime from suspend state by
+ * pulling RX low (by sending wakeup bytes).
+ */
+ pins = "gpio39";
+ function = "gpio";
+ bias-pull-down;
+ };
+
+ tx-pins {
+ /*
+ * Configure pull-up on TX when it isn't actively driven
+ * to prevent BT SoC from receiving garbage during sleep.
+ */
+ pins = "gpio40";
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ rx-pins {
+ /*
+ * Configure a pull-up on RX. This is needed to avoid
+ * garbage data when the TX pin of the Bluetooth module
+ * is floating which may cause spurious wakeups.
+ */
+ pins = "gpio41";
+ function = "gpio";
+ bias-pull-up;
+ };
+ };
+
+ sdc1_default: sdc1-default-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+
+ sdc1_sleep: sdc1-sleep-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index 11f353d416b..df7b86f437a 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -1532,6 +1532,83 @@ mmss_noc: interconnect@1740000 {
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ ufs_mem_hc: ufshc@1d84000 {
+ compatible = "qcom,sdm845-ufshc", "qcom,ufshc",
+ "jedec,ufs-2.0";
+ reg = <0 0x01d84000 0 0x2500>,
+ <0 0x01d90000 0 0x8000>;
+ reg-names = "std", "ice";
+ interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&ufs_mem_phy_lanes>;
+ phy-names = "ufsphy";
+ lanes-per-direction = <2>;
+ power-domains = <&gcc UFS_PHY_GDSC>;
+ #reset-cells = <1>;
+ resets = <&gcc GCC_UFS_PHY_BCR>;
+ reset-names = "rst";
+
+ iommus = <&apps_smmu 0x100 0xf>;
+
+ clock-names =
+ "core_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk",
+ "ice_core_clk";
+ clocks =
+ <&gcc GCC_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_UFS_PHY_AHB_CLK>,
+ <&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+ freq-table-hz =
+ <50000000 200000000>,
+ <0 0>,
+ <0 0>,
+ <37500000 150000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <75000000 300000000>;
+
+ interconnects = <&aggre1_noc MASTER_UFS_MEM 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_UFS_MEM_CFG 0>;
+ interconnect-names = "ufs-ddr", "cpu-ufs";
+
+ status = "disabled";
+ };
+
+ ufs_mem_phy: phy@1d87000 {
+ compatible = "qcom,sdm845-qmp-ufs-phy";
+ reg = <0 0x01d87000 0 0x18c>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clock-names = "ref",
+ "ref_aux";
+ clocks = <&gcc GCC_UFS_MEM_CLKREF_CLK>,
+ <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
+
+ resets = <&ufs_mem_hc 0>;
+ reset-names = "ufsphy";
+ status = "disabled";
+
+ ufs_mem_phy_lanes: phy@1d87400 {
+ reg = <0 0x01d87400 0 0x108>,
+ <0 0x01d87600 0 0x1e0>,
+ <0 0x01d87c00 0 0x1dc>,
+ <0 0x01d87800 0 0x108>,
+ <0 0x01d87a00 0 0x1e0>;
+ #phy-cells = <0>;
+ };
+ };
+
ipa: ipa@1e40000 {
compatible = "qcom,sc7180-ipa";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
index c7eba6c491b..c58b57e78c7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -194,6 +194,7 @@ pcie0_3p3v_dual: vldo-3v3-regulator {
regulator-max-microvolt = <3300000>;
gpio = <&tlmm 90 GPIO_ACTIVE_HIGH>;
+ regulator-always-on;
enable-active-high;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
index 99dafc6716e..57ed447409d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
@@ -93,12 +93,6 @@ spss_mem: memory@99000000 {
no-map;
};
- /* Framebuffer region */
- memory@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x2400000>;
- no-map;
- };
-
/* rmtfs lower guard */
memory@f0800000 {
reg = <0 0xf0800000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
index b523b5fff70..2cd4567bc94 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
@@ -8,9 +8,11 @@
/dts-v1/;
#include <dt-bindings/input/linux-event-codes.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"
@@ -20,6 +22,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;
@@ -252,7 +289,6 @@ vreg_l14a_1p88: ldo14 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-always-on;
};
vreg_l17a_1p3: ldo17 {
@@ -388,6 +424,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>;
@@ -396,7 +434,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>;
};
@@ -484,6 +522,46 @@ &pmi8998_charger {
status = "okay";
};
+&pmi8998_flash {
+ status = "okay";
+
+ led-0 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ led-sources = <1>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <1500000>;
+ flash-max-timeout-us = <1280000>;
+ };
+
+ led-1 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_YELLOW>;
+ led-sources = <2>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <1500000>;
+ flash-max-timeout-us = <1280000>;
+ };
+};
+
+&pmi8998_haptics {
+ status = "okay";
+
+ qcom,wave-play-rate-us = <4255>;
+};
+
+&q6cvp {
+ status = "okay";
+};
+
+&q6cvs {
+ status = "okay";
+};
+
+&q6mvm {
+ status = "okay";
+};
+
&q6afedai {
qi2s@22 {
reg = <22>;
@@ -603,6 +681,13 @@ cpu {
};
};
+ voicemmode1-dai-link {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+
speaker_playback_dai: speaker-dai-link {
link-name = "Speaker Playback";
cpu {
@@ -780,8 +865,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;
@@ -849,4 +935,5 @@ &wifi {
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "oneplus_sdm845";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts b/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts
index 4005e04d998..476f0810fbc 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-enchilada.dts
@@ -6,6 +6,7 @@
*/
#include "sdm845-oneplus-common.dtsi"
+#include <dt-bindings/leds/common.h>
/ {
model = "OnePlus 6";
@@ -55,6 +56,33 @@ &pmi8998_charger {
monitored-battery = <&battery>;
};
+&pmi8998_lpg {
+ status = "okay";
+
+ multi-led {
+ color = <LED_COLOR_ID_RGB>;
+ function = LED_FUNCTION_STATUS;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@3 {
+ reg = <3>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+
+ led@4 {
+ reg = <4>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@5 {
+ reg = <5>;
+ color = <LED_COLOR_ID_RED>;
+ };
+ };
+};
+
&sound {
model = "OnePlus 6";
audio-routing = "RX_BIAS", "MCLK",
@@ -70,6 +98,11 @@ codec {
};
};
+&rmi4_f12 {
+ touchscreen-y-mm = <144>;
+ syna,clip-y-high = <2279>;
+};
+
&wcd9340 {
qcom,micbias1-microvolt = <1800000>;
qcom,micbias2-microvolt = <2700000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts b/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts
index 9471ada0d6a..5a81287fa6d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dts
@@ -30,7 +30,16 @@ &display_panel {
};
&i2c4 {
- /* nxp,tfa9894 @ 0x34 */
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tfa9894_codec: tfa9894@34 {
+ #sound-dai-cells = <1>;
+ compatible = "nxp,tfa9894";
+ reg = <0x34>;
+ reset-gpio = <&tlmm 69 0>;
+ };
+
};
&bq27441_fg {
@@ -51,15 +60,15 @@ &pmi8998_charger {
monitored-battery = <&battery>;
};
-/*
- * The TFA9894 codec is currently unsupported.
- * We need to delete the node to allow the soundcard
- * to probe for headphones/earpiece.
- */
-/delete-node/ &speaker_playback_dai;
+&speaker_playback_dai {
+ codec {
+ sound-dai = <&tfa9894_codec 0>;
+ };
+};
&rmi4_f12 {
touchscreen-y-mm = <148>;
+ syna,clip-y-high = <2339>;
};
&wcd9340 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
index d37a433130b..a3b0aff86c8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -11,11 +11,17 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sdm845.dtsi"
+/delete-node/ &rmtfs_mem;
+
/ {
chassis-type = "handset";
model = "Samsung Galaxy S9 SM-G9600";
compatible = "samsung,starqltechn", "qcom,sdm845";
+ aliases {
+ serial0 = &uart9;
+ };
+
chosen {
#address-cells = <2>;
#size-cells = <2>;
@@ -27,6 +33,9 @@ framebuffer: framebuffer@9d400000 {
height = <2960>;
stride = <(1440 * 4)>;
format = "a8r8g8b8";
+ vci-supply = <&s2dos05_ldo4>;
+ vddr-supply = <&s2dos05_buck1>;
+ vdd3-supply = <&s2dos05_ldo1>;
};
};
@@ -55,11 +64,6 @@ vreg_s4a_1p8: pm8998-smps4 {
};
reserved-memory {
- memory@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x02400000>;
- no-map;
- };
-
memory@a1300000 {
compatible = "ramoops";
reg = <0x0 0xa1300000 0x0 0x100000>;
@@ -68,6 +72,93 @@ memory@a1300000 {
ftrace-size = <0x40000>;
pmsg-size = <0x40000>;
};
+
+ /* The rmtfs_mem needs to be guarded due to "XPU limitations"
+ * it is otherwise possible for an allocation adjacent to the
+ * rmtfs_mem region to trigger an XPU violation, causing a crash.
+ */
+ rmtfs_lower_guard: memory@fde00000 {
+ no-map;
+ reg = <0 0xfde00000 0 0x1000>;
+ };
+
+ rmtfs_mem: rmtfs-mem@fde01000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0 0xfde01000 0 0x200000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
+ rmtfs_upper_guard: rmtfs-upper-guard@fe001000 {
+ no-map;
+ reg = <0 0xfe001000 0 0x1000>;
+ };
+
+ /*
+ * It seems like reserving the old rmtfs_mem region is also needed to prevent
+ * random crashes which are most likely modem related, more testing needed.
+ */
+ removed_region: removed-region@88f00000 {
+ no-map;
+ reg = <0 0x88f00000 0 0x1c00000>;
+ };
+ };
+
+ i2c@21 {
+ compatible = "i2c-gpio";
+ sda-gpios = <&tlmm 127 0x0>;
+ scl-gpios = <&tlmm 128 0x0>;
+ i2c-gpio,delay-us = <0x2>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c21_sda_state &i2c21_scl_state>;
+
+ regulator@60 {
+ compatible = "samsung,s2dos05";
+ reg = <0x60>;
+
+ regulators {
+ s2dos05_ldo1: s2dos05-ldo1 {
+ regulator-name = "s2dos05-ldo1";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ s2dos05_ldo2: s2dos05-ldo2 {
+ regulator-name = "s2dos05-ldo2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ s2dos05_ldo3: s2dos05-ldo3 {
+ regulator-name = "s2dos05-ldo3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-active-discharge = <0x1>;
+ regulator-boot-on;
+ };
+
+ s2dos05_ldo4: s2dos05-ldo4 {
+ regulator-name = "s2dos05-ldo4";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3775000>;
+ regulator-active-discharge = <0x1>;
+ };
+
+ s2dos05_buck1: s2dos05-buck1 {
+ regulator-name = "s2dos05-buck1";
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <2100000>;
+ regulator-active-discharge = <0x1>;
+ };
+ };
+ };
};
};
@@ -135,8 +226,6 @@ vdda_pll_cc_ebi23:
vdda_sp_sensor:
vdda_ufs1_core:
vdda_ufs2_core:
- vdda_usb1_ss_core:
- vdda_usb2_ss_core:
vreg_l1a_0p875: ldo1 {
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
@@ -157,6 +246,7 @@ vreg_l3a_1p0: ldo3 {
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vdda_usb1_ss_core:
vdd_wcss_cx:
vdd_wcss_mx:
vdda_wcss_pll:
@@ -365,6 +455,10 @@ &qupv3_id_1 {
status = "okay";
};
+&gpi_dma1 {
+ status = "okay";
+};
+
&uart9 {
status = "okay";
};
@@ -391,13 +485,55 @@ &sdhc_2 {
status = "okay";
};
+&i2c11 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ touchscreen@48 {
+ compatible = "samsung,s6sy761";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <120 0x0>;
+ vdd-supply = <&s2dos05_ldo2>;
+ avdd-supply = <&s2dos05_ldo3>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_irq_state>;
+ };
+};
+
+&crypto {
+ /* FIXME: qce_start triggers an SError */
+ status = "disable";
+};
+
+/* Modem/wifi*/
+&mss_pil {
+ status = "okay";
+ firmware-name = "qcom/sdm845/starqltechn/mba.mbn", "qcom/sdm845/starqltechn/modem.mbn";
+};
+
+&ipa {
+ qcom,gsi-loader = "self";
+ memory-region = <&ipa_fw_mem>;
+ firmware-name = "qcom/sdm845/starqltechn/ipa_fws.mbn";
+ status = "okay";
+};
+
&usb_1 {
status = "okay";
+ /*
+ * disable USB3 clock requirement as the device only supports
+ * USB2.
+ */
+ qcom,select-utmi-as-pipe-clk;
};
&usb_1_dwc3 {
/* Until we have Type C hooked up we'll force this as peripheral. */
dr_mode = "peripheral";
+
+ maximum-speed = "high-speed";
};
&usb_1_hsphy {
@@ -418,14 +554,6 @@ &usb_1_qmpphy {
status = "okay";
};
-&wifi {
- vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
- vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
- vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
- vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
- status = "okay";
-};
-
&tlmm {
gpio-reserved-ranges = <0 4>, <27 4>, <81 4>, <85 4>;
@@ -457,4 +585,40 @@ sd_card_det_n_state: sd-card-det-n-state {
function = "gpio";
bias-pull-up;
};
+
+ i2c21_sda_state: i2c-sda-state {
+ pins = "gpio127";
+ function = "gpio";
+ drive-strength = <0x2>;
+ bias-disable;
+ };
+
+ i2c21_scl_state: i2c-scl-state {
+ pins = "gpio128";
+ function = "gpio";
+ drive-strength = <0x2>;
+ bias-disable;
+ };
+
+ touch_irq_state: touch-irq-state {
+ pins = "gpio120";
+ function = "gpio";
+ bias-disable;
+ output-disable;
+ };
+};
+
+&qup_uart9_tx {
+ drive-strength = <0x2>;
+ bias-pull-up;
+};
+
+&qup_uart9_rx {
+ drive-strength = <0x2>;
+ bias-pull-up;
+};
+
+&qup_i2c11_default {
+ drive-strength = <2>;
+ bias-disable;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
index fbb8655653f..3fd0d3fd669 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
@@ -10,7 +10,11 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
#include "sdm845.dtsi"
+#include "sdm845-wcd9340.dtsi"
#include "pm8998.dtsi"
#include "pmi8998.dtsi"
@@ -22,6 +26,7 @@ / {
aliases {
display0 = &framebuffer0;
+ hsuart0 = &uart6;
serial0 = &uart9;
serial1 = &uart6;
};
@@ -60,11 +65,6 @@ key-vol-up {
};
reserved-memory {
- framebuffer_region@9d400000 {
- reg = <0x0 0x9d400000 0x0 (1080 * 2160 * 4)>;
- no-map;
- };
-
ramoops: ramoops@b0000000 {
compatible = "ramoops";
reg = <0 0xb0000000 0 0x00400000>;
@@ -434,25 +434,24 @@ zap-shader {
&i2c5 {
status = "okay";
+ clock-frequency = <400000>;
touchscreen@38 {
- compatible = "focaltech,fts8719";
+ compatible = "focaltech,ft5452";
reg = <0x38>;
- wakeup-source;
- interrupt-parent = <&tlmm>;
- interrupts = <125 IRQ_TYPE_EDGE_FALLING>;
- vdd-supply = <&vreg_l28a_3p0>;
- vcc-i2c-supply = <&vreg_l14a_1p88>;
- pinctrl-names = "default", "suspend";
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l28a_3p0>;
+ iovcc-supply = <&vreg_l14a_1p88>;
+
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ pinctrl-names = "default", "suspend";
- reset-gpio = <&tlmm 99 GPIO_ACTIVE_HIGH>;
- irq-gpio = <&tlmm 125 GPIO_TRANSITORY>;
touchscreen-size-x = <1080>;
touchscreen-size-y = <2160>;
- focaltech,max-touch-number = <5>;
};
};
@@ -460,6 +459,19 @@ &i2c10 {
/* SMB1355@0x0C */
};
+&i2c11 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tfa9890_codec: audio-codec@34 {
+ compatible = "nxp,tfa9890";
+ reg = <0x34>;
+ vddd-supply = <&vreg_s4a_1p8>;
+ sound-name-prefix = "Speaker";
+ #sound-dai-cells = <0>;
+ };
+};
+
&ipa {
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
@@ -485,7 +497,7 @@ panel@0 {
#address-cells = <1>;
#size-cells = <0>;
- reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sde_dsi_active &sde_te_active>;
@@ -532,6 +544,18 @@ &pmi8998_charger {
status = "okay";
};
+&pmi8998_fg {
+ status = "okay";
+ monitored-battery = <&battery>;
+ power-supplies = <&pmi8998_charger>;
+};
+
+&pmi8998_haptics {
+ status = "okay";
+
+ qcom,wave-play-rate-us = <4255>;
+};
+
&pm8998_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -586,6 +610,103 @@ led-1 {
};
};
+&q6cvp {
+ status = "okay";
+};
+
+&q6cvs {
+ status = "okay";
+};
+
+&q6mvm {
+ status = "okay";
+};
+
+&q6afedai {
+ qi2s@22 {
+ reg = <22>;
+ qcom,sd-lines = <0>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
+
+ dai@2 {
+ reg = <2>;
+ };
+
+ dai@3 {
+ reg = <3>;
+ };
+
+ dai@4 {
+ reg = <4>;
+ };
+
+ dai@5 {
+ reg = <5>;
+ };
+};
+
+/*
+ * Prevent garbage data on bluetooth UART lines
+ */
+&qup_uart6_default {
+ pinmux {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
+ function = "qup6";
+ };
+
+ cts {
+ pins = "gpio45";
+ bias-pull-down;
+ };
+
+ rts-tx {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio48";
+ bias-pull-up;
+ };
+};
+
+/*
+ * Prevent garbage data on bluetooth UART lines
+ */
+&qup_uart6_default {
+ pinmux {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
+ function = "qup6";
+ };
+
+ cts {
+ pins = "gpio45";
+ bias-pull-down;
+ };
+
+ rts-tx {
+ pins = "gpio46", "gpio47";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx {
+ pins = "gpio48";
+ bias-pull-up;
+ };
+};
+
&qup_uart9_rx {
drive-strength = <2>;
bias-pull-up;
@@ -604,14 +725,219 @@ &qupv3_id_1 {
status = "okay";
};
+&sdhc_2 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdc2_default_state &sdc2_card_det_n>;
+
+ vmmc-supply = <&vreg_l21a_2p95>;
+ vqmmc-supply = <&vreg_l13a_2p95>;
+
+ bus-width = <4>;
+ /* card detection is broken, but because the battery must be removed
+ * to insert the card, we use this rather than the broken-cd property
+ * which would just waste CPU cycles polling.
+ */
+ non-removable;
+};
+
&slpi_pas {
firmware-name = "qcom/sdm845/axolotl/slpi.mbn";
status = "okay";
};
+&sound {
+ model = "SHIFT6mq";
+ compatible = "qcom,sdm845-sndcard";
+ pinctrl-0 = <&quat_mi2s_active &quat_mi2s_sd0_active>;
+ pinctrl-names = "default";
+
+ audio-routing = "RX_BIAS", "MCLK",
+ "AMIC1", "MIC BIAS1",
+ "AMIC2", "MIC BIAS2",
+ "AMIC3", "MIC BIAS3",
+ "MM_DL1", "MultiMedia1 Playback",
+ "MM_DL3", "MultiMedia3 Playback",
+ "MM_DL5", "MultiMedia5 Playback",
+ "MultiMedia2 Capture", "MM_UL2",
+ "MultiMedia4 Capture", "MM_UL4",
+ "MultiMedia6 Capture", "MM_UL6";
+
+ mm1-dai-link {
+ link-name = "MultiMedia1";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ mm2-dai-link {
+ link-name = "MultiMedia2";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ };
+ };
+
+ mm3-dai-link {
+ link-name = "MultiMedia3";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ mm4-dai-link {
+ link-name = "MultiMedia4";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ mm5-dai-link {
+ link-name = "MultiMedia5";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA5>;
+ };
+ };
+
+ mm6-dai-link {
+ link-name = "MultiMedia6";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA6>;
+ };
+ };
+
+ speaker-dai-link {
+ link-name = "Speaker Playback";
+ codec {
+ sound-dai = <&tfa9890_codec>;
+ };
+
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slimcap-wcd-dai-link {
+ link-name = "SLIM WCD Capture 1";
+ codec {
+ sound-dai = <&wcd9340 1>; /* AIF1_CAP */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_1_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slim-dai-link {
+ link-name = "SLIM WCD Playback 1";
+ codec {
+ sound-dai = <&wcd9340 0>; /* AIF1_PB */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_0_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slimcap-dai-link {
+ link-name = "SLIM WCD Capture 2";
+ codec {
+ sound-dai = <&wcd9340 3>; /* AIF2_CAP */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_0_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slim-wcd-dai-link {
+ link-name = "SLIM WCD Playback 2";
+ codec {
+ sound-dai = <&wcd9340 2>; /* AIF2_PB */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_1_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ slimcap2-wcd-dai-link {
+ link-name = "SLIM WCD Capture 3";
+ codec {
+ sound-dai = <&wcd9340 5>; /* AIF3_CAP */
+ };
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_2_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+ };
+
+ voicemmode1-dai-link {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
+ sdc2_default_state: sdc2-default-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ bias-disable;
+
+ /*
+ * It seems that mmc_test reports errors if drive
+ * strength is not 16 on clk, cmd, and data pins.
+ */
+ drive-strength = <16>;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+ };
+
+ sdc2_card_det_n: sd-card-det-n-state {
+ pins = "gpio126";
+ function = "gpio";
+ bias-pull-up;
+ };
+
sde_dsi_active: sde-dsi-active-state {
pins = "gpio6", "gpio11";
function = "gpio";
@@ -739,6 +1065,22 @@ &venus {
firmware-name = "qcom/sdm845/axolotl/venus.mbn";
};
+&wcd9340 {
+ pinctrl-0 = <&wcd_intr_default>;
+ pinctrl-names = "default";
+ reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
+ vdd-buck-supply = <&vreg_s4a_1p8>;
+ vdd-buck-sido-supply = <&vreg_s4a_1p8>;
+ vdd-tx-supply = <&vreg_s4a_1p8>;
+ vdd-rx-supply = <&vreg_s4a_1p8>;
+ vdd-io-supply = <&vreg_s4a_1p8>;
+
+ qcom,micbias1-microvolt = <2700000>;
+ qcom,micbias2-microvolt = <2700000>;
+ qcom,micbias3-microvolt = <2700000>;
+ qcom,micbias4-microvolt = <2700000>;
+};
+
&wifi {
status = "okay";
@@ -749,4 +1091,5 @@ &wifi {
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
qcom,snoc-host-cap-8bit-quirk;
+ qcom,ath10k-calibration-variant = "shift_axolotl";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
index b02a1dc5fec..c4845b0e3b1 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
@@ -118,12 +118,6 @@ vreg_s4a_1p8: pm8998-smps4 {
};
reserved-memory {
- /* SONY was cool and didn't diverge from MTP this time, yay! */
- cont_splash_mem: memory@9d400000 {
- reg = <0x0 0x9d400000 0x0 0x2400000>;
- no-map;
- };
-
ramoops@ffc00000 {
compatible = "ramoops";
reg = <0x0 0xffc00000 0x0 0x100000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index 93b1582e807..3b2177bb175 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -7,6 +7,9 @@
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,q6voice.h>
#include "sdm845.dtsi"
#include "sdm845-wcd9340.dtsi"
#include "pm8998.dtsi"
@@ -99,12 +102,6 @@ spss_mem: memory@97f00000 {
no-map;
};
- /* Cont splash region set up by the bootloader */
- cont_splash_mem: framebuffer@9d400000 {
- reg = <0 0x9d400000 0 0x2400000>;
- no-map;
- };
-
rmtfs_mem: memory@f6301000 {
compatible = "qcom,rmtfs-mem";
reg = <0 0xf6301000 0 0x200000>;
@@ -243,6 +240,14 @@ &gmu {
status = "okay";
};
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
&gpu {
status = "okay";
@@ -264,7 +269,7 @@ &ibb {
&lab {
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <6000000>;
- regulator-over-current-protection;
+ // regulator-over-current-protection;
regulator-pull-down;
regulator-soft-start;
};
@@ -318,6 +323,26 @@ &ipa {
status = "okay";
};
+&i2c5 {
+ #dma-cells = <3>;
+ status="okay";
+
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+
+ /*smart PA*/
+ tas2559_codec: tas2559@4c{
+ #sound-dai-cells = <1>;
+ compatible = "ti,tas2559";
+ reg = <0x4c>;
+ ti,tas2559-reset-gpio = <&tlmm 12 0>;
+ ti,tas2560-reset-gpio = <&tlmm 76 0>;
+ ti,tas2559-addr = <0x4c>;
+ ti,tas2560-addr = <0x4d>;
+ };
+};
+
&pm8998_gpios {
vol_up_pin_a: vol-up-active-state {
pins = "gpio6";
@@ -355,6 +380,35 @@ &pmi8998_charger {
status = "okay";
};
+&pmi8998_flash {
+ status = "okay";
+
+ led-0 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ led-sources = <1>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <1500000>;
+ flash-max-timeout-us = <1280000>;
+ };
+
+ led-1 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_YELLOW>;
+ led-sources = <2>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <1500000>;
+ flash-max-timeout-us = <1280000>;
+ };
+};
+
+&pmi8998_fg {
+ status = "okay";
+
+ power-supplies = <&pmi8998_charger>;
+ monitored-battery = <&battery>;
+};
+
&pm8998_resin {
linux,code = <KEY_VOLUMEDOWN>;
status = "okay";
@@ -380,12 +434,37 @@ dai@1 {
dai@2 {
reg = <2>;
};
+
+ dai@3 {
+ reg = <3>;
+ };
+};
+
+&pmi8998_haptics {
+ status = "okay";
+ qcom,wave-play-rate-us = <4878>;
+};
+
+&q6cvp {
+ status = "okay";
+};
+
+&q6cvs {
+ status = "okay";
+};
+
+&q6mvm {
+ status = "okay";
};
&qupv3_id_0 {
status = "okay";
};
+&qupv3_id_1 {
+ status = "okay";
+};
+
&sdhc_2 {
status = "okay";
@@ -414,21 +493,50 @@ &sound {
mm1-dai-link {
link-name = "MultiMedia1";
cpu {
- sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
};
};
mm2-dai-link {
link-name = "MultiMedia2";
cpu {
- sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
};
};
mm3-dai-link {
link-name = "MultiMedia3";
cpu {
- sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ mm4-dai-link {
+ link-name = "MultiMedia4";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ dai-link-voicemmode1 {
+ link-name = "VoiceMMode1";
+ cpu {
+ sound-dai = <&q6voicedai VOICEMMODE1>;
+ };
+ };
+
+ tas2559-dai-link {
+ link-name = "Primary Spkr Playback";
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&tas2559_codec 0>;
};
};
@@ -448,7 +556,7 @@ codec {
};
slimcap-dai-link {
- link-name = "SLIM Capture";
+ link-name = "SLIM WCD Capture";
cpu {
sound-dai = <&q6afedai SLIMBUS_0_TX>;
};
@@ -458,7 +566,22 @@ platform {
};
codec {
- sound-dai = <&wcd9340 1>;
+ sound-dai = <&wcd9340 1>; /* AIF1_CAP */
+ };
+ };
+
+ slimcap2-dai-link {
+ link-name = "SLIM WCD Capture 2";
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_1_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&wcd9340 3>; /* AIF2_CAP */
};
};
};
@@ -491,6 +614,37 @@ sdc2_card_det_n: sd-card-det-n-state {
function = "gpio";
bias-pull-up;
};
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-pull-down;
+ input-enable;
+ };
+
+ ts_reset_default: ts-reset-default-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <16>;
+ output-high;
+ };
+
+ ts_int_sleep: ts-int-sleep-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ input-enable;
+ };
+
+ ts_reset_sleep: ts-reset-sleep-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
};
&uart6 {
@@ -579,4 +733,7 @@ &wifi {
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
+
+ qcom,snoc-host-cap-skip-quirk;
+ qcom,ath10k-calibration-variant = "xiaomi_beryllium";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
index 76931ebad06..74b4284b5f5 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
@@ -13,3 +13,24 @@ &display_panel {
compatible = "ebbg,ft8719";
status = "okay";
};
+
+&i2c14 {
+ status = "okay";
+
+ touchscreen@38 {
+ compatible = "focaltech,ft8719";
+ reg = <0x38>;
+
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+
+ iovcc-supply = <&vreg_l14a_1p8>;
+
+ pinctrl-0 = <&ts_int_default &ts_reset_default>;
+ pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2246>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
index e9427851eba..0ca1997f934 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
@@ -13,3 +13,24 @@ &display_panel {
compatible = "tianma,fhd-video", "novatek,nt36672a";
status = "okay";
};
+
+&i2c14 {
+ status = "okay";
+
+ touchscreen@1 {
+ compatible = "novatek,nvt-ts";
+ reg = <0x01>;
+
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
+
+ iovcc-supply = <&vreg_l14a_1p8>;
+
+ pinctrl-0 = <&ts_int_default &ts_reset_default>;
+ pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2246>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index bf5e6eb9d31..b0f1d08a620 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 {
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 92a812b5f42..d3a29e246c9 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -370,6 +370,44 @@ 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 = "dual";
+ data-role = "dual";
+ };
+
+ connector@1 {
+ compatible = "usb-c-connector";
+ reg = <1>;
+ power-role = "dual";
+ data-role = "dual";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@1 {
+ reg = <1>;
+ lenovo_ec_dp_in: endpoint {
+ remote-endpoint = <&mdss_dp_out>;
+ };
+ };
+ };
+ };
+ };
};
&i2c3 {
@@ -495,6 +533,20 @@ &mdss {
status = "okay";
};
+&mdss_dp {
+ status = "okay";
+ data-lanes = <0 1>;
+
+ ports {
+ port@1 {
+ reg = <1>;
+ mdss_dp_out: endpoint {
+ remote-endpoint = <&lenovo_ec_dp_in>;
+ };
+ };
+ };
+};
+
&mdss_dsi0 {
status = "okay";
vdda-supply = <&vreg_l26a_1p2>;
@@ -688,6 +740,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 54383731600..fae9492b9ec 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/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi
index 839c6035124..258eebfbaba 100644
--- a/arch/arm64/boot/dts/qcom/sm6115.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/firmware/qcom,scm.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interconnect/qcom,sm6115.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom-rpmpd.h>
@@ -264,6 +265,7 @@ firmware {
scm: scm {
compatible = "qcom,scm-sm6115", "qcom,scm";
#reset-cells = <1>;
+ interconnects = <&system_noc MASTER_CRYPTO_CORE0 0 &bimc SLAVE_EBI_CH0 0>;
};
};
@@ -859,6 +861,43 @@ usb_qmpphy: phy@1615000 {
status = "disabled";
};
+ system_noc: interconnect@1880000 {
+ compatible = "qcom,sm6115-snoc";
+ reg = <0x0 0x01880000 0x0 0x5f080>;
+ clocks = <&gcc GCC_SYS_NOC_CPUSS_AHB_CLK>,
+ <&gcc GCC_SYS_NOC_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>,
+ <&rpmcc RPM_SMD_IPA_CLK>;
+ clock-names = "cpu_axi",
+ "ufs_axi",
+ "usb_axi",
+ "ipa";
+ #interconnect-cells = <2>;
+
+ clk_virt: interconnect-clk {
+ compatible = "qcom,sm6115-clk-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mmrt_virt: interconnect-mmrt {
+ compatible = "qcom,sm6115-mmrt-virt";
+ #interconnect-cells = <2>;
+ };
+
+ mmnrt_virt: interconnect-mmnrt {
+ compatible = "qcom,sm6115-mmnrt-virt";
+ #interconnect-cells = <2>;
+ };
+ };
+
+ config_noc: interconnect@1900000 {
+ compatible = "qcom,sm6115-cnoc";
+ reg = <0x0 0x01900000 0x0 0x6200>;
+ clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>;
+ clock-names = "usb_axi";
+ #interconnect-cells = <2>;
+ };
+
qfprom@1b40000 {
compatible = "qcom,sm6115-qfprom", "qcom,qfprom";
reg = <0x0 0x01b40000 0x0 0x7000>;
@@ -883,6 +922,59 @@ rng: rng@1b53000 {
clock-names = "core";
};
+ pmu@1b8e300 {
+ compatible = "qcom,sm6115-cpu-bwmon", "qcom,sdm845-bwmon";
+ reg = <0x0 0x01b8e300 0x0 0x600>;
+ interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>;
+
+ operating-points-v2 = <&cpu_bwmon_opp_table>;
+ interconnects = <&bimc MASTER_AMPSS_M0 1 &bimc SLAVE_EBI_CH0 1>;
+
+ cpu_bwmon_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-0 {
+ opp-peak-kBps = <(200 * 4 * 1000)>;
+ };
+
+ opp-1 {
+ opp-peak-kBps = <(300 * 4 * 1000)>;
+ };
+
+ opp-2 {
+ opp-peak-kBps = <(451 * 4 * 1000)>;
+ };
+
+ opp-3 {
+ opp-peak-kBps = <(547 * 4 * 1000)>;
+ };
+
+ opp-4 {
+ opp-peak-kBps = <(681 * 4 * 1000)>;
+ };
+
+ opp-5 {
+ opp-peak-kBps = <(768 * 4 * 1000)>;
+ };
+
+ opp-6 {
+ opp-peak-kBps = <(1017 * 4 * 1000)>;
+ };
+
+ opp-7 {
+ opp-peak-kBps = <(1353 * 4 * 1000)>;
+ };
+
+ opp-8 {
+ opp-peak-kBps = <(1555 * 4 * 1000)>;
+ };
+
+ opp-9 {
+ opp-peak-kBps = <(1804 * 4 * 1000)>;
+ };
+ };
+ };
+
spmi_bus: spmi@1c40000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x0 0x01c40000 0x0 0x1100>,
@@ -912,6 +1004,12 @@ tsens0: thermal-sensor@4411000 {
#thermal-sensor-cells = <1>;
};
+ bimc: interconnect@4480000 {
+ compatible = "qcom,sm6115-bimc";
+ reg = <0x0 0x04480000 0x0 0x80000>;
+ #interconnect-cells = <2>;
+ };
+
rpm_msg_ram: sram@45f0000 {
compatible = "qcom,rpm-msg-ram";
reg = <0x0 0x045f0000 0x0 0x7000>;
@@ -939,8 +1037,40 @@ sdhc_1: mmc@4744000 {
<&gcc GCC_SDCC1_ICE_CORE_CLK>;
clock-names = "iface", "core", "xo", "ice";
+ power-domains = <&rpmpd SM6115_VDDCX>;
+ operating-points-v2 = <&sdhc1_opp_table>;
+ interconnects = <&system_noc MASTER_SDCC_1 0 &bimc SLAVE_EBI_CH0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_SDCC_1 0>;
+ interconnect-names = "sdhc-ddr",
+ "cpu-sdhc";
+
bus-width = <8>;
status = "disabled";
+
+ sdhc1_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <250000 133320>;
+ opp-avg-kBps = <102400 65000>;
+ };
+
+ opp-192000000 {
+ opp-hz = /bits/ 64 <192000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <204800 200000>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <204800 200000>;
+ };
+ };
};
sdhc_2: mmc@4784000 {
@@ -961,6 +1091,10 @@ sdhc_2: mmc@4784000 {
operating-points-v2 = <&sdhc2_opp_table>;
iommus = <&apps_smmu 0x00a0 0x0>;
resets = <&gcc GCC_SDCC2_BCR>;
+ interconnects = <&system_noc MASTER_SDCC_2 0 &bimc SLAVE_EBI_CH0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_SDCC_2 0>;
+ interconnect-names = "sdhc-ddr",
+ "cpu-sdhc";
bus-width = <4>;
qcom,dll-config = <0x0007642c>;
@@ -973,11 +1107,15 @@ sdhc2_opp_table: opp-table {
opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
required-opps = <&rpmpd_opp_low_svs>;
+ opp-peak-kBps = <250000 133320>;
+ opp-avg-kBps = <261438 150000>;
};
opp-202000000 {
opp-hz = /bits/ 64 <202000000>;
required-opps = <&rpmpd_opp_nom>;
+ opp-peak-kBps = <800000 300000>;
+ opp-avg-kBps = <261438 300000>;
};
};
};
@@ -1091,6 +1229,12 @@ i2c0: i2c@4a80000 {
dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
<&gpi_dma0 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1107,6 +1251,12 @@ spi0: spi@4a80000 {
dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
<&gpi_dma0 1 0 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1123,6 +1273,12 @@ i2c1: i2c@4a84000 {
dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
<&gpi_dma0 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1139,6 +1295,12 @@ spi1: spi@4a84000 {
dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
<&gpi_dma0 1 1 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1155,6 +1317,12 @@ i2c2: i2c@4a88000 {
dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
<&gpi_dma0 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1171,6 +1339,12 @@ spi2: spi@4a88000 {
dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>,
<&gpi_dma0 1 2 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1187,6 +1361,12 @@ i2c3: i2c@4a8c000 {
dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
<&gpi_dma0 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1203,6 +1383,12 @@ spi3: spi@4a8c000 {
dmas = <&gpi_dma0 0 3 QCOM_GPI_SPI>,
<&gpi_dma0 1 3 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1219,6 +1405,12 @@ i2c4: i2c@4a90000 {
dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
<&gpi_dma0 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1235,6 +1427,12 @@ spi4: spi@4a90000 {
dmas = <&gpi_dma0 0 4 QCOM_GPI_SPI>,
<&gpi_dma0 1 4 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1246,6 +1444,12 @@ uart4: serial@4a90000 {
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
status = "disabled";
};
@@ -1260,6 +1464,12 @@ i2c5: i2c@4a94000 {
dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
<&gpi_dma0 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1276,6 +1486,12 @@ spi5: spi@4a94000 {
dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>,
<&gpi_dma0 1 5 QCOM_GPI_SPI>;
dma-names = "tx", "rx";
+ interconnects = <&clk_virt MASTER_QUP_CORE_0 0 &clk_virt SLAVE_QUP_CORE_0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_QUP_0 0>,
+ <&system_noc MASTER_QUP_0 0 &bimc SLAVE_EBI_CH0 0>;
+ interconnect-names = "qup-core",
+ "qup-config",
+ "qup-memory";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -1307,6 +1523,12 @@ usb: usb@4ef8800 {
resets = <&gcc GCC_USB30_PRIM_BCR>;
power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+ /* TODO: USB<->IPA path */
+ interconnects = <&system_noc MASTER_USB3 0 &bimc SLAVE_EBI_CH0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_USB3 0>;
+ interconnect-names = "usb-ddr",
+ "apps-usb";
+
qcom,select-utmi-as-pipe-clk;
status = "disabled";
@@ -1478,6 +1700,11 @@ mdss: display-subsystem@5e00000 {
iommus = <&apps_smmu 0x420 0x2>,
<&apps_smmu 0x421 0x0>;
+ interconnects = <&mmrt_virt MASTER_MDP_PORT0 0 &bimc SLAVE_EBI_CH0 0>,
+ <&bimc MASTER_AMPSS_M0 0 &config_noc SLAVE_DISPLAY_CFG 0>;
+ interconnect-names = "mdp0-mem",
+ "cpu-cfg";
+
#address-cells = <2>;
#size-cells = <2>;
ranges;
diff --git a/arch/arm64/configs/sdm845.config b/arch/arm64/configs/sdm845.config
new file mode 100644
index 00000000000..91bb92c77a6
--- /dev/null
+++ b/arch/arm64/configs/sdm845.config
@@ -0,0 +1,1014 @@
+# Qualcomm Snapdragon 845 (SDM845) config fragment
+CONFIG_LOCALVERSION="-sdm845"
+
+# OnePlus 6
+CONFIG_DRM_PANEL_SAMSUNG_SOFEF00=y
+CONFIG_BATTERY_BQ27XXX=m
+CONFIG_HID_RMI=m
+CONFIG_RMI4_CORE=m
+CONFIG_RMI4_I2C=m
+CONFIG_RMI4_F55=y
+
+# OnePlus 6T
+CONFIG_DRM_PANEL_SAMSUNG_S6E3FC2X01=y
+CONFIG_SND_SOC_TFA98XX=m
+
+# Pocophone F1
+CONFIG_DRM_PANEL_NOVATEK_NT36672A=y
+CONFIG_DRM_PANEL_EBBG_FT8719=y
+CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS=m
+CONFIG_QCOM_GPI_DMA=m
+CONFIG_SND_SOC_TAS2559=m
+
+# Samsung S9 SM-G9600(starqltechn)
+CONFIG_TOUCHSCREEN_S6SY761=m
+CONFIG_REGULATOR_S2DOS05=m
+
+# SHIFT6mq
+CONFIG_DRM_PANEL_VISIONOX_RM69299_SHIFT=y
+CONFIG_SND_SOC_TFA989X=m
+
+# Odin
+# Driver has been dropped
+CONFIG_DRM_PANEL_INNOLUX_TD4328=y
+
+# Mi Mix 2S
+CONFIG_DRM_PANEL_NOVATEK_NT35596S=y
+
+# C630
+CONFIG_DRM_TI_SN65DSI86=m
+CONFIG_DRM_PANEL_EDP=m
+CONFIG_PHY_QCOM_EDP=m
+CONFIG_I2C_HID_OF_ELAN=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
+
+# 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
+
+# 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
+
+# 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
+
+# SC7180
+CONFIG_SC_GPUCC_7180=y
+CONFIG_SC_LPASS_CORECC_7180=y
+CONFIG_SC_MSS_7180=y
+CONFIG_SC_VIDEOCC_7180=y
+CONFIG_INTERCONNECT_QCOM_SC7180=y
+CONFIG_SC_DISPCC_7180=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_NF_TABLES=m
+CONFIG_NF_TABLES_INET=y
+CONFIG_NFT_CT=m
+CONFIG_NFT_COUNTER=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
+
+# pmos containers kconfig
+CONFIG_CGROUP_FREEZER=y
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_DUMMY=m
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_RR=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_DM_THIN_PROVISIONING=y
+CONFIG_VXLAN=m
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_IPVLAN=m
+
+# pmOS ZRAM kconfig
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_ZRAM=m
+CONFIG_ZRAM_DEF_COMP_ZSTD=y
+CONFIG_ZRAM_DEF_COMP="zstd"
+CONFIG_ZRAM_MEMORY_TRACKING=y
+CONFIG_ZRAM_MULTI_COMP=y
+CONFIG_CRYPTO_LZ4=m
+CONFIG_LZ4_COMPRESS=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_ZSTD=m
+
+# pmOS iwd kconfig
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_KEY_DH_OPERATIONS=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=y
+
+# pmOS wireguard kconfig
+CONFIG_WIREGUARD=m
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NFT_FIB=m
+CONFIG_NFT_FIB_IPV4=m
+CONFIG_NFT_FIB_IPV6=m
+CONFIG_FIB_RULES=y
+
+# pmOS community kconfig
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+# LEDs
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+# Game controllers, etc
+CONFIG_HID_SONY=m
+CONFIG_SONY_FF=y
+CONFIG_HID_NINTENDO=m
+
+# Disable all unrelated stuffs afaik
+CONFIG_HIBERNATION=n
+CONFIG_FW_LOADER_USER_HELPER=n
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n
+CONFIG_BLK_DEV_NVME=n
+CONFIG_ATA=n
+CONFIG_MTD=n
+CONFIG_SRAM=n
+CONFIG_MEGARAID_SAS=n
+CONFIG_EEPROM_AT25=n
+CONFIG_SCSI_MPT3SAS=n
+CONFIG_BLK_DEV_MD=n
+CONFIG_DM_MIRROR=n
+CONFIG_DM_ZERO=n
+CONFIG_EXT2_FS=n
+CONFIG_EXT3_FS=n
+CONFIG_USB_DWC2=n
+CONFIG_USB_CHIPIDEA=n
+CONFIG_USB_MUSB_HDRC=n
+CONFIG_USB_ISP1760=n
+CONFIG_USB_HSIC_USB3503=n
+CONFIG_USB_NET_PLUSB=n
+CONFIG_TYPEC_FUSB302=n
+CONFIG_EXTCON_PTN5150=n
+CONFIG_REALTEK_PHY=n
+CONFIG_NET_VENDOR_NI=n
+CONFIG_NET_9P=n
+CONFIG_CAN=n
+CONFIG_BNX2X=n
+CONFIG_MACB=n
+CONFIG_IGB=n
+CONFIG_IGBVF=n
+CONFIG_SMC91X=n
+CONFIG_MLX4_EN=n
+CONFIG_MLX5_CORE=n
+CONFIG_STMMAC_ETH=n
+CONFIG_ATL1C=n
+CONFIG_BRCMFMAC=n
+CONFIG_WL18XX=n
+CONFIG_WLCORE=n
+CONFIG_ATH10K_PCI=n
+CONFIG_NET_SCH_CBS=n
+CONFIG_NET_SCH_ETF=n
+CONFIG_NET_SCH_TAPRIO=n
+CONFIG_NET_SCH_MQPRIO=n
+CONFIG_NET_CLS_BASIC=n
+CONFIG_NET_CLS_FLOWER=n
+CONFIG_NET_CLS_ACT=n
+CONFIG_NET_ACT_GACT=n
+CONFIG_NET_ACT_MIRRED=n
+CONFIG_NET_ACT_GATE=n
+CONFIG_MDIO_BUS_MUX_MMIOREG=n
+CONFIG_MDIO_BUS_MUX_MULTIPLEXER=n
+CONFIG_SND_SOC_ES7134=n
+CONFIG_SND_SOC_ES7241=n
+CONFIG_SND_SOC_TAS571X=n
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER=n
+CONFIG_GPIO_DWAPB=n
+CONFIG_COMMON_CLK_XGENE=n
+CONFIG_SENSORS_ARM_SCPI=n
+CONFIG_TCG_TPM=n
+CONFIG_BATTERY_SBS=n
+CONFIG_REGULATOR_VCTRL=n
+CONFIG_SND_SOC_MAX98357A=n
+CONFIG_SND_SOC_RL6231=n
+CONFIG_THUNDER_NIC_BGX=n
+CONFIG_THUNDER_NIC_RGX=n
+CONFIG_MDIO_THUNDER=n
+CONFIG_CAVIUM_ERRATUM_22375=n
+CONFIG_CAVIUM_ERRATUM_23154=n
+CONFIG_CAVIUM_ERRATUM_27456=n
+CONFIG_CAVIUM_ERRATUM_30115=n
+CONFIG_CAVIUM_TX2_ERRATUM_219=n
+CONFIG_HW_RANDOM_CAVIUM=n
+CONFIG_EEPROM_AT24=n
+CONFIG_NET_DSA=n
+CONFIG_AQUANTIA_PHY=n
+CONFIG_MICROSEMI_PHY=n
+CONFIG_VITESSE_PHY=n
+CONFIG_I2C_MUX_PCA954x=n
+CONFIG_SND_SOC_PCM3168A_I2C=n
+CONFIG_SENSORS_LM90=n
+CONFIG_SENSORS_INA2XX=n
+CONFIG_RTC_DRV_DS3232=n
+CONFIG_SPI_NXP_FLEXSPI=n
+CONFIG_GPIO_MAX732X=n
+CONFIG_SENSORS_ISL29018=n
+CONFIG_MPL3115=n
+CONFIG_MFD_ROHM_BD718XX=n
+CONFIG_ARM_SBSA_WATCHDOG=n
+CONFIG_ARM_SMC_WATCHDOG=n
+CONFIG_REGULATOR_PCA9450=n
+CONFIG_REGULATOR_PFUZE100=n
+CONFIG_DRM_PANEL_RAYDIUM_RM67191=n
+CONFIG_DRM_PANEL_SITRONIX_ST7703=n
+CONFIG_PHY_MIXEL_MIPI_DPHY=n
+CONFIG_DRM_NWL_MIPI_DSI=n
+CONFIG_DRM_MXSFB=n
+CONFIG_SND_SOC_FSL_SAI=n
+CONFIG_SND_SOC_FSL_ASRC=n
+CONFIG_SND_SOC_FSL_MICFIL=n
+CONFIG_SND_SOC_FSL_AUDMIX=n
+CONFIG_SND_SOC_FSL_SPDIF=n
+CONFIG_SND_SOC_WM8904=n
+CONFIG_RTC_DRV_RV8803=n
+CONFIG_RTC_DRV_DS1307=n
+CONFIG_RTC_DRV_PCF85363=n
+CONFIG_RTC_DRV_PCF2127=n
+CONFIG_PHY_FSL_IMX8MQ_USB=n
+CONFIG_FUJITSU_ERRATUM_010001=n
+CONFIG_PCI_PASID=n
+CONFIG_UACCE=n
+CONFIG_SPI_CADENCE_QUADSPI=n
+CONFIG_DW_WATCHDOG=n
+CONFIG_NOP_USB_XCEIV=n
+CONFIG_SURFACE_PLATFORMS=n
+CONFIG_GPIO_PCA953X=n
+CONFIG_BACKLIGHT_LP855X=n
+CONFIG_MFD_MAX77620=n
+CONFIG_SENSORS_PWM_FAN=n
+CONFIG_SENSORS_INA3221=n
+CONFIG_REGULATOR_MAX8973=n
+CONFIG_USB_CONN_GPIO=n
+CONFIG_MICREL_PHY=n
+CONFIG_MFD_BD9571MWV=n
+CONFIG_DRM_PANEL_LVDS=n
+CONFIG_DRM_RCAR_LVDS=n
+CONFIG_COMMON_CLK_VC5=n
+CONFIG_CRYPTO_DEV_CCREE=n
+CONFIG_VIDEO_IMX219=n
+CONFIG_VIDEO_OV5645=n
+CONFIG_SND_SOC_AK4613=n
+CONFIG_SND_SIMPLE_CARD=n
+CONFIG_SND_SIMPLE_CARD_UTILS=n
+CONFIG_SND_AUDIO_GRAPH_CARD=n
+CONFIG_TYPEC_HD3SS3220=n
+CONFIG_RTC_DRV_RX8581=n
+CONFIG_COMMON_CLK_CS2000_CP=n
+CONFIG_KEYBOARD_ADC=n
+CONFIG_REGULATOR_FAN53555=n
+CONFIG_TOUCHSCREEN_ATMEL_MXT=n
+CONFIG_RTC_DRV_HYM8563=n
+CONFIG_MFD_SEC_CORE=n
+CONFIG_PL330_DMA=n
+CONFIG_GPIO_MB86S7X=n
+CONFIG_MMC_SDHCI_F_SDH30=n
+CONFIG_MMC_SDHCI_CADENCE=n
+CONFIG_SOCIONEXT_SYNQUACER_PREITS=n
+CONFIG_NET_VENDOR_SOCIONEXT=n
+CONFIG_ARCH_ACTIONS=n
+CONFIG_ARCH_AGILEX=n
+CONFIG_ARCH_N5X=n
+CONFIG_ARCH_SUNXI=n
+CONFIG_ARCH_ALPINE=n
+CONFIG_ARCH_APPLE=n
+CONFIG_ARCH_BCM2835=n
+CONFIG_ARCH_BCM4908=n
+CONFIG_ARCH_BCM_IPROC=n
+CONFIG_ARCH_BERLIN=n
+CONFIG_ARCH_BRCMSTB=n
+CONFIG_ARCH_EXYNOS=n
+CONFIG_ARCH_K3=n
+CONFIG_ARCH_LAYERSCAPE=n
+CONFIG_ARCH_LG1K=n
+CONFIG_ARCH_HISI=n
+CONFIG_ARCH_KEEMBAY=n
+CONFIG_ARCH_MEDIATEK=n
+CONFIG_ARCH_MESON=n
+CONFIG_ARCH_MVEBU=n
+CONFIG_ARCH_MXC=n
+CONFIG_ARCH_RENESAS=n
+CONFIG_ARCH_ROCKCHIP=n
+CONFIG_ARCH_S32=n
+CONFIG_ARCH_SEATTLE=n
+CONFIG_ARCH_INTEL_SOCFPGA=n
+CONFIG_ARCH_SYNQUACER=n
+CONFIG_ARCH_TEGRA=n
+CONFIG_ARCH_SPRD=n
+CONFIG_ARCH_THUNDER=n
+CONFIG_ARCH_THUNDER2=n
+CONFIG_ARCH_UNIPHIER=n
+CONFIG_ARCH_VEXPRESS=n
+CONFIG_ARCH_VISCONTI=n
+CONFIG_ARCH_XGENE=n
+CONFIG_ARCH_ZX=n
+CONFIG_ARCH_ZYNQMP=n
+CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM=n
+CONFIG_ARM_ARMADA_37XX_CPUFREQ=n
+CONFIG_ARM_IMX_CPUFREQ_DT=n
+CONFIG_ARM_RASPBERRYPI_CPUFREQ=n
+CONFIG_ARM_TEGRA186_CPUFREQ=n
+CONFIG_QORIQ_CPUFREQ=n
+CONFIG_RASPBERRYPI_FIRMWARE=n
+CONFIG_INTEL_STRATIX10_SERVICE=n
+CONFIG_INTEL_STRATIX10_RSU=n
+CONFIG_IMX_SCU=n
+CONFIG_IMX_SCU_PD=n
+CONFIG_CAN_RCAR=n
+CONFIG_CAN_RCAR_CANFD=n
+CONFIG_CAN_FLEXCAN=n
+CONFIG_PCI_AARDVARK=n
+CONFIG_PCI_TEGRA=n
+CONFIG_PCIE_RCAR_HOST=n
+CONFIG_PCIE_RCAR_EP=n
+CONFIG_PCI_XGENE=n
+CONFIG_PCIE_ALTERA=n
+CONFIG_PCIE_ALTERA_MSI=n
+CONFIG_PCI_HOST_THUNDER_PEM=n
+CONFIG_PCI_HOST_THUNDER_ECAM=n
+CONFIG_PCIE_ROCKCHIP_HOST=n
+CONFIG_PCIE_BRCMSTB=n
+CONFIG_PCI_IMX6=n
+CONFIG_PCI_LAYERSCAPE=n
+CONFIG_PCIE_LAYERSCAPE_GEN4=n
+CONFIG_PCI_HISI=n
+CONFIG_PCIE_ARMADA_8K=n
+CONFIG_PCIE_KIRIN=n
+CONFIG_PCIE_HISI_STB=n
+CONFIG_PCIE_TEGRA194_HOST=n
+CONFIG_HISILICON_LPC=n
+CONFIG_FSL_MC_BUS=n
+CONFIG_TEGRA_ACONNECT=n
+CONFIG_MTD_CFI_INTELEXT=n
+CONFIG_MTD_CFI_AMDSTD=n
+CONFIG_MTD_CFI_STAA=n
+CONFIG_MTD_SST25L=n
+CONFIG_MTD_NAND_DENALI_DT=n
+CONFIG_MTD_NAND_MARVELL=n
+CONFIG_MTD_NAND_FSL_IFC=n
+CONFIG_SCSI_HISI_SAS=n
+CONFIG_SCSI_HISI_SAS_PCI=n
+CONFIG_SCSI_UFS_HISI=n
+CONFIG_SCSI_UFS_EXYNOS=n
+CONFIG_AHCI_CEVA=n
+CONFIG_AHCI_MVEBU=n
+CONFIG_AHCI_XGENE=n
+CONFIG_AHCI_QORIQ=n
+CONFIG_SATA_SIL24=n
+CONFIG_SATA_RCAR=n
+CONFIG_FSL_FMAN=n
+CONFIG_FSL_DPAA_ETH=n
+CONFIG_FSL_DPAA2_ETH=n
+CONFIG_FSL_ENETC=n
+CONFIG_FSL_ENETC_VF=n
+CONFIG_FSL_ENETC_QOS=n
+CONFIG_HIX5HD2_GMAC=n
+CONFIG_HNS_DSAF=n
+CONFIG_HNS_ENET=n
+CONFIG_HNS3=n
+CONFIG_HNS3_HCLGE=n
+CONFIG_HNS3_ENET=n
+CONFIG_SERIAL_MESON=n
+CONFIG_SERIAL_MESON_CONSOLE=n
+CONFIG_SERIAL_SAMSUNG=n
+CONFIG_SERIAL_SAMSUNG_CONSOLE=n
+CONFIG_SERIAL_TEGRA=n
+CONFIG_SERIAL_TEGRA_TCU=n
+CONFIG_SERIAL_IMX=n
+CONFIG_SERIAL_IMX_CONSOLE=n
+CONFIG_SERIAL_XILINX_PS_UART=n
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=n
+CONFIG_SERIAL_FSL_LPUART=n
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=n
+CONFIG_SERIAL_FSL_LINFLEXUART=n
+CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=n
+CONFIG_SERIAL_MVEBU_UART=n
+CONFIG_SERIAL_OWL=n
+CONFIG_I2C_BCM2835=n
+CONFIG_I2C_DESIGNWARE_PLATFORM=n
+CONFIG_I2C_IMX=n
+CONFIG_I2C_IMX_LPI2C=n
+CONFIG_I2C_MESON=n
+CONFIG_I2C_MT65XX=n
+CONFIG_I2C_MV64XXX=n
+CONFIG_I2C_OMAP=n
+CONFIG_I2C_OWL=n
+CONFIG_I2C_PXA=n
+CONFIG_I2C_RK3X=n
+CONFIG_I2C_SH_MOBILE=n
+CONFIG_I2C_TEGRA=n
+CONFIG_I2C_UNIPHIER_F=n
+CONFIG_I2C_RCAR=n
+CONFIG_SPI_ARMADA_3700=n
+CONFIG_SPI_BCM2835=n
+CONFIG_SPI_BCM2835AUX=n
+CONFIG_SPI_DESIGNWARE=n
+CONFIG_SPI_DW_DMA=n
+CONFIG_SPI_DW_MMIO=n
+CONFIG_SPI_FSL_LPSPI=n
+CONFIG_SPI_FSL_QUADSPI=n
+CONFIG_SPI_IMX=n
+CONFIG_SPI_FSL_DSPI=n
+CONFIG_SPI_MESON_SPICC=n
+CONFIG_SPI_MESON_SPIFC=n
+CONFIG_SPI_ORION=n
+CONFIG_SPI_PL022=n
+CONFIG_SPI_ROCKCHIP=n
+CONFIG_SPI_RPCIF=n
+CONFIG_SPI_S3C64XX=n
+CONFIG_SPI_SH_MSIOF=n
+CONFIG_SPI_SUN6I=n
+CONFIG_PINCTRL_MAX77620=n
+CONFIG_PINCTRL_OWL=n
+CONFIG_PINCTRL_S700=n
+CONFIG_PINCTRL_S900=n
+CONFIG_PINCTRL_IMX8MM=n
+CONFIG_PINCTRL_IMX8MN=n
+CONFIG_PINCTRL_IMX8MP=n
+CONFIG_PINCTRL_IMX8MQ=n
+CONFIG_PINCTRL_IMX8QM=n
+CONFIG_PINCTRL_IMX8QXP=n
+CONFIG_PINCTRL_IMX8DXL=n
+CONFIG_GPIO_ALTERA=n
+CONFIG_GPIO_DAVINCI=n
+CONFIG_GPIO_MPC8XXX=n
+CONFIG_GPIO_MXC=n
+CONFIG_GPIO_PL061=n
+CONFIG_GPIO_RCAR=n
+CONFIG_GPIO_UNIPHIER=n
+CONFIG_GPIO_VISCONTI=n
+CONFIG_GPIO_XGENE=n
+CONFIG_GPIO_XGENE_SB=n
+CONFIG_GPIO_PCA953X_IRQ=n
+CONFIG_GPIO_BD9571MWV=n
+CONFIG_GPIO_MAX77620=n
+CONFIG_GPIO_SL28CPLD=n
+CONFIG_ROCKCHIP_IODOMAIN=n
+CONFIG_POWER_RESET_XGENE=n
+CONFIG_POWER_RESET_SYSCON=n
+CONFIG_GNSS_MTK_SERIAL=n
+CONFIG_SENSORS_RASPBERRYPI_HWMON=n
+CONFIG_SENSORS_SL28CPLD=n
+CONFIG_QORIQ_THERMAL=n
+CONFIG_SUN8I_THERMAL=n
+CONFIG_IMX_SC_THERMAL=n
+CONFIG_IMX8MM_THERMAL=n
+CONFIG_ROCKCHIP_THERMAL=n
+CONFIG_RCAR_THERMAL=n
+CONFIG_RCAR_GEN3_THERMAL=n
+CONFIG_ARMADA_THERMAL=n
+CONFIG_BCM2711_THERMAL=n
+CONFIG_BCM2835_THERMAL=n
+CONFIG_BRCMSTB_THERMAL=n
+CONFIG_EXYNOS_THERMAL=n
+CONFIG_TEGRA_BPMP_THERMAL=n
+CONFIG_TEGRA_SOCTHERM=n
+CONFIG_UNIPHIER_THERMAL=n
+CONFIG_SL28CPLD_WATCHDOG=n
+CONFIG_ARM_SP805_WATCHDOG=n
+CONFIG_S3C2410_WATCHDOG=n
+CONFIG_SUNXI_WATCHDOG=n
+CONFIG_IMX2_WDT=n
+CONFIG_IMX_SC_WDT=n
+CONFIG_MESON_GXBB_WATCHDOG=n
+CONFIG_MESON_WATCHDOG=n
+CONFIG_RENESAS_WDT=n
+CONFIG_UNIPHIER_WATCHDOG=n
+CONFIG_BCM2835_WDT=n
+CONFIG_MFD_ALTERA_SYSMGR=n
+CONFIG_MFD_AXP20X_I2C=n
+CONFIG_MFD_AXP20X_RSB=n
+CONFIG_MFD_EXYNOS_LPASS=n
+CONFIG_MFD_HI6421_PMIC=n
+CONFIG_MFD_HI655X_PMIC=n
+CONFIG_MFD_MT6397=n
+CONFIG_MFD_RK808=n
+CONFIG_MFD_SL28CPLD=n
+CONFIG_REGULATOR_AXP20X=n
+CONFIG_REGULATOR_BD718XX=n
+CONFIG_REGULATOR_BD9571MWV=n
+CONFIG_REGULATOR_HI6421V530=n
+CONFIG_REGULATOR_HI655X=n
+CONFIG_REGULATOR_MAX77620=n
+CONFIG_REGULATOR_MP8859=n
+CONFIG_REGULATOR_MT6358=n
+CONFIG_REGULATOR_MT6397=n
+CONFIG_REGULATOR_PF8X00=n
+CONFIG_REGULATOR_RK808=n
+CONFIG_REGULATOR_S2MPS11=n
+CONFIG_REGULATOR_TPS65132=n
+CONFIG_IR_MESON=n
+CONFIG_IR_SUNXI=n
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=n
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=n
+CONFIG_MEDIA_SDR_SUPPORT=n
+CONFIG_VIDEO_RCAR_CSI2=n
+CONFIG_VIDEO_RCAR_VIN=n
+CONFIG_VIDEO_SUN6I_CSI=n
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=n
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=n
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=n
+CONFIG_VIDEO_RENESAS_FDP1=n
+CONFIG_VIDEO_RENESAS_FCP=n
+CONFIG_VIDEO_RENESAS_VSP1=n
+CONFIG_SDR_PLATFORM_DRIVERS=n
+CONFIG_VIDEO_RCAR_DRIF=n
+CONFIG_DRM_I2C_NXP_TDA998X=n
+CONFIG_DRM_MALI_DISPLAY=n
+CONFIG_DRM_NOUVEAU=n
+CONFIG_DRM_EXYNOS=n
+CONFIG_DRM_EXYNOS5433_DECON=n
+CONFIG_DRM_EXYNOS7_DECON=n
+CONFIG_DRM_EXYNOS_DSI=n
+CONFIG_DRM_EXYNOS_HDMI=n
+CONFIG_DRM_EXYNOS_MIC=n
+CONFIG_DRM_ROCKCHIP=n
+CONFIG_ROCKCHIP_ANALOGIX_DP=n
+CONFIG_ROCKCHIP_CDN_DP=n
+CONFIG_ROCKCHIP_DW_HDMI=n
+CONFIG_ROCKCHIP_DW_MIPI_DSI=n
+CONFIG_ROCKCHIP_INNO_HDMI=n
+CONFIG_ROCKCHIP_LVDS=n
+CONFIG_DRM_RCAR_DU=n
+CONFIG_DRM_RCAR_DW_HDMI=n
+CONFIG_DRM_SUN4I=n
+CONFIG_DRM_SUN6I_DSI=n
+CONFIG_DRM_SUN8I_DW_HDMI=n
+CONFIG_DRM_SUN8I_MIXER=n
+CONFIG_DRM_TEGRA=n
+CONFIG_DRM_PARADE_PS8640=n
+CONFIG_DRM_SII902X=n
+CONFIG_DRM_THINE_THC63LVD1024=n
+CONFIG_DRM_VC4=n
+CONFIG_DRM_ETNAVIV=n
+CONFIG_DRM_HISI_HIBMC=n
+CONFIG_DRM_HISI_KIRIN=n
+CONFIG_DRM_MEDIATEK=n
+CONFIG_DRM_MEDIATEK_HDMI=n
+CONFIG_DRM_MESON=n
+CONFIG_DRM_PL111=n
+CONFIG_DRM_LIMA=n
+CONFIG_DRM_PANFROST=n
+CONFIG_SND_HDA_TEGRA=n
+CONFIG_SND_HDA_CODEC_HDMI=n
+CONFIG_SND_BCM2835_SOC_I2S=n
+CONFIG_SND_SOC_FSL_EASRC=n
+CONFIG_SND_IMX_SOC=n
+CONFIG_SND_SOC_IMX_SGTL5000=n
+CONFIG_SND_SOC_IMX_SPDIF=n
+CONFIG_SND_SOC_IMX_AUDMIX=n
+CONFIG_SND_SOC_FSL_ASOC_CARD=n
+CONFIG_SND_MESON_AXG_SOUND_CARD=n
+CONFIG_SND_MESON_GX_SOUND_CARD=n
+CONFIG_SND_SOC_ROCKCHIP=n
+CONFIG_SND_SOC_ROCKCHIP_SPDIF=n
+CONFIG_SND_SOC_ROCKCHIP_RT5645=n
+CONFIG_SND_SOC_RK3399_GRU_SOUND=n
+CONFIG_SND_SOC_SAMSUNG=n
+CONFIG_SND_SOC_RCAR=n
+CONFIG_SND_SUN4I_I2S=n
+CONFIG_SND_SUN4I_SPDIF=n
+CONFIG_SND_SOC_TEGRA=n
+CONFIG_SND_SOC_TEGRA210_AHUB=n
+CONFIG_SND_SOC_TEGRA210_DMIC=n
+CONFIG_SND_SOC_TEGRA210_I2S=n
+CONFIG_SND_SOC_TEGRA186_DSPK=n
+CONFIG_SND_SOC_TEGRA210_ADMAIF=n
+CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=n
+CONFIG_SND_SOC_GTM601=n
+CONFIG_SND_SOC_RT5659=n
+CONFIG_SND_SOC_WM8960=n
+CONFIG_SND_SOC_WM8962=n
+CONFIG_USB_XHCI_PCI_RENESAS=n
+CONFIG_USB_XHCI_TEGRA=n
+CONFIG_USB_EHCI_EXYNOS=n
+CONFIG_USB_OHCI_EXYNOS=n
+CONFIG_USB_RENESAS_USBHS_HCD=n
+CONFIG_USB_RENESAS_USBHS=n
+CONFIG_USB_CHIPIDEA_UDC=n
+CONFIG_USB_CHIPIDEA_HOST=n
+CONFIG_USB_RENESAS_USBHS_UDC=n
+CONFIG_USB_RENESAS_USB3=n
+CONFIG_USB_TEGRA_XUDC=n
+CONFIG_MMC_SDHCI_OF_ARASAN=n
+CONFIG_MMC_SDHCI_OF_ESDHC=n
+CONFIG_MMC_SDHCI_ESDHC_IMX=n
+CONFIG_MMC_SDHCI_TEGRA=n
+CONFIG_MMC_MESON_GX=n
+CONFIG_MMC_DW_EXYNOS=n
+CONFIG_MMC_DW_HI3798CV200=n
+CONFIG_MMC_DW_K3=n
+CONFIG_MMC_DW_ROCKCHIP=n
+CONFIG_MMC_SUNXI=n
+CONFIG_MMC_BCM2835=n
+CONFIG_MMC_MTK=n
+CONFIG_MMC_SDHCI_XENON=n
+CONFIG_MMC_SDHCI_AM654=n
+CONFIG_MMC_OWL=n
+CONFIG_RTC_DRV_MAX77686=n
+CONFIG_RTC_DRV_RK808=n
+CONFIG_RTC_DRV_M41T80=n
+CONFIG_RTC_DRV_RV3028=n
+CONFIG_RTC_DRV_S5M=n
+CONFIG_RTC_DRV_FSL_FTM_ALARM=n
+CONFIG_RTC_DRV_S3C=n
+CONFIG_RTC_DRV_PL031=n
+CONFIG_RTC_DRV_SUN6I=n
+CONFIG_RTC_DRV_ARMADA38X=n
+CONFIG_RTC_DRV_TEGRA=n
+CONFIG_RTC_DRV_SNVS=n
+CONFIG_RTC_DRV_IMX_SC=n
+CONFIG_RTC_DRV_XGENE=n
+CONFIG_DMA_BCM2835=n
+CONFIG_DMA_SUN6I=n
+CONFIG_FSL_EDMA=n
+CONFIG_IMX_SDMA=n
+CONFIG_K3_DMA=n
+CONFIG_MV_XOR=n
+CONFIG_MV_XOR_V2=n
+CONFIG_OWL_DMA=n
+CONFIG_TEGRA20_APB_DMA=n
+CONFIG_TEGRA210_ADMA=n
+CONFIG_RCAR_DMAC=n
+CONFIG_RENESAS_USB_DMAC=n
+CONFIG_TI_K3_UDMA=n
+CONFIG_TI_K3_UDMA_GLUE_LAYER=n
+CONFIG_COMMON_CLK_RK808=n
+CONFIG_COMMON_CLK_FSL_SAI=n
+CONFIG_COMMON_CLK_S2MPS11=n
+CONFIG_COMMON_CLK_ZYNQMP=n
+CONFIG_COMMON_CLK_BD718XX=n
+CONFIG_CLK_RASPBERRYPI=n
+CONFIG_CLK_IMX8MM=n
+CONFIG_CLK_IMX8MN=n
+CONFIG_CLK_IMX8MP=n
+CONFIG_CLK_IMX8MQ=n
+CONFIG_CLK_IMX8QXP=n
+CONFIG_TI_SCI_CLK=n
+CONFIG_IMX_MBOX=n
+CONFIG_BCM2835_MBOX=n
+CONFIG_ROCKCHIP_IOMMU=n
+CONFIG_TEGRA_IOMMU_SMMU=n
+CONFIG_MTK_IOMMU=n
+CONFIG_OWL_PM_DOMAINS=n
+CONFIG_RASPBERRYPI_POWER=n
+CONFIG_FSL_DPAA=n
+CONFIG_FSL_MC_DPIO=n
+CONFIG_FSL_RCPM=n
+CONFIG_MTK_PMIC_WRAP=n
+CONFIG_ARCH_R8A774A1=n
+CONFIG_ARCH_R8A774B1=n
+CONFIG_ARCH_R8A774C0=n
+CONFIG_ARCH_R8A774E1=n
+CONFIG_ARCH_R8A77950=n
+CONFIG_ARCH_R8A77951=n
+CONFIG_ARCH_R8A77960=n
+CONFIG_ARCH_R8A77961=n
+CONFIG_ARCH_R8A77965=n
+CONFIG_ARCH_R8A77970=n
+CONFIG_ARCH_R8A77980=n
+CONFIG_ARCH_R8A77990=n
+CONFIG_ARCH_R8A77995=n
+CONFIG_ARCH_R8A779A0=n
+CONFIG_ARCH_R9A07G044=n
+CONFIG_ROCKCHIP_PM_DOMAINS=n
+CONFIG_ARCH_TEGRA_132_SOC=n
+CONFIG_ARCH_TEGRA_210_SOC=n
+CONFIG_ARCH_TEGRA_186_SOC=n
+CONFIG_ARCH_TEGRA_194_SOC=n
+CONFIG_ARCH_TEGRA_234_SOC=n
+CONFIG_TI_SCI_PM_DOMAINS=n
+CONFIG_ARM_IMX_BUS_DEVFREQ=n
+CONFIG_ARM_IMX8M_DDRC_DEVFREQ=n
+CONFIG_RENESAS_RPCIF=n
+CONFIG_EXYNOS_ADC=n
+CONFIG_MAX9611=n
+CONFIG_ROCKCHIP_SARADC=n
+CONFIG_PWM_BCM2835=n
+CONFIG_PWM_IMX27=n
+CONFIG_PWM_MESON=n
+CONFIG_PWM_MTK_DISP=n
+CONFIG_PWM_MEDIATEK=n
+CONFIG_PWM_RCAR=n
+CONFIG_PWM_ROCKCHIP=n
+CONFIG_PWM_SAMSUNG=n
+CONFIG_PWM_SL28CPLD=n
+CONFIG_PWM_SUN4I=n
+CONFIG_PWM_TEGRA=n
+CONFIG_PWM_VISCONTI=n
+CONFIG_SL28CPLD_INTC=n
+CONFIG_RESET_IMX7=n
+CONFIG_RESET_TI_SCI=n
+CONFIG_PHY_XGENE=n
+CONFIG_PHY_SUN4I_USB=n
+CONFIG_PHY_HI6220_USB=n
+CONFIG_PHY_HISTB_COMBPHY=n
+CONFIG_PHY_HISI_INNO_USB2=n
+CONFIG_PHY_MVEBU_CP110_COMPHY=n
+CONFIG_PHY_MTK_TPHY=n
+CONFIG_PHY_RCAR_GEN3_PCIE=n
+CONFIG_PHY_RCAR_GEN3_USB2=n
+CONFIG_PHY_RCAR_GEN3_USB3=n
+CONFIG_PHY_ROCKCHIP_EMMC=n
+CONFIG_PHY_ROCKCHIP_INNO_HDMI=n
+CONFIG_PHY_ROCKCHIP_INNO_USB2=n
+CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=n
+CONFIG_PHY_ROCKCHIP_PCIE=n
+CONFIG_PHY_ROCKCHIP_TYPEC=n
+CONFIG_PHY_SAMSUNG_UFS=n
+CONFIG_PHY_UNIPHIER_USB2=n
+CONFIG_PHY_UNIPHIER_USB3=n
+CONFIG_PHY_TEGRA_XUSB=n
+CONFIG_FSL_IMX8_DDR_PMU=n
+CONFIG_HISI_PMU=n
+CONFIG_NVMEM_IMX_OCOTP=n
+CONFIG_NVMEM_IMX_OCOTP_SCU=n
+CONFIG_MTK_EFUSE=n
+CONFIG_ROCKCHIP_EFUSE=n
+CONFIG_NVMEM_SUNXI_SID=n
+CONFIG_UNIPHIER_EFUSE=n
+CONFIG_MESON_EFUSE=n
+CONFIG_NVMEM_RMEM=n
+CONFIG_FPGA=n
+CONFIG_FPGA_MGR_STRATIX10_SOC=n
+CONFIG_FPGA_BRIDGE=n
+CONFIG_ALTERA_FREEZE_BRIDGE=n
+CONFIG_FPGA_REGION=n
+CONFIG_OF_FPGA_REGION=n
+CONFIG_INTERCONNECT_IMX=n
+CONFIG_INTERCONNECT_IMX8MQ=n
+CONFIG_INTERCONNECT_QCOM_MSM8996=n
+CONFIG_INTERCONNECT_QCOM_QCS404=n
+CONFIG_INTERCONNECT_QCOM_SC7180=n
+CONFIG_INTERCONNECT_QCOM_SM8150=n
+CONFIG_INTERCONNECT_QCOM_SM8350=n
+CONFIG_INTERCONNECT_QCOM_SM8450=n
+CONFIG_INTERCONNECT_QCOM_SM8550=n
+CONFIG_INTERCONNECT_QCOM_SC8280XP=n
+CONFIG_ARCH_BCMBCA=n
+CONFIG_ARCH_NPCM=n
+CONFIG_SERIAL_BCM63XX=n
+CONFIG_PINCTRL_SC8280XP=n
+CONFIG_SC_GCC_8280XP=n
+CONFIG_BCM_SBA_RAID=n
+CONFIG_DMA_ENGINE_RAID=n
+CONFIG_SENSORS_GPIO_FAN=n
+CONFIG_ARCH_BCM=n
+CONFIG_ARCH_NXP=n
+CONFIG_NET_VENDOR_ADI=n
+CONFIG_PINCTRL_SC8180X=n
+CONFIG_SND_SOC_SC7180=n
+CONFIG_SND_SOC_SC7280=n
+CONFIG_SND_SOC_ADAU7002=n
+CONFIG_SND_SOC_RT5682=n
+CONFIG_SND_SOC_RT5682_I2C=n
+CONFIG_SND_SOC_RT5682S=n
+CONFIG_SND_SOC_WCD938X=n
+CONFIG_SND_SOC_WCD938X_SDW=n
+CONFIG_MMC_SDHCI_OF_DWCMSHC=n
+CONFIG_CROS_TYPEC_SWITCH=n
+CONFIG_SC_GCC_8180X=n
+CONFIG_IOMMU_IO_PGTABLE_DART=n
+CONFIG_INTERCONNECT_QCOM_SC8180X=n
+CONFIG_MEMORY_HOTPLUG=n
+CONFIG_MELLANOX_PLATFORM=n
+CONFIG_CHROME_PLATFORMS=n
+CONFIG_PINCTRL_SM8150=n
+CONFIG_SM_GCC_8150=n
+CONFIG_SM_GPUCC_8150=n
+CONFIG_PINCTRL_SM8350=n
+CONFIG_SM_GCC_8350=n
+CONFIG_SM_DISPCC_8450=n
+CONFIG_SM_GCC_8450=n
+CONFIG_PINCTRL_SM8550=n
+CONFIG_PINCTRL_SM8550_LPASS_LPI=n
+CONFIG_SM_DISPCC_8550=n
+CONFIG_SM_GCC_8550=n
+CONFIG_SM_TCSRCC_8550=n
diff --git a/arch/arm64/include/asm/setup.h b/arch/arm64/include/asm/setup.h
index f4af547ef54..2e4d7da74fb 100644
--- a/arch/arm64/include/asm/setup.h
+++ b/arch/arm64/include/asm/setup.h
@@ -21,9 +21,22 @@ static inline bool arch_parse_debug_rodata(char *arg)
extern bool rodata_enabled;
extern bool rodata_full;
- if (arg && !strcmp(arg, "full")) {
+ if (!arg)
+ return false;
+
+ if (!strcmp(arg, "full")) {
+ rodata_enabled = rodata_full = true;
+ return true;
+ }
+
+ if (!strcmp(arg, "off")) {
+ rodata_enabled = rodata_full = false;
+ return true;
+ }
+
+ if (!strcmp(arg, "on")) {
rodata_enabled = true;
- rodata_full = true;
+ rodata_full = false;
return true;
}
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index 8e2017ba5f1..924843f1f66 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -29,8 +29,8 @@ bool can_set_direct_map(void)
*
* KFENCE pool requires page-granular mapping if initialized late.
*/
- return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
- arm64_kfence_can_set_direct_map();
+ return rodata_full || debug_pagealloc_enabled() ||
+ arm64_kfence_can_set_direct_map();
}
static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
@@ -105,8 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages,
* If we are manipulating read-only permissions, apply the same
* change to the linear mapping of the pages that back this VM area.
*/
- if (rodata_enabled &&
- rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
+ if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
pgprot_val(clear_mask) == PTE_RDONLY)) {
for (i = 0; i < area->nr_pages; i++) {
__change_memory_common((u64)page_address(area->pages[i]),
diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile
index 9eeb0c05f3f..204b94b2e6a 100644
--- a/arch/loongarch/Makefile
+++ b/arch/loongarch/Makefile
@@ -68,6 +68,7 @@ LDFLAGS_vmlinux += -static -n -nostdlib
ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS
cflags-y += $(call cc-option,-mexplicit-relocs)
KBUILD_CFLAGS_KERNEL += $(call cc-option,-mdirect-extern-access)
+KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdirect-access-external-data)
KBUILD_AFLAGS_MODULE += $(call cc-option,-fno-direct-access-external-data)
KBUILD_CFLAGS_MODULE += $(call cc-option,-fno-direct-access-external-data)
KBUILD_AFLAGS_MODULE += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax)
@@ -142,6 +143,8 @@ vdso-install-y += arch/loongarch/vdso/vdso.so.dbg
all: $(notdir $(KBUILD_IMAGE))
+vmlinuz.efi: vmlinux.efi
+
vmlinux.elf vmlinux.efi vmlinuz.efi: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $(boot)/$@
diff --git a/arch/loongarch/include/asm/asmmacro.h b/arch/loongarch/include/asm/asmmacro.h
index c9544f358c3..655db7d7a42 100644
--- a/arch/loongarch/include/asm/asmmacro.h
+++ b/arch/loongarch/include/asm/asmmacro.h
@@ -609,8 +609,7 @@
lu32i.d \reg, 0
lu52i.d \reg, \reg, 0
.pushsection ".la_abs", "aw", %progbits
- 768:
- .dword 768b-766b
+ .dword 766b
.dword \sym
.popsection
#endif
diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h
index ed5da02b1cf..9b36ac003f8 100644
--- a/arch/loongarch/include/asm/percpu.h
+++ b/arch/loongarch/include/asm/percpu.h
@@ -40,13 +40,13 @@ static __always_inline unsigned long __percpu_##op(void *ptr, \
switch (size) { \
case 4: \
__asm__ __volatile__( \
- "am"#asm_op".w" " %[ret], %[val], %[ptr] \n" \
+ "am"#asm_op".w" " %[ret], %[val], %[ptr] \n" \
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u32 *)ptr) \
: [val] "r" (val)); \
break; \
case 8: \
__asm__ __volatile__( \
- "am"#asm_op".d" " %[ret], %[val], %[ptr] \n" \
+ "am"#asm_op".d" " %[ret], %[val], %[ptr] \n" \
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u64 *)ptr) \
: [val] "r" (val)); \
break; \
@@ -63,7 +63,7 @@ PERCPU_OP(and, and, &)
PERCPU_OP(or, or, |)
#undef PERCPU_OP
-static __always_inline unsigned long __percpu_read(void *ptr, int size)
+static __always_inline unsigned long __percpu_read(void __percpu *ptr, int size)
{
unsigned long ret;
@@ -100,7 +100,7 @@ static __always_inline unsigned long __percpu_read(void *ptr, int size)
return ret;
}
-static __always_inline void __percpu_write(void *ptr, unsigned long val, int size)
+static __always_inline void __percpu_write(void __percpu *ptr, unsigned long val, int size)
{
switch (size) {
case 1:
@@ -132,8 +132,7 @@ static __always_inline void __percpu_write(void *ptr, unsigned long val, int siz
}
}
-static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
- int size)
+static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, int size)
{
switch (size) {
case 1:
diff --git a/arch/loongarch/include/asm/setup.h b/arch/loongarch/include/asm/setup.h
index a0bc159ce8b..ee52fb1e996 100644
--- a/arch/loongarch/include/asm/setup.h
+++ b/arch/loongarch/include/asm/setup.h
@@ -25,7 +25,7 @@ extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len
#ifdef CONFIG_RELOCATABLE
struct rela_la_abs {
- long offset;
+ long pc;
long symvalue;
};
diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c
index 6c3eff9af9f..1acfa704c8d 100644
--- a/arch/loongarch/kernel/relocate.c
+++ b/arch/loongarch/kernel/relocate.c
@@ -52,7 +52,7 @@ static inline void __init relocate_absolute(long random_offset)
for (p = begin; (void *)p < end; p++) {
long v = p->symvalue;
uint32_t lu12iw, ori, lu32id, lu52id;
- union loongarch_instruction *insn = (void *)p - p->offset;
+ union loongarch_instruction *insn = (void *)p->pc;
lu12iw = (v >> 12) & 0xfffff;
ori = v & 0xfff;
@@ -102,6 +102,14 @@ static inline __init unsigned long get_random_boot(void)
return hash;
}
+static int __init nokaslr(char *p)
+{
+ pr_info("KASLR is disabled.\n");
+
+ return 0; /* Print a notice and silence the boot warning */
+}
+early_param("nokaslr", nokaslr);
+
static inline __init bool kaslr_disabled(void)
{
char *str;
diff --git a/arch/loongarch/kernel/time.c b/arch/loongarch/kernel/time.c
index 3064af94db9..e7015f7b70e 100644
--- a/arch/loongarch/kernel/time.c
+++ b/arch/loongarch/kernel/time.c
@@ -58,14 +58,16 @@ static int constant_set_state_oneshot(struct clock_event_device *evt)
return 0;
}
-static int constant_set_state_oneshot_stopped(struct clock_event_device *evt)
+static int constant_set_state_periodic(struct clock_event_device *evt)
{
+ unsigned long period;
unsigned long timer_config;
raw_spin_lock(&state_lock);
- timer_config = csr_read64(LOONGARCH_CSR_TCFG);
- timer_config &= ~CSR_TCFG_EN;
+ period = const_clock_freq / HZ;
+ timer_config = period & CSR_TCFG_VAL;
+ timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
csr_write64(timer_config, LOONGARCH_CSR_TCFG);
raw_spin_unlock(&state_lock);
@@ -73,16 +75,14 @@ static int constant_set_state_oneshot_stopped(struct clock_event_device *evt)
return 0;
}
-static int constant_set_state_periodic(struct clock_event_device *evt)
+static int constant_set_state_shutdown(struct clock_event_device *evt)
{
- unsigned long period;
unsigned long timer_config;
raw_spin_lock(&state_lock);
- period = const_clock_freq / HZ;
- timer_config = period & CSR_TCFG_VAL;
- timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
+ timer_config = csr_read64(LOONGARCH_CSR_TCFG);
+ timer_config &= ~CSR_TCFG_EN;
csr_write64(timer_config, LOONGARCH_CSR_TCFG);
raw_spin_unlock(&state_lock);
@@ -90,11 +90,6 @@ static int constant_set_state_periodic(struct clock_event_device *evt)
return 0;
}
-static int constant_set_state_shutdown(struct clock_event_device *evt)
-{
- return 0;
-}
-
static int constant_timer_next_event(unsigned long delta, struct clock_event_device *evt)
{
unsigned long timer_config;
@@ -161,7 +156,7 @@ int constant_clockevent_init(void)
cd->rating = 320;
cd->cpumask = cpumask_of(cpu);
cd->set_state_oneshot = constant_set_state_oneshot;
- cd->set_state_oneshot_stopped = constant_set_state_oneshot_stopped;
+ cd->set_state_oneshot_stopped = constant_set_state_shutdown;
cd->set_state_periodic = constant_set_state_periodic;
cd->set_state_shutdown = constant_set_state_shutdown;
cd->set_next_event = constant_timer_next_event;
diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c
index 71d0539e2d0..2aae72e6387 100644
--- a/arch/loongarch/mm/pgtable.c
+++ b/arch/loongarch/mm/pgtable.c
@@ -13,13 +13,13 @@ struct page *dmw_virt_to_page(unsigned long kaddr)
{
return pfn_to_page(virt_to_pfn(kaddr));
}
-EXPORT_SYMBOL_GPL(dmw_virt_to_page);
+EXPORT_SYMBOL(dmw_virt_to_page);
struct page *tlb_virt_to_page(unsigned long kaddr)
{
return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr)));
}
-EXPORT_SYMBOL_GPL(tlb_virt_to_page);
+EXPORT_SYMBOL(tlb_virt_to_page);
pgd_t *pgd_alloc(struct mm_struct *mm)
{
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index a7c9c0e69e5..d14ccc948a2 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -115,9 +115,12 @@ config ARCH_HAS_ILOG2_U64
default n
config GENERIC_BUG
- bool
- default y
+ def_bool y
depends on BUG
+ select GENERIC_BUG_RELATIVE_POINTERS if 64BIT
+
+config GENERIC_BUG_RELATIVE_POINTERS
+ bool
config GENERIC_HWEIGHT
bool
diff --git a/arch/parisc/include/asm/alternative.h b/arch/parisc/include/asm/alternative.h
index 1ed45fd085d..1eb488f25b8 100644
--- a/arch/parisc/include/asm/alternative.h
+++ b/arch/parisc/include/asm/alternative.h
@@ -34,7 +34,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* Alternative SMP implementation. */
#define ALTERNATIVE(cond, replacement) "!0:" \
- ".section .altinstructions, \"aw\" !" \
+ ".section .altinstructions, \"a\" !" \
+ ".align 4 !" \
".word (0b-4-.) !" \
".hword 1, " __stringify(cond) " !" \
".word " __stringify(replacement) " !" \
@@ -44,7 +45,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* to replace one single instructions by a new instruction */
#define ALTERNATIVE(from, to, cond, replacement)\
- .section .altinstructions, "aw" ! \
+ .section .altinstructions, "a" ! \
+ .align 4 ! \
.word (from - .) ! \
.hword (to - from)/4, cond ! \
.word replacement ! \
@@ -52,7 +54,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end,
/* to replace multiple instructions by new code */
#define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\
- .section .altinstructions, "aw" ! \
+ .section .altinstructions, "a" ! \
+ .align 4 ! \
.word (from - .) ! \
.hword -num_instructions, cond ! \
.word (new_instr_ptr - .) ! \
diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index 75677b526b2..74d17d7e759 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -574,6 +574,7 @@
*/
#define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr) \
.section __ex_table,"aw" ! \
+ .align 4 ! \
.word (fault_addr - .), (except_addr - .) ! \
.previous
diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h
index 4b6d60b9412..1641ff9a8b8 100644
--- a/arch/parisc/include/asm/bug.h
+++ b/arch/parisc/include/asm/bug.h
@@ -17,24 +17,27 @@
#define PARISC_BUG_BREAK_ASM "break 0x1f, 0x1fff"
#define PARISC_BUG_BREAK_INSN 0x03ffe01f /* PARISC_BUG_BREAK_ASM */
-#if defined(CONFIG_64BIT)
-#define ASM_WORD_INSN ".dword\t"
+#ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
+# define __BUG_REL(val) ".word " __stringify(val) " - ."
#else
-#define ASM_WORD_INSN ".word\t"
+# define __BUG_REL(val) ".word " __stringify(val)
#endif
+
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define BUG() \
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
- "\t.pushsection __bug_table,\"aw\"\n" \
- "2:\t" ASM_WORD_INSN "1b, %c0\n" \
- "\t.short %c1, %c2\n" \
- "\t.org 2b+%c3\n" \
+ "\t.pushsection __bug_table,\"a\"\n" \
+ "\t.align 4\n" \
+ "2:\t" __BUG_REL(1b) "\n" \
+ "\t" __BUG_REL(%c0) "\n" \
+ "\t.short %1, %2\n" \
+ "\t.blockz %3-2*4-2*2\n" \
"\t.popsection" \
: : "i" (__FILE__), "i" (__LINE__), \
- "i" (0), "i" (sizeof(struct bug_entry)) ); \
+ "i" (0), "i" (sizeof(struct bug_entry)) ); \
unreachable(); \
} while(0)
@@ -51,10 +54,12 @@
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
- "\t.pushsection __bug_table,\"aw\"\n" \
- "2:\t" ASM_WORD_INSN "1b, %c0\n" \
- "\t.short %c1, %c2\n" \
- "\t.org 2b+%c3\n" \
+ "\t.pushsection __bug_table,\"a\"\n" \
+ "\t.align 4\n" \
+ "2:\t" __BUG_REL(1b) "\n" \
+ "\t" __BUG_REL(%c0) "\n" \
+ "\t.short %1, %2\n" \
+ "\t.blockz %3-2*4-2*2\n" \
"\t.popsection" \
: : "i" (__FILE__), "i" (__LINE__), \
"i" (BUGFLAG_WARNING|(flags)), \
@@ -65,10 +70,11 @@
do { \
asm volatile("\n" \
"1:\t" PARISC_BUG_BREAK_ASM "\n" \
- "\t.pushsection __bug_table,\"aw\"\n" \
- "2:\t" ASM_WORD_INSN "1b\n" \
- "\t.short %c0\n" \
- "\t.org 2b+%c1\n" \
+ "\t.pushsection __bug_table,\"a\"\n" \
+ "\t.align %2\n" \
+ "2:\t" __BUG_REL(1b) "\n" \
+ "\t.short %0\n" \
+ "\t.blockz %1-4-2\n" \
"\t.popsection" \
: : "i" (BUGFLAG_WARNING|(flags)), \
"i" (sizeof(struct bug_entry)) ); \
diff --git a/arch/parisc/include/asm/jump_label.h b/arch/parisc/include/asm/jump_label.h
index af2a598bc0f..94428798b6a 100644
--- a/arch/parisc/include/asm/jump_label.h
+++ b/arch/parisc/include/asm/jump_label.h
@@ -15,10 +15,12 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
asm_volatile_goto("1:\n\t"
"nop\n\t"
".pushsection __jump_table, \"aw\"\n\t"
+ ".align %1\n\t"
".word 1b - ., %l[l_yes] - .\n\t"
__stringify(ASM_ULONG_INSN) " %c0 - .\n\t"
".popsection\n\t"
- : : "i" (&((char *)key)[branch]) : : l_yes);
+ : : "i" (&((char *)key)[branch]), "i" (sizeof(long))
+ : : l_yes);
return false;
l_yes:
@@ -30,10 +32,12 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
asm_volatile_goto("1:\n\t"
"b,n %l[l_yes]\n\t"
".pushsection __jump_table, \"aw\"\n\t"
+ ".align %1\n\t"
".word 1b - ., %l[l_yes] - .\n\t"
__stringify(ASM_ULONG_INSN) " %c0 - .\n\t"
".popsection\n\t"
- : : "i" (&((char *)key)[branch]) : : l_yes);
+ : : "i" (&((char *)key)[branch]), "i" (sizeof(long))
+ : : l_yes);
return false;
l_yes:
diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h
index ee9e071859b..47ebc4c91ea 100644
--- a/arch/parisc/include/asm/ldcw.h
+++ b/arch/parisc/include/asm/ldcw.h
@@ -55,7 +55,7 @@
})
#ifdef CONFIG_SMP
-# define __lock_aligned __section(".data..lock_aligned")
+# define __lock_aligned __section(".data..lock_aligned") __aligned(16)
#endif
#endif /* __PARISC_LDCW_H */
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 2bf660eabe4..4165079898d 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -41,6 +41,7 @@ struct exception_table_entry {
#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
".section __ex_table,\"aw\"\n" \
+ ".align 4\n" \
".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \
".previous\n"
diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
index 87245c58478..8d94739d75c 100644
--- a/arch/parisc/include/uapi/asm/errno.h
+++ b/arch/parisc/include/uapi/asm/errno.h
@@ -75,7 +75,6 @@
/* We now return you to your regularly scheduled HPUX. */
-#define ENOSYM 215 /* symbol does not exist in executable */
#define ENOTSOCK 216 /* Socket operation on non-socket */
#define EDESTADDRREQ 217 /* Destination address required */
#define EMSGSIZE 218 /* Message too long */
@@ -101,7 +100,6 @@
#define ETIMEDOUT 238 /* Connection timed out */
#define ECONNREFUSED 239 /* Connection refused */
#define EREFUSED ECONNREFUSED /* for HP's NFS apparently */
-#define EREMOTERELEASE 240 /* Remote peer released connection */
#define EHOSTDOWN 241 /* Host is down */
#define EHOSTUNREACH 242 /* No route to host */
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 58694d1989c..548051b0b4a 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -130,6 +130,7 @@ SECTIONS
RO_DATA(8)
/* unwind info */
+ . = ALIGN(4);
.PARISC.unwind : {
__start___unwind = .;
*(.PARISC.unwind)
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index dc17896a001..c15eadbb998 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -228,7 +228,6 @@ typedef struct thread_struct thread_struct;
execve_tail(); \
} while (0)
-/* Forward declaration, a strange C thing */
struct task_struct;
struct mm_struct;
struct seq_file;
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index cc364fce6aa..ba75f6bee77 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -666,6 +666,7 @@ static int __init ipl_init(void)
&ipl_ccw_attr_group_lpar);
break;
case IPL_TYPE_ECKD:
+ case IPL_TYPE_ECKD_DUMP:
rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group);
break;
case IPL_TYPE_FCP:
diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c
index 77fd24e6cbb..39a91b00438 100644
--- a/arch/s390/kernel/perf_pai_crypto.c
+++ b/arch/s390/kernel/perf_pai_crypto.c
@@ -279,12 +279,6 @@ static int paicrypt_event_init(struct perf_event *event)
if (IS_ERR(cpump))
return PTR_ERR(cpump);
- /* Event initialization sets last_tag to 0. When later on the events
- * are deleted and re-added, do not reset the event count value to zero.
- * Events are added, deleted and re-added when 2 or more events
- * are active at the same time.
- */
- event->hw.last_tag = 0;
event->destroy = paicrypt_event_destroy;
if (a->sample_period) {
@@ -318,6 +312,11 @@ static void paicrypt_start(struct perf_event *event, int flags)
{
u64 sum;
+ /* Event initialization sets last_tag to 0. When later on the events
+ * are deleted and re-added, do not reset the event count value to zero.
+ * Events are added, deleted and re-added when 2 or more events
+ * are active at the same time.
+ */
if (!event->hw.last_tag) {
event->hw.last_tag = 1;
sum = paicrypt_getall(event); /* Get current value */
diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c
index 8ba0f1a3a39..e7013a2e896 100644
--- a/arch/s390/kernel/perf_pai_ext.c
+++ b/arch/s390/kernel/perf_pai_ext.c
@@ -260,7 +260,6 @@ static int paiext_event_init(struct perf_event *event)
rc = paiext_alloc(a, event);
if (rc)
return rc;
- event->hw.last_tag = 0;
event->destroy = paiext_event_destroy;
if (a->sample_period) {
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index a08f794a0e7..ce1c777227b 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4660,7 +4660,7 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu)
if (pmu->intel_cap.pebs_output_pt_available)
pmu->pmu.capabilities |= PERF_PMU_CAP_AUX_OUTPUT;
else
- pmu->pmu.capabilities |= ~PERF_PMU_CAP_AUX_OUTPUT;
+ pmu->pmu.capabilities &= ~PERF_PMU_CAP_AUX_OUTPUT;
intel_pmu_check_event_constraints(pmu->event_constraints,
pmu->num_counters,
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 21556ad87f4..8f3a4d16bb7 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <asm/apic.h>
#include <asm/desc.h>
+#include <asm/e820/api.h>
#include <asm/sev.h>
#include <asm/ibt.h>
#include <asm/hypervisor.h>
@@ -286,15 +287,31 @@ static int hv_cpu_die(unsigned int cpu)
static int __init hv_pci_init(void)
{
- int gen2vm = efi_enabled(EFI_BOOT);
+ bool gen2vm = efi_enabled(EFI_BOOT);
/*
- * For Generation-2 VM, we exit from pci_arch_init() by returning 0.
- * The purpose is to suppress the harmless warning:
+ * A Generation-2 VM doesn't support legacy PCI/PCIe, so both
+ * raw_pci_ops and raw_pci_ext_ops are NULL, and pci_subsys_init() ->
+ * pcibios_init() doesn't call pcibios_resource_survey() ->
+ * e820__reserve_resources_late(); as a result, any emulated persistent
+ * memory of E820_TYPE_PRAM (12) via the kernel parameter
+ * memmap=nn[KMG]!ss is not added into iomem_resource and hence can't be
+ * detected by register_e820_pmem(). Fix this by directly calling
+ * e820__reserve_resources_late() here: e820__reserve_resources_late()
+ * depends on e820__reserve_resources(), which has been called earlier
+ * from setup_arch(). Note: e820__reserve_resources_late() also adds
+ * any memory of E820_TYPE_PMEM (7) into iomem_resource, and
+ * acpi_nfit_register_region() -> acpi_nfit_insert_resource() ->
+ * region_intersects() returns REGION_INTERSECTS, so the memory of
+ * E820_TYPE_PMEM won't get added twice.
+ *
+ * We return 0 here so that pci_arch_init() won't print the warning:
* "PCI: Fatal: No config space access function found"
*/
- if (gen2vm)
+ if (gen2vm) {
+ e820__reserve_resources_late();
return 0;
+ }
/* For Generation-1 VM, we'll proceed in pci_arch_init(). */
return 1;
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 9373ec01c5a..13b45b9c806 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -104,8 +104,6 @@ struct cont_desc {
size_t size;
};
-static u32 ucode_new_rev;
-
/*
* Microcode patch container file is prepended to the initrd in cpio
* format. See Documentation/arch/x86/microcode.rst
@@ -442,12 +440,11 @@ static int __apply_microcode_amd(struct microcode_amd *mc)
*
* Returns true if container found (sets @desc), false otherwise.
*/
-static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size)
+static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, size_t size)
{
struct cont_desc desc = { 0 };
struct microcode_amd *mc;
bool ret = false;
- u32 rev, dummy;
desc.cpuid_1_eax = cpuid_1_eax;
@@ -457,22 +454,15 @@ static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size)
if (!mc)
return ret;
- native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
-
/*
* Allow application of the same revision to pick up SMT-specific
* changes even if the revision of the other SMT thread is already
* up-to-date.
*/
- if (rev > mc->hdr.patch_id)
+ if (old_rev > mc->hdr.patch_id)
return ret;
- if (!__apply_microcode_amd(mc)) {
- ucode_new_rev = mc->hdr.patch_id;
- ret = true;
- }
-
- return ret;
+ return !__apply_microcode_amd(mc);
}
static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
@@ -506,9 +496,12 @@ static void __init find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpi
*ret = cp;
}
-void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax)
+void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
{
struct cpio_data cp = { };
+ u32 dummy;
+
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
/* Needed in load_microcode_amd() */
ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
@@ -517,7 +510,8 @@ void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax)
if (!(cp.data && cp.size))
return;
- early_apply_microcode(cpuid_1_eax, cp.data, cp.size);
+ if (early_apply_microcode(cpuid_1_eax, ed->old_rev, cp.data, cp.size))
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
}
static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
@@ -625,10 +619,8 @@ void reload_ucode_amd(unsigned int cpu)
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
if (rev < mc->hdr.patch_id) {
- if (!__apply_microcode_amd(mc)) {
- ucode_new_rev = mc->hdr.patch_id;
- pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
- }
+ if (!__apply_microcode_amd(mc))
+ pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
}
}
@@ -649,8 +641,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
if (p && (p->patch_id == csig->rev))
uci->mc = p->data;
- pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
-
return 0;
}
@@ -691,8 +681,6 @@ static enum ucode_state apply_microcode_amd(int cpu)
rev = mc_amd->hdr.patch_id;
ret = UCODE_UPDATED;
- pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
-
out:
uci->cpu_sig.rev = rev;
c->microcode = rev;
@@ -935,11 +923,6 @@ struct microcode_ops * __init init_amd_microcode(void)
pr_warn("AMD CPU family 0x%x not supported\n", c->x86);
return NULL;
}
-
- if (ucode_new_rev)
- pr_info_once("microcode updated early to new patch_level=0x%08x\n",
- ucode_new_rev);
-
return &microcode_amd_ops;
}
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 666d25bbc5a..232026a239a 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -41,8 +41,6 @@
#include "internal.h"
-#define DRIVER_VERSION "2.2"
-
static struct microcode_ops *microcode_ops;
bool dis_ucode_ldr = true;
@@ -77,6 +75,8 @@ static u32 final_levels[] = {
0, /* T-101 terminator */
};
+struct early_load_data early_data;
+
/*
* Check the current patch level on this CPU.
*
@@ -155,9 +155,9 @@ void __init load_ucode_bsp(void)
return;
if (intel)
- load_ucode_intel_bsp();
+ load_ucode_intel_bsp(&early_data);
else
- load_ucode_amd_bsp(cpuid_1_eax);
+ load_ucode_amd_bsp(&early_data, cpuid_1_eax);
}
void load_ucode_ap(void)
@@ -828,6 +828,11 @@ static int __init microcode_init(void)
if (!microcode_ops)
return -ENODEV;
+ pr_info_once("Current revision: 0x%08x\n", (early_data.new_rev ?: early_data.old_rev));
+
+ if (early_data.new_rev)
+ pr_info_once("Updated early from: 0x%08x\n", early_data.old_rev);
+
microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0);
if (IS_ERR(microcode_pdev))
return PTR_ERR(microcode_pdev);
@@ -846,8 +851,6 @@ static int __init microcode_init(void)
cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
mc_cpu_online, mc_cpu_down_prep);
- pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION);
-
return 0;
out_pdev:
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 6024feb98d2..070426b9895 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -339,16 +339,9 @@ static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci,
static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
{
struct microcode_intel *mc = uci->mc;
- enum ucode_state ret;
- u32 cur_rev, date;
+ u32 cur_rev;
- ret = __apply_microcode(uci, mc, &cur_rev);
- if (ret == UCODE_UPDATED) {
- date = mc->hdr.date;
- pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
- cur_rev, mc->hdr.rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
- }
- return ret;
+ return __apply_microcode(uci, mc, &cur_rev);
}
static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
@@ -413,13 +406,17 @@ static int __init save_builtin_microcode(void)
early_initcall(save_builtin_microcode);
/* Load microcode on BSP from initrd or builtin blobs */
-void __init load_ucode_intel_bsp(void)
+void __init load_ucode_intel_bsp(struct early_load_data *ed)
{
struct ucode_cpu_info uci;
+ ed->old_rev = intel_get_microcode_revision();
+
uci.mc = get_microcode_blob(&uci, false);
if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED)
ucode_patch_va = UCODE_BSP_LOADED;
+
+ ed->new_rev = uci.cpu_sig.rev;
}
void load_ucode_intel_ap(void)
diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h
index f8047b12329..21776c529fa 100644
--- a/arch/x86/kernel/cpu/microcode/internal.h
+++ b/arch/x86/kernel/cpu/microcode/internal.h
@@ -37,6 +37,12 @@ struct microcode_ops {
use_nmi : 1;
};
+struct early_load_data {
+ u32 old_rev;
+ u32 new_rev;
+};
+
+extern struct early_load_data early_data;
extern struct ucode_cpu_info ucode_cpu_info[];
struct cpio_data find_microcode_in_initrd(const char *path);
@@ -92,14 +98,14 @@ extern bool dis_ucode_ldr;
extern bool force_minrev;
#ifdef CONFIG_CPU_SUP_AMD
-void load_ucode_amd_bsp(unsigned int family);
+void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family);
void load_ucode_amd_ap(unsigned int family);
int save_microcode_in_initrd_amd(unsigned int family);
void reload_ucode_amd(unsigned int cpu);
struct microcode_ops *init_amd_microcode(void);
void exit_amd_microcode(void);
#else /* CONFIG_CPU_SUP_AMD */
-static inline void load_ucode_amd_bsp(unsigned int family) { }
+static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { }
static inline void load_ucode_amd_ap(unsigned int family) { }
static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
static inline void reload_ucode_amd(unsigned int cpu) { }
@@ -108,12 +114,12 @@ static inline void exit_amd_microcode(void) { }
#endif /* !CONFIG_CPU_SUP_AMD */
#ifdef CONFIG_CPU_SUP_INTEL
-void load_ucode_intel_bsp(void);
+void load_ucode_intel_bsp(struct early_load_data *ed);
void load_ucode_intel_ap(void);
void reload_ucode_intel(void);
struct microcode_ops *init_intel_microcode(void);
#else /* CONFIG_CPU_SUP_INTEL */
-static inline void load_ucode_intel_bsp(void) { }
+static inline void load_ucode_intel_bsp(struct early_load_data *ed) { }
static inline void load_ucode_intel_ap(void) { }
static inline void reload_ucode_intel(void) { }
static inline struct microcode_ops *init_intel_microcode(void) { return NULL; }
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index e6bba12c759..01fa06dd06b 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -262,11 +262,14 @@ static uint32_t __init ms_hyperv_platform(void)
static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
{
static atomic_t nmi_cpu = ATOMIC_INIT(-1);
+ unsigned int old_cpu, this_cpu;
if (!unknown_nmi_panic)
return NMI_DONE;
- if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1)
+ old_cpu = -1;
+ this_cpu = raw_smp_processor_id();
+ if (!atomic_try_cmpxchg(&nmi_cpu, &old_cpu, this_cpu))
return NMI_HANDLED;
return NMI_DONE;
diff --git a/block/bdev.c b/block/bdev.c
index e4cfb7adb64..750aec178b6 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -425,6 +425,8 @@ void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
void bdev_add(struct block_device *bdev, dev_t dev)
{
+ if (bdev_stable_writes(bdev))
+ mapping_set_stable_writes(bdev->bd_inode->i_mapping);
bdev->bd_dev = dev;
bdev->bd_inode->i_rdev = dev;
bdev->bd_inode->i_ino = dev;
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 4a42ea2972a..4b48c2c4409 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -577,6 +577,7 @@ static void blkg_destroy_all(struct gendisk *disk)
struct request_queue *q = disk->queue;
struct blkcg_gq *blkg, *n;
int count = BLKG_DESTROY_BATCH_SIZE;
+ int i;
restart:
spin_lock_irq(&q->queue_lock);
@@ -602,6 +603,18 @@ static void blkg_destroy_all(struct gendisk *disk)
}
}
+ /*
+ * Mark policy deactivated since policy offline has been done, and
+ * the free is scheduled, so future blkcg_deactivate_policy() can
+ * be bypassed
+ */
+ for (i = 0; i < BLKCG_MAX_POLS; i++) {
+ struct blkcg_policy *pol = blkcg_policy[i];
+
+ if (pol)
+ __clear_bit(pol->plid, q->blkcg_pols);
+ }
+
q->root_blkg = NULL;
spin_unlock_irq(&q->queue_lock);
}
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 624c03c8fe6..fd482439afb 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -249,8 +249,6 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
{
struct blkcg_gq *blkg;
- WARN_ON_ONCE(!rcu_read_lock_held());
-
if (blkcg == &blkcg_root)
return q->root_blkg;
diff --git a/block/blk-pm.c b/block/blk-pm.c
index 6b72b2e03fc..42e84207471 100644
--- a/block/blk-pm.c
+++ b/block/blk-pm.c
@@ -163,38 +163,15 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
* @q: the queue of the device
*
* Description:
- * For historical reasons, this routine merely calls blk_set_runtime_active()
- * to do the real work of restarting the queue. It does this regardless of
- * whether the device's runtime-resume succeeded; even if it failed the
+ * Restart the queue of a runtime suspended device. It does this regardless
+ * of whether the device's runtime-resume succeeded; even if it failed the
* driver or error handler will need to communicate with the device.
*
* This function should be called near the end of the device's
- * runtime_resume callback.
+ * runtime_resume callback to correct queue runtime PM status and re-enable
+ * peeking requests from the queue.
*/
void blk_post_runtime_resume(struct request_queue *q)
-{
- blk_set_runtime_active(q);
-}
-EXPORT_SYMBOL(blk_post_runtime_resume);
-
-/**
- * blk_set_runtime_active - Force runtime status of the queue to be active
- * @q: the queue of the device
- *
- * If the device is left runtime suspended during system suspend the resume
- * hook typically resumes the device and corrects runtime status
- * accordingly. However, that does not affect the queue runtime PM status
- * which is still "suspended". This prevents processing requests from the
- * queue.
- *
- * This function can be used in driver's resume hook to correct queue
- * runtime PM status and re-enable peeking requests from the queue. It
- * should be called before first request is added to the queue.
- *
- * This function is also called by blk_post_runtime_resume() for
- * runtime resumes. It does everything necessary to restart the queue.
- */
-void blk_set_runtime_active(struct request_queue *q)
{
int old_status;
@@ -211,4 +188,4 @@ void blk_set_runtime_active(struct request_queue *q)
if (old_status != RPM_ACTIVE)
blk_clear_pm_only(q);
}
-EXPORT_SYMBOL(blk_set_runtime_active);
+EXPORT_SYMBOL(blk_post_runtime_resume);
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 13e4377a8b2..16f5766620a 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1320,6 +1320,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
tg_bps_limit(tg, READ), tg_bps_limit(tg, WRITE),
tg_iops_limit(tg, READ), tg_iops_limit(tg, WRITE));
+ rcu_read_lock();
/*
* Update has_rules[] flags for the updated tg's subtree. A tg is
* considered to have rules if either the tg itself or any of its
@@ -1347,6 +1348,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global)
this_tg->latency_target = max(this_tg->latency_target,
parent_tg->latency_target);
}
+ rcu_read_unlock();
/*
* We're already holding queue_lock and know @tg is valid. Let's
diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
index 5c0246b9e52..4ccf1994b97 100644
--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
+++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
@@ -502,6 +502,16 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
return ret;
}
+static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev)
+{
+ ivpu_boot_dpu_active_drive(vdev, false);
+ ivpu_boot_pwr_island_isolation_drive(vdev, true);
+ ivpu_boot_pwr_island_trickle_drive(vdev, false);
+ ivpu_boot_pwr_island_drive(vdev, false);
+
+ return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0);
+}
+
static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev)
{
u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES);
@@ -600,25 +610,17 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev)
static int ivpu_hw_37xx_reset(struct ivpu_device *vdev)
{
- int ret;
- u32 val;
-
- if (IVPU_WA(punit_disabled))
- return 0;
+ int ret = 0;
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret) {
- ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n");
- return ret;
+ if (ivpu_boot_pwr_domain_disable(vdev)) {
+ ivpu_err(vdev, "Failed to disable power domain\n");
+ ret = -EIO;
}
- val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET);
- val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val);
- REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val);
-
- ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US);
- if (ret)
- ivpu_err(vdev, "Timed out waiting for RESET completion\n");
+ if (ivpu_pll_disable(vdev)) {
+ ivpu_err(vdev, "Failed to disable PLL\n");
+ ret = -EIO;
+ }
return ret;
}
@@ -651,10 +653,6 @@ static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev)
{
int ret;
- ret = ivpu_hw_37xx_reset(vdev);
- if (ret)
- ivpu_warn(vdev, "Failed to reset HW: %d\n", ret);
-
ret = ivpu_hw_37xx_d0i3_disable(vdev);
if (ret)
ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);
@@ -722,11 +720,11 @@ static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev)
{
int ret = 0;
- if (!ivpu_hw_37xx_is_idle(vdev) && ivpu_hw_37xx_reset(vdev))
- ivpu_err(vdev, "Failed to reset the VPU\n");
+ if (!ivpu_hw_37xx_is_idle(vdev))
+ ivpu_warn(vdev, "VPU not idle during power down\n");
- if (ivpu_pll_disable(vdev)) {
- ivpu_err(vdev, "Failed to disable PLL\n");
+ if (ivpu_hw_37xx_reset(vdev)) {
+ ivpu_err(vdev, "Failed to reset VPU\n");
ret = -EIO;
}
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 0b7a01f38b6..d321ca7160d 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -2031,7 +2031,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
* HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0
* evaluated to have functional panel brightness control.
*/
- acpi_device_fix_up_power_extended(device);
+ acpi_device_fix_up_power_children(device);
pr_info("%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index f007116a842..3b4d048c494 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -397,6 +397,19 @@ void acpi_device_fix_up_power_extended(struct acpi_device *adev)
}
EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended);
+/**
+ * acpi_device_fix_up_power_children - Force a device's children into D0.
+ * @adev: Parent device object whose children's power state is to be fixed up.
+ *
+ * Call acpi_device_fix_up_power() for @adev's children so long as they
+ * are reported as present and enabled.
+ */
+void acpi_device_fix_up_power_children(struct acpi_device *adev)
+{
+ acpi_dev_for_each_child(adev, fix_up_power_if_applicable, NULL);
+}
+EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_children);
+
int acpi_device_update_power(struct acpi_device *device, int *state_p)
{
int state;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 3a34a8c425f..55437f5e0c3 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -592,7 +592,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
while (1) {
if (cx->entry_method == ACPI_CSTATE_HALT)
- safe_halt();
+ raw_safe_halt();
else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
io_idle(cx->address);
} else
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 15a3bdbd075..9bd9f79cd40 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -447,6 +447,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"),
},
},
+ {
+ /* Asus ExpertBook B1402CVA */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"),
+ },
+ },
{
/* Asus ExpertBook B1502CBA */
.matches = {
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 25a63d043c8..0f77e042406 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -82,6 +82,9 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
if (pnp_port_valid(idev, 1)) {
ctl_addr = devm_ioport_map(&idev->dev,
pnp_port_start(idev, 1), 1);
+ if (!ctl_addr)
+ return -ENOMEM;
+
ap->ioaddr.altstatus_addr = ctl_addr;
ap->ioaddr.ctl_addr = ctl_addr;
ap->ops = &isapnp_port_ops;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 855fdf5c3b4..b6414e1e645 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -67,6 +67,7 @@ struct nbd_sock {
struct recv_thread_args {
struct work_struct work;
struct nbd_device *nbd;
+ struct nbd_sock *nsock;
int index;
};
@@ -395,6 +396,22 @@ static u32 req_to_nbd_cmd_type(struct request *req)
}
}
+static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd)
+{
+ if (refcount_inc_not_zero(&nbd->config_refs)) {
+ /*
+ * Add smp_mb__after_atomic to ensure that reading nbd->config_refs
+ * and reading nbd->config is ordered. The pair is the barrier in
+ * nbd_alloc_and_init_config(), avoid nbd->config_refs is set
+ * before nbd->config.
+ */
+ smp_mb__after_atomic();
+ return nbd->config;
+ }
+
+ return NULL;
+}
+
static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
{
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
@@ -409,13 +426,13 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
return BLK_EH_DONE;
}
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
cmd->status = BLK_STS_TIMEOUT;
__clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
mutex_unlock(&cmd->lock);
goto done;
}
- config = nbd->config;
if (config->num_connections > 1 ||
(config->num_connections == 1 && nbd->tag_set.timeout)) {
@@ -489,15 +506,9 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)
return BLK_EH_DONE;
}
-/*
- * Send or receive packet. Return a positive value on success and
- * negtive value on failue, and never return 0.
- */
-static int sock_xmit(struct nbd_device *nbd, int index, int send,
- struct iov_iter *iter, int msg_flags, int *sent)
+static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,
+ struct iov_iter *iter, int msg_flags, int *sent)
{
- struct nbd_config *config = nbd->config;
- struct socket *sock = config->socks[index]->sock;
int result;
struct msghdr msg;
unsigned int noreclaim_flag;
@@ -540,6 +551,19 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
return result;
}
+/*
+ * Send or receive packet. Return a positive value on success and
+ * negtive value on failure, and never return 0.
+ */
+static int sock_xmit(struct nbd_device *nbd, int index, int send,
+ struct iov_iter *iter, int msg_flags, int *sent)
+{
+ struct nbd_config *config = nbd->config;
+ struct socket *sock = config->socks[index]->sock;
+
+ return __sock_xmit(nbd, sock, send, iter, msg_flags, sent);
+}
+
/*
* Different settings for sk->sk_sndtimeo can result in different return values
* if there is a signal pending when we enter sendmsg, because reasons?
@@ -696,7 +720,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
return 0;
}
-static int nbd_read_reply(struct nbd_device *nbd, int index,
+static int nbd_read_reply(struct nbd_device *nbd, struct socket *sock,
struct nbd_reply *reply)
{
struct kvec iov = {.iov_base = reply, .iov_len = sizeof(*reply)};
@@ -705,7 +729,7 @@ static int nbd_read_reply(struct nbd_device *nbd, int index,
reply->magic = 0;
iov_iter_kvec(&to, ITER_DEST, &iov, 1, sizeof(*reply));
- result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
+ result = __sock_xmit(nbd, sock, 0, &to, MSG_WAITALL, NULL);
if (result < 0) {
if (!nbd_disconnected(nbd->config))
dev_err(disk_to_dev(nbd->disk),
@@ -829,14 +853,14 @@ static void recv_work(struct work_struct *work)
struct nbd_device *nbd = args->nbd;
struct nbd_config *config = nbd->config;
struct request_queue *q = nbd->disk->queue;
- struct nbd_sock *nsock;
+ struct nbd_sock *nsock = args->nsock;
struct nbd_cmd *cmd;
struct request *rq;
while (1) {
struct nbd_reply reply;
- if (nbd_read_reply(nbd, args->index, &reply))
+ if (nbd_read_reply(nbd, nsock->sock, &reply))
break;
/*
@@ -871,7 +895,6 @@ static void recv_work(struct work_struct *work)
percpu_ref_put(&q->q_usage_counter);
}
- nsock = config->socks[args->index];
mutex_lock(&nsock->tx_lock);
nbd_mark_nsock_dead(nbd, nsock, 1);
mutex_unlock(&nsock->tx_lock);
@@ -977,12 +1000,12 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
struct nbd_sock *nsock;
int ret;
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
dev_err_ratelimited(disk_to_dev(nbd->disk),
"Socks array is empty\n");
return -EINVAL;
}
- config = nbd->config;
if (index >= config->num_connections) {
dev_err_ratelimited(disk_to_dev(nbd->disk),
@@ -1215,6 +1238,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
INIT_WORK(&args->work, recv_work);
args->index = i;
args->nbd = nbd;
+ args->nsock = nsock;
nsock->cookie++;
mutex_unlock(&nsock->tx_lock);
sockfd_put(old);
@@ -1397,6 +1421,7 @@ static int nbd_start_device(struct nbd_device *nbd)
refcount_inc(&nbd->config_refs);
INIT_WORK(&args->work, recv_work);
args->nbd = nbd;
+ args->nsock = config->socks[i];
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
@@ -1530,17 +1555,20 @@ static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,
return error;
}
-static struct nbd_config *nbd_alloc_config(void)
+static int nbd_alloc_and_init_config(struct nbd_device *nbd)
{
struct nbd_config *config;
+ if (WARN_ON(nbd->config))
+ return -EINVAL;
+
if (!try_module_get(THIS_MODULE))
- return ERR_PTR(-ENODEV);
+ return -ENODEV;
config = kzalloc(sizeof(struct nbd_config), GFP_NOFS);
if (!config) {
module_put(THIS_MODULE);
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
atomic_set(&config->recv_threads, 0);
@@ -1548,12 +1576,24 @@ static struct nbd_config *nbd_alloc_config(void)
init_waitqueue_head(&config->conn_wait);
config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
atomic_set(&config->live_connections, 0);
- return config;
+
+ nbd->config = config;
+ /*
+ * Order refcount_set(&nbd->config_refs, 1) and nbd->config assignment,
+ * its pair is the barrier in nbd_get_config_unlocked().
+ * So nbd_get_config_unlocked() won't see nbd->config as null after
+ * refcount_inc_not_zero() succeed.
+ */
+ smp_mb__before_atomic();
+ refcount_set(&nbd->config_refs, 1);
+
+ return 0;
}
static int nbd_open(struct gendisk *disk, blk_mode_t mode)
{
struct nbd_device *nbd;
+ struct nbd_config *config;
int ret = 0;
mutex_lock(&nbd_index_mutex);
@@ -1566,27 +1606,25 @@ static int nbd_open(struct gendisk *disk, blk_mode_t mode)
ret = -ENXIO;
goto out;
}
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
- struct nbd_config *config;
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
mutex_lock(&nbd->config_lock);
if (refcount_inc_not_zero(&nbd->config_refs)) {
mutex_unlock(&nbd->config_lock);
goto out;
}
- config = nbd_alloc_config();
- if (IS_ERR(config)) {
- ret = PTR_ERR(config);
+ ret = nbd_alloc_and_init_config(nbd);
+ if (ret) {
mutex_unlock(&nbd->config_lock);
goto out;
}
- nbd->config = config;
- refcount_set(&nbd->config_refs, 1);
+
refcount_inc(&nbd->refs);
mutex_unlock(&nbd->config_lock);
if (max_part)
set_bit(GD_NEED_PART_SCAN, &disk->state);
- } else if (nbd_disconnected(nbd->config)) {
+ } else if (nbd_disconnected(config)) {
if (max_part)
set_bit(GD_NEED_PART_SCAN, &disk->state);
}
@@ -1990,22 +2028,17 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
pr_err("nbd%d already in use\n", index);
return -EBUSY;
}
- if (WARN_ON(nbd->config)) {
- mutex_unlock(&nbd->config_lock);
- nbd_put(nbd);
- return -EINVAL;
- }
- config = nbd_alloc_config();
- if (IS_ERR(config)) {
+
+ ret = nbd_alloc_and_init_config(nbd);
+ if (ret) {
mutex_unlock(&nbd->config_lock);
nbd_put(nbd);
pr_err("couldn't allocate config\n");
- return PTR_ERR(config);
+ return ret;
}
- nbd->config = config;
- refcount_set(&nbd->config_refs, 1);
- set_bit(NBD_RT_BOUND, &config->runtime_flags);
+ config = nbd->config;
+ set_bit(NBD_RT_BOUND, &config->runtime_flags);
ret = nbd_genl_size_set(info, nbd);
if (ret)
goto out;
@@ -2208,7 +2241,8 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
}
mutex_unlock(&nbd_index_mutex);
- if (!refcount_inc_not_zero(&nbd->config_refs)) {
+ config = nbd_get_config_unlocked(nbd);
+ if (!config) {
dev_err(nbd_to_dev(nbd),
"not configured, cannot reconfigure\n");
nbd_put(nbd);
@@ -2216,7 +2250,6 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
}
mutex_lock(&nbd->config_lock);
- config = nbd->config;
if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) ||
!nbd->pid) {
dev_err(nbd_to_dev(nbd),
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index 22a3cf7f32e..3021d58ca51 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1464,19 +1464,13 @@ blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op,
return BLK_STS_OK;
}
-static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
- sector_t nr_sectors, enum req_op op)
+static void null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
+ sector_t nr_sectors, enum req_op op)
{
struct nullb_device *dev = cmd->nq->dev;
struct nullb *nullb = dev->nullb;
blk_status_t sts;
- if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) {
- sts = null_handle_throttled(cmd);
- if (sts != BLK_STS_OK)
- return sts;
- }
-
if (op == REQ_OP_FLUSH) {
cmd->error = errno_to_blk_status(null_handle_flush(nullb));
goto out;
@@ -1493,7 +1487,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
out:
nullb_complete_cmd(cmd);
- return BLK_STS_OK;
}
static enum hrtimer_restart nullb_bwtimer_fn(struct hrtimer *timer)
@@ -1724,8 +1717,6 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
cmd->fake_timeout = should_timeout_request(rq) ||
blk_should_fake_timeout(rq->q);
- blk_mq_start_request(rq);
-
if (should_requeue_request(rq)) {
/*
* Alternate between hitting the core BUSY path, and the
@@ -1738,6 +1729,15 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_OK;
}
+ if (test_bit(NULLB_DEV_FL_THROTTLED, &nq->dev->flags)) {
+ blk_status_t sts = null_handle_throttled(cmd);
+
+ if (sts != BLK_STS_OK)
+ return sts;
+ }
+
+ blk_mq_start_request(rq);
+
if (is_poll) {
spin_lock(&nq->poll_lock);
list_add_tail(&rq->queuelist, &nq->poll_list);
@@ -1747,7 +1747,8 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
if (cmd->fake_timeout)
return BLK_STS_OK;
- return null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
+ null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
+ return BLK_STS_OK;
}
static void null_queue_rqs(struct request **rqlist)
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index a6dc3997bf5..442a0ebeb95 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -1093,9 +1093,10 @@ int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info)
return -ENOMEM;
hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
DPLL_CMD_PIN_ID_GET);
- if (!hdr)
+ if (!hdr) {
+ nlmsg_free(msg);
return -EMSGSIZE;
-
+ }
pin = dpll_pin_find_from_nlattr(info);
if (!IS_ERR(pin)) {
ret = dpll_msg_add_pin_handle(msg, pin);
@@ -1123,8 +1124,10 @@ int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info)
return -ENOMEM;
hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
DPLL_CMD_PIN_GET);
- if (!hdr)
+ if (!hdr) {
+ nlmsg_free(msg);
return -EMSGSIZE;
+ }
ret = dpll_cmd_pin_get_one(msg, pin, info->extack);
if (ret) {
nlmsg_free(msg);
@@ -1256,8 +1259,10 @@ int dpll_nl_device_id_get_doit(struct sk_buff *skb, struct genl_info *info)
return -ENOMEM;
hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
DPLL_CMD_DEVICE_ID_GET);
- if (!hdr)
+ if (!hdr) {
+ nlmsg_free(msg);
return -EMSGSIZE;
+ }
dpll = dpll_device_find_from_nlattr(info);
if (!IS_ERR(dpll)) {
@@ -1284,8 +1289,10 @@ int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info)
return -ENOMEM;
hdr = genlmsg_put_reply(msg, info, &dpll_nl_family, 0,
DPLL_CMD_DEVICE_GET);
- if (!hdr)
+ if (!hdr) {
+ nlmsg_free(msg);
return -EMSGSIZE;
+ }
ret = dpll_device_get_one(dpll, msg, info->extack);
if (ret) {
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 2aee32344f4..772f3b049c1 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -174,6 +174,17 @@ to_ast_sil164_connector(struct drm_connector *connector)
return container_of(connector, struct ast_sil164_connector, base);
}
+struct ast_bmc_connector {
+ struct drm_connector base;
+ struct drm_connector *physical_connector;
+};
+
+static inline struct ast_bmc_connector *
+to_ast_bmc_connector(struct drm_connector *connector)
+{
+ return container_of(connector, struct ast_bmc_connector, base);
+}
+
/*
* Device
*/
@@ -218,7 +229,7 @@ struct ast_device {
} astdp;
struct {
struct drm_encoder encoder;
- struct drm_connector connector;
+ struct ast_bmc_connector bmc_connector;
} bmc;
} output;
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index cb961498428..c20534d0ef7 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -1767,6 +1767,30 @@ static const struct drm_encoder_funcs ast_bmc_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
+static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool force)
+{
+ struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector);
+ struct drm_connector *physical_connector = bmc_connector->physical_connector;
+
+ /*
+ * Most user-space compositors cannot handle more than one connected
+ * connector per CRTC. Hence, we only mark the BMC as connected if the
+ * physical connector is disconnected. If the physical connector's status
+ * is connected or unknown, the BMC remains disconnected. This has no
+ * effect on the output of the BMC.
+ *
+ * FIXME: Remove this logic once user-space compositors can handle more
+ * than one connector per CRTC. The BMC should always be connected.
+ */
+
+ if (physical_connector && physical_connector->status == connector_status_disconnected)
+ return connector_status_connected;
+
+ return connector_status_disconnected;
+}
+
static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
{
return drm_add_modes_noedid(connector, 4096, 4096);
@@ -1774,6 +1798,7 @@ static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {
.get_modes = ast_bmc_connector_helper_get_modes,
+ .detect_ctx = ast_bmc_connector_helper_detect_ctx,
};
static const struct drm_connector_funcs ast_bmc_connector_funcs = {
@@ -1784,12 +1809,33 @@ static const struct drm_connector_funcs ast_bmc_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-static int ast_bmc_output_init(struct ast_device *ast)
+static int ast_bmc_connector_init(struct drm_device *dev,
+ struct ast_bmc_connector *bmc_connector,
+ struct drm_connector *physical_connector)
+{
+ struct drm_connector *connector = &bmc_connector->base;
+ int ret;
+
+ ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
+ DRM_MODE_CONNECTOR_VIRTUAL);
+ if (ret)
+ return ret;
+
+ drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
+
+ bmc_connector->physical_connector = physical_connector;
+
+ return 0;
+}
+
+static int ast_bmc_output_init(struct ast_device *ast,
+ struct drm_connector *physical_connector)
{
struct drm_device *dev = &ast->base;
struct drm_crtc *crtc = &ast->crtc;
struct drm_encoder *encoder = &ast->output.bmc.encoder;
- struct drm_connector *connector = &ast->output.bmc.connector;
+ struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector;
+ struct drm_connector *connector = &bmc_connector->base;
int ret;
ret = drm_encoder_init(dev, encoder,
@@ -1799,13 +1845,10 @@ static int ast_bmc_output_init(struct ast_device *ast)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
- DRM_MODE_CONNECTOR_VIRTUAL);
+ ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector);
if (ret)
return ret;
- drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
-
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
@@ -1864,6 +1907,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = {
int ast_mode_config_init(struct ast_device *ast)
{
struct drm_device *dev = &ast->base;
+ struct drm_connector *physical_connector = NULL;
int ret;
ret = drmm_mode_config_init(dev);
@@ -1904,23 +1948,27 @@ int ast_mode_config_init(struct ast_device *ast)
ret = ast_vga_output_init(ast);
if (ret)
return ret;
+ physical_connector = &ast->output.vga.vga_connector.base;
}
if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
ret = ast_sil164_output_init(ast);
if (ret)
return ret;
+ physical_connector = &ast->output.sil164.sil164_connector.base;
}
if (ast->tx_chip_types & AST_TX_DP501_BIT) {
ret = ast_dp501_output_init(ast);
if (ret)
return ret;
+ physical_connector = &ast->output.dp501.connector;
}
if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
ret = ast_astdp_output_init(ast);
if (ret)
return ret;
+ physical_connector = &ast->output.astdp.connector;
}
- ret = ast_bmc_output_init(ast);
+ ret = ast_bmc_output_init(ast, physical_connector);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 7b4628f4f12..851b312bd84 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1161,6 +1161,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
intel_connector->port = port;
drm_dp_mst_get_port_malloc(port);
+ /*
+ * TODO: set the AUX for the actual MST port decompressing the stream.
+ * At the moment the driver only supports enabling this globally in the
+ * first downstream MST branch, via intel_dp's (root port) AUX.
+ */
+ intel_connector->dp.dsc_decompression_aux = &intel_dp->aux;
+ intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
+
connector = &intel_connector->base;
ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
DRM_MODE_CONNECTOR_DisplayPort);
@@ -1172,14 +1180,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
- /*
- * TODO: set the AUX for the actual MST port decompressing the stream.
- * At the moment the driver only supports enabling this globally in the
- * first downstream MST branch, via intel_dp's (root port) AUX.
- */
- intel_connector->dp.dsc_decompression_aux = &intel_dp->aux;
- intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
-
for_each_pipe(dev_priv, pipe) {
struct drm_encoder *enc =
&intel_dp->mst_encoders[pipe]->base.base;
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index ed32bf5b154..ba1186fc524 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -982,8 +982,6 @@ int intel_gt_probe_all(struct drm_i915_private *i915)
err:
i915_probe_error(i915, "Failed to initialize %s! (%d)\n", gtdef->name, ret);
- intel_gt_release_all(i915);
-
return ret;
}
@@ -1002,15 +1000,6 @@ int intel_gt_tiles_init(struct drm_i915_private *i915)
return 0;
}
-void intel_gt_release_all(struct drm_i915_private *i915)
-{
- struct intel_gt *gt;
- unsigned int id;
-
- for_each_gt(gt, i915, id)
- i915->gt[id] = NULL;
-}
-
void intel_gt_info_print(const struct intel_gt_info *info,
struct drm_printer *p)
{
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index 8a0e2c745e1..802de2c6dec 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -782,7 +782,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ret = i915_driver_mmio_probe(i915);
if (ret < 0)
- goto out_tiles_cleanup;
+ goto out_runtime_pm_put;
ret = i915_driver_hw_probe(i915);
if (ret < 0)
@@ -842,8 +842,6 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i915_ggtt_driver_late_release(i915);
out_cleanup_mmio:
i915_driver_mmio_release(i915);
-out_tiles_cleanup:
- intel_gt_release_all(i915);
out_runtime_pm_put:
enable_rpm_wakeref_asserts(&i915->runtime_pm);
i915_driver_late_release(i915);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
index 1ccd1edd693..4c0528794e7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
@@ -406,6 +406,7 @@ static const struct dpu_perf_cfg sc8280xp_perf_data = {
.min_llcc_ib = 0,
.min_dram_ib = 800000,
.danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sc8180x_qos_linear),
.entries = sc8180x_qos_linear
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 11d9fc2c6bf..ec933d597e2 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -844,8 +844,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
return 0;
fail:
- if (mdp5_kms)
- mdp5_destroy(mdp5_kms);
+ mdp5_destroy(mdp5_kms);
return ret;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index e329e03e068..1b88fb52726 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -365,9 +365,11 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,
/* reset video pattern flag on disconnect */
if (!hpd) {
dp->panel->video_test = false;
- drm_dp_set_subconnector_property(dp->dp_display.connector,
- connector_status_disconnected,
- dp->panel->dpcd, dp->panel->downstream_ports);
+ if (!dp->dp_display.is_edp)
+ drm_dp_set_subconnector_property(dp->dp_display.connector,
+ connector_status_disconnected,
+ dp->panel->dpcd,
+ dp->panel->downstream_ports);
}
dp->dp_display.is_connected = hpd;
@@ -396,8 +398,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
dp_link_process_request(dp->link);
- drm_dp_set_subconnector_property(dp->dp_display.connector, connector_status_connected,
- dp->panel->dpcd, dp->panel->downstream_ports);
+ if (!dp->dp_display.is_edp)
+ drm_dp_set_subconnector_property(dp->dp_display.connector,
+ connector_status_connected,
+ dp->panel->dpcd,
+ dp->panel->downstream_ports);
edid = dp->panel->edid;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 40e7344180e..e3bdd7dd4cd 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -345,6 +345,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct dr
if (IS_ERR(connector))
return connector;
+ if (!dp_display->is_edp)
+ drm_connector_attach_dp_subconnector_property(connector);
+
drm_connector_attach_encoder(connector, encoder);
return connector;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 3b1ed02f644..89a6344bc86 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -918,7 +918,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
if (phy->cphy_mode) {
vreg_ctrl_0 = 0x45;
- vreg_ctrl_1 = 0x45;
+ vreg_ctrl_1 = 0x41;
glbl_rescode_top_ctrl = 0x00;
glbl_rescode_bot_ctrl = 0x00;
} else {
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 2aae7d107f3..3f217b57829 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -288,8 +288,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
if (ret)
goto err_msm_uninit;
- drm_kms_helper_poll_init(ddev);
-
if (priv->kms_init) {
drm_kms_helper_poll_init(ddev);
msm_fbdev_setup(ddev);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/r535.c
index 3adbb05ff58..d088e636edc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/r535.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/r535.c
@@ -539,7 +539,7 @@ r535_fifo_runl_ctor(struct nvkm_fifo *fifo)
struct nvkm_runl *runl;
struct nvkm_engn *engn;
u32 cgids = 2048;
- u32 chids = 2048 / CHID_PER_USERD;
+ u32 chids = 2048;
int ret;
NV2080_CTRL_FIFO_GET_DEVICE_INFO_TABLE_PARAMS *ctrl;
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 99e14dc212e..99124320288 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -398,6 +398,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
@@ -644,16 +654,28 @@ config DRM_PANEL_SAMSUNG_S6E8AA0
select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_SOFEF00
- tristate "Samsung sofef00/s6e3fc2x01 OnePlus 6/6T DSI cmd mode panels"
+ tristate "Samsung sofef00 OnePlus 6 DSI cmd mode panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
+ help
+ Say Y or M here if you want to enable support for the Samsung AMOLED
+ command mode panel found in the OnePlus 6 smartphone.
+
+ The panel is 2280x1080@60Hz
+
+config DRM_PANEL_SAMSUNG_S6E3FC2X01
+ tristate "Samsung s6e3fc2x01 OnePlus 6T DSI cmd mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y or M here if you want to enable support for the Samsung AMOLED
- command mode panels found in the OnePlus 6/6T smartphones.
+ command mode panel found in the OnePlus 6T smartphone.
- The panels are 2280x1080@60Hz and 2340x1080@60Hz respectively
+ The panel is 2340x1080@60Hz
config DRM_PANEL_SEIKO_43WVF1G
tristate "Seiko 43WVF1G panel"
@@ -825,6 +847,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 d10c3de51c6..9fd3ac441b3 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35560) += panel-novatek-nt35560.o
+obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35596S) += panel-novatek-nt35596s.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o
@@ -66,6 +67,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
@@ -84,6 +86,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-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
index 9323e7b9e38..be8f48e3c1d 100644
--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
@@ -1709,6 +1709,7 @@ static const struct panel_desc auo_b101uan08_3_desc = {
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM,
.init_cmds = auo_b101uan08_3_init_cmd,
+ .lp11_before_reset = true,
};
static const struct drm_display_mode boe_tv105wum_nw0_default_mode = {
@@ -1766,11 +1767,11 @@ static const struct panel_desc starry_qfh032011_53g_desc = {
};
static const struct drm_display_mode starry_himax83102_j02_default_mode = {
- .clock = 161600,
+ .clock = 162850,
.hdisplay = 1200,
- .hsync_start = 1200 + 40,
- .hsync_end = 1200 + 40 + 20,
- .htotal = 1200 + 40 + 20 + 40,
+ .hsync_start = 1200 + 50,
+ .hsync_end = 1200 + 50 + 20,
+ .htotal = 1200 + 50 + 20 + 50,
.vdisplay = 1920,
.vsync_start = 1920 + 116,
.vsync_end = 1920 + 116 + 8,
diff --git a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c
index e85d63a176d..2ad37758079 100644
--- a/drivers/gpu/drm/panel/panel-ebbg-ft8719.c
+++ b/drivers/gpu/drm/panel/panel-ebbg-ft8719.c
@@ -87,22 +87,22 @@ static int ebbg_ft8719_on(struct ebbg_ft8719 *ctx)
return 0;
}
-static int ebbg_ft8719_off(struct ebbg_ft8719 *ctx)
+static int ebbg_ft8719_disable(struct drm_panel *panel)
{
- struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
+ struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel);
+ struct device *dev = &ctx->dsi->dev;
int ret;
- dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+ ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
- ret = mipi_dsi_dcs_set_display_off(dsi);
+ ret = mipi_dsi_dcs_set_display_off(ctx->dsi);
if (ret < 0) {
dev_err(dev, "Failed to set display off: %d\n", ret);
return ret;
}
usleep_range(10000, 11000);
- ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ ret = mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
if (ret < 0) {
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
@@ -137,13 +137,8 @@ static int ebbg_ft8719_prepare(struct drm_panel *panel)
static int ebbg_ft8719_unprepare(struct drm_panel *panel)
{
struct ebbg_ft8719 *ctx = to_ebbg_ft8719(panel);
- struct device *dev = &ctx->dsi->dev;
int ret;
- ret = ebbg_ft8719_off(ctx);
- if (ret < 0)
- dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
-
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
@@ -188,6 +183,7 @@ static int ebbg_ft8719_get_modes(struct drm_panel *panel,
static const struct drm_panel_funcs ebbg_ft8719_panel_funcs = {
.prepare = ebbg_ft8719_prepare,
+ .disable = ebbg_ft8719_disable,
.unprepare = ebbg_ft8719_unprepare,
.get_modes = ebbg_ft8719_get_modes,
};
@@ -233,6 +229,7 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi)
drm_panel_init(&ctx->panel, dev, &ebbg_ft8719_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
ret = drm_panel_of_backlight(&ctx->panel);
if (ret)
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35596s.c b/drivers/gpu/drm/panel/panel-novatek-nt35596s.c
new file mode 100644
index 00000000000..b1c724ebf8f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-novatek-nt35596s.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Linaro Ltd
+ * Author: Sumit Semwal <sumit.semwal@linaro.org>
+ * Copyright (C) 2023 Arnaud Ferraris <arnaud.ferraris@collabora.com>
+ *
+ * This driver is for the DSI interface to panels using the NT35596S display driver IC
+ * from Novatek.
+ * Currently supported are the JDI FHD panels found in some Xiaomi phones, including
+ * some variants of the Mi Mix 2S phone.
+ *
+ * Panels using the Novatek NT35596S IC should add appropriate configuration per-panel and
+ * use this driver.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <video/mipi_display.h>
+
+struct nt35596s_panel_cmd {
+ const char data[2];
+};
+
+static const char * const nt35596s_regulator_names[] = {
+ "vddio",
+ "vddpos",
+ "vddneg",
+};
+
+static unsigned long const nt35596s_regulator_enable_loads[] = {
+ 62000,
+ 100000,
+ 100000
+};
+
+struct nt35596s_panel_desc {
+ const struct drm_display_mode *display_mode;
+ const char *panel_name;
+
+ unsigned int width_mm;
+ unsigned int height_mm;
+
+ unsigned long mode_flags;
+ enum mipi_dsi_pixel_format format;
+ unsigned int lanes;
+
+ unsigned int num_on_cmds;
+ const struct nt35596s_panel_cmd *on_cmds;
+};
+
+struct nt35596s_panel {
+ struct drm_panel base;
+ struct mipi_dsi_device *link;
+ const struct nt35596s_panel_desc *desc;
+
+ struct regulator_bulk_data supplies[ARRAY_SIZE(nt35596s_regulator_names)];
+
+ struct gpio_desc *reset_gpio;
+
+ bool prepared;
+};
+
+static inline struct nt35596s_panel *to_nt35596s_panel(struct drm_panel *panel)
+{
+ return container_of(panel, struct nt35596s_panel, base);
+}
+
+static int nt35596s_send_cmds(struct drm_panel *panel, const struct nt35596s_panel_cmd *cmds,
+ int num)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ unsigned int i;
+ int err;
+
+ for (i = 0; i < num; i++) {
+ const struct nt35596s_panel_cmd *cmd = &cmds[i];
+
+ err = mipi_dsi_dcs_write(pinfo->link, cmd->data[0], cmd->data + 1, 1);
+
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int nt35596s_panel_power_off(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int ret = 0;
+
+ gpiod_set_value(pinfo->reset_gpio, 1);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(pinfo->supplies), pinfo->supplies);
+ if (ret)
+ dev_err(panel->dev, "regulator_bulk_disable failed %d\n", ret);
+
+ return ret;
+}
+
+static int nt35596s_panel_disable(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int ret;
+
+ if (!pinfo->prepared)
+ return 0;
+
+ ret = mipi_dsi_dcs_set_display_off(pinfo->link);
+ if (ret < 0)
+ dev_err(panel->dev, "set_display_off cmd failed ret = %d\n", ret);
+
+ /* 120ms delay required here as per DCS spec */
+ msleep(120);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
+ if (ret < 0)
+ dev_err(panel->dev, "enter_sleep cmd failed ret = %d\n", ret);
+
+ /* 0x3C = 60ms delay */
+ msleep(60);
+
+ return ret;
+}
+
+static int nt35596s_panel_unprepare(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int ret;
+
+ ret = nt35596s_panel_power_off(panel);
+ if (ret < 0)
+ dev_err(panel->dev, "power_off failed ret = %d\n", ret);
+
+ pinfo->prepared = false;
+
+ return ret;
+}
+
+static int nt35596s_panel_power_on(struct nt35596s_panel *pinfo)
+{
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pinfo->supplies), pinfo->supplies);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * As per downstream kernel, Reset sequence of Tianma FHD panel requires the panel to
+ * be out of reset for 10ms, followed by being held in reset for 10ms. But for Android
+ * AOSP, we needed to bump it upto 200ms otherwise we get white screen sometimes.
+ * FIXME: Try to reduce this 200ms to a lesser value.
+ */
+ gpiod_set_value(pinfo->reset_gpio, 1);
+ msleep(200);
+ gpiod_set_value(pinfo->reset_gpio, 0);
+ msleep(200);
+
+ return 0;
+}
+
+static int nt35596s_panel_prepare(struct drm_panel *panel)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ int err;
+
+ if (pinfo->prepared)
+ return 0;
+
+ err = nt35596s_panel_power_on(pinfo);
+ if (err < 0)
+ goto poweroff;
+
+ /* send first part of init cmds */
+ err = nt35596s_send_cmds(panel, pinfo->desc->on_cmds,
+ pinfo->desc->num_on_cmds);
+
+ if (err < 0) {
+ dev_err(panel->dev, "failed to send DCS Init 1st Code: %d\n", err);
+ goto poweroff;
+ }
+
+ err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
+ if (err < 0) {
+ dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);
+ goto poweroff;
+ }
+
+ /* 0x46 = 70 ms delay */
+ msleep(70);
+
+ err = mipi_dsi_dcs_set_display_on(pinfo->link);
+ if (err < 0) {
+ dev_err(panel->dev, "failed to Set Display ON: %d\n", err);
+ goto poweroff;
+ }
+
+ msleep(120);
+
+ pinfo->prepared = true;
+
+ return 0;
+
+poweroff:
+ gpiod_set_value(pinfo->reset_gpio, 0);
+ return err;
+}
+
+static int nt35596s_panel_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct nt35596s_panel *pinfo = to_nt35596s_panel(panel);
+ const struct drm_display_mode *m = pinfo->desc->display_mode;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, m);
+ if (!mode) {
+ dev_err(panel->dev, "failed to add mode %ux%u@%u\n", m->hdisplay,
+ m->vdisplay, drm_mode_vrefresh(m));
+ return -ENOMEM;
+ }
+
+ connector->display_info.width_mm = pinfo->desc->width_mm;
+ connector->display_info.height_mm = pinfo->desc->height_mm;
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs panel_funcs = {
+ .disable = nt35596s_panel_disable,
+ .unprepare = nt35596s_panel_unprepare,
+ .prepare = nt35596s_panel_prepare,
+ .get_modes = nt35596s_panel_get_modes,
+};
+
+static const struct nt35596s_panel_cmd jdi_nt35596s_video_on_cmds[] = {
+ { .data = { 0xff, 0x24 } },
+ { .data = { 0x9d, 0x34 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0xc4, 0x25 } },
+ { .data = { 0xd1, 0x08 } },
+ { .data = { 0xd2, 0x84 } },
+ { .data = { 0xff, 0x26 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0x03, 0x1c } },
+ { .data = { 0x3b, 0x08 } },
+ { .data = { 0x6b, 0x08 } },
+ { .data = { 0x97, 0x08 } },
+ { .data = { 0xc5, 0x08 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0xff, 0x23 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0x01, 0x84 } },
+ { .data = { 0x05, 0x2d } },
+ { .data = { 0x06, 0x00 } },
+ { .data = { 0x33, 0x07 } },
+ { .data = { 0x21, 0xee } },
+ { .data = { 0x22, 0xed } },
+ { .data = { 0x23, 0xea } },
+ { .data = { 0x24, 0xe8 } },
+ { .data = { 0x25, 0xe5 } },
+ { .data = { 0x26, 0xe2 } },
+ { .data = { 0x27, 0xde } },
+ { .data = { 0x28, 0xbb } },
+ { .data = { 0x29, 0x87 } },
+ { .data = { 0x2a, 0x77 } },
+ { .data = { 0x32, 0x0c } },
+ { .data = { 0x13, 0x3f } },
+ { .data = { 0x14, 0x34 } },
+ { .data = { 0x15, 0x2a } },
+ { .data = { 0x16, 0x25 } },
+ { .data = { 0x17, 0x9d } },
+ { .data = { 0x18, 0x9a } },
+ { .data = { 0x19, 0x97 } },
+ { .data = { 0x1a, 0x94 } },
+ { .data = { 0x1b, 0x91 } },
+ { .data = { 0x1c, 0x8e } },
+ { .data = { 0x1d, 0x8b } },
+ { .data = { 0x1e, 0x89 } },
+ { .data = { 0x1f, 0x86 } },
+ { .data = { 0x20, 0x83 } },
+ { .data = { 0xff, 0x22 } },
+ { .data = { 0x00, 0x0a } },
+ { .data = { 0x01, 0x43 } },
+ { .data = { 0x02, 0x5b } },
+ { .data = { 0x03, 0x6a } },
+ { .data = { 0x04, 0x7a } },
+ { .data = { 0x05, 0x82 } },
+ { .data = { 0x06, 0x85 } },
+ { .data = { 0x07, 0x80 } },
+ { .data = { 0x08, 0x7c } },
+ { .data = { 0x09, 0x7c } },
+ { .data = { 0x0a, 0x74 } },
+ { .data = { 0x0b, 0x71 } },
+ { .data = { 0x0c, 0x6e } },
+ { .data = { 0x0d, 0x68 } },
+ { .data = { 0x0e, 0x65 } },
+ { .data = { 0x0f, 0x5c } },
+ { .data = { 0x10, 0x32 } },
+ { .data = { 0x11, 0x18 } },
+ { .data = { 0x12, 0x00 } },
+ { .data = { 0x13, 0x00 } },
+ { .data = { 0x1a, 0x00 } },
+ { .data = { 0x1b, 0x00 } },
+ { .data = { 0x1c, 0x00 } },
+ { .data = { 0x1d, 0x00 } },
+ { .data = { 0x1e, 0x00 } },
+ { .data = { 0x1f, 0x00 } },
+ { .data = { 0x20, 0x00 } },
+ { .data = { 0x21, 0x00 } },
+ { .data = { 0x22, 0x00 } },
+ { .data = { 0x23, 0x00 } },
+ { .data = { 0x24, 0x00 } },
+ { .data = { 0x25, 0x00 } },
+ { .data = { 0x26, 0x00 } },
+ { .data = { 0x27, 0x00 } },
+ { .data = { 0x28, 0x00 } },
+ { .data = { 0x29, 0x00 } },
+ { .data = { 0x2a, 0x00 } },
+ { .data = { 0x2b, 0x00 } },
+ { .data = { 0x2f, 0x00 } },
+ { .data = { 0x30, 0x00 } },
+ { .data = { 0x31, 0x00 } },
+ { .data = { 0x32, 0x0c } },
+ { .data = { 0x33, 0x0c } },
+ { .data = { 0x34, 0x0c } },
+ { .data = { 0x35, 0x0b } },
+ { .data = { 0x36, 0x09 } },
+ { .data = { 0x37, 0x09 } },
+ { .data = { 0x38, 0x08 } },
+ { .data = { 0x39, 0x05 } },
+ { .data = { 0x3a, 0x03 } },
+ { .data = { 0x3b, 0x00 } },
+ { .data = { 0x3f, 0x00 } },
+ { .data = { 0x40, 0x00 } },
+ { .data = { 0x41, 0x00 } },
+ { .data = { 0x42, 0x00 } },
+ { .data = { 0x43, 0x00 } },
+ { .data = { 0x44, 0x00 } },
+ { .data = { 0x45, 0x00 } },
+ { .data = { 0x46, 0x00 } },
+ { .data = { 0x47, 0x00 } },
+ { .data = { 0x48, 0x00 } },
+ { .data = { 0x49, 0x03 } },
+ { .data = { 0x4a, 0x06 } },
+ { .data = { 0x4b, 0x07 } },
+ { .data = { 0x4c, 0x07 } },
+ { .data = { 0x53, 0x01 } },
+ { .data = { 0x54, 0x01 } },
+ { .data = { 0x55, 0x89 } },
+ { .data = { 0x56, 0x00 } },
+ { .data = { 0x58, 0x00 } },
+ { .data = { 0x68, 0x00 } },
+ { .data = { 0x84, 0xff } },
+ { .data = { 0x85, 0xff } },
+ { .data = { 0x86, 0x03 } },
+ { .data = { 0x87, 0x00 } },
+ { .data = { 0x88, 0x00 } },
+ { .data = { 0xa2, 0x20 } },
+ { .data = { 0xa9, 0x01 } },
+ { .data = { 0xaa, 0x12 } },
+ { .data = { 0xab, 0x13 } },
+ { .data = { 0xac, 0x0a } },
+ { .data = { 0xad, 0x74 } },
+ { .data = { 0xaf, 0x33 } },
+ { .data = { 0xb0, 0x03 } },
+ { .data = { 0xb1, 0x14 } },
+ { .data = { 0xb2, 0x42 } },
+ { .data = { 0xb3, 0x40 } },
+ { .data = { 0xb4, 0xa5 } },
+ { .data = { 0xb6, 0x44 } },
+ { .data = { 0xb7, 0x04 } },
+ { .data = { 0xb8, 0x14 } },
+ { .data = { 0xb9, 0x42 } },
+ { .data = { 0xba, 0x40 } },
+ { .data = { 0xbb, 0xa5 } },
+ { .data = { 0xbd, 0x44 } },
+ { .data = { 0xbe, 0x04 } },
+ { .data = { 0xbf, 0x00 } },
+ { .data = { 0xc0, 0x75 } },
+ { .data = { 0xc1, 0x6a } },
+ { .data = { 0xc2, 0xa5 } },
+ { .data = { 0xc4, 0x22 } },
+ { .data = { 0xc5, 0x02 } },
+ { .data = { 0xc6, 0x00 } },
+ { .data = { 0xc7, 0x95 } },
+ { .data = { 0xc8, 0x8a } },
+ { .data = { 0xc9, 0xa5 } },
+ { .data = { 0xcb, 0x22 } },
+ { .data = { 0xcc, 0x02 } },
+ { .data = { 0xcd, 0x00 } },
+ { .data = { 0xce, 0xb5 } },
+ { .data = { 0xcf, 0xaa } },
+ { .data = { 0xd0, 0xa5 } },
+ { .data = { 0xd2, 0x22 } },
+ { .data = { 0xd3, 0x02 } },
+ { .data = { 0xfb, 0x01 } },
+ { .data = { 0xff, 0x10 } },
+ { .data = { 0x26, 0x02 } },
+ { .data = { 0x35, 0x00 } },
+ { .data = { 0x51, 0xff } },
+ { .data = { 0x53, 0x24 } },
+ { .data = { 0x55, 0x00 } },
+ { .data = { 0xb0, 0x00 } },
+};
+
+static const struct drm_display_mode jdi_nt35596s_video_panel_mode = {
+ .clock = (1080 + 16 + 28 + 40) * (2160 + 7 + 4 + 24) * 60 / 1000,
+
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 16,
+ .hsync_end = 1080 + 16 + 28,
+ .htotal = 1080 + 16 + 28 + 40,
+
+ .vdisplay = 2160,
+ .vsync_start = 2160 + 7,
+ .vsync_end = 2160 + 7 + 4,
+ .vtotal = 2160 + 7 + 4 + 24,
+
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct nt35596s_panel_desc jdi_nt35596s_video_panel_desc = {
+ .display_mode = &jdi_nt35596s_video_panel_mode,
+
+ .width_mm = 68,
+ .height_mm = 136,
+
+ .mode_flags = MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_VIDEO_BURST,
+ .format = MIPI_DSI_FMT_RGB888,
+ .lanes = 4,
+ .on_cmds = jdi_nt35596s_video_on_cmds,
+ .num_on_cmds = ARRAY_SIZE(jdi_nt35596s_video_on_cmds),
+};
+
+static int nt35596s_panel_add(struct nt35596s_panel *pinfo)
+{
+ struct device *dev = &pinfo->link->dev;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++)
+ pinfo->supplies[i].supply = nt35596s_regulator_names[i];
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pinfo->supplies),
+ pinfo->supplies);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ for (i = 0; i < ARRAY_SIZE(pinfo->supplies); i++) {
+ ret = regulator_set_load(pinfo->supplies[i].consumer,
+ nt35596s_regulator_enable_loads[i]);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set regulator enable loads\n");
+ }
+
+ pinfo->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(pinfo->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(pinfo->reset_gpio),
+ "failed to get reset gpio from DT\n");
+
+ drm_panel_init(&pinfo->base, dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
+
+ drm_panel_add(&pinfo->base);
+
+ return 0;
+}
+
+static int nt35596s_panel_probe(struct mipi_dsi_device *dsi)
+{
+ struct nt35596s_panel *pinfo;
+ const struct nt35596s_panel_desc *desc;
+ int err;
+
+ pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
+ if (!pinfo)
+ return -ENOMEM;
+
+ desc = of_device_get_match_data(&dsi->dev);
+ dsi->mode_flags = desc->mode_flags;
+ dsi->format = desc->format;
+ dsi->lanes = desc->lanes;
+ pinfo->desc = desc;
+ pinfo->link = dsi;
+
+ mipi_dsi_set_drvdata(dsi, pinfo);
+
+ err = nt35596s_panel_add(pinfo);
+ if (err < 0)
+ return err;
+
+ err = mipi_dsi_attach(dsi);
+ if (err < 0) {
+ drm_panel_remove(&pinfo->base);
+ return err;
+ }
+
+ return 0;
+}
+
+static void nt35596s_panel_remove(struct mipi_dsi_device *dsi)
+{
+ struct nt35596s_panel *pinfo = mipi_dsi_get_drvdata(dsi);
+ int err;
+
+ err = drm_panel_unprepare(&pinfo->base);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
+
+ err = drm_panel_disable(&pinfo->base);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
+
+ err = mipi_dsi_detach(dsi);
+ if (err < 0)
+ dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
+
+ drm_panel_remove(&pinfo->base);
+}
+
+static void nt35596s_panel_shutdown(struct mipi_dsi_device *dsi)
+{
+ struct nt35596s_panel *pinfo = mipi_dsi_get_drvdata(dsi);
+
+ drm_panel_disable(&pinfo->base);
+ drm_panel_unprepare(&pinfo->base);
+}
+
+static const struct of_device_id jdi_fhd_video_of_match[] = {
+ { .compatible = "jdi,fhd-nt35596s", .data = &jdi_nt35596s_video_panel_desc },
+ { },
+};
+MODULE_DEVICE_TABLE(of, jdi_fhd_video_of_match);
+
+static struct mipi_dsi_driver nt35596s_panel_driver = {
+ .driver = {
+ .name = "panel-jdi-nt35596s",
+ .of_match_table = jdi_fhd_video_of_match,
+ },
+ .probe = nt35596s_panel_probe,
+ .remove = nt35596s_panel_remove,
+ .shutdown = nt35596s_panel_shutdown,
+};
+module_mipi_dsi_driver(nt35596s_panel_driver);
+
+MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
+MODULE_DESCRIPTION("NOVATEK NT35596s based MIPI-DSI LCD panel driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
index 33fb3d715e5..6e764cfbeb5 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c
@@ -114,7 +114,7 @@ static int nt36672a_panel_power_off(struct drm_panel *panel)
return ret;
}
-static int nt36672a_panel_unprepare(struct drm_panel *panel)
+static int nt36672a_panel_disable(struct drm_panel *panel)
{
struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
int ret;
@@ -143,6 +143,14 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel)
/* 0x3C = 60ms delay */
msleep(60);
+ return ret;
+}
+
+static int nt36672a_panel_unprepare(struct drm_panel *panel)
+{
+ struct nt36672a_panel *pinfo = to_nt36672a_panel(panel);
+ int ret;
+
ret = nt36672a_panel_power_off(panel);
if (ret < 0)
dev_err(panel->dev, "power_off failed ret = %d\n", ret);
@@ -254,6 +262,7 @@ static int nt36672a_panel_get_modes(struct drm_panel *panel,
}
static const struct drm_panel_funcs panel_funcs = {
+ .disable = nt36672a_panel_disable,
.unprepare = nt36672a_panel_unprepare,
.prepare = nt36672a_panel_prepare,
.get_modes = nt36672a_panel_get_modes,
@@ -626,6 +635,7 @@ static int nt36672a_panel_add(struct nt36672a_panel *pinfo)
"failed to get reset gpio from DT\n");
drm_panel_init(&pinfo->base, dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
+ pinfo->base.prepare_prev_first = true;
ret = drm_panel_of_backlight(&pinfo->base);
if (ret)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c b/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c
new file mode 100644
index 00000000000..32714e276b6
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e3fc2x01.c
@@ -0,0 +1,385 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2022 Nia Espera <a5b6@riseup.net>
+ * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+ * Copyright (c) 2022, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/swab.h>
+#include <linux/backlight.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct samsung_s6e3fc2x01 {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+ const struct drm_display_mode *mode;
+ bool prepared;
+};
+
+static inline
+struct samsung_s6e3fc2x01 *to_samsung_s6e3fc2x01(struct drm_panel *panel)
+{
+ return container_of(panel, struct samsung_s6e3fc2x01, panel);
+}
+
+static void samsung_s6e3fc2x01_reset(struct samsung_s6e3fc2x01 *ctx)
+{
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(2000, 3000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ usleep_range(10000, 11000);
+}
+
+static int samsung_s6e3fc2x01_on(struct samsung_s6e3fc2x01 *ctx)
+{
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &dsi->dev;
+ int ret;
+
+ dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xcd, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ usleep_range(15000, 16000);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set tear on: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x17, 0x41, 0x92, 0x0e, 0x10, 0x82, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_column_address(dsi, 0x0000, 0x0437);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set column address: %d\n", ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_page_address(dsi, 0x0000, 0x0923);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set page address: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x09);
+ mipi_dsi_dcs_write_seq(dsi, 0xe8, 0x10, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x12);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xe3, 0x88);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xed, 0x67);
+ mipi_dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x20);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+ usleep_range(1000, 2000);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x00, 0xc1);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display on: %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(10000, 11000);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+ mipi_dsi_dcs_write_seq(dsi, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_disable(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+ struct mipi_dsi_device *dsi = ctx->dsi;
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0xa5, 0xa5);
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set display off: %d\n", ret);
+ return ret;
+ }
+ usleep_range(10000, 11000);
+
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ usleep_range(16000, 17000);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x50);
+ mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x82);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ usleep_range(16000, 17000);
+ msleep(40);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ mipi_dsi_dcs_write_seq(dsi, 0x9f, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+ msleep(160);
+
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_prepare(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+ struct device *dev = &ctx->dsi->dev;
+ int ret;
+
+ if (ctx->prepared)
+ return 0;
+
+ ret = regulator_enable(ctx->supply);
+ if (ret < 0) {
+ dev_err(dev, "Failed to enable regulator: %d\n", ret);
+ return ret;
+ }
+
+ samsung_s6e3fc2x01_reset(ctx);
+
+ ret = samsung_s6e3fc2x01_on(ctx);
+ if (ret < 0) {
+ dev_err(dev, "Failed to initialize panel: %d\n", ret);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_disable(ctx->supply);
+ return ret;
+ }
+
+ ctx->prepared = true;
+ return 0;
+}
+
+static int samsung_s6e3fc2x01_unprepare(struct drm_panel *panel)
+{
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+
+ if (!ctx->prepared)
+ return 0;
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_disable(ctx->supply);
+
+ ctx->prepared = false;
+ return 0;
+}
+
+static const struct drm_display_mode samsung_s6e3fc2x01_mode = {
+ .clock = (1080 + 72 + 16 + 36) * (2340 + 32 + 4 + 18) * 60 / 1000,
+ .hdisplay = 1080,
+ .hsync_start = 1080 + 72,
+ .hsync_end = 1080 + 72 + 16,
+ .htotal = 1080 + 72 + 16 + 36,
+ .vdisplay = 2340,
+ .vsync_start = 2340 + 32,
+ .vsync_end = 2340 + 32 + 4,
+ .vtotal = 2340 + 32 + 4 + 18,
+ .width_mm = 68,
+ .height_mm = 145,
+};
+
+static int samsung_s6e3fc2x01_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode;
+ struct samsung_s6e3fc2x01 *ctx = to_samsung_s6e3fc2x01(panel);
+
+ mode = drm_mode_duplicate(connector->dev, ctx->mode);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs samsung_s6e3fc2x01_panel_funcs = {
+ .prepare = samsung_s6e3fc2x01_prepare,
+ .disable = samsung_s6e3fc2x01_disable,
+ .unprepare = samsung_s6e3fc2x01_unprepare,
+ .get_modes = samsung_s6e3fc2x01_get_modes,
+};
+
+static int s6e3fc2x01_panel_bl_update_status(struct backlight_device *bl)
+{
+ struct mipi_dsi_device *dsi = bl_get_data(bl);
+ int err;
+ u16 brightness;
+
+ brightness = (u16)backlight_get_brightness(bl);
+ // This panel needs the high and low bytes swapped for the brightness value
+ brightness = __swab16(brightness);
+
+ err = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static const struct backlight_ops s6e3fc2x01_panel_bl_ops = {
+ .update_status = s6e3fc2x01_panel_bl_update_status,
+};
+
+static struct backlight_device *
+s6e3fc2x01_create_backlight(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct backlight_properties props = {
+ .type = BACKLIGHT_PLATFORM,
+ .brightness = 1023,
+ .max_brightness = 1023,
+ };
+
+ return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+ &s6e3fc2x01_panel_bl_ops, &props);
+}
+
+static int samsung_s6e3fc2x01_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct samsung_s6e3fc2x01 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->mode = of_device_get_match_data(dev);
+
+ if (!ctx->mode) {
+ dev_err(dev, "Missing device mode\n");
+ return -ENODEV;
+ }
+
+ ctx->supply = devm_regulator_get(dev, "vddio");
+ if (IS_ERR(ctx->supply))
+ return dev_err_probe(dev, PTR_ERR(ctx->supply),
+ "Failed to get vddio regulator\n");
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset-gpios\n");
+
+ ctx->dsi = dsi;
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_NO_EOT_PACKET |
+ MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+ drm_panel_init(&ctx->panel, dev, &samsung_s6e3fc2x01_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
+
+ ctx->panel.backlight = s6e3fc2x01_create_backlight(dsi);
+ if (IS_ERR(ctx->panel.backlight))
+ return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+ "Failed to create backlight\n");
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void samsung_s6e3fc2x01_remove(struct mipi_dsi_device *dsi)
+{
+ struct samsung_s6e3fc2x01 *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+
+ return;
+}
+
+static const struct of_device_id samsung_s6e3fc2x01_of_match[] = {
+ {
+ .compatible = "samsung,s6e3fc2x01",
+ .data = &samsung_s6e3fc2x01_mode,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, samsung_s6e3fc2x01_of_match);
+
+static struct mipi_dsi_driver samsung_s6e3fc2x01_driver = {
+ .probe = samsung_s6e3fc2x01_probe,
+ .remove = samsung_s6e3fc2x01_remove,
+ .driver = {
+ .name = "panel-samsung-s6e3fc2x01",
+ .of_match_table = samsung_s6e3fc2x01_of_match,
+ },
+};
+module_mipi_dsi_driver(samsung_s6e3fc2x01_driver);
+
+MODULE_AUTHOR("Nia Espera <a5b6@riseup.net>");
+MODULE_DESCRIPTION("DRM driver for OnePlus 6T Panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-samsung-sofef00.c b/drivers/gpu/drm/panel/panel-samsung-sofef00.c
index 04ce925b3d9..d7df52a25fb 100644
--- a/drivers/gpu/drm/panel/panel-samsung-sofef00.c
+++ b/drivers/gpu/drm/panel/panel-samsung-sofef00.c
@@ -81,24 +81,24 @@ static int sofef00_panel_on(struct sofef00_panel *ctx)
return 0;
}
-static int sofef00_panel_off(struct sofef00_panel *ctx)
+static int sofef00_panel_disable(struct drm_panel *panel)
{
+ struct sofef00_panel *ctx = to_sofef00_panel(panel);
struct mipi_dsi_device *dsi = ctx->dsi;
- struct device *dev = &dsi->dev;
int ret;
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_set_display_off(dsi);
if (ret < 0) {
- dev_err(dev, "Failed to set display off: %d\n", ret);
+ dev_err(&dsi->dev, "Failed to set display off: %d\n", ret);
return ret;
}
msleep(40);
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
if (ret < 0) {
- dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+ dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
return ret;
}
msleep(160);
@@ -133,12 +133,6 @@ static int sofef00_panel_prepare(struct drm_panel *panel)
static int sofef00_panel_unprepare(struct drm_panel *panel)
{
struct sofef00_panel *ctx = to_sofef00_panel(panel);
- struct device *dev = &ctx->dsi->dev;
- int ret;
-
- ret = sofef00_panel_off(ctx);
- if (ret < 0)
- dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
regulator_disable(ctx->supply);
@@ -159,20 +153,6 @@ static const struct drm_display_mode enchilada_panel_mode = {
.height_mm = 145,
};
-static const struct drm_display_mode fajita_panel_mode = {
- .clock = (1080 + 72 + 16 + 36) * (2340 + 32 + 4 + 18) * 60 / 1000,
- .hdisplay = 1080,
- .hsync_start = 1080 + 72,
- .hsync_end = 1080 + 72 + 16,
- .htotal = 1080 + 72 + 16 + 36,
- .vdisplay = 2340,
- .vsync_start = 2340 + 32,
- .vsync_end = 2340 + 32 + 4,
- .vtotal = 2340 + 32 + 4 + 18,
- .width_mm = 68,
- .height_mm = 145,
-};
-
static int sofef00_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
{
struct drm_display_mode *mode;
@@ -194,6 +174,7 @@ static int sofef00_panel_get_modes(struct drm_panel *panel, struct drm_connector
static const struct drm_panel_funcs sofef00_panel_panel_funcs = {
.prepare = sofef00_panel_prepare,
+ .disable = sofef00_panel_disable,
.unprepare = sofef00_panel_unprepare,
.get_modes = sofef00_panel_get_modes,
};
@@ -264,6 +245,7 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi)
drm_panel_init(&ctx->panel, dev, &sofef00_panel_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
+ ctx->panel.prepare_prev_first = true;
ctx->panel.backlight = sofef00_create_backlight(dsi);
if (IS_ERR(ctx->panel.backlight))
@@ -299,10 +281,6 @@ static const struct of_device_id sofef00_panel_of_match[] = {
.compatible = "samsung,sofef00",
.data = &enchilada_panel_mode,
},
- { // OnePlus 6T / fajita
- .compatible = "samsung,s6e3fc2x01",
- .data = &fajita_panel_mode,
- },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sofef00_panel_of_match);
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 6cd32b90908..9367a4572dc 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2379,13 +2379,13 @@ static const struct panel_desc innolux_g070y2_t02 = {
static const struct display_timing innolux_g101ice_l01_timing = {
.pixelclock = { 60400000, 71100000, 74700000 },
.hactive = { 1280, 1280, 1280 },
- .hfront_porch = { 41, 80, 100 },
- .hback_porch = { 40, 79, 99 },
- .hsync_len = { 1, 1, 1 },
+ .hfront_porch = { 30, 60, 70 },
+ .hback_porch = { 30, 60, 70 },
+ .hsync_len = { 22, 40, 60 },
.vactive = { 800, 800, 800 },
- .vfront_porch = { 5, 11, 14 },
- .vback_porch = { 4, 11, 14 },
- .vsync_len = { 1, 1, 1 },
+ .vfront_porch = { 3, 8, 14 },
+ .vback_porch = { 3, 8, 14 },
+ .vsync_len = { 4, 7, 12 },
.flags = DISPLAY_FLAGS_DE_HIGH,
};
@@ -2402,6 +2402,7 @@ static const struct panel_desc innolux_g101ice_l01 = {
.disable = 200,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
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/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 066299894d0..a13473b2d54 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -247,14 +247,22 @@ static inline void vop_cfg_done(struct vop *vop)
VOP_REG_SET(vop, common, cfg_done, 1);
}
-static bool has_rb_swapped(uint32_t format)
+static bool has_rb_swapped(uint32_t version, uint32_t format)
{
switch (format) {
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888:
- case DRM_FORMAT_BGR888:
case DRM_FORMAT_BGR565:
return true;
+ /*
+ * full framework (IP version 3.x) only need rb swapped for RGB888 and
+ * little framework (IP version 2.x) only need rb swapped for BGR888,
+ * check for 3.x to also only rb swap BGR888 for unknown vop version
+ */
+ case DRM_FORMAT_RGB888:
+ return VOP_MAJOR(version) == 3;
+ case DRM_FORMAT_BGR888:
+ return VOP_MAJOR(version) != 3;
default:
return false;
}
@@ -1030,7 +1038,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
VOP_WIN_SET(vop, win, dsp_info, dsp_info);
VOP_WIN_SET(vop, win, dsp_st, dsp_st);
- rb_swap = has_rb_swapped(fb->format->format);
+ rb_swap = has_rb_swapped(vop->data->version, fb->format->format);
VOP_WIN_SET(vop, win, rb_swap, rb_swap);
/*
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 3ca45975c68..d9e9829b220 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -345,6 +345,8 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
{ "AONE" },
{ "GANSS" },
{ "Hailuck" },
+ { "Jamesdonkey" },
+ { "A3R" },
};
static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index fd61dba8823..78cdfb8b9a7 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -381,7 +381,7 @@ static int asus_raw_event(struct hid_device *hdev,
return 0;
}
-static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size)
+static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
{
unsigned char *dmabuf;
int ret;
@@ -404,7 +404,7 @@ static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size
static int asus_kbd_init(struct hid_device *hdev)
{
- u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
+ const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
int ret;
@@ -418,7 +418,7 @@ static int asus_kbd_init(struct hid_device *hdev)
static int asus_kbd_get_functions(struct hid_device *hdev,
unsigned char *kbd_func)
{
- u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
+ const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
u8 *readbuf;
int ret;
@@ -449,7 +449,7 @@ static int asus_kbd_get_functions(struct hid_device *hdev,
static int rog_nkey_led_init(struct hid_device *hdev)
{
- u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
+ const u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20,
0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1,
@@ -1000,6 +1000,24 @@ static int asus_start_multitouch(struct hid_device *hdev)
return 0;
}
+static int __maybe_unused asus_resume(struct hid_device *hdev) {
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ int ret = 0;
+
+ if (drvdata->kbd_backlight) {
+ const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4,
+ drvdata->kbd_backlight->cdev.brightness };
+ ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
+ if (ret < 0) {
+ hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret);
+ goto asus_resume_err;
+ }
+ }
+
+asus_resume_err:
+ return ret;
+}
+
static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
{
struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
@@ -1294,6 +1312,7 @@ static struct hid_driver asus_driver = {
.input_configured = asus_input_configured,
#ifdef CONFIG_PM
.reset_resume = asus_reset_resume,
+ .resume = asus_resume,
#endif
.event = asus_event,
.raw_event = asus_raw_event
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8992e3c1e76..e0181218ad8 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -702,15 +702,22 @@ static void hid_close_report(struct hid_device *device)
* Free a device structure, all reports, and all fields.
*/
-static void hid_device_release(struct device *dev)
+void hiddev_free(struct kref *ref)
{
- struct hid_device *hid = to_hid_device(dev);
+ struct hid_device *hid = container_of(ref, struct hid_device, ref);
hid_close_report(hid);
kfree(hid->dev_rdesc);
kfree(hid);
}
+static void hid_device_release(struct device *dev)
+{
+ struct hid_device *hid = to_hid_device(dev);
+
+ kref_put(&hid->ref, hiddev_free);
+}
+
/*
* Fetch a report description item from the data stream. We support long
* items, though they are not used yet.
@@ -2846,6 +2853,7 @@ struct hid_device *hid_allocate_device(void)
spin_lock_init(&hdev->debug_list_lock);
sema_init(&hdev->driver_input_lock, 1);
mutex_init(&hdev->ll_open_lock);
+ kref_init(&hdev->ref);
hid_bpf_device_init(hdev);
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index e7ef1ea107c..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",
@@ -1135,6 +1136,7 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
goto out;
}
list->hdev = (struct hid_device *) inode->i_private;
+ kref_get(&list->hdev->ref);
file->private_data = list;
mutex_init(&list->read_mutex);
@@ -1227,6 +1229,8 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
list_del(&list->node);
spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
kfifo_free(&list->hid_debug_fifo);
+
+ kref_put(&list->hdev->ref, hiddev_free);
kfree(list);
return 0;
diff --git a/drivers/hid/hid-glorious.c b/drivers/hid/hid-glorious.c
index 558eb08c19e..281b3a7187c 100644
--- a/drivers/hid/hid-glorious.c
+++ b/drivers/hid/hid-glorious.c
@@ -21,6 +21,10 @@ MODULE_DESCRIPTION("HID driver for Glorious PC Gaming Race mice");
* Glorious Model O and O- specify the const flag in the consumer input
* report descriptor, which leads to inputs being ignored. Fix this
* by patching the descriptor.
+ *
+ * Glorious Model I incorrectly specifes the Usage Minimum for its
+ * keyboard HID report, causing keycodes to be misinterpreted.
+ * Fix this by setting Usage Minimum to 0 in that report.
*/
static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
@@ -32,6 +36,10 @@ static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc,
rdesc[85] = rdesc[113] = rdesc[141] = \
HID_MAIN_ITEM_VARIABLE | HID_MAIN_ITEM_RELATIVE;
}
+ if (*rsize == 156 && rdesc[41] == 1) {
+ hid_info(hdev, "patching Glorious Model I keyboard report descriptor\n");
+ rdesc[41] = 0;
+ }
return rdesc;
}
@@ -44,6 +52,8 @@ static void glorious_update_name(struct hid_device *hdev)
model = "Model O"; break;
case USB_DEVICE_ID_GLORIOUS_MODEL_D:
model = "Model D"; break;
+ case USB_DEVICE_ID_GLORIOUS_MODEL_I:
+ model = "Model I"; break;
}
snprintf(hdev->name, sizeof(hdev->name), "%s %s", "Glorious", model);
@@ -66,10 +76,12 @@ static int glorious_probe(struct hid_device *hdev,
}
static const struct hid_device_id glorious_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS,
+ { HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH,
USB_DEVICE_ID_GLORIOUS_MODEL_O) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS,
+ { HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH,
USB_DEVICE_ID_GLORIOUS_MODEL_D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LAVIEW,
+ USB_DEVICE_ID_GLORIOUS_MODEL_I) },
{ }
};
MODULE_DEVICE_TABLE(hid, glorious_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f7973ccd84a..c6e4e0d1f21 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -511,10 +511,6 @@
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
-#define USB_VENDOR_ID_GLORIOUS 0x258a
-#define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033
-#define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036
-
#define I2C_VENDOR_ID_GOODIX 0x27c6
#define I2C_DEVICE_ID_GOODIX_01F0 0x01f0
@@ -745,6 +741,9 @@
#define USB_VENDOR_ID_LABTEC 0x1020
#define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
+#define USB_VENDOR_ID_LAVIEW 0x22D4
+#define USB_DEVICE_ID_GLORIOUS_MODEL_I 0x1503
+
#define USB_VENDOR_ID_LCPOWER 0x1241
#define USB_DEVICE_ID_LCPOWER_LC1000 0xf767
@@ -869,7 +868,6 @@
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f
-#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2 0xc547
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a
#define USB_DEVICE_ID_SPACETRAVELLER 0xc623
#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626
@@ -1160,6 +1158,10 @@
#define USB_VENDOR_ID_SIGMATEL 0x066F
#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780
+#define USB_VENDOR_ID_SINOWEALTH 0x258a
+#define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033
+#define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036
+
#define USB_VENDOR_ID_SIS_TOUCH 0x0457
#define USB_DEVICE_ID_SIS9200_TOUCH 0x9200
#define USB_DEVICE_ID_SIS817_TOUCH 0x0817
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 8afe3be683b..e6a8b6d8eab 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -1695,12 +1695,11 @@ static int logi_dj_raw_event(struct hid_device *hdev,
}
/*
* Mouse-only receivers send unnumbered mouse data. The 27 MHz
- * receiver uses 6 byte packets, the nano receiver 8 bytes,
- * the lightspeed receiver (Pro X Superlight) 13 bytes.
+ * receiver uses 6 byte packets, the nano receiver 8 bytes.
*/
if (djrcv_dev->unnumbered_application == HID_GD_MOUSE &&
- size <= 13){
- u8 mouse_report[14];
+ size <= 8) {
+ u8 mouse_report[9];
/* Prepend report id */
mouse_report[0] = REPORT_TYPE_MOUSE;
@@ -1984,10 +1983,6 @@ static const struct hid_device_id logi_dj_receivers[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1),
.driver_data = recvr_type_gaming_hidpp},
- { /* Logitech lightspeed receiver (0xc547) */
- HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
- USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2),
- .driver_data = recvr_type_gaming_hidpp},
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index 72883e0ce75..aef0785c91c 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -1142,6 +1142,8 @@ static int mcp2221_probe(struct hid_device *hdev,
if (ret)
return ret;
+ hid_device_io_start(hdev);
+
/* Set I2C bus clock diviser */
if (i2c_clk_freq > 400)
i2c_clk_freq = 400;
@@ -1157,12 +1159,12 @@ static int mcp2221_probe(struct hid_device *hdev,
snprintf(mcp->adapter.name, sizeof(mcp->adapter.name),
"MCP2221 usb-i2c bridge");
+ i2c_set_adapdata(&mcp->adapter, mcp);
ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter);
if (ret) {
hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
return ret;
}
- i2c_set_adapdata(&mcp->adapter, mcp);
#if IS_REACHABLE(CONFIG_GPIOLIB)
/* Setup GPIO chip */
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index e098cc7b394..fd5b0637dad 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -2046,6 +2046,11 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
+ /* HONOR GLO-GXXX panel */
+ { .driver_data = MT_CLS_VTL,
+ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+ 0x347d, 0x7853) },
+
/* Ilitek dual touch panel */
{ .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 5a48fcaa32f..ea472923fab 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -33,6 +33,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD },
{ HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET },
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 258d5fe3d39..2469d198485 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 d7603c50f86..4aee30d2dcd 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -250,6 +250,20 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
}
}
+ /*
+ * Some aftermarket ICs put garbage into the product id field unless
+ * we read directly from the product id register.
+ */
+ if (props->product_id[0] < 0x20) {
+ ret = rmi_read_block(rmi_dev, query_base_addr + 11,
+ props->product_id, RMI_PRODUCT_ID_LENGTH);
+ if (ret) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read product id: %d\n", ret);
+ return ret;
+ }
+ }
+
return 0;
}
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 7e97944f761..719ee3b4255 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -195,6 +195,41 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
}
+static void rmi_f12_set_hardcoded_desc(struct rmi_function *fn, struct f12_data *f12)
+{
+ struct rmi_2d_sensor *sensor = &f12->sensor;
+ struct rmi_register_desc_item *reg_desc;
+
+ /* We have no f12->data_reg_desc, so the pkt_size is 0, override it with
+ * a somewhat sensible default (this corresponds to 10 fingers).
+ */
+ sensor->pkt_size = 88;
+
+ /*
+ * There are no register descriptors to get these values from.
+ * We set them to high values to either be overwritten by the clip
+ * properties from devicetree, or to just not get in the way.
+ */
+ sensor->max_x = 65535;
+ sensor->max_y = 65535;
+
+ /*
+ * Create the Data1 register descriptor so that touch events
+ * can work properly.
+ */
+ reg_desc = devm_kcalloc(&fn->dev, 1,
+ sizeof(struct rmi_register_desc_item), GFP_KERNEL);
+ reg_desc->reg = 1;
+ reg_desc->reg_size = 80;
+ reg_desc->num_subpackets = 10;
+
+ f12->data1 = reg_desc;
+ f12->data1_offset = 0;
+ sensor->nbr_fingers = reg_desc->num_subpackets;
+ sensor->report_abs = 1;
+ sensor->attn_size += reg_desc->reg_size;
+}
+
static irqreturn_t rmi_f12_attention(int irq, void *ctx)
{
int retval;
@@ -315,6 +350,40 @@ static int rmi_f12_config(struct rmi_function *fn)
return 0;
}
+static int rmi_f12_sensor_init(struct rmi_function *fn, struct f12_data *f12)
+{
+ struct rmi_2d_sensor *sensor = &f12->sensor;
+
+ sensor->fn = fn;
+ f12->data_addr = fn->fd.data_base_addr;
+
+ /* On quirky devices that don't have a data_reg_desc we hardcode the packet
+ * in rmi_f12_set_hardcoded_desc(). Make sure not to set it to 0 here.
+ */
+ if (!sensor->pkt_size)
+ sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+
+ sensor->axis_align =
+ f12->sensor_pdata.axis_align;
+
+ sensor->x_mm = f12->sensor_pdata.x_mm;
+ sensor->y_mm = f12->sensor_pdata.y_mm;
+ sensor->dribble = f12->sensor_pdata.dribble;
+
+ if (sensor->sensor_type == rmi_sensor_default)
+ sensor->sensor_type =
+ f12->sensor_pdata.sensor_type;
+
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
+ sensor->pkt_size);
+
+ sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
+ if (!sensor->data_pkt)
+ return -ENOMEM;
+
+ return 0;
+}
+
static int rmi_f12_probe(struct rmi_function *fn)
{
struct f12_data *f12;
@@ -328,6 +397,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
u16 data_offset = 0;
int mask_size;
+ bool hardcoded_desc_quirk = false;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
@@ -342,9 +412,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
++query_addr;
if (!(buf & BIT(0))) {
- dev_err(&fn->dev,
- "Behavior of F12 without register descriptors is undefined.\n");
- return -ENODEV;
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "No register descriptors defined for F12, using fallback\n");
+ hardcoded_desc_quirk = true;
}
f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
@@ -352,6 +422,8 @@ static int rmi_f12_probe(struct rmi_function *fn)
if (!f12)
return -ENOMEM;
+ dev_set_drvdata(&fn->dev, f12);
+
f12->abs_mask = (unsigned long *)((char *)f12
+ sizeof(struct f12_data));
f12->rel_mask = (unsigned long *)((char *)f12
@@ -370,6 +442,18 @@ static int rmi_f12_probe(struct rmi_function *fn)
f12->sensor_pdata = pdata->sensor_pdata;
}
+ sensor = &f12->sensor;
+
+ if (hardcoded_desc_quirk) {
+ rmi_f12_set_hardcoded_desc(fn, f12);
+
+ ret = rmi_f12_sensor_init(fn, f12);
+ if (ret)
+ return ret;
+
+ goto skip_register_desc;
+ }
+
ret = rmi_read_register_desc(rmi_dev, query_addr,
&f12->query_reg_desc);
if (ret) {
@@ -400,29 +484,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
query_addr += 3;
- sensor = &f12->sensor;
- sensor->fn = fn;
- f12->data_addr = fn->fd.data_base_addr;
- sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
-
- sensor->axis_align =
- f12->sensor_pdata.axis_align;
-
- sensor->x_mm = f12->sensor_pdata.x_mm;
- sensor->y_mm = f12->sensor_pdata.y_mm;
- sensor->dribble = f12->sensor_pdata.dribble;
-
- if (sensor->sensor_type == rmi_sensor_default)
- sensor->sensor_type =
- f12->sensor_pdata.sensor_type;
-
- rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
- sensor->pkt_size);
- sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
- if (!sensor->data_pkt)
- return -ENOMEM;
-
- dev_set_drvdata(&fn->dev, f12);
+ ret = rmi_f12_sensor_init(fn, f12);
+ if (ret)
+ return ret;
ret = rmi_f12_read_sensor_tuning(f12);
if (ret)
@@ -520,6 +584,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
data_offset += item->reg_size;
}
+skip_register_desc:
/* allocate the in-kernel tracking buffers */
sensor->tracking_pos = devm_kcalloc(&fn->dev,
sensor->nbr_fingers, sizeof(struct input_mt_pos),
diff --git a/drivers/input/rmi4/rmi_f55.c b/drivers/input/rmi4/rmi_f55.c
index 488adaca4dd..ad2ef14ae9f 100644
--- a/drivers/input/rmi4/rmi_f55.c
+++ b/drivers/input/rmi4/rmi_f55.c
@@ -52,6 +52,11 @@ static int rmi_f55_detect(struct rmi_function *fn)
f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
+ if (!f55->num_rx_electrodes || !f55->num_tx_electrodes) {
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "F55 query returned no electrodes, giving up\n");
+ return 0;
+ }
f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 3e102bcc4a1..7955f69823d 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/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index 62b516d38d0..d2a54c5ecd0 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -191,6 +191,15 @@ config INTERCONNECT_QCOM_SDX75
This is a driver for the Qualcomm Network-on-Chip on sdx75-based
platforms.
+config INTERCONNECT_QCOM_SM6115
+ tristate "Qualcomm SM6115 interconnect driver"
+ depends on INTERCONNECT_QCOM
+ depends on QCOM_SMD_RPM
+ select INTERCONNECT_QCOM_SMD_RPM
+ help
+ This is a driver for the Qualcomm Network-on-Chip on sm6115-based
+ platforms.
+
config INTERCONNECT_QCOM_SM6350
tristate "Qualcomm SM6350 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index c5320e29396..7564042a30d 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -24,6 +24,7 @@ qnoc-sdm845-objs := sdm845.o
qnoc-sdx55-objs := sdx55.o
qnoc-sdx65-objs := sdx65.o
qnoc-sdx75-objs := sdx75.o
+qnoc-sm6115-objs := sm6115.o
qnoc-sm6350-objs := sm6350.o
qnoc-sm8150-objs := sm8150.o
qnoc-sm8250-objs := sm8250.o
@@ -53,6 +54,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDX55) += qnoc-sdx55.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDX65) += qnoc-sdx65.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDX75) += qnoc-sdx75.o
+obj-$(CONFIG_INTERCONNECT_QCOM_SM6115) += qnoc-sm6115.o
obj-$(CONFIG_INTERCONNECT_QCOM_SM6350) += qnoc-sm6350.o
obj-$(CONFIG_INTERCONNECT_QCOM_SM8150) += qnoc-sm8150.o
obj-$(CONFIG_INTERCONNECT_QCOM_SM8250) += qnoc-sm8250.o
diff --git a/drivers/interconnect/qcom/sm6115.c b/drivers/interconnect/qcom/sm6115.c
new file mode 100644
index 00000000000..da8a85456f5
--- /dev/null
+++ b/drivers/interconnect/qcom/sm6115.c
@@ -0,0 +1,1424 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <dt-bindings/interconnect/qcom,sm6115.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interconnect-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "icc-rpm.h"
+
+static const char * const snoc_intf_clocks[] = {
+ "cpu_axi",
+ "ufs_axi",
+ "usb_axi",
+ "ipa", /* qxm_ipa */
+};
+
+static const char * const cnoc_intf_clocks[] = {
+ "usb_axi",
+};
+
+enum {
+ SM6115_MASTER_AMPSS_M0,
+ SM6115_MASTER_ANOC_SNOC,
+ SM6115_MASTER_BIMC_SNOC,
+ SM6115_MASTER_CAMNOC_HF,
+ SM6115_MASTER_CAMNOC_SF,
+ SM6115_MASTER_CRYPTO_CORE0,
+ SM6115_MASTER_GRAPHICS_3D,
+ SM6115_MASTER_IPA,
+ SM6115_MASTER_MDP_PORT0,
+ SM6115_MASTER_PIMEM,
+ SM6115_MASTER_QDSS_BAM,
+ SM6115_MASTER_QDSS_DAP,
+ SM6115_MASTER_QDSS_ETR,
+ SM6115_MASTER_QPIC,
+ SM6115_MASTER_QUP_0,
+ SM6115_MASTER_QUP_CORE_0,
+ SM6115_MASTER_SDCC_1,
+ SM6115_MASTER_SDCC_2,
+ SM6115_MASTER_SNOC_BIMC_NRT,
+ SM6115_MASTER_SNOC_BIMC_RT,
+ SM6115_MASTER_SNOC_BIMC,
+ SM6115_MASTER_SNOC_CFG,
+ SM6115_MASTER_SNOC_CNOC,
+ SM6115_MASTER_TCU_0,
+ SM6115_MASTER_TIC,
+ SM6115_MASTER_USB3,
+ SM6115_MASTER_VIDEO_P0,
+ SM6115_MASTER_VIDEO_PROC,
+
+ SM6115_SLAVE_AHB2PHY_USB,
+ SM6115_SLAVE_ANOC_SNOC,
+ SM6115_SLAVE_APPSS,
+ SM6115_SLAVE_APSS_THROTTLE_CFG,
+ SM6115_SLAVE_BIMC_CFG,
+ SM6115_SLAVE_BIMC_SNOC,
+ SM6115_SLAVE_BOOT_ROM,
+ SM6115_SLAVE_CAMERA_CFG,
+ SM6115_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ SM6115_SLAVE_CAMERA_RT_THROTTLE_CFG,
+ SM6115_SLAVE_CLK_CTL,
+ SM6115_SLAVE_CNOC_MSS,
+ SM6115_SLAVE_CRYPTO_0_CFG,
+ SM6115_SLAVE_DCC_CFG,
+ SM6115_SLAVE_DDR_PHY_CFG,
+ SM6115_SLAVE_DDR_SS_CFG,
+ SM6115_SLAVE_DISPLAY_CFG,
+ SM6115_SLAVE_DISPLAY_THROTTLE_CFG,
+ SM6115_SLAVE_EBI_CH0,
+ SM6115_SLAVE_GPU_CFG,
+ SM6115_SLAVE_GPU_THROTTLE_CFG,
+ SM6115_SLAVE_HWKM_CORE,
+ SM6115_SLAVE_IMEM_CFG,
+ SM6115_SLAVE_IPA_CFG,
+ SM6115_SLAVE_LPASS,
+ SM6115_SLAVE_MAPSS,
+ SM6115_SLAVE_MDSP_MPU_CFG,
+ SM6115_SLAVE_MESSAGE_RAM,
+ SM6115_SLAVE_OCIMEM,
+ SM6115_SLAVE_PDM,
+ SM6115_SLAVE_PIMEM_CFG,
+ SM6115_SLAVE_PIMEM,
+ SM6115_SLAVE_PKA_CORE,
+ SM6115_SLAVE_PMIC_ARB,
+ SM6115_SLAVE_QDSS_CFG,
+ SM6115_SLAVE_QDSS_STM,
+ SM6115_SLAVE_QM_CFG,
+ SM6115_SLAVE_QM_MPU_CFG,
+ SM6115_SLAVE_QPIC,
+ SM6115_SLAVE_QUP_0,
+ SM6115_SLAVE_QUP_CORE_0,
+ SM6115_SLAVE_RBCPR_CX_CFG,
+ SM6115_SLAVE_RBCPR_MX_CFG,
+ SM6115_SLAVE_RPM,
+ SM6115_SLAVE_SDCC_1,
+ SM6115_SLAVE_SDCC_2,
+ SM6115_SLAVE_SECURITY,
+ SM6115_SLAVE_SERVICE_CNOC,
+ SM6115_SLAVE_SERVICE_SNOC,
+ SM6115_SLAVE_SNOC_BIMC_NRT,
+ SM6115_SLAVE_SNOC_BIMC_RT,
+ SM6115_SLAVE_SNOC_BIMC,
+ SM6115_SLAVE_SNOC_CFG,
+ SM6115_SLAVE_SNOC_CNOC,
+ SM6115_SLAVE_TCSR,
+ SM6115_SLAVE_TCU,
+ SM6115_SLAVE_TLMM,
+ SM6115_SLAVE_USB3,
+ SM6115_SLAVE_VENUS_CFG,
+ SM6115_SLAVE_VENUS_THROTTLE_CFG,
+ SM6115_SLAVE_VSENSE_CTRL_CFG,
+};
+
+static const u16 slv_ebi_slv_bimc_snoc_links[] = {
+ SM6115_SLAVE_EBI_CH0,
+ SM6115_SLAVE_BIMC_SNOC,
+};
+
+static struct qcom_icc_node apps_proc = {
+ .name = "apps_proc",
+ .id = SM6115_MASTER_AMPSS_M0,
+ .channels = 1,
+ .buswidth = 16,
+ .qos.qos_port = 0,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.prio_level = 0,
+ .qos.areq_prio = 0,
+ .mas_rpm_id = 0,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_ebi_slv_bimc_snoc_links),
+ .links = slv_ebi_slv_bimc_snoc_links,
+};
+
+static const u16 link_slv_ebi[] = {
+ SM6115_SLAVE_EBI_CH0,
+};
+
+static struct qcom_icc_node mas_snoc_bimc_rt = {
+ .name = "mas_snoc_bimc_rt",
+ .id = SM6115_MASTER_SNOC_BIMC_RT,
+ .channels = 1,
+ .buswidth = 16,
+ .qos.qos_port = 2,
+ .qos.qos_mode = NOC_QOS_MODE_BYPASS,
+ .qos.areq_prio = 0,
+ .qos.prio_level = 0,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_ebi),
+ .links = link_slv_ebi,
+};
+
+static struct qcom_icc_node mas_snoc_bimc_nrt = {
+ .name = "mas_snoc_bimc_nrt",
+ .id = SM6115_MASTER_SNOC_BIMC_NRT,
+ .channels = 1,
+ .buswidth = 16,
+ .qos.qos_port = 3,
+ .qos.qos_mode = NOC_QOS_MODE_BYPASS,
+ .qos.areq_prio = 0,
+ .qos.prio_level = 0,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_ebi),
+ .links = link_slv_ebi,
+};
+
+static struct qcom_icc_node mas_snoc_bimc = {
+ .name = "mas_snoc_bimc",
+ .id = SM6115_MASTER_SNOC_BIMC,
+ .channels = 1,
+ .buswidth = 16,
+ .qos.qos_port = 6,
+ .qos.qos_mode = NOC_QOS_MODE_BYPASS,
+ .qos.areq_prio = 0,
+ .qos.prio_level = 0,
+ .mas_rpm_id = 3,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_ebi),
+ .links = link_slv_ebi,
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = SM6115_MASTER_GRAPHICS_3D,
+ .channels = 1,
+ .buswidth = 32,
+ .qos.qos_port = 1,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.prio_level = 0,
+ .qos.areq_prio = 0,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_ebi_slv_bimc_snoc_links),
+ .links = slv_ebi_slv_bimc_snoc_links,
+};
+
+static struct qcom_icc_node tcu_0 = {
+ .name = "tcu_0",
+ .id = SM6115_MASTER_TCU_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 4,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.prio_level = 6,
+ .qos.areq_prio = 6,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_ebi_slv_bimc_snoc_links),
+ .links = slv_ebi_slv_bimc_snoc_links,
+};
+
+static const u16 qup_core_0_links[] = {
+ SM6115_SLAVE_QUP_CORE_0,
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = SM6115_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = 170,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(qup_core_0_links),
+ .links = qup_core_0_links,
+};
+
+static const u16 link_slv_anoc_snoc[] = {
+ SM6115_SLAVE_ANOC_SNOC,
+};
+
+static struct qcom_icc_node crypto_c0 = {
+ .name = "crypto_c0",
+ .id = SM6115_MASTER_CRYPTO_CORE0,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 43,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = 23,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static const u16 mas_snoc_cnoc_links[] = {
+ SM6115_SLAVE_AHB2PHY_USB,
+ SM6115_SLAVE_APSS_THROTTLE_CFG,
+ SM6115_SLAVE_BIMC_CFG,
+ SM6115_SLAVE_BOOT_ROM,
+ SM6115_SLAVE_CAMERA_CFG,
+ SM6115_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ SM6115_SLAVE_CAMERA_RT_THROTTLE_CFG,
+ SM6115_SLAVE_CLK_CTL,
+ SM6115_SLAVE_CNOC_MSS,
+ SM6115_SLAVE_CRYPTO_0_CFG,
+ SM6115_SLAVE_DCC_CFG,
+ SM6115_SLAVE_DDR_PHY_CFG,
+ SM6115_SLAVE_DDR_SS_CFG,
+ SM6115_SLAVE_DISPLAY_CFG,
+ SM6115_SLAVE_DISPLAY_THROTTLE_CFG,
+ SM6115_SLAVE_GPU_CFG,
+ SM6115_SLAVE_GPU_THROTTLE_CFG,
+ SM6115_SLAVE_HWKM_CORE,
+ SM6115_SLAVE_IMEM_CFG,
+ SM6115_SLAVE_IPA_CFG,
+ SM6115_SLAVE_LPASS,
+ SM6115_SLAVE_MAPSS,
+ SM6115_SLAVE_MDSP_MPU_CFG,
+ SM6115_SLAVE_MESSAGE_RAM,
+ SM6115_SLAVE_PDM,
+ SM6115_SLAVE_PIMEM_CFG,
+ SM6115_SLAVE_PKA_CORE,
+ SM6115_SLAVE_PMIC_ARB,
+ SM6115_SLAVE_QDSS_CFG,
+ SM6115_SLAVE_QM_CFG,
+ SM6115_SLAVE_QM_MPU_CFG,
+ SM6115_SLAVE_QPIC,
+ SM6115_SLAVE_QUP_0,
+ SM6115_SLAVE_RBCPR_CX_CFG,
+ SM6115_SLAVE_RBCPR_MX_CFG,
+ SM6115_SLAVE_RPM,
+ SM6115_SLAVE_SDCC_1,
+ SM6115_SLAVE_SDCC_2,
+ SM6115_SLAVE_SECURITY,
+ SM6115_SLAVE_SERVICE_CNOC,
+ SM6115_SLAVE_SNOC_CFG,
+ SM6115_SLAVE_TCSR,
+ SM6115_SLAVE_TLMM,
+ SM6115_SLAVE_USB3,
+ SM6115_SLAVE_VENUS_CFG,
+ SM6115_SLAVE_VENUS_THROTTLE_CFG,
+ SM6115_SLAVE_VSENSE_CTRL_CFG,
+};
+
+static struct qcom_icc_node mas_snoc_cnoc = {
+ .name = "mas_snoc_cnoc",
+ .id = SM6115_MASTER_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_snoc_cnoc_links),
+ .links = mas_snoc_cnoc_links,
+};
+
+static struct qcom_icc_node xm_dap = {
+ .name = "xm_dap",
+ .id = SM6115_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_snoc_cnoc_links),
+ .links = mas_snoc_cnoc_links,
+};
+
+static const u16 link_slv_snoc_bimc_nrt[] = {
+ SM6115_SLAVE_SNOC_BIMC_NRT,
+};
+
+static struct qcom_icc_node qnm_camera_nrt = {
+ .name = "qnm_camera_nrt",
+ .id = SM6115_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .qos.qos_port = 25,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 3,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_snoc_bimc_nrt),
+ .links = link_slv_snoc_bimc_nrt,
+};
+
+static struct qcom_icc_node qxm_venus0 = {
+ .name = "qxm_venus0",
+ .id = SM6115_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 16,
+ .qos.qos_port = 30,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 3,
+ .qos.urg_fwd_en = true,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_snoc_bimc_nrt),
+ .links = link_slv_snoc_bimc_nrt,
+};
+
+static struct qcom_icc_node qxm_venus_cpu = {
+ .name = "qxm_venus_cpu",
+ .id = SM6115_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 34,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_snoc_bimc_nrt),
+ .links = link_slv_snoc_bimc_nrt,
+};
+
+static const u16 link_slv_snoc_bimc_rt[] = {
+ SM6115_SLAVE_SNOC_BIMC_RT,
+};
+
+static struct qcom_icc_node qnm_camera_rt = {
+ .name = "qnm_camera_rt",
+ .id = SM6115_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .qos.qos_port = 31,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 3,
+ .qos.urg_fwd_en = true,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_snoc_bimc_rt),
+ .links = link_slv_snoc_bimc_rt,
+};
+
+static struct qcom_icc_node qxm_mdp0 = {
+ .name = "qxm_mdp0",
+ .id = SM6115_MASTER_MDP_PORT0,
+ .channels = 1,
+ .buswidth = 16,
+ .qos.qos_port = 26,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 3,
+ .qos.urg_fwd_en = true,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_snoc_bimc_rt),
+ .links = link_slv_snoc_bimc_rt,
+};
+
+static const u16 slv_service_snoc_links[] = {
+ SM6115_SLAVE_SERVICE_SNOC,
+};
+
+static struct qcom_icc_node qhm_snoc_cfg = {
+ .name = "qhm_snoc_cfg",
+ .id = SM6115_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_service_snoc_links),
+ .links = slv_service_snoc_links,
+};
+
+static const u16 mas_tic_links[] = {
+ SM6115_SLAVE_APPSS,
+ SM6115_SLAVE_OCIMEM,
+ SM6115_SLAVE_PIMEM,
+ SM6115_SLAVE_QDSS_STM,
+ SM6115_SLAVE_TCU,
+ SM6115_SLAVE_SNOC_BIMC,
+ SM6115_SLAVE_SNOC_CNOC,
+};
+
+static struct qcom_icc_node qhm_tic = {
+ .name = "qhm_tic",
+ .id = SM6115_MASTER_TIC,
+ .channels = 1,
+ .buswidth = 4,
+ .qos.qos_port = 29,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_tic_links),
+ .links = mas_tic_links,
+};
+
+static struct qcom_icc_node mas_anoc_snoc = {
+ .name = "mas_anoc_snoc",
+ .id = SM6115_MASTER_ANOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_tic_links),
+ .links = mas_tic_links,
+};
+
+static const u16 mas_bimc_snoc_links[] = {
+ SM6115_SLAVE_APPSS,
+ SM6115_SLAVE_SNOC_CNOC,
+ SM6115_SLAVE_OCIMEM,
+ SM6115_SLAVE_PIMEM,
+ SM6115_SLAVE_QDSS_STM,
+ SM6115_SLAVE_TCU,
+};
+
+static struct qcom_icc_node mas_bimc_snoc = {
+ .name = "mas_bimc_snoc",
+ .id = SM6115_MASTER_BIMC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = 21,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_bimc_snoc_links),
+ .links = mas_bimc_snoc_links,
+};
+
+static const u16 mas_pimem_links[] = {
+ SM6115_SLAVE_OCIMEM,
+ SM6115_SLAVE_SNOC_BIMC,
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = SM6115_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 41,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_pimem_links),
+ .links = mas_pimem_links,
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = SM6115_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .qos.qos_port = 23,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node qhm_qpic = {
+ .name = "qhm_qpic",
+ .id = SM6115_MASTER_QPIC,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = SM6115_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qos.qos_port = 21,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = 166,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = SM6115_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 24,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = 59,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node xm_qdss_etr = {
+ .name = "xm_qdss_etr",
+ .id = SM6115_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 33,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = SM6115_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 38,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = 33,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node xm_sdc2 = {
+ .name = "xm_sdc2",
+ .id = SM6115_MASTER_SDCC_2,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 44,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = 35,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = SM6115_MASTER_USB3,
+ .channels = 1,
+ .buswidth = 8,
+ .qos.qos_port = 45,
+ .qos.qos_mode = NOC_QOS_MODE_FIXED,
+ .qos.areq_prio = 2,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(link_slv_anoc_snoc),
+ .links = link_slv_anoc_snoc,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = SM6115_SLAVE_EBI_CH0,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 0,
+};
+
+static const u16 slv_bimc_snoc_links[] = {
+ SM6115_MASTER_BIMC_SNOC,
+};
+
+static struct qcom_icc_node slv_bimc_snoc = {
+ .name = "slv_bimc_snoc",
+ .id = SM6115_SLAVE_BIMC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 2,
+ .num_links = ARRAY_SIZE(slv_bimc_snoc_links),
+ .links = slv_bimc_snoc_links,
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = SM6115_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_ahb2phy_usb = {
+ .name = "qhs_ahb2phy_usb",
+ .id = SM6115_SLAVE_AHB2PHY_USB,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_apss_throttle_cfg = {
+ .name = "qhs_apss_throttle_cfg",
+ .id = SM6115_SLAVE_APSS_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_bimc_cfg = {
+ .name = "qhs_bimc_cfg",
+ .id = SM6115_SLAVE_BIMC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_boot_rom = {
+ .name = "qhs_boot_rom",
+ .id = SM6115_SLAVE_BOOT_ROM,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_camera_nrt_throttle_cfg = {
+ .name = "qhs_camera_nrt_throttle_cfg",
+ .id = SM6115_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_camera_rt_throttle_cfg = {
+ .name = "qhs_camera_rt_throttle_cfg",
+ .id = SM6115_SLAVE_CAMERA_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_camera_ss_cfg = {
+ .name = "qhs_camera_ss_cfg",
+ .id = SM6115_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = SM6115_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = SM6115_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = SM6115_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = SM6115_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_dcc_cfg = {
+ .name = "qhs_dcc_cfg",
+ .id = SM6115_SLAVE_DCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_ddr_phy_cfg = {
+ .name = "qhs_ddr_phy_cfg",
+ .id = SM6115_SLAVE_DDR_PHY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_ddr_ss_cfg = {
+ .name = "qhs_ddr_ss_cfg",
+ .id = SM6115_SLAVE_DDR_SS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_disp_ss_cfg = {
+ .name = "qhs_disp_ss_cfg",
+ .id = SM6115_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_display_throttle_cfg = {
+ .name = "qhs_display_throttle_cfg",
+ .id = SM6115_SLAVE_DISPLAY_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_gpu_cfg = {
+ .name = "qhs_gpu_cfg",
+ .id = SM6115_SLAVE_GPU_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_gpu_throttle_cfg = {
+ .name = "qhs_gpu_throttle_cfg",
+ .id = SM6115_SLAVE_GPU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_hwkm = {
+ .name = "qhs_hwkm",
+ .id = SM6115_SLAVE_HWKM_CORE,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = SM6115_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_ipa_cfg = {
+ .name = "qhs_ipa_cfg",
+ .id = SM6115_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_lpass = {
+ .name = "qhs_lpass",
+ .id = SM6115_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_mapss = {
+ .name = "qhs_mapss",
+ .id = SM6115_SLAVE_MAPSS,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_mdsp_mpu_cfg = {
+ .name = "qhs_mdsp_mpu_cfg",
+ .id = SM6115_SLAVE_MDSP_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_mesg_ram = {
+ .name = "qhs_mesg_ram",
+ .id = SM6115_SLAVE_MESSAGE_RAM,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_mss = {
+ .name = "qhs_mss",
+ .id = SM6115_SLAVE_CNOC_MSS,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = SM6115_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = SM6115_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_pka_wrapper = {
+ .name = "qhs_pka_wrapper",
+ .id = SM6115_SLAVE_PKA_CORE,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_pmic_arb = {
+ .name = "qhs_pmic_arb",
+ .id = SM6115_SLAVE_PMIC_ARB,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = SM6115_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_qm_cfg = {
+ .name = "qhs_qm_cfg",
+ .id = SM6115_SLAVE_QM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_qm_mpu_cfg = {
+ .name = "qhs_qm_mpu_cfg",
+ .id = SM6115_SLAVE_QM_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_qpic = {
+ .name = "qhs_qpic",
+ .id = SM6115_SLAVE_QPIC,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = SM6115_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_rpm = {
+ .name = "qhs_rpm",
+ .id = SM6115_SLAVE_RPM,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = SM6115_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_sdc2 = {
+ .name = "qhs_sdc2",
+ .id = SM6115_SLAVE_SDCC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_security = {
+ .name = "qhs_security",
+ .id = SM6115_SLAVE_SECURITY,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static const u16 slv_snoc_cfg_links[] = {
+ SM6115_MASTER_SNOC_CFG,
+};
+
+static struct qcom_icc_node qhs_snoc_cfg = {
+ .name = "qhs_snoc_cfg",
+ .id = SM6115_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_snoc_cfg_links),
+ .links = slv_snoc_cfg_links,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = SM6115_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = SM6115_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_usb3 = {
+ .name = "qhs_usb3",
+ .id = SM6115_SLAVE_USB3,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = SM6115_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_venus_throttle_cfg = {
+ .name = "qhs_venus_throttle_cfg",
+ .id = SM6115_SLAVE_VENUS_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = SM6115_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = SM6115_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static const u16 slv_snoc_bimc_nrt_links[] = {
+ SM6115_MASTER_SNOC_BIMC_NRT,
+};
+
+static struct qcom_icc_node slv_snoc_bimc_nrt = {
+ .name = "slv_snoc_bimc_nrt",
+ .id = SM6115_SLAVE_SNOC_BIMC_NRT,
+ .channels = 1,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_snoc_bimc_nrt_links),
+ .links = slv_snoc_bimc_nrt_links,
+};
+
+static const u16 slv_snoc_bimc_rt_links[] = {
+ SM6115_MASTER_SNOC_BIMC_RT,
+};
+
+static struct qcom_icc_node slv_snoc_bimc_rt = {
+ .name = "slv_snoc_bimc_rt",
+ .id = SM6115_SLAVE_SNOC_BIMC_RT,
+ .channels = 1,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_snoc_bimc_rt_links),
+ .links = slv_snoc_bimc_rt_links,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = SM6115_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static const u16 slv_snoc_cnoc_links[] = {
+ SM6115_MASTER_SNOC_CNOC
+};
+
+static struct qcom_icc_node slv_snoc_cnoc = {
+ .name = "slv_snoc_cnoc",
+ .id = SM6115_SLAVE_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 25,
+ .num_links = ARRAY_SIZE(slv_snoc_cnoc_links),
+ .links = slv_snoc_cnoc_links,
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = SM6115_SLAVE_OCIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 26,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = SM6115_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static const u16 slv_snoc_bimc_links[] = {
+ SM6115_MASTER_SNOC_BIMC,
+};
+
+static struct qcom_icc_node slv_snoc_bimc = {
+ .name = "slv_snoc_bimc",
+ .id = SM6115_SLAVE_SNOC_BIMC,
+ .channels = 1,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 24,
+ .num_links = ARRAY_SIZE(slv_snoc_bimc_links),
+ .links = slv_snoc_bimc_links,
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = SM6115_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = SM6115_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 30,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = SM6115_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+};
+
+static const u16 slv_anoc_snoc_links[] = {
+ SM6115_MASTER_ANOC_SNOC,
+};
+
+static struct qcom_icc_node slv_anoc_snoc = {
+ .name = "slv_anoc_snoc",
+ .id = SM6115_SLAVE_ANOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(slv_anoc_snoc_links),
+ .links = slv_anoc_snoc_links,
+};
+
+static struct qcom_icc_node *bimc_nodes[] = {
+ [MASTER_AMPSS_M0] = &apps_proc,
+ [MASTER_SNOC_BIMC_RT] = &mas_snoc_bimc_rt,
+ [MASTER_SNOC_BIMC_NRT] = &mas_snoc_bimc_nrt,
+ [SNOC_BIMC_MAS] = &mas_snoc_bimc,
+ [MASTER_GRAPHICS_3D] = &qnm_gpu,
+ [MASTER_TCU_0] = &tcu_0,
+ [SLAVE_EBI_CH0] = &ebi,
+ [BIMC_SNOC_SLV] = &slv_bimc_snoc,
+};
+
+static const struct regmap_config bimc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x80000,
+ .fast_io = true,
+};
+
+static const struct qcom_icc_desc sm6115_bimc = {
+ .type = QCOM_ICC_BIMC,
+ .nodes = bimc_nodes,
+ .num_nodes = ARRAY_SIZE(bimc_nodes),
+ .regmap_cfg = &bimc_regmap_config,
+ .bus_clk_desc = &bimc_clk,
+ .keep_alive = true,
+ .qos_offset = 0x8000,
+};
+
+static struct qcom_icc_node *config_noc_nodes[] = {
+ [SNOC_CNOC_MAS] = &mas_snoc_cnoc,
+ [MASTER_QDSS_DAP] = &xm_dap,
+ [SLAVE_AHB2PHY_USB] = &qhs_ahb2phy_usb,
+ [SLAVE_APSS_THROTTLE_CFG] = &qhs_apss_throttle_cfg,
+ [SLAVE_BIMC_CFG] = &qhs_bimc_cfg,
+ [SLAVE_BOOT_ROM] = &qhs_boot_rom,
+ [SLAVE_CAMERA_NRT_THROTTLE_CFG] = &qhs_camera_nrt_throttle_cfg,
+ [SLAVE_CAMERA_RT_THROTTLE_CFG] = &qhs_camera_rt_throttle_cfg,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_ss_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_DCC_CFG] = &qhs_dcc_cfg,
+ [SLAVE_DDR_PHY_CFG] = &qhs_ddr_phy_cfg,
+ [SLAVE_DDR_SS_CFG] = &qhs_ddr_ss_cfg,
+ [SLAVE_DISPLAY_CFG] = &qhs_disp_ss_cfg,
+ [SLAVE_DISPLAY_THROTTLE_CFG] = &qhs_display_throttle_cfg,
+ [SLAVE_GPU_CFG] = &qhs_gpu_cfg,
+ [SLAVE_GPU_THROTTLE_CFG] = &qhs_gpu_throttle_cfg,
+ [SLAVE_HWKM_CORE] = &qhs_hwkm,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa_cfg,
+ [SLAVE_LPASS] = &qhs_lpass,
+ [SLAVE_MAPSS] = &qhs_mapss,
+ [SLAVE_MDSP_MPU_CFG] = &qhs_mdsp_mpu_cfg,
+ [SLAVE_MESSAGE_RAM] = &qhs_mesg_ram,
+ [SLAVE_CNOC_MSS] = &qhs_mss,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PKA_CORE] = &qhs_pka_wrapper,
+ [SLAVE_PMIC_ARB] = &qhs_pmic_arb,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QM_CFG] = &qhs_qm_cfg,
+ [SLAVE_QM_MPU_CFG] = &qhs_qm_mpu_cfg,
+ [SLAVE_QPIC] = &qhs_qpic,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_RPM] = &qhs_rpm,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_SDCC_2] = &qhs_sdc2,
+ [SLAVE_SECURITY] = &qhs_security,
+ [SLAVE_SNOC_CFG] = &qhs_snoc_cfg,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_USB3] = &qhs_usb3,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VENUS_THROTTLE_CFG] = &qhs_venus_throttle_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+};
+
+static const struct regmap_config cnoc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x6200,
+ .fast_io = true,
+};
+
+static const struct qcom_icc_desc sm6115_config_noc = {
+ .type = QCOM_ICC_QNOC,
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .regmap_cfg = &cnoc_regmap_config,
+ .intf_clocks = cnoc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(cnoc_intf_clocks),
+ .bus_clk_desc = &bus_1_clk,
+ .keep_alive = true,
+};
+
+static struct qcom_icc_node *sys_noc_nodes[] = {
+ [MASTER_CRYPTO_CORE0] = &crypto_c0,
+ [MASTER_SNOC_CFG] = &qhm_snoc_cfg,
+ [MASTER_TIC] = &qhm_tic,
+ [MASTER_ANOC_SNOC] = &mas_anoc_snoc,
+ [BIMC_SNOC_MAS] = &mas_bimc_snoc,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QPIC] = &qhm_qpic,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_SDCC_2] = &xm_sdc2,
+ [MASTER_USB3] = &xm_usb3_0,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SNOC_CNOC_SLV] = &slv_snoc_cnoc,
+ [SLAVE_OCIMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SNOC_BIMC_SLV] = &slv_snoc_bimc,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+ [SLAVE_ANOC_SNOC] = &slv_anoc_snoc,
+};
+
+static const struct regmap_config sys_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x5f080,
+ .fast_io = true,
+};
+
+static const struct qcom_icc_desc sm6115_sys_noc = {
+ .type = QCOM_ICC_QNOC,
+ .nodes = sys_noc_nodes,
+ .num_nodes = ARRAY_SIZE(sys_noc_nodes),
+ .regmap_cfg = &sys_noc_regmap_config,
+ .intf_clocks = snoc_intf_clocks,
+ .num_intf_clocks = ARRAY_SIZE(snoc_intf_clocks),
+ .bus_clk_desc = &bus_2_clk,
+ .keep_alive = true,
+};
+
+static struct qcom_icc_node *clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+};
+
+static const struct qcom_icc_desc sm6115_clk_virt = {
+ .type = QCOM_ICC_QNOC,
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .regmap_cfg = &sys_noc_regmap_config,
+ .bus_clk_desc = &qup_clk,
+ .keep_alive = true,
+};
+
+static struct qcom_icc_node *mmnrt_virt_nodes[] = {
+ [MASTER_CAMNOC_SF] = &qnm_camera_nrt,
+ [MASTER_VIDEO_P0] = &qxm_venus0,
+ [MASTER_VIDEO_PROC] = &qxm_venus_cpu,
+ [SLAVE_SNOC_BIMC_NRT] = &slv_snoc_bimc_nrt,
+};
+
+static const struct qcom_icc_desc sm6115_mmnrt_virt = {
+ .type = QCOM_ICC_QNOC,
+ .nodes = mmnrt_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mmnrt_virt_nodes),
+ .regmap_cfg = &sys_noc_regmap_config,
+ .bus_clk_desc = &mmaxi_0_clk,
+ .keep_alive = true,
+};
+
+static struct qcom_icc_node *mmrt_virt_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camera_rt,
+ [MASTER_MDP_PORT0] = &qxm_mdp0,
+ [SLAVE_SNOC_BIMC_RT] = &slv_snoc_bimc_rt,
+};
+
+static const struct qcom_icc_desc sm6115_mmrt_virt = {
+ .type = QCOM_ICC_QNOC,
+ .nodes = mmrt_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mmrt_virt_nodes),
+ .regmap_cfg = &sys_noc_regmap_config,
+ .bus_clk_desc = &mmaxi_1_clk,
+ .keep_alive = true,
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sm6115-bimc", .data = &sm6115_bimc },
+ { .compatible = "qcom,sm6115-clk-virt", .data = &sm6115_clk_virt },
+ { .compatible = "qcom,sm6115-cnoc", .data = &sm6115_config_noc },
+ { .compatible = "qcom,sm6115-mmrt-virt", .data = &sm6115_mmrt_virt },
+ { .compatible = "qcom,sm6115-mmnrt-virt", .data = &sm6115_mmnrt_virt },
+ { .compatible = "qcom,sm6115-snoc", .data = &sm6115_sys_noc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qnoc_probe,
+ .remove = qnoc_remove,
+ .driver = {
+ .name = "qnoc-sm6115",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("SM6115 NoC driver");
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 549ae4dba3a..0fd2c124299 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -245,6 +245,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
{ .compatible = "qcom,adreno" },
{ .compatible = "qcom,mdp4" },
{ .compatible = "qcom,mdss" },
+ { .compatible = "qcom,qcm2290-mdss" },
{ .compatible = "qcom,sc7180-mdss" },
{ .compatible = "qcom,sc7180-mss-pil" },
{ .compatible = "qcom,sc7280-mdss" },
@@ -254,6 +255,7 @@ static const struct of_device_id qcom_smmu_client_of_match[] __maybe_unused = {
{ .compatible = "qcom,sdm670-mdss" },
{ .compatible = "qcom,sdm845-mdss" },
{ .compatible = "qcom,sdm845-mss-pil" },
+ { .compatible = "qcom,sm6115-mdss" },
{ .compatible = "qcom,sm6350-mdss" },
{ .compatible = "qcom,sm6375-mdss" },
{ .compatible = "qcom,sm8150-mdss" },
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 05be59ae21b..6ae2329052c 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -265,6 +265,7 @@ struct bcache_device {
#define BCACHE_DEV_WB_RUNNING 3
#define BCACHE_DEV_RATE_DW_RUNNING 4
int nr_stripes;
+#define BCH_MIN_STRIPE_SZ ((4 << 20) >> SECTOR_SHIFT)
unsigned int stripe_size;
atomic_t *stripe_sectors_dirty;
unsigned long *full_dirty_stripes;
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index ae5cbb55861..de3019972b3 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -1000,6 +1000,9 @@ static struct btree *mca_alloc(struct cache_set *c, struct btree_op *op,
*
* The btree node will have either a read or a write lock held, depending on
* level and op->lock.
+ *
+ * Note: Only error code or btree pointer will be returned, it is unncessary
+ * for callers to check NULL pointer.
*/
struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
struct bkey *k, int level, bool write,
@@ -1111,6 +1114,10 @@ static void btree_node_free(struct btree *b)
mutex_unlock(&b->c->bucket_lock);
}
+/*
+ * Only error code or btree pointer will be returned, it is unncessary for
+ * callers to check NULL pointer.
+ */
struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
int level, bool wait,
struct btree *parent)
@@ -1368,7 +1375,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
memset(new_nodes, 0, sizeof(new_nodes));
closure_init_stack(&cl);
- while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b))
+ while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
keys += r[nodes++].keys;
blocks = btree_default_blocks(b->c) * 2 / 3;
@@ -1532,6 +1539,8 @@ static int btree_gc_rewrite_node(struct btree *b, struct btree_op *op,
return 0;
n = btree_node_alloc_replacement(replace, NULL);
+ if (IS_ERR(n))
+ return 0;
/* recheck reserve after allocating replacement node */
if (btree_check_reserve(b, NULL)) {
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 8bd89976637..bfe1685dbae 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -905,6 +905,8 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
if (!d->stripe_size)
d->stripe_size = 1 << 31;
+ else if (d->stripe_size < BCH_MIN_STRIPE_SZ)
+ d->stripe_size = roundup(BCH_MIN_STRIPE_SZ, d->stripe_size);
n = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
if (!n || n > max_stripes) {
@@ -2016,7 +2018,7 @@ static int run_cache_set(struct cache_set *c)
c->root = bch_btree_node_get(c, NULL, k,
j->btree_level,
true, NULL);
- if (IS_ERR_OR_NULL(c->root))
+ if (IS_ERR(c->root))
goto err;
list_del_init(&c->root->list);
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 45d8af755de..a438efb6606 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -1104,7 +1104,7 @@ SHOW(__bch_cache)
sum += INITIAL_PRIO - cached[i];
if (n)
- do_div(sum, n);
+ sum = div64_u64(sum, n);
for (i = 0; i < ARRAY_SIZE(q); i++)
q[i] = INITIAL_PRIO - cached[n * (i + 1) /
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 24c049067f6..3accfdaee6b 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -913,7 +913,7 @@ static int bch_dirty_init_thread(void *arg)
int cur_idx, prev_idx, skip_nr;
k = p = NULL;
- cur_idx = prev_idx = 0;
+ prev_idx = 0;
bch_btree_iter_init(&c->root->keys, &iter, NULL);
k = bch_btree_iter_next_filter(&iter, &c->root->keys, bch_ptr_bad);
@@ -977,24 +977,35 @@ static int bch_btre_dirty_init_thread_nr(void)
void bch_sectors_dirty_init(struct bcache_device *d)
{
int i;
+ struct btree *b = NULL;
struct bkey *k = NULL;
struct btree_iter iter;
struct sectors_dirty_init op;
struct cache_set *c = d->c;
struct bch_dirty_init_state state;
+retry_lock:
+ b = c->root;
+ rw_lock(0, b, b->level);
+ if (b != c->root) {
+ rw_unlock(0, b);
+ goto retry_lock;
+ }
+
/* Just count root keys if no leaf node */
- rw_lock(0, c->root, c->root->level);
if (c->root->level == 0) {
bch_btree_op_init(&op.op, -1);
op.inode = d->id;
op.count = 0;
for_each_key_filter(&c->root->keys,
- k, &iter, bch_ptr_invalid)
+ k, &iter, bch_ptr_invalid) {
+ if (KEY_INODE(k) != op.inode)
+ continue;
sectors_dirty_init_fn(&op.op, c->root, k);
+ }
- rw_unlock(0, c->root);
+ rw_unlock(0, b);
return;
}
@@ -1014,23 +1025,24 @@ void bch_sectors_dirty_init(struct bcache_device *d)
if (atomic_read(&state.enough))
break;
+ atomic_inc(&state.started);
state.infos[i].state = &state;
state.infos[i].thread =
kthread_run(bch_dirty_init_thread, &state.infos[i],
"bch_dirtcnt[%d]", i);
if (IS_ERR(state.infos[i].thread)) {
pr_err("fails to run thread bch_dirty_init[%d]\n", i);
+ atomic_dec(&state.started);
for (--i; i >= 0; i--)
kthread_stop(state.infos[i].thread);
goto out;
}
- atomic_inc(&state.started);
}
out:
/* Must wait for all threads to stop. */
wait_event(state.wait, atomic_read(&state.started) == 0);
- rw_unlock(0, c->root);
+ rw_unlock(0, b);
}
void bch_cached_dev_writeback_init(struct cached_dev *dc)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 4ee4593c874..c94373d64f2 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -8666,7 +8666,8 @@ static void md_end_clone_io(struct bio *bio)
struct bio *orig_bio = md_io_clone->orig_bio;
struct mddev *mddev = md_io_clone->mddev;
- orig_bio->bi_status = bio->bi_status;
+ if (bio->bi_status && !orig_bio->bi_status)
+ orig_bio->bi_status = bio->bi_status;
if (md_io_clone->start_time)
bio_end_io_acct(orig_bio, md_io_clone->start_time);
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 1c6c62a7f7f..2a59d240e14 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -954,7 +954,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;
@@ -2254,6 +2257,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,19 @@ 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) {
+ rmem = of_reserved_mem_lookup(rmem_node);
+ if (!rmem) {
+ err = -EINVAL;
+ goto fdev_error;
+ }
+
+ qcom_scm_assign_mem(rmem->base, rmem->size, &data->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/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 614c0278419..6b73648b377 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -682,10 +682,24 @@ static void xgbe_service(struct work_struct *work)
static void xgbe_service_timer(struct timer_list *t)
{
struct xgbe_prv_data *pdata = from_timer(pdata, t, service_timer);
+ struct xgbe_channel *channel;
+ unsigned int i;
queue_work(pdata->dev_workqueue, &pdata->service_work);
mod_timer(&pdata->service_timer, jiffies + HZ);
+
+ if (!pdata->tx_usecs)
+ return;
+
+ for (i = 0; i < pdata->channel_count; i++) {
+ channel = pdata->channel[i];
+ if (!channel->tx_ring || channel->tx_timer_active)
+ break;
+ channel->tx_timer_active = 1;
+ mod_timer(&channel->tx_timer,
+ jiffies + usecs_to_jiffies(pdata->tx_usecs));
+ }
}
static void xgbe_init_timers(struct xgbe_prv_data *pdata)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 6e83ff59172..32fab5e7724 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -314,10 +314,15 @@ static int xgbe_get_link_ksettings(struct net_device *netdev,
cmd->base.phy_address = pdata->phy.address;
- cmd->base.autoneg = pdata->phy.autoneg;
- cmd->base.speed = pdata->phy.speed;
- cmd->base.duplex = pdata->phy.duplex;
+ if (netif_carrier_ok(netdev)) {
+ cmd->base.speed = pdata->phy.speed;
+ cmd->base.duplex = pdata->phy.duplex;
+ } else {
+ cmd->base.speed = SPEED_UNKNOWN;
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ }
+ cmd->base.autoneg = pdata->phy.autoneg;
cmd->base.port = PORT_NONE;
XGBE_LM_COPY(cmd, supported, lks, supported);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 32d2c6fac65..4a2dc705b52 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -1193,7 +1193,19 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
if (pdata->phy.duplex != DUPLEX_FULL)
return -EINVAL;
- xgbe_set_mode(pdata, mode);
+ /* Force the mode change for SFI in Fixed PHY config.
+ * Fixed PHY configs needs PLL to be enabled while doing mode set.
+ * When the SFP module isn't connected during boot, driver assumes
+ * AN is ON and attempts autonegotiation. However, if the connected
+ * SFP comes up in Fixed PHY config, the link will not come up as
+ * PLL isn't enabled while the initial mode set command is issued.
+ * So, force the mode change for SFI in Fixed PHY configuration to
+ * fix link issues.
+ */
+ if (mode == XGBE_MODE_SFI)
+ xgbe_change_mode(pdata, mode);
+ else
+ xgbe_set_mode(pdata, mode);
return 0;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 08d7edccfb8..3f99eb19824 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -3844,7 +3844,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
struct i40e_pf *pf = vf->pf;
struct i40e_vsi *vsi = NULL;
int aq_ret = 0;
- int i, ret;
+ int i;
if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
aq_ret = -EINVAL;
@@ -3868,8 +3868,10 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
}
cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL);
- if (!cfilter)
- return -ENOMEM;
+ if (!cfilter) {
+ aq_ret = -ENOMEM;
+ goto err_out;
+ }
/* parse destination mac address */
for (i = 0; i < ETH_ALEN; i++)
@@ -3917,13 +3919,13 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg)
/* Adding cloud filter programmed as TC filter */
if (tcf.dst_port)
- ret = i40e_add_del_cloud_filter_big_buf(vsi, cfilter, true);
+ aq_ret = i40e_add_del_cloud_filter_big_buf(vsi, cfilter, true);
else
- ret = i40e_add_del_cloud_filter(vsi, cfilter, true);
- if (ret) {
+ aq_ret = i40e_add_del_cloud_filter(vsi, cfilter, true);
+ if (aq_ret) {
dev_err(&pf->pdev->dev,
"VF %d: Failed to add cloud filter, err %pe aq_err %s\n",
- vf->vf_id, ERR_PTR(ret),
+ vf->vf_id, ERR_PTR(aq_ret),
i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
goto err_free;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 6607fa6fe55..fb9c93f37e8 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -7401,15 +7401,6 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
goto err_vsi_rebuild;
}
- /* configure PTP timestamping after VSI rebuild */
- if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) {
- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF)
- ice_ptp_cfg_timestamp(pf, false);
- else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL)
- /* for E82x PHC owner always need to have interrupts */
- ice_ptp_cfg_timestamp(pf, true);
- }
-
err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL);
if (err) {
dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err);
@@ -7461,6 +7452,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
ice_plug_aux_dev(pf);
if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG))
ice_lag_rebuild(pf);
+
+ /* Restore timestamp mode settings after VSI rebuild */
+ ice_ptp_restore_timestamp_mode(pf);
return;
err_vsi_rebuild:
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 1eddcbe89b0..71f405f8a6f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -256,48 +256,42 @@ ice_verify_pin_e810t(struct ptp_clock_info *info, unsigned int pin,
}
/**
- * ice_ptp_configure_tx_tstamp - Enable or disable Tx timestamp interrupt
- * @pf: The PF pointer to search in
- * @on: bool value for whether timestamp interrupt is enabled or disabled
+ * ice_ptp_cfg_tx_interrupt - Configure Tx timestamp interrupt for the device
+ * @pf: Board private structure
+ *
+ * Program the device to respond appropriately to the Tx timestamp interrupt
+ * cause.
*/
-static void ice_ptp_configure_tx_tstamp(struct ice_pf *pf, bool on)
+static void ice_ptp_cfg_tx_interrupt(struct ice_pf *pf)
{
+ struct ice_hw *hw = &pf->hw;
+ bool enable;
u32 val;
+ switch (pf->ptp.tx_interrupt_mode) {
+ case ICE_PTP_TX_INTERRUPT_ALL:
+ /* React to interrupts across all quads. */
+ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f);
+ enable = true;
+ break;
+ case ICE_PTP_TX_INTERRUPT_NONE:
+ /* Do not react to interrupts on any quad. */
+ wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0);
+ enable = false;
+ break;
+ case ICE_PTP_TX_INTERRUPT_SELF:
+ default:
+ enable = pf->ptp.tstamp_config.tx_type == HWTSTAMP_TX_ON;
+ break;
+ }
+
/* Configure the Tx timestamp interrupt */
- val = rd32(&pf->hw, PFINT_OICR_ENA);
- if (on)
+ val = rd32(hw, PFINT_OICR_ENA);
+ if (enable)
val |= PFINT_OICR_TSYN_TX_M;
else
val &= ~PFINT_OICR_TSYN_TX_M;
- wr32(&pf->hw, PFINT_OICR_ENA, val);
-}
-
-/**
- * ice_set_tx_tstamp - Enable or disable Tx timestamping
- * @pf: The PF pointer to search in
- * @on: bool value for whether timestamps are enabled or disabled
- */
-static void ice_set_tx_tstamp(struct ice_pf *pf, bool on)
-{
- struct ice_vsi *vsi;
- u16 i;
-
- vsi = ice_get_main_vsi(pf);
- if (!vsi)
- return;
-
- /* Set the timestamp enable flag for all the Tx rings */
- ice_for_each_txq(vsi, i) {
- if (!vsi->tx_rings[i])
- continue;
- vsi->tx_rings[i]->ptp_tx = on;
- }
-
- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF)
- ice_ptp_configure_tx_tstamp(pf, on);
-
- pf->ptp.tstamp_config.tx_type = on ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+ wr32(hw, PFINT_OICR_ENA, val);
}
/**
@@ -311,7 +305,7 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on)
u16 i;
vsi = ice_get_main_vsi(pf);
- if (!vsi)
+ if (!vsi || !vsi->rx_rings)
return;
/* Set the timestamp flag for all the Rx rings */
@@ -320,23 +314,50 @@ static void ice_set_rx_tstamp(struct ice_pf *pf, bool on)
continue;
vsi->rx_rings[i]->ptp_rx = on;
}
+}
+
+/**
+ * ice_ptp_disable_timestamp_mode - Disable current timestamp mode
+ * @pf: Board private structure
+ *
+ * Called during preparation for reset to temporarily disable timestamping on
+ * the device. Called during remove to disable timestamping while cleaning up
+ * driver resources.
+ */
+static void ice_ptp_disable_timestamp_mode(struct ice_pf *pf)
+{
+ struct ice_hw *hw = &pf->hw;
+ u32 val;
+
+ val = rd32(hw, PFINT_OICR_ENA);
+ val &= ~PFINT_OICR_TSYN_TX_M;
+ wr32(hw, PFINT_OICR_ENA, val);
- pf->ptp.tstamp_config.rx_filter = on ? HWTSTAMP_FILTER_ALL :
- HWTSTAMP_FILTER_NONE;
+ ice_set_rx_tstamp(pf, false);
}
/**
- * ice_ptp_cfg_timestamp - Configure timestamp for init/deinit
+ * ice_ptp_restore_timestamp_mode - Restore timestamp configuration
* @pf: Board private structure
- * @ena: bool value to enable or disable time stamp
*
- * This function will configure timestamping during PTP initialization
- * and deinitialization
+ * Called at the end of rebuild to restore timestamp configuration after
+ * a device reset.
*/
-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena)
+void ice_ptp_restore_timestamp_mode(struct ice_pf *pf)
{
- ice_set_tx_tstamp(pf, ena);
- ice_set_rx_tstamp(pf, ena);
+ struct ice_hw *hw = &pf->hw;
+ bool enable_rx;
+
+ ice_ptp_cfg_tx_interrupt(pf);
+
+ enable_rx = pf->ptp.tstamp_config.rx_filter == HWTSTAMP_FILTER_ALL;
+ ice_set_rx_tstamp(pf, enable_rx);
+
+ /* Trigger an immediate software interrupt to ensure that timestamps
+ * which occurred during reset are handled now.
+ */
+ wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
+ ice_flush(hw);
}
/**
@@ -2037,10 +2058,10 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config)
{
switch (config->tx_type) {
case HWTSTAMP_TX_OFF:
- ice_set_tx_tstamp(pf, false);
+ pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_OFF;
break;
case HWTSTAMP_TX_ON:
- ice_set_tx_tstamp(pf, true);
+ pf->ptp.tstamp_config.tx_type = HWTSTAMP_TX_ON;
break;
default:
return -ERANGE;
@@ -2048,7 +2069,7 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config)
switch (config->rx_filter) {
case HWTSTAMP_FILTER_NONE:
- ice_set_rx_tstamp(pf, false);
+ pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
break;
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
@@ -2064,12 +2085,15 @@ ice_ptp_set_timestamp_mode(struct ice_pf *pf, struct hwtstamp_config *config)
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
case HWTSTAMP_FILTER_NTP_ALL:
case HWTSTAMP_FILTER_ALL:
- ice_set_rx_tstamp(pf, true);
+ pf->ptp.tstamp_config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
default:
return -ERANGE;
}
+ /* Immediately update the device timestamping mode */
+ ice_ptp_restore_timestamp_mode(pf);
+
return 0;
}
@@ -2737,7 +2761,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf)
clear_bit(ICE_FLAG_PTP, pf->flags);
/* Disable timestamping for both Tx and Rx */
- ice_ptp_cfg_timestamp(pf, false);
+ ice_ptp_disable_timestamp_mode(pf);
kthread_cancel_delayed_work_sync(&ptp->work);
@@ -2803,15 +2827,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
/* Release the global hardware lock */
ice_ptp_unlock(hw);
- if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) {
- /* The clock owner for this device type handles the timestamp
- * interrupt for all ports.
- */
- ice_ptp_configure_tx_tstamp(pf, true);
-
- /* React on all quads interrupts for E82x */
- wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x1f);
-
+ if (!ice_is_e810(hw)) {
/* Enable quad interrupts */
err = ice_ptp_tx_ena_intr(pf, true, itr);
if (err)
@@ -2881,13 +2897,6 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
case ICE_PHY_E810:
return ice_ptp_init_tx_e810(pf, &ptp_port->tx);
case ICE_PHY_E822:
- /* Non-owner PFs don't react to any interrupts on E82x,
- * neither on own quad nor on others
- */
- if (!ice_ptp_pf_handles_tx_interrupt(pf)) {
- ice_ptp_configure_tx_tstamp(pf, false);
- wr32(hw, PFINT_TSYN_MSK + (0x4 * hw->pf_id), (u32)0x0);
- }
kthread_init_delayed_work(&ptp_port->ov_work,
ice_ptp_wait_for_offsets);
@@ -3032,6 +3041,9 @@ void ice_ptp_init(struct ice_pf *pf)
/* Start the PHY timestamping block */
ice_ptp_reset_phy_timestamping(pf);
+ /* Configure initial Tx interrupt settings */
+ ice_ptp_cfg_tx_interrupt(pf);
+
set_bit(ICE_FLAG_PTP, pf->flags);
err = ice_ptp_init_work(pf, ptp);
if (err)
@@ -3067,7 +3079,7 @@ void ice_ptp_release(struct ice_pf *pf)
return;
/* Disable timestamping for both Tx and Rx */
- ice_ptp_cfg_timestamp(pf, false);
+ ice_ptp_disable_timestamp_mode(pf);
ice_ptp_remove_auxbus_device(pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 8f6f9439275..06a330867fc 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -292,7 +292,7 @@ int ice_ptp_clock_index(struct ice_pf *pf);
struct ice_pf;
int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr);
int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr);
-void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena);
+void ice_ptp_restore_timestamp_mode(struct ice_pf *pf);
void ice_ptp_extts_event(struct ice_pf *pf);
s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
@@ -317,8 +317,7 @@ static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr)
return -EOPNOTSUPP;
}
-static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { }
-
+static inline void ice_ptp_restore_timestamp_mode(struct ice_pf *pf) { }
static inline void ice_ptp_extts_event(struct ice_pf *pf) { }
static inline s8
ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 52d0a126eb6..9e97ea86306 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -2306,9 +2306,6 @@ ice_tstamp(struct ice_tx_ring *tx_ring, struct sk_buff *skb,
if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
return;
- if (!tx_ring->ptp_tx)
- return;
-
/* Tx timestamps cannot be sampled when doing TSO */
if (first->tx_flags & ICE_TX_FLAGS_TSO)
return;
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
index 166413fc33f..daf7b9dbb14 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
@@ -380,7 +380,6 @@ struct ice_tx_ring {
#define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2)
u8 flags;
u8 dcb_tc; /* Traffic class of ring */
- u8 ptp_tx;
} ____cacheline_internodealigned_in_smp;
static inline bool ice_ring_uses_build_skb(struct ice_rx_ring *ring)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 4762dbea64a..97a71e9b856 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -1088,6 +1088,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
struct ethhdr *eth_hdr;
bool new = false;
int err = 0;
+ u64 vf_num;
u32 ring;
if (!flow_cfg->max_flows) {
@@ -1100,7 +1101,21 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
return -ENOMEM;
- if (ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
+ /* Number of queues on a VF can be greater or less than
+ * the PF's queue. Hence no need to check for the
+ * queue count. Hence no need to check queue count if PF
+ * is installing for its VF. Below is the expected vf_num value
+ * based on the ethtool commands.
+ *
+ * e.g.
+ * 1. ethtool -U <netdev> ... action -1 ==> vf_num:255
+ * 2. ethtool -U <netdev> ... action <queue_num> ==> vf_num:0
+ * 3. ethtool -U <netdev> ... vf <vf_idx> queue <queue_num> ==>
+ * vf_num:vf_idx+1
+ */
+ vf_num = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);
+ if (!is_otx2_vf(pfvf->pcifunc) && !vf_num &&
+ ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
return -EINVAL;
if (fsp->location >= otx2_get_maxflows(flow_cfg))
@@ -1182,6 +1197,9 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
flow_cfg->nr_flows++;
}
+ if (flow->is_vf)
+ netdev_info(pfvf->netdev,
+ "Make sure that VF's queue number is within its queue limit\n");
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index 91b99fd7036..ba95ac91327 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1934,6 +1934,8 @@ int otx2_stop(struct net_device *netdev)
/* Clear RSS enable flag */
rss = &pf->hw.rss_info;
rss->enable = false;
+ if (!netif_is_rxfh_configured(netdev))
+ kfree(rss->rss_ctx[DEFAULT_RSS_CONTEXT_GROUP]);
/* Cleanup Queue IRQ */
vec = pci_irq_vector(pf->pdev,
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index b9bb1d2f023..295366a85c6 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -2599,9 +2599,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
rx_mode &= ~AcceptMulticast;
} else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
dev->flags & IFF_ALLMULTI ||
- tp->mac_version == RTL_GIGA_MAC_VER_35 ||
- tp->mac_version == RTL_GIGA_MAC_VER_46 ||
- tp->mac_version == RTL_GIGA_MAC_VER_48) {
+ tp->mac_version == RTL_GIGA_MAC_VER_35) {
/* accept all multicasts */
} else if (netdev_mc_empty(dev)) {
rx_mode &= ~AcceptMulticast;
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index a2b9e289aa3..85dcda51df0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -280,7 +280,7 @@ config DWMAC_INTEL
config DWMAC_LOONGSON
tristate "Loongson PCI DWMAC support"
default MACH_LOONGSON64
- depends on STMMAC_ETH && PCI
+ depends on (MACH_LOONGSON64 || COMPILE_TEST) && STMMAC_ETH && PCI
depends on COMMON_CLK
help
This selects the LOONGSON PCI bus support for the stmmac driver,
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index a3c5de9d547..533e912af08 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1769,10 +1769,12 @@ int wx_sw_init(struct wx *wx)
wx->subsystem_device_id = pdev->subsystem_device;
} else {
err = wx_flash_read_dword(wx, 0xfffdc, &ssid);
- if (!err)
- wx->subsystem_device_id = swab16((u16)ssid);
+ if (err < 0) {
+ wx_err(wx, "read of internal subsystem device id failed\n");
+ return err;
+ }
- return err;
+ wx->subsystem_device_id = swab16((u16)ssid);
}
wx->mac_table = kcalloc(wx->mac.num_rar_entries,
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 3d43f808c86..8db804543e6 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -121,10 +121,8 @@ static int ngbe_sw_init(struct wx *wx)
/* PCI config space info */
err = wx_sw_init(wx);
- if (err < 0) {
- wx_err(wx, "read of internal subsystem device id failed\n");
+ if (err < 0)
return err;
- }
/* mac type, phy type , oem type */
ngbe_init_type_code(wx);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 70f0b5c01da..526250102db 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -364,10 +364,8 @@ static int txgbe_sw_init(struct wx *wx)
/* PCI config space info */
err = wx_sw_init(wx);
- if (err < 0) {
- wx_err(wx, "read of internal subsystem device id failed\n");
+ if (err < 0)
return err;
- }
txgbe_init_type_code(wx);
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 82d0d44b2b0..bf6e3399049 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -822,7 +822,7 @@ axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
if (lp->features & XAE_FEATURE_FULL_TX_CSUM) {
/* Tx Full Checksum Offload Enabled */
cur_p->app0 |= 2;
- } else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) {
+ } else if (lp->features & XAE_FEATURE_PARTIAL_TX_CSUM) {
csum_start_off = skb_transport_offset(skb);
csum_index_off = csum_start_off + skb->csum_offset;
/* Tx Partial Checksum Offload Enabled */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 3ba3c8fb28a..706ea5263e8 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2206,9 +2206,6 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
goto upper_link_failed;
}
- /* set slave flag before open to prevent IPv6 addrconf */
- vf_netdev->flags |= IFF_SLAVE;
-
schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
@@ -2315,16 +2312,18 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
}
- /* Fallback path to check synthetic vf with
- * help of mac addr
+ /* Fallback path to check synthetic vf with help of mac addr.
+ * Because this function can be called before vf_netdev is
+ * initialized (NETDEV_POST_INIT) when its perm_addr has not been copied
+ * from dev_addr, also try to match to its dev_addr.
+ * Note: On Hyper-V and Azure, it's not possible to set a MAC address
+ * on a VF that matches to the MAC of a unrelated NETVSC device.
*/
list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
ndev = hv_get_drvdata(ndev_ctx->device_ctx);
- if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr)) {
- netdev_notice(vf_netdev,
- "falling back to mac addr based matching\n");
+ if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr) ||
+ ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
return ndev;
- }
}
netdev_notice(vf_netdev,
@@ -2332,6 +2331,19 @@ static struct net_device *get_netvsc_byslot(const struct net_device *vf_netdev)
return NULL;
}
+static int netvsc_prepare_bonding(struct net_device *vf_netdev)
+{
+ struct net_device *ndev;
+
+ ndev = get_netvsc_byslot(vf_netdev);
+ if (!ndev)
+ return NOTIFY_DONE;
+
+ /* set slave flag before open to prevent IPv6 addrconf */
+ vf_netdev->flags |= IFF_SLAVE;
+ return NOTIFY_DONE;
+}
+
static int netvsc_register_vf(struct net_device *vf_netdev)
{
struct net_device_context *net_device_ctx;
@@ -2531,15 +2543,6 @@ static int netvsc_probe(struct hv_device *dev,
goto devinfo_failed;
}
- nvdev = rndis_filter_device_add(dev, device_info);
- if (IS_ERR(nvdev)) {
- ret = PTR_ERR(nvdev);
- netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
- goto rndis_failed;
- }
-
- eth_hw_addr_set(net, device_info->mac_adr);
-
/* We must get rtnl lock before scheduling nvdev->subchan_work,
* otherwise netvsc_subchan_work() can get rtnl lock first and wait
* all subchannels to show up, but that may not happen because
@@ -2547,9 +2550,23 @@ static int netvsc_probe(struct hv_device *dev,
* -> ... -> device_add() -> ... -> __device_attach() can't get
* the device lock, so all the subchannels can't be processed --
* finally netvsc_subchan_work() hangs forever.
+ *
+ * The rtnl lock also needs to be held before rndis_filter_device_add()
+ * which advertises nvsp_2_vsc_capability / sriov bit, and triggers
+ * VF NIC offering and registering. If VF NIC finished register_netdev()
+ * earlier it may cause name based config failure.
*/
rtnl_lock();
+ nvdev = rndis_filter_device_add(dev, device_info);
+ if (IS_ERR(nvdev)) {
+ ret = PTR_ERR(nvdev);
+ netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
+ goto rndis_failed;
+ }
+
+ eth_hw_addr_set(net, device_info->mac_adr);
+
if (nvdev->num_chn > 1)
schedule_work(&nvdev->subchan_work);
@@ -2586,9 +2603,9 @@ static int netvsc_probe(struct hv_device *dev,
return 0;
register_failed:
- rtnl_unlock();
rndis_filter_device_remove(dev, nvdev);
rndis_failed:
+ rtnl_unlock();
netvsc_devinfo_put(device_info);
devinfo_failed:
free_percpu(net_device_ctx->vf_stats);
@@ -2753,6 +2770,8 @@ static int netvsc_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
switch (event) {
+ case NETDEV_POST_INIT:
+ return netvsc_prepare_bonding(event_dev);
case NETDEV_REGISTER:
return netvsc_register_vf(event_dev);
case NETDEV_UNREGISTER:
@@ -2788,12 +2807,17 @@ static int __init netvsc_drv_init(void)
}
netvsc_ring_bytes = ring_size * PAGE_SIZE;
+ register_netdevice_notifier(&netvsc_netdev_notifier);
+
ret = vmbus_driver_register(&netvsc_drv);
if (ret)
- return ret;
+ goto err_vmbus_reg;
- register_netdevice_notifier(&netvsc_netdev_notifier);
return 0;
+
+err_vmbus_reg:
+ unregister_netdevice_notifier(&netvsc_netdev_notifier);
+ return ret;
}
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ipa/reg/gsi_reg-v5.0.c b/drivers/net/ipa/reg/gsi_reg-v5.0.c
index d7b81a36d67..145eb0bd096 100644
--- a/drivers/net/ipa/reg/gsi_reg-v5.0.c
+++ b/drivers/net/ipa/reg/gsi_reg-v5.0.c
@@ -78,7 +78,7 @@ REG_STRIDE_FIELDS(EV_CH_E_CNTXT_0, ev_ch_e_cntxt_0,
0x0001c000 + 0x12000 * GSI_EE_AP, 0x80);
static const u32 reg_ev_ch_e_cntxt_1_fmask[] = {
- [R_LENGTH] = GENMASK(19, 0),
+ [R_LENGTH] = GENMASK(23, 0),
};
REG_STRIDE_FIELDS(EV_CH_E_CNTXT_1, ev_ch_e_cntxt_1,
diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c
index 5a0f86f38f0..97bd6705c24 100644
--- a/drivers/net/netkit.c
+++ b/drivers/net/netkit.c
@@ -7,6 +7,7 @@
#include <linux/filter.h>
#include <linux/netfilter_netdev.h>
#include <linux/bpf_mprog.h>
+#include <linux/indirect_call_wrapper.h>
#include <net/netkit.h>
#include <net/dst.h>
@@ -68,6 +69,7 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_t ret_dev = NET_XMIT_SUCCESS;
const struct bpf_mprog_entry *entry;
struct net_device *peer;
+ int len = skb->len;
rcu_read_lock();
peer = rcu_dereference(nk->peer);
@@ -85,15 +87,22 @@ static netdev_tx_t netkit_xmit(struct sk_buff *skb, struct net_device *dev)
case NETKIT_PASS:
skb->protocol = eth_type_trans(skb, skb->dev);
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
- __netif_rx(skb);
+ if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {
+ dev_sw_netstats_tx_add(dev, 1, len);
+ dev_sw_netstats_rx_add(peer, len);
+ } else {
+ goto drop_stats;
+ }
break;
case NETKIT_REDIRECT:
+ dev_sw_netstats_tx_add(dev, 1, len);
skb_do_redirect(skb);
break;
case NETKIT_DROP:
default:
drop:
kfree_skb(skb);
+drop_stats:
dev_core_stats_tx_dropped_inc(dev);
ret_dev = NET_XMIT_DROP;
break;
@@ -169,11 +178,18 @@ static void netkit_set_headroom(struct net_device *dev, int headroom)
rcu_read_unlock();
}
-static struct net_device *netkit_peer_dev(struct net_device *dev)
+INDIRECT_CALLABLE_SCOPE struct net_device *netkit_peer_dev(struct net_device *dev)
{
return rcu_dereference(netkit_priv(dev)->peer);
}
+static void netkit_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ dev_fetch_sw_netstats(stats, dev->tstats);
+ stats->tx_dropped = DEV_STATS_READ(dev, tx_dropped);
+}
+
static void netkit_uninit(struct net_device *dev);
static const struct net_device_ops netkit_netdev_ops = {
@@ -184,6 +200,7 @@ static const struct net_device_ops netkit_netdev_ops = {
.ndo_set_rx_headroom = netkit_set_headroom,
.ndo_get_iflink = netkit_get_iflink,
.ndo_get_peer_dev = netkit_peer_dev,
+ .ndo_get_stats64 = netkit_get_stats,
.ndo_uninit = netkit_uninit,
.ndo_features_check = passthru_features_check,
};
@@ -218,6 +235,7 @@ static void netkit_setup(struct net_device *dev)
ether_setup(dev);
dev->max_mtu = ETH_MAX_MTU;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
dev->flags |= IFF_NOARP;
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
index a017e9de211..7b8afa589a5 100644
--- a/drivers/net/usb/aqc111.c
+++ b/drivers/net/usb/aqc111.c
@@ -1079,17 +1079,17 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
u16 pkt_count = 0;
u64 desc_hdr = 0;
u16 vlan_tag = 0;
- u32 skb_len = 0;
+ u32 skb_len;
if (!skb)
goto err;
- if (skb->len == 0)
+ skb_len = skb->len;
+ if (skb_len < sizeof(desc_hdr))
goto err;
- skb_len = skb->len;
/* RX Descriptor Header */
- skb_trim(skb, skb->len - sizeof(desc_hdr));
+ skb_trim(skb, skb_len - sizeof(desc_hdr));
desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb));
/* Check these packets */
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index aff39bf3161..4ea0e155bb0 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1583,11 +1583,11 @@ static int ax88179_reset(struct usbnet *dev)
*tmp16 = AX_PHYPWR_RSTCTL_IPRL;
ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
- msleep(200);
+ msleep(500);
*tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
- msleep(100);
+ msleep(200);
/* Ethernet PHY Auto Detach*/
ax88179_auto_detach(dev);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 344af3c5c83..e2e181378f4 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1289,6 +1289,7 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
{QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
{QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+ {QMI_FIXED_INTF(0x19d2, 0x0189, 4)}, /* ZTE MF290 */
{QMI_FIXED_INTF(0x19d2, 0x0191, 4)}, /* ZTE EuFi890 */
{QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */
{QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 9980517ed8b..57efb3454c5 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -236,8 +236,8 @@ static void veth_get_ethtool_stats(struct net_device *dev,
data[tx_idx + j] += *(u64 *)(base + offset);
}
} while (u64_stats_fetch_retry(&rq_stats->syncp, start));
- pp_idx = tx_idx + VETH_TQ_STATS_LEN;
}
+ pp_idx = idx + dev->real_num_tx_queues * VETH_TQ_STATS_LEN;
page_pool_stats:
veth_get_page_pool_stats(dev, &data[pp_idx]);
@@ -373,7 +373,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
skb_tx_timestamp(skb);
if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) {
if (!use_napi)
- dev_lstats_add(dev, length);
+ dev_sw_netstats_tx_add(dev, 1, length);
else
__veth_xdp_flush(rq);
} else {
@@ -387,14 +387,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
return ret;
}
-static u64 veth_stats_tx(struct net_device *dev, u64 *packets, u64 *bytes)
-{
- struct veth_priv *priv = netdev_priv(dev);
-
- dev_lstats_read(dev, packets, bytes);
- return atomic64_read(&priv->dropped);
-}
-
static void veth_stats_rx(struct veth_stats *result, struct net_device *dev)
{
struct veth_priv *priv = netdev_priv(dev);
@@ -432,24 +424,24 @@ static void veth_get_stats64(struct net_device *dev,
struct veth_priv *priv = netdev_priv(dev);
struct net_device *peer;
struct veth_stats rx;
- u64 packets, bytes;
- tot->tx_dropped = veth_stats_tx(dev, &packets, &bytes);
- tot->tx_bytes = bytes;
- tot->tx_packets = packets;
+ tot->tx_dropped = atomic64_read(&priv->dropped);
+ dev_fetch_sw_netstats(tot, dev->tstats);
veth_stats_rx(&rx, dev);
tot->tx_dropped += rx.xdp_tx_err;
tot->rx_dropped = rx.rx_drops + rx.peer_tq_xdp_xmit_err;
- tot->rx_bytes = rx.xdp_bytes;
- tot->rx_packets = rx.xdp_packets;
+ tot->rx_bytes += rx.xdp_bytes;
+ tot->rx_packets += rx.xdp_packets;
rcu_read_lock();
peer = rcu_dereference(priv->peer);
if (peer) {
- veth_stats_tx(peer, &packets, &bytes);
- tot->rx_bytes += bytes;
- tot->rx_packets += packets;
+ struct rtnl_link_stats64 tot_peer = {};
+
+ dev_fetch_sw_netstats(&tot_peer, peer->tstats);
+ tot->rx_bytes += tot_peer.tx_bytes;
+ tot->rx_packets += tot_peer.tx_packets;
veth_stats_rx(&rx, peer);
tot->tx_dropped += rx.peer_tq_xdp_xmit_err;
@@ -1506,25 +1498,12 @@ static void veth_free_queues(struct net_device *dev)
static int veth_dev_init(struct net_device *dev)
{
- int err;
-
- dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
- if (!dev->lstats)
- return -ENOMEM;
-
- err = veth_alloc_queues(dev);
- if (err) {
- free_percpu(dev->lstats);
- return err;
- }
-
- return 0;
+ return veth_alloc_queues(dev);
}
static void veth_dev_free(struct net_device *dev)
{
veth_free_queues(dev);
- free_percpu(dev->lstats);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1796,6 +1775,7 @@ static void veth_setup(struct net_device *dev)
NETIF_F_HW_VLAN_STAG_RX);
dev->needs_free_netdev = true;
dev->priv_destructor = veth_dev_free;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
dev->max_mtu = ETH_MAX_MTU;
dev->hw_features = VETH_FEATURES;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index db766941b78..bb95ce43cd9 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -121,22 +121,12 @@ struct net_vrf {
int ifindex;
};
-struct pcpu_dstats {
- u64 tx_pkts;
- u64 tx_bytes;
- u64 tx_drps;
- u64 rx_pkts;
- u64 rx_bytes;
- u64 rx_drps;
- struct u64_stats_sync syncp;
-};
-
static void vrf_rx_stats(struct net_device *dev, int len)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
u64_stats_update_begin(&dstats->syncp);
- dstats->rx_pkts++;
+ dstats->rx_packets++;
dstats->rx_bytes += len;
u64_stats_update_end(&dstats->syncp);
}
@@ -161,10 +151,10 @@ static void vrf_get_stats64(struct net_device *dev,
do {
start = u64_stats_fetch_begin(&dstats->syncp);
tbytes = dstats->tx_bytes;
- tpkts = dstats->tx_pkts;
- tdrops = dstats->tx_drps;
+ tpkts = dstats->tx_packets;
+ tdrops = dstats->tx_drops;
rbytes = dstats->rx_bytes;
- rpkts = dstats->rx_pkts;
+ rpkts = dstats->rx_packets;
} while (u64_stats_fetch_retry(&dstats->syncp, start));
stats->tx_bytes += tbytes;
stats->tx_packets += tpkts;
@@ -421,7 +411,7 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
vrf_rx_stats(dev, len);
else
- this_cpu_inc(dev->dstats->rx_drps);
+ this_cpu_inc(dev->dstats->rx_drops);
return NETDEV_TX_OK;
}
@@ -616,11 +606,11 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
u64_stats_update_begin(&dstats->syncp);
- dstats->tx_pkts++;
+ dstats->tx_packets++;
dstats->tx_bytes += len;
u64_stats_update_end(&dstats->syncp);
} else {
- this_cpu_inc(dev->dstats->tx_drps);
+ this_cpu_inc(dev->dstats->tx_drops);
}
return ret;
@@ -1174,22 +1164,15 @@ static void vrf_dev_uninit(struct net_device *dev)
vrf_rtable_release(dev, vrf);
vrf_rt6_release(dev, vrf);
-
- free_percpu(dev->dstats);
- dev->dstats = NULL;
}
static int vrf_dev_init(struct net_device *dev)
{
struct net_vrf *vrf = netdev_priv(dev);
- dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
- if (!dev->dstats)
- goto out_nomem;
-
/* create the default dst which points back to us */
if (vrf_rtable_create(dev) != 0)
- goto out_stats;
+ goto out_nomem;
if (vrf_rt6_create(dev) != 0)
goto out_rth;
@@ -1203,9 +1186,6 @@ static int vrf_dev_init(struct net_device *dev)
out_rth:
vrf_rtable_release(dev, vrf);
-out_stats:
- free_percpu(dev->dstats);
- dev->dstats = NULL;
out_nomem:
return -ENOMEM;
}
@@ -1704,6 +1684,8 @@ static void vrf_setup(struct net_device *dev)
dev->min_mtu = IPV6_MIN_MTU;
dev->max_mtu = IP6_MAX_MTU;
dev->mtu = dev->max_mtu;
+
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
}
static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index 258dcc10392..deb9636b0ec 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -210,7 +210,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
*/
while (skb_queue_len(&peer->staged_packet_queue) > MAX_STAGED_PACKETS) {
dev_kfree_skb(__skb_dequeue(&peer->staged_packet_queue));
- ++dev->stats.tx_dropped;
+ DEV_STATS_INC(dev, tx_dropped);
}
skb_queue_splice_tail(&packets, &peer->staged_packet_queue);
spin_unlock_bh(&peer->staged_packet_queue.lock);
@@ -228,7 +228,7 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
else if (skb->protocol == htons(ETH_P_IPV6))
icmpv6_ndo_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
err:
- ++dev->stats.tx_errors;
+ DEV_STATS_INC(dev, tx_errors);
kfree_skb(skb);
return ret;
}
diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c
index 0b3f0c84355..a176653c886 100644
--- a/drivers/net/wireguard/receive.c
+++ b/drivers/net/wireguard/receive.c
@@ -416,20 +416,20 @@ static void wg_packet_consume_data_done(struct wg_peer *peer,
net_dbg_skb_ratelimited("%s: Packet has unallowed src IP (%pISc) from peer %llu (%pISpfsc)\n",
dev->name, skb, peer->internal_id,
&peer->endpoint.addr);
- ++dev->stats.rx_errors;
- ++dev->stats.rx_frame_errors;
+ DEV_STATS_INC(dev, rx_errors);
+ DEV_STATS_INC(dev, rx_frame_errors);
goto packet_processed;
dishonest_packet_type:
net_dbg_ratelimited("%s: Packet is neither ipv4 nor ipv6 from peer %llu (%pISpfsc)\n",
dev->name, peer->internal_id, &peer->endpoint.addr);
- ++dev->stats.rx_errors;
- ++dev->stats.rx_frame_errors;
+ DEV_STATS_INC(dev, rx_errors);
+ DEV_STATS_INC(dev, rx_frame_errors);
goto packet_processed;
dishonest_packet_size:
net_dbg_ratelimited("%s: Packet has incorrect size from peer %llu (%pISpfsc)\n",
dev->name, peer->internal_id, &peer->endpoint.addr);
- ++dev->stats.rx_errors;
- ++dev->stats.rx_length_errors;
+ DEV_STATS_INC(dev, rx_errors);
+ DEV_STATS_INC(dev, rx_length_errors);
goto packet_processed;
packet_processed:
dev_kfree_skb(skb);
diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c
index 95c853b59e1..0d48e0f4a1b 100644
--- a/drivers/net/wireguard/send.c
+++ b/drivers/net/wireguard/send.c
@@ -333,7 +333,8 @@ static void wg_packet_create_data(struct wg_peer *peer, struct sk_buff *first)
void wg_packet_purge_staged_packets(struct wg_peer *peer)
{
spin_lock_bh(&peer->staged_packet_queue.lock);
- peer->device->dev->stats.tx_dropped += peer->staged_packet_queue.qlen;
+ DEV_STATS_ADD(peer->device->dev, tx_dropped,
+ peer->staged_packet_queue.qlen);
__skb_queue_purge(&peer->staged_packet_queue);
spin_unlock_bh(&peer->staged_packet_queue.lock);
}
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 52c1a3de8da..0334be061bc 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -807,6 +807,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);
@@ -818,9 +819,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/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c
index b027be0b0b6..590b038e449 100644
--- a/drivers/nfc/virtual_ncidev.c
+++ b/drivers/nfc/virtual_ncidev.c
@@ -26,10 +26,14 @@ struct virtual_nci_dev {
struct mutex mtx;
struct sk_buff *send_buff;
struct wait_queue_head wq;
+ bool running;
};
static int virtual_nci_open(struct nci_dev *ndev)
{
+ struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
+
+ vdev->running = true;
return 0;
}
@@ -40,6 +44,7 @@ static int virtual_nci_close(struct nci_dev *ndev)
mutex_lock(&vdev->mtx);
kfree_skb(vdev->send_buff);
vdev->send_buff = NULL;
+ vdev->running = false;
mutex_unlock(&vdev->mtx);
return 0;
@@ -50,7 +55,7 @@ static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
mutex_lock(&vdev->mtx);
- if (vdev->send_buff) {
+ if (vdev->send_buff || !vdev->running) {
mutex_unlock(&vdev->mtx);
kfree_skb(skb);
return -1;
diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c
index 48328e36e93..72c0525c75f 100644
--- a/drivers/nvme/host/auth.c
+++ b/drivers/nvme/host/auth.c
@@ -757,12 +757,11 @@ static void nvme_queue_auth_work(struct work_struct *work)
__func__, chap->qid);
mutex_lock(&ctrl->dhchap_auth_mutex);
ret = nvme_auth_dhchap_setup_host_response(ctrl, chap);
+ mutex_unlock(&ctrl->dhchap_auth_mutex);
if (ret) {
- mutex_unlock(&ctrl->dhchap_auth_mutex);
chap->error = ret;
goto fail2;
}
- mutex_unlock(&ctrl->dhchap_auth_mutex);
/* DH-HMAC-CHAP Step 3: send reply */
dev_dbg(ctrl->device, "%s: qid %d send reply\n",
@@ -839,6 +838,8 @@ static void nvme_queue_auth_work(struct work_struct *work)
}
fail2:
+ if (chap->status == 0)
+ chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
dev_dbg(ctrl->device, "%s: qid %d send failure2, status %x\n",
__func__, chap->qid, chap->status);
tl = nvme_auth_set_dhchap_failure2_data(ctrl, chap);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 88b54cdcbd6..46a4c9c5ea9 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -482,7 +482,6 @@ EXPORT_SYMBOL_GPL(nvme_cancel_tagset);
void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl)
{
- nvme_stop_keep_alive(ctrl);
if (ctrl->admin_tagset) {
blk_mq_tagset_busy_iter(ctrl->admin_tagset,
nvme_cancel_request, ctrl);
@@ -1814,16 +1813,18 @@ static int nvme_init_ms(struct nvme_ns *ns, struct nvme_id_ns *id)
return ret;
}
-static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
+static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
{
struct nvme_ctrl *ctrl = ns->ctrl;
+ int ret;
- if (nvme_init_ms(ns, id))
- return;
+ ret = nvme_init_ms(ns, id);
+ if (ret)
+ return ret;
ns->features &= ~(NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS);
if (!ns->ms || !(ctrl->ops->flags & NVME_F_METADATA_SUPPORTED))
- return;
+ return 0;
if (ctrl->ops->flags & NVME_F_FABRICS) {
/*
@@ -1832,7 +1833,7 @@ static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
* remap the separate metadata buffer from the block layer.
*/
if (WARN_ON_ONCE(!(id->flbas & NVME_NS_FLBAS_META_EXT)))
- return;
+ return 0;
ns->features |= NVME_NS_EXT_LBAS;
@@ -1859,6 +1860,7 @@ static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id)
else
ns->features |= NVME_NS_METADATA_SUPPORTED;
}
+ return 0;
}
static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
@@ -2032,7 +2034,11 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
ns->lba_shift = id->lbaf[lbaf].ds;
nvme_set_queue_limits(ns->ctrl, ns->queue);
- nvme_configure_metadata(ns, id);
+ ret = nvme_configure_metadata(ns, id);
+ if (ret < 0) {
+ blk_mq_unfreeze_queue(ns->disk->queue);
+ goto out;
+ }
nvme_set_chunk_sectors(ns, id);
nvme_update_disk_info(ns->disk, ns, id);
@@ -4348,6 +4354,7 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
{
nvme_mpath_stop(ctrl);
nvme_auth_stop(ctrl);
+ nvme_stop_keep_alive(ctrl);
nvme_stop_failfast_work(ctrl);
flush_work(&ctrl->async_event_work);
cancel_work_sync(&ctrl->fw_act_work);
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 4673ead69c5..aa88606a44c 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -667,8 +667,10 @@ static const match_table_t opt_tokens = {
#endif
{ NVMF_OPT_FAIL_FAST_TMO, "fast_io_fail_tmo=%d" },
{ NVMF_OPT_DISCOVERY, "discovery" },
+#ifdef CONFIG_NVME_HOST_AUTH
{ NVMF_OPT_DHCHAP_SECRET, "dhchap_secret=%s" },
{ NVMF_OPT_DHCHAP_CTRL_SECRET, "dhchap_ctrl_secret=%s" },
+#endif
#ifdef CONFIG_NVME_TCP_TLS
{ NVMF_OPT_TLS, "tls" },
#endif
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 49c3e46eaa1..9f9a3b35dc6 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -2530,12 +2530,6 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
* clean up the admin queue. Same thing as above.
*/
nvme_quiesce_admin_queue(&ctrl->ctrl);
-
- /*
- * Open-coding nvme_cancel_admin_tagset() as fc
- * is not using nvme_cancel_request().
- */
- nvme_stop_keep_alive(&ctrl->ctrl);
blk_sync_queue(ctrl->ctrl.admin_q);
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
nvme_fc_terminate_exchange, &ctrl->ctrl);
@@ -3138,11 +3132,12 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
nvme_unquiesce_admin_queue(&ctrl->ctrl);
ret = nvme_init_ctrl_finish(&ctrl->ctrl, false);
- if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
- ret = -EIO;
if (ret)
goto out_disconnect_admin_queue;
-
+ if (test_bit(ASSOC_FAILED, &ctrl->flags)) {
+ ret = -EIO;
+ goto out_stop_keep_alive;
+ }
/* sanity checks */
/* FC-NVME does not have other data in the capsule */
@@ -3150,7 +3145,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n",
ctrl->ctrl.icdoff);
ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
- goto out_disconnect_admin_queue;
+ goto out_stop_keep_alive;
}
/* FC-NVME supports normal SGL Data Block Descriptors */
@@ -3158,7 +3153,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
dev_err(ctrl->ctrl.device,
"Mandatory sgls are not supported!\n");
ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
- goto out_disconnect_admin_queue;
+ goto out_stop_keep_alive;
}
if (opts->queue_size > ctrl->ctrl.maxcmd) {
@@ -3205,6 +3200,8 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
out_term_aen_ops:
nvme_fc_term_aen_ops(ctrl);
+out_stop_keep_alive:
+ nvme_stop_keep_alive(&ctrl->ctrl);
out_disconnect_admin_queue:
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n",
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index a7fea4cbacd..6d178d55592 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -1080,6 +1080,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
nvme_rdma_free_io_queues(ctrl);
}
destroy_admin:
+ nvme_stop_keep_alive(&ctrl->ctrl);
nvme_quiesce_admin_queue(&ctrl->ctrl);
blk_sync_queue(ctrl->ctrl.admin_q);
nvme_rdma_stop_queue(&ctrl->queues[0]);
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 89661a9cf85..d79811cfa0c 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -36,11 +36,11 @@ static int so_priority;
module_param(so_priority, int, 0644);
MODULE_PARM_DESC(so_priority, "nvme tcp socket optimize priority");
-#ifdef CONFIG_NVME_TCP_TLS
/*
* TLS handshake timeout
*/
static int tls_handshake_timeout = 10;
+#ifdef CONFIG_NVME_TCP_TLS
module_param(tls_handshake_timeout, int, 0644);
MODULE_PARM_DESC(tls_handshake_timeout,
"nvme TLS handshake timeout in seconds (default 10)");
@@ -161,10 +161,8 @@ struct nvme_tcp_queue {
struct ahash_request *snd_hash;
__le32 exp_ddgst;
__le32 recv_ddgst;
-#ifdef CONFIG_NVME_TCP_TLS
struct completion tls_complete;
int tls_err;
-#endif
struct page_frag_cache pf_cache;
void (*state_change)(struct sock *);
@@ -207,6 +205,14 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)
return queue - queue->ctrl->queues;
}
+static inline bool nvme_tcp_tls(struct nvme_ctrl *ctrl)
+{
+ if (!IS_ENABLED(CONFIG_NVME_TCP_TLS))
+ return 0;
+
+ return ctrl->opts->tls;
+}
+
static inline struct blk_mq_tags *nvme_tcp_tagset(struct nvme_tcp_queue *queue)
{
u32 queue_idx = nvme_tcp_queue_id(queue);
@@ -1412,7 +1418,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
memset(&msg, 0, sizeof(msg));
iov.iov_base = icresp;
iov.iov_len = sizeof(*icresp);
- if (queue->ctrl->ctrl.opts->tls) {
+ if (nvme_tcp_tls(&queue->ctrl->ctrl)) {
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
}
@@ -1424,7 +1430,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
goto free_icresp;
}
ret = -ENOTCONN;
- if (queue->ctrl->ctrl.opts->tls) {
+ if (nvme_tcp_tls(&queue->ctrl->ctrl)) {
ctype = tls_get_record_type(queue->sock->sk,
(struct cmsghdr *)cbuf);
if (ctype != TLS_RECORD_TYPE_DATA) {
@@ -1548,7 +1554,6 @@ static void nvme_tcp_set_queue_io_cpu(struct nvme_tcp_queue *queue)
queue->io_cpu = cpumask_next_wrap(n - 1, cpu_online_mask, -1, false);
}
-#ifdef CONFIG_NVME_TCP_TLS
static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
{
struct nvme_tcp_queue *queue = data;
@@ -1625,14 +1630,6 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
}
return ret;
}
-#else
-static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
- struct nvme_tcp_queue *queue,
- key_serial_t pskid)
-{
- return -EPROTONOSUPPORT;
-}
-#endif
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
key_serial_t pskid)
@@ -1759,7 +1756,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
}
/* If PSKs are configured try to start TLS */
- if (pskid) {
+ if (IS_ENABLED(CONFIG_NVME_TCP_TLS) && pskid) {
ret = nvme_tcp_start_tls(nctrl, queue, pskid);
if (ret)
goto err_init_connect;
@@ -1916,7 +1913,7 @@ static int nvme_tcp_alloc_admin_queue(struct nvme_ctrl *ctrl)
int ret;
key_serial_t pskid = 0;
- if (ctrl->opts->tls) {
+ if (nvme_tcp_tls(ctrl)) {
if (ctrl->opts->tls_key)
pskid = key_serial(ctrl->opts->tls_key);
else
@@ -1949,7 +1946,7 @@ static int __nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
{
int i, ret;
- if (ctrl->opts->tls && !ctrl->tls_key) {
+ if (nvme_tcp_tls(ctrl) && !ctrl->tls_key) {
dev_err(ctrl->device, "no PSK negotiated\n");
return -ENOKEY;
}
@@ -2237,6 +2234,7 @@ static int nvme_tcp_setup_ctrl(struct nvme_ctrl *ctrl, bool new)
nvme_tcp_destroy_io_queues(ctrl, new);
}
destroy_admin:
+ nvme_stop_keep_alive(ctrl);
nvme_tcp_teardown_admin_queue(ctrl, false);
return ret;
}
diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig
index 31633da9427..e1ebc73f3e5 100644
--- a/drivers/nvme/target/Kconfig
+++ b/drivers/nvme/target/Kconfig
@@ -4,6 +4,8 @@ config NVME_TARGET
tristate "NVMe Target support"
depends on BLOCK
depends on CONFIGFS_FS
+ select NVME_KEYRING if NVME_TARGET_TCP_TLS
+ select KEYS if NVME_TARGET_TCP_TLS
select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
select SGL_ALLOC
help
@@ -87,9 +89,7 @@ config NVME_TARGET_TCP
config NVME_TARGET_TCP_TLS
bool "NVMe over Fabrics TCP target TLS encryption support"
depends on NVME_TARGET_TCP
- select NVME_KEYRING
select NET_HANDSHAKE
- select KEYS
help
Enables TLS encryption for the NVMe TCP target using the netlink handshake API.
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 9eed6e6765e..e307a044b1a 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1893,7 +1893,7 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
return ERR_PTR(-ENOMEM);
}
- if (nvme_keyring_id()) {
+ if (IS_ENABLED(CONFIG_NVME_TARGET_TCP_TLS) && nvme_keyring_id()) {
port->keyring = key_lookup(nvme_keyring_id());
if (IS_ERR(port->keyring)) {
pr_warn("NVMe keyring not available, disabling TLS\n");
diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index 43b5bd8bb6a..d8da840a1c0 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -244,6 +244,8 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
goto out;
}
+ d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+ d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req,
le32_to_cpu(c->kato), &ctrl);
if (status)
@@ -313,6 +315,8 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
goto out;
}
+ d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+ d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
ctrl = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn,
le16_to_cpu(d->cntlid), req);
if (!ctrl) {
diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index 92b74d0b868..4cc27856aa8 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -1854,6 +1854,8 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue)
}
return ret;
}
+#else
+static void nvmet_tcp_tls_handshake_timeout(struct work_struct *w) {}
#endif
static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
@@ -1911,9 +1913,9 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port,
list_add_tail(&queue->queue_list, &nvmet_tcp_queue_list);
mutex_unlock(&nvmet_tcp_queue_mutex);
-#ifdef CONFIG_NVME_TARGET_TCP_TLS
INIT_DELAYED_WORK(&queue->tls_handshake_tmo_work,
nvmet_tcp_tls_handshake_timeout);
+#ifdef CONFIG_NVME_TARGET_TCP_TLS
if (queue->state == NVMET_TCP_Q_TLS_HANDSHAKE) {
struct sock *sk = queue->sock->sk;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 787354b849c..4cef568231b 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -87,7 +87,6 @@ source "drivers/phy/motorola/Kconfig"
source "drivers/phy/mscc/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
-source "drivers/phy/realtek/Kconfig"
source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 868a220ed0f..fb3dc9de611 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -26,7 +26,6 @@ obj-y += allwinner/ \
mscc/ \
qualcomm/ \
ralink/ \
- realtek/ \
renesas/ \
rockchip/ \
samsung/ \
diff --git a/drivers/phy/realtek/Kconfig b/drivers/phy/realtek/Kconfig
deleted file mode 100644
index 75ac7e7c31a..00000000000
--- a/drivers/phy/realtek/Kconfig
+++ /dev/null
@@ -1,32 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Phy drivers for Realtek platforms
-#
-
-if ARCH_REALTEK || COMPILE_TEST
-
-config PHY_RTK_RTD_USB2PHY
- tristate "Realtek RTD USB2 PHY Transceiver Driver"
- depends on USB_SUPPORT
- select GENERIC_PHY
- select USB_PHY
- select USB_COMMON
- help
- Enable this to support Realtek SoC USB2 phy transceiver.
- The DHC (digital home center) RTD series SoCs used the Synopsys
- DWC3 USB IP. This driver will do the PHY initialization
- of the parameters.
-
-config PHY_RTK_RTD_USB3PHY
- tristate "Realtek RTD USB3 PHY Transceiver Driver"
- depends on USB_SUPPORT
- select GENERIC_PHY
- select USB_PHY
- select USB_COMMON
- help
- Enable this to support Realtek SoC USB3 phy transceiver.
- The DHC (digital home center) RTD series SoCs used the Synopsys
- DWC3 USB IP. This driver will do the PHY initialization
- of the parameters.
-
-endif # ARCH_REALTEK || COMPILE_TEST
diff --git a/drivers/phy/realtek/Makefile b/drivers/phy/realtek/Makefile
deleted file mode 100644
index ed7b47ff8a2..00000000000
--- a/drivers/phy/realtek/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_PHY_RTK_RTD_USB2PHY) += phy-rtk-usb2.o
-obj-$(CONFIG_PHY_RTK_RTD_USB3PHY) += phy-rtk-usb3.o
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
deleted file mode 100644
index 0a6426285c6..00000000000
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ /dev/null
@@ -1,1325 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * phy-rtk-usb2.c RTK usb2.0 PHY driver
- *
- * Copyright (C) 2023 Realtek Semiconductor Corporation
- *
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/regmap.h>
-#include <linux/sys_soc.h>
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-#include <linux/usb.h>
-#include <linux/usb/phy.h>
-#include <linux/usb/hcd.h>
-
-/* GUSB2PHYACCn register */
-#define PHY_NEW_REG_REQ BIT(25)
-#define PHY_VSTS_BUSY BIT(23)
-#define PHY_VCTRL_SHIFT 8
-#define PHY_REG_DATA_MASK 0xff
-
-#define GET_LOW_NIBBLE(addr) ((addr) & 0x0f)
-#define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4)
-
-#define EFUS_USB_DC_CAL_RATE 2
-#define EFUS_USB_DC_CAL_MAX 7
-
-#define EFUS_USB_DC_DIS_RATE 1
-#define EFUS_USB_DC_DIS_MAX 7
-
-#define MAX_PHY_DATA_SIZE 20
-#define OFFEST_PHY_READ 0x20
-
-#define MAX_USB_PHY_NUM 4
-#define MAX_USB_PHY_PAGE0_DATA_SIZE 16
-#define MAX_USB_PHY_PAGE1_DATA_SIZE 16
-#define MAX_USB_PHY_PAGE2_DATA_SIZE 8
-
-#define SET_PAGE_OFFSET 0xf4
-#define SET_PAGE_0 0x9b
-#define SET_PAGE_1 0xbb
-#define SET_PAGE_2 0xdb
-
-#define PAGE_START 0xe0
-#define PAGE0_0XE4 0xe4
-#define PAGE0_0XE6 0xe6
-#define PAGE0_0XE7 0xe7
-#define PAGE1_0XE0 0xe0
-#define PAGE1_0XE2 0xe2
-
-#define SENSITIVITY_CTRL (BIT(4) | BIT(5) | BIT(6))
-#define ENABLE_AUTO_SENSITIVITY_CALIBRATION BIT(2)
-#define DEFAULT_DC_DRIVING_VALUE (0x8)
-#define DEFAULT_DC_DISCONNECTION_VALUE (0x6)
-#define HS_CLK_SELECT BIT(6)
-
-struct phy_reg {
- void __iomem *reg_wrap_vstatus;
- void __iomem *reg_gusb2phyacc0;
- int vstatus_index;
-};
-
-struct phy_data {
- u8 addr;
- u8 data;
-};
-
-struct phy_cfg {
- int page0_size;
- struct phy_data page0[MAX_USB_PHY_PAGE0_DATA_SIZE];
- int page1_size;
- struct phy_data page1[MAX_USB_PHY_PAGE1_DATA_SIZE];
- int page2_size;
- struct phy_data page2[MAX_USB_PHY_PAGE2_DATA_SIZE];
-
- int num_phy;
-
- bool check_efuse;
- int check_efuse_version;
-#define CHECK_EFUSE_V1 1
-#define CHECK_EFUSE_V2 2
- int efuse_dc_driving_rate;
- int efuse_dc_disconnect_rate;
- int dc_driving_mask;
- int dc_disconnect_mask;
- bool usb_dc_disconnect_at_page0;
- int driving_updated_for_dev_dis;
-
- bool do_toggle;
- bool do_toggle_driving;
- bool use_default_parameter;
- bool is_double_sensitivity_mode;
-};
-
-struct phy_parameter {
- struct phy_reg phy_reg;
-
- /* Get from efuse */
- s8 efuse_usb_dc_cal;
- s8 efuse_usb_dc_dis;
-
- /* Get from dts */
- bool inverse_hstx_sync_clock;
- u32 driving_level;
- s32 driving_level_compensate;
- s32 disconnection_compensate;
-};
-
-struct rtk_phy {
- struct usb_phy phy;
- struct device *dev;
-
- struct phy_cfg *phy_cfg;
- int num_phy;
- struct phy_parameter *phy_parameter;
-
- struct dentry *debug_dir;
-};
-
-/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
-static inline int page_addr_to_array_index(u8 addr)
-{
- return (int)((((addr) - PAGE_START) & 0x7) +
- ((((addr) - PAGE_START) & 0x10) >> 1));
-}
-
-static inline u8 array_index_to_page_addr(int index)
-{
- return ((((index) + PAGE_START) & 0x7) +
- ((((index) & 0x8) << 1) + PAGE_START));
-}
-
-#define PHY_IO_TIMEOUT_USEC (50000)
-#define PHY_IO_DELAY_US (100)
-
-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
-{
- int ret;
- unsigned int val;
-
- ret = read_poll_timeout(readl, val, ((val & mask) == result),
- PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
- if (ret) {
- pr_err("%s can't program USB phy\n", __func__);
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
-{
- void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
- unsigned int val;
- int ret = 0;
-
- addr -= OFFEST_PHY_READ;
-
- /* polling until VBusy == 0 */
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
- if (ret)
- return (char)ret;
-
- /* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
- if (ret)
- return (char)ret;
-
- /* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
- if (ret)
- return (char)ret;
-
- val = readl(reg_gusb2phyacc0);
-
- return (char)(val & PHY_REG_DATA_MASK);
-}
-
-static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
-{
- unsigned int val;
- void __iomem *reg_wrap_vstatus = phy_reg->reg_wrap_vstatus;
- void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
- int shift_bits = phy_reg->vstatus_index * 8;
- int ret = 0;
-
- /* write data to VStatusOut2 (data output to phy) */
- writel((u32)data << shift_bits, reg_wrap_vstatus);
-
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
- if (ret)
- return ret;
-
- /* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
-
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
- if (ret)
- return ret;
-
- /* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
-
- writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static int rtk_phy_set_page(struct phy_reg *phy_reg, int page)
-{
- switch (page) {
- case 0:
- return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_0);
- case 1:
- return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_1);
- case 2:
- return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_2);
- default:
- pr_err("%s error page=%d\n", __func__, page);
- }
-
- return -EINVAL;
-}
-
-static u8 __updated_dc_disconnect_level_page0_0xe4(struct phy_cfg *phy_cfg,
- struct phy_parameter *phy_parameter, u8 data)
-{
- u8 ret;
- s32 val;
- s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
- int offset = 4;
-
- val = (s32)((data >> offset) & dc_disconnect_mask)
- + phy_parameter->efuse_usb_dc_dis
- + phy_parameter->disconnection_compensate;
-
- if (val > dc_disconnect_mask)
- val = dc_disconnect_mask;
- else if (val < 0)
- val = 0;
-
- ret = (data & (~(dc_disconnect_mask << offset))) |
- (val & dc_disconnect_mask) << offset;
-
- return ret;
-}
-
-/* updated disconnect level at page0 */
-static void update_dc_disconnect_level_at_page0(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter, bool update)
-{
- struct phy_cfg *phy_cfg;
- struct phy_reg *phy_reg;
- struct phy_data *phy_data_page;
- struct phy_data *phy_data;
- u8 addr, data;
- int offset = 4;
- s32 dc_disconnect_mask;
- int i;
-
- phy_cfg = rtk_phy->phy_cfg;
- phy_reg = &phy_parameter->phy_reg;
-
- /* Set page 0 */
- phy_data_page = phy_cfg->page0;
- rtk_phy_set_page(phy_reg, 0);
-
- i = page_addr_to_array_index(PAGE0_0XE4);
- phy_data = phy_data_page + i;
- if (!phy_data->addr) {
- phy_data->addr = PAGE0_0XE4;
- phy_data->data = rtk_phy_read(phy_reg, PAGE0_0XE4);
- }
-
- addr = phy_data->addr;
- data = phy_data->data;
- dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-
- if (update)
- data = __updated_dc_disconnect_level_page0_0xe4(phy_cfg, phy_parameter, data);
- else
- data = (data & ~(dc_disconnect_mask << offset)) |
- (DEFAULT_DC_DISCONNECTION_VALUE << offset);
-
- if (rtk_phy_write(phy_reg, addr, data))
- dev_err(rtk_phy->dev,
- "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
- __func__, addr, data);
-}
-
-static u8 __updated_dc_disconnect_level_page1_0xe2(struct phy_cfg *phy_cfg,
- struct phy_parameter *phy_parameter, u8 data)
-{
- u8 ret;
- s32 val;
- s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-
- if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
- val = (s32)(data & dc_disconnect_mask)
- + phy_parameter->efuse_usb_dc_dis
- + phy_parameter->disconnection_compensate;
- } else { /* for CHECK_EFUSE_V2 or no efuse */
- if (phy_parameter->efuse_usb_dc_dis)
- val = (s32)(phy_parameter->efuse_usb_dc_dis +
- phy_parameter->disconnection_compensate);
- else
- val = (s32)((data & dc_disconnect_mask) +
- phy_parameter->disconnection_compensate);
- }
-
- if (val > dc_disconnect_mask)
- val = dc_disconnect_mask;
- else if (val < 0)
- val = 0;
-
- ret = (data & (~dc_disconnect_mask)) | (val & dc_disconnect_mask);
-
- return ret;
-}
-
-/* updated disconnect level at page1 */
-static void update_dc_disconnect_level_at_page1(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter, bool update)
-{
- struct phy_cfg *phy_cfg;
- struct phy_data *phy_data_page;
- struct phy_data *phy_data;
- struct phy_reg *phy_reg;
- u8 addr, data;
- s32 dc_disconnect_mask;
- int i;
-
- phy_cfg = rtk_phy->phy_cfg;
- phy_reg = &phy_parameter->phy_reg;
-
- /* Set page 1 */
- phy_data_page = phy_cfg->page1;
- rtk_phy_set_page(phy_reg, 1);
-
- i = page_addr_to_array_index(PAGE1_0XE2);
- phy_data = phy_data_page + i;
- if (!phy_data->addr) {
- phy_data->addr = PAGE1_0XE2;
- phy_data->data = rtk_phy_read(phy_reg, PAGE1_0XE2);
- }
-
- addr = phy_data->addr;
- data = phy_data->data;
- dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
-
- if (update)
- data = __updated_dc_disconnect_level_page1_0xe2(phy_cfg, phy_parameter, data);
- else
- data = (data & ~dc_disconnect_mask) | DEFAULT_DC_DISCONNECTION_VALUE;
-
- if (rtk_phy_write(phy_reg, addr, data))
- dev_err(rtk_phy->dev,
- "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
- __func__, addr, data);
-}
-
-static void update_dc_disconnect_level(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter, bool update)
-{
- struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
-
- if (phy_cfg->usb_dc_disconnect_at_page0)
- update_dc_disconnect_level_at_page0(rtk_phy, phy_parameter, update);
- else
- update_dc_disconnect_level_at_page1(rtk_phy, phy_parameter, update);
-}
-
-static u8 __update_dc_driving_page0_0xe4(struct phy_cfg *phy_cfg,
- struct phy_parameter *phy_parameter, u8 data)
-{
- s32 driving_level_compensate = phy_parameter->driving_level_compensate;
- s32 dc_driving_mask = phy_cfg->dc_driving_mask;
- s32 val;
- u8 ret;
-
- if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
- val = (s32)(data & dc_driving_mask) + driving_level_compensate
- + phy_parameter->efuse_usb_dc_cal;
- } else { /* for CHECK_EFUSE_V2 or no efuse */
- if (phy_parameter->efuse_usb_dc_cal)
- val = (s32)((phy_parameter->efuse_usb_dc_cal & dc_driving_mask)
- + driving_level_compensate);
- else
- val = (s32)(data & dc_driving_mask);
- }
-
- if (val > dc_driving_mask)
- val = dc_driving_mask;
- else if (val < 0)
- val = 0;
-
- ret = (data & (~dc_driving_mask)) | (val & dc_driving_mask);
-
- return ret;
-}
-
-static void update_dc_driving_level(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter)
-{
- struct phy_cfg *phy_cfg;
- struct phy_reg *phy_reg;
-
- phy_reg = &phy_parameter->phy_reg;
- phy_cfg = rtk_phy->phy_cfg;
- if (!phy_cfg->page0[4].addr) {
- rtk_phy_set_page(phy_reg, 0);
- phy_cfg->page0[4].addr = PAGE0_0XE4;
- phy_cfg->page0[4].data = rtk_phy_read(phy_reg, PAGE0_0XE4);
- }
-
- if (phy_parameter->driving_level != DEFAULT_DC_DRIVING_VALUE) {
- u32 dc_driving_mask;
- u8 driving_level;
- u8 data;
-
- data = phy_cfg->page0[4].data;
- dc_driving_mask = phy_cfg->dc_driving_mask;
- driving_level = data & dc_driving_mask;
-
- dev_dbg(rtk_phy->dev, "%s driving_level=%d => dts driving_level=%d\n",
- __func__, driving_level, phy_parameter->driving_level);
-
- phy_cfg->page0[4].data = (data & (~dc_driving_mask)) |
- (phy_parameter->driving_level & dc_driving_mask);
- }
-
- phy_cfg->page0[4].data = __update_dc_driving_page0_0xe4(phy_cfg,
- phy_parameter,
- phy_cfg->page0[4].data);
-}
-
-static void update_hs_clk_select(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter)
-{
- struct phy_cfg *phy_cfg;
- struct phy_reg *phy_reg;
-
- phy_cfg = rtk_phy->phy_cfg;
- phy_reg = &phy_parameter->phy_reg;
-
- if (phy_parameter->inverse_hstx_sync_clock) {
- if (!phy_cfg->page0[6].addr) {
- rtk_phy_set_page(phy_reg, 0);
- phy_cfg->page0[6].addr = PAGE0_0XE6;
- phy_cfg->page0[6].data = rtk_phy_read(phy_reg, PAGE0_0XE6);
- }
-
- phy_cfg->page0[6].data = phy_cfg->page0[6].data | HS_CLK_SELECT;
- }
-}
-
-static void do_rtk_phy_toggle(struct rtk_phy *rtk_phy,
- int index, bool connect)
-{
- struct phy_parameter *phy_parameter;
- struct phy_cfg *phy_cfg;
- struct phy_reg *phy_reg;
- struct phy_data *phy_data_page;
- u8 addr, data;
- int i;
-
- phy_cfg = rtk_phy->phy_cfg;
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
- phy_reg = &phy_parameter->phy_reg;
-
- if (!phy_cfg->do_toggle)
- goto out;
-
- if (phy_cfg->is_double_sensitivity_mode)
- goto do_toggle_driving;
-
- /* Set page 0 */
- rtk_phy_set_page(phy_reg, 0);
-
- addr = PAGE0_0XE7;
- data = rtk_phy_read(phy_reg, addr);
-
- if (connect)
- rtk_phy_write(phy_reg, addr, data & (~SENSITIVITY_CTRL));
- else
- rtk_phy_write(phy_reg, addr, data | (SENSITIVITY_CTRL));
-
-do_toggle_driving:
-
- if (!phy_cfg->do_toggle_driving)
- goto do_toggle;
-
- /* Page 0 addr 0xE4 driving capability */
-
- /* Set page 0 */
- phy_data_page = phy_cfg->page0;
- rtk_phy_set_page(phy_reg, 0);
-
- i = page_addr_to_array_index(PAGE0_0XE4);
- addr = phy_data_page[i].addr;
- data = phy_data_page[i].data;
-
- if (connect) {
- rtk_phy_write(phy_reg, addr, data);
- } else {
- u8 value;
- s32 tmp;
- s32 driving_updated =
- phy_cfg->driving_updated_for_dev_dis;
- s32 dc_driving_mask = phy_cfg->dc_driving_mask;
-
- tmp = (s32)(data & dc_driving_mask) + driving_updated;
-
- if (tmp > dc_driving_mask)
- tmp = dc_driving_mask;
- else if (tmp < 0)
- tmp = 0;
-
- value = (data & (~dc_driving_mask)) | (tmp & dc_driving_mask);
-
- rtk_phy_write(phy_reg, addr, value);
- }
-
-do_toggle:
- /* restore dc disconnect level before toggle */
- update_dc_disconnect_level(rtk_phy, phy_parameter, false);
-
- /* Set page 1 */
- rtk_phy_set_page(phy_reg, 1);
-
- addr = PAGE1_0XE0;
- data = rtk_phy_read(phy_reg, addr);
-
- rtk_phy_write(phy_reg, addr, data &
- (~ENABLE_AUTO_SENSITIVITY_CALIBRATION));
- mdelay(1);
- rtk_phy_write(phy_reg, addr, data |
- (ENABLE_AUTO_SENSITIVITY_CALIBRATION));
-
- /* update dc disconnect level after toggle */
- update_dc_disconnect_level(rtk_phy, phy_parameter, true);
-
-out:
- return;
-}
-
-static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
-{
- struct phy_parameter *phy_parameter;
- struct phy_cfg *phy_cfg;
- struct phy_data *phy_data_page;
- struct phy_reg *phy_reg;
- int i;
-
- phy_cfg = rtk_phy->phy_cfg;
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
- phy_reg = &phy_parameter->phy_reg;
-
- if (phy_cfg->use_default_parameter) {
- dev_dbg(rtk_phy->dev, "%s phy#%d use default parameter\n",
- __func__, index);
- goto do_toggle;
- }
-
- /* Set page 0 */
- phy_data_page = phy_cfg->page0;
- rtk_phy_set_page(phy_reg, 0);
-
- for (i = 0; i < phy_cfg->page0_size; i++) {
- struct phy_data *phy_data = phy_data_page + i;
- u8 addr = phy_data->addr;
- u8 data = phy_data->data;
-
- if (!addr)
- continue;
-
- if (rtk_phy_write(phy_reg, addr, data)) {
- dev_err(rtk_phy->dev,
- "%s: Error to set page0 parameter addr=0x%x value=0x%x\n",
- __func__, addr, data);
- return -EINVAL;
- }
- }
-
- /* Set page 1 */
- phy_data_page = phy_cfg->page1;
- rtk_phy_set_page(phy_reg, 1);
-
- for (i = 0; i < phy_cfg->page1_size; i++) {
- struct phy_data *phy_data = phy_data_page + i;
- u8 addr = phy_data->addr;
- u8 data = phy_data->data;
-
- if (!addr)
- continue;
-
- if (rtk_phy_write(phy_reg, addr, data)) {
- dev_err(rtk_phy->dev,
- "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
- __func__, addr, data);
- return -EINVAL;
- }
- }
-
- if (phy_cfg->page2_size == 0)
- goto do_toggle;
-
- /* Set page 2 */
- phy_data_page = phy_cfg->page2;
- rtk_phy_set_page(phy_reg, 2);
-
- for (i = 0; i < phy_cfg->page2_size; i++) {
- struct phy_data *phy_data = phy_data_page + i;
- u8 addr = phy_data->addr;
- u8 data = phy_data->data;
-
- if (!addr)
- continue;
-
- if (rtk_phy_write(phy_reg, addr, data)) {
- dev_err(rtk_phy->dev,
- "%s: Error to set page2 parameter addr=0x%x value=0x%x\n",
- __func__, addr, data);
- return -EINVAL;
- }
- }
-
-do_toggle:
- do_rtk_phy_toggle(rtk_phy, index, false);
-
- return 0;
-}
-
-static int rtk_phy_init(struct phy *phy)
-{
- struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
- unsigned long phy_init_time = jiffies;
- int i, ret = 0;
-
- if (!rtk_phy)
- return -EINVAL;
-
- for (i = 0; i < rtk_phy->num_phy; i++)
- ret = do_rtk_phy_init(rtk_phy, i);
-
- dev_dbg(rtk_phy->dev, "Initialized RTK USB 2.0 PHY (take %dms)\n",
- jiffies_to_msecs(jiffies - phy_init_time));
- return ret;
-}
-
-static int rtk_phy_exit(struct phy *phy)
-{
- return 0;
-}
-
-static const struct phy_ops ops = {
- .init = rtk_phy_init,
- .exit = rtk_phy_exit,
- .owner = THIS_MODULE,
-};
-
-static void rtk_phy_toggle(struct usb_phy *usb2_phy, bool connect, int port)
-{
- int index = port;
- struct rtk_phy *rtk_phy = NULL;
-
- rtk_phy = dev_get_drvdata(usb2_phy->dev);
-
- if (index > rtk_phy->num_phy) {
- dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
- __func__, index, rtk_phy->num_phy);
- return;
- }
-
- do_rtk_phy_toggle(rtk_phy, index, connect);
-}
-
-static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
- u16 portstatus, u16 portchange)
-{
- bool connect = false;
-
- pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
- __func__, port, (int)portstatus, (int)portchange);
- if (portstatus & USB_PORT_STAT_CONNECTION)
- connect = true;
-
- if (portchange & USB_PORT_STAT_C_CONNECTION)
- rtk_phy_toggle(x, connect, port);
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *create_phy_debug_root(void)
-{
- struct dentry *phy_debug_root;
-
- phy_debug_root = debugfs_lookup("phy", usb_debug_root);
- if (!phy_debug_root)
- phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
-
- return phy_debug_root;
-}
-
-static int rtk_usb2_parameter_show(struct seq_file *s, void *unused)
-{
- struct rtk_phy *rtk_phy = s->private;
- struct phy_cfg *phy_cfg;
- int i, index;
-
- phy_cfg = rtk_phy->phy_cfg;
-
- seq_puts(s, "Property:\n");
- seq_printf(s, " check_efuse: %s\n",
- phy_cfg->check_efuse ? "Enable" : "Disable");
- seq_printf(s, " check_efuse_version: %d\n",
- phy_cfg->check_efuse_version);
- seq_printf(s, " efuse_dc_driving_rate: %d\n",
- phy_cfg->efuse_dc_driving_rate);
- seq_printf(s, " dc_driving_mask: 0x%x\n",
- phy_cfg->dc_driving_mask);
- seq_printf(s, " efuse_dc_disconnect_rate: %d\n",
- phy_cfg->efuse_dc_disconnect_rate);
- seq_printf(s, " dc_disconnect_mask: 0x%x\n",
- phy_cfg->dc_disconnect_mask);
- seq_printf(s, " usb_dc_disconnect_at_page0: %s\n",
- phy_cfg->usb_dc_disconnect_at_page0 ? "true" : "false");
- seq_printf(s, " do_toggle: %s\n",
- phy_cfg->do_toggle ? "Enable" : "Disable");
- seq_printf(s, " do_toggle_driving: %s\n",
- phy_cfg->do_toggle_driving ? "Enable" : "Disable");
- seq_printf(s, " driving_updated_for_dev_dis: 0x%x\n",
- phy_cfg->driving_updated_for_dev_dis);
- seq_printf(s, " use_default_parameter: %s\n",
- phy_cfg->use_default_parameter ? "Enable" : "Disable");
- seq_printf(s, " is_double_sensitivity_mode: %s\n",
- phy_cfg->is_double_sensitivity_mode ? "Enable" : "Disable");
-
- for (index = 0; index < rtk_phy->num_phy; index++) {
- struct phy_parameter *phy_parameter;
- struct phy_reg *phy_reg;
- struct phy_data *phy_data_page;
-
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
- phy_reg = &phy_parameter->phy_reg;
-
- seq_printf(s, "PHY %d:\n", index);
-
- seq_puts(s, "Page 0:\n");
- /* Set page 0 */
- phy_data_page = phy_cfg->page0;
- rtk_phy_set_page(phy_reg, 0);
-
- for (i = 0; i < phy_cfg->page0_size; i++) {
- struct phy_data *phy_data = phy_data_page + i;
- u8 addr = array_index_to_page_addr(i);
- u8 data = phy_data->data;
- u8 value = rtk_phy_read(phy_reg, addr);
-
- if (phy_data->addr)
- seq_printf(s, " Page 0: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
- addr, data, value);
- else
- seq_printf(s, " Page 0: addr=0x%x data=none ==> read value=0x%02x\n",
- addr, value);
- }
-
- seq_puts(s, "Page 1:\n");
- /* Set page 1 */
- phy_data_page = phy_cfg->page1;
- rtk_phy_set_page(phy_reg, 1);
-
- for (i = 0; i < phy_cfg->page1_size; i++) {
- struct phy_data *phy_data = phy_data_page + i;
- u8 addr = array_index_to_page_addr(i);
- u8 data = phy_data->data;
- u8 value = rtk_phy_read(phy_reg, addr);
-
- if (phy_data->addr)
- seq_printf(s, " Page 1: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
- addr, data, value);
- else
- seq_printf(s, " Page 1: addr=0x%x data=none ==> read value=0x%02x\n",
- addr, value);
- }
-
- if (phy_cfg->page2_size == 0)
- goto out;
-
- seq_puts(s, "Page 2:\n");
- /* Set page 2 */
- phy_data_page = phy_cfg->page2;
- rtk_phy_set_page(phy_reg, 2);
-
- for (i = 0; i < phy_cfg->page2_size; i++) {
- struct phy_data *phy_data = phy_data_page + i;
- u8 addr = array_index_to_page_addr(i);
- u8 data = phy_data->data;
- u8 value = rtk_phy_read(phy_reg, addr);
-
- if (phy_data->addr)
- seq_printf(s, " Page 2: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
- addr, data, value);
- else
- seq_printf(s, " Page 2: addr=0x%x data=none ==> read value=0x%02x\n",
- addr, value);
- }
-
-out:
- seq_puts(s, "PHY Property:\n");
- seq_printf(s, " efuse_usb_dc_cal: %d\n",
- (int)phy_parameter->efuse_usb_dc_cal);
- seq_printf(s, " efuse_usb_dc_dis: %d\n",
- (int)phy_parameter->efuse_usb_dc_dis);
- seq_printf(s, " inverse_hstx_sync_clock: %s\n",
- phy_parameter->inverse_hstx_sync_clock ? "Enable" : "Disable");
- seq_printf(s, " driving_level: %d\n",
- phy_parameter->driving_level);
- seq_printf(s, " driving_level_compensate: %d\n",
- phy_parameter->driving_level_compensate);
- seq_printf(s, " disconnection_compensate: %d\n",
- phy_parameter->disconnection_compensate);
- }
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(rtk_usb2_parameter);
-
-static inline void create_debug_files(struct rtk_phy *rtk_phy)
-{
- struct dentry *phy_debug_root = NULL;
-
- phy_debug_root = create_phy_debug_root();
- if (!phy_debug_root)
- return;
-
- rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev),
- phy_debug_root);
-
- debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
- &rtk_usb2_parameter_fops);
-
- return;
-}
-
-static inline void remove_debug_files(struct rtk_phy *rtk_phy)
-{
- debugfs_remove_recursive(rtk_phy->debug_dir);
-}
-#else
-static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
-static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
-#endif /* CONFIG_DEBUG_FS */
-
-static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter, int index)
-{
- struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
- u8 value = 0;
- struct nvmem_cell *cell;
- struct soc_device_attribute rtk_soc_groot[] = {
- { .family = "Realtek Groot",},
- { /* empty */ } };
-
- if (!phy_cfg->check_efuse)
- goto out;
-
- /* Read efuse for usb dc cal */
- cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-cal");
- if (IS_ERR(cell)) {
- dev_dbg(rtk_phy->dev, "%s no usb-dc-cal: %ld\n",
- __func__, PTR_ERR(cell));
- } else {
- unsigned char *buf;
- size_t buf_size;
-
- buf = nvmem_cell_read(cell, &buf_size);
- if (!IS_ERR(buf)) {
- value = buf[0] & phy_cfg->dc_driving_mask;
- kfree(buf);
- }
- nvmem_cell_put(cell);
- }
-
- if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
- int rate = phy_cfg->efuse_dc_driving_rate;
-
- if (value <= EFUS_USB_DC_CAL_MAX)
- phy_parameter->efuse_usb_dc_cal = (int8_t)(value * rate);
- else
- phy_parameter->efuse_usb_dc_cal = -(int8_t)
- ((EFUS_USB_DC_CAL_MAX & value) * rate);
-
- if (soc_device_match(rtk_soc_groot)) {
- dev_dbg(rtk_phy->dev, "For groot IC we need a workaround to adjust efuse_usb_dc_cal\n");
-
- /* We don't multiple dc_cal_rate=2 for positive dc cal compensate */
- if (value <= EFUS_USB_DC_CAL_MAX)
- phy_parameter->efuse_usb_dc_cal = (int8_t)(value);
-
- /* We set max dc cal compensate is 0x8 if otp is 0x7 */
- if (value == 0x7)
- phy_parameter->efuse_usb_dc_cal = (int8_t)(value + 1);
- }
- } else { /* for CHECK_EFUSE_V2 */
- phy_parameter->efuse_usb_dc_cal = value & phy_cfg->dc_driving_mask;
- }
-
- /* Read efuse for usb dc disconnect level */
- value = 0;
- cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-dis");
- if (IS_ERR(cell)) {
- dev_dbg(rtk_phy->dev, "%s no usb-dc-dis: %ld\n",
- __func__, PTR_ERR(cell));
- } else {
- unsigned char *buf;
- size_t buf_size;
-
- buf = nvmem_cell_read(cell, &buf_size);
- if (!IS_ERR(buf)) {
- value = buf[0] & phy_cfg->dc_disconnect_mask;
- kfree(buf);
- }
- nvmem_cell_put(cell);
- }
-
- if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
- int rate = phy_cfg->efuse_dc_disconnect_rate;
-
- if (value <= EFUS_USB_DC_DIS_MAX)
- phy_parameter->efuse_usb_dc_dis = (int8_t)(value * rate);
- else
- phy_parameter->efuse_usb_dc_dis = -(int8_t)
- ((EFUS_USB_DC_DIS_MAX & value) * rate);
- } else { /* for CHECK_EFUSE_V2 */
- phy_parameter->efuse_usb_dc_dis = value & phy_cfg->dc_disconnect_mask;
- }
-
-out:
- return 0;
-}
-
-static int parse_phy_data(struct rtk_phy *rtk_phy)
-{
- struct device *dev = rtk_phy->dev;
- struct device_node *np = dev->of_node;
- struct phy_parameter *phy_parameter;
- int ret = 0;
- int index;
-
- rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
- rtk_phy->num_phy, GFP_KERNEL);
- if (!rtk_phy->phy_parameter)
- return -ENOMEM;
-
- for (index = 0; index < rtk_phy->num_phy; index++) {
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-
- phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
- phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
- phy_parameter->phy_reg.vstatus_index = index;
-
- if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
- phy_parameter->inverse_hstx_sync_clock = true;
- else
- phy_parameter->inverse_hstx_sync_clock = false;
-
- if (of_property_read_u32_index(np, "realtek,driving-level",
- index, &phy_parameter->driving_level))
- phy_parameter->driving_level = DEFAULT_DC_DRIVING_VALUE;
-
- if (of_property_read_u32_index(np, "realtek,driving-level-compensate",
- index, &phy_parameter->driving_level_compensate))
- phy_parameter->driving_level_compensate = 0;
-
- if (of_property_read_u32_index(np, "realtek,disconnection-compensate",
- index, &phy_parameter->disconnection_compensate))
- phy_parameter->disconnection_compensate = 0;
-
- get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
-
- update_dc_driving_level(rtk_phy, phy_parameter);
-
- update_hs_clk_select(rtk_phy, phy_parameter);
- }
-
- return ret;
-}
-
-static int rtk_usb2phy_probe(struct platform_device *pdev)
-{
- struct rtk_phy *rtk_phy;
- struct device *dev = &pdev->dev;
- struct phy *generic_phy;
- struct phy_provider *phy_provider;
- const struct phy_cfg *phy_cfg;
- int ret = 0;
-
- phy_cfg = of_device_get_match_data(dev);
- if (!phy_cfg) {
- dev_err(dev, "phy config are not assigned!\n");
- return -EINVAL;
- }
-
- rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
- if (!rtk_phy)
- return -ENOMEM;
-
- rtk_phy->dev = &pdev->dev;
- rtk_phy->phy.dev = rtk_phy->dev;
- rtk_phy->phy.label = "rtk-usb2phy";
- rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
-
- rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
-
- memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
-
- rtk_phy->num_phy = phy_cfg->num_phy;
-
- ret = parse_phy_data(rtk_phy);
- if (ret)
- goto err;
-
- platform_set_drvdata(pdev, rtk_phy);
-
- generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
- if (IS_ERR(generic_phy))
- return PTR_ERR(generic_phy);
-
- phy_set_drvdata(generic_phy, rtk_phy);
-
- phy_provider = devm_of_phy_provider_register(rtk_phy->dev,
- of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- ret = usb_add_phy_dev(&rtk_phy->phy);
- if (ret)
- goto err;
-
- create_debug_files(rtk_phy);
-
-err:
- return ret;
-}
-
-static void rtk_usb2phy_remove(struct platform_device *pdev)
-{
- struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
-
- remove_debug_files(rtk_phy);
-
- usb_remove_phy(&rtk_phy->phy);
-}
-
-static const struct phy_cfg rtd1295_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [0] = {0xe0, 0x90},
- [3] = {0xe3, 0x3a},
- [4] = {0xe4, 0x68},
- [6] = {0xe6, 0x91},
- [13] = {0xf5, 0x81},
- [15] = {0xf7, 0x02}, },
- .page1_size = 8,
- .page1 = { /* default parameter */ },
- .page2_size = 0,
- .page2 = { /* no parameter */ },
- .num_phy = 1,
- .check_efuse = false,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = 1,
- .dc_driving_mask = 0xf,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = true,
- .do_toggle = true,
- .do_toggle_driving = false,
- .driving_updated_for_dev_dis = 0xf,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1395_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [4] = {0xe4, 0xac},
- [13] = {0xf5, 0x00},
- [15] = {0xf7, 0x02}, },
- .page1_size = 8,
- .page1 = { /* default parameter */ },
- .page2_size = 0,
- .page2 = { /* no parameter */ },
- .num_phy = 1,
- .check_efuse = false,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = 1,
- .dc_driving_mask = 0xf,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = true,
- .do_toggle = true,
- .do_toggle_driving = false,
- .driving_updated_for_dev_dis = 0xf,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1395_phy_cfg_2port = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [4] = {0xe4, 0xac},
- [13] = {0xf5, 0x00},
- [15] = {0xf7, 0x02}, },
- .page1_size = 8,
- .page1 = { /* default parameter */ },
- .page2_size = 0,
- .page2 = { /* no parameter */ },
- .num_phy = 2,
- .check_efuse = false,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = 1,
- .dc_driving_mask = 0xf,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = true,
- .do_toggle = true,
- .do_toggle_driving = false,
- .driving_updated_for_dev_dis = 0xf,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1619_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [4] = {0xe4, 0x68}, },
- .page1_size = 8,
- .page1 = { /* default parameter */ },
- .page2_size = 0,
- .page2 = { /* no parameter */ },
- .num_phy = 1,
- .check_efuse = true,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = 1,
- .dc_driving_mask = 0xf,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = true,
- .do_toggle = true,
- .do_toggle_driving = false,
- .driving_updated_for_dev_dis = 0xf,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = false,
-};
-
-static const struct phy_cfg rtd1319_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [0] = {0xe0, 0x18},
- [4] = {0xe4, 0x6a},
- [7] = {0xe7, 0x71},
- [13] = {0xf5, 0x15},
- [15] = {0xf7, 0x32}, },
- .page1_size = 8,
- .page1 = { [3] = {0xe3, 0x44}, },
- .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
- .page2 = { [0] = {0xe0, 0x01}, },
- .num_phy = 1,
- .check_efuse = true,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = 1,
- .dc_driving_mask = 0xf,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = true,
- .do_toggle = true,
- .do_toggle_driving = true,
- .driving_updated_for_dev_dis = 0xf,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1312c_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [0] = {0xe0, 0x14},
- [4] = {0xe4, 0x67},
- [5] = {0xe5, 0x55}, },
- .page1_size = 8,
- .page1 = { [3] = {0xe3, 0x23},
- [6] = {0xe6, 0x58}, },
- .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
- .page2 = { /* default parameter */ },
- .num_phy = 1,
- .check_efuse = true,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = 1,
- .dc_driving_mask = 0xf,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = true,
- .do_toggle = true,
- .do_toggle_driving = true,
- .driving_updated_for_dev_dis = 0xf,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1619b_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [0] = {0xe0, 0xa3},
- [4] = {0xe4, 0x88},
- [5] = {0xe5, 0x4f},
- [6] = {0xe6, 0x02}, },
- .page1_size = 8,
- .page1 = { [3] = {0xe3, 0x64}, },
- .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
- .page2 = { [7] = {0xe7, 0x45}, },
- .num_phy = 1,
- .check_efuse = true,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
- .dc_driving_mask = 0x1f,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = false,
- .do_toggle = true,
- .do_toggle_driving = true,
- .driving_updated_for_dev_dis = 0x8,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1319d_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [0] = {0xe0, 0xa3},
- [4] = {0xe4, 0x8e},
- [5] = {0xe5, 0x4f},
- [6] = {0xe6, 0x02}, },
- .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
- .page1 = { [14] = {0xf5, 0x1}, },
- .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
- .page2 = { [7] = {0xe7, 0x44}, },
- .check_efuse = true,
- .num_phy = 1,
- .check_efuse_version = CHECK_EFUSE_V1,
- .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
- .dc_driving_mask = 0x1f,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = false,
- .do_toggle = true,
- .do_toggle_driving = false,
- .driving_updated_for_dev_dis = 0x8,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = true,
-};
-
-static const struct phy_cfg rtd1315e_phy_cfg = {
- .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
- .page0 = { [0] = {0xe0, 0xa3},
- [4] = {0xe4, 0x8c},
- [5] = {0xe5, 0x4f},
- [6] = {0xe6, 0x02}, },
- .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
- .page1 = { [3] = {0xe3, 0x7f},
- [14] = {0xf5, 0x01}, },
- .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
- .page2 = { [7] = {0xe7, 0x44}, },
- .num_phy = 1,
- .check_efuse = true,
- .check_efuse_version = CHECK_EFUSE_V2,
- .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
- .dc_driving_mask = 0x1f,
- .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
- .dc_disconnect_mask = 0xf,
- .usb_dc_disconnect_at_page0 = false,
- .do_toggle = true,
- .do_toggle_driving = false,
- .driving_updated_for_dev_dis = 0x8,
- .use_default_parameter = false,
- .is_double_sensitivity_mode = true,
-};
-
-static const struct of_device_id usbphy_rtk_dt_match[] = {
- { .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg },
- { .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg },
- { .compatible = "realtek,rtd1315e-usb2phy", .data = &rtd1315e_phy_cfg },
- { .compatible = "realtek,rtd1319-usb2phy", .data = &rtd1319_phy_cfg },
- { .compatible = "realtek,rtd1319d-usb2phy", .data = &rtd1319d_phy_cfg },
- { .compatible = "realtek,rtd1395-usb2phy", .data = &rtd1395_phy_cfg },
- { .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port },
- { .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg },
- { .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg },
- {},
-};
-MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
-
-static struct platform_driver rtk_usb2phy_driver = {
- .probe = rtk_usb2phy_probe,
- .remove_new = rtk_usb2phy_remove,
- .driver = {
- .name = "rtk-usb2phy",
- .of_match_table = usbphy_rtk_dt_match,
- },
-};
-
-module_platform_driver(rtk_usb2phy_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform: rtk-usb2phy");
-MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
-MODULE_DESCRIPTION("Realtek usb 2.0 phy driver");
diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c
deleted file mode 100644
index 67446a85e96..00000000000
--- a/drivers/phy/realtek/phy-rtk-usb3.c
+++ /dev/null
@@ -1,761 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * phy-rtk-usb3.c RTK usb3.0 phy driver
- *
- * copyright (c) 2023 realtek semiconductor corporation
- *
- */
-
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/nvmem-consumer.h>
-#include <linux/regmap.h>
-#include <linux/sys_soc.h>
-#include <linux/mfd/syscon.h>
-#include <linux/phy/phy.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/usb/phy.h>
-
-#define USB_MDIO_CTRL_PHY_BUSY BIT(7)
-#define USB_MDIO_CTRL_PHY_WRITE BIT(0)
-#define USB_MDIO_CTRL_PHY_ADDR_SHIFT 8
-#define USB_MDIO_CTRL_PHY_DATA_SHIFT 16
-
-#define MAX_USB_PHY_DATA_SIZE 0x30
-#define PHY_ADDR_0X09 0x09
-#define PHY_ADDR_0X0B 0x0b
-#define PHY_ADDR_0X0D 0x0d
-#define PHY_ADDR_0X10 0x10
-#define PHY_ADDR_0X1F 0x1f
-#define PHY_ADDR_0X20 0x20
-#define PHY_ADDR_0X21 0x21
-#define PHY_ADDR_0X30 0x30
-
-#define REG_0X09_FORCE_CALIBRATION BIT(9)
-#define REG_0X0B_RX_OFFSET_RANGE_MASK 0xc
-#define REG_0X0D_RX_DEBUG_TEST_EN BIT(6)
-#define REG_0X10_DEBUG_MODE_SETTING 0x3c0
-#define REG_0X10_DEBUG_MODE_SETTING_MASK 0x3f8
-#define REG_0X1F_RX_OFFSET_CODE_MASK 0x1e
-
-#define USB_U3_TX_LFPS_SWING_TRIM_SHIFT 4
-#define USB_U3_TX_LFPS_SWING_TRIM_MASK 0xf
-#define AMPLITUDE_CONTROL_COARSE_MASK 0xff
-#define AMPLITUDE_CONTROL_FINE_MASK 0xffff
-#define AMPLITUDE_CONTROL_COARSE_DEFAULT 0xff
-#define AMPLITUDE_CONTROL_FINE_DEFAULT 0xffff
-
-#define PHY_ADDR_MAP_ARRAY_INDEX(addr) (addr)
-#define ARRAY_INDEX_MAP_PHY_ADDR(index) (index)
-
-struct phy_reg {
- void __iomem *reg_mdio_ctl;
-};
-
-struct phy_data {
- u8 addr;
- u16 data;
-};
-
-struct phy_cfg {
- int param_size;
- struct phy_data param[MAX_USB_PHY_DATA_SIZE];
-
- bool check_efuse;
- bool do_toggle;
- bool do_toggle_once;
- bool use_default_parameter;
- bool check_rx_front_end_offset;
-};
-
-struct phy_parameter {
- struct phy_reg phy_reg;
-
- /* Get from efuse */
- u8 efuse_usb_u3_tx_lfps_swing_trim;
-
- /* Get from dts */
- u32 amplitude_control_coarse;
- u32 amplitude_control_fine;
-};
-
-struct rtk_phy {
- struct usb_phy phy;
- struct device *dev;
-
- struct phy_cfg *phy_cfg;
- int num_phy;
- struct phy_parameter *phy_parameter;
-
- struct dentry *debug_dir;
-};
-
-#define PHY_IO_TIMEOUT_USEC (50000)
-#define PHY_IO_DELAY_US (100)
-
-static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
-{
- int ret;
- unsigned int val;
-
- ret = read_poll_timeout(readl, val, ((val & mask) == result),
- PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
- if (ret) {
- pr_err("%s can't program USB phy\n", __func__);
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static int rtk_phy3_wait_vbusy(struct phy_reg *phy_reg)
-{
- return utmi_wait_register(phy_reg->reg_mdio_ctl, USB_MDIO_CTRL_PHY_BUSY, 0);
-}
-
-static u16 rtk_phy_read(struct phy_reg *phy_reg, char addr)
-{
- unsigned int tmp;
- u32 value;
-
- tmp = (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT);
-
- writel(tmp, phy_reg->reg_mdio_ctl);
-
- rtk_phy3_wait_vbusy(phy_reg);
-
- value = readl(phy_reg->reg_mdio_ctl);
- value = value >> USB_MDIO_CTRL_PHY_DATA_SHIFT;
-
- return (u16)value;
-}
-
-static int rtk_phy_write(struct phy_reg *phy_reg, char addr, u16 data)
-{
- unsigned int val;
-
- val = USB_MDIO_CTRL_PHY_WRITE |
- (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT) |
- (data << USB_MDIO_CTRL_PHY_DATA_SHIFT);
-
- writel(val, phy_reg->reg_mdio_ctl);
-
- rtk_phy3_wait_vbusy(phy_reg);
-
- return 0;
-}
-
-static void do_rtk_usb3_phy_toggle(struct rtk_phy *rtk_phy, int index, bool connect)
-{
- struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
- struct phy_reg *phy_reg;
- struct phy_parameter *phy_parameter;
- struct phy_data *phy_data;
- u8 addr;
- u16 data;
- int i;
-
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
- phy_reg = &phy_parameter->phy_reg;
-
- if (!phy_cfg->do_toggle)
- return;
-
- i = PHY_ADDR_MAP_ARRAY_INDEX(PHY_ADDR_0X09);
- phy_data = phy_cfg->param + i;
- addr = phy_data->addr;
- data = phy_data->data;
-
- if (!addr && !data) {
- addr = PHY_ADDR_0X09;
- data = rtk_phy_read(phy_reg, addr);
- phy_data->addr = addr;
- phy_data->data = data;
- }
-
- rtk_phy_write(phy_reg, addr, data & (~REG_0X09_FORCE_CALIBRATION));
- mdelay(1);
- rtk_phy_write(phy_reg, addr, data | REG_0X09_FORCE_CALIBRATION);
-}
-
-static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
-{
- struct phy_cfg *phy_cfg;
- struct phy_reg *phy_reg;
- struct phy_parameter *phy_parameter;
- int i = 0;
-
- phy_cfg = rtk_phy->phy_cfg;
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
- phy_reg = &phy_parameter->phy_reg;
-
- if (phy_cfg->use_default_parameter)
- goto do_toggle;
-
- for (i = 0; i < phy_cfg->param_size; i++) {
- struct phy_data *phy_data = phy_cfg->param + i;
- u8 addr = phy_data->addr;
- u16 data = phy_data->data;
-
- if (!addr && !data)
- continue;
-
- rtk_phy_write(phy_reg, addr, data);
- }
-
-do_toggle:
- if (phy_cfg->do_toggle_once)
- phy_cfg->do_toggle = true;
-
- do_rtk_usb3_phy_toggle(rtk_phy, index, false);
-
- if (phy_cfg->do_toggle_once) {
- u16 check_value = 0;
- int count = 10;
- u16 value_0x0d, value_0x10;
-
- /* Enable Debug mode by set 0x0D and 0x10 */
- value_0x0d = rtk_phy_read(phy_reg, PHY_ADDR_0X0D);
- value_0x10 = rtk_phy_read(phy_reg, PHY_ADDR_0X10);
-
- rtk_phy_write(phy_reg, PHY_ADDR_0X0D,
- value_0x0d | REG_0X0D_RX_DEBUG_TEST_EN);
- rtk_phy_write(phy_reg, PHY_ADDR_0X10,
- (value_0x10 & ~REG_0X10_DEBUG_MODE_SETTING_MASK) |
- REG_0X10_DEBUG_MODE_SETTING);
-
- check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
-
- while (!(check_value & BIT(15))) {
- check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
- mdelay(1);
- if (count-- < 0)
- break;
- }
-
- if (!(check_value & BIT(15)))
- dev_info(rtk_phy->dev, "toggle fail addr=0x%02x, data=0x%04x\n",
- PHY_ADDR_0X30, check_value);
-
- /* Disable Debug mode by set 0x0D and 0x10 to default*/
- rtk_phy_write(phy_reg, PHY_ADDR_0X0D, value_0x0d);
- rtk_phy_write(phy_reg, PHY_ADDR_0X10, value_0x10);
-
- phy_cfg->do_toggle = false;
- }
-
- if (phy_cfg->check_rx_front_end_offset) {
- u16 rx_offset_code, rx_offset_range;
- u16 code_mask = REG_0X1F_RX_OFFSET_CODE_MASK;
- u16 range_mask = REG_0X0B_RX_OFFSET_RANGE_MASK;
- bool do_update = false;
-
- rx_offset_code = rtk_phy_read(phy_reg, PHY_ADDR_0X1F);
- if (((rx_offset_code & code_mask) == 0x0) ||
- ((rx_offset_code & code_mask) == code_mask))
- do_update = true;
-
- rx_offset_range = rtk_phy_read(phy_reg, PHY_ADDR_0X0B);
- if (((rx_offset_range & range_mask) == range_mask) && do_update) {
- dev_warn(rtk_phy->dev, "Don't update rx_offset_range (rx_offset_code=0x%x, rx_offset_range=0x%x)\n",
- rx_offset_code, rx_offset_range);
- do_update = false;
- }
-
- if (do_update) {
- u16 tmp1, tmp2;
-
- tmp1 = rx_offset_range & (~range_mask);
- tmp2 = rx_offset_range & range_mask;
- tmp2 += (1 << 2);
- rx_offset_range = tmp1 | (tmp2 & range_mask);
- rtk_phy_write(phy_reg, PHY_ADDR_0X0B, rx_offset_range);
- goto do_toggle;
- }
- }
-
- return 0;
-}
-
-static int rtk_phy_init(struct phy *phy)
-{
- struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
- int ret = 0;
- int i;
- unsigned long phy_init_time = jiffies;
-
- for (i = 0; i < rtk_phy->num_phy; i++)
- ret = do_rtk_phy_init(rtk_phy, i);
-
- dev_dbg(rtk_phy->dev, "Initialized RTK USB 3.0 PHY (take %dms)\n",
- jiffies_to_msecs(jiffies - phy_init_time));
-
- return ret;
-}
-
-static int rtk_phy_exit(struct phy *phy)
-{
- return 0;
-}
-
-static const struct phy_ops ops = {
- .init = rtk_phy_init,
- .exit = rtk_phy_exit,
- .owner = THIS_MODULE,
-};
-
-static void rtk_phy_toggle(struct usb_phy *usb3_phy, bool connect, int port)
-{
- int index = port;
- struct rtk_phy *rtk_phy = NULL;
-
- rtk_phy = dev_get_drvdata(usb3_phy->dev);
-
- if (index > rtk_phy->num_phy) {
- dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
- __func__, index, rtk_phy->num_phy);
- return;
- }
-
- do_rtk_usb3_phy_toggle(rtk_phy, index, connect);
-}
-
-static int rtk_phy_notify_port_status(struct usb_phy *x, int port,
- u16 portstatus, u16 portchange)
-{
- bool connect = false;
-
- pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n",
- __func__, port, (int)portstatus, (int)portchange);
- if (portstatus & USB_PORT_STAT_CONNECTION)
- connect = true;
-
- if (portchange & USB_PORT_STAT_C_CONNECTION)
- rtk_phy_toggle(x, connect, port);
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *create_phy_debug_root(void)
-{
- struct dentry *phy_debug_root;
-
- phy_debug_root = debugfs_lookup("phy", usb_debug_root);
- if (!phy_debug_root)
- phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
-
- return phy_debug_root;
-}
-
-static int rtk_usb3_parameter_show(struct seq_file *s, void *unused)
-{
- struct rtk_phy *rtk_phy = s->private;
- struct phy_cfg *phy_cfg;
- int i, index;
-
- phy_cfg = rtk_phy->phy_cfg;
-
- seq_puts(s, "Property:\n");
- seq_printf(s, " check_efuse: %s\n",
- phy_cfg->check_efuse ? "Enable" : "Disable");
- seq_printf(s, " do_toggle: %s\n",
- phy_cfg->do_toggle ? "Enable" : "Disable");
- seq_printf(s, " do_toggle_once: %s\n",
- phy_cfg->do_toggle_once ? "Enable" : "Disable");
- seq_printf(s, " use_default_parameter: %s\n",
- phy_cfg->use_default_parameter ? "Enable" : "Disable");
-
- for (index = 0; index < rtk_phy->num_phy; index++) {
- struct phy_reg *phy_reg;
- struct phy_parameter *phy_parameter;
-
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
- phy_reg = &phy_parameter->phy_reg;
-
- seq_printf(s, "PHY %d:\n", index);
-
- for (i = 0; i < phy_cfg->param_size; i++) {
- struct phy_data *phy_data = phy_cfg->param + i;
- u8 addr = ARRAY_INDEX_MAP_PHY_ADDR(i);
- u16 data = phy_data->data;
-
- if (!phy_data->addr && !data)
- seq_printf(s, " addr = 0x%02x, data = none ==> read value = 0x%04x\n",
- addr, rtk_phy_read(phy_reg, addr));
- else
- seq_printf(s, " addr = 0x%02x, data = 0x%04x ==> read value = 0x%04x\n",
- addr, data, rtk_phy_read(phy_reg, addr));
- }
-
- seq_puts(s, "PHY Property:\n");
- seq_printf(s, " efuse_usb_u3_tx_lfps_swing_trim: 0x%x\n",
- (int)phy_parameter->efuse_usb_u3_tx_lfps_swing_trim);
- seq_printf(s, " amplitude_control_coarse: 0x%x\n",
- (int)phy_parameter->amplitude_control_coarse);
- seq_printf(s, " amplitude_control_fine: 0x%x\n",
- (int)phy_parameter->amplitude_control_fine);
- }
-
- return 0;
-}
-DEFINE_SHOW_ATTRIBUTE(rtk_usb3_parameter);
-
-static inline void create_debug_files(struct rtk_phy *rtk_phy)
-{
- struct dentry *phy_debug_root = NULL;
-
- phy_debug_root = create_phy_debug_root();
-
- if (!phy_debug_root)
- return;
-
- rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root);
-
- debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
- &rtk_usb3_parameter_fops);
-
- return;
-}
-
-static inline void remove_debug_files(struct rtk_phy *rtk_phy)
-{
- debugfs_remove_recursive(rtk_phy->debug_dir);
-}
-#else
-static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
-static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
-#endif /* CONFIG_DEBUG_FS */
-
-static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter, int index)
-{
- struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
- u8 value = 0;
- struct nvmem_cell *cell;
-
- if (!phy_cfg->check_efuse)
- goto out;
-
- cell = nvmem_cell_get(rtk_phy->dev, "usb_u3_tx_lfps_swing_trim");
- if (IS_ERR(cell)) {
- dev_dbg(rtk_phy->dev, "%s no usb_u3_tx_lfps_swing_trim: %ld\n",
- __func__, PTR_ERR(cell));
- } else {
- unsigned char *buf;
- size_t buf_size;
-
- buf = nvmem_cell_read(cell, &buf_size);
- if (!IS_ERR(buf)) {
- value = buf[0] & USB_U3_TX_LFPS_SWING_TRIM_MASK;
- kfree(buf);
- }
- nvmem_cell_put(cell);
- }
-
- if (value > 0 && value < 0x8)
- phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = 0x8;
- else
- phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = (u8)value;
-
-out:
- return 0;
-}
-
-static void update_amplitude_control_value(struct rtk_phy *rtk_phy,
- struct phy_parameter *phy_parameter)
-{
- struct phy_cfg *phy_cfg;
- struct phy_reg *phy_reg;
-
- phy_reg = &phy_parameter->phy_reg;
- phy_cfg = rtk_phy->phy_cfg;
-
- if (phy_parameter->amplitude_control_coarse != AMPLITUDE_CONTROL_COARSE_DEFAULT) {
- u16 val_mask = AMPLITUDE_CONTROL_COARSE_MASK;
- u16 data;
-
- if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
- phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
- data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
- } else {
- data = phy_cfg->param[PHY_ADDR_0X20].data;
- }
-
- data &= (~val_mask);
- data |= (phy_parameter->amplitude_control_coarse & val_mask);
-
- phy_cfg->param[PHY_ADDR_0X20].data = data;
- }
-
- if (phy_parameter->efuse_usb_u3_tx_lfps_swing_trim) {
- u8 efuse_val = phy_parameter->efuse_usb_u3_tx_lfps_swing_trim;
- u16 val_mask = USB_U3_TX_LFPS_SWING_TRIM_MASK;
- int val_shift = USB_U3_TX_LFPS_SWING_TRIM_SHIFT;
- u16 data;
-
- if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
- phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
- data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
- } else {
- data = phy_cfg->param[PHY_ADDR_0X20].data;
- }
-
- data &= ~(val_mask << val_shift);
- data |= ((efuse_val & val_mask) << val_shift);
-
- phy_cfg->param[PHY_ADDR_0X20].data = data;
- }
-
- if (phy_parameter->amplitude_control_fine != AMPLITUDE_CONTROL_FINE_DEFAULT) {
- u16 val_mask = AMPLITUDE_CONTROL_FINE_MASK;
-
- if (!phy_cfg->param[PHY_ADDR_0X21].addr && !phy_cfg->param[PHY_ADDR_0X21].data)
- phy_cfg->param[PHY_ADDR_0X21].addr = PHY_ADDR_0X21;
-
- phy_cfg->param[PHY_ADDR_0X21].data =
- phy_parameter->amplitude_control_fine & val_mask;
- }
-}
-
-static int parse_phy_data(struct rtk_phy *rtk_phy)
-{
- struct device *dev = rtk_phy->dev;
- struct phy_parameter *phy_parameter;
- int ret = 0;
- int index;
-
- rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
- rtk_phy->num_phy, GFP_KERNEL);
- if (!rtk_phy->phy_parameter)
- return -ENOMEM;
-
- for (index = 0; index < rtk_phy->num_phy; index++) {
- phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
-
- phy_parameter->phy_reg.reg_mdio_ctl = of_iomap(dev->of_node, 0) + index;
-
- /* Amplitude control address 0x20 bit 0 to bit 7 */
- if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-coarse-tuning",
- &phy_parameter->amplitude_control_coarse))
- phy_parameter->amplitude_control_coarse = AMPLITUDE_CONTROL_COARSE_DEFAULT;
-
- /* Amplitude control address 0x21 bit 0 to bit 16 */
- if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-fine-tuning",
- &phy_parameter->amplitude_control_fine))
- phy_parameter->amplitude_control_fine = AMPLITUDE_CONTROL_FINE_DEFAULT;
-
- get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
-
- update_amplitude_control_value(rtk_phy, phy_parameter);
- }
-
- return ret;
-}
-
-static int rtk_usb3phy_probe(struct platform_device *pdev)
-{
- struct rtk_phy *rtk_phy;
- struct device *dev = &pdev->dev;
- struct phy *generic_phy;
- struct phy_provider *phy_provider;
- const struct phy_cfg *phy_cfg;
- int ret;
-
- phy_cfg = of_device_get_match_data(dev);
- if (!phy_cfg) {
- dev_err(dev, "phy config are not assigned!\n");
- return -EINVAL;
- }
-
- rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
- if (!rtk_phy)
- return -ENOMEM;
-
- rtk_phy->dev = &pdev->dev;
- rtk_phy->phy.dev = rtk_phy->dev;
- rtk_phy->phy.label = "rtk-usb3phy";
- rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status;
-
- rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
-
- memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
-
- rtk_phy->num_phy = 1;
-
- ret = parse_phy_data(rtk_phy);
- if (ret)
- goto err;
-
- platform_set_drvdata(pdev, rtk_phy);
-
- generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
- if (IS_ERR(generic_phy))
- return PTR_ERR(generic_phy);
-
- phy_set_drvdata(generic_phy, rtk_phy);
-
- phy_provider = devm_of_phy_provider_register(rtk_phy->dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- ret = usb_add_phy_dev(&rtk_phy->phy);
- if (ret)
- goto err;
-
- create_debug_files(rtk_phy);
-
-err:
- return ret;
-}
-
-static void rtk_usb3phy_remove(struct platform_device *pdev)
-{
- struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
-
- remove_debug_files(rtk_phy);
-
- usb_remove_phy(&rtk_phy->phy);
-}
-
-static const struct phy_cfg rtd1295_phy_cfg = {
- .param_size = MAX_USB_PHY_DATA_SIZE,
- .param = { [0] = {0x01, 0x4008}, [1] = {0x01, 0xe046},
- [2] = {0x02, 0x6046}, [3] = {0x03, 0x2779},
- [4] = {0x04, 0x72f5}, [5] = {0x05, 0x2ad3},
- [6] = {0x06, 0x000e}, [7] = {0x07, 0x2e00},
- [8] = {0x08, 0x3591}, [9] = {0x09, 0x525c},
- [10] = {0x0a, 0xa600}, [11] = {0x0b, 0xa904},
- [12] = {0x0c, 0xc000}, [13] = {0x0d, 0xef1c},
- [14] = {0x0e, 0x2000}, [15] = {0x0f, 0x0000},
- [16] = {0x10, 0x000c}, [17] = {0x11, 0x4c00},
- [18] = {0x12, 0xfc00}, [19] = {0x13, 0x0c81},
- [20] = {0x14, 0xde01}, [21] = {0x15, 0x0000},
- [22] = {0x16, 0x0000}, [23] = {0x17, 0x0000},
- [24] = {0x18, 0x0000}, [25] = {0x19, 0x4004},
- [26] = {0x1a, 0x1260}, [27] = {0x1b, 0xff00},
- [28] = {0x1c, 0xcb00}, [29] = {0x1d, 0xa03f},
- [30] = {0x1e, 0xc2e0}, [31] = {0x1f, 0x2807},
- [32] = {0x20, 0x947a}, [33] = {0x21, 0x88aa},
- [34] = {0x22, 0x0057}, [35] = {0x23, 0xab66},
- [36] = {0x24, 0x0800}, [37] = {0x25, 0x0000},
- [38] = {0x26, 0x040a}, [39] = {0x27, 0x01d6},
- [40] = {0x28, 0xf8c2}, [41] = {0x29, 0x3080},
- [42] = {0x2a, 0x3082}, [43] = {0x2b, 0x2078},
- [44] = {0x2c, 0xffff}, [45] = {0x2d, 0xffff},
- [46] = {0x2e, 0x0000}, [47] = {0x2f, 0x0040}, },
- .check_efuse = false,
- .do_toggle = true,
- .do_toggle_once = false,
- .use_default_parameter = false,
- .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1619_phy_cfg = {
- .param_size = MAX_USB_PHY_DATA_SIZE,
- .param = { [8] = {0x08, 0x3591},
- [38] = {0x26, 0x840b},
- [40] = {0x28, 0xf842}, },
- .check_efuse = false,
- .do_toggle = true,
- .do_toggle_once = false,
- .use_default_parameter = false,
- .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1319_phy_cfg = {
- .param_size = MAX_USB_PHY_DATA_SIZE,
- .param = { [1] = {0x01, 0xac86},
- [6] = {0x06, 0x0003},
- [9] = {0x09, 0x924c},
- [10] = {0x0a, 0xa608},
- [11] = {0x0b, 0xb905},
- [14] = {0x0e, 0x2010},
- [32] = {0x20, 0x705a},
- [33] = {0x21, 0xf645},
- [34] = {0x22, 0x0013},
- [35] = {0x23, 0xcb66},
- [41] = {0x29, 0xff00}, },
- .check_efuse = true,
- .do_toggle = true,
- .do_toggle_once = false,
- .use_default_parameter = false,
- .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1619b_phy_cfg = {
- .param_size = MAX_USB_PHY_DATA_SIZE,
- .param = { [1] = {0x01, 0xac8c},
- [6] = {0x06, 0x0017},
- [9] = {0x09, 0x724c},
- [10] = {0x0a, 0xb610},
- [11] = {0x0b, 0xb90d},
- [13] = {0x0d, 0xef2a},
- [15] = {0x0f, 0x9050},
- [16] = {0x10, 0x000c},
- [32] = {0x20, 0x70ff},
- [34] = {0x22, 0x0013},
- [35] = {0x23, 0xdb66},
- [38] = {0x26, 0x8609},
- [41] = {0x29, 0xff13},
- [42] = {0x2a, 0x3070}, },
- .check_efuse = true,
- .do_toggle = false,
- .do_toggle_once = true,
- .use_default_parameter = false,
- .check_rx_front_end_offset = false,
-};
-
-static const struct phy_cfg rtd1319d_phy_cfg = {
- .param_size = MAX_USB_PHY_DATA_SIZE,
- .param = { [1] = {0x01, 0xac89},
- [4] = {0x04, 0xf2f5},
- [6] = {0x06, 0x0017},
- [9] = {0x09, 0x424c},
- [10] = {0x0a, 0x9610},
- [11] = {0x0b, 0x9901},
- [12] = {0x0c, 0xf000},
- [13] = {0x0d, 0xef2a},
- [14] = {0x0e, 0x1000},
- [15] = {0x0f, 0x9050},
- [32] = {0x20, 0x7077},
- [35] = {0x23, 0x0b62},
- [37] = {0x25, 0x10ec},
- [42] = {0x2a, 0x3070}, },
- .check_efuse = true,
- .do_toggle = false,
- .do_toggle_once = true,
- .use_default_parameter = false,
- .check_rx_front_end_offset = true,
-};
-
-static const struct of_device_id usbphy_rtk_dt_match[] = {
- { .compatible = "realtek,rtd1295-usb3phy", .data = &rtd1295_phy_cfg },
- { .compatible = "realtek,rtd1319-usb3phy", .data = &rtd1319_phy_cfg },
- { .compatible = "realtek,rtd1319d-usb3phy", .data = &rtd1319d_phy_cfg },
- { .compatible = "realtek,rtd1619-usb3phy", .data = &rtd1619_phy_cfg },
- { .compatible = "realtek,rtd1619b-usb3phy", .data = &rtd1619b_phy_cfg },
- {},
-};
-MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
-
-static struct platform_driver rtk_usb3phy_driver = {
- .probe = rtk_usb3phy_probe,
- .remove_new = rtk_usb3phy_remove,
- .driver = {
- .name = "rtk-usb3phy",
- .of_match_table = usbphy_rtk_dt_match,
- },
-};
-
-module_platform_driver(rtk_usb3phy_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform: rtk-usb3phy");
-MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
-MODULE_DESCRIPTION("Realtek usb 3.0 phy driver");
diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
index cd6ac04c146..c3104714b48 100644
--- a/drivers/platform/x86/amd/pmc/pmc.c
+++ b/drivers/platform/x86/amd/pmc/pmc.c
@@ -964,33 +964,6 @@ static const struct pci_device_id pmc_pci_ids[] = {
{ }
};
-static int amd_pmc_get_dram_size(struct amd_pmc_dev *dev)
-{
- int ret;
-
- switch (dev->cpu_id) {
- case AMD_CPU_ID_YC:
- if (!(dev->major > 90 || (dev->major == 90 && dev->minor > 39))) {
- ret = -EINVAL;
- goto err_dram_size;
- }
- break;
- default:
- ret = -EINVAL;
- goto err_dram_size;
- }
-
- ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
- if (ret || !dev->dram_size)
- goto err_dram_size;
-
- return 0;
-
-err_dram_size:
- dev_err(dev->dev, "DRAM size command not supported for this platform\n");
- return ret;
-}
-
static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
{
u32 phys_addr_low, phys_addr_hi;
@@ -1009,8 +982,8 @@ static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
return -EIO;
/* Get DRAM size */
- ret = amd_pmc_get_dram_size(dev);
- if (ret)
+ ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->s2d_msg_id, true);
+ if (ret || !dev->dram_size)
dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX;
/* Get STB DRAM address */
diff --git a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
index 5798b49ddab..8c9f4f3227f 100644
--- a/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
+++ b/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c
@@ -588,17 +588,14 @@ static void release_attributes_data(void)
static int hp_add_other_attributes(int attr_type)
{
struct kobject *attr_name_kobj;
- union acpi_object *obj = NULL;
int ret;
char *attr_name;
- mutex_lock(&bioscfg_drv.mutex);
-
attr_name_kobj = kzalloc(sizeof(*attr_name_kobj), GFP_KERNEL);
- if (!attr_name_kobj) {
- ret = -ENOMEM;
- goto err_other_attr_init;
- }
+ if (!attr_name_kobj)
+ return -ENOMEM;
+
+ mutex_lock(&bioscfg_drv.mutex);
/* Check if attribute type is supported */
switch (attr_type) {
@@ -615,14 +612,14 @@ static int hp_add_other_attributes(int attr_type)
default:
pr_err("Error: Unknown attr_type: %d\n", attr_type);
ret = -EINVAL;
- goto err_other_attr_init;
+ kfree(attr_name_kobj);
+ goto unlock_drv_mutex;
}
ret = kobject_init_and_add(attr_name_kobj, &attr_name_ktype,
NULL, "%s", attr_name);
if (ret) {
pr_err("Error encountered [%d]\n", ret);
- kobject_put(attr_name_kobj);
goto err_other_attr_init;
}
@@ -630,27 +627,26 @@ static int hp_add_other_attributes(int attr_type)
switch (attr_type) {
case HPWMI_SECURE_PLATFORM_TYPE:
ret = hp_populate_secure_platform_data(attr_name_kobj);
- if (ret)
- goto err_other_attr_init;
break;
case HPWMI_SURE_START_TYPE:
ret = hp_populate_sure_start_data(attr_name_kobj);
- if (ret)
- goto err_other_attr_init;
break;
default:
ret = -EINVAL;
- goto err_other_attr_init;
}
+ if (ret)
+ goto err_other_attr_init;
+
mutex_unlock(&bioscfg_drv.mutex);
return 0;
err_other_attr_init:
+ kobject_put(attr_name_kobj);
+unlock_drv_mutex:
mutex_unlock(&bioscfg_drv.mutex);
- kfree(obj);
return ret;
}
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index ac037540acf..88eefccb6ed 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1425,18 +1425,17 @@ static int ideapad_kbd_bl_init(struct ideapad_private *priv)
if (WARN_ON(priv->kbd_bl.initialized))
return -EEXIST;
- brightness = ideapad_kbd_bl_brightness_get(priv);
- if (brightness < 0)
- return brightness;
-
- priv->kbd_bl.last_brightness = brightness;
-
if (ideapad_kbd_bl_check_tristate(priv->kbd_bl.type)) {
priv->kbd_bl.led.max_brightness = 2;
} else {
priv->kbd_bl.led.max_brightness = 1;
}
+ brightness = ideapad_kbd_bl_brightness_get(priv);
+ if (brightness < 0)
+ return brightness;
+
+ priv->kbd_bl.last_brightness = brightness;
priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get;
priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
diff --git a/drivers/platform/x86/intel/telemetry/core.c b/drivers/platform/x86/intel/telemetry/core.c
index fdf55b5d694..e4be40f73ee 100644
--- a/drivers/platform/x86/intel/telemetry/core.c
+++ b/drivers/platform/x86/intel/telemetry/core.c
@@ -102,7 +102,7 @@ static const struct telemetry_core_ops telm_defpltops = {
/**
* telemetry_update_events() - Update telemetry Configuration
* @pss_evtconfig: PSS related config. No change if num_evts = 0.
- * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
+ * @ioss_evtconfig: IOSS related config. No change if num_evts = 0.
*
* This API updates the IOSS & PSS Telemetry configuration. Old config
* is overwritten. Call telemetry_reset_events when logging is over
@@ -176,7 +176,7 @@ EXPORT_SYMBOL_GPL(telemetry_reset_events);
/**
* telemetry_get_eventconfig() - Returns the pss and ioss events enabled
* @pss_evtconfig: Pointer to PSS related configuration.
- * @pss_evtconfig: Pointer to IOSS related configuration.
+ * @ioss_evtconfig: Pointer to IOSS related configuration.
* @pss_len: Number of u32 elements allocated for pss_evtconfig array
* @ioss_len: Number of u32 elements allocated for ioss_evtconfig array
*
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index f21cb05815e..bccf431f462 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
@@ -984,4 +992,15 @@ 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 DRM
+ depends on I2C
+ help
+ Driver for the Embedded Controller in the Qualcomm Snapdragon-based
+ Lenovo Yoga C630, which provides battery information and USB Type-C
+ altmode notifications.
+
+ Say M or Y here to include this support.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 58b56727803..655b583eb9d 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -112,5 +112,7 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
+obj-$(CONFIG_BATTERY_QCOM_FG) += qcom_fg.o
obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o
obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o
+obj-$(CONFIG_LENOVO_YOGA_C630_EC) += yoga-c630-ec.o
diff --git a/drivers/power/supply/qcom_fg.c b/drivers/power/supply/qcom_fg.c
new file mode 100644
index 00000000000..f8dd93aa23c
--- /dev/null
+++ b/drivers/power/supply/qcom_fg.c
@@ -0,0 +1,1320 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+/* SOC */
+#define BATT_MONOTONIC_SOC 0x009
+
+/* BATT */
+#define PARAM_ADDR_BATT_TEMP 0x150
+#define BATT_INFO_JEITA_COLD 0x162
+#define BATT_INFO_JEITA_COOL 0x163
+#define BATT_INFO_JEITA_WARM 0x164
+#define BATT_INFO_JEITA_HOT 0x165
+#define PARAM_ADDR_BATT_VOLTAGE 0x1a0
+#define PARAM_ADDR_BATT_CURRENT 0x1a2
+
+/* MEMIF */
+#define MEM_INTF_STS 0x410
+#define MEM_INTF_CFG 0x450
+#define MEM_INTF_CTL 0x451
+#define MEM_INTF_IMA_CFG 0x452
+#define MEM_INTF_IMA_EXP_STS 0x455
+#define MEM_INTF_IMA_HW_STS 0x456
+#define MEM_INTF_IMA_ERR_STS 0x45f
+#define MEM_INTF_IMA_BYTE_EN 0x460
+#define MEM_INTF_ADDR_LSB 0x461
+#define MEM_INTF_RD_DATA0 0x467
+#define MEM_INTF_WR_DATA0 0x463
+#define MEM_IF_DMA_STS 0x470
+#define MEM_IF_DMA_CTL 0x471
+
+/* SRAM addresses */
+#define TEMP_THRESHOLD 0x454
+#define BATT_TEMP 0x550
+#define BATT_VOLTAGE_CURRENT 0x5cc
+
+#define BATT_TEMP_LSB_MASK GENMASK(7, 0)
+#define BATT_TEMP_MSB_MASK GENMASK(2, 0)
+
+#define BATT_TEMP_JEITA_COLD 100
+#define BATT_TEMP_JEITA_COOL 50
+#define BATT_TEMP_JEITA_WARM 400
+#define BATT_TEMP_JEITA_HOT 450
+
+#define MEM_INTF_AVAIL BIT(0)
+#define MEM_INTF_CTL_BURST BIT(7)
+#define MEM_INTF_CTL_WR_EN BIT(6)
+#define RIF_MEM_ACCESS_REQ BIT(7)
+
+#define MEM_IF_TIMEOUT_MS 5000
+#define SRAM_ACCESS_RELEASE_DELAY_MS 500
+
+struct qcom_fg_chip;
+
+struct qcom_fg_ops {
+ int (*get_capacity)(struct qcom_fg_chip *chip, int *);
+ int (*get_temperature)(struct qcom_fg_chip *chip, int *);
+ int (*get_current)(struct qcom_fg_chip *chip, int *);
+ int (*get_voltage)(struct qcom_fg_chip *chip, int *);
+ int (*get_temp_threshold)(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int *);
+ int (*set_temp_threshold)(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int);
+};
+
+struct qcom_fg_chip {
+ struct device *dev;
+ unsigned int base;
+ struct regmap *regmap;
+ const struct qcom_fg_ops *ops;
+ struct notifier_block nb;
+
+ struct power_supply *batt_psy;
+ struct power_supply_battery_info *batt_info;
+ struct power_supply *chg_psy;
+ int status;
+ struct delayed_work status_changed_work;
+
+ struct completion sram_access_granted;
+ struct completion sram_access_revoked;
+ struct workqueue_struct *sram_wq;
+ struct delayed_work sram_release_access_work;
+ spinlock_t sram_request_lock;
+ spinlock_t sram_rw_lock;
+ int sram_requests;
+};
+
+/************************
+ * IO FUNCTIONS
+ * **********************/
+
+/**
+ * @brief qcom_fg_read() - Read multiple registers with regmap_bulk_read
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to read values into
+ * @param addr Address to read from
+ * @param len Number of registers (bytes) to read
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_read(struct qcom_fg_chip *chip, u8 *val, u16 addr, int len)
+{
+ if (((chip->base + addr) & 0xff00) == 0)
+ return -EINVAL;
+
+ dev_vdbg(chip->dev, "%s: Reading 0x%x bytes from 0x%x", __func__, len, addr);
+
+ return regmap_bulk_read(chip->regmap, chip->base + addr, val, len);
+}
+
+/**
+ * @brief qcom_fg_write() - Write multiple registers with regmap_bulk_write
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to write values from
+ * @param addr Address to write to
+ * @param len Number of registers (bytes) to write
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_write(struct qcom_fg_chip *chip, u8 *val, u16 addr, int len)
+{
+ bool sec_access = (addr & 0xff) > 0xd0;
+ u8 sec_addr_val = 0xa5;
+ int ret;
+
+ if (((chip->base + addr) & 0xff00) == 0)
+ return -EINVAL;
+
+ dev_vdbg(chip->dev, "%s: Writing 0x%x to 0x%x", __func__, *val, addr);
+
+ if (sec_access) {
+ ret = regmap_bulk_write(chip->regmap,
+ ((chip->base + addr) & 0xff00) | 0xd0,
+ &sec_addr_val, 1);
+ if (ret)
+ return ret;
+ }
+
+ return regmap_bulk_write(chip->regmap, chip->base + addr, val, len);
+}
+
+/**
+ * @brief qcom_fg_masked_write() - like qcom_fg_write but applies
+ * a mask first.
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to write values from
+ * @param addr Address to write to
+ * @param len Number of registers (bytes) to write
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_masked_write(struct qcom_fg_chip *chip, u16 addr, u8 mask, u8 val)
+{
+ u8 reg;
+ int ret;
+
+ ret = qcom_fg_read(chip, &reg, addr, 1);
+ if (ret)
+ return ret;
+
+ reg &= ~mask;
+ reg |= val & mask;
+
+ return qcom_fg_write(chip, &reg, addr, 1);
+}
+
+/************************
+ * SRAM FUNCTIONS
+ * **********************/
+
+/**
+ * @brief qcom_fg_sram_check_access() - Check if SRAM is accessible
+ *
+ * @param chip Pointer to chip
+ * @return bool true if accessible, false otherwise
+ */
+static bool qcom_fg_sram_check_access(struct qcom_fg_chip *chip)
+{
+ u8 mem_if_status;
+ int ret;
+
+ ret = qcom_fg_read(chip, &mem_if_status,
+ MEM_INTF_STS, 1);
+
+ if (ret || !(mem_if_status & MEM_INTF_AVAIL))
+ return false;
+
+ ret = qcom_fg_read(chip, &mem_if_status,
+ MEM_INTF_CFG, 1);
+
+ if (ret)
+ return false;
+
+ return !!(mem_if_status & RIF_MEM_ACCESS_REQ);
+}
+
+/**
+ * @brief qcom_fg_sram_request_access() - Request access to SRAM and wait for it
+ *
+ * @param chip Pointer to chip
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_request_access(struct qcom_fg_chip *chip)
+{
+ bool sram_accessible;
+ int ret;
+
+ spin_lock(&chip->sram_request_lock);
+
+ sram_accessible = qcom_fg_sram_check_access(chip);
+
+ dev_vdbg(chip->dev, "Requesting SRAM access, current state: %d, requests: %d\n",
+ sram_accessible, chip->sram_requests);
+
+ if (!sram_accessible && chip->sram_requests == 0) {
+ ret = qcom_fg_masked_write(chip, MEM_INTF_CFG,
+ RIF_MEM_ACCESS_REQ, RIF_MEM_ACCESS_REQ);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set SRAM access request bit: %d\n", ret);
+
+ spin_unlock(&chip->sram_request_lock);
+ return ret;
+ }
+ }
+
+ chip->sram_requests++;
+
+ spin_unlock(&chip->sram_request_lock);
+
+ /* Wait to get access to SRAM, and try again if interrupted */
+ do {
+ ret = wait_for_completion_interruptible_timeout(
+ &chip->sram_access_granted,
+ msecs_to_jiffies(MEM_IF_TIMEOUT_MS));
+ } while(ret == -ERESTARTSYS);
+
+ if (ret <= 0) {
+ ret = -ETIMEDOUT;
+
+ spin_lock(&chip->sram_request_lock);
+ chip->sram_requests--;
+ spin_unlock(&chip->sram_request_lock);
+ } else {
+ ret = 0;
+
+ reinit_completion(&chip->sram_access_revoked);
+ }
+
+ return ret;
+}
+
+/**
+ * @brief qcom_fg_sram_release_access() - Release access to SRAM
+ *
+ * @param chip Pointer to chip
+ * @return int 0 on success, negative errno on error
+ */
+static void qcom_fg_sram_release_access(struct qcom_fg_chip *chip)
+{
+ spin_lock(&chip->sram_request_lock);
+
+ chip->sram_requests--;
+
+ if(WARN(chip->sram_requests < 0,
+ "sram_requests=%d, cannot be negative! resetting to 0.\n",
+ chip->sram_requests))
+ chip->sram_requests = 0;
+
+ if(chip->sram_requests == 0)
+ /* Schedule access release */
+ queue_delayed_work(chip->sram_wq, &chip->sram_release_access_work,
+ msecs_to_jiffies(SRAM_ACCESS_RELEASE_DELAY_MS));
+
+ spin_unlock(&chip->sram_request_lock);
+}
+
+static void qcom_fg_sram_release_access_worker(struct work_struct *work)
+{
+ struct qcom_fg_chip *chip;
+ bool wait = false;
+ int ret;
+
+ chip = container_of(work, struct qcom_fg_chip, sram_release_access_work.work);
+
+ spin_lock(&chip->sram_request_lock);
+
+ /* Request access release if there are still no access requests */
+ if(chip->sram_requests == 0) {
+ qcom_fg_masked_write(chip, MEM_INTF_CFG, RIF_MEM_ACCESS_REQ, 0);
+ wait = true;
+ }
+
+ spin_unlock(&chip->sram_request_lock);
+
+ if(!wait)
+ return;
+
+ /* Wait for SRAM access to be released, and try again if interrupted */
+ do {
+ ret = wait_for_completion_interruptible_timeout(
+ &chip->sram_access_revoked,
+ msecs_to_jiffies(MEM_IF_TIMEOUT_MS));
+ } while(ret == -ERESTARTSYS);
+
+ reinit_completion(&chip->sram_access_granted);
+}
+
+/**
+ * @brief qcom_fg_sram_config_access() - Configure access to SRAM
+ *
+ * @param chip Pointer to chip
+ * @param write 0 for read access, 1 for write access
+ * @param burst 1 to access mutliple addresses successively
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_config_access(struct qcom_fg_chip *chip,
+ bool write, bool burst)
+{
+ u8 intf_ctl;
+ int ret;
+
+ intf_ctl = (write ? MEM_INTF_CTL_WR_EN : 0)
+ | (burst ? MEM_INTF_CTL_BURST : 0);
+
+ ret = qcom_fg_write(chip, &intf_ctl,
+ MEM_INTF_CTL, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to configure SRAM access: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_sram_read() - Read data from SRAM
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to read values into
+ * @param addr Address to read from
+ * @param len Number of bytes to read
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_read(struct qcom_fg_chip *chip,
+ u8 *val, u16 addr, int len, int offset)
+{
+ u8 *rd_data = val;
+ int ret = 0;
+
+ ret = qcom_fg_sram_request_access(chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request SRAM access: %d", ret);
+ return ret;
+ }
+
+ spin_lock(&chip->sram_rw_lock);
+
+ dev_vdbg(chip->dev,
+ "Reading address 0x%x with offset %d of length %d from SRAM",
+ addr, len, offset);
+
+ ret = qcom_fg_sram_config_access(chip, 0, (len > 4));
+ if (ret) {
+ dev_err(chip->dev, "Failed to configure SRAM access: %d", ret);
+ goto out;
+ }
+
+ while(len > 0) {
+ /* Set SRAM address register */
+ ret = qcom_fg_write(chip, (u8 *) &addr,
+ MEM_INTF_ADDR_LSB, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to set SRAM address: %d", ret);
+ goto out;
+ }
+
+ ret = qcom_fg_read(chip, rd_data,
+ MEM_INTF_RD_DATA0 + offset, len);
+
+ addr += 4;
+
+ if (ret)
+ goto out;
+
+ rd_data += 4 - offset;
+ len -= 4 - offset;
+ offset = 0;
+ }
+out:
+ spin_unlock(&chip->sram_rw_lock);
+ qcom_fg_sram_release_access(chip);
+
+ return ret;
+}
+
+/**
+ * @brief qcom_fg_sram_write() - Write data to SRAM
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to write values from
+ * @param addr Address to write to
+ * @param len Number of bytes to write
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_sram_write(struct qcom_fg_chip *chip,
+ u8 *val, u16 addr, int len, int offset)
+{
+ u8 *wr_data = val;
+ int ret;
+
+ ret = qcom_fg_sram_request_access(chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request SRAM access: %d", ret);
+ return ret;
+ }
+
+ spin_lock(&chip->sram_rw_lock);
+
+ dev_vdbg(chip->dev,
+ "Wrtiting address 0x%x with offset %d of length %d to SRAM",
+ addr, len, offset);
+
+ ret = qcom_fg_sram_config_access(chip, 1, (len > 4));
+ if (ret) {
+ dev_err(chip->dev, "Failed to configure SRAM access: %d", ret);
+ goto out;
+ }
+
+ while(len > 0) {
+ /* Set SRAM address register */
+ ret = qcom_fg_write(chip, (u8 *) &addr,
+ MEM_INTF_ADDR_LSB, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to set SRAM address: %d", ret);
+ goto out;
+ }
+
+ ret = qcom_fg_write(chip, wr_data,
+ MEM_INTF_WR_DATA0 + offset, len);
+
+ addr += 4;
+
+ if (ret)
+ goto out;
+
+ wr_data += 4 - offset;
+ len -= 4 - offset;
+ offset = 0;
+ }
+out:
+ spin_unlock(&chip->sram_rw_lock);
+ qcom_fg_sram_release_access(chip);
+
+ return ret;
+}
+
+/*************************
+ * BATTERY STATUS
+ * ***********************/
+
+/**
+ * @brief qcom_fg_get_capacity() - Get remaining capacity of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_capacity(struct qcom_fg_chip *chip, int *val)
+{
+ u8 cap[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, cap, BATT_MONOTONIC_SOC, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read capacity: %d", ret);
+ return ret;
+ }
+
+ if (cap[0] != cap[1]) {
+ cap[0] = cap[0] < cap[1] ? cap[0] : cap[1];
+ }
+
+ *val = DIV_ROUND_CLOSEST((cap[0] - 1) * 98, 0xff - 2) + 1;
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_temperature() - Get temperature of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_temperature(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_sram_read(chip, readval, BATT_TEMP, 2, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read temperature: %d", ret);
+ return ret;
+ }
+
+ temp = readval[1] << 8 | readval[0];
+ *val = temp * 625 / 1000 - 2730;
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_current() - Get current being drawn from battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_current(struct qcom_fg_chip *chip, int *val)
+{
+ s16 temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_sram_read(chip, readval, BATT_VOLTAGE_CURRENT, 2, 3);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read current: %d", ret);
+ return ret;
+ }
+
+ temp = (s16)(readval[1] << 8 | readval[0]);
+ *val = div_s64((s64)temp * 152587, 1000);
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_voltage() - Get voltage of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_voltage(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_sram_read(chip, readval, BATT_VOLTAGE_CURRENT, 2, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read voltage: %d", ret);
+ return ret;
+ }
+
+ temp = readval[1] << 8 | readval[0];
+ *val = div_u64((u64)temp * 152587, 1000);
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_get_temp_threshold() - Get configured temperature thresholds
+ *
+ * @param chip Pointer to chip
+ * @param psp Power supply property of temperature limit
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_get_temp_threshold(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int *val)
+{
+ u8 temp;
+ int offset;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ offset = 0;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ offset = 1;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ offset = 2;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ offset = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = qcom_fg_sram_read(chip, &temp, TEMP_THRESHOLD, 1, offset);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read JEITA property %d level: %d\n", psp, ret);
+ return ret;
+ }
+
+ *val = (temp - 30) * 10;
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_set_temp_threshold() - Configure temperature thresholds
+ *
+ * @param chip Pointer to chip
+ * @param psp Power supply property of temperature limit
+ * @param val Pointer to get value from
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_set_temp_threshold(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int val)
+{
+ u8 temp;
+ int offset;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ offset = 0;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ offset = 1;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ offset = 2;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ offset = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ temp = val / 10 + 30;
+
+ ret = qcom_fg_sram_write(chip, &temp, TEMP_THRESHOLD, 1, offset);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to write JEITA property %d level: %d\n", psp, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*************************
+ * BATTERY STATUS, GEN3
+ * ***********************/
+
+/**
+ * @brief qcom_fg_gen3_get_temperature() - Get temperature of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_temperature(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, readval, PARAM_ADDR_BATT_TEMP, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read temperature: %d\n", ret);
+ return ret;
+ }
+
+ temp = ((readval[1] & BATT_TEMP_MSB_MASK) << 8) |
+ (readval[0] & BATT_TEMP_LSB_MASK);
+ temp = DIV_ROUND_CLOSEST(temp * 10, 4);
+
+ *val = temp -2730;
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_gen3_get_current() - Get current being drawn from battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_current(struct qcom_fg_chip *chip, int *val)
+{
+ s16 temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, readval, PARAM_ADDR_BATT_CURRENT, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read current: %d\n", ret);
+ return ret;
+ }
+
+ //handle rev 1 too
+ temp = (s16)(readval[1] << 8 | readval[0]);
+ *val = div_s64((s64)temp * 488281, 1000);
+
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_gen3_get_voltage() - Get voltage of battery
+ *
+ * @param chip Pointer to chip
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_voltage(struct qcom_fg_chip *chip, int *val)
+{
+ int temp;
+ u8 readval[2];
+ int ret;
+
+ ret = qcom_fg_read(chip, readval, PARAM_ADDR_BATT_VOLTAGE, 2);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read voltage: %d\n", ret);
+ return ret;
+ }
+
+ //handle rev 1 too
+ temp = readval[1] << 8 | readval[0];
+ *val = div_u64((u64)temp * 122070, 1000);
+ return 0;
+}
+
+/**
+ * @brief qcom_fg_gen3_get_temp_threshold() - Get configured temperature thresholds
+ *
+ * @param chip Pointer to chip
+ * @param psp Power supply property of temperature limit
+ * @param val Pointer to store value at
+ * @return int 0 on success, negative errno on error
+ */
+static int qcom_fg_gen3_get_temp_threshold(struct qcom_fg_chip *chip,
+ enum power_supply_property psp, int *val)
+{
+ u8 temp;
+ u16 reg;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ reg = BATT_INFO_JEITA_COLD;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ reg = BATT_INFO_JEITA_HOT;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ reg = BATT_INFO_JEITA_COOL;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ reg = BATT_INFO_JEITA_WARM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = qcom_fg_read(chip, &temp, reg, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read JEITA property %d level: %d\n", psp, ret);
+ return ret;
+ }
+
+ /* Resolution is 0.5C. Base is -30C. */
+ *val = (((5 * temp) / 10) - 30) * 10;
+ return 0;
+}
+
+/************************
+ * BATTERY POWER SUPPLY
+ * **********************/
+
+/* Pre-Gen3 fuel gauge. PMI8996 and older */
+static const struct qcom_fg_ops ops_fg = {
+ .get_capacity = qcom_fg_get_capacity,
+ .get_temperature = qcom_fg_get_temperature,
+ .get_current = qcom_fg_get_current,
+ .get_voltage = qcom_fg_get_voltage,
+ .get_temp_threshold = qcom_fg_get_temp_threshold,
+ .set_temp_threshold = qcom_fg_set_temp_threshold,
+};
+
+/* Gen3 fuel gauge. PMI8998 and newer */
+static const struct qcom_fg_ops ops_fg_gen3 = {
+ .get_capacity = qcom_fg_get_capacity,
+ .get_temperature = qcom_fg_gen3_get_temperature,
+ .get_current = qcom_fg_gen3_get_current,
+ .get_voltage = qcom_fg_gen3_get_voltage,
+ .get_temp_threshold = qcom_fg_gen3_get_temp_threshold,
+};
+
+static enum power_supply_property qcom_fg_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_MIN,
+ POWER_SUPPLY_PROP_TEMP_MAX,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+};
+
+static int qcom_fg_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct qcom_fg_chip *chip = power_supply_get_drvdata(psy);
+ int temp, ret = 0;
+
+ dev_dbg(chip->dev, "Getting property: %d", psp);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ /* Get status from charger if available */
+ if (chip->chg_psy &&
+ chip->status != POWER_SUPPLY_STATUS_UNKNOWN) {
+ val->intval = chip->status;
+ break;
+ } else {
+ /*
+ * Fall back to capacity and current-based
+ * status checking
+ */
+ ret = chip->ops->get_capacity(chip, &temp);
+ if (ret) {
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+ }
+ if (temp == 100) {
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ }
+
+ ret = chip->ops->get_current(chip, &temp);
+ if (ret) {
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+ }
+ if (temp < 0)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (temp > 0)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = chip->ops->get_capacity(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = chip->ops->get_current(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = chip->ops->get_voltage(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = chip->batt_info->voltage_min_design_uv;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = chip->batt_info->voltage_max_design_uv;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = chip->batt_info->charge_full_design_uah;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = chip->ops->get_temperature(chip, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ ret = chip->ops->get_temp_threshold(chip, psp, &val->intval);
+ break;
+ default:
+ dev_err(chip->dev, "invalid property: %d\n", psp);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct power_supply_desc batt_psy_desc = {
+ .name = "qcom-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = qcom_fg_props,
+ .num_properties = ARRAY_SIZE(qcom_fg_props),
+ .get_property = qcom_fg_get_property,
+};
+
+/********************
+ * INIT FUNCTIONS
+ * ******************/
+
+static int qcom_fg_iacs_clear_sequence(struct qcom_fg_chip *chip)
+{
+ u8 temp;
+ int ret;
+
+ /* clear the error */
+ ret = qcom_fg_masked_write(chip, MEM_INTF_IMA_CFG, BIT(2), BIT(2));
+ if (ret) {
+ dev_err(chip->dev, "Failed to write IMA_CFG: %d\n", ret);
+ return ret;
+ }
+
+ temp = 0x4;
+ ret = qcom_fg_write(chip, &temp, MEM_INTF_ADDR_LSB + 1, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write MEM_INTF_ADDR_MSB: %d\n", ret);
+ return ret;
+ }
+
+ temp = 0x0;
+ ret = qcom_fg_write(chip, &temp, MEM_INTF_WR_DATA0 + 3, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write WR_DATA3: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_read(chip, &temp, MEM_INTF_RD_DATA0 + 3, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write RD_DATA3: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_masked_write(chip, MEM_INTF_IMA_CFG, BIT(2), 0);
+ if (ret) {
+ dev_err(chip->dev, "Failed to write IMA_CFG: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int qcom_fg_clear_ima(struct qcom_fg_chip *chip,
+ bool check_hw_sts)
+{
+ u8 err_sts, exp_sts, hw_sts;
+ bool run_err_clr_seq = false;
+ int ret;
+
+ ret = qcom_fg_read(chip, &err_sts,
+ MEM_INTF_IMA_ERR_STS, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read IMA_ERR_STS: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_read(chip, &exp_sts,
+ MEM_INTF_IMA_EXP_STS, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read IMA_EXP_STS: %d\n", ret);
+ return ret;
+ }
+
+ if (check_hw_sts) {
+ ret = qcom_fg_read(chip, &hw_sts,
+ MEM_INTF_IMA_HW_STS, 1);
+ if (ret) {
+ dev_err(chip->dev, "Failed to read IMA_HW_STS: %d\n", ret);
+ return ret;
+ }
+ /*
+ * Lower nibble should be equal to upper nibble before SRAM
+ * transactions begins from SW side.
+ */
+ if ((hw_sts & 0x0f) != hw_sts >> 4) {
+ dev_dbg(chip->dev, "IMA HW not in correct state, hw_sts=%x\n",
+ hw_sts);
+ run_err_clr_seq = true;
+ }
+ }
+
+ if (exp_sts & (BIT(0) | BIT(1) | BIT(3) |
+ BIT(4) | BIT(5) | BIT(6) |
+ BIT(7))) {
+ dev_dbg(chip->dev, "IMA exception bit set, exp_sts=%x\n", exp_sts);
+ run_err_clr_seq = true;
+ }
+
+ if (run_err_clr_seq) {
+ ret = qcom_fg_iacs_clear_sequence(chip);
+ if (!ret)
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+irqreturn_t qcom_fg_handle_soc_delta(int irq, void *data)
+{
+ struct qcom_fg_chip *chip = data;
+
+ /* Signal change in state of charge */
+ power_supply_changed(chip->batt_psy);
+ dev_dbg(chip->dev, "SOC changed");
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t qcom_fg_handle_mem_avail(int irq, void *data)
+{
+ struct qcom_fg_chip *chip = data;
+
+ if (qcom_fg_sram_check_access(chip)) {
+ complete_all(&chip->sram_access_granted);
+ dev_dbg(chip->dev, "SRAM access granted");
+ } else {
+ complete_all(&chip->sram_access_revoked);
+ dev_dbg(chip->dev, "SRAM access revoked");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void qcom_fg_status_changed_worker(struct work_struct *work)
+{
+ struct qcom_fg_chip *chip = container_of(work, struct qcom_fg_chip,
+ status_changed_work.work);
+
+ power_supply_changed(chip->batt_psy);
+}
+
+static int qcom_fg_notifier_call(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct qcom_fg_chip *chip = container_of(nb, struct qcom_fg_chip, nb);
+ struct power_supply *psy = v;
+ union power_supply_propval propval;
+ int ret;
+
+ if (psy == chip->chg_psy) {
+ ret = power_supply_get_property(psy,
+ POWER_SUPPLY_PROP_STATUS, &propval);
+ if (ret)
+ chip->status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ chip->status = propval.intval;
+
+ power_supply_changed(chip->batt_psy);
+
+ if (chip->status == POWER_SUPPLY_STATUS_UNKNOWN) {
+ /*
+ * REVISIT: Find better solution or remove current-based
+ * status checking once checking is properly implemented
+ * in charger drivers
+
+ * Sometimes it take a while for current to stabilize,
+ * so signal property change again later to make sure
+ * current-based status is properly detected.
+ */
+ cancel_delayed_work_sync(&chip->status_changed_work);
+ schedule_delayed_work(&chip->status_changed_work,
+ msecs_to_jiffies(1000));
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static int qcom_fg_probe(struct platform_device *pdev)
+{
+ struct power_supply_config supply_config = {};
+ struct qcom_fg_chip *chip;
+ const __be32 *prop_addr;
+ int irq;
+ u8 dma_status;
+ bool error_present;
+ int ret;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->dev = &pdev->dev;
+ chip->ops = of_device_get_match_data(&pdev->dev);
+
+ chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chip->regmap) {
+ dev_err(chip->dev, "Failed to locate the regmap\n");
+ return -ENODEV;
+ }
+
+ /* Get base address */
+ prop_addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
+ if (!prop_addr) {
+ dev_err(chip->dev, "Failed to read SOC base address from dt\n");
+ return -EINVAL;
+ }
+ chip->base = be32_to_cpu(*prop_addr);
+
+ /*
+ * Change the FG_MEM_INT interrupt to track IACS_READY
+ * condition instead of end-of-transaction. This makes sure
+ * that the next transaction starts only after the hw is ready.
+ * IACS_INTR_SRC_SLCT is BIT(3)
+ */
+ ret = qcom_fg_masked_write(chip,
+ MEM_INTF_IMA_CFG, BIT(3), BIT(3));
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to configure interrupt sourete: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_fg_clear_ima(chip, true);
+ if (ret && ret != -EAGAIN) {
+ dev_err(chip->dev, "Failed to clear IMA exception: %d\n", ret);
+ return ret;
+ }
+
+ /* Check and clear DMA errors */
+ ret = qcom_fg_read(chip, &dma_status, MEM_IF_DMA_STS, 1);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read dma_status: %d\n", ret);
+ return ret;
+ }
+
+ error_present = dma_status & (BIT(1) | BIT(2));
+ ret = qcom_fg_masked_write(chip, MEM_IF_DMA_CTL, BIT(0),
+ error_present ? BIT(0) : 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to write dma_ctl: %d\n", ret);
+ return ret;
+ }
+
+ supply_config.drv_data = chip;
+ supply_config.of_node = pdev->dev.of_node;
+
+ chip->batt_psy = devm_power_supply_register(chip->dev,
+ &batt_psy_desc, &supply_config);
+ if (IS_ERR(chip->batt_psy)) {
+ if (PTR_ERR(chip->batt_psy) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to register battery\n");
+ return PTR_ERR(chip->batt_psy);
+ }
+
+ platform_set_drvdata(pdev, chip);
+
+ ret = power_supply_get_battery_info(chip->batt_psy, &chip->batt_info);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to get battery info: %d\n", ret);
+ return ret;
+ }
+
+ /* Initialize SRAM */
+ if (of_device_is_compatible(pdev->dev.of_node, "qcom,pmi8994-fg")) {
+ irq = of_irq_get_byname(pdev->dev.of_node, "mem-avail");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq mem-avail byname: %d\n",
+ irq);
+ return irq;
+ }
+
+ init_completion(&chip->sram_access_granted);
+ init_completion(&chip->sram_access_revoked);
+
+ chip->sram_wq = create_singlethread_workqueue("qcom_fg");
+ INIT_DELAYED_WORK(&chip->sram_release_access_work,
+ qcom_fg_sram_release_access_worker);
+
+ ret = devm_request_threaded_irq(chip->dev, irq, NULL,
+ qcom_fg_handle_mem_avail,
+ IRQF_ONESHOT, "mem-avail", chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request mem-avail IRQ: %d\n", ret);
+ return ret;
+ }
+
+ spin_lock_init(&chip->sram_request_lock);
+ spin_lock_init(&chip->sram_rw_lock);
+ chip->sram_requests = 0;
+ }
+
+ /* Set default temperature thresholds */
+ if (chip->ops->set_temp_threshold) {
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_MIN,
+ BATT_TEMP_JEITA_COLD);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set cold threshold: %d\n", ret);
+ return ret;
+ }
+
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_MAX,
+ BATT_TEMP_JEITA_WARM);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set warm threshold: %d\n", ret);
+ return ret;
+ }
+
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+ BATT_TEMP_JEITA_COOL);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set cool threshold: %d\n", ret);
+ return ret;
+ }
+
+ ret = chip->ops->set_temp_threshold(chip,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+ BATT_TEMP_JEITA_HOT);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to set hot threshold: %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* Get soc-delta IRQ */
+ irq = of_irq_get_byname(pdev->dev.of_node, "soc-delta");
+ if (irq < 0) {
+ dev_err(&pdev->dev, "Failed to get irq soc-delta byname: %d\n",
+ irq);
+ return irq;
+ }
+
+ ret = devm_request_threaded_irq(chip->dev, irq, NULL,
+ qcom_fg_handle_soc_delta,
+ IRQF_ONESHOT, "soc-delta", chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to request soc-delta IRQ: %d\n", ret);
+ return ret;
+ }
+
+ /* Optional: Get charger power supply for status checking */
+ chip->chg_psy = power_supply_get_by_phandle(chip->dev->of_node,
+ "power-supplies");
+ if (IS_ERR(chip->chg_psy)) {
+ ret = PTR_ERR(chip->chg_psy);
+ dev_warn(chip->dev, "Failed to get charger supply: %d\n", ret);
+ chip->chg_psy = NULL;
+ }
+
+ if (chip->chg_psy) {
+ INIT_DELAYED_WORK(&chip->status_changed_work,
+ qcom_fg_status_changed_worker);
+
+ chip->nb.notifier_call = qcom_fg_notifier_call;
+ ret = power_supply_reg_notifier(&chip->nb);
+ if (ret) {
+ dev_err(chip->dev,
+ "Failed to register notifier: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int qcom_fg_remove(struct platform_device *pdev)
+{
+ struct qcom_fg_chip *chip = platform_get_drvdata(pdev);
+
+ power_supply_put_battery_info(chip->chg_psy, chip->batt_info);
+
+ if(chip->sram_wq)
+ destroy_workqueue(chip->sram_wq);
+
+ return 0;
+}
+
+static const struct of_device_id fg_match_id_table[] = {
+ { .compatible = "qcom,pmi8994-fg", .data = &ops_fg },
+ { .compatible = "qcom,pmi8998-fg", .data = &ops_fg_gen3 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fg_match_id_table);
+
+static struct platform_driver qcom_fg_driver = {
+ .probe = qcom_fg_probe,
+ .remove = qcom_fg_remove,
+ .driver = {
+ .name = "qcom-fg",
+ .of_match_table = fg_match_id_table,
+ },
+};
+
+module_platform_driver(qcom_fg_driver);
+
+MODULE_AUTHOR("Caleb Connolly <caleb@connolly.tech>");
+MODULE_AUTHOR("Joel Selvaraj <jo@jsfamily.in>");
+MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
+MODULE_DESCRIPTION("Qualcomm PMIC Fuel Gauge Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/yoga-c630-ec.c b/drivers/power/supply/yoga-c630-ec.c
new file mode 100644
index 00000000000..1fa0b5844e0
--- /dev/null
+++ b/drivers/power/supply/yoga-c630-ec.c
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Linaro Ltd.
+ */
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/usb/typec_mux.h>
+
+#include <drm/drm_bridge.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;
+
+ struct typec_switch *typec_switch;
+
+ 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;
+
+ bool bridge_configured;
+ struct drm_bridge bridge;
+};
+
+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;
+ case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+ val->strval = "05072018";
+ 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,
+ POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
+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_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
+}
+
+static const struct drm_bridge_funcs yoga_c630_ec_bridge_funcs = {
+ .attach = yoga_c630_ec_attach,
+};
+
+static int yoga_c630_ec_query_usb_event(struct yoga_c630_ec *ec)
+{
+ struct device *dev = &ec->client->dev;
+ enum typec_orientation orientation;
+ enum drm_connector_status status;
+ 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;
+ }
+
+ if (FIELD_GET(LENOVO_EC_USB_EVENT_MUX, event))
+ status = connector_status_connected;
+ else
+ status = connector_status_disconnected;
+
+ if (FIELD_GET(LENOVO_EC_USB_EVENT_ORIENTATION, event))
+ orientation = TYPEC_ORIENTATION_REVERSE;
+ else
+ orientation = TYPEC_ORIENTATION_NORMAL;
+
+ typec_switch_set(ec->typec_switch, orientation);
+ if (ec->bridge_configured)
+ drm_bridge_hpd_notify(&ec->bridge, status);
+
+ 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 void yoga_c630_ec_put_switch(void *data)
+{
+ typec_switch_put(data);
+}
+
+static int yoga_c630_ec_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct power_supply_config adp_cfg = {};
+ struct power_supply_config bat_cfg = {};
+ struct fwnode_handle *fwnode;
+ struct yoga_c630_ec *ec;
+ struct device *dev = &client->dev;
+ u32 port;
+ 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);
+ }
+
+ device_for_each_child_node(dev, fwnode) {
+ ret = fwnode_property_read_u32(fwnode, "reg", &port);
+ if (ret < 0)
+ continue;
+
+ /* Got multiple ports, but altmode is only possible on port 1 */
+ if (port != 1)
+ continue;
+
+ ec->bridge.funcs = &yoga_c630_ec_bridge_funcs;
+ ec->bridge.of_node = to_of_node(fwnode);
+ ec->bridge.ops = DRM_BRIDGE_OP_HPD;
+ ec->bridge.type = DRM_MODE_CONNECTOR_USB;
+
+ ret = devm_drm_bridge_add(dev, &ec->bridge);
+ if (ret) {
+ dev_err(dev, "failed to register drm bridge\n");
+ fwnode_handle_put(fwnode);
+ return ret;
+ }
+
+ ec->bridge_configured = true;
+
+ ec->typec_switch = fwnode_typec_switch_get(fwnode);
+ if (IS_ERR(ec->typec_switch))
+ return dev_err_probe(dev, PTR_ERR(ec->typec_switch),
+ "failed to acquire orientation-switch for port 1\n");
+
+ ret = devm_add_action_or_reset(dev, yoga_c630_ec_put_switch,
+ ec->typec_switch);
+ if (ret)
+ return ret;
+ }
+
+ 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 f3ec2469137..6e4b32383ff 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1287,6 +1287,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 b2b059b5ee5..c573b12a806 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -150,6 +150,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/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d440319a794..833cfab7d87 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -676,18 +676,20 @@ static void dasd_profile_start(struct dasd_block *block,
* we count each request only once.
*/
device = cqr->startdev;
- if (device->profile.data) {
- counter = 1; /* request is not yet queued on the start device */
- list_for_each(l, &device->ccw_queue)
- if (++counter >= 31)
- break;
- }
+ if (!device->profile.data)
+ return;
+
+ spin_lock(get_ccwdev_lock(device->cdev));
+ counter = 1; /* request is not yet queued on the start device */
+ list_for_each(l, &device->ccw_queue)
+ if (++counter >= 31)
+ break;
+ spin_unlock(get_ccwdev_lock(device->cdev));
+
spin_lock(&device->profile.lock);
- if (device->profile.data) {
- device->profile.data->dasd_io_nr_req[counter]++;
- if (rq_data_dir(req) == READ)
- device->profile.data->dasd_read_nr_req[counter]++;
- }
+ device->profile.data->dasd_io_nr_req[counter]++;
+ if (rq_data_dir(req) == READ)
+ device->profile.data->dasd_read_nr_req[counter]++;
spin_unlock(&device->profile.lock);
}
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 2e663131ada..1b1b8a41c4d 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -283,7 +283,7 @@ struct dasd_pprc_dev_info {
__u8 secondary; /* 7 Secondary device address */
__u16 pprc_id; /* 8-9 Peer-to-Peer Remote Copy ID */
__u8 reserved2[12]; /* 10-21 reserved */
- __u16 prim_cu_ssid; /* 22-23 Pimary Control Unit SSID */
+ __u16 prim_cu_ssid; /* 22-23 Primary Control Unit SSID */
__u8 reserved3[12]; /* 24-35 reserved */
__u16 sec_cu_ssid; /* 36-37 Secondary Control Unit SSID */
__u8 reserved4[90]; /* 38-127 reserved */
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 4902d45e929..c61e6427384 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -103,10 +103,11 @@ config CCWGROUP
config ISM
tristate "Support for ISM vPCI Adapter"
depends on PCI
+ imply SMC
default n
help
Select this option if you want to use the Internal Shared Memory
- vPCI Adapter.
+ vPCI Adapter. The adapter can be used with the SMC network protocol.
To compile as a module choose M. The module name is ism.
If unsure, choose N.
diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
index 6df7f377d2f..81aabbfbbe2 100644
--- a/drivers/s390/net/ism_drv.c
+++ b/drivers/s390/net/ism_drv.c
@@ -30,7 +30,6 @@ static const struct pci_device_id ism_device_table[] = {
MODULE_DEVICE_TABLE(pci, ism_device_table);
static debug_info_t *ism_debug_info;
-static const struct smcd_ops ism_ops;
#define NO_CLIENT 0xff /* must be >= MAX_CLIENTS */
static struct ism_client *clients[MAX_CLIENTS]; /* use an array rather than */
@@ -289,22 +288,6 @@ static int ism_read_local_gid(struct ism_dev *ism)
return ret;
}
-static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
- u32 vid)
-{
- union ism_query_rgid cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.request.hdr.cmd = ISM_QUERY_RGID;
- cmd.request.hdr.len = sizeof(cmd.request);
-
- cmd.request.rgid = rgid;
- cmd.request.vlan_valid = vid_valid;
- cmd.request.vlan_id = vid;
-
- return ism_cmd(ism, &cmd);
-}
-
static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
{
clear_bit(dmb->sba_idx, ism->sba_bitmap);
@@ -429,23 +412,6 @@ static int ism_del_vlan_id(struct ism_dev *ism, u64 vlan_id)
return ism_cmd(ism, &cmd);
}
-static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
- u32 event_code, u64 info)
-{
- union ism_sig_ieq cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.request.hdr.cmd = ISM_SIGNAL_IEQ;
- cmd.request.hdr.len = sizeof(cmd.request);
-
- cmd.request.rgid = rgid;
- cmd.request.trigger_irq = trigger_irq;
- cmd.request.event_code = event_code;
- cmd.request.info = info;
-
- return ism_cmd(ism, &cmd);
-}
-
static unsigned int max_bytes(unsigned int start, unsigned int len,
unsigned int boundary)
{
@@ -503,14 +469,6 @@ u8 *ism_get_seid(void)
}
EXPORT_SYMBOL_GPL(ism_get_seid);
-static u16 ism_get_chid(struct ism_dev *ism)
-{
- if (!ism || !ism->pdev)
- return 0;
-
- return to_zpci(ism->pdev)->pchid;
-}
-
static void ism_handle_event(struct ism_dev *ism)
{
struct ism_event *entry;
@@ -569,11 +527,6 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static u64 ism_get_local_gid(struct ism_dev *ism)
-{
- return ism->local_gid;
-}
-
static int ism_dev_init(struct ism_dev *ism)
{
struct pci_dev *pdev = ism->pdev;
@@ -774,6 +727,22 @@ module_exit(ism_exit);
/*************************** SMC-D Implementation *****************************/
#if IS_ENABLED(CONFIG_SMC)
+static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
+ u32 vid)
+{
+ union ism_query_rgid cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.request.hdr.cmd = ISM_QUERY_RGID;
+ cmd.request.hdr.len = sizeof(cmd.request);
+
+ cmd.request.rgid = rgid;
+ cmd.request.vlan_valid = vid_valid;
+ cmd.request.vlan_id = vid;
+
+ return ism_cmd(ism, &cmd);
+}
+
static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,
u32 vid)
{
@@ -811,6 +780,23 @@ static int smcd_reset_vlan_required(struct smcd_dev *smcd)
return ism_cmd_simple(smcd->priv, ISM_RESET_VLAN);
}
+static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
+ u32 event_code, u64 info)
+{
+ union ism_sig_ieq cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.request.hdr.cmd = ISM_SIGNAL_IEQ;
+ cmd.request.hdr.len = sizeof(cmd.request);
+
+ cmd.request.rgid = rgid;
+ cmd.request.trigger_irq = trigger_irq;
+ cmd.request.event_code = event_code;
+ cmd.request.info = info;
+
+ return ism_cmd(ism, &cmd);
+}
+
static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq,
u32 event_code, u64 info)
{
@@ -830,11 +816,24 @@ static int smcd_supports_v2(void)
SYSTEM_EID.type[0] != '0';
}
+static u64 ism_get_local_gid(struct ism_dev *ism)
+{
+ return ism->local_gid;
+}
+
static u64 smcd_get_local_gid(struct smcd_dev *smcd)
{
return ism_get_local_gid(smcd->priv);
}
+static u16 ism_get_chid(struct ism_dev *ism)
+{
+ if (!ism || !ism->pdev)
+ return 0;
+
+ return to_zpci(ism->pdev)->pchid;
+}
+
static u16 smcd_get_chid(struct smcd_dev *smcd)
{
return ism_get_chid(smcd->priv);
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 1e15ffa7929..44e9b09de47 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -1143,7 +1143,7 @@ int tb_port_lane_bonding_enable(struct tb_port *port)
* Only set bonding if the link was not already bonded. This
* avoids the lane adapter to re-enter bonding state.
*/
- if (width == TB_LINK_WIDTH_SINGLE) {
+ if (width == TB_LINK_WIDTH_SINGLE && !tb_is_upstream_port(port)) {
ret = tb_port_set_lane_bonding(port, true);
if (ret)
goto err_lane1;
@@ -2880,6 +2880,7 @@ static int tb_switch_lane_bonding_disable(struct tb_switch *sw)
return tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100);
}
+/* Note updating sw->link_width done in tb_switch_update_link_attributes() */
static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width)
{
struct tb_port *up, *down, *port;
@@ -2919,10 +2920,10 @@ static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width)
return ret;
}
- sw->link_width = width;
return 0;
}
+/* Note updating sw->link_width done in tb_switch_update_link_attributes() */
static int tb_switch_asym_disable(struct tb_switch *sw)
{
struct tb_port *up, *down;
@@ -2957,7 +2958,6 @@ static int tb_switch_asym_disable(struct tb_switch *sw)
return ret;
}
- sw->link_width = TB_LINK_WIDTH_DUAL;
return 0;
}
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 5acdeb76686..fd49f86e035 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -213,7 +213,17 @@ static void tb_add_dp_resources(struct tb_switch *sw)
if (!tb_switch_query_dp_resource(sw, port))
continue;
- list_add(&port->list, &tcm->dp_resources);
+ /*
+ * If DP IN on device router exist, position it at the
+ * beginning of the DP resources list, so that it is used
+ * before DP IN of the host router. This way external GPU(s)
+ * will be prioritized when pairing DP IN to a DP OUT.
+ */
+ if (tb_route(sw))
+ list_add(&port->list, &tcm->dp_resources);
+ else
+ list_add_tail(&port->list, &tcm->dp_resources);
+
tb_port_dbg(port, "DP IN resource available\n");
}
}
diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c
index af981778382..02f297f5637 100644
--- a/drivers/usb/cdns3/cdnsp-ring.c
+++ b/drivers/usb/cdns3/cdnsp-ring.c
@@ -1529,6 +1529,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
unsigned long flags;
int counter = 0;
+ local_bh_disable();
spin_lock_irqsave(&pdev->lock, flags);
if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) {
@@ -1541,6 +1542,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
cdnsp_died(pdev);
spin_unlock_irqrestore(&pdev->lock, flags);
+ local_bh_enable();
return IRQ_HANDLED;
}
@@ -1557,6 +1559,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
cdnsp_update_erst_dequeue(pdev, event_ring_deq, 1);
spin_unlock_irqrestore(&pdev->lock, flags);
+ local_bh_enable();
return IRQ_HANDLED;
}
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index b19e38d5fd1..7f8d33f92dd 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -1047,7 +1047,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
dev_notice(ddev, "descriptor type invalid, skip\n");
- continue;
+ goto skip_to_next_descriptor;
}
switch (cap_type) {
@@ -1078,6 +1078,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
break;
}
+skip_to_next_descriptor:
total_len -= length;
buffer += length;
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b4584a0cd48..87480a6e6d9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -622,29 +622,6 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type,
ret = 0;
}
mutex_unlock(&hub->status_mutex);
-
- /*
- * There is no need to lock status_mutex here, because status_mutex
- * protects hub->status, and the phy driver only checks the port
- * status without changing the status.
- */
- if (!ret) {
- struct usb_device *hdev = hub->hdev;
-
- /*
- * Only roothub will be notified of port state changes,
- * since the USB PHY only cares about changes at the next
- * level.
- */
- if (is_root_hub(hdev)) {
- struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
-
- if (hcd->usb_phy)
- usb_phy_notify_port_status(hcd->usb_phy,
- port1 - 1, *status, *change);
- }
- }
-
return ret;
}
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 0144ca8350c..5c7538d498d 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -2015,15 +2015,17 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
{
struct dwc2_qtd *qtd;
struct dwc2_host_chan *chan;
- u32 hcint, hcintmsk;
+ u32 hcint, hcintraw, hcintmsk;
chan = hsotg->hc_ptr_array[chnum];
- hcint = dwc2_readl(hsotg, HCINT(chnum));
+ hcintraw = dwc2_readl(hsotg, HCINT(chnum));
hcintmsk = dwc2_readl(hsotg, HCINTMSK(chnum));
+ hcint = hcintraw & hcintmsk;
+ dwc2_writel(hsotg, hcint, HCINT(chnum));
+
if (!chan) {
dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
- dwc2_writel(hsotg, hcint, HCINT(chnum));
return;
}
@@ -2032,11 +2034,9 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
chnum);
dev_vdbg(hsotg->dev,
" hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
- hcint, hcintmsk, hcint & hcintmsk);
+ hcintraw, hcintmsk, hcint);
}
- dwc2_writel(hsotg, hcint, HCINT(chnum));
-
/*
* If we got an interrupt after someone called
* dwc2_hcd_endpoint_disable() we don't want to crash below
@@ -2046,8 +2046,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
return;
}
- chan->hcint = hcint;
- hcint &= hcintmsk;
+ chan->hcint = hcintraw;
/*
* If the channel was halted due to a dequeue, the qtd list might
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 0328c86ef80..b101dbf8c5d 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -2034,6 +2034,8 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_put(dev);
+ dma_set_max_seg_size(dev, UINT_MAX);
+
return 0;
err_exit_debugfs:
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
index 039bf241769..57ddd2e4302 100644
--- a/drivers/usb/dwc3/drd.c
+++ b/drivers/usb/dwc3/drd.c
@@ -505,6 +505,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL;
mode = DWC3_GCTL_PRTCAP_DEVICE;
}
+ dwc3_set_mode(dwc, mode);
dwc3_role_switch.fwnode = dev_fwnode(dwc->dev);
dwc3_role_switch.set = dwc3_usb_role_switch_set;
@@ -526,7 +527,6 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc)
}
}
- dwc3_set_mode(dwc, mode);
return 0;
}
#else
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 3de43df6bbe..fdf6d5d3c2a 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -546,10 +546,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
pdata ? pdata->hs_phy_irq_index : -1);
if (irq > 0) {
/* Keep wakeup interrupts disabled until suspend */
- irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 HS", qcom);
if (ret) {
dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret);
@@ -561,10 +560,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq",
pdata ? pdata->dp_hs_phy_irq_index : -1);
if (irq > 0) {
- irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 DP_HS", qcom);
if (ret) {
dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret);
@@ -576,10 +574,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq",
pdata ? pdata->dm_hs_phy_irq_index : -1);
if (irq > 0) {
- irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 DM_HS", qcom);
if (ret) {
dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret);
@@ -591,10 +588,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev)
irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq",
pdata ? pdata->ss_phy_irq_index : -1);
if (irq > 0) {
- irq_set_status_flags(irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(qcom->dev, irq, NULL,
qcom_dwc3_resume_irq,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
"qcom_dwc3 SS", qcom);
if (ret) {
dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret);
@@ -758,6 +754,7 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
if (!qcom->dwc3) {
ret = -ENODEV;
dev_err(dev, "failed to get dwc3 platform device\n");
+ of_platform_depopulate(dev);
}
node_put:
@@ -766,9 +763,9 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
return ret;
}
-static struct platform_device *
-dwc3_qcom_create_urs_usb_platdev(struct device *dev)
+static struct platform_device *dwc3_qcom_create_urs_usb_platdev(struct device *dev)
{
+ struct platform_device *urs_usb = NULL;
struct fwnode_handle *fwh;
struct acpi_device *adev;
char name[8];
@@ -788,9 +785,26 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
adev = to_acpi_device_node(fwh);
if (!adev)
- return NULL;
+ goto err_put_handle;
+
+ urs_usb = acpi_create_platform_device(adev, NULL);
+ if (IS_ERR_OR_NULL(urs_usb))
+ goto err_put_handle;
+
+ return urs_usb;
+
+err_put_handle:
+ fwnode_handle_put(fwh);
+
+ return urs_usb;
+}
- return acpi_create_platform_device(adev, NULL);
+static void dwc3_qcom_destroy_urs_usb_platdev(struct platform_device *urs_usb)
+{
+ struct fwnode_handle *fwh = urs_usb->dev.fwnode;
+
+ platform_device_unregister(urs_usb);
+ fwnode_handle_put(fwh);
}
static int dwc3_qcom_probe(struct platform_device *pdev)
@@ -874,13 +888,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
qcom->qscratch_base = devm_ioremap_resource(dev, parent_res);
if (IS_ERR(qcom->qscratch_base)) {
ret = PTR_ERR(qcom->qscratch_base);
- goto clk_disable;
+ goto free_urs;
}
ret = dwc3_qcom_setup_irq(pdev);
if (ret) {
dev_err(dev, "failed to setup IRQs, err=%d\n", ret);
- goto clk_disable;
+ goto free_urs;
}
/*
@@ -899,7 +913,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret);
- goto depopulate;
+ goto free_urs;
}
ret = dwc3_qcom_interconnect_init(qcom);
@@ -931,10 +945,16 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
interconnect_exit:
dwc3_qcom_interconnect_exit(qcom);
depopulate:
- if (np)
+ if (np) {
of_platform_depopulate(&pdev->dev);
- else
- platform_device_put(pdev);
+ } else {
+ device_remove_software_node(&qcom->dwc3->dev);
+ platform_device_del(qcom->dwc3);
+ }
+ platform_device_put(qcom->dwc3);
+free_urs:
+ if (qcom->urs_usb)
+ dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
clk_disable:
for (i = qcom->num_clocks - 1; i >= 0; i--) {
clk_disable_unprepare(qcom->clks[i]);
@@ -953,11 +973,16 @@ static void dwc3_qcom_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int i;
- device_remove_software_node(&qcom->dwc3->dev);
- if (np)
+ if (np) {
of_platform_depopulate(&pdev->dev);
- else
- platform_device_put(pdev);
+ } else {
+ device_remove_software_node(&qcom->dwc3->dev);
+ platform_device_del(qcom->dwc3);
+ }
+ platform_device_put(qcom->dwc3);
+
+ if (qcom->urs_usb)
+ dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb);
for (i = qcom->num_clocks - 1; i >= 0; i--) {
clk_disable_unprepare(qcom->clks[i]);
diff --git a/drivers/usb/dwc3/dwc3-rtk.c b/drivers/usb/dwc3/dwc3-rtk.c
index 590028e8fdc..3cd6b184551 100644
--- a/drivers/usb/dwc3/dwc3-rtk.c
+++ b/drivers/usb/dwc3/dwc3-rtk.c
@@ -183,10 +183,13 @@ static enum usb_device_speed __get_dwc3_maximum_speed(struct device_node *np)
ret = of_property_read_string(dwc3_np, "maximum-speed", &maximum_speed);
if (ret < 0)
- return USB_SPEED_UNKNOWN;
+ goto out;
ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
+out:
+ of_node_put(dwc3_np);
+
return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
}
@@ -339,6 +342,9 @@ static int dwc3_rtk_probe_dwc3_core(struct dwc3_rtk *rtk)
switch_usb2_role(rtk, rtk->cur_role);
+ platform_device_put(dwc3_pdev);
+ of_node_put(dwc3_node);
+
return 0;
err_pdev_put:
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 9d1c40c152d..4bb0553da65 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -1200,7 +1200,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/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 5b3cd455ade..61f3f8bbdce 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -650,9 +650,8 @@ static int check_isoc_ss_overlap(struct mu3h_sch_ep_info *sch_ep, u32 offset)
if (sch_ep->ep_type == ISOC_OUT_EP) {
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
- k = XHCI_MTK_BW_INDEX(base + j + CS_OFFSET);
- /* use cs to indicate existence of in-ss @(base+j) */
- if (tt->fs_bus_bw_in[k])
+ k = XHCI_MTK_BW_INDEX(base + j);
+ if (tt->in_ss_cnt[k])
return -ESCH_SS_OVERLAP;
}
} else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
@@ -769,6 +768,14 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j];
}
}
+
+ if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) {
+ k = XHCI_MTK_BW_INDEX(base);
+ if (used)
+ tt->in_ss_cnt[k]++;
+ else
+ tt->in_ss_cnt[k]--;
+ }
}
if (used)
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index 865b55e23b1..39f7ae7d308 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -38,6 +38,7 @@
* @fs_bus_bw_in: save bandwidth used by FS/LS IN eps in each uframes
* @ls_bus_bw: save bandwidth used by LS eps in each uframes
* @fs_frame_bw: save bandwidth used by FS/LS eps in each FS frames
+ * @in_ss_cnt: the count of Start-Split for IN eps
* @ep_list: Endpoints using this TT
*/
struct mu3h_sch_tt {
@@ -45,6 +46,7 @@ struct mu3h_sch_tt {
u16 fs_bus_bw_in[XHCI_MTK_MAX_ESIT];
u8 ls_bus_bw[XHCI_MTK_MAX_ESIT];
u16 fs_frame_bw[XHCI_MTK_FRAMES_CNT];
+ u8 in_ss_cnt[XHCI_MTK_MAX_ESIT];
struct list_head ep_list;
};
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index b9316137429..732cdeb7392 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/usb/phy.h>
#include <linux/slab.h>
@@ -148,7 +149,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
int ret;
int irq;
struct xhci_plat_priv *priv = NULL;
-
+ bool of_match;
if (usb_disabled())
return -ENODEV;
@@ -253,16 +254,23 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
&xhci->imod_interval);
}
- hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
- if (IS_ERR(hcd->usb_phy)) {
- ret = PTR_ERR(hcd->usb_phy);
- if (ret == -EPROBE_DEFER)
- goto disable_clk;
- hcd->usb_phy = NULL;
- } else {
- ret = usb_phy_init(hcd->usb_phy);
- if (ret)
- goto disable_clk;
+ /*
+ * Drivers such as dwc3 manages PHYs themself (and rely on driver name
+ * matching for the xhci platform device).
+ */
+ of_match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+ if (of_match) {
+ hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
+ if (IS_ERR(hcd->usb_phy)) {
+ ret = PTR_ERR(hcd->usb_phy);
+ if (ret == -EPROBE_DEFER)
+ goto disable_clk;
+ hcd->usb_phy = NULL;
+ } else {
+ ret = usb_phy_init(hcd->usb_phy);
+ if (ret)
+ goto disable_clk;
+ }
}
hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
@@ -285,15 +293,17 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
goto dealloc_usb2_hcd;
}
- xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
- "usb-phy", 1);
- if (IS_ERR(xhci->shared_hcd->usb_phy)) {
- xhci->shared_hcd->usb_phy = NULL;
- } else {
- ret = usb_phy_init(xhci->shared_hcd->usb_phy);
- if (ret)
- dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
- __func__, ret);
+ if (of_match) {
+ xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev,
+ "usb-phy", 1);
+ if (IS_ERR(xhci->shared_hcd->usb_phy)) {
+ xhci->shared_hcd->usb_phy = NULL;
+ } else {
+ ret = usb_phy_init(xhci->shared_hcd->usb_phy);
+ if (ret)
+ dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n",
+ __func__, ret);
+ }
}
xhci->shared_hcd->tpl_support = hcd->tpl_support;
diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c
index a341b2fbb7b..2b45404e973 100644
--- a/drivers/usb/misc/onboard_usb_hub.c
+++ b/drivers/usb/misc/onboard_usb_hub.c
@@ -432,6 +432,8 @@ static const struct usb_device_id onboard_hub_id_table[] = {
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */
{ USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */
+ { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2744) }, /* USB5744 USB 2.0 */
+ { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x5744) }, /* USB5744 USB 3.0 */
{ USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */
{ USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */
{ USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */
diff --git a/drivers/usb/misc/onboard_usb_hub.h b/drivers/usb/misc/onboard_usb_hub.h
index c4e24a7b929..292110e64a1 100644
--- a/drivers/usb/misc/onboard_usb_hub.h
+++ b/drivers/usb/misc/onboard_usb_hub.h
@@ -16,6 +16,11 @@ static const struct onboard_hub_pdata microchip_usb424_data = {
.num_supplies = 1,
};
+static const struct onboard_hub_pdata microchip_usb5744_data = {
+ .reset_us = 0,
+ .num_supplies = 2,
+};
+
static const struct onboard_hub_pdata realtek_rts5411_data = {
.reset_us = 0,
.num_supplies = 1,
@@ -50,6 +55,8 @@ static const struct of_device_id onboard_hub_match[] = {
{ .compatible = "usb424,2412", .data = &microchip_usb424_data, },
{ .compatible = "usb424,2514", .data = &microchip_usb424_data, },
{ .compatible = "usb424,2517", .data = &microchip_usb424_data, },
+ { .compatible = "usb424,2744", .data = &microchip_usb5744_data, },
+ { .compatible = "usb424,5744", .data = &microchip_usb5744_data, },
{ .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
{ .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
{ .compatible = "usb4b4,6504", .data = &cypress_hx3_data, },
diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c
index c9decd0396d..35770e608c6 100644
--- a/drivers/usb/misc/usb-ljca.c
+++ b/drivers/usb/misc/usb-ljca.c
@@ -457,8 +457,8 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
u64 adr, u8 id)
{
struct ljca_match_ids_walk_data wd = { 0 };
- struct acpi_device *parent, *adev;
struct device *dev = adap->dev;
+ struct acpi_device *parent;
char uid[4];
parent = ACPI_COMPANION(dev);
@@ -466,17 +466,7 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap,
return;
/*
- * get auxdev ACPI handle from the ACPI device directly
- * under the parent that matches _ADR.
- */
- adev = acpi_find_child_device(parent, adr, false);
- if (adev) {
- ACPI_COMPANION_SET(&auxdev->dev, adev);
- return;
- }
-
- /*
- * _ADR is a grey area in the ACPI specification, some
+ * Currently LJCA hw doesn't use _ADR instead the shipped
* platforms use _HID to distinguish children devices.
*/
switch (adr) {
@@ -656,10 +646,11 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap)
unsigned int i;
int ret;
+ /* Not all LJCA chips implement SPI, a timeout reading the descriptors is normal */
ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf,
sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS);
if (ret < 0)
- return ret;
+ return (ret == -ETIMEDOUT) ? 0 : ret;
/* check firmware response */
desc = (struct ljca_spi_descriptor *)buf;
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 45dcfaadaf9..4dffcfefd62 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -203,8 +203,8 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5829E_ESIM 0x81e4
#define DELL_PRODUCT_5829E 0x81e6
-#define DELL_PRODUCT_FM101R 0x8213
-#define DELL_PRODUCT_FM101R_ESIM 0x8215
+#define DELL_PRODUCT_FM101R_ESIM 0x8213
+#define DELL_PRODUCT_FM101R 0x8215
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
@@ -609,6 +609,8 @@ static void option_instat_callback(struct urb *urb);
#define UNISOC_VENDOR_ID 0x1782
/* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */
#define TOZED_PRODUCT_LT70C 0x4055
+/* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
+#define LUAT_PRODUCT_AIR720U 0x4e00
/* Device flags */
@@ -1546,7 +1548,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
.driver_info = RSVD(4) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff),
+ .driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
.driver_info = RSVD(4) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) },
@@ -2249,6 +2252,7 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
{ USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x0001, 0xff, 0xff, 0xff) }, /* Fibocom L716-EU (ECM/RNDIS mode) */
{ USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
.driver_info = RSVD(4) | RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
@@ -2271,6 +2275,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 058d5b853b5..bfb6f9481e8 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -4273,7 +4273,8 @@ static void run_state_machine(struct tcpm_port *port)
current_lim = PD_P_SNK_STDBY_MW / 5;
tcpm_set_current_limit(port, current_lim, 5000);
/* Not sink vbus if operational current is 0mA */
- tcpm_set_charge(port, !!pdo_max_current(port->snk_pdo[0]));
+ tcpm_set_charge(port, !port->pd_supported ||
+ pdo_max_current(port->snk_pdo[0]));
if (!port->pd_supported)
tcpm_set_state(port, SNK_READY, 0);
@@ -5391,6 +5392,15 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port)
if (port->bist_request == BDO_MODE_TESTDATA && port->tcpc->set_bist_data)
port->tcpc->set_bist_data(port->tcpc, false);
+ switch (port->state) {
+ case ERROR_RECOVERY:
+ case PORT_RESET:
+ case PORT_RESET_WAIT_OFF:
+ return;
+ default:
+ break;
+ }
+
if (port->ams != NONE_AMS)
port->ams = NONE_AMS;
if (port->hard_reset_count < PD_N_HARD_RESET_COUNT)
diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
index 0e867f531d3..196535ad996 100644
--- a/drivers/usb/typec/tipd/core.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -968,16 +968,17 @@ static int tps25750_start_patch_burst_mode(struct tps6598x *tps)
ret = of_property_match_string(np, "reg-names", "patch-address");
if (ret < 0) {
dev_err(tps->dev, "failed to get patch-address %d\n", ret);
- return ret;
+ goto release_fw;
}
ret = of_property_read_u32_index(np, "reg", ret, &addr);
if (ret)
- return ret;
+ goto release_fw;
if (addr == 0 || (addr >= 0x20 && addr <= 0x23)) {
dev_err(tps->dev, "wrong patch address %u\n", addr);
- return -EINVAL;
+ ret = -EINVAL;
+ goto release_fw;
}
bpms_data.addr = (u8)addr;
@@ -1226,7 +1227,10 @@ static int tps6598x_probe(struct i2c_client *client)
TPS_REG_INT_PLUG_EVENT;
}
- tps->data = device_get_match_data(tps->dev);
+ if (dev_fwnode(tps->dev))
+ tps->data = device_get_match_data(tps->dev);
+ else
+ tps->data = i2c_get_match_data(client);
if (!tps->data)
return -EINVAL;
@@ -1425,7 +1429,7 @@ static const struct of_device_id tps6598x_of_match[] = {
MODULE_DEVICE_TABLE(of, tps6598x_of_match);
static const struct i2c_device_id tps6598x_id[] = {
- { "tps6598x" },
+ { "tps6598x", (kernel_ulong_t)&tps6598x_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, tps6598x_id);
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/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 1ce7f3c7a95..0eb337a8ec0 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -1115,7 +1115,7 @@ struct privcmd_kernel_ioreq {
spinlock_t lock; /* Protects ioeventfds list */
struct list_head ioeventfds;
struct list_head list;
- struct ioreq_port ports[0];
+ struct ioreq_port ports[] __counted_by(vcpus);
};
static irqreturn_t ioeventfd_interrupt(int irq, void *dev_id)
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 946bd56f0ac..0e6c6c25d15 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -405,4 +405,5 @@ const struct dma_map_ops xen_swiotlb_dma_ops = {
.get_sgtable = dma_common_get_sgtable,
.alloc_pages = dma_common_alloc_pages,
.free_pages = dma_common_free_pages,
+ .max_mapping_size = swiotlb_max_mapping_size,
};
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
index 4d04ef2d3ae..1fa8cf23bd3 100644
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -132,8 +132,8 @@ static int afs_probe_cell_name(struct dentry *dentry)
ret = dns_query(net->net, "afsdb", name, len, "srv=1",
NULL, NULL, false);
- if (ret == -ENODATA)
- ret = -EDESTADDRREQ;
+ if (ret == -ENODATA || ret == -ENOKEY)
+ ret = -ENOENT;
return ret;
}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index c9cef3782b4..a812952be1c 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -553,6 +553,7 @@ struct afs_server_entry {
};
struct afs_server_list {
+ struct rcu_head rcu;
afs_volid_t vids[AFS_MAXTYPES]; /* Volume IDs */
refcount_t usage;
unsigned char nr_servers;
diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c
index ed905670350..b59896b1de0 100644
--- a/fs/afs/server_list.c
+++ b/fs/afs/server_list.c
@@ -17,7 +17,7 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
for (i = 0; i < slist->nr_servers; i++)
afs_unuse_server(net, slist->servers[i].server,
afs_server_trace_put_slist);
- kfree(slist);
+ kfree_rcu(slist, rcu);
}
}
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 95d713074dc..a01a0fb2cdb 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -407,6 +407,10 @@ static int afs_validate_fc(struct fs_context *fc)
return PTR_ERR(volume);
ctx->volume = volume;
+ if (volume->type != AFSVL_RWVOL) {
+ ctx->flock_mode = afs_flock_mode_local;
+ fc->sb_flags |= SB_RDONLY;
+ }
}
return 0;
diff --git a/fs/afs/vl_rotate.c b/fs/afs/vl_rotate.c
index 488e58490b1..eb415ce5636 100644
--- a/fs/afs/vl_rotate.c
+++ b/fs/afs/vl_rotate.c
@@ -58,6 +58,12 @@ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc)
}
/* Status load is ordered after lookup counter load */
+ if (cell->dns_status == DNS_LOOKUP_GOT_NOT_FOUND) {
+ pr_warn("No record of cell %s\n", cell->name);
+ vc->error = -ENOENT;
+ return false;
+ }
+
if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
vc->error = -EDESTADDRREQ;
return false;
@@ -285,6 +291,7 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
*/
static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
{
+ struct afs_cell *cell = vc->cell;
static int count;
int i;
@@ -294,6 +301,9 @@ static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc)
rcu_read_lock();
pr_notice("EDESTADDR occurred\n");
+ pr_notice("CELL: %s err=%d\n", cell->name, cell->error);
+ pr_notice("DNS: src=%u st=%u lc=%x\n",
+ cell->dns_source, cell->dns_status, cell->dns_lookup_count);
pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n",
vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error);
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index a5083d447a6..1f5db686366 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -309,9 +309,7 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
struct autofs_fs_context *ctx = fc->fs_private;
struct autofs_sb_info *sbi = s->s_fs_info;
struct inode *root_inode;
- struct dentry *root;
struct autofs_info *ino;
- int ret = -ENOMEM;
pr_debug("starting up, sbi = %p\n", sbi);
@@ -328,56 +326,44 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc)
*/
ino = autofs_new_ino(sbi);
if (!ino)
- goto fail;
+ return -ENOMEM;
root_inode = autofs_get_inode(s, S_IFDIR | 0755);
+ if (!root_inode)
+ return -ENOMEM;
+
root_inode->i_uid = ctx->uid;
root_inode->i_gid = ctx->gid;
+ root_inode->i_fop = &autofs_root_operations;
+ root_inode->i_op = &autofs_dir_inode_operations;
- root = d_make_root(root_inode);
- if (!root)
- goto fail_ino;
-
- root->d_fsdata = ino;
+ s->s_root = d_make_root(root_inode);
+ if (unlikely(!s->s_root)) {
+ autofs_free_ino(ino);
+ return -ENOMEM;
+ }
+ s->s_root->d_fsdata = ino;
if (ctx->pgrp_set) {
sbi->oz_pgrp = find_get_pid(ctx->pgrp);
- if (!sbi->oz_pgrp) {
- ret = invalf(fc, "Could not find process group %d",
- ctx->pgrp);
- goto fail_dput;
- }
- } else {
+ if (!sbi->oz_pgrp)
+ return invalf(fc, "Could not find process group %d",
+ ctx->pgrp);
+ } else
sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID);
- }
if (autofs_type_trigger(sbi->type))
- __managed_dentry_set_managed(root);
-
- root_inode->i_fop = &autofs_root_operations;
- root_inode->i_op = &autofs_dir_inode_operations;
+ /* s->s_root won't be contended so there's little to
+ * be gained by not taking the d_lock when setting
+ * d_flags, even when a lot mounts are being done.
+ */
+ managed_dentry_set_managed(s->s_root);
pr_debug("pipe fd = %d, pgrp = %u\n",
sbi->pipefd, pid_nr(sbi->oz_pgrp));
sbi->flags &= ~AUTOFS_SBI_CATATONIC;
-
- /*
- * Success! Install the root dentry now to indicate completion.
- */
- s->s_root = root;
return 0;
-
- /*
- * Failure ... clean up.
- */
-fail_dput:
- dput(root);
- goto fail;
-fail_ino:
- autofs_free_ino(ino);
-fail:
- return ret;
}
/*
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index a25dd3d2000..b0e8774c435 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -998,6 +998,14 @@ static int ecryptfs_getattr_link(struct mnt_idmap *idmap,
return rc;
}
+static int ecryptfs_do_getattr(const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int flags)
+{
+ if (flags & AT_GETATTR_NOSEC)
+ return vfs_getattr_nosec(path, stat, request_mask, flags);
+ return vfs_getattr(path, stat, request_mask, flags);
+}
+
static int ecryptfs_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags)
@@ -1006,8 +1014,8 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap,
struct kstat lower_stat;
int rc;
- rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat,
- request_mask, flags);
+ rc = ecryptfs_do_getattr(ecryptfs_dentry_to_lower_path(dentry),
+ &lower_stat, request_mask, flags);
if (!rc) {
fsstack_copy_attr_all(d_inode(dentry),
ecryptfs_inode_to_lower(d_inode(dentry)));
diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
index e540648dedc..1d318f85232 100644
--- a/fs/erofs/Kconfig
+++ b/fs/erofs/Kconfig
@@ -21,7 +21,7 @@ config EROFS_FS
performance under extremely memory pressure without extra cost.
See the documentation at <file:Documentation/filesystems/erofs.rst>
- for more details.
+ and the web pages at <https://erofs.docs.kernel.org> for more details.
If unsure, say N.
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 029c761670b..c98aeda8abb 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -220,7 +220,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
up_read(&devs->rwsem);
return 0;
}
- map->m_bdev = dif->bdev_handle->bdev;
+ map->m_bdev = dif->bdev_handle ? dif->bdev_handle->bdev : NULL;
map->m_daxdev = dif->dax_dev;
map->m_dax_part_off = dif->dax_part_off;
map->m_fscache = dif->fscache;
@@ -238,7 +238,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
if (map->m_pa >= startoff &&
map->m_pa < startoff + length) {
map->m_pa -= startoff;
- map->m_bdev = dif->bdev_handle->bdev;
+ map->m_bdev = dif->bdev_handle ?
+ dif->bdev_handle->bdev : NULL;
map->m_daxdev = dif->dax_dev;
map->m_dax_part_off = dif->dax_part_off;
map->m_fscache = dif->fscache;
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index b8ad05b4509..14a79d3226a 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -15,11 +15,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
struct erofs_sb_info *sbi = EROFS_SB(sb);
struct erofs_inode *vi = EROFS_I(inode);
const erofs_off_t inode_loc = erofs_iloc(inode);
-
erofs_blk_t blkaddr, nblks = 0;
void *kaddr;
struct erofs_inode_compact *dic;
struct erofs_inode_extended *die, *copied = NULL;
+ union erofs_inode_i_u iu;
unsigned int ifmt;
int err;
@@ -35,9 +35,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
dic = kaddr + *ofs;
ifmt = le16_to_cpu(dic->i_format);
-
if (ifmt & ~EROFS_I_ALL) {
- erofs_err(inode->i_sb, "unsupported i_format %u of nid %llu",
+ erofs_err(sb, "unsupported i_format %u of nid %llu",
ifmt, vi->nid);
err = -EOPNOTSUPP;
goto err_out;
@@ -45,7 +44,7 @@ static void *erofs_read_inode(struct erofs_buf *buf,
vi->datalayout = erofs_inode_datalayout(ifmt);
if (vi->datalayout >= EROFS_INODE_DATALAYOUT_MAX) {
- erofs_err(inode->i_sb, "unsupported datalayout %u of nid %llu",
+ erofs_err(sb, "unsupported datalayout %u of nid %llu",
vi->datalayout, vi->nid);
err = -EOPNOTSUPP;
goto err_out;
@@ -82,40 +81,15 @@ static void *erofs_read_inode(struct erofs_buf *buf,
vi->xattr_isize = erofs_xattr_ibody_size(die->i_xattr_icount);
inode->i_mode = le16_to_cpu(die->i_mode);
- switch (inode->i_mode & S_IFMT) {
- case S_IFREG:
- case S_IFDIR:
- case S_IFLNK:
- vi->raw_blkaddr = le32_to_cpu(die->i_u.raw_blkaddr);
- break;
- case S_IFCHR:
- case S_IFBLK:
- inode->i_rdev =
- new_decode_dev(le32_to_cpu(die->i_u.rdev));
- break;
- case S_IFIFO:
- case S_IFSOCK:
- inode->i_rdev = 0;
- break;
- default:
- goto bogusimode;
- }
+ iu = die->i_u;
i_uid_write(inode, le32_to_cpu(die->i_uid));
i_gid_write(inode, le32_to_cpu(die->i_gid));
set_nlink(inode, le32_to_cpu(die->i_nlink));
-
- /* extended inode has its own timestamp */
+ /* each extended inode has its own timestamp */
inode_set_ctime(inode, le64_to_cpu(die->i_mtime),
le32_to_cpu(die->i_mtime_nsec));
inode->i_size = le64_to_cpu(die->i_size);
-
- /* total blocks for compressed files */
- if (erofs_inode_is_data_compressed(vi->datalayout))
- nblks = le32_to_cpu(die->i_u.compressed_blocks);
- else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
- /* fill chunked inode summary info */
- vi->chunkformat = le16_to_cpu(die->i_u.c.format);
kfree(copied);
copied = NULL;
break;
@@ -125,49 +99,51 @@ static void *erofs_read_inode(struct erofs_buf *buf,
vi->xattr_isize = erofs_xattr_ibody_size(dic->i_xattr_icount);
inode->i_mode = le16_to_cpu(dic->i_mode);
- switch (inode->i_mode & S_IFMT) {
- case S_IFREG:
- case S_IFDIR:
- case S_IFLNK:
- vi->raw_blkaddr = le32_to_cpu(dic->i_u.raw_blkaddr);
- break;
- case S_IFCHR:
- case S_IFBLK:
- inode->i_rdev =
- new_decode_dev(le32_to_cpu(dic->i_u.rdev));
- break;
- case S_IFIFO:
- case S_IFSOCK:
- inode->i_rdev = 0;
- break;
- default:
- goto bogusimode;
- }
+ iu = dic->i_u;
i_uid_write(inode, le16_to_cpu(dic->i_uid));
i_gid_write(inode, le16_to_cpu(dic->i_gid));
set_nlink(inode, le16_to_cpu(dic->i_nlink));
-
/* use build time for compact inodes */
inode_set_ctime(inode, sbi->build_time, sbi->build_time_nsec);
inode->i_size = le32_to_cpu(dic->i_size);
- if (erofs_inode_is_data_compressed(vi->datalayout))
- nblks = le32_to_cpu(dic->i_u.compressed_blocks);
- else if (vi->datalayout == EROFS_INODE_CHUNK_BASED)
- vi->chunkformat = le16_to_cpu(dic->i_u.c.format);
break;
default:
- erofs_err(inode->i_sb,
- "unsupported on-disk inode version %u of nid %llu",
+ erofs_err(sb, "unsupported on-disk inode version %u of nid %llu",
erofs_inode_version(ifmt), vi->nid);
err = -EOPNOTSUPP;
goto err_out;
}
- if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFDIR:
+ case S_IFLNK:
+ vi->raw_blkaddr = le32_to_cpu(iu.raw_blkaddr);
+ break;
+ case S_IFCHR:
+ case S_IFBLK:
+ inode->i_rdev = new_decode_dev(le32_to_cpu(iu.rdev));
+ break;
+ case S_IFIFO:
+ case S_IFSOCK:
+ inode->i_rdev = 0;
+ break;
+ default:
+ erofs_err(sb, "bogus i_mode (%o) @ nid %llu", inode->i_mode,
+ vi->nid);
+ err = -EFSCORRUPTED;
+ goto err_out;
+ }
+
+ /* total blocks for compressed files */
+ if (erofs_inode_is_data_compressed(vi->datalayout)) {
+ nblks = le32_to_cpu(iu.compressed_blocks);
+ } else if (vi->datalayout == EROFS_INODE_CHUNK_BASED) {
+ /* fill chunked inode summary info */
+ vi->chunkformat = le16_to_cpu(iu.c.format);
if (vi->chunkformat & ~EROFS_CHUNK_FORMAT_ALL) {
- erofs_err(inode->i_sb,
- "unsupported chunk format %x of nid %llu",
+ erofs_err(sb, "unsupported chunk format %x of nid %llu",
vi->chunkformat, vi->nid);
err = -EOPNOTSUPP;
goto err_out;
@@ -191,10 +167,6 @@ static void *erofs_read_inode(struct erofs_buf *buf,
inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
return kaddr;
-bogusimode:
- erofs_err(inode->i_sb, "bogus i_mode (%o) @ nid %llu",
- inode->i_mode, vi->nid);
- err = -EFSCORRUPTED;
err_out:
DBG_BUGON(1);
kfree(copied);
diff --git a/fs/inode.c b/fs/inode.c
index edcd8a61975..f238d987dec 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -215,6 +215,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
lockdep_set_class_and_name(&mapping->invalidate_lock,
&sb->s_type->invalidate_lock_key,
"mapping.invalidate_lock");
+ if (sb->s_iflags & SB_I_STABLE_WRITES)
+ mapping_set_stable_writes(mapping);
inode->i_private = NULL;
inode->i_mapping = mapping;
INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */
diff --git a/fs/libfs.c b/fs/libfs.c
index e9440d55073..c2aa6fd4795 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -399,6 +399,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
return -EINVAL;
}
+ /* In this case, ->private_data is protected by f_pos_lock */
+ file->private_data = NULL;
return vfs_setpos(file, offset, U32_MAX);
}
@@ -428,7 +430,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
inode->i_ino, fs_umode_to_dtype(inode->i_mode));
}
-static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
{
struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
XA_STATE(xas, &so_ctx->xa, ctx->pos);
@@ -437,7 +439,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
while (true) {
dentry = offset_find_next(&xas);
if (!dentry)
- break;
+ return ERR_PTR(-ENOENT);
if (!offset_dir_emit(ctx, dentry)) {
dput(dentry);
@@ -447,6 +449,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
dput(dentry);
ctx->pos = xas.xa_index + 1;
}
+ return NULL;
}
/**
@@ -479,7 +482,12 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
if (!dir_emit_dots(file, ctx))
return 0;
- offset_iterate_dir(d_inode(dir), ctx);
+ /* In this case, ->private_data is protected by f_pos_lock */
+ if (ctx->pos == 2)
+ file->private_data = NULL;
+ else if (file->private_data == ERR_PTR(-ENOENT))
+ return 0;
+ file->private_data = offset_iterate_dir(d_inode(dir), ctx);
return 0;
}
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 345b8f161ca..c63b31a460b 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -171,7 +171,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
type = ovl_path_real(dentry, &realpath);
old_cred = ovl_override_creds(dentry->d_sb);
- err = vfs_getattr(&realpath, stat, request_mask, flags);
+ err = ovl_do_getattr(&realpath, stat, request_mask, flags);
if (err)
goto out;
@@ -196,8 +196,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
(!is_dir ? STATX_NLINK : 0);
ovl_path_lower(dentry, &realpath);
- err = vfs_getattr(&realpath, &lowerstat,
- lowermask, flags);
+ err = ovl_do_getattr(&realpath, &lowerstat, lowermask,
+ flags);
if (err)
goto out;
@@ -249,8 +249,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
ovl_path_lowerdata(dentry, &realpath);
if (realpath.dentry) {
- err = vfs_getattr(&realpath, &lowerdatastat,
- lowermask, flags);
+ err = ovl_do_getattr(&realpath, &lowerdatastat,
+ lowermask, flags);
if (err)
goto out;
} else {
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index ca88b2636a5..05c3dd597fa 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -408,6 +408,14 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
}
+static inline int ovl_do_getattr(const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int flags)
+{
+ if (flags & AT_GETATTR_NOSEC)
+ return vfs_getattr_nosec(path, stat, request_mask, flags);
+ return vfs_getattr(path, stat, request_mask, flags);
+}
+
/* util.c */
int ovl_get_write_access(struct dentry *dentry);
void ovl_put_write_access(struct dentry *dentry);
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 6ffbd81bd10..7558167f603 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -191,7 +191,13 @@ struct cifs_open_info_data {
bool reparse_point;
bool symlink;
};
- __u32 reparse_tag;
+ struct {
+ __u32 tag;
+ union {
+ struct reparse_data_buffer *buf;
+ struct reparse_posix_data *posix;
+ };
+ } reparse;
char *symlink_target;
union {
struct smb2_file_all_info fi;
@@ -395,8 +401,7 @@ struct smb_version_operations {
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const char *full_path,
- char **target_path,
- struct kvec *rsp_iov);
+ char **target_path);
/* open a file for non-posix mounts */
int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
void *buf);
@@ -551,6 +556,9 @@ struct smb_version_operations {
bool (*is_status_io_timeout)(char *buf);
/* Check for STATUS_NETWORK_NAME_DELETED */
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
+ int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
+ struct kvec *rsp_iov,
+ struct cifs_open_info_data *data);
};
struct smb_version_values {
diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h
index a75220db5c1..83ccc51a54d 100644
--- a/fs/smb/client/cifspdu.h
+++ b/fs/smb/client/cifspdu.h
@@ -1356,7 +1356,7 @@ typedef struct smb_com_transaction_ioctl_rsp {
__le32 DataDisplacement;
__u8 SetupCount; /* 1 */
__le16 ReturnedDataLen;
- __u16 ByteCount;
+ __le16 ByteCount;
} __attribute__((packed)) TRANSACT_IOCTL_RSP;
#define CIFS_ACL_OWNER 1
@@ -1509,7 +1509,7 @@ struct reparse_posix_data {
__le16 ReparseDataLength;
__u16 Reserved;
__le64 InodeType; /* LNK, FIFO, CHR etc. */
- char PathBuffer[];
+ __u8 DataBuffer[];
} __attribute__((packed));
struct cifs_quota_data {
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index d87e2c26cce..46feaa0880b 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -210,7 +210,7 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path,
const struct cifs_fid *fid);
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr,
- u32 tag);
+ struct cifs_open_info_data *data);
extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
struct super_block *sb, unsigned int xid);
extern int cifs_get_inode_info_unix(struct inode **pinode,
@@ -458,6 +458,12 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
struct cifs_tcon *tcon,
const unsigned char *searchName, char **syminfo,
const struct nls_table *nls_codepage, int remap);
+extern int cifs_query_reparse_point(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const char *full_path,
+ u32 *tag, struct kvec *rsp,
+ int *rsp_buftype);
extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
__u16 fid, char **symlinkinfo,
const struct nls_table *nls_codepage);
@@ -659,6 +665,12 @@ void cifs_put_tcp_super(struct super_block *sb);
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
char *extract_hostname(const char *unc);
char *extract_sharename(const char *unc);
+int parse_reparse_point(struct reparse_data_buffer *buf,
+ u32 plen, struct cifs_sb_info *cifs_sb,
+ bool unicode, struct cifs_open_info_data *data);
+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+ struct dentry *dentry, struct cifs_tcon *tcon,
+ const char *full_path, umode_t mode, dev_t dev);
#ifdef CONFIG_CIFS_DFS_UPCALL
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 25503f1a4fd..bad91ba6c3a 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -2690,136 +2690,97 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}
-/*
- * Recent Windows versions now create symlinks more frequently
- * and they use the "reparse point" mechanism below. We can of course
- * do symlinks nicely to Samba and other servers which support the
- * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
- * "MF" symlinks optionally, but for recent Windows we really need to
- * reenable the code below and fix the cifs_symlink callers to handle this.
- * In the interim this code has been moved to its own config option so
- * it is not compiled in by default until callers fixed up and more tested.
- */
-int
-CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 fid, char **symlinkinfo,
- const struct nls_table *nls_codepage)
+int cifs_query_reparse_point(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ const char *full_path,
+ u32 *tag, struct kvec *rsp,
+ int *rsp_buftype)
{
- int rc = 0;
- int bytes_returned;
- struct smb_com_transaction_ioctl_req *pSMB;
- struct smb_com_transaction_ioctl_rsp *pSMBr;
- bool is_unicode;
- unsigned int sub_len;
- char *sub_start;
- struct reparse_symlink_data *reparse_buf;
- struct reparse_posix_data *posix_buf;
+ struct cifs_open_parms oparms;
+ TRANSACT_IOCTL_REQ *io_req = NULL;
+ TRANSACT_IOCTL_RSP *io_rsp = NULL;
+ struct cifs_fid fid;
__u32 data_offset, data_count;
- char *end_of_smb;
+ __u8 *start, *end;
+ int io_rsp_len;
+ int oplock = 0;
+ int rc;
- cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
- rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
+
+ if (cap_unix(tcon->ses))
+ return -EOPNOTSUPP;
+
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+ .desired_access = FILE_READ_ATTRIBUTES,
+ .create_options = cifs_create_options(cifs_sb,
+ OPEN_REPARSE_POINT),
+ .disposition = FILE_OPEN,
+ .path = full_path,
+ .fid = &fid,
+ };
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
if (rc)
return rc;
- pSMB->TotalParameterCount = 0 ;
- pSMB->TotalDataCount = 0;
- pSMB->MaxParameterCount = cpu_to_le32(2);
- /* BB find exact data count max from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
- pSMB->MaxSetupCount = 4;
- pSMB->Reserved = 0;
- pSMB->ParameterOffset = 0;
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 4;
- pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
- pSMB->IsFsctl = 1; /* FSCTL */
- pSMB->IsRootFlag = 0;
- pSMB->Fid = fid; /* file handle always le */
- pSMB->ByteCount = 0;
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
+ (void **)&io_req, (void **)&io_rsp);
+ if (rc)
+ goto error;
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
- if (rc) {
- cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
- goto qreparse_out;
- }
+ io_req->TotalParameterCount = 0;
+ io_req->TotalDataCount = 0;
+ io_req->MaxParameterCount = cpu_to_le32(2);
+ /* BB find exact data count max from sess structure BB */
+ io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
+ io_req->MaxSetupCount = 4;
+ io_req->Reserved = 0;
+ io_req->ParameterOffset = 0;
+ io_req->DataCount = 0;
+ io_req->DataOffset = 0;
+ io_req->SetupCount = 4;
+ io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+ io_req->ParameterCount = io_req->TotalParameterCount;
+ io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
+ io_req->IsFsctl = 1;
+ io_req->IsRootFlag = 0;
+ io_req->Fid = fid.netfid;
+ io_req->ByteCount = 0;
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req,
+ (struct smb_hdr *)io_rsp, &io_rsp_len, 0);
+ if (rc)
+ goto error;
- data_offset = le32_to_cpu(pSMBr->DataOffset);
- data_count = le32_to_cpu(pSMBr->DataCount);
- if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
- /* BB also check enough total bytes returned */
- rc = -EIO; /* bad smb */
- goto qreparse_out;
- }
- if (!data_count || (data_count > 2048)) {
+ data_offset = le32_to_cpu(io_rsp->DataOffset);
+ data_count = le32_to_cpu(io_rsp->DataCount);
+ if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
+ !data_count || data_count > 2048) {
rc = -EIO;
- cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
- goto qreparse_out;
- }
- end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
- reparse_buf = (struct reparse_symlink_data *)
- ((char *)&pSMBr->hdr.Protocol + data_offset);
- if ((char *)reparse_buf >= end_of_smb) {
- rc = -EIO;
- goto qreparse_out;
- }
- if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
- cifs_dbg(FYI, "NFS style reparse tag\n");
- posix_buf = (struct reparse_posix_data *)reparse_buf;
-
- if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
- cifs_dbg(FYI, "unsupported file type 0x%llx\n",
- le64_to_cpu(posix_buf->InodeType));
- rc = -EOPNOTSUPP;
- goto qreparse_out;
- }
- is_unicode = true;
- sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
- if (posix_buf->PathBuffer + sub_len > end_of_smb) {
- cifs_dbg(FYI, "reparse buf beyond SMB\n");
- rc = -EIO;
- goto qreparse_out;
- }
- *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
- sub_len, is_unicode, nls_codepage);
- goto qreparse_out;
- } else if (reparse_buf->ReparseTag !=
- cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
- rc = -EOPNOTSUPP;
- goto qreparse_out;
+ goto error;
}
- /* Reparse tag is NTFS symlink */
- sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
- reparse_buf->PathBuffer;
- sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
- if (sub_start + sub_len > end_of_smb) {
- cifs_dbg(FYI, "reparse buf beyond SMB\n");
+ end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
+ start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
+ if (start >= end) {
rc = -EIO;
- goto qreparse_out;
+ goto error;
}
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- is_unicode = true;
- else
- is_unicode = false;
-
- /* BB FIXME investigate remapping reserved chars here */
- *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
- nls_codepage);
- if (!*symlinkinfo)
- rc = -ENOMEM;
-qreparse_out:
- cifs_buf_release(pSMB);
- /*
- * Note: On -EAGAIN error only caller can retry on handle based calls
- * since file handle passed in no longer valid.
- */
+ *tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag);
+ rsp->iov_base = io_rsp;
+ rsp->iov_len = io_rsp_len;
+ *rsp_buftype = CIFS_LARGE_BUFFER;
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ return 0;
+
+error:
+ cifs_buf_release(io_req);
+ CIFSSMBClose(xid, tcon, fid.netfid);
return rc;
}
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index 86fbd3f847d..47f49be69ce 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -459,8 +459,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path,
return -EOPNOTSUPP;
rc = server->ops->query_symlink(xid, tcon,
cifs_sb, full_path,
- &fattr->cf_symlink_target,
- NULL);
+ &fattr->cf_symlink_target);
cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
}
return rc;
@@ -722,10 +721,51 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
}
+static inline dev_t nfs_mkdev(struct reparse_posix_data *buf)
+{
+ u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer);
+
+ return MKDEV(v >> 32, v & 0xffffffff);
+}
+
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr,
- u32 tag)
+ struct cifs_open_info_data *data)
{
+ struct reparse_posix_data *buf = data->reparse.posix;
+ u32 tag = data->reparse.tag;
+
+ if (tag == IO_REPARSE_TAG_NFS && buf) {
+ switch (le64_to_cpu(buf->InodeType)) {
+ case NFS_SPECFILE_CHR:
+ fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_CHR;
+ fattr->cf_rdev = nfs_mkdev(buf);
+ break;
+ case NFS_SPECFILE_BLK:
+ fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_BLK;
+ fattr->cf_rdev = nfs_mkdev(buf);
+ break;
+ case NFS_SPECFILE_FIFO:
+ fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_FIFO;
+ break;
+ case NFS_SPECFILE_SOCK:
+ fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_SOCK;
+ break;
+ case NFS_SPECFILE_LNK:
+ fattr->cf_mode = S_IFLNK | cifs_sb->ctx->file_mode;
+ fattr->cf_dtype = DT_LNK;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return false;
+ }
+ return true;
+ }
+
switch (tag) {
case IO_REPARSE_TAG_LX_SYMLINK:
fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode;
@@ -791,7 +831,7 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr,
fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
if (cifs_open_data_reparse(data) &&
- cifs_reparse_point_to_fattr(cifs_sb, fattr, data->reparse_tag))
+ cifs_reparse_point_to_fattr(cifs_sb, fattr, data))
goto out_reparse;
if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
@@ -856,7 +896,7 @@ cifs_get_file_info(struct file *filp)
data.adjust_tz = false;
if (data.symlink_target) {
data.symlink = true;
- data.reparse_tag = IO_REPARSE_TAG_SYMLINK;
+ data.reparse.tag = IO_REPARSE_TAG_SYMLINK;
}
cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
break;
@@ -1025,7 +1065,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct kvec rsp_iov, *iov = NULL;
int rsp_buftype = CIFS_NO_BUFFER;
- u32 tag = data->reparse_tag;
+ u32 tag = data->reparse.tag;
int rc = 0;
if (!tag && server->ops->query_reparse_point) {
@@ -1035,22 +1075,28 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
if (!rc)
iov = &rsp_iov;
}
- switch ((data->reparse_tag = tag)) {
+
+ rc = -EOPNOTSUPP;
+ switch ((data->reparse.tag = tag)) {
case 0: /* SMB1 symlink */
- iov = NULL;
- fallthrough;
- case IO_REPARSE_TAG_NFS:
- case IO_REPARSE_TAG_SYMLINK:
- if (!data->symlink_target && server->ops->query_symlink) {
+ if (server->ops->query_symlink) {
rc = server->ops->query_symlink(xid, tcon,
cifs_sb, full_path,
- &data->symlink_target,
- iov);
+ &data->symlink_target);
}
break;
case IO_REPARSE_TAG_MOUNT_POINT:
cifs_create_junction_fattr(fattr, sb);
+ rc = 0;
goto out;
+ default:
+ if (data->symlink_target) {
+ rc = 0;
+ } else if (server->ops->parse_reparse_point) {
+ rc = server->ops->parse_reparse_point(cifs_sb,
+ iov, data);
+ }
+ break;
}
cifs_open_info_to_fattr(fattr, data, sb);
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index 47fc22de8d2..d30ea2005eb 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -153,6 +153,10 @@ static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
static void
cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
{
+ struct cifs_open_info_data data = {
+ .reparse = { .tag = fattr->cf_cifstag, },
+ };
+
fattr->cf_uid = cifs_sb->ctx->linux_uid;
fattr->cf_gid = cifs_sb->ctx->linux_gid;
@@ -165,7 +169,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
* reasonably map some of them to directories vs. files vs. symlinks
*/
if ((fattr->cf_cifsattrs & ATTR_REPARSE) &&
- cifs_reparse_point_to_fattr(cifs_sb, fattr, fattr->cf_cifstag))
+ cifs_reparse_point_to_fattr(cifs_sb, fattr, &data))
goto out_reparse;
if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
index 8b2d7c1ca42..816e01c5589 100644
--- a/fs/smb/client/sess.c
+++ b/fs/smb/client/sess.c
@@ -332,10 +332,10 @@ cifs_disable_secondary_channels(struct cifs_ses *ses)
if (iface) {
spin_lock(&ses->iface_lock);
- kref_put(&iface->refcount, release_iface);
iface->num_channels--;
if (iface->weight_fulfilled)
iface->weight_fulfilled--;
+ kref_put(&iface->refcount, release_iface);
spin_unlock(&ses->iface_lock);
}
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 9bf8735cdd1..a9eaba8083b 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -976,64 +976,37 @@ static int cifs_query_symlink(const unsigned int xid,
struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const char *full_path,
- char **target_path,
- struct kvec *rsp_iov)
+ char **target_path)
{
int rc;
- int oplock = 0;
- bool is_reparse_point = !!rsp_iov;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
+ cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
- if (is_reparse_point) {
- cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n");
+ if (!cap_unix(tcon->ses))
return -EOPNOTSUPP;
- }
-
- /* Check for unix extensions */
- if (cap_unix(tcon->ses)) {
- rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
- cifs_sb->local_nls,
- cifs_remap(cifs_sb));
- if (rc == -EREMOTE)
- rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
- target_path,
- cifs_sb->local_nls);
-
- goto out;
- }
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = FILE_READ_ATTRIBUTES,
- .create_options = cifs_create_options(cifs_sb,
- OPEN_REPARSE_POINT),
- .disposition = FILE_OPEN,
- .path = full_path,
- .fid = &fid,
- };
-
- rc = CIFS_open(xid, &oparms, &oplock, NULL);
- if (rc)
- goto out;
-
- rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
- cifs_sb->local_nls);
- if (rc)
- goto out_close;
- convert_delimiter(*target_path, '/');
-out_close:
- CIFSSMBClose(xid, tcon, fid.netfid);
-out:
- if (!rc)
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+ rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
+ cifs_sb->local_nls, cifs_remap(cifs_sb));
+ if (rc == -EREMOTE)
+ rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
+ target_path, cifs_sb->local_nls);
return rc;
}
+static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+ struct kvec *rsp_iov,
+ struct cifs_open_info_data *data)
+{
+ struct reparse_data_buffer *buf;
+ TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
+ bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
+ u32 plen = le16_to_cpu(io->ByteCount);
+
+ buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
+ le32_to_cpu(io->DataOffset));
+ return parse_reparse_point(buf, plen, cifs_sb, unicode, data);
+}
+
static bool
cifs_is_read_op(__u32 oplock)
{
@@ -1068,15 +1041,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct inode *newinode = NULL;
- int rc = -EPERM;
- struct cifs_open_info_data buf = {};
- struct cifs_io_parms io_parms;
- __u32 oplock = 0;
- struct cifs_fid fid;
- struct cifs_open_parms oparms;
- unsigned int bytes_written;
- struct win_dev *pdev;
- struct kvec iov[2];
+ int rc;
if (tcon->unix_ext) {
/*
@@ -1110,74 +1075,18 @@ cifs_make_node(unsigned int xid, struct inode *inode,
d_instantiate(dentry, newinode);
return rc;
}
-
/*
- * SMB1 SFU emulation: should work with all servers, but only
- * support block and char device (no socket & fifo)
+ * Check if mounted with mount parm 'sfu' mount parm.
+ * SFU emulation should work with all servers, but only
+ * supports block and char device (no socket & fifo),
+ * and was used by default in earlier versions of Windows
*/
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
- return rc;
-
- if (!S_ISCHR(mode) && !S_ISBLK(mode))
- return rc;
-
- cifs_dbg(FYI, "sfu compat create special file\n");
-
- oparms = (struct cifs_open_parms) {
- .tcon = tcon,
- .cifs_sb = cifs_sb,
- .desired_access = GENERIC_WRITE,
- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR |
- CREATE_OPTION_SPECIAL),
- .disposition = FILE_CREATE,
- .path = full_path,
- .fid = &fid,
- };
-
- if (tcon->ses->server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
- if (rc)
- return rc;
-
- /*
- * BB Do not bother to decode buf since no local inode yet to put
- * timestamps in, but we can reuse it safely.
- */
-
- pdev = (struct win_dev *)&buf.fi;
- io_parms.pid = current->tgid;
- io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = sizeof(struct win_dev);
- iov[1].iov_base = &buf.fi;
- iov[1].iov_len = sizeof(struct win_dev);
- if (S_ISCHR(mode)) {
- memcpy(pdev->type, "IntxCHR", 8);
- pdev->major = cpu_to_le64(MAJOR(dev));
- pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- } else if (S_ISBLK(mode)) {
- memcpy(pdev->type, "IntxBLK", 8);
- pdev->major = cpu_to_le64(MAJOR(dev));
- pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
- }
- tcon->ses->server->ops->close(xid, tcon, &fid);
- d_drop(dentry);
-
- /* FIXME: add code here to set EAs */
-
- cifs_free_open_info(&buf);
- return rc;
+ return -EPERM;
+ return cifs_sfu_make_node(xid, inode, dentry, tcon,
+ full_path, mode, dev);
}
-
-
struct smb_version_operations smb1_operations = {
.send_cancel = send_nt_cancel,
.compare_fids = cifs_compare_fids,
@@ -1214,6 +1123,7 @@ struct smb_version_operations smb1_operations = {
.is_path_accessible = cifs_is_path_accessible,
.can_echo = cifs_can_echo,
.query_path_info = cifs_query_path_info,
+ .query_reparse_point = cifs_query_reparse_point,
.query_file_info = cifs_query_file_info,
.get_srv_inum = cifs_get_srv_inum,
.set_path_size = CIFSSMBSetEOF,
@@ -1229,6 +1139,7 @@ struct smb_version_operations smb1_operations = {
.rename = CIFSSMBRename,
.create_hardlink = CIFSCreateHardLink,
.query_symlink = cifs_query_symlink,
+ .parse_reparse_point = cifs_parse_reparse_point,
.open = cifs_open_file,
.set_fid = cifs_set_fid,
.close = cifs_close_file,
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 0b89f7008ac..c94940af5d4 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -555,7 +555,7 @@ static int parse_create_response(struct cifs_open_info_data *data,
break;
}
data->reparse_point = reparse_point;
- data->reparse_tag = tag;
+ data->reparse.tag = tag;
return rc;
}
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index a959ed2c9b2..82ab62fd004 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -2866,115 +2866,119 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
return rc;
}
-static int
-parse_reparse_posix(struct reparse_posix_data *symlink_buf,
- u32 plen, char **target_path,
- struct cifs_sb_info *cifs_sb)
+/* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
+static int parse_reparse_posix(struct reparse_posix_data *buf,
+ struct cifs_sb_info *cifs_sb,
+ struct cifs_open_info_data *data)
{
unsigned int len;
-
- /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */
- len = le16_to_cpu(symlink_buf->ReparseDataLength);
-
- if (le64_to_cpu(symlink_buf->InodeType) != NFS_SPECFILE_LNK) {
- cifs_dbg(VFS, "%lld not a supported symlink type\n",
- le64_to_cpu(symlink_buf->InodeType));
+ u64 type;
+
+ switch ((type = le64_to_cpu(buf->InodeType))) {
+ case NFS_SPECFILE_LNK:
+ len = le16_to_cpu(buf->ReparseDataLength);
+ data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer,
+ len, true,
+ cifs_sb->local_nls);
+ if (!data->symlink_target)
+ return -ENOMEM;
+ convert_delimiter(data->symlink_target, '/');
+ cifs_dbg(FYI, "%s: target path: %s\n",
+ __func__, data->symlink_target);
+ break;
+ case NFS_SPECFILE_CHR:
+ case NFS_SPECFILE_BLK:
+ case NFS_SPECFILE_FIFO:
+ case NFS_SPECFILE_SOCK:
+ break;
+ default:
+ cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n",
+ __func__, type);
return -EOPNOTSUPP;
}
-
- *target_path = cifs_strndup_from_utf16(
- symlink_buf->PathBuffer,
- len, true, cifs_sb->local_nls);
- if (!(*target_path))
- return -ENOMEM;
-
- convert_delimiter(*target_path, '/');
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
-
return 0;
}
-static int
-parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
- u32 plen, char **target_path,
- struct cifs_sb_info *cifs_sb)
+static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
+ u32 plen, bool unicode,
+ struct cifs_sb_info *cifs_sb,
+ struct cifs_open_info_data *data)
{
- unsigned int sub_len;
- unsigned int sub_offset;
+ unsigned int len;
+ unsigned int offs;
/* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
- sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
- sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
- if (sub_offset + 20 > plen ||
- sub_offset + sub_len + 20 > plen) {
+ offs = le16_to_cpu(sym->SubstituteNameOffset);
+ len = le16_to_cpu(sym->SubstituteNameLength);
+ if (offs + 20 > plen || offs + len + 20 > plen) {
cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
return -EIO;
}
- *target_path = cifs_strndup_from_utf16(
- symlink_buf->PathBuffer + sub_offset,
- sub_len, true, cifs_sb->local_nls);
- if (!(*target_path))
+ data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs,
+ len, unicode,
+ cifs_sb->local_nls);
+ if (!data->symlink_target)
return -ENOMEM;
- convert_delimiter(*target_path, '/');
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+ convert_delimiter(data->symlink_target, '/');
+ cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target);
return 0;
}
-static int
-parse_reparse_point(struct reparse_data_buffer *buf,
- u32 plen, char **target_path,
- struct cifs_sb_info *cifs_sb)
+int parse_reparse_point(struct reparse_data_buffer *buf,
+ u32 plen, struct cifs_sb_info *cifs_sb,
+ bool unicode, struct cifs_open_info_data *data)
{
- if (plen < sizeof(struct reparse_data_buffer)) {
- cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n",
- plen);
+ if (plen < sizeof(*buf)) {
+ cifs_dbg(VFS, "%s: reparse buffer is too small. Must be at least 8 bytes but was %d\n",
+ __func__, plen);
return -EIO;
}
- if (plen < le16_to_cpu(buf->ReparseDataLength) +
- sizeof(struct reparse_data_buffer)) {
- cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n",
- plen);
+ if (plen < le16_to_cpu(buf->ReparseDataLength) + sizeof(*buf)) {
+ cifs_dbg(VFS, "%s: invalid reparse buf length: %d\n",
+ __func__, plen);
return -EIO;
}
+ data->reparse.buf = buf;
+
/* See MS-FSCC 2.1.2 */
switch (le32_to_cpu(buf->ReparseTag)) {
case IO_REPARSE_TAG_NFS:
- return parse_reparse_posix(
- (struct reparse_posix_data *)buf,
- plen, target_path, cifs_sb);
+ return parse_reparse_posix((struct reparse_posix_data *)buf,
+ cifs_sb, data);
case IO_REPARSE_TAG_SYMLINK:
return parse_reparse_symlink(
(struct reparse_symlink_data_buffer *)buf,
- plen, target_path, cifs_sb);
+ plen, unicode, cifs_sb, data);
+ case IO_REPARSE_TAG_LX_SYMLINK:
+ case IO_REPARSE_TAG_AF_UNIX:
+ case IO_REPARSE_TAG_LX_FIFO:
+ case IO_REPARSE_TAG_LX_CHR:
+ case IO_REPARSE_TAG_LX_BLK:
+ return 0;
default:
- cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
- le32_to_cpu(buf->ReparseTag));
+ cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n",
+ __func__, le32_to_cpu(buf->ReparseTag));
return -EOPNOTSUPP;
}
}
-static int smb2_query_symlink(const unsigned int xid,
- struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb,
- const char *full_path,
- char **target_path,
- struct kvec *rsp_iov)
+static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+ struct kvec *rsp_iov,
+ struct cifs_open_info_data *data)
{
struct reparse_data_buffer *buf;
struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
u32 plen = le32_to_cpu(io->OutputCount);
- cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
-
buf = (struct reparse_data_buffer *)((u8 *)io +
le32_to_cpu(io->OutputOffset));
- return parse_reparse_point(buf, plen, target_path, cifs_sb);
+ return parse_reparse_point(buf, plen, cifs_sb, true, data);
}
static int smb2_query_reparse_point(const unsigned int xid,
@@ -5064,41 +5068,24 @@ smb2_next_header(char *buf)
return le32_to_cpu(hdr->NextCommand);
}
-static int
-smb2_make_node(unsigned int xid, struct inode *inode,
- struct dentry *dentry, struct cifs_tcon *tcon,
- const char *full_path, umode_t mode, dev_t dev)
+int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
+ struct dentry *dentry, struct cifs_tcon *tcon,
+ const char *full_path, umode_t mode, dev_t dev)
{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- int rc = -EPERM;
struct cifs_open_info_data buf = {};
- struct cifs_io_parms io_parms = {0};
- __u32 oplock = 0;
- struct cifs_fid fid;
+ struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_open_parms oparms;
+ struct cifs_io_parms io_parms = {};
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_fid fid;
unsigned int bytes_written;
struct win_dev *pdev;
struct kvec iov[2];
-
- /*
- * Check if mounted with mount parm 'sfu' mount parm.
- * SFU emulation should work with all servers, but only
- * supports block and char device (no socket & fifo),
- * and was used by default in earlier versions of Windows
- */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
- return rc;
-
- /*
- * TODO: Add ability to create instead via reparse point. Windows (e.g.
- * their current NFS server) uses this approach to expose special files
- * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
- */
+ __u32 oplock = server->oplocks ? REQ_OPLOCK : 0;
+ int rc;
if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
- return rc;
-
- cifs_dbg(FYI, "sfu compat create special file\n");
+ return -EPERM;
oparms = (struct cifs_open_parms) {
.tcon = tcon,
@@ -5111,11 +5098,7 @@ smb2_make_node(unsigned int xid, struct inode *inode,
.fid = &fid,
};
- if (tcon->ses->server->oplocks)
- oplock = REQ_OPLOCK;
- else
- oplock = 0;
- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
+ rc = server->ops->open(xid, &oparms, &oplock, &buf);
if (rc)
return rc;
@@ -5123,42 +5106,56 @@ smb2_make_node(unsigned int xid, struct inode *inode,
* BB Do not bother to decode buf since no local inode yet to put
* timestamps in, but we can reuse it safely.
*/
-
pdev = (struct win_dev *)&buf.fi;
io_parms.pid = current->tgid;
io_parms.tcon = tcon;
- io_parms.offset = 0;
- io_parms.length = sizeof(struct win_dev);
- iov[1].iov_base = &buf.fi;
- iov[1].iov_len = sizeof(struct win_dev);
+ io_parms.length = sizeof(*pdev);
+ iov[1].iov_base = pdev;
+ iov[1].iov_len = sizeof(*pdev);
if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major = cpu_to_le64(MAJOR(dev));
pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
} else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major = cpu_to_le64(MAJOR(dev));
pdev->minor = cpu_to_le64(MINOR(dev));
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
} else if (S_ISFIFO(mode)) {
memcpy(pdev->type, "LnxFIFO", 8);
- pdev->major = 0;
- pdev->minor = 0;
- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
- &bytes_written, iov, 1);
}
- tcon->ses->server->ops->close(xid, tcon, &fid);
- d_drop(dentry);
+ rc = server->ops->sync_write(xid, &fid, &io_parms,
+ &bytes_written, iov, 1);
+ server->ops->close(xid, tcon, &fid);
+ d_drop(dentry);
/* FIXME: add code here to set EAs */
-
cifs_free_open_info(&buf);
return rc;
}
+static int smb2_make_node(unsigned int xid, struct inode *inode,
+ struct dentry *dentry, struct cifs_tcon *tcon,
+ const char *full_path, umode_t mode, dev_t dev)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ /*
+ * Check if mounted with mount parm 'sfu' mount parm.
+ * SFU emulation should work with all servers, but only
+ * supports block and char device (no socket & fifo),
+ * and was used by default in earlier versions of Windows
+ */
+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
+ return -EPERM;
+ /*
+ * TODO: Add ability to create instead via reparse point. Windows (e.g.
+ * their current NFS server) uses this approach to expose special files
+ * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
+ */
+ return cifs_sfu_make_node(xid, inode, dentry, tcon,
+ full_path, mode, dev);
+}
+
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct smb_version_operations smb20_operations = {
.compare_fids = smb2_compare_fids,
@@ -5209,7 +5206,7 @@ struct smb_version_operations smb20_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
+ .parse_reparse_point = smb2_parse_reparse_point,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.open = smb2_open_file,
@@ -5311,7 +5308,7 @@ struct smb_version_operations smb21_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
+ .parse_reparse_point = smb2_parse_reparse_point,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.open = smb2_open_file,
@@ -5416,7 +5413,7 @@ struct smb_version_operations smb30_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
+ .parse_reparse_point = smb2_parse_reparse_point,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.open = smb2_open_file,
@@ -5530,7 +5527,7 @@ struct smb_version_operations smb311_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .query_symlink = smb2_query_symlink,
+ .parse_reparse_point = smb2_parse_reparse_point,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.open = smb2_open_file,
diff --git a/fs/stat.c b/fs/stat.c
index 24bb0209e45..f721d26ec3f 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -133,7 +133,8 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
idmap = mnt_idmap(path->mnt);
if (inode->i_op->getattr)
return inode->i_op->getattr(idmap, path, stat,
- request_mask, query_flags);
+ request_mask,
+ query_flags | AT_GETATTR_NOSEC);
generic_fillattr(idmap, request_mask, inode, stat);
return 0;
@@ -166,6 +167,9 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
{
int retval;
+ if (WARN_ON_ONCE(query_flags & AT_GETATTR_NOSEC))
+ return -EPERM;
+
retval = security_inode_getattr(path);
if (retval)
return retval;
diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index f8a594a50ae..0b90869fd80 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -27,16 +27,16 @@
/*
* eventfs_mutex protects the eventfs_inode (ei) dentry. Any access
* to the ei->dentry must be done under this mutex and after checking
- * if ei->is_freed is not set. The ei->dentry is released under the
- * mutex at the same time ei->is_freed is set. If ei->is_freed is set
- * then the ei->dentry is invalid.
+ * if ei->is_freed is not set. When ei->is_freed is set, the dentry
+ * is on its way to being freed after the last dput() is made on it.
*/
static DEFINE_MUTEX(eventfs_mutex);
/*
* The eventfs_inode (ei) itself is protected by SRCU. It is released from
* its parent's list and will have is_freed set (under eventfs_mutex).
- * After the SRCU grace period is over, the ei may be freed.
+ * After the SRCU grace period is over and the last dput() is called
+ * the ei is freed.
*/
DEFINE_STATIC_SRCU(eventfs_srcu);
@@ -95,7 +95,7 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
if (!(dentry->d_inode->i_mode & S_IFDIR)) {
if (!ei->entry_attrs) {
ei->entry_attrs = kzalloc(sizeof(*ei->entry_attrs) * ei->nr_entries,
- GFP_KERNEL);
+ GFP_NOFS);
if (!ei->entry_attrs) {
ret = -ENOMEM;
goto out;
@@ -326,7 +326,8 @@ create_file_dentry(struct eventfs_inode *ei, int idx,
struct eventfs_attr *attr = NULL;
struct dentry **e_dentry = &ei->d_children[idx];
struct dentry *dentry;
- bool invalidate = false;
+
+ WARN_ON_ONCE(!inode_is_locked(parent->d_inode));
mutex_lock(&eventfs_mutex);
if (ei->is_freed) {
@@ -348,15 +349,8 @@ create_file_dentry(struct eventfs_inode *ei, int idx,
mutex_unlock(&eventfs_mutex);
- /* The lookup already has the parent->d_inode locked */
- if (!lookup)
- inode_lock(parent->d_inode);
-
dentry = create_file(name, mode, attr, parent, data, fops);
- if (!lookup)
- inode_unlock(parent->d_inode);
-
mutex_lock(&eventfs_mutex);
if (IS_ERR_OR_NULL(dentry)) {
@@ -365,12 +359,14 @@ create_file_dentry(struct eventfs_inode *ei, int idx,
* created the dentry for this e_dentry. In which case
* use that one.
*
- * Note, with the mutex held, the e_dentry cannot have content
- * and the ei->is_freed be true at the same time.
+ * If ei->is_freed is set, the e_dentry is currently on its
+ * way to being freed, don't return it. If e_dentry is NULL
+ * it means it was already freed.
*/
- dentry = *e_dentry;
- if (WARN_ON_ONCE(dentry && ei->is_freed))
+ if (ei->is_freed)
dentry = NULL;
+ else
+ dentry = *e_dentry;
/* The lookup does not need to up the dentry refcount */
if (dentry && !lookup)
dget(dentry);
@@ -387,17 +383,14 @@ create_file_dentry(struct eventfs_inode *ei, int idx,
* Otherwise it means two dentries exist with the same name.
*/
WARN_ON_ONCE(!ei->is_freed);
- invalidate = true;
+ dentry = NULL;
}
mutex_unlock(&eventfs_mutex);
- if (invalidate)
- d_invalidate(dentry);
-
- if (lookup || invalidate)
+ if (lookup)
dput(dentry);
- return invalidate ? NULL : dentry;
+ return dentry;
}
/**
@@ -437,9 +430,10 @@ static struct dentry *
create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
struct dentry *parent, bool lookup)
{
- bool invalidate = false;
struct dentry *dentry = NULL;
+ WARN_ON_ONCE(!inode_is_locked(parent->d_inode));
+
mutex_lock(&eventfs_mutex);
if (pei->is_freed || ei->is_freed) {
mutex_unlock(&eventfs_mutex);
@@ -456,15 +450,8 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
}
mutex_unlock(&eventfs_mutex);
- /* The lookup already has the parent->d_inode locked */
- if (!lookup)
- inode_lock(parent->d_inode);
-
dentry = create_dir(ei, parent);
- if (!lookup)
- inode_unlock(parent->d_inode);
-
mutex_lock(&eventfs_mutex);
if (IS_ERR_OR_NULL(dentry) && !ei->is_freed) {
@@ -473,8 +460,8 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
* created the dentry for this e_dentry. In which case
* use that one.
*
- * Note, with the mutex held, the e_dentry cannot have content
- * and the ei->is_freed be true at the same time.
+ * If ei->is_freed is set, the e_dentry is currently on its
+ * way to being freed.
*/
dentry = ei->dentry;
if (dentry && !lookup)
@@ -493,16 +480,14 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei,
* Otherwise it means two dentries exist with the same name.
*/
WARN_ON_ONCE(!ei->is_freed);
- invalidate = true;
+ dentry = NULL;
}
mutex_unlock(&eventfs_mutex);
- if (invalidate)
- d_invalidate(dentry);
- if (lookup || invalidate)
+ if (lookup)
dput(dentry);
- return invalidate ? NULL : dentry;
+ return dentry;
}
/**
@@ -632,7 +617,7 @@ static int add_dentries(struct dentry ***dentries, struct dentry *d, int cnt)
{
struct dentry **tmp;
- tmp = krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_KERNEL);
+ tmp = krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_NOFS);
if (!tmp)
return -1;
tmp[cnt] = d;
@@ -698,6 +683,7 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
return -ENOMEM;
}
+ inode_lock(parent->d_inode);
list_for_each_entry_srcu(ei_child, &ei->children, list,
srcu_read_lock_held(&eventfs_srcu)) {
d = create_dir_dentry(ei, ei_child, parent, false);
@@ -730,6 +716,7 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
cnt++;
}
}
+ inode_unlock(parent->d_inode);
srcu_read_unlock(&eventfs_srcu, idx);
ret = dcache_dir_open(inode, file);
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index 5b54948514f..ae648deed01 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -509,20 +509,15 @@ struct dentry *eventfs_start_creating(const char *name, struct dentry *parent)
struct dentry *dentry;
int error;
+ /* Must always have a parent. */
+ if (WARN_ON_ONCE(!parent))
+ return ERR_PTR(-EINVAL);
+
error = simple_pin_fs(&trace_fs_type, &tracefs_mount,
&tracefs_mount_count);
if (error)
return ERR_PTR(error);
- /*
- * If the parent is not specified, we create it in the root.
- * We need the root dentry to do this, which is in the super
- * block. A pointer to that is in the struct vfsmount that we
- * have around.
- */
- if (!parent)
- parent = tracefs_mount->mnt_root;
-
if (unlikely(IS_DEADDIR(parent->d_inode)))
dentry = ERR_PTR(-ENOENT);
else
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index ac6ba646624..a013b87ab8d 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -562,7 +562,8 @@ xfs_dquot_from_disk(
struct xfs_dquot *dqp,
struct xfs_buf *bp)
{
- struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset;
+ struct xfs_dqblk *dqb = xfs_buf_offset(bp, dqp->q_bufoffset);
+ struct xfs_disk_dquot *ddqp = &dqb->dd_diskdq;
/*
* Ensure that we got the type and ID we were looking for.
@@ -1250,7 +1251,7 @@ xfs_qm_dqflush(
}
/* Flush the incore dquot to the ondisk buffer. */
- dqblk = bp->b_addr + dqp->q_bufoffset;
+ dqblk = xfs_buf_offset(bp, dqp->q_bufoffset);
xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp);
/*
diff --git a/fs/xfs/xfs_dquot_item_recover.c b/fs/xfs/xfs_dquot_item_recover.c
index 8966ba84239..2c2720ce692 100644
--- a/fs/xfs/xfs_dquot_item_recover.c
+++ b/fs/xfs/xfs_dquot_item_recover.c
@@ -19,6 +19,7 @@
#include "xfs_log.h"
#include "xfs_log_priv.h"
#include "xfs_log_recover.h"
+#include "xfs_error.h"
STATIC void
xlog_recover_dquot_ra_pass2(
@@ -65,6 +66,7 @@ xlog_recover_dquot_commit_pass2(
{
struct xfs_mount *mp = log->l_mp;
struct xfs_buf *bp;
+ struct xfs_dqblk *dqb;
struct xfs_disk_dquot *ddq, *recddq;
struct xfs_dq_logformat *dq_f;
xfs_failaddr_t fa;
@@ -130,14 +132,14 @@ xlog_recover_dquot_commit_pass2(
return error;
ASSERT(bp);
- ddq = xfs_buf_offset(bp, dq_f->qlf_boffset);
+ dqb = xfs_buf_offset(bp, dq_f->qlf_boffset);
+ ddq = &dqb->dd_diskdq;
/*
* If the dquot has an LSN in it, recover the dquot only if it's less
* than the lsn of the transaction we are replaying.
*/
if (xfs_has_crc(mp)) {
- struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddq;
xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn);
if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
@@ -147,10 +149,23 @@ xlog_recover_dquot_commit_pass2(
memcpy(ddq, recddq, item->ri_buf[1].i_len);
if (xfs_has_crc(mp)) {
- xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk),
+ xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
}
+ /* Validate the recovered dquot. */
+ fa = xfs_dqblk_verify(log->l_mp, dqb, dq_f->qlf_id);
+ if (fa) {
+ XFS_CORRUPTION_ERROR("Bad dquot after recovery",
+ XFS_ERRLEVEL_LOW, mp, dqb,
+ sizeof(struct xfs_dqblk));
+ xfs_alert(mp,
+ "Metadata corruption detected at %pS, dquot 0x%x",
+ fa, dq_f->qlf_id);
+ error = -EFSCORRUPTED;
+ goto out_release;
+ }
+
ASSERT(dq_f->qlf_size == 2);
ASSERT(bp->b_mount == mp);
bp->b_flags |= _XBF_LOGRECOVERY;
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 3dc47937da5..3beb470f189 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -569,6 +569,14 @@ extern void xfs_setup_inode(struct xfs_inode *ip);
extern void xfs_setup_iops(struct xfs_inode *ip);
extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init);
+static inline void xfs_update_stable_writes(struct xfs_inode *ip)
+{
+ if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev))
+ mapping_set_stable_writes(VFS_I(ip)->i_mapping);
+ else
+ mapping_clear_stable_writes(VFS_I(ip)->i_mapping);
+}
+
/*
* When setting up a newly allocated inode, we need to call
* xfs_finish_inode_setup() once the inode is fully instantiated at
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index a82470e027f..6c3919687ea 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1121,23 +1121,25 @@ xfs_ioctl_setattr_xflags(
struct fileattr *fa)
{
struct xfs_mount *mp = ip->i_mount;
+ bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);
uint64_t i_flags2;
- /* Can't change realtime flag if any extents are allocated. */
- if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
- XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
- return -EINVAL;
+ if (rtflag != XFS_IS_REALTIME_INODE(ip)) {
+ /* Can't change realtime flag if any extents are allocated. */
+ if (ip->i_df.if_nextents || ip->i_delayed_blks)
+ return -EINVAL;
+ }
- /* If realtime flag is set then must have realtime device */
- if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
+ if (rtflag) {
+ /* If realtime flag is set then must have realtime device */
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
xfs_extlen_to_rtxmod(mp, ip->i_extsize))
return -EINVAL;
- }
- /* Clear reflink if we are actually able to set the rt flag. */
- if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
- ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
+ /* Clear reflink if we are actually able to set the rt flag. */
+ if (xfs_is_reflink_inode(ip))
+ ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
+ }
/* diflags2 only valid for v3 inodes. */
i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
@@ -1148,6 +1150,14 @@ xfs_ioctl_setattr_xflags(
ip->i_diflags2 = i_flags2;
xfs_diflags_to_iflags(ip, false);
+
+ /*
+ * Make the stable writes flag match that of the device the inode
+ * resides on when flipping the RT flag.
+ */
+ if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode))
+ xfs_update_stable_writes(ip);
+
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
XFS_STATS_INC(mp, xs_ig_attrchg);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index fdfda4fba12..a0d77f5f512 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1298,6 +1298,13 @@ xfs_setup_inode(
gfp_mask = mapping_gfp_mask(inode->i_mapping);
mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS)));
+ /*
+ * For real-time inodes update the stable write flags to that of the RT
+ * device instead of the data device.
+ */
+ if (S_ISREG(inode->i_mode) && XFS_IS_REALTIME_INODE(ip))
+ xfs_update_stable_writes(ip);
+
/*
* If there is no attribute fork no ACL can exist on this inode,
* and it can't have any file capabilities attached to it either.
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index afeed6e7204..1216d72c650 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -542,6 +542,7 @@ int acpi_device_set_power(struct acpi_device *device, int state);
int acpi_bus_init_power(struct acpi_device *device);
int acpi_device_fix_up_power(struct acpi_device *device);
void acpi_device_fix_up_power_extended(struct acpi_device *adev);
+void acpi_device_fix_up_power_children(struct acpi_device *adev);
int acpi_bus_update_power(acpi_handle handle, int *state_p);
int acpi_device_update_power(struct acpi_device *device, int *state_p);
bool acpi_bus_power_manageable(acpi_handle handle);
diff --git a/include/asm-generic/qspinlock.h b/include/asm-generic/qspinlock.h
index 995513fa269..0655aa5b57b 100644
--- a/include/asm-generic/qspinlock.h
+++ b/include/asm-generic/qspinlock.h
@@ -70,7 +70,7 @@ static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
*/
static __always_inline int queued_spin_value_unlocked(struct qspinlock lock)
{
- return !atomic_read(&lock.val);
+ return !lock.val.counter;
}
/**
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/interconnect/qcom,sm6115.h b/include/dt-bindings/interconnect/qcom,sm6115.h
new file mode 100644
index 00000000000..a41d3b254c2
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,sm6115.h
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SM6115_H
+#define __DT_BINDINGS_INTERCONNECT_QCOM_SM6115_H
+
+/* BIMC */
+#define MASTER_AMPSS_M0 0
+#define MASTER_SNOC_BIMC_RT 1
+#define MASTER_SNOC_BIMC_NRT 2
+#define SNOC_BIMC_MAS 3
+#define MASTER_GRAPHICS_3D 4
+#define MASTER_TCU_0 5
+#define SLAVE_EBI_CH0 6
+#define BIMC_SNOC_SLV 7
+
+/* CNOC */
+#define SNOC_CNOC_MAS 0
+#define MASTER_QDSS_DAP 1
+#define SLAVE_AHB2PHY_USB 2
+#define SLAVE_APSS_THROTTLE_CFG 3
+#define SLAVE_BIMC_CFG 4
+#define SLAVE_BOOT_ROM 5
+#define SLAVE_CAMERA_NRT_THROTTLE_CFG 6
+#define SLAVE_CAMERA_RT_THROTTLE_CFG 7
+#define SLAVE_CAMERA_CFG 8
+#define SLAVE_CLK_CTL 9
+#define SLAVE_RBCPR_CX_CFG 10
+#define SLAVE_RBCPR_MX_CFG 11
+#define SLAVE_CRYPTO_0_CFG 12
+#define SLAVE_DCC_CFG 13
+#define SLAVE_DDR_PHY_CFG 14
+#define SLAVE_DDR_SS_CFG 15
+#define SLAVE_DISPLAY_CFG 16
+#define SLAVE_DISPLAY_THROTTLE_CFG 17
+#define SLAVE_GPU_CFG 18
+#define SLAVE_GPU_THROTTLE_CFG 19
+#define SLAVE_HWKM_CORE 20
+#define SLAVE_IMEM_CFG 21
+#define SLAVE_IPA_CFG 22
+#define SLAVE_LPASS 23
+#define SLAVE_MAPSS 24
+#define SLAVE_MDSP_MPU_CFG 25
+#define SLAVE_MESSAGE_RAM 26
+#define SLAVE_CNOC_MSS 27
+#define SLAVE_PDM 28
+#define SLAVE_PIMEM_CFG 29
+#define SLAVE_PKA_CORE 30
+#define SLAVE_PMIC_ARB 31
+#define SLAVE_QDSS_CFG 32
+#define SLAVE_QM_CFG 33
+#define SLAVE_QM_MPU_CFG 34
+#define SLAVE_QPIC 35
+#define SLAVE_QUP_0 36
+#define SLAVE_RPM 37
+#define SLAVE_SDCC_1 38
+#define SLAVE_SDCC_2 39
+#define SLAVE_SECURITY 40
+#define SLAVE_SNOC_CFG 41
+#define SLAVE_TCSR 42
+#define SLAVE_TLMM 43
+#define SLAVE_USB3 44
+#define SLAVE_VENUS_CFG 45
+#define SLAVE_VENUS_THROTTLE_CFG 46
+#define SLAVE_VSENSE_CTRL_CFG 47
+#define SLAVE_SERVICE_CNOC 48
+
+/* SNOC */
+#define MASTER_CRYPTO_CORE0 0
+#define MASTER_SNOC_CFG 1
+#define MASTER_TIC 2
+#define MASTER_ANOC_SNOC 3
+#define BIMC_SNOC_MAS 4
+#define MASTER_PIMEM 5
+#define MASTER_QDSS_BAM 6
+#define MASTER_QPIC 7
+#define MASTER_QUP_0 8
+#define MASTER_IPA 9
+#define MASTER_QDSS_ETR 10
+#define MASTER_SDCC_1 11
+#define MASTER_SDCC_2 12
+#define MASTER_USB3 13
+#define SLAVE_APPSS 14
+#define SNOC_CNOC_SLV 15
+#define SLAVE_OCIMEM 16
+#define SLAVE_PIMEM 17
+#define SNOC_BIMC_SLV 18
+#define SLAVE_SERVICE_SNOC 19
+#define SLAVE_QDSS_STM 20
+#define SLAVE_TCU 21
+#define SLAVE_ANOC_SNOC 22
+
+/* CLK Virtual */
+#define MASTER_QUP_CORE_0 0
+#define SLAVE_QUP_CORE_0 1
+
+/* MMRT Virtual */
+#define MASTER_CAMNOC_HF 0
+#define MASTER_MDP_PORT0 1
+#define SLAVE_SNOC_BIMC_RT 2
+
+/* MMNRT Virtual */
+#define MASTER_CAMNOC_SF 0
+#define MASTER_VIDEO_P0 1
+#define MASTER_VIDEO_PROC 2
+#define SLAVE_SNOC_BIMC_NRT 3
+
+#endif
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/blk-pm.h b/include/linux/blk-pm.h
index 2580e05a8ab..004b38a538f 100644
--- a/include/linux/blk-pm.h
+++ b/include/linux/blk-pm.h
@@ -15,7 +15,6 @@ extern int blk_pre_runtime_suspend(struct request_queue *q);
extern void blk_post_runtime_suspend(struct request_queue *q, int err);
extern void blk_pre_runtime_resume(struct request_queue *q);
extern void blk_post_runtime_resume(struct request_queue *q);
-extern void blk_set_runtime_active(struct request_queue *q);
#else
static inline void blk_pm_runtime_init(struct request_queue *q,
struct device *dev) {}
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 24213a99cc7..aa4d19d0bc9 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -301,6 +301,17 @@ struct bpf_func_state {
struct tnum callback_ret_range;
bool in_async_callback_fn;
bool in_exception_callback_fn;
+ /* For callback calling functions that limit number of possible
+ * callback executions (e.g. bpf_loop) keeps track of current
+ * simulated iteration number.
+ * Value in frame N refers to number of times callback with frame
+ * N+1 was simulated, e.g. for the following call:
+ *
+ * bpf_loop(..., fn, ...); | suppose current frame is N
+ * | fn would be simulated in frame N+1
+ * | number of simulations is tracked in frame N
+ */
+ u32 callback_depth;
/* The following fields should be last. See copy_func_state() */
int acquired_refs;
@@ -400,6 +411,7 @@ struct bpf_verifier_state {
struct bpf_idx_pair *jmp_history;
u32 jmp_history_cnt;
u32 dfs_depth;
+ u32 callback_unroll_depth;
};
#define bpf_get_spilled_reg(slot, frame, mask) \
@@ -511,6 +523,10 @@ struct bpf_insn_aux_data {
* this instruction, regardless of any heuristics
*/
bool force_checkpoint;
+ /* true if instruction is a call to a helper function that
+ * accepts callback function as a parameter.
+ */
+ bool calls_callback;
};
#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 5a8387a4a71..bf43f3ff666 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -679,6 +679,7 @@ struct hid_device { /* device report descriptor */
struct list_head debug_list;
spinlock_t debug_list_lock;
wait_queue_head_t debug_wait;
+ struct kref ref;
unsigned int id; /* system unique id */
@@ -687,6 +688,8 @@ struct hid_device { /* device report descriptor */
#endif /* CONFIG_BPF */
};
+void hiddev_free(struct kref *ref);
+
#define to_hid_device(pdev) \
container_of(pdev, struct hid_device, dev)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a16c9cc063f..2564e209465 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1797,6 +1797,13 @@ enum netdev_ml_priv_type {
ML_PRIV_CAN,
};
+enum netdev_stat_type {
+ NETDEV_PCPU_STAT_NONE,
+ NETDEV_PCPU_STAT_LSTATS, /* struct pcpu_lstats */
+ NETDEV_PCPU_STAT_TSTATS, /* struct pcpu_sw_netstats */
+ NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */
+};
+
/**
* struct net_device - The DEVICE structure.
*
@@ -1991,10 +1998,14 @@ enum netdev_ml_priv_type {
*
* @ml_priv: Mid-layer private
* @ml_priv_type: Mid-layer private type
- * @lstats: Loopback statistics
- * @tstats: Tunnel statistics
- * @dstats: Dummy statistics
- * @vstats: Virtual ethernet statistics
+ *
+ * @pcpu_stat_type: Type of device statistics which the core should
+ * allocate/free: none, lstats, tstats, dstats. none
+ * means the driver is handling statistics allocation/
+ * freeing internally.
+ * @lstats: Loopback statistics: packets, bytes
+ * @tstats: Tunnel statistics: RX/TX packets, RX/TX bytes
+ * @dstats: Dummy statistics: RX/TX/drop packets, RX/TX bytes
*
* @garp_port: GARP
* @mrp_port: MRP
@@ -2354,6 +2365,7 @@ struct net_device {
void *ml_priv;
enum netdev_ml_priv_type ml_priv_type;
+ enum netdev_stat_type pcpu_stat_type:8;
union {
struct pcpu_lstats __percpu *lstats;
struct pcpu_sw_netstats __percpu *tstats;
@@ -2755,6 +2767,16 @@ struct pcpu_sw_netstats {
struct u64_stats_sync syncp;
} __aligned(4 * sizeof(u64));
+struct pcpu_dstats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 rx_drops;
+ u64 tx_packets;
+ u64 tx_bytes;
+ u64 tx_drops;
+ struct u64_stats_sync syncp;
+} __aligned(8 * sizeof(u64));
+
struct pcpu_lstats {
u64_stats_t packets;
u64_stats_t bytes;
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index bcc1ea44b4e..06142ff7f9c 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -204,6 +204,8 @@ enum mapping_flags {
AS_NO_WRITEBACK_TAGS = 5,
AS_LARGE_FOLIO_SUPPORT = 6,
AS_RELEASE_ALWAYS, /* Call ->release_folio(), even if no private data */
+ AS_STABLE_WRITES, /* must wait for writeback before modifying
+ folio contents */
};
/**
@@ -289,6 +291,21 @@ static inline void mapping_clear_release_always(struct address_space *mapping)
clear_bit(AS_RELEASE_ALWAYS, &mapping->flags);
}
+static inline bool mapping_stable_writes(const struct address_space *mapping)
+{
+ return test_bit(AS_STABLE_WRITES, &mapping->flags);
+}
+
+static inline void mapping_set_stable_writes(struct address_space *mapping)
+{
+ set_bit(AS_STABLE_WRITES, &mapping->flags);
+}
+
+static inline void mapping_clear_stable_writes(struct address_space *mapping)
+{
+ clear_bit(AS_STABLE_WRITES, &mapping->flags);
+}
+
static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
{
return mapping->gfp_mask;
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/linux/usb/phy.h b/include/linux/usb/phy.h
index b513749582d..e4de6bc1f69 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -144,10 +144,6 @@ struct usb_phy {
*/
int (*set_wakeup)(struct usb_phy *x, bool enabled);
- /* notify phy port status change */
- int (*notify_port_status)(struct usb_phy *x, int port,
- u16 portstatus, u16 portchange);
-
/* notify phy connect status change */
int (*notify_connect)(struct usb_phy *x,
enum usb_device_speed speed);
@@ -320,15 +316,6 @@ usb_phy_set_wakeup(struct usb_phy *x, bool enabled)
return 0;
}
-static inline int
-usb_phy_notify_port_status(struct usb_phy *x, int port, u16 portstatus, u16 portchange)
-{
- if (x && x->notify_port_status)
- return x->notify_port_status(x, port, portstatus, portchange);
- else
- return 0;
-}
-
static inline int
usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed)
{
diff --git a/include/net/netkit.h b/include/net/netkit.h
index 0ba2e6b847c..9ec0163739f 100644
--- a/include/net/netkit.h
+++ b/include/net/netkit.h
@@ -10,6 +10,7 @@ int netkit_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog);
int netkit_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
int netkit_prog_detach(const union bpf_attr *attr, struct bpf_prog *prog);
int netkit_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr);
+INDIRECT_CALLABLE_DECLARE(struct net_device *netkit_peer_dev(struct net_device *dev));
#else
static inline int netkit_prog_attach(const union bpf_attr *attr,
struct bpf_prog *prog)
@@ -34,5 +35,10 @@ static inline int netkit_prog_query(const union bpf_attr *attr,
{
return -EINVAL;
}
+
+static inline struct net_device *netkit_peer_dev(struct net_device *dev)
+{
+ return NULL;
+}
#endif /* CONFIG_NETKIT */
#endif /* __NET_NETKIT_H */
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 4c53a5ef625..f7e537f64db 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -328,7 +328,7 @@
E_(rxrpc_rtt_tx_ping, "PING")
#define rxrpc_rtt_rx_traces \
- EM(rxrpc_rtt_rx_cancel, "CNCL") \
+ EM(rxrpc_rtt_rx_other_ack, "OACK") \
EM(rxrpc_rtt_rx_obsolete, "OBSL") \
EM(rxrpc_rtt_rx_lost, "LOST") \
EM(rxrpc_rtt_rx_ping_response, "PONG") \
diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h
index 6c80f96049b..282e90aeb16 100644
--- a/include/uapi/linux/fcntl.h
+++ b/include/uapi/linux/fcntl.h
@@ -116,5 +116,8 @@
#define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to
compare object identity and may not
be usable to open_by_handle_at(2) */
+#if defined(__KERNEL__)
+#define AT_GETATTR_NOSEC 0x80000000
+#endif
#endif /* _UAPI_LINUX_FCNTL_H */
diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
index 022a520e31f..e8d5ee027b4 100644
--- a/include/uapi/linux/input-event-codes.h
+++ b/include/uapi/linux/input-event-codes.h
@@ -866,6 +866,7 @@
#define ABS_VOLUME 0x20
#define ABS_PROFILE 0x21
+#define ABS_SND_PROFILE 0x22
#define ABS_MISC 0x28
@@ -974,4 +975,12 @@
#define SND_MAX 0x07
#define SND_CNT (SND_MAX+1)
+/*
+ * ABS_SND_PROFILE values
+ */
+
+#define SND_PROFILE_SILENT 0x00
+#define SND_PROFILE_VIBRATE 0x01
+#define SND_PROFILE_RING 0x02
+
#endif
diff --git a/io_uring/fs.c b/io_uring/fs.c
index 08e3b175469..eccea851dd5 100644
--- a/io_uring/fs.c
+++ b/io_uring/fs.c
@@ -254,7 +254,7 @@ int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
newf = u64_to_user_ptr(READ_ONCE(sqe->addr2));
lnk->flags = READ_ONCE(sqe->hardlink_flags);
- lnk->oldpath = getname(oldf);
+ lnk->oldpath = getname_uflags(oldf, lnk->flags);
if (IS_ERR(lnk->oldpath))
return PTR_ERR(lnk->oldpath);
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 7034be55533..f521c5965a9 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -1258,7 +1258,7 @@ int io_import_fixed(int ddir, struct iov_iter *iter,
*/
const struct bio_vec *bvec = imu->bvec;
- if (offset <= bvec->bv_len) {
+ if (offset < bvec->bv_len) {
/*
* Note, huge pages buffers consists of one large
* bvec entry and should always go this way. The other
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 6da370a047f..af2819d5c8e 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -547,13 +547,12 @@ static bool is_dynptr_ref_function(enum bpf_func_id func_id)
return func_id == BPF_FUNC_dynptr_data;
}
-static bool is_callback_calling_kfunc(u32 btf_id);
+static bool is_sync_callback_calling_kfunc(u32 btf_id);
static bool is_bpf_throw_kfunc(struct bpf_insn *insn);
-static bool is_callback_calling_function(enum bpf_func_id func_id)
+static bool is_sync_callback_calling_function(enum bpf_func_id func_id)
{
return func_id == BPF_FUNC_for_each_map_elem ||
- func_id == BPF_FUNC_timer_set_callback ||
func_id == BPF_FUNC_find_vma ||
func_id == BPF_FUNC_loop ||
func_id == BPF_FUNC_user_ringbuf_drain;
@@ -564,6 +563,18 @@ static bool is_async_callback_calling_function(enum bpf_func_id func_id)
return func_id == BPF_FUNC_timer_set_callback;
}
+static bool is_callback_calling_function(enum bpf_func_id func_id)
+{
+ return is_sync_callback_calling_function(func_id) ||
+ is_async_callback_calling_function(func_id);
+}
+
+static bool is_sync_callback_calling_insn(struct bpf_insn *insn)
+{
+ return (bpf_helper_call(insn) && is_sync_callback_calling_function(insn->imm)) ||
+ (bpf_pseudo_kfunc_call(insn) && is_sync_callback_calling_kfunc(insn->imm));
+}
+
static bool is_storage_get_function(enum bpf_func_id func_id)
{
return func_id == BPF_FUNC_sk_storage_get ||
@@ -1808,6 +1819,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
dst_state->first_insn_idx = src->first_insn_idx;
dst_state->last_insn_idx = src->last_insn_idx;
dst_state->dfs_depth = src->dfs_depth;
+ dst_state->callback_unroll_depth = src->callback_unroll_depth;
dst_state->used_as_loop_entry = src->used_as_loop_entry;
for (i = 0; i <= src->curframe; i++) {
dst = dst_state->frame[i];
@@ -3439,13 +3451,11 @@ static void mark_insn_zext(struct bpf_verifier_env *env,
reg->subreg_def = DEF_NOT_SUBREG;
}
-static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
- enum reg_arg_type t)
+static int __check_reg_arg(struct bpf_verifier_env *env, struct bpf_reg_state *regs, u32 regno,
+ enum reg_arg_type t)
{
- struct bpf_verifier_state *vstate = env->cur_state;
- struct bpf_func_state *state = vstate->frame[vstate->curframe];
struct bpf_insn *insn = env->prog->insnsi + env->insn_idx;
- struct bpf_reg_state *reg, *regs = state->regs;
+ struct bpf_reg_state *reg;
bool rw64;
if (regno >= MAX_BPF_REG) {
@@ -3486,6 +3496,15 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
return 0;
}
+static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
+ enum reg_arg_type t)
+{
+ struct bpf_verifier_state *vstate = env->cur_state;
+ struct bpf_func_state *state = vstate->frame[vstate->curframe];
+
+ return __check_reg_arg(env, state->regs, regno, t);
+}
+
static void mark_jmp_point(struct bpf_verifier_env *env, int idx)
{
env->insn_aux_data[idx].jmp_point = true;
@@ -3724,6 +3743,8 @@ static void fmt_stack_mask(char *buf, ssize_t buf_sz, u64 stack_mask)
}
}
+static bool calls_callback(struct bpf_verifier_env *env, int insn_idx);
+
/* For given verifier state backtrack_insn() is called from the last insn to
* the first insn. Its purpose is to compute a bitmask of registers and
* stack slots that needs precision in the parent verifier state.
@@ -3899,16 +3920,13 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
return -EFAULT;
return 0;
}
- } else if ((bpf_helper_call(insn) &&
- is_callback_calling_function(insn->imm) &&
- !is_async_callback_calling_function(insn->imm)) ||
- (bpf_pseudo_kfunc_call(insn) && is_callback_calling_kfunc(insn->imm))) {
- /* callback-calling helper or kfunc call, which means
- * we are exiting from subprog, but unlike the subprog
- * call handling above, we shouldn't propagate
- * precision of r1-r5 (if any requested), as they are
- * not actually arguments passed directly to callback
- * subprogs
+ } else if (is_sync_callback_calling_insn(insn) && idx != subseq_idx - 1) {
+ /* exit from callback subprog to callback-calling helper or
+ * kfunc call. Use idx/subseq_idx check to discern it from
+ * straight line code backtracking.
+ * Unlike the subprog call handling above, we shouldn't
+ * propagate precision of r1-r5 (if any requested), as they are
+ * not actually arguments passed directly to callback subprogs
*/
if (bt_reg_mask(bt) & ~BPF_REGMASK_ARGS) {
verbose(env, "BUG regs %x\n", bt_reg_mask(bt));
@@ -3943,10 +3961,18 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
} else if (opcode == BPF_EXIT) {
bool r0_precise;
+ /* Backtracking to a nested function call, 'idx' is a part of
+ * the inner frame 'subseq_idx' is a part of the outer frame.
+ * In case of a regular function call, instructions giving
+ * precision to registers R1-R5 should have been found already.
+ * In case of a callback, it is ok to have R1-R5 marked for
+ * backtracking, as these registers are set by the function
+ * invoking callback.
+ */
+ if (subseq_idx >= 0 && calls_callback(env, subseq_idx))
+ for (i = BPF_REG_1; i <= BPF_REG_5; i++)
+ bt_clear_reg(bt, i);
if (bt_reg_mask(bt) & BPF_REGMASK_ARGS) {
- /* if backtracing was looking for registers R1-R5
- * they should have been found already.
- */
verbose(env, "BUG regs %x\n", bt_reg_mask(bt));
WARN_ONCE(1, "verifier backtracking bug");
return -EFAULT;
@@ -9350,7 +9376,7 @@ static void clear_caller_saved_regs(struct bpf_verifier_env *env,
/* after the call registers r0 - r5 were scratched */
for (i = 0; i < CALLER_SAVED_REGS; i++) {
mark_reg_not_init(env, regs, caller_saved[i]);
- check_reg_arg(env, caller_saved[i], DST_OP_NO_MARK);
+ __check_reg_arg(env, regs, caller_saved[i], DST_OP_NO_MARK);
}
}
@@ -9363,11 +9389,10 @@ static int set_callee_state(struct bpf_verifier_env *env,
struct bpf_func_state *caller,
struct bpf_func_state *callee, int insn_idx);
-static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
- int *insn_idx, int subprog,
- set_callee_state_fn set_callee_state_cb)
+static int setup_func_entry(struct bpf_verifier_env *env, int subprog, int callsite,
+ set_callee_state_fn set_callee_state_cb,
+ struct bpf_verifier_state *state)
{
- struct bpf_verifier_state *state = env->cur_state;
struct bpf_func_state *caller, *callee;
int err;
@@ -9377,54 +9402,72 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
return -E2BIG;
}
- caller = state->frame[state->curframe];
if (state->frame[state->curframe + 1]) {
verbose(env, "verifier bug. Frame %d already allocated\n",
state->curframe + 1);
return -EFAULT;
}
+ caller = state->frame[state->curframe];
+ callee = kzalloc(sizeof(*callee), GFP_KERNEL);
+ if (!callee)
+ return -ENOMEM;
+ state->frame[state->curframe + 1] = callee;
+
+ /* callee cannot access r0, r6 - r9 for reading and has to write
+ * into its own stack before reading from it.
+ * callee can read/write into caller's stack
+ */
+ init_func_state(env, callee,
+ /* remember the callsite, it will be used by bpf_exit */
+ callsite,
+ state->curframe + 1 /* frameno within this callchain */,
+ subprog /* subprog number within this prog */);
+ /* Transfer references to the callee */
+ err = copy_reference_state(callee, caller);
+ err = err ?: set_callee_state_cb(env, caller, callee, callsite);
+ if (err)
+ goto err_out;
+
+ /* only increment it after check_reg_arg() finished */
+ state->curframe++;
+
+ return 0;
+
+err_out:
+ free_func_state(callee);
+ state->frame[state->curframe + 1] = NULL;
+ return err;
+}
+
+static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+ int insn_idx, int subprog,
+ set_callee_state_fn set_callee_state_cb)
+{
+ struct bpf_verifier_state *state = env->cur_state, *callback_state;
+ struct bpf_func_state *caller, *callee;
+ int err;
+
+ caller = state->frame[state->curframe];
err = btf_check_subprog_call(env, subprog, caller->regs);
if (err == -EFAULT)
return err;
- if (subprog_is_global(env, subprog)) {
- if (err) {
- verbose(env, "Caller passes invalid args into func#%d\n",
- subprog);
- return err;
- } else {
- if (env->log.level & BPF_LOG_LEVEL)
- verbose(env,
- "Func#%d is global and valid. Skipping.\n",
- subprog);
- clear_caller_saved_regs(env, caller->regs);
-
- /* All global functions return a 64-bit SCALAR_VALUE */
- mark_reg_unknown(env, caller->regs, BPF_REG_0);
- caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
-
- /* continue with next insn after call */
- return 0;
- }
- }
/* set_callee_state is used for direct subprog calls, but we are
* interested in validating only BPF helpers that can call subprogs as
* callbacks
*/
- if (set_callee_state_cb != set_callee_state) {
- env->subprog_info[subprog].is_cb = true;
- if (bpf_pseudo_kfunc_call(insn) &&
- !is_callback_calling_kfunc(insn->imm)) {
- verbose(env, "verifier bug: kfunc %s#%d not marked as callback-calling\n",
- func_id_name(insn->imm), insn->imm);
- return -EFAULT;
- } else if (!bpf_pseudo_kfunc_call(insn) &&
- !is_callback_calling_function(insn->imm)) { /* helper */
- verbose(env, "verifier bug: helper %s#%d not marked as callback-calling\n",
- func_id_name(insn->imm), insn->imm);
- return -EFAULT;
- }
+ env->subprog_info[subprog].is_cb = true;
+ if (bpf_pseudo_kfunc_call(insn) &&
+ !is_sync_callback_calling_kfunc(insn->imm)) {
+ verbose(env, "verifier bug: kfunc %s#%d not marked as callback-calling\n",
+ func_id_name(insn->imm), insn->imm);
+ return -EFAULT;
+ } else if (!bpf_pseudo_kfunc_call(insn) &&
+ !is_callback_calling_function(insn->imm)) { /* helper */
+ verbose(env, "verifier bug: helper %s#%d not marked as callback-calling\n",
+ func_id_name(insn->imm), insn->imm);
+ return -EFAULT;
}
if (insn->code == (BPF_JMP | BPF_CALL) &&
@@ -9435,53 +9478,83 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
/* there is no real recursion here. timer callbacks are async */
env->subprog_info[subprog].is_async_cb = true;
async_cb = push_async_cb(env, env->subprog_info[subprog].start,
- *insn_idx, subprog);
+ insn_idx, subprog);
if (!async_cb)
return -EFAULT;
callee = async_cb->frame[0];
callee->async_entry_cnt = caller->async_entry_cnt + 1;
/* Convert bpf_timer_set_callback() args into timer callback args */
- err = set_callee_state_cb(env, caller, callee, *insn_idx);
+ err = set_callee_state_cb(env, caller, callee, insn_idx);
if (err)
return err;
+ return 0;
+ }
+
+ /* for callback functions enqueue entry to callback and
+ * proceed with next instruction within current frame.
+ */
+ callback_state = push_stack(env, env->subprog_info[subprog].start, insn_idx, false);
+ if (!callback_state)
+ return -ENOMEM;
+
+ err = setup_func_entry(env, subprog, insn_idx, set_callee_state_cb,
+ callback_state);
+ if (err)
+ return err;
+
+ callback_state->callback_unroll_depth++;
+ callback_state->frame[callback_state->curframe - 1]->callback_depth++;
+ caller->callback_depth = 0;
+ return 0;
+}
+
+static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
+ int *insn_idx)
+{
+ struct bpf_verifier_state *state = env->cur_state;
+ struct bpf_func_state *caller;
+ int err, subprog, target_insn;
+
+ target_insn = *insn_idx + insn->imm + 1;
+ subprog = find_subprog(env, target_insn);
+ if (subprog < 0) {
+ verbose(env, "verifier bug. No program starts at insn %d\n", target_insn);
+ return -EFAULT;
+ }
+
+ caller = state->frame[state->curframe];
+ err = btf_check_subprog_call(env, subprog, caller->regs);
+ if (err == -EFAULT)
+ return err;
+ if (subprog_is_global(env, subprog)) {
+ if (err) {
+ verbose(env, "Caller passes invalid args into func#%d\n", subprog);
+ return err;
+ }
+
+ if (env->log.level & BPF_LOG_LEVEL)
+ verbose(env, "Func#%d is global and valid. Skipping.\n", subprog);
clear_caller_saved_regs(env, caller->regs);
+
+ /* All global functions return a 64-bit SCALAR_VALUE */
mark_reg_unknown(env, caller->regs, BPF_REG_0);
caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG;
+
/* continue with next insn after call */
return 0;
}
- callee = kzalloc(sizeof(*callee), GFP_KERNEL);
- if (!callee)
- return -ENOMEM;
- state->frame[state->curframe + 1] = callee;
-
- /* callee cannot access r0, r6 - r9 for reading and has to write
- * into its own stack before reading from it.
- * callee can read/write into caller's stack
+ /* for regular function entry setup new frame and continue
+ * from that frame.
*/
- init_func_state(env, callee,
- /* remember the callsite, it will be used by bpf_exit */
- *insn_idx /* callsite */,
- state->curframe + 1 /* frameno within this callchain */,
- subprog /* subprog number within this prog */);
-
- /* Transfer references to the callee */
- err = copy_reference_state(callee, caller);
+ err = setup_func_entry(env, subprog, *insn_idx, set_callee_state, state);
if (err)
- goto err_out;
-
- err = set_callee_state_cb(env, caller, callee, *insn_idx);
- if (err)
- goto err_out;
+ return err;
clear_caller_saved_regs(env, caller->regs);
- /* only increment it after check_reg_arg() finished */
- state->curframe++;
-
/* and go analyze first insn of the callee */
*insn_idx = env->subprog_info[subprog].start - 1;
@@ -9489,14 +9562,10 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn
verbose(env, "caller:\n");
print_verifier_state(env, caller, true);
verbose(env, "callee:\n");
- print_verifier_state(env, callee, true);
+ print_verifier_state(env, state->frame[state->curframe], true);
}
- return 0;
-err_out:
- free_func_state(callee);
- state->frame[state->curframe + 1] = NULL;
- return err;
+ return 0;
}
int map_set_for_each_callback_args(struct bpf_verifier_env *env,
@@ -9540,22 +9609,6 @@ static int set_callee_state(struct bpf_verifier_env *env,
return 0;
}
-static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
- int *insn_idx)
-{
- int subprog, target_insn;
-
- target_insn = *insn_idx + insn->imm + 1;
- subprog = find_subprog(env, target_insn);
- if (subprog < 0) {
- verbose(env, "verifier bug. No program starts at insn %d\n",
- target_insn);
- return -EFAULT;
- }
-
- return __check_func_call(env, insn, insn_idx, subprog, set_callee_state);
-}
-
static int set_map_elem_callback_state(struct bpf_verifier_env *env,
struct bpf_func_state *caller,
struct bpf_func_state *callee,
@@ -9748,9 +9801,10 @@ static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env)
static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
{
- struct bpf_verifier_state *state = env->cur_state;
+ struct bpf_verifier_state *state = env->cur_state, *prev_st;
struct bpf_func_state *caller, *callee;
struct bpf_reg_state *r0;
+ bool in_callback_fn;
int err;
callee = state->frame[state->curframe];
@@ -9779,6 +9833,11 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
verbose_invalid_scalar(env, r0, &range, "callback return", "R0");
return -EINVAL;
}
+ if (!calls_callback(env, callee->callsite)) {
+ verbose(env, "BUG: in callback at %d, callsite %d !calls_callback\n",
+ *insn_idx, callee->callsite);
+ return -EFAULT;
+ }
} else {
/* return to the caller whatever r0 had in the callee */
caller->regs[BPF_REG_0] = *r0;
@@ -9796,7 +9855,16 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
return err;
}
- *insn_idx = callee->callsite + 1;
+ /* for callbacks like bpf_loop or bpf_for_each_map_elem go back to callsite,
+ * there function call logic would reschedule callback visit. If iteration
+ * converges is_state_visited() would prune that visit eventually.
+ */
+ in_callback_fn = callee->in_callback_fn;
+ if (in_callback_fn)
+ *insn_idx = callee->callsite;
+ else
+ *insn_idx = callee->callsite + 1;
+
if (env->log.level & BPF_LOG_LEVEL) {
verbose(env, "returning from callee:\n");
print_verifier_state(env, callee, true);
@@ -9807,6 +9875,24 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx)
* bpf_throw, this will be done by copy_verifier_state for extra frames. */
free_func_state(callee);
state->frame[state->curframe--] = NULL;
+
+ /* for callbacks widen imprecise scalars to make programs like below verify:
+ *
+ * struct ctx { int i; }
+ * void cb(int idx, struct ctx *ctx) { ctx->i++; ... }
+ * ...
+ * struct ctx = { .i = 0; }
+ * bpf_loop(100, cb, &ctx, 0);
+ *
+ * This is similar to what is done in process_iter_next_call() for open
+ * coded iterators.
+ */
+ prev_st = in_callback_fn ? find_prev_entry(env, state, *insn_idx) : NULL;
+ if (prev_st) {
+ err = widen_imprecise_scalars(env, prev_st, state);
+ if (err)
+ return err;
+ }
return 0;
}
@@ -10209,24 +10295,37 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
}
break;
case BPF_FUNC_for_each_map_elem:
- err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
- set_map_elem_callback_state);
+ err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+ set_map_elem_callback_state);
break;
case BPF_FUNC_timer_set_callback:
- err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
- set_timer_callback_state);
+ err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+ set_timer_callback_state);
break;
case BPF_FUNC_find_vma:
- err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
- set_find_vma_callback_state);
+ err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+ set_find_vma_callback_state);
break;
case BPF_FUNC_snprintf:
err = check_bpf_snprintf_call(env, regs);
break;
case BPF_FUNC_loop:
update_loop_inline_state(env, meta.subprogno);
- err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
- set_loop_callback_state);
+ /* Verifier relies on R1 value to determine if bpf_loop() iteration
+ * is finished, thus mark it precise.
+ */
+ err = mark_chain_precision(env, BPF_REG_1);
+ if (err)
+ return err;
+ if (cur_func(env)->callback_depth < regs[BPF_REG_1].umax_value) {
+ err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+ set_loop_callback_state);
+ } else {
+ cur_func(env)->callback_depth = 0;
+ if (env->log.level & BPF_LOG_LEVEL2)
+ verbose(env, "frame%d bpf_loop iteration limit reached\n",
+ env->cur_state->curframe);
+ }
break;
case BPF_FUNC_dynptr_from_mem:
if (regs[BPF_REG_1].type != PTR_TO_MAP_VALUE) {
@@ -10322,8 +10421,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
break;
}
case BPF_FUNC_user_ringbuf_drain:
- err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
- set_user_ringbuf_callback_state);
+ err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+ set_user_ringbuf_callback_state);
break;
}
@@ -11211,7 +11310,7 @@ static bool is_bpf_graph_api_kfunc(u32 btf_id)
btf_id == special_kfunc_list[KF_bpf_refcount_acquire_impl];
}
-static bool is_callback_calling_kfunc(u32 btf_id)
+static bool is_sync_callback_calling_kfunc(u32 btf_id)
{
return btf_id == special_kfunc_list[KF_bpf_rbtree_add_impl];
}
@@ -11963,6 +12062,21 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
return -EACCES;
}
+ /* Check the arguments */
+ err = check_kfunc_args(env, &meta, insn_idx);
+ if (err < 0)
+ return err;
+
+ if (meta.func_id == special_kfunc_list[KF_bpf_rbtree_add_impl]) {
+ err = push_callback_call(env, insn, insn_idx, meta.subprogno,
+ set_rbtree_add_callback_state);
+ if (err) {
+ verbose(env, "kfunc %s#%d failed callback verification\n",
+ func_name, meta.func_id);
+ return err;
+ }
+ }
+
rcu_lock = is_kfunc_bpf_rcu_read_lock(&meta);
rcu_unlock = is_kfunc_bpf_rcu_read_unlock(&meta);
@@ -11998,10 +12112,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
return -EINVAL;
}
- /* Check the arguments */
- err = check_kfunc_args(env, &meta, insn_idx);
- if (err < 0)
- return err;
/* In case of release function, we get register number of refcounted
* PTR_TO_BTF_ID in bpf_kfunc_arg_meta, do the release now.
*/
@@ -12035,16 +12145,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
}
}
- if (meta.func_id == special_kfunc_list[KF_bpf_rbtree_add_impl]) {
- err = __check_func_call(env, insn, insn_idx_p, meta.subprogno,
- set_rbtree_add_callback_state);
- if (err) {
- verbose(env, "kfunc %s#%d failed callback verification\n",
- func_name, meta.func_id);
- return err;
- }
- }
-
if (meta.func_id == special_kfunc_list[KF_bpf_throw]) {
if (!bpf_jit_supports_exceptions()) {
verbose(env, "JIT does not support calling kfunc %s#%d\n",
@@ -15408,6 +15508,15 @@ static bool is_force_checkpoint(struct bpf_verifier_env *env, int insn_idx)
return env->insn_aux_data[insn_idx].force_checkpoint;
}
+static void mark_calls_callback(struct bpf_verifier_env *env, int idx)
+{
+ env->insn_aux_data[idx].calls_callback = true;
+}
+
+static bool calls_callback(struct bpf_verifier_env *env, int insn_idx)
+{
+ return env->insn_aux_data[insn_idx].calls_callback;
+}
enum {
DONE_EXPLORING = 0,
@@ -15521,6 +15630,21 @@ static int visit_insn(int t, struct bpf_verifier_env *env)
* async state will be pushed for further exploration.
*/
mark_prune_point(env, t);
+ /* For functions that invoke callbacks it is not known how many times
+ * callback would be called. Verifier models callback calling functions
+ * by repeatedly visiting callback bodies and returning to origin call
+ * instruction.
+ * In order to stop such iteration verifier needs to identify when a
+ * state identical some state from a previous iteration is reached.
+ * Check below forces creation of checkpoint before callback calling
+ * instruction to allow search for such identical states.
+ */
+ if (is_sync_callback_calling_insn(insn)) {
+ mark_calls_callback(env, t);
+ mark_force_checkpoint(env, t);
+ mark_prune_point(env, t);
+ mark_jmp_point(env, t);
+ }
if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
struct bpf_kfunc_call_arg_meta meta;
@@ -16990,10 +17114,16 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
}
goto skip_inf_loop_check;
}
+ if (calls_callback(env, insn_idx)) {
+ if (states_equal(env, &sl->state, cur, true))
+ goto hit;
+ goto skip_inf_loop_check;
+ }
/* attempt to detect infinite loop to avoid unnecessary doomed work */
if (states_maybe_looping(&sl->state, cur) &&
states_equal(env, &sl->state, cur, false) &&
- !iter_active_depths_differ(&sl->state, cur)) {
+ !iter_active_depths_differ(&sl->state, cur) &&
+ sl->state.callback_unroll_depth == cur->callback_unroll_depth) {
verbose_linfo(env, insn_idx, "; ");
verbose(env, "infinite loop detected at insn %d\n", insn_idx);
verbose(env, "cur state:");
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index e85b5ad3e20..151bd3de593 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -3497,7 +3497,8 @@ static int alloc_chain_hlocks(int req)
size = chain_block_size(curr);
if (likely(size >= req)) {
del_chain_block(0, size, chain_block_next(curr));
- add_chain_block(curr + req, size - req);
+ if (size > req)
+ add_chain_block(curr + req, size - req);
return curr;
}
}
diff --git a/lib/errname.c b/lib/errname.c
index dd1b998552c..4f9112b38f3 100644
--- a/lib/errname.c
+++ b/lib/errname.c
@@ -111,9 +111,6 @@ static const char *names_0[] = {
E(ENOSPC),
E(ENOSR),
E(ENOSTR),
-#ifdef ENOSYM
- E(ENOSYM),
-#endif
E(ENOSYS),
E(ENOTBLK),
E(ENOTCONN),
@@ -144,9 +141,6 @@ static const char *names_0[] = {
#endif
E(EREMOTE),
E(EREMOTEIO),
-#ifdef EREMOTERELEASE
- E(EREMOTERELEASE),
-#endif
E(ERESTART),
E(ERFKILL),
E(EROFS),
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index de7d11cf4c6..8ff6824a100 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -409,7 +409,7 @@ size_t copy_page_to_iter_nofault(struct page *page, unsigned offset, size_t byte
void *kaddr = kmap_local_page(page);
size_t n = min(bytes, (size_t)PAGE_SIZE - offset);
- n = iterate_and_advance(i, bytes, kaddr,
+ n = iterate_and_advance(i, n, kaddr + offset,
copy_to_user_iter_nofault,
memcpy_to_iter);
kunmap_local(kaddr);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 46f2f5d3d18..ee2fd6a6af4 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -3107,7 +3107,7 @@ EXPORT_SYMBOL_GPL(folio_wait_writeback_killable);
*/
void folio_wait_stable(struct folio *folio)
{
- if (folio_inode(folio)->i_sb->s_iflags & SB_I_STABLE_WRITES)
+ if (mapping_stable_writes(folio_mapping(folio)))
folio_wait_writeback(folio);
}
EXPORT_SYMBOL_GPL(folio_wait_stable);
diff --git a/net/core/dev.c b/net/core/dev.c
index af53f6d838c..c879246be48 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -10051,6 +10051,54 @@ void netif_tx_stop_all_queues(struct net_device *dev)
}
EXPORT_SYMBOL(netif_tx_stop_all_queues);
+static int netdev_do_alloc_pcpu_stats(struct net_device *dev)
+{
+ void __percpu *v;
+
+ /* Drivers implementing ndo_get_peer_dev must support tstat
+ * accounting, so that skb_do_redirect() can bump the dev's
+ * RX stats upon network namespace switch.
+ */
+ if (dev->netdev_ops->ndo_get_peer_dev &&
+ dev->pcpu_stat_type != NETDEV_PCPU_STAT_TSTATS)
+ return -EOPNOTSUPP;
+
+ switch (dev->pcpu_stat_type) {
+ case NETDEV_PCPU_STAT_NONE:
+ return 0;
+ case NETDEV_PCPU_STAT_LSTATS:
+ v = dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
+ break;
+ case NETDEV_PCPU_STAT_TSTATS:
+ v = dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+ break;
+ case NETDEV_PCPU_STAT_DSTATS:
+ v = dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return v ? 0 : -ENOMEM;
+}
+
+static void netdev_do_free_pcpu_stats(struct net_device *dev)
+{
+ switch (dev->pcpu_stat_type) {
+ case NETDEV_PCPU_STAT_NONE:
+ return;
+ case NETDEV_PCPU_STAT_LSTATS:
+ free_percpu(dev->lstats);
+ break;
+ case NETDEV_PCPU_STAT_TSTATS:
+ free_percpu(dev->tstats);
+ break;
+ case NETDEV_PCPU_STAT_DSTATS:
+ free_percpu(dev->dstats);
+ break;
+ }
+}
+
/**
* register_netdevice() - register a network device
* @dev: device to register
@@ -10111,9 +10159,13 @@ int register_netdevice(struct net_device *dev)
goto err_uninit;
}
+ ret = netdev_do_alloc_pcpu_stats(dev);
+ if (ret)
+ goto err_uninit;
+
ret = dev_index_reserve(net, dev->ifindex);
if (ret < 0)
- goto err_uninit;
+ goto err_free_pcpu;
dev->ifindex = ret;
/* Transfer changeable features to wanted_features and enable
@@ -10219,6 +10271,8 @@ int register_netdevice(struct net_device *dev)
call_netdevice_notifiers(NETDEV_PRE_UNINIT, dev);
err_ifindex_release:
dev_index_release(net, dev->ifindex);
+err_free_pcpu:
+ netdev_do_free_pcpu_stats(dev);
err_uninit:
if (dev->netdev_ops->ndo_uninit)
dev->netdev_ops->ndo_uninit(dev);
@@ -10471,6 +10525,7 @@ void netdev_run_todo(void)
WARN_ON(rcu_access_pointer(dev->ip_ptr));
WARN_ON(rcu_access_pointer(dev->ip6_ptr));
+ netdev_do_free_pcpu_stats(dev);
if (dev->priv_destructor)
dev->priv_destructor(dev);
if (dev->needs_free_netdev)
diff --git a/net/core/filter.c b/net/core/filter.c
index 383f96b0a1c..7e4d7c3bcc8 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -81,6 +81,7 @@
#include <net/xdp.h>
#include <net/mptcp.h>
#include <net/netfilter/nf_conntrack_bpf.h>
+#include <net/netkit.h>
#include <linux/un.h>
#include "dev.h"
@@ -2468,6 +2469,16 @@ static const struct bpf_func_proto bpf_clone_redirect_proto = {
DEFINE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
EXPORT_PER_CPU_SYMBOL_GPL(bpf_redirect_info);
+static struct net_device *skb_get_peer_dev(struct net_device *dev)
+{
+ const struct net_device_ops *ops = dev->netdev_ops;
+
+ if (likely(ops->ndo_get_peer_dev))
+ return INDIRECT_CALL_1(ops->ndo_get_peer_dev,
+ netkit_peer_dev, dev);
+ return NULL;
+}
+
int skb_do_redirect(struct sk_buff *skb)
{
struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
@@ -2481,17 +2492,15 @@ int skb_do_redirect(struct sk_buff *skb)
if (unlikely(!dev))
goto out_drop;
if (flags & BPF_F_PEER) {
- const struct net_device_ops *ops = dev->netdev_ops;
-
- if (unlikely(!ops->ndo_get_peer_dev ||
- !skb_at_tc_ingress(skb)))
+ if (unlikely(!skb_at_tc_ingress(skb)))
goto out_drop;
- dev = ops->ndo_get_peer_dev(dev);
+ dev = skb_get_peer_dev(dev);
if (unlikely(!dev ||
!(dev->flags & IFF_UP) ||
net_eq(net, dev_net(dev))))
goto out_drop;
skb->dev = dev;
+ dev_sw_netstats_rx_add(dev, skb->len);
return -EAGAIN;
}
return flags & BPF_F_NEIGH ?
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index f01aee832aa..7d0e7aaa71e 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -1481,5 +1481,6 @@ static void __exit inet_diag_exit(void)
module_init(inet_diag_init);
module_exit(inet_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("INET/INET6: socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2 /* AF_INET */);
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10 /* AF_INET6 */);
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
index 63a40e4b678..fe2140c8375 100644
--- a/net/ipv4/raw_diag.c
+++ b/net/ipv4/raw_diag.c
@@ -257,5 +257,6 @@ static void __exit raw_diag_exit(void)
module_init(raw_diag_init);
module_exit(raw_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("RAW socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-255 /* AF_INET - IPPROTO_RAW */);
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10-255 /* AF_INET6 - IPPROTO_RAW */);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 3290a4442b4..16615d107cf 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -780,7 +780,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
goto reject_redirect;
}
- n = __ipv4_neigh_lookup(rt->dst.dev, new_gw);
+ n = __ipv4_neigh_lookup(rt->dst.dev, (__force u32)new_gw);
if (!n)
n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev);
if (!IS_ERR(n)) {
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 01b50fa7918..4cbe4b44425 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -247,4 +247,5 @@ static void __exit tcp_diag_exit(void)
module_init(tcp_diag_init);
module_exit(tcp_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-6 /* AF_INET - IPPROTO_TCP */);
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index de3f2d31f51..dc41a22ee80 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -296,5 +296,6 @@ static void __exit udp_diag_exit(void)
module_init(udp_diag_init);
module_exit(udp_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UDP socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-17 /* AF_INET - IPPROTO_UDP */);
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-136 /* AF_INET - IPPROTO_UDPLITE */);
diff --git a/net/mptcp/mptcp_diag.c b/net/mptcp/mptcp_diag.c
index 8df1bdb647e..5409c2ea3f5 100644
--- a/net/mptcp/mptcp_diag.c
+++ b/net/mptcp/mptcp_diag.c
@@ -245,4 +245,5 @@ static void __exit mptcp_diag_exit(void)
module_init(mptcp_diag_init);
module_exit(mptcp_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MPTCP socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-262 /* AF_INET - IPPROTO_MPTCP */);
diff --git a/net/packet/diag.c b/net/packet/diag.c
index f6b200cb3c0..9a7980e3309 100644
--- a/net/packet/diag.c
+++ b/net/packet/diag.c
@@ -262,4 +262,5 @@ static void __exit packet_diag_exit(void)
module_init(packet_diag_init);
module_exit(packet_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PACKET socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 17 /* AF_PACKET */);
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 981ca5b98bc..1d95f8bc769 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -73,6 +73,7 @@ static void rxrpc_destroy_client_conn_ids(struct rxrpc_local *local)
static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
gfp_t gfp)
{
+ static atomic_t rxrpc_bundle_id;
struct rxrpc_bundle *bundle;
bundle = kzalloc(sizeof(*bundle), gfp);
@@ -85,6 +86,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
bundle->upgrade = test_bit(RXRPC_CALL_UPGRADE, &call->flags);
bundle->service_id = call->dest_srx.srx_service;
bundle->security_level = call->security_level;
+ bundle->debug_id = atomic_inc_return(&rxrpc_bundle_id);
refcount_set(&bundle->ref, 1);
atomic_set(&bundle->active, 1);
INIT_LIST_HEAD(&bundle->waiting_calls);
@@ -105,7 +107,8 @@ struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle,
static void rxrpc_free_bundle(struct rxrpc_bundle *bundle)
{
- trace_rxrpc_bundle(bundle->debug_id, 1, rxrpc_bundle_free);
+ trace_rxrpc_bundle(bundle->debug_id, refcount_read(&bundle->ref),
+ rxrpc_bundle_free);
rxrpc_put_peer(bundle->peer, rxrpc_peer_put_bundle);
key_put(bundle->key);
kfree(bundle);
@@ -239,7 +242,6 @@ static bool rxrpc_may_reuse_conn(struct rxrpc_connection *conn)
*/
int rxrpc_look_up_bundle(struct rxrpc_call *call, gfp_t gfp)
{
- static atomic_t rxrpc_bundle_id;
struct rxrpc_bundle *bundle, *candidate;
struct rxrpc_local *local = call->local;
struct rb_node *p, **pp, *parent;
@@ -306,7 +308,6 @@ int rxrpc_look_up_bundle(struct rxrpc_call *call, gfp_t gfp)
}
_debug("new bundle");
- candidate->debug_id = atomic_inc_return(&rxrpc_bundle_id);
rb_link_node(&candidate->local_node, parent, pp);
rb_insert_color(&candidate->local_node, &local->client_bundles);
call->bundle = rxrpc_get_bundle(candidate, rxrpc_bundle_get_client_call);
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 030d64f282f..92495e73b86 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -643,12 +643,8 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call,
clear_bit(i + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
smp_mb(); /* Read data before setting avail bit */
set_bit(i, &call->rtt_avail);
- if (type != rxrpc_rtt_rx_cancel)
- rxrpc_peer_add_rtt(call, type, i, acked_serial, ack_serial,
- sent_at, resp_time);
- else
- trace_rxrpc_rtt_rx(call, rxrpc_rtt_rx_cancel, i,
- orig_serial, acked_serial, 0, 0);
+ rxrpc_peer_add_rtt(call, type, i, acked_serial, ack_serial,
+ sent_at, resp_time);
matched = true;
}
@@ -801,28 +797,21 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
summary.ack_reason, nr_acks);
rxrpc_inc_stat(call->rxnet, stat_rx_acks[ack.reason]);
- switch (ack.reason) {
- case RXRPC_ACK_PING_RESPONSE:
- rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
- rxrpc_rtt_rx_ping_response);
- break;
- case RXRPC_ACK_REQUESTED:
- rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
- rxrpc_rtt_rx_requested_ack);
- break;
- default:
- if (acked_serial != 0)
+ if (acked_serial != 0) {
+ switch (ack.reason) {
+ case RXRPC_ACK_PING_RESPONSE:
rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
- rxrpc_rtt_rx_cancel);
- break;
- }
-
- if (ack.reason == RXRPC_ACK_PING) {
- rxrpc_send_ACK(call, RXRPC_ACK_PING_RESPONSE, ack_serial,
- rxrpc_propose_ack_respond_to_ping);
- } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) {
- rxrpc_send_ACK(call, RXRPC_ACK_REQUESTED, ack_serial,
- rxrpc_propose_ack_respond_to_ack);
+ rxrpc_rtt_rx_ping_response);
+ break;
+ case RXRPC_ACK_REQUESTED:
+ rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
+ rxrpc_rtt_rx_requested_ack);
+ break;
+ default:
+ rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
+ rxrpc_rtt_rx_other_ack);
+ break;
+ }
}
/* If we get an EXCEEDS_WINDOW ACK from the server, it probably
@@ -835,7 +824,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_is_client_call(call)) {
rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
0, -ENETRESET);
- return;
+ goto send_response;
}
/* If we get an OUT_OF_SEQUENCE ACK from the server, that can also
@@ -849,7 +838,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_is_client_call(call)) {
rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
0, -ENETRESET);
- return;
+ goto send_response;
}
/* Discard any out-of-order or duplicate ACKs (outside lock). */
@@ -857,7 +846,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
first_soft_ack, call->acks_first_seq,
prev_pkt, call->acks_prev_seq);
- return;
+ goto send_response;
}
info.rxMTU = 0;
@@ -897,7 +886,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
case RXRPC_CALL_SERVER_AWAIT_ACK:
break;
default:
- return;
+ goto send_response;
}
if (before(hard_ack, call->acks_hard_ack) ||
@@ -909,7 +898,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
if (after(hard_ack, call->acks_hard_ack)) {
if (rxrpc_rotate_tx_window(call, hard_ack, &summary)) {
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ack);
- return;
+ goto send_response;
}
}
@@ -927,6 +916,14 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_propose_ack_ping_for_lost_reply);
rxrpc_congestion_management(call, skb, &summary, acked_serial);
+
+send_response:
+ if (ack.reason == RXRPC_ACK_PING)
+ rxrpc_send_ACK(call, RXRPC_ACK_PING_RESPONSE, ack_serial,
+ rxrpc_propose_ack_respond_to_ping);
+ else if (sp->hdr.flags & RXRPC_REQUEST_ACK)
+ rxrpc_send_ACK(call, RXRPC_ACK_REQUESTED, ack_serial,
+ rxrpc_propose_ack_respond_to_ack);
}
/*
diff --git a/net/sctp/diag.c b/net/sctp/diag.c
index c3d6b92dd38..eb05131ff1d 100644
--- a/net/sctp/diag.c
+++ b/net/sctp/diag.c
@@ -527,4 +527,5 @@ static void __exit sctp_diag_exit(void)
module_init(sctp_diag_init);
module_exit(sctp_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SCTP socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-132);
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index da97f946b79..2a138884195 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -598,8 +598,12 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
struct smc_llc_qentry *qentry;
int rc;
- /* receive CONFIRM LINK request from server over RoCE fabric */
- qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
+ /* Receive CONFIRM LINK request from server over RoCE fabric.
+ * Increasing the client's timeout by twice as much as the server's
+ * timeout by default can temporarily avoid decline messages of
+ * both sides crossing or colliding
+ */
+ qentry = smc_llc_wait(link->lgr, NULL, 2 * SMC_LLC_WAIT_TIME,
SMC_LLC_CONFIRM_LINK);
if (!qentry) {
struct smc_clc_msg_decline dclc;
diff --git a/net/smc/smc_diag.c b/net/smc/smc_diag.c
index 7ff2152971a..a584613aca1 100644
--- a/net/smc/smc_diag.c
+++ b/net/smc/smc_diag.c
@@ -268,5 +268,6 @@ static void __exit smc_diag_exit(void)
module_init(smc_diag_init);
module_exit(smc_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SMC socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 43 /* AF_SMC */);
MODULE_ALIAS_GENL_FAMILY(SMCR_GENL_FAMILY_NAME);
diff --git a/net/tipc/diag.c b/net/tipc/diag.c
index 73137f4aeb6..18733451c9e 100644
--- a/net/tipc/diag.c
+++ b/net/tipc/diag.c
@@ -113,4 +113,5 @@ module_init(tipc_diag_init);
module_exit(tipc_diag_exit);
MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("TIPC socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, AF_TIPC);
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index a78e8e72240..316f7618796 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1232,11 +1232,14 @@ void tls_sw_splice_eof(struct socket *sock)
lock_sock(sk);
retry:
+ /* same checks as in tls_sw_push_pending_record() */
rec = ctx->open_rec;
if (!rec)
goto unlock;
msg_pl = &rec->msg_plaintext;
+ if (msg_pl->sg.size == 0)
+ goto unlock;
/* Check the BPF advisor and perform transmission. */
ret = bpf_exec_tx_verdict(msg_pl, sk, false, TLS_RECORD_TYPE_DATA,
diff --git a/net/unix/diag.c b/net/unix/diag.c
index 616b55c5b89..bec09a3a1d4 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -339,4 +339,5 @@ static void __exit unix_diag_exit(void)
module_init(unix_diag_init);
module_exit(unix_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UNIX socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 1 /* AF_LOCAL */);
diff --git a/net/vmw_vsock/diag.c b/net/vmw_vsock/diag.c
index a2823b1c5e2..2e29994f92f 100644
--- a/net/vmw_vsock/diag.c
+++ b/net/vmw_vsock/diag.c
@@ -174,5 +174,6 @@ static void __exit vsock_diag_exit(void)
module_init(vsock_diag_init);
module_exit(vsock_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VMware Virtual Sockets monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG,
40 /* AF_VSOCK */);
diff --git a/net/xdp/xsk_diag.c b/net/xdp/xsk_diag.c
index 22b36c8143c..9f895536727 100644
--- a/net/xdp/xsk_diag.c
+++ b/net/xdp/xsk_diag.c
@@ -211,4 +211,5 @@ static void __exit xsk_diag_exit(void)
module_init(xsk_diag_init);
module_exit(xsk_diag_exit);
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("XDP socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, AF_XDP);
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index 84f5fb7f1ce..d83ba5d8f3f 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -97,8 +97,7 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack);
# 11160: a7 fb ff 60 aghi %r15,-160
# or
# 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15)
- $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})
- (?:\(\%r15\))?$/ox;
+ $re = qr/.*(?:lay|ag?hi).*\%r15,-([0-9]+)(?:\(\%r15\))?$/o;
} elsif ($arch eq 'sparc' || $arch eq 'sparc64') {
# f0019d10: 9d e3 bf 90 save %sp, -112, %sp
$re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 3429419ca69..fe4dd313198 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -252,6 +252,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_TAS5720
imply SND_SOC_TAS6424
imply SND_SOC_TDA7419
+ imply SND_SOC_TFA98xx
imply SND_SOC_TFA9879
imply SND_SOC_TFA989X
imply SND_SOC_TLV320ADC3XXX
@@ -338,6 +339,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_WSA883X
imply SND_SOC_WSA884X
imply SND_SOC_ZL38060
+ imply SND_SOC_TAS2559
help
Normally ASoC codec drivers are only built if a machine driver which
uses them is also built since they are only usable with a machine
@@ -1882,6 +1884,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
@@ -2431,6 +2441,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 2078bb0d981..3730c959639 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -283,6 +283,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
@@ -387,6 +391,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
@@ -669,6 +677,7 @@ obj-$(CONFIG_SND_SOC_TAS5805M) += snd-soc-tas5805m.o
obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
+obj-$(CONFIG_SND_SOC_TFA98XX) += snd-soc-tfa98xx.o
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TFA989X) += snd-soc-tfa989x.o
obj-$(CONFIG_SND_SOC_TLV320ADC3XXX) += snd-soc-tlv320adc3xxx.o
diff --git a/sound/soc/codecs/tas2559.c b/sound/soc/codecs/tas2559.c
new file mode 100644
index 00000000000..8a5994eb3a9
--- /dev/null
+++ b/sound/soc/codecs/tas2559.c
@@ -0,0 +1,2289 @@
+/*
+** =============================================================================
+** Copyright (c) 2016 Texas Instruments Inc.
+**
+** This program is free software; you can redistribute it and/or modify it under
+** the terms of the GNU General Public License as published by the Free Software
+** Foundation; version 2.
+**
+** This program is distributed in the hope that it will be useful, but WITHOUT
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+**
+** File:
+** tas2559.c
+**
+** Description:
+** ALSA SoC driver for Texas Instruments TAS2559 High Performance 4W Smart Amplifier
+**
+** =============================================================================
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/syscalls.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#include <linux/crc8.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "tas2559.h"
+
+struct TBlock {
+ unsigned int mnType;
+ unsigned char mbPChkSumPresent;
+ unsigned char mnPChkSum;
+ unsigned int mnCommands;
+ unsigned char *mpData;
+};
+
+struct TData {
+ char mpName[64];
+ char *mpDescription;
+ unsigned int mnBlocks;
+ struct TBlock *mpBlocks;
+};
+
+struct TProgram {
+ char mpName[64];
+ char *mpDescription;
+ unsigned char mnAppMode;
+ unsigned short mnBoost;
+ struct TData mData;
+};
+
+struct TPLL {
+ char mpName[64];
+ char *mpDescription;
+ struct TBlock mBlock;
+};
+
+struct TConfiguration {
+ char mpName[64];
+ char *mpDescription;
+ unsigned int mnDevices;
+ unsigned int mnProgram;
+ unsigned int mnPLL;
+ unsigned int mnSamplingRate;
+ unsigned char mnPLLSrc;
+ unsigned int mnPLLSrcRate;
+ struct TData mData;
+};
+
+struct TCalibration {
+ char mpName[64];
+ char *mpDescription;
+ unsigned int mnProgram;
+ unsigned int mnConfiguration;
+ struct TData mData;
+};
+
+struct TFirmware {
+ unsigned int mnFWSize;
+ unsigned int mnChecksum;
+ unsigned int mnPPCVersion;
+ unsigned int mnFWVersion;
+ unsigned int mnDriverVersion;
+ unsigned int mnTimeStamp;
+ char mpDDCName[64];
+ char *mpDescription;
+ unsigned int mnDeviceFamily;
+ unsigned int mnDevice;
+ unsigned int mnPLLs;
+ struct TPLL *mpPLLs;
+ unsigned int mnPrograms;
+ struct TProgram *mpPrograms;
+ unsigned int mnConfigurations;
+ struct TConfiguration *mpConfigurations;
+ unsigned int mnCalibrations;
+ struct TCalibration *mpCalibrations;
+};
+
+struct tas2559_register {
+ int book;
+ int page;
+ int reg;
+};
+
+enum channel {
+ DevA = 0x01,
+ DevB = 0x02,
+ DevBoth = (DevA | DevB),
+};
+
+struct tas2559_priv {
+ struct device *dev;
+ struct regmap *mpRegmap;
+ struct i2c_client *client;
+ struct mutex dev_lock;
+ struct TFirmware *mpFirmware;
+ unsigned int mnCurrentProgram;
+ unsigned int mnCurrentSampleRate;
+ unsigned int mnCurrentConfiguration;
+ unsigned int mnNewConfiguration;
+ unsigned int mnCurrentCalibration;
+ bool mbPowerUp;
+ bool mbLoadConfigurationPrePowerUp;
+
+ /* parameters for TAS2559 */
+ struct gpio_desc *mnDevAGPIORST;
+ unsigned char mnDevAAddr;
+ unsigned char mnDevACurrentBook;
+ unsigned char mnDevACurrentPage;
+
+ /* parameters for TAS2560 */
+ struct gpio_desc *mnDevBGPIORST;
+ unsigned char mnDevBAddr;
+ unsigned char mnDevBCurrentBook;
+ unsigned char mnDevBCurrentPage;
+
+ unsigned int mnErrCode;
+ unsigned int mnRestart;
+ struct mutex codec_lock;
+};
+
+static unsigned int p_tas2559_default_data[] = {
+ DevA, TAS2559_SAR_ADC2_REG, 0x05,/* enable SAR ADC */
+ DevA, TAS2559_CLK_ERR_CTRL2, 0x21,/*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/
+ DevA, TAS2559_CLK_ERR_CTRL3, 0x21,/*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */
+ DevB, TAS2560_CLK_ERR_CTRL2, 0x21,/*rampDown 15dB/us, clock1 hysteresis, 0.34ms; clock2 hysteresis, 10.6us */
+ DevA, TAS2559_SAFE_GUARD_REG, TAS2559_SAFE_GUARD_PATTERN,/* safe guard */
+ DevA, TAS2559_CLK_ERR_CTRL, 0x00,/*enable clock error detection*/
+ DevB, TAS2560_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_startup_data[] = {
+ DevA, TAS2559_GPIO1_PIN_REG, 0x01,/* enable BCLK */
+ DevA, TAS2559_GPIO2_PIN_REG, 0x01,/* enable WCLK */
+ DevA, TAS2559_POWER_CTRL2_REG, 0xA0,/*Class-D, Boost power up*/
+ DevA, TAS2559_POWER_CTRL2_REG, 0xA3,/*Class-D, Boost, IV sense power up*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0xF8,/*PLL, DSP, clock dividers power up*/
+ DevBoth, TAS2559_UDELAY, 2000,/*delay*/
+ DevB, TAS2560_DEV_MODE_REG, 0x02,
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevBoth, TAS2559_UDELAY, 2000,/*delay*/
+ DevA, TAS2559_CLK_ERR_CTRL, 0x2B,/*enable clock error detection*/
+ DevB, TAS2560_CLK_ERR_CTRL, 0x0B,/* disable clock error detection */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_mute_data[] = {
+ DevA, TAS2559_SOFT_MUTE_REG, 0x01,/*soft mute*/
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevA, TAS2559_MDELAY, 10,/*delay 10ms*/
+ DevA, TAS2559_MUTE_REG, 0x03,/*mute*/
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_unmute_data[] = {
+ DevA, TAS2559_MUTE_REG, 0x00, /*unmute*/
+ DevB, TAS2560_MUTE_REG, 0x40,
+ DevA, TAS2559_SOFT_MUTE_REG, 0x00, /*soft unmute*/
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_shutdown_data[] = {
+ DevA, TAS2559_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevB, TAS2560_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevA, TAS2559_SOFT_MUTE_REG, 0x01,/*soft mute*/
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevB, TAS2560_MUTE_REG, 0x01,
+ DevBoth, TAS2559_MDELAY, 10,/*delay 10ms*/
+ DevB, TAS2559_MDELAY, 20,/*delay 20ms*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0x60,/*DSP power down*/
+ DevA, TAS2559_MDELAY, 2,/*delay 20ms*/
+ DevA, TAS2559_MUTE_REG, 0x03,/*mute*/
+ DevA, TAS2559_POWER_CTRL2_REG, 0x00,/*Class-D, Boost power down*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0x00,/*all power down*/
+ DevB, TAS2560_DEV_MODE_REG, 0x01,
+ DevA, TAS2559_GPIO1_PIN_REG, 0x00,/* disable BCLK */
+ DevA, TAS2559_GPIO2_PIN_REG, 0x00,/* disable WCLK */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static unsigned int p_tas2559_shutdown_DevB_data[] = {
+ DevA, TAS2559_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevB, TAS2560_CLK_ERR_CTRL, 0x00,/* disable clock error detection */
+ DevB, TAS2560_MUTE_REG, 0x41,
+ DevB, TAS2560_MUTE_REG, 0x01,
+ DevA, TAS2559_POWER_CTRL1_REG, 0x60,/*DSP power down*/
+ DevBoth, TAS2559_MDELAY, 30,/*delay 2ms*/
+ DevB, TAS2560_DEV_MODE_REG, 0x01,
+ DevA, TAS2559_POWER_CTRL2_REG, 0x00,/*Class-D, Boost power down*/
+ DevA, TAS2559_POWER_CTRL1_REG, 0x00,/*all power down*/
+ DevA, TAS2559_GPIO1_PIN_REG, 0x00,/* disable BCLK */
+ DevA, TAS2559_GPIO2_PIN_REG, 0x00,/* disable WCLK */
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static int tas2559_i2c_read_device(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char *p_value)
+{
+ int nResult = 0;
+ unsigned int val = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_read(pTAS2559->mpRegmap, reg, &val);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+ else
+ *p_value = (unsigned char)val;
+
+ return nResult;
+}
+
+static int tas2559_i2c_write_device(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char value)
+{
+ int nResult = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_write(pTAS2559->mpRegmap, reg, value);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+
+ return nResult;
+}
+
+static int tas2559_i2c_update_bits(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char mask,
+ unsigned char value)
+{
+ int nResult = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_update_bits(pTAS2559->mpRegmap, reg, mask, value);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+
+ return nResult;
+}
+
+static int tas2559_i2c_bulkwrite_device(struct tas2559_priv *pTAS2559,
+ unsigned char addr,
+ unsigned char reg,
+ unsigned char *pBuf,
+ unsigned int len)
+{
+ int nResult = 0;
+
+ pTAS2559->client->addr = addr;
+ nResult = regmap_bulk_write(pTAS2559->mpRegmap, reg, pBuf, len);
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s[0x%x] Error %d\n",
+ __func__, addr, nResult);
+
+ return nResult;
+}
+
+static int tas2559_change_book_page(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned char nBook,
+ unsigned char nPage)
+{
+ int nResult = 0;
+
+ if (chn & DevA) {
+ if (pTAS2559->mnDevACurrentBook == nBook) {
+ if (pTAS2559->mnDevACurrentPage != nPage) {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_PAGE, nPage);
+
+ if (nResult >= 0)
+ pTAS2559->mnDevACurrentPage = nPage;
+ }
+ } else {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_PAGE, 0);
+
+ if (nResult >= 0) {
+ pTAS2559->mnDevACurrentPage = 0;
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_REG, nBook);
+ pTAS2559->mnDevACurrentBook = nBook;
+
+ if (nPage != 0) {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_BOOKCTL_PAGE, nPage);
+ pTAS2559->mnDevACurrentPage = nPage;
+ }
+ }
+ }
+ }
+
+ if (chn & DevB) {
+ if (pTAS2559->mnDevBCurrentBook == nBook) {
+ if (pTAS2559->mnDevBCurrentPage != nPage) {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_PAGE, nPage);
+
+ if (nResult >= 0)
+ pTAS2559->mnDevBCurrentPage = nPage;
+ }
+ } else {
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_PAGE, 0);
+
+ if (nResult >= 0) {
+ pTAS2559->mnDevBCurrentPage = 0;
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_REG, nBook);
+ pTAS2559->mnDevBCurrentBook = nBook;
+
+ if (nPage != 0) {
+ tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_BOOKCTL_PAGE, nPage);
+ pTAS2559->mnDevBCurrentPage = nPage;
+ }
+ }
+ }
+ }
+
+ return nResult;
+}
+
+static int tas2559_dev_read(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned int *pValue)
+{
+ int nResult = 0;
+ unsigned char Value = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559, chn,
+ TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ if (chn == DevA)
+ nResult = tas2559_i2c_read_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_PAGE_REG(nRegister), &Value);
+ else
+ if (chn == DevB)
+ nResult = tas2559_i2c_read_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_PAGE_REG(nRegister), &Value);
+ else {
+ dev_err(pTAS2559->dev, "%s read chn ERROR %d\n", __func__, chn);
+ nResult = -EINVAL;
+ }
+
+ if (nResult >= 0)
+ *pValue = Value;
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static int tas2559_dev_write(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned int nValue)
+{
+ int nResult = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559,
+ chn, TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ if (chn & DevA)
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_PAGE_REG(nRegister), nValue);
+
+ if (chn & DevB)
+ nResult = tas2559_i2c_write_device(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_PAGE_REG(nRegister), nValue);
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static int tas2559_dev_bulk_write(struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned char *pData,
+ unsigned int nLength)
+{
+ int nResult = 0;
+ unsigned char reg = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559, chn,
+ TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ reg = TAS2559_PAGE_REG(nRegister);
+
+ if (chn & DevA)
+ nResult = tas2559_i2c_bulkwrite_device(pTAS2559,
+ pTAS2559->mnDevAAddr, reg, pData, nLength);
+
+ if (chn & DevB)
+ nResult = tas2559_i2c_bulkwrite_device(pTAS2559,
+ pTAS2559->mnDevBAddr, reg, pData, nLength);
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static int tas2559_dev_update_bits(
+ struct tas2559_priv *pTAS2559,
+ enum channel chn,
+ unsigned int nRegister,
+ unsigned int nMask,
+ unsigned int nValue)
+{
+ int nResult = 0;
+
+ mutex_lock(&pTAS2559->dev_lock);
+
+ nResult = tas2559_change_book_page(pTAS2559,
+ chn, TAS2559_BOOK_ID(nRegister), TAS2559_PAGE_ID(nRegister));
+
+ if (nResult >= 0) {
+ if (chn & DevA)
+ nResult = tas2559_i2c_update_bits(pTAS2559,
+ pTAS2559->mnDevAAddr, TAS2559_PAGE_REG(nRegister), nMask, nValue);
+
+ if (chn & DevB)
+ nResult = tas2559_i2c_update_bits(pTAS2559,
+ pTAS2559->mnDevBAddr, TAS2559_PAGE_REG(nRegister), nMask, nValue);
+ }
+
+ mutex_unlock(&pTAS2559->dev_lock);
+ return nResult;
+}
+
+static void tas2559_hw_reset(struct tas2559_priv *pTAS2559)
+{
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+
+ gpiod_set_value_cansleep(pTAS2559->mnDevAGPIORST, 0);
+ msleep(5);
+ gpiod_set_value_cansleep(pTAS2559->mnDevAGPIORST, 1);
+ msleep(2);
+
+ gpiod_set_value_cansleep(pTAS2559->mnDevBGPIORST, 0);
+ msleep(5);
+ gpiod_set_value_cansleep(pTAS2559->mnDevBGPIORST, 1);
+ msleep(2);
+
+ pTAS2559->mnDevACurrentBook = -1;
+ pTAS2559->mnDevACurrentPage = -1;
+ pTAS2559->mnDevBCurrentBook = -1;
+ pTAS2559->mnDevBCurrentPage = -1;
+
+ if (pTAS2559->mnErrCode)
+ dev_info(pTAS2559->dev, "%s, ErrCode=0x%x\n", __func__, pTAS2559->mnErrCode);
+
+ pTAS2559->mnErrCode = 0;
+}
+
+static int tas2559_dev_load_data(struct tas2559_priv *pTAS2559,
+ enum channel dev, unsigned int *pData)
+{
+ int nResult = 0;
+ unsigned int n = 0;
+ unsigned int nRegister;
+ unsigned int nData;
+ enum channel chl;
+
+ do {
+ chl = pData[n * 3];
+
+ if (chl == 0xffffffff)
+ break;
+
+ if (dev & chl) {
+ nRegister = pData[n * 3 + 1];
+ nData = pData[n * 3 + 2];
+
+ if (nRegister == TAS2559_UDELAY) {
+ udelay(nData);
+ } else if (nRegister == TAS2559_MDELAY) {
+ mdelay(nData);
+ } else if (nRegister != 0xFFFFFFFF) {
+ nResult = tas2559_dev_write(pTAS2559, chl, nRegister, nData);
+ if (nResult < 0)
+ break;
+ }
+ }
+
+ n++;
+ } while (nRegister != 0xFFFFFFFF);
+
+ return nResult;
+}
+
+static int tas2559_DevStartup(struct tas2559_priv *pTAS2559,
+ unsigned int dev)
+{
+ int nResult = 0;
+ enum channel chl = dev;
+
+ if (dev == DevB)
+ chl = DevBoth;
+
+ dev_dbg(pTAS2559->dev, "%s, chl=%d\n", __func__, chl);
+ nResult = tas2559_dev_load_data(pTAS2559, chl, p_tas2559_startup_data);
+
+ return nResult;
+}
+
+static int tas2559_DevShutdown(struct tas2559_priv *pTAS2559,
+ unsigned int dev)
+{
+ int nResult = 0;
+
+ dev_dbg(pTAS2559->dev, "%s, dev=%d\n", __func__, dev);
+
+ if (dev == DevB)
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_shutdown_DevB_data);
+ else
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_shutdown_data);
+
+ return nResult;
+}
+
+int tas2559_set_DAC_gain(struct tas2559_priv *pTAS2559,
+ enum channel chl, unsigned int nGain)
+{
+ int nResult = 0;
+ int gain = (nGain & 0x0f);
+
+ dev_dbg(pTAS2559->dev, "%s, nGain: %d", __func__, nGain);
+
+ if (chl & DevA) {
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA,
+ TAS2559_SPK_CTRL_REG, 0x78, (gain << 3));
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (chl & DevB)
+ nResult = tas2559_dev_update_bits(pTAS2559, DevB,
+ TAS2560_SPK_CTRL_REG, 0x0f, gain);
+
+end:
+
+ return nResult;
+}
+
+int tas2559_get_DAC_gain(struct tas2559_priv *pTAS2559,
+ enum channel chl, unsigned char *pnGain)
+{
+ int nResult = 0;
+ int nGain;
+
+ if (chl == DevA) {
+ nResult = tas2559_dev_read(pTAS2559, DevA, TAS2559_SPK_CTRL_REG, &nGain);
+
+ if (nResult >= 0)
+ *pnGain = ((nGain >> 3) & 0x0f);
+ } else
+ if (chl == DevB) {
+ nResult = tas2559_dev_read(pTAS2559, DevB, TAS2560_SPK_CTRL_REG, &nGain);
+
+ if (nResult >= 0)
+ *pnGain = (nGain & 0x0f);
+ }
+
+ return nResult;
+}
+
+int tas2559_DevMute(struct tas2559_priv *pTAS2559, enum channel dev, bool mute)
+{
+ int nResult = 0;
+
+ dev_dbg(pTAS2559->dev, "%s, dev=%d, mute=%d\n", __func__, dev, mute);
+
+ if (mute)
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_mute_data);
+ else
+ nResult = tas2559_dev_load_data(pTAS2559, dev, p_tas2559_unmute_data);
+
+ return nResult;
+}
+
+int tas2559_load_default(struct tas2559_priv *pTAS2559)
+{
+ int nResult = 0;
+
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+
+ nResult = tas2559_dev_load_data(pTAS2559, DevBoth, p_tas2559_default_data);
+ if (nResult < 0)
+ goto end;
+
+ // Set default bit rate of 16 for DevA
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA, TAS2559_ASI1_DAC_FORMAT_REG, 0x18, 0);
+ if (nResult < 0)
+ goto end;
+
+ // Set default bit rate of 16 for DevB
+ nResult = tas2559_dev_update_bits(pTAS2559, DevB, TAS2560_DAI_FMT, 0x03, 0);
+ if (nResult < 0)
+ goto end;
+
+ /* enable DOUT tri-state for extra BCLKs */
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA, TAS2559_ASI1_DAC_FORMAT_REG, 0x01, 0x01);
+ if (nResult < 0)
+ goto end;
+
+ nResult = tas2559_dev_update_bits(pTAS2559, DevB, TAS2560_ASI_CFG_1, 0x02, 0x02);
+ if (nResult < 0)
+ goto end;
+
+ /* Interrupt pin, low-highZ, high active driven */
+ nResult = tas2559_dev_update_bits(pTAS2559, DevA, TAS2559_GPIO_HIZ_CTRL2_REG, 0x30, 0x30);
+
+end:
+ return nResult;
+}
+
+
+void tas2559_clear_firmware(struct TFirmware *pFirmware)
+{
+ unsigned int n, nn;
+
+ if (!pFirmware)
+ return;
+
+ kfree(pFirmware->mpDescription);
+
+ if (pFirmware->mpPLLs != NULL) {
+ for (n = 0; n < pFirmware->mnPLLs; n++) {
+ kfree(pFirmware->mpPLLs[n].mpDescription);
+ kfree(pFirmware->mpPLLs[n].mBlock.mpData);
+ }
+
+ kfree(pFirmware->mpPLLs);
+ }
+
+ if (pFirmware->mpPrograms != NULL) {
+ for (n = 0; n < pFirmware->mnPrograms; n++) {
+ kfree(pFirmware->mpPrograms[n].mpDescription);
+ kfree(pFirmware->mpPrograms[n].mData.mpDescription);
+
+ for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++)
+ kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData);
+
+ kfree(pFirmware->mpPrograms[n].mData.mpBlocks);
+ }
+
+ kfree(pFirmware->mpPrograms);
+ }
+
+ if (pFirmware->mpConfigurations != NULL) {
+ for (n = 0; n < pFirmware->mnConfigurations; n++) {
+ kfree(pFirmware->mpConfigurations[n].mpDescription);
+ kfree(pFirmware->mpConfigurations[n].mData.mpDescription);
+
+ for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++)
+ kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData);
+
+ kfree(pFirmware->mpConfigurations[n].mData.mpBlocks);
+ }
+
+ kfree(pFirmware->mpConfigurations);
+ }
+
+ if (pFirmware->mpCalibrations != NULL) {
+ for (n = 0; n < pFirmware->mnCalibrations; n++) {
+ kfree(pFirmware->mpCalibrations[n].mpDescription);
+ kfree(pFirmware->mpCalibrations[n].mData.mpDescription);
+
+ for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++)
+ kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData);
+
+ kfree(pFirmware->mpCalibrations[n].mData.mpBlocks);
+ }
+
+ kfree(pFirmware->mpCalibrations);
+ }
+
+ memset(pFirmware, 0x00, sizeof(struct TFirmware));
+}
+
+static int tas2559_load_block(struct tas2559_priv *pTAS2559, struct TBlock *pBlock)
+{
+ int nResult = 0;
+ unsigned int nCommand = 0;
+ unsigned char nBook;
+ unsigned char nPage;
+ unsigned char nOffset;
+ unsigned char nData;
+ unsigned int nValue1;
+ unsigned int nLength;
+ unsigned int nSleep;
+ enum channel chl;
+ unsigned char *pData = pBlock->mpData;
+
+ dev_dbg(pTAS2559->dev, "%s: Type = %d, commands = %d\n", __func__,
+ pBlock->mnType, pBlock->mnCommands);
+
+ if (pBlock->mnType == TAS2559_BLOCK_PLL) {
+ chl = DevA;
+ } else if ((pBlock->mnType == TAS2559_BLOCK_PGM_DEV_A)
+ || (pBlock->mnType == TAS2559_BLOCK_CFG_COEFF_DEV_A)
+ || (pBlock->mnType == TAS2559_BLOCK_CFG_PRE_DEV_A)) {
+ chl = DevA;
+ } else if ((pBlock->mnType == TAS2559_BLOCK_PGM_DEV_B)
+ || (pBlock->mnType == TAS2559_BLOCK_PST_POWERUP_DEV_B)
+ || (pBlock->mnType == TAS2559_BLOCK_CFG_PRE_DEV_B)) {
+ chl = DevB;
+ } else {
+ dev_err(pTAS2559->dev, "block type error %d\n", pBlock->mnType);
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (pBlock->mbPChkSumPresent) {
+ if (chl == DevA) {
+ nResult = tas2559_dev_write(pTAS2559, DevA, TAS2559_CRC_RESET_REG, 1);
+ if (nResult < 0)
+ goto end;
+ } else {
+ nResult = tas2559_dev_write(pTAS2559, DevB, TAS2560_CRC_CHK_REG, 1);
+ if (nResult < 0)
+ goto end;
+ }
+ }
+
+ nCommand = 0;
+ while (nCommand < pBlock->mnCommands) {
+ pData = pBlock->mpData + nCommand * 4;
+ nBook = pData[0];
+ nPage = pData[1];
+ nOffset = pData[2];
+ nData = pData[3];
+ nCommand++;
+
+ if (nOffset <= 0x7F) {
+ nResult = tas2559_dev_write(pTAS2559,
+ chl, TAS2559_REG(nBook, nPage, nOffset), nData);
+ if (nResult < 0)
+ goto end;
+
+ } else if (nOffset == 0x81) {
+ nSleep = (nBook << 8) + nPage;
+ msleep(nSleep);
+ } else if (nOffset == 0x85) {
+ pData += 4;
+ nLength = (nBook << 8) + nPage;
+ nBook = pData[0];
+ nPage = pData[1];
+ nOffset = pData[2];
+
+ if (nLength > 1) {
+ nResult = tas2559_dev_bulk_write(pTAS2559,
+ chl, TAS2559_REG(nBook, nPage, nOffset), pData + 3, nLength);
+ if (nResult < 0)
+ goto end;
+
+ } else {
+ nResult = tas2559_dev_write(pTAS2559,
+ chl, TAS2559_REG(nBook, nPage, nOffset), pData[3]);
+ if (nResult < 0)
+ goto end;
+
+ }
+
+ nCommand++;
+ if (nLength >= 2)
+ nCommand += ((nLength - 2) / 4) + 1;
+ }
+ }
+
+ if (pBlock->mbPChkSumPresent) {
+ if (chl == DevA)
+ nResult = tas2559_dev_read(pTAS2559, DevA,
+ TAS2559_CRC_CHECKSUM_REG, &nValue1);
+ else
+ nResult = tas2559_dev_read(pTAS2559, DevB,
+ TAS2560_CRC_CHK_REG, &nValue1);
+
+ if (nResult < 0)
+ goto end;
+
+ if (nValue1 != pBlock->mnPChkSum) {
+ dev_err(pTAS2559->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n",
+ pBlock->mnPChkSum, (nValue1 & 0xff));
+ nResult = -EAGAIN;
+ pTAS2559->mnErrCode |= ERROR_PRAM_CRCCHK;
+ }
+ }
+
+end:
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "Block (%d) load error\n",
+ pBlock->mnType);
+
+ return nResult;
+}
+
+static int tas2559_load_data(struct tas2559_priv *pTAS2559, struct TData *pData, unsigned int nType)
+{
+ int nResult = 0;
+ unsigned int nBlock;
+ struct TBlock *pBlock;
+
+ dev_dbg(pTAS2559->dev,
+ "TAS2559 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType);
+
+ for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) {
+ pBlock = &(pData->mpBlocks[nBlock]);
+
+ if (pBlock->mnType == nType) {
+ nResult = tas2559_load_block(pTAS2559, pBlock);
+
+ if (nResult < 0)
+ break;
+ }
+ }
+
+ return nResult;
+}
+
+static void failsafe(struct tas2559_priv *pTAS2559)
+{
+ dev_err(pTAS2559->dev, "%s\n", __func__);
+ pTAS2559->mnErrCode |= ERROR_FAILSAFE;
+
+ tas2559_DevShutdown(pTAS2559, DevBoth);
+ pTAS2559->mbPowerUp = false;
+ tas2559_hw_reset(pTAS2559);
+ tas2559_dev_write(pTAS2559, DevBoth, TAS2559_SW_RESET_REG, 0x01);
+ msleep(1);
+ tas2559_dev_write(pTAS2559, DevA, TAS2559_SPK_CTRL_REG, 0x04);
+ tas2559_dev_write(pTAS2559, DevB, TAS2560_SPK_CTRL_REG, 0x50);
+
+ if (pTAS2559->mpFirmware != NULL)
+ tas2559_clear_firmware(pTAS2559->mpFirmware);
+}
+
+static int tas2559_load_coefficient(struct tas2559_priv *pTAS2559,
+ int nPrevConfig, int nNewConfig, bool bPowerOn)
+{
+ int nResult = 0;
+ struct TPLL *pPLL;
+ struct TProgram *pProgram = NULL;
+ struct TConfiguration *pPrevConfiguration;
+ struct TConfiguration *pNewConfiguration;
+ enum channel chl;
+ bool bRestorePower = false;
+
+ dev_dbg(pTAS2559->dev, "%s, Prev=%d, new=%d, Pow=%d\n",
+ __func__, nPrevConfig, nNewConfig, bPowerOn);
+
+ if (!pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "%s, firmware not loaded\n", __func__);
+ goto end;
+ }
+
+ if (nNewConfig >= pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "%s, invalid configuration New=%d, total=%d\n",
+ __func__, nNewConfig, pTAS2559->mpFirmware->mnConfigurations);
+ goto end;
+ }
+
+ if (nPrevConfig < 0) {
+ pPrevConfiguration = NULL;
+ chl = DevBoth;
+ } else
+ if (nPrevConfig == nNewConfig) {
+ dev_dbg(pTAS2559->dev, "%d configuration is already loaded\n", nNewConfig);
+ goto end;
+ } else {
+ pPrevConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[nPrevConfig]);
+ chl = pPrevConfiguration->mnDevices;
+ }
+
+ pNewConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[nNewConfig]);
+ pTAS2559->mnCurrentConfiguration = nNewConfig;
+
+ if (pPrevConfiguration) {
+ if ((pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL)
+ && (pPrevConfiguration->mnDevices == pNewConfiguration->mnDevices)) {
+ dev_dbg(pTAS2559->dev, "%s, PLL and device same\n", __func__);
+ goto prog_coefficient;
+ }
+ }
+
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[pTAS2559->mnCurrentProgram]);
+
+ if (bPowerOn) {
+
+ nResult = tas2559_DevShutdown(pTAS2559, chl);
+
+ if (nResult < 0)
+ goto end;
+
+ bRestorePower = true;
+ }
+
+ /* load PLL */
+ pPLL = &(pTAS2559->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]);
+ dev_dbg(pTAS2559->dev, "load PLL: %s block for Configuration %s\n",
+ pPLL->mpName, pNewConfiguration->mpName);
+ nResult = tas2559_load_block(pTAS2559, &(pPLL->mBlock));
+
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate;
+
+ dev_dbg(pTAS2559->dev, "load configuration %s conefficient pre block\n",
+ pNewConfiguration->mpName);
+
+ if (pNewConfiguration->mnDevices & DevA) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData), TAS2559_BLOCK_CFG_PRE_DEV_A);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (pNewConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData), TAS2559_BLOCK_CFG_PRE_DEV_B);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+prog_coefficient:
+ dev_dbg(pTAS2559->dev, "load new configuration: %s, coeff block data\n",
+ pNewConfiguration->mpName);
+
+ if (pNewConfiguration->mnDevices & DevA) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData),
+ TAS2559_BLOCK_CFG_COEFF_DEV_A);
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (pNewConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData),
+ TAS2559_BLOCK_CFG_COEFF_DEV_B);
+ if (nResult < 0)
+ goto end;
+ }
+
+ if (bRestorePower) {
+ nResult = tas2559_DevStartup(pTAS2559, pNewConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ if (pNewConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pNewConfiguration->mData),
+ TAS2559_BLOCK_PST_POWERUP_DEV_B);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ dev_dbg(pTAS2559->dev,
+ "device powered up, load unmute\n");
+ nResult = tas2559_DevMute(pTAS2559, pNewConfiguration->mnDevices, false);
+ if (nResult < 0)
+ goto end;
+ }
+
+end:
+
+ if (nResult < 0)
+ dev_err(pTAS2559->dev, "%s, load new conf %s error\n", __func__, pNewConfiguration->mpName);
+
+ pTAS2559->mnNewConfiguration = pTAS2559->mnCurrentConfiguration;
+ return nResult;
+}
+
+static int tas2559_load_configuration(struct tas2559_priv *pTAS2559,
+ unsigned int nConfiguration, bool bLoadSame)
+{
+ int nResult = 0;
+ struct TConfiguration *pCurrentConfiguration = NULL;
+ struct TConfiguration *pNewConfiguration = NULL;
+
+ dev_dbg(pTAS2559->dev, "%s: %d\n", __func__, nConfiguration);
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = 0;
+ goto end;
+ }
+
+ if (nConfiguration >= pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "Configuration %d doesn't exist\n",
+ nConfiguration);
+ nResult = 0;
+ goto end;
+ }
+
+ if ((!pTAS2559->mbLoadConfigurationPrePowerUp)
+ && (nConfiguration == pTAS2559->mnCurrentConfiguration)
+ && (!bLoadSame)) {
+ dev_info(pTAS2559->dev, "Configuration %d is already loaded\n",
+ nConfiguration);
+ nResult = 0;
+ goto end;
+ }
+
+ pCurrentConfiguration =
+ &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+ pNewConfiguration =
+ &(pTAS2559->mpFirmware->mpConfigurations[nConfiguration]);
+
+ if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) {
+ dev_err(pTAS2559->dev, "Configuration %d, %s doesn't share the same program as current %d\n",
+ nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram);
+ nResult = 0;
+ goto end;
+ }
+
+ if (pNewConfiguration->mnPLL >= pTAS2559->mpFirmware->mnPLLs) {
+ dev_err(pTAS2559->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n",
+ nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL);
+ nResult = 0;
+ goto end;
+ }
+
+ if (pTAS2559->mbPowerUp) {
+ dev_err(pTAS2559->dev, "%s, device power on, load new conf[%d] %s\n", __func__,
+ nConfiguration, pNewConfiguration->mpName);
+ nResult = tas2559_load_coefficient(pTAS2559, pTAS2559->mnCurrentConfiguration, nConfiguration, true);
+ pTAS2559->mbLoadConfigurationPrePowerUp = false;
+ } else {
+ dev_dbg(pTAS2559->dev,
+ "TAS2559 was powered down, will load coefficient when power up\n");
+ pTAS2559->mbLoadConfigurationPrePowerUp = true;
+ pTAS2559->mnNewConfiguration = nConfiguration;
+ }
+
+end:
+
+ if (nResult < 0) {
+ if (pTAS2559->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+ failsafe(pTAS2559);
+ }
+
+ return nResult;
+}
+
+int tas2559_set_program(struct tas2559_priv *pTAS2559,
+ unsigned int nProgram, int nConfig)
+{
+ struct TProgram *pProgram;
+ struct TConfiguration *pConfiguration;
+ unsigned int nConfiguration = 0;
+ unsigned int nSampleRate = 0;
+ bool bFound = false;
+ int nResult = 0;
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = 0;
+ goto end;
+ }
+
+ if (nProgram >= pTAS2559->mpFirmware->mnPrograms) {
+ dev_err(pTAS2559->dev, "TAS2559: Program %d doesn't exist\n",
+ nProgram);
+ nResult = 0;
+ goto end;
+ }
+
+ if(nProgram == 1)
+ pTAS2559->mnCurrentSampleRate = 96000;
+ else
+ pTAS2559->mnCurrentSampleRate = 48000;
+
+ if (nConfig < 0) {
+ nConfiguration = 0;
+ nSampleRate = pTAS2559->mnCurrentSampleRate;
+ dev_err(pTAS2559->dev, "nSampleRate: %d\n", nSampleRate);
+
+ while (!bFound && (nConfiguration < pTAS2559->mpFirmware->mnConfigurations)) {
+ dev_err(pTAS2559->dev, "mpConfigurations SampleRate: %d\n",
+ pTAS2559->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate);
+ if (pTAS2559->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) {
+ if (nSampleRate == 0) {
+ bFound = true;
+ dev_info(pTAS2559->dev, "find default configuration %d\n", nConfiguration);
+ } else if (nSampleRate == pTAS2559->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) {
+ bFound = true;
+ dev_info(pTAS2559->dev, "find matching configuration %d\n", nConfiguration);
+ } else {
+ nConfiguration++;
+ }
+ } else {
+ nConfiguration++;
+ }
+ }
+
+ if (!bFound) {
+ dev_err(pTAS2559->dev,
+ "Program %d, no valid configuration found for sample rate %d, ignore\n",
+ nProgram, nSampleRate);
+ nResult = 0;
+ goto end;
+ }
+ } else {
+ if (pTAS2559->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) {
+ dev_err(pTAS2559->dev, "%s, configuration program doesn't match\n", __func__);
+ nResult = 0;
+ goto end;
+ }
+
+ nConfiguration = nConfig;
+ }
+
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[nProgram]);
+
+ if (pTAS2559->mbPowerUp) {
+ dev_info(pTAS2559->dev,
+ "device powered up, power down to load program %d (%s)\n",
+ nProgram, pProgram->mpName);
+
+ nResult = tas2559_DevShutdown(pTAS2559, DevBoth);
+
+ if (nResult < 0)
+ goto end;
+ }
+
+ tas2559_hw_reset(pTAS2559);
+ nResult = tas2559_dev_write(pTAS2559, DevBoth, TAS2559_SW_RESET_REG, 0x01);
+ if (nResult < 0)
+ goto end;
+
+ msleep(1);
+ nResult = tas2559_load_default(pTAS2559);
+ if (nResult < 0)
+ goto end;
+
+ dev_info(pTAS2559->dev, "load program %d (%s)\n", nProgram, pProgram->mpName);
+ nResult = tas2559_load_data(pTAS2559, &(pProgram->mData), TAS2559_BLOCK_PGM_DEV_A);
+ if (nResult < 0)
+ goto end;
+
+ nResult = tas2559_load_data(pTAS2559, &(pProgram->mData), TAS2559_BLOCK_PGM_DEV_B);
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mnCurrentProgram = nProgram;
+
+ nResult = tas2559_load_coefficient(pTAS2559, -1, nConfiguration, false);
+ if (nResult < 0)
+ goto end;
+
+ if (pTAS2559->mbPowerUp) {
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+ nResult = tas2559_DevStartup(pTAS2559, pConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ if (pConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pConfiguration->mData),
+ TAS2559_BLOCK_PST_POWERUP_DEV_B);
+ if (nResult < 0)
+ goto end;
+ }
+
+ nResult = tas2559_DevMute(pTAS2559, pConfiguration->mnDevices, false);
+ if (nResult < 0)
+ goto end;
+ }
+
+end:
+
+ if (nResult < 0) {
+ if (pTAS2559->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK))
+ failsafe(pTAS2559);
+ }
+
+ return nResult;
+}
+
+static void fw_print_header(struct tas2559_priv *pTAS2559, struct TFirmware *pFirmware)
+{
+ dev_info(pTAS2559->dev, "FW Size = %d", pFirmware->mnFWSize);
+ dev_info(pTAS2559->dev, "Checksum = 0x%04X", pFirmware->mnChecksum);
+ dev_info(pTAS2559->dev, "PPC Version = 0x%04X", pFirmware->mnPPCVersion);
+ dev_info(pTAS2559->dev, "FW Version = 0x%04X", pFirmware->mnFWVersion);
+ dev_info(pTAS2559->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion);
+ dev_info(pTAS2559->dev, "Timestamp = %d", pFirmware->mnTimeStamp);
+ dev_info(pTAS2559->dev, "DDC Name = %s", pFirmware->mpDDCName);
+ dev_info(pTAS2559->dev, "Description = %s", pFirmware->mpDescription);
+}
+
+static inline unsigned int fw_convert_number(unsigned char *pData)
+{
+ return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24);
+}
+
+static int fw_parse_header(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 };
+
+ if (nSize < 104) {
+ dev_err(pTAS2559->dev, "Firmware: Header too short");
+ return -EINVAL;
+ }
+
+ if (memcmp(pData, pMagicNumber, 4)) {
+ dev_err(pTAS2559->dev, "Firmware: Magic number doesn't match");
+ return -EINVAL;
+ }
+
+ pData += 4;
+
+ pFirmware->mnFWSize = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnChecksum = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnPPCVersion = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnFWVersion = fw_convert_number(pData);
+ pData += 4;
+
+ pFirmware->mnDriverVersion = fw_convert_number(pData);
+ dev_err(pTAS2559->dev, "Firmware driver: 0x%x", pFirmware->mnDriverVersion);
+ pData += 4;
+
+ pFirmware->mnTimeStamp = fw_convert_number(pData);
+ pData += 4;
+
+ memcpy(pFirmware->mpDDCName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ if ((pData - pDataStart) >= nSize) {
+ dev_err(pTAS2559->dev, "Firmware: Header too short after DDC description");
+ return -EINVAL;
+ }
+
+ pFirmware->mnDeviceFamily = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDeviceFamily != 0) {
+ dev_err(pTAS2559->dev,
+ "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily);
+ return -EINVAL;
+ }
+
+ pFirmware->mnDevice = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDevice != 4) {
+ dev_err(pTAS2559->dev,
+ "device %d, not TAS2559", pFirmware->mnDevice);
+ return -EINVAL;
+ }
+
+ fw_print_header(pTAS2559, pFirmware);
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_block_data(struct tas2559_priv *pTAS2559, struct TFirmware *pFirmware,
+ struct TBlock *pBlock, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+
+ pBlock->mnType = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) {
+ pBlock->mbPChkSumPresent = pData[0];
+ pData++;
+
+ pBlock->mnPChkSum = pData[0];
+ pData++;
+
+ // skip YRAM checksum data for simplicity
+ pData += 2;
+ } else {
+ pBlock->mbPChkSumPresent = 0;
+ }
+
+ pBlock->mnCommands = fw_convert_number(pData);
+ pData += 4;
+
+ n = pBlock->mnCommands * 4;
+ pBlock->mpData = kmemdup(pData, n, GFP_KERNEL);
+ pData += n;
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_data(struct tas2559_priv *pTAS2559, struct TFirmware *pFirmware,
+ struct TData *pImageData, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int nBlock;
+ unsigned int n;
+
+ memcpy(pImageData->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ pImageData->mnBlocks = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ pImageData->mpBlocks =
+ kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL);
+
+ for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) {
+ n = fw_parse_block_data(pTAS2559, pFirmware,
+ &(pImageData->mpBlocks[nBlock]), pData);
+ pData += n;
+ }
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_pll_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nPLL;
+ struct TPLL *pPLL;
+
+ pFirmware->mnPLLs = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnPLLs == 0)
+ goto end;
+
+ pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL);
+
+ for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) {
+ pPLL = &(pFirmware->mpPLLs[nPLL]);
+
+ memcpy(pPLL->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ n = fw_parse_block_data(pTAS2559, pFirmware, &(pPLL->mBlock), pData);
+ pData += n;
+ }
+
+end:
+ return pData - pDataStart;
+}
+
+static int fw_parse_program_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nProgram;
+ struct TProgram *pProgram;
+
+ pFirmware->mnPrograms = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnPrograms == 0)
+ goto end;
+
+ pFirmware->mpPrograms =
+ kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL);
+
+ for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) {
+ pProgram = &(pFirmware->mpPrograms[nProgram]);
+ memcpy(pProgram->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ pProgram->mnAppMode = pData[0];
+ pData++;
+
+ pProgram->mnBoost = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ n = fw_parse_data(pTAS2559, pFirmware, &(pProgram->mData), pData);
+ pData += n;
+ }
+
+end:
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_configuration_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nConfiguration;
+ struct TConfiguration *pConfiguration;
+
+ pFirmware->mnConfigurations = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnConfigurations == 0)
+ goto end;
+
+ pFirmware->mpConfigurations =
+ kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations,
+ GFP_KERNEL);
+
+ for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations;
+ nConfiguration++) {
+ pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]);
+ memcpy(pConfiguration->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV)
+ || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC)
+ && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) {
+ pConfiguration->mnDevices = (pData[0] << 8) + pData[1];
+ pData += 2;
+ } else
+ pConfiguration->mnDevices = DevBoth;
+
+ pConfiguration->mnProgram = pData[0];
+ pData++;
+
+ pConfiguration->mnPLL = pData[0];
+ pData++;
+
+ pConfiguration->mnSamplingRate = fw_convert_number(pData);
+ pData += 4;
+
+ if (pFirmware->mnDriverVersion >= PPC_DRIVER_MTPLLSRC) {
+ pConfiguration->mnPLLSrc = pData[0];
+ pData++;
+
+ pConfiguration->mnPLLSrcRate = fw_convert_number(pData);
+ pData += 4;
+ dev_err(pTAS2559->dev, "line:%d, pData: 0x%x, 0x%x, 0x%x, 0x%x", __LINE__, pData[0], pData[1], pData[2], pData[3]);
+ }
+
+ n = fw_parse_data(pTAS2559, pFirmware, &(pConfiguration->mData), pData);
+ pData += n;
+ }
+
+end:
+
+ return pData - pDataStart;
+}
+
+static int fw_parse_calibration_data(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData)
+{
+ unsigned char *pDataStart = pData;
+ unsigned int n;
+ unsigned int nCalibration;
+ struct TCalibration *pCalibration;
+
+ pFirmware->mnCalibrations = (pData[0] << 8) + pData[1];
+ pData += 2;
+
+ if (pFirmware->mnCalibrations == 0)
+ goto end;
+
+ pFirmware->mpCalibrations =
+ kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL);
+
+ for (nCalibration = 0;
+ nCalibration < pFirmware->mnCalibrations;
+ nCalibration++) {
+ pCalibration = &(pFirmware->mpCalibrations[nCalibration]);
+ memcpy(pCalibration->mpName, pData, 64);
+ pData += 64;
+
+ n = strlen(pData);
+ pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL);
+ pData += n + 1;
+
+ pCalibration->mnProgram = pData[0];
+ pData++;
+
+ pCalibration->mnConfiguration = pData[0];
+ pData++;
+
+ n = fw_parse_data(pTAS2559, pFirmware, &(pCalibration->mData), pData);
+ pData += n;
+ }
+
+end:
+
+ return pData - pDataStart;
+}
+
+static int fw_parse(struct tas2559_priv *pTAS2559,
+ struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize)
+{
+ int nPosition = 0;
+
+ nPosition = fw_parse_header(pTAS2559, pFirmware, pData, nSize);
+
+ if (nPosition < 0) {
+ dev_err(pTAS2559->dev, "Firmware: Wrong Header");
+ return -EINVAL;
+ }
+
+ if (nPosition >= nSize) {
+ dev_err(pTAS2559->dev, "Firmware: Too short");
+ return -EINVAL;
+ }
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ nPosition = fw_parse_pll_data(pTAS2559, pFirmware, pData);
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ nPosition = fw_parse_program_data(pTAS2559, pFirmware, pData);
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ nPosition = fw_parse_configuration_data(pTAS2559, pFirmware, pData);
+
+ pData += nPosition;
+ nSize -= nPosition;
+ nPosition = 0;
+
+ if (nSize > 64)
+ nPosition = fw_parse_calibration_data(pTAS2559, pFirmware, pData);
+
+ return 0;
+}
+
+void tas2559_fw_ready(const struct firmware *pFW, void *pContext)
+{
+ struct tas2559_priv *pTAS2559 = (struct tas2559_priv *) pContext;
+ int nResult;
+ unsigned int nProgram = 0;
+ unsigned int nSampleRate = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_info(pTAS2559->dev, "%s:\n", __func__);
+
+ if (unlikely(!pFW) || unlikely(!pFW->data)) {
+ dev_err(pTAS2559->dev, "%s firmware is not loaded.\n",
+ TAS2559_FW_NAME);
+ goto end;
+ }
+
+ if (pTAS2559->mpFirmware->mpConfigurations) {
+ nProgram = pTAS2559->mnCurrentProgram;
+ nSampleRate = pTAS2559->mnCurrentSampleRate;
+ dev_dbg(pTAS2559->dev, "clear current firmware\n");
+ tas2559_clear_firmware(pTAS2559->mpFirmware);
+ }
+
+ nResult = fw_parse(pTAS2559, pTAS2559->mpFirmware, (unsigned char *)(pFW->data), pFW->size);
+ release_firmware(pFW);
+
+ if (nResult < 0) {
+ dev_err(pTAS2559->dev, "firmware is corrupt\n");
+ goto end;
+ }
+
+ if (!pTAS2559->mpFirmware->mnPrograms) {
+ dev_err(pTAS2559->dev, "firmware contains no programs\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (!pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "firmware contains no configurations\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (nProgram >= pTAS2559->mpFirmware->mnPrograms) {
+ dev_info(pTAS2559->dev,
+ "no previous program, set to default\n");
+ nProgram = 0;
+ }
+
+ pTAS2559->mnCurrentSampleRate = nSampleRate;
+ nResult = tas2559_set_program(pTAS2559, nProgram, -1);
+
+end:
+ mutex_unlock(&pTAS2559->codec_lock);
+}
+
+int tas2559_enable(struct tas2559_priv *pTAS2559, bool bEnable)
+{
+ int nResult = 0;
+ struct TProgram *pProgram;
+ struct TConfiguration *pConfiguration;
+ unsigned int nValue;
+
+ dev_dbg(pTAS2559->dev, "%s: %s\n", __func__, bEnable ? "On" : "Off");
+
+ if ((pTAS2559->mpFirmware->mnPrograms == 0)
+ || (pTAS2559->mpFirmware->mnConfigurations == 0)) {
+ dev_err(pTAS2559->dev, "%s, firmware not loaded\n", __func__);
+ /*Load firmware*/
+ nResult = request_firmware_nowait(THIS_MODULE, 1, TAS2559_FW_NAME,
+ pTAS2559->dev, GFP_KERNEL, pTAS2559, tas2559_fw_ready);
+ if(nResult < 0) {
+ dev_err(pTAS2559->dev, "%s, firmware is loaded\n", __func__);
+ goto end;
+ }
+ }
+
+ /* check safe guard*/
+ nResult = tas2559_dev_read(pTAS2559, DevA, TAS2559_SAFE_GUARD_REG, &nValue);
+ if (nResult < 0)
+ goto end;
+ if ((nValue & 0xff) != TAS2559_SAFE_GUARD_PATTERN) {
+ dev_err(pTAS2559->dev, "ERROR DevA safe guard (0x%x) failure!\n", nValue);
+ nResult = -EPIPE;
+ pTAS2559->mnErrCode = ERROR_SAFE_GUARD;
+ pTAS2559->mbPowerUp = true;
+ goto end;
+ }
+
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[pTAS2559->mnCurrentProgram]);
+ if (bEnable) {
+ if (!pTAS2559->mbPowerUp) {
+ if (pTAS2559->mbLoadConfigurationPrePowerUp) {
+ pTAS2559->mbLoadConfigurationPrePowerUp = false;
+ nResult = tas2559_load_coefficient(pTAS2559,
+ pTAS2559->mnCurrentConfiguration, pTAS2559->mnNewConfiguration, false);
+ if (nResult < 0)
+ goto end;
+ }
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+ nResult = tas2559_DevStartup(pTAS2559, pConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ if (pConfiguration->mnDevices & DevB) {
+ nResult = tas2559_load_data(pTAS2559, &(pConfiguration->mData),
+ TAS2559_BLOCK_PST_POWERUP_DEV_B);
+ if (nResult < 0)
+ goto end;
+ }
+
+ nResult = tas2559_DevMute(pTAS2559, pConfiguration->mnDevices, false);
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mbPowerUp = true;
+ pTAS2559->mnRestart = 0;
+ }
+ } else {
+ if (pTAS2559->mbPowerUp) {
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+
+ nResult = tas2559_DevShutdown(pTAS2559, pConfiguration->mnDevices);
+ if (nResult < 0)
+ goto end;
+
+ pTAS2559->mbPowerUp = false;
+ pTAS2559->mnRestart = 0;
+ }
+ }
+
+ nResult = 0;
+
+end:
+
+ if (nResult < 0) {
+ if (pTAS2559->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_DEVB_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK | ERROR_SAFE_GUARD))
+ failsafe(pTAS2559);
+ }
+
+ dev_dbg(pTAS2559->dev, "%s: exit\n", __func__);
+ return nResult;
+}
+
+int tas2559_set_sampling_rate(struct tas2559_priv *pTAS2559, unsigned int nSamplingRate)
+{
+ int nResult = 0;
+ struct TConfiguration *pConfiguration;
+ unsigned int nConfiguration;
+
+ dev_dbg(pTAS2559->dev, "%s: nSamplingRate = %d [Hz]\n", __func__,
+ nSamplingRate);
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[pTAS2559->mnCurrentConfiguration]);
+
+ if (pConfiguration->mnSamplingRate == nSamplingRate) {
+ dev_info(pTAS2559->dev, "Sampling rate for current configuration matches: %d\n",
+ nSamplingRate);
+ nResult = 0;
+ goto end;
+ }
+
+ for (nConfiguration = 0;
+ nConfiguration < pTAS2559->mpFirmware->mnConfigurations;
+ nConfiguration++) {
+ pConfiguration =
+ &(pTAS2559->mpFirmware->mpConfigurations[nConfiguration]);
+
+ if ((pConfiguration->mnSamplingRate == nSamplingRate)
+ && (pConfiguration->mnProgram == pTAS2559->mnCurrentProgram)) {
+ dev_info(pTAS2559->dev,
+ "Found configuration: %s, with compatible sampling rate %d\n",
+ pConfiguration->mpName, nSamplingRate);
+ nResult = tas2559_load_configuration(pTAS2559, nConfiguration, false);
+ goto end;
+ }
+ }
+
+ dev_err(pTAS2559->dev, "Cannot find a configuration that supports sampling rate: %d\n",
+ nSamplingRate);
+
+end:
+
+ return nResult;
+}
+
+int tas2559_set_config(struct tas2559_priv *pTAS2559, int config)
+{
+ struct TConfiguration *pConfiguration;
+ struct TProgram *pProgram;
+ unsigned int nProgram = pTAS2559->mnCurrentProgram;
+ unsigned int nConfiguration = config;
+ int nResult = 0;
+
+ if ((!pTAS2559->mpFirmware->mpPrograms) ||
+ (!pTAS2559->mpFirmware->mpConfigurations)) {
+ dev_err(pTAS2559->dev, "Firmware not loaded\n");
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ if (nConfiguration >= pTAS2559->mpFirmware->mnConfigurations) {
+ dev_err(pTAS2559->dev, "Configuration %d doesn't exist\n",
+ nConfiguration);
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ pConfiguration = &(pTAS2559->mpFirmware->mpConfigurations[nConfiguration]);
+ pProgram = &(pTAS2559->mpFirmware->mpPrograms[nProgram]);
+
+ if (nProgram != pConfiguration->mnProgram) {
+ dev_err(pTAS2559->dev,
+ "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n",
+ nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram,
+ nProgram, pProgram->mpName);
+ nResult = -EINVAL;
+ goto end;
+ }
+
+ dev_dbg(pTAS2559->dev, "%s, load new conf %s\n", __func__, pConfiguration->mpName);
+ nResult = tas2559_load_configuration(pTAS2559, nConfiguration, false);
+
+end:
+
+ return nResult;
+}
+
+int tas2559_parse_dt(struct device *dev, struct tas2559_priv *pTAS2559)
+{
+ struct device_node *np = dev->of_node;
+ int rc = 0, ret = 0;
+ unsigned int value;
+
+ pTAS2559->mnDevAGPIORST = devm_gpiod_get(dev, "ti,tas2559-reset", GPIOD_OUT_LOW);
+ if (IS_ERR(pTAS2559->mnDevAGPIORST)) {
+ ret = PTR_ERR(pTAS2559->mnDevAGPIORST);
+ dev_err(dev, "Failed to request reset gpio, error %d\n", ret);
+ return ret;
+ }
+ else
+ dev_dbg(pTAS2559->dev, "%s, tas2559 reset gpio\n", __func__);
+
+ pTAS2559->mnDevBGPIORST = devm_gpiod_get(dev, "ti,tas2560-reset", GPIOD_OUT_LOW);
+ if (IS_ERR(pTAS2559->mnDevBGPIORST)) {
+ ret = PTR_ERR(pTAS2559->mnDevBGPIORST);
+ dev_err(dev, "Failed to request reset gpio, error %d\n", ret);
+ return ret;
+ }
+ else
+ dev_dbg(pTAS2559->dev, "%s, tas2560 reset gpio\n", __func__);
+
+ rc = of_property_read_u32(np, "ti,tas2559-addr", &value);
+ if (rc) {
+ dev_err(pTAS2559->dev, "Looking up %s property in node %s failed %d\n",
+ "ti,tas2559-addr", np->full_name, rc);
+ ret = -EINVAL;
+ goto end;
+ } else {
+ pTAS2559->mnDevAAddr = value;
+ dev_dbg(pTAS2559->dev, "ti,tas2559 addr=0x%x\n", pTAS2559->mnDevAAddr);
+ }
+
+ rc = of_property_read_u32(np, "ti,tas2560-addr", &value);
+ if (rc) {
+ dev_err(pTAS2559->dev, "Looking up %s property in node %s failed %d\n",
+ "ti,tas2560-addr", np->full_name, rc);
+ ret = -EINVAL;
+ goto end;
+ } else {
+ pTAS2559->mnDevBAddr = value;
+ dev_dbg(pTAS2559->dev, "ti,tas2560-addr=0x%x\n", pTAS2559->mnDevBAddr);
+ }
+
+end:
+
+ return ret;
+}
+
+// Codec related
+
+static const struct snd_soc_dapm_widget tas2559_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("ASI2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("ASIM", "ASIM Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_OUT_DRV("ClassD", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("NDivider", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("OUT")
+};
+
+static const struct snd_soc_dapm_route tas2559_audio_map[] = {
+ {"DAC", NULL, "ASI1"},
+ {"DAC", NULL, "ASI2"},
+ {"DAC", NULL, "ASIM"},
+ {"ClassD", NULL, "DAC"},
+ {"OUT", NULL, "ClassD"},
+ {"DAC", NULL, "PLL"},
+ {"DAC", NULL, "NDivider"},
+};
+
+static int tas2559_mute(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *codec = dai->component;
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+ tas2559_enable(pTAS2559, !mute);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return 0;
+}
+
+static int tas2559_hw_params(struct snd_pcm_substream *pSubstream,
+ struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
+{
+ struct snd_soc_component *pCodec = pDAI->component;
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(pCodec);
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_dbg(pTAS2559->dev, "%s\n", __func__);
+ tas2559_set_sampling_rate(pTAS2559, params_rate(pParams));
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return 0;
+}
+
+static int tas2559_configuration_get(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ pValue->value.integer.value[0] = pTAS2559->mnCurrentConfiguration;
+ dev_dbg(pTAS2559->dev, "%s = %d\n", __func__,
+ pTAS2559->mnCurrentConfiguration);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return 0;
+}
+
+static int tas2559_configuration_put(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned int nConfiguration = pValue->value.integer.value[0];
+ int ret = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ dev_info(pTAS2559->dev, "%s = %d\n", __func__, nConfiguration);
+ ret = tas2559_set_config(pTAS2559, nConfiguration);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static int tas2559_ldac_gain_get(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned char nGain = 0;
+ int ret = -1;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_get_DAC_gain(pTAS2559, DevA, &nGain);
+
+ if (ret >= 0)
+ pValue->value.integer.value[0] = nGain;
+
+ dev_dbg(pTAS2559->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static int tas2559_ldac_gain_put(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned int nGain = pValue->value.integer.value[0];
+ int ret = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_set_DAC_gain(pTAS2559, DevA, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static int tas2559_rdac_gain_get(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned char nGain = 0;
+ int ret = -1;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_get_DAC_gain(pTAS2559, DevB, &nGain);
+
+ if (ret >= 0)
+ pValue->value.integer.value[0] = nGain;
+
+ dev_dbg(pTAS2559->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+
+ return ret;
+}
+
+static int tas2559_rdac_gain_put(struct snd_kcontrol *pKcontrol,
+ struct snd_ctl_elem_value *pValue)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(pKcontrol);
+ struct tas2559_priv *pTAS2559 = snd_soc_component_get_drvdata(codec);
+ unsigned int nGain = pValue->value.integer.value[0];
+ int ret = 0;
+
+ mutex_lock(&pTAS2559->codec_lock);
+
+ ret = tas2559_set_DAC_gain(pTAS2559, DevB, nGain);
+
+ mutex_unlock(&pTAS2559->codec_lock);
+ return ret;
+}
+
+static const struct snd_kcontrol_new tas2559_snd_controls[] = {
+ SOC_SINGLE_EXT("TAS2559 DAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0,
+ tas2559_ldac_gain_get, tas2559_ldac_gain_put),
+ SOC_SINGLE_EXT("TAS2560 DAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0,
+ tas2559_rdac_gain_get, tas2559_rdac_gain_put),
+ SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
+ tas2559_configuration_get, tas2559_configuration_put),
+};
+
+static const struct snd_soc_component_driver soc_codec_driver_tas2559 = {
+ .idle_bias_on = false,
+ .controls = tas2559_snd_controls,
+ .num_controls = ARRAY_SIZE(tas2559_snd_controls),
+ .dapm_widgets = tas2559_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tas2559_dapm_widgets),
+ .dapm_routes = tas2559_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(tas2559_audio_map),
+ .legacy_dai_naming = 1,
+};
+
+static struct snd_soc_dai_ops tas2559_dai_ops = {
+ .mute_stream = tas2559_mute,
+ .hw_params = tas2559_hw_params,
+};
+
+#define TAS2559_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+static struct snd_soc_dai_driver tas2559_dai_driver[] = {
+ {
+ .name = "tas2559 ASI1",
+ .id = 0,
+ .playback = {
+ .stream_name = "ASI1 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2559_FORMATS,
+ },
+ .ops = &tas2559_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tas2559 ASI2",
+ .id = 1,
+ .playback = {
+ .stream_name = "ASI2 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2559_FORMATS,
+ },
+ .ops = &tas2559_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tas2559 ASIM",
+ .id = 2,
+ .playback = {
+ .stream_name = "ASIM Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = TAS2559_FORMATS,
+ },
+ .ops = &tas2559_dai_ops,
+ .symmetric_rate = 1,
+ },
+};
+
+int tas2559_register_codec(struct tas2559_priv *pTAS2559)
+{
+ int nResult = 0;
+
+ dev_info(pTAS2559->dev, "%s, enter\n", __func__);
+ nResult = devm_snd_soc_register_component(pTAS2559->dev,
+ &soc_codec_driver_tas2559,
+ tas2559_dai_driver, ARRAY_SIZE(tas2559_dai_driver));
+ return nResult;
+}
+
+int tas2559_deregister_codec(struct tas2559_priv *pTAS2559)
+{
+ snd_soc_unregister_component(pTAS2559->dev);
+ return 0;
+}
+
+//I2C Driver
+
+static bool tas2559_volatile(struct device *pDev, unsigned int nRegister)
+{
+ return true;
+}
+
+static bool tas2559_writeable(struct device *pDev, unsigned int nRegister)
+{
+ return true;
+}
+
+static const struct regmap_config tas2559_i2c_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = tas2559_writeable,
+ .volatile_reg = tas2559_volatile,
+ .cache_type = REGCACHE_NONE,
+ .max_register = 128,
+};
+
+static int tas2559_i2c_probe(struct i2c_client *pClient)
+{
+ struct tas2559_priv *pTAS2559;
+ int nResult;
+
+ dev_info(&pClient->dev, "%s enter\n", __func__);
+ pTAS2559 = devm_kzalloc(&pClient->dev, sizeof(struct tas2559_priv), GFP_KERNEL);
+
+ if (!pTAS2559) {
+ dev_err(&pClient->dev, " -ENOMEM\n");
+ nResult = -ENOMEM;
+ goto err;
+ }
+
+ pTAS2559->client = pClient;
+ pTAS2559->dev = &pClient->dev;
+ i2c_set_clientdata(pClient, pTAS2559);
+ dev_set_drvdata(&pClient->dev, pTAS2559);
+
+ pTAS2559->mpRegmap = devm_regmap_init_i2c(pClient, &tas2559_i2c_regmap);
+
+ if (IS_ERR(pTAS2559->mpRegmap)) {
+ nResult = PTR_ERR(pTAS2559->mpRegmap);
+ dev_err(&pClient->dev, "Failed to allocate register map: %d\n",
+ nResult);
+ goto err;
+ }
+
+ if (pClient->dev.of_node)
+ tas2559_parse_dt(&pClient->dev, pTAS2559);
+
+ tas2559_hw_reset(pTAS2559);
+
+ pTAS2559->mnRestart = 0;
+
+ mutex_init(&pTAS2559->dev_lock);
+
+ /* Reset the chip */
+ nResult = tas2559_dev_write(pTAS2559, DevBoth, TAS2559_SW_RESET_REG, 1);
+ if (nResult < 0) {
+ dev_err(&pClient->dev, "I2c fail, %d\n", nResult);
+ goto err;
+ }
+ msleep(1);
+
+ pTAS2559->mpFirmware = devm_kzalloc(&pClient->dev, sizeof(struct TFirmware), GFP_KERNEL);
+
+ if (!pTAS2559->mpFirmware) {
+ dev_err(&pClient->dev, "mpFirmware ENOMEM\n");
+ nResult = -ENOMEM;
+ goto err;
+ }
+
+ mutex_init(&pTAS2559->codec_lock);
+ tas2559_register_codec(pTAS2559);
+
+ nResult = request_firmware_nowait(THIS_MODULE, 1, TAS2559_FW_NAME,
+ pTAS2559->dev, GFP_KERNEL, pTAS2559, tas2559_fw_ready);
+
+err:
+
+ return nResult;
+}
+
+static void tas2559_i2c_remove(struct i2c_client *pClient)
+{
+ struct tas2559_priv *pTAS2559 = i2c_get_clientdata(pClient);
+
+ dev_info(pTAS2559->dev, "%s\n", __func__);
+
+ tas2559_deregister_codec(pTAS2559);
+ mutex_destroy(&pTAS2559->codec_lock);
+
+ mutex_destroy(&pTAS2559->dev_lock);
+ return;
+}
+
+static const struct i2c_device_id tas2559_i2c_id[] = {
+ {"tas2559", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tas2559_i2c_id);
+
+#if defined(CONFIG_OF)
+static const struct of_device_id tas2559_of_match[] = {
+ {.compatible = "ti,tas2559"},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, tas2559_of_match);
+#endif
+
+static struct i2c_driver tas2559_i2c_driver = {
+ .driver = {
+ .name = "tas2559",
+ .owner = THIS_MODULE,
+#if defined(CONFIG_OF)
+ .of_match_table = of_match_ptr(tas2559_of_match),
+#endif
+ },
+ .probe = tas2559_i2c_probe,
+ .remove = tas2559_i2c_remove,
+ .id_table = tas2559_i2c_id,
+};
+
+module_i2c_driver(tas2559_i2c_driver);
+
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("TAS2559 ALSA SOC Smart Amplifier Stereo driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/tas2559.h b/sound/soc/codecs/tas2559.h
new file mode 100644
index 00000000000..bdd5f4e767a
--- /dev/null
+++ b/sound/soc/codecs/tas2559.h
@@ -0,0 +1,525 @@
+/*
+** =============================================================================
+** Copyright (c) 2016 Texas Instruments Inc.
+**
+** This program is free software; you can redistribute it and/or modify it under
+** the terms of the GNU General Public License as published by the Free Software
+** Foundation; version 2.
+**
+** This program is distributed in the hope that it will be useful, but WITHOUT
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+**
+** File:
+** tas2559.h
+**
+** Description:
+** definitions and data structures for TAS2559 Android Linux driver
+**
+** =============================================================================
+*/
+
+#ifndef _TAS2559_H
+#define _TAS2559_H
+
+#include <linux/regmap.h>
+
+/* Page Control Register */
+#define TAS2559_PAGECTL_REG 0
+
+/* Book Control Register (available in page0 of each book) */
+#define TAS2559_BOOKCTL_PAGE 0
+#define TAS2559_BOOKCTL_REG 127
+
+#define TAS2559_REG(book, page, reg) ((((unsigned int)book * 256 * 128) + \
+ ((unsigned int)page * 128)) + reg)
+
+#define TAS2559_BOOK_ID(reg) ((unsigned char)(reg / (256 * 128)))
+#define TAS2559_PAGE_ID(reg) ((unsigned char)((reg % (256 * 128)) / 128))
+#define TAS2559_BOOK_REG(reg) ((unsigned char)(reg % (256 * 128)))
+#define TAS2559_PAGE_REG(reg) ((unsigned char)((reg % (256 * 128)) % 128))
+
+/* Book0, Page0 registers */
+#define TAS2559_SW_RESET_REG TAS2559_REG(0, 0, 1)
+
+#define TAS2559_REV_PGID_REG TAS2559_REG(0, 0, 3)
+#define TAS2559_PG_VERSION_1P0 0x00
+#define TAS2559_PG_VERSION_2P0 0x10
+#define TAS2559_PG_VERSION_2P1 0x20
+
+#define TAS2559_POWER_CTRL1_REG TAS2559_REG(0, 0, 4)
+#define TAS2559_POWER_CTRL2_REG TAS2559_REG(0, 0, 5)
+
+#define TAS2559_SPK_CTRL_REG TAS2559_REG(0, 0, 6)
+/* B0P0R6 - TAS2559_SPK_CTRL_REG */
+#define TAS2559_DAC_GAIN_MASK (0xf << 3)
+#define TAS2559_DAC_GAIN_SHIFT 0x03
+
+#define TAS2559_MUTE_REG TAS2559_REG(0, 0, 7)
+#define TAS2559_SNS_CTRL_REG TAS2559_REG(0, 0, 8)
+#define TAS2559_ADC_INPUT_SEL_REG TAS2559_REG(0, 0, 9)
+#define TAS2559_DBOOST_CTL_REG TAS2559_REG(0, 0, 10)
+#define TAS2559_NONAME11_REG TAS2559_REG(0, 0, 11)
+#define TAS2559_NONAME12_REG TAS2559_REG(0, 0, 12)
+#define TAS2559_NONAME13_REG TAS2559_REG(0, 0, 13)
+#define TAS2559_NONAME14_REG TAS2559_REG(0, 0, 14)
+#define TAS2559_NONAME15_REG TAS2559_REG(0, 0, 15)
+#define TAS2559_NONAME16_REG TAS2559_REG(0, 0, 16)
+#define TAS2559_NONAME17_REG TAS2559_REG(0, 0, 17)
+#define TAS2559_NONAME18_REG TAS2559_REG(0, 0, 18)
+#define TAS2559_SAR_SAMPLING_TIME_REG TAS2559_REG(0, 0, 19)
+#define TAS2559_SAR_ADC1_REG TAS2559_REG(0, 0, 20)
+#define TAS2559_SAR_ADC2_REG TAS2559_REG(0, 0, 21) /* B0_P0_R0x15 */
+#define TAS2559_CRC_CHECKSUM_REG TAS2559_REG(0, 0, 32) /* B0_P0_R0x20 */
+#define TAS2559_CRC_RESET_REG TAS2559_REG(0, 0, 33) /* B0_P0_R0x21 */
+#define TAS2559_DSP_MODE_SELECT_REG TAS2559_REG(0, 0, 34)
+#define TAS2559_SAFE_GUARD_REG TAS2559_REG(0, 0, 37) /* B0_P0_R0x25 */
+#define TAS2559_ASI_CTRL_REG TAS2559_REG(0, 0, 42)
+#define TAS2559_CLK_ERR_CTRL TAS2559_REG(0, 0, 44) /* B0_P0_R0x2c */
+#define TAS2559_CLK_ERR_CTRL2 TAS2559_REG(0, 0, 45) /* B0_P0_R0x2d*/
+#define TAS2559_CLK_ERR_CTRL3 TAS2559_REG(0, 0, 46) /* B0_P0_R0x2e*/
+#define TAS2559_DBOOST_CFG_REG TAS2559_REG(0, 0, 52)
+#define TAS2559_POWER_UP_FLAG_REG TAS2559_REG(0, 0, 100) /* B0_P0_R0x64 */
+#define TAS2559_FLAGS_1 TAS2559_REG(0, 0, 104) /* B0_P0_R0x68 */
+#define TAS2559_FLAGS_2 TAS2559_REG(0, 0, 108) /* B0_P0_R0x6c */
+
+/* Book0, Page1 registers */
+#define TAS2559_ASI1_DAC_FORMAT_REG TAS2559_REG(0, 1, 1)
+#define TAS2559_ASI1_ADC_FORMAT_REG TAS2559_REG(0, 1, 2)
+#define TAS2559_ASI1_OFFSET1_REG TAS2559_REG(0, 1, 3)
+#define TAS2559_ASI1_ADC_PATH_REG TAS2559_REG(0, 1, 7)
+#define TAS2559_ASI1_DAC_BCLK_REG TAS2559_REG(0, 1, 8)
+#define TAS2559_ASI1_DAC_WCLK_REG TAS2559_REG(0, 1, 9)
+#define TAS2559_ASI1_ADC_BCLK_REG TAS2559_REG(0, 1, 10)
+#define TAS2559_ASI1_ADC_WCLK_REG TAS2559_REG(0, 1, 11)
+#define TAS2559_ASI1_DIN_DOUT_MUX_REG TAS2559_REG(0, 1, 12)
+#define TAS2559_ASI1_BDIV_CLK_SEL_REG TAS2559_REG(0, 1, 13)
+#define TAS2559_ASI1_BDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 14)
+#define TAS2559_ASI1_WDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 15)
+#define TAS2559_ASI1_DAC_CLKOUT_REG TAS2559_REG(0, 1, 16)
+#define TAS2559_ASI1_ADC_CLKOUT_REG TAS2559_REG(0, 1, 17)
+
+#define TAS2559_ASI2_DAC_FORMAT_REG TAS2559_REG(0, 1, 21)
+#define TAS2559_ASI2_ADC_FORMAT_REG TAS2559_REG(0, 1, 22)
+#define TAS2559_ASI2_OFFSET1_REG TAS2559_REG(0, 1, 23)
+#define TAS2559_ASI2_ADC_PATH_REG TAS2559_REG(0, 1, 27)
+#define TAS2559_ASI2_DAC_BCLK_REG TAS2559_REG(0, 1, 28)
+#define TAS2559_ASI2_DAC_WCLK_REG TAS2559_REG(0, 1, 29)
+#define TAS2559_ASI2_ADC_BCLK_REG TAS2559_REG(0, 1, 30)
+#define TAS2559_ASI2_ADC_WCLK_REG TAS2559_REG(0, 1, 31)
+#define TAS2559_ASI2_DIN_DOUT_MUX_REG TAS2559_REG(0, 1, 32)
+#define TAS2559_ASI2_BDIV_CLK_SEL_REG TAS2559_REG(0, 1, 33)
+#define TAS2559_ASI2_BDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 34)
+#define TAS2559_ASI2_WDIV_CLK_RATIO_REG TAS2559_REG(0, 1, 35)
+#define TAS2559_ASI2_DAC_CLKOUT_REG TAS2559_REG(0, 1, 36)
+#define TAS2559_ASI2_ADC_CLKOUT_REG TAS2559_REG(0, 1, 37)
+
+#define TAS2559_GPIO1_PIN_REG TAS2559_REG(0, 1, 61) /* B0_P1_R0x3d */
+#define TAS2559_GPIO2_PIN_REG TAS2559_REG(0, 1, 62) /* B0_P1_R0x3e */
+#define TAS2559_GPIO3_PIN_REG TAS2559_REG(0, 1, 63)
+#define TAS2559_GPIO4_PIN_REG TAS2559_REG(0, 1, 64)
+#define TAS2559_GPIO5_PIN_REG TAS2559_REG(0, 1, 65)
+#define TAS2559_GPIO6_PIN_REG TAS2559_REG(0, 1, 66)
+#define TAS2559_GPIO7_PIN_REG TAS2559_REG(0, 1, 67)
+#define TAS2559_GPIO8_PIN_REG TAS2559_REG(0, 1, 68)
+#define TAS2559_GPIO9_PIN_REG TAS2559_REG(0, 1, 69)
+#define TAS2559_GPIO10_PIN_REG TAS2559_REG(0, 1, 70)
+
+#define TAS2559_GPI_PIN_REG TAS2559_REG(0, 1, 77) /* B0_P1_R0x4d */
+#define TAS2559_GPIO_HIZ_CTRL1_REG TAS2559_REG(0, 1, 79)
+#define TAS2559_GPIO_HIZ_CTRL2_REG TAS2559_REG(0, 1, 80) /* B0_P1_R0x50 */
+#define TAS2559_GPIO_HIZ_CTRL3_REG TAS2559_REG(0, 1, 81)
+#define TAS2559_GPIO_HIZ_CTRL4_REG TAS2559_REG(0, 1, 82)
+#define TAS2559_GPIO_HIZ_CTRL5_REG TAS2559_REG(0, 1, 83)
+
+#define TAS2559_BIT_BANG_CTRL_REG TAS2559_REG(0, 1, 87)
+#define TAS2559_BIT_BANG_OUT1_REG TAS2559_REG(0, 1, 88)
+#define TAS2559_BIT_BANG_OUT2_REG TAS2559_REG(0, 1, 89)
+#define TAS2559_BIT_BANG_IN1_REG TAS2559_REG(0, 1, 90)
+#define TAS2559_BIT_BANG_IN2_REG TAS2559_REG(0, 1, 91)
+#define TAS2559_BIT_BANG_IN3_REG TAS2559_REG(0, 1, 92)
+
+#define TAS2559_PDM_IN_CLK_REG TAS2559_REG(0, 1, 94)
+#define TAS2559_PDM_IN_PIN_REG TAS2559_REG(0, 1, 95)
+
+#define TAS2559_ASIM_IFACE1_REG TAS2559_REG(0, 1, 98)
+#define TAS2559_ASIM_FORMAT_REG TAS2559_REG(0, 1, 99)
+#define TAS2559_ASIM_IFACE3_REG TAS2559_REG(0, 1, 100)
+#define TAS2559_ASIM_IFACE4_REG TAS2559_REG(0, 1, 101)
+#define TAS2559_ASIM_IFACE5_REG TAS2559_REG(0, 1, 102)
+#define TAS2559_ASIM_IFACE6_REG TAS2559_REG(0, 1, 103)
+#define TAS2559_ASIM_IFACE7_REG TAS2559_REG(0, 1, 104)
+#define TAS2559_ASIM_IFACE8_REG TAS2559_REG(0, 1, 105)
+#define TAS2559_CLK_HALT_REG TAS2559_REG(0, 1, 106) /* B0_P1_R0x6a */
+#define TAS2559_INT_GEN1_REG TAS2559_REG(0, 1, 108) /* B0_P1_R0x6c */
+#define TAS2559_INT_GEN2_REG TAS2559_REG(0, 1, 109) /* B0_P1_R0x6d */
+#define TAS2559_INT_GEN3_REG TAS2559_REG(0, 1, 110) /* B0_P1_R0x6e */
+#define TAS2559_INT_GEN4_REG TAS2559_REG(0, 1, 111) /* B0_P1_R0x6f */
+#define TAS2559_INT_MODE_REG TAS2559_REG(0, 1, 114) /* B0_P1_R0x72 */
+#define TAS2559_MAIN_CLKIN_REG TAS2559_REG(0, 1, 115)
+#define TAS2559_PLL_CLKIN_REG TAS2559_REG(0, 1, 116)
+#define TAS2559_CLKOUT_MUX_REG TAS2559_REG(0, 1, 117)
+#define TAS2559_CLKOUT_CDIV_REG TAS2559_REG(0, 1, 118)
+#define TAS2559_HACK_GP01_REG TAS2559_REG(0, 1, 122)
+
+#define TAS2559_SLEEPMODE_CTL_REG TAS2559_REG(0, 2, 7)
+#define TAS2559_HACK01_REG TAS2559_REG(0, 2, 10)
+
+#define TAS2559_ISENSE_THRESHOLD TAS2559_REG(0, 50, 104)
+#define TAS2559_BOOSTON_EFFICIENCY TAS2559_REG(0, 51, 16)
+#define TAS2559_BOOSTOFF_EFFICIENCY TAS2559_REG(0, 51, 20)
+#define TAS2559_BOOST_HEADROOM TAS2559_REG(0, 51, 24)
+#define TAS2559_THERMAL_FOLDBACK_REG TAS2559_REG(0, 51, 100)
+
+#define TAS2559_SA_CHL_CTRL_REG TAS2559_REG(0, 53, 20) /* B0_P0x35_R0x14 */
+#define TAS2559_VPRED_COMP_REG TAS2559_REG(0, 53, 24)
+#define TAS2559_SA_COEFF_SWAP_REG TAS2559_REG(0, 53, 44) /* B0_P0x35_R0x2c */
+
+#define TAS2559_TEST_MODE_REG TAS2559_REG(0, 253, 13)
+#define TAS2559_BROADCAST_REG TAS2559_REG(0, 253, 54)
+#define TAS2559_VBST_VOLT_REG TAS2559_REG(0, 253, 58)/* B0_P0xfd_R0x3a */
+#define TAS2559_CRYPTIC_REG TAS2559_REG(0, 253, 71)
+
+#define TAS2559_DAC_INTERPOL_REG TAS2559_REG(100, 0, 1)
+#define TAS2559_SOFT_MUTE_REG TAS2559_REG(100, 0, 7)
+#define TAS2559_PLL_P_VAL_REG TAS2559_REG(100, 0, 27)
+#define TAS2559_PLL_J_VAL_REG TAS2559_REG(100, 0, 28)
+#define TAS2559_PLL_D_VAL_MSB_REG TAS2559_REG(100, 0, 29)
+#define TAS2559_PLL_D_VAL_LSB_REG TAS2559_REG(100, 0, 30)
+#define TAS2559_CLK_MISC_REG TAS2559_REG(100, 0, 31)
+#define TAS2559_PLL_N_VAL_REG TAS2559_REG(100, 0, 32)
+#define TAS2559_DAC_MADC_VAL_REG TAS2559_REG(100, 0, 33)
+#define TAS2559_ISENSE_DIV_REG TAS2559_REG(100, 0, 42)
+#define TAS2559_RAMP_CLK_DIV_MSB_REG TAS2559_REG(100, 0, 43)
+#define TAS2559_RAMP_CLK_DIV_LSB_REG TAS2559_REG(100, 0, 44)
+#define TAS2559_VBOOST_CTL_REG TAS2559_REG(100, 0, 64) /* B0x64_P0x00_R0x40 */
+
+#define TAS2559_DIE_TEMP_REG TAS2559_REG(130, 2, 124) /* B0x82_P0x02_R0x7C */
+#define TAS2559_DEVA_CALI_R0_REG TAS2559_REG(140, 47, 40) /* B0x8c_P0x2f_R0x28 */
+#define TAS2559_DEVB_CALI_R0_REG TAS2559_REG(140, 54, 12) /* B0x8c_P0x36_R0x0c */
+
+/* Bits */
+/* B0P0R4 - TAS2559_POWER_CTRL1_REG */
+#define TAS2559_SW_SHUTDOWN (0x1 << 0)
+#define TAS2559_MADC_POWER_UP (0x1 << 3)
+#define TAS2559_MDAC_POWER_UP (0x1 << 4)
+#define TAS2559_NDIV_POWER_UP (0x1 << 5)
+#define TAS2559_PLL_POWER_UP (0x1 << 6)
+#define TAS2559_DSP_POWER_UP (0x1 << 7)
+
+/* B0P0R5 - TAS2559_POWER_CTRL2_REG */
+#define TAS2559_VSENSE_ENABLE (0x1 << 0)
+#define TAS2559_ISENSE_ENABLE (0x1 << 1)
+#define TAS2559_BOOST_ENABLE (0x1 << 5)
+#define TAS2559_CLASSD_ENABLE (0x1 << 7)
+
+/* B0P0R7 - TAS2559_MUTE_REG */
+#define TAS2559_CLASSD_MUTE (0x1 << 0)
+#define TAS2559_ISENSE_MUTE (0x1 << 1)
+
+/* B0P253R13 - TAS2559_TEST_MODE_REG */
+#define TAS2559_TEST_MODE_ENABLE (13)
+#define TAS2559_TEST_MODE_MASK (0xf << 0)
+
+/* B0P253R71 - TAS2559_CRYPTIC_REG */
+#define TAS2559_OSC_TRIM_CAP(x) ((x & 0x3f) << 0)
+#define TAS2559_DISABLE_ENCRYPTION (0x1 << 6)
+#define TAS2559_SL_COMP (0x1 << 7)
+
+/* B0P1R115/6 - TAS2559_MAIN/PLL_CLKIN_REG */
+#define TAS2559_XXX_CLKIN_GPIO1 (0)
+#define TAS2559_XXX_CLKIN_GPIO2 (1)
+#define TAS2559_XXX_CLKIN_GPIO3 (2)
+#define TAS2559_XXX_CLKIN_GPIO4 (3)
+#define TAS2559_XXX_CLKIN_GPIO5 (4)
+#define TAS2559_XXX_CLKIN_GPIO6 (5)
+#define TAS2559_XXX_CLKIN_GPIO7 (6)
+#define TAS2559_XXX_CLKIN_GPIO8 (7)
+#define TAS2559_XXX_CLKIN_GPIO9 (8)
+#define TAS2559_XXX_CLKIN_GPIO10 (9)
+#define TAS2559_XXX_CLKIN_GPI1 (12)
+#define TAS2559_XXX_CLKIN_GPI2 (13)
+#define TAS2559_XXX_CLKIN_GPI3 (14)
+#define TAS2559_NDIV_CLKIN_PLL (15)
+#define TAS2559_PLL_CLKIN_INT_OSC (15)
+
+#define TAS2559_MCLK_CLKIN_SRC_GPIO1 (0)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO2 (1)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO3 (2)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO4 (3)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO5 (4)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO6 (5)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO7 (6)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO8 (7)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO9 (8)
+#define TAS2559_MCLK_CLKIN_SRC_GPIO10 (9)
+#define TAS2559_MCLK_CLKIN_SRC_GPI1 (12)
+#define TAS2559_MCLK_CLKIN_SRC_GPI2 (13)
+#define TAS2559_MCLK_CLKIN_SRC_GPI3 (14)
+
+#define TAS2559_FORMAT_I2S (0x0 << 5)
+#define TAS2559_FORMAT_DSP (0x1 << 5)
+#define TAS2559_FORMAT_RIGHT_J (0x2 << 5)
+#define TAS2559_FORMAT_LEFT_J (0x3 << 5)
+#define TAS2559_FORMAT_MONO_PCM (0x4 << 5)
+#define TAS2559_FORMAT_MASK (0x7 << 5)
+
+#define TAS2559_WORDLENGTH_16BIT (0x0 << 3)
+#define TAS2559_WORDLENGTH_20BIT (0x1 << 3)
+#define TAS2559_WORDLENGTH_24BIT (0x2 << 3)
+#define TAS2559_WORDLENGTH_32BIT (0x3 << 3)
+#define TAS2559_WORDLENGTH_MASK TAS2559_WORDLENGTH_32BIT
+
+/* B100P0R7 - TAS2559_SOFT_MUTE_REG */
+#define TAS2559_PDM_SOFT_MUTE (0x1 << 0)
+#define TAS2559_VSENSE_SOFT_MUTE (0x1 << 1)
+#define TAS2559_ISENSE_SOFT_MUTE (0x1 << 2)
+#define TAS2559_CLASSD_SOFT_MUTE (0x1 << 3)
+
+/* B100P0R27 - TAS2559_PLL_P_VAL_REG */
+#define TAS2559_PLL_P_VAL_MASK (0x3f << 0)
+
+/* B100P0R28 - TAS2559_PLL_J_VAL_REG */
+#define TAS2559_PLL_J_VAL_MASK ((unsigned int) (0x7f << 0))
+#define TAS2559_PLL_J_VAL_MASKX 0x00
+
+/* B100P0R29-30 - TAS2559_PLL_D_VAL_MSB/LSB_REG */
+#define TAS2559_PLL_D_MSB_VAL(x) ((x >> 8) & 0x3f)
+#define TAS2559_PLL_D_LSB_VAL(x) (x & 0xff)
+
+/* B100P0R31 - TAS2559_CLK_MISC_REG */
+#define TAS2559_DSP_CLK_FROM_PLL (0x1 << 5)
+
+#define TAS2559_FW_NAME "tas2559_uCDSP.bin"
+
+#define CHANNEL_LEFT (0)
+#define CHANNEL_RIGHT (1)
+
+#define TAS2559_APP_ROM1MODE 0
+#define TAS2559_APP_ROM2MODE 1
+#define TAS2559_APP_TUNINGMODE 2
+#define TAS2559_APP_ROM1_96KHZ 3
+#define TAS2559_APP_ROM2_96KHZ 4
+#define TAS2559_APP_RAMMODE 5
+
+#define TAS2559_BOOST_OFF 0
+#define TAS2559_BOOST_DEVA 1
+#define TAS2559_BOOST_DEVB 2
+#define TAS2559_BOOST_BOTH 3
+
+#define TAS2559_AD_BD 0 /* DevA default, DevB default */
+#define TAS2559_AM_BM 1 /* DevA mute, DevB mute */
+#define TAS2559_AL_BR 2 /* DevA left channel, DevB right channel */
+#define TAS2559_AR_BL 3 /* DevA right channel, DevB left channel */
+#define TAS2559_AH_BH 4 /* DevA (L+R)/2, DevB (L+R)/2 */
+
+#define TAS2559_VBST_DEFAULT 0 /* firmware default */
+#define TAS2559_VBST_A_ON 1 /* DevA always 8.5V, DevB default */
+#define TAS2559_VBST_B_ON 2 /* DevA default, DevB always 8.5V */
+#define TAS2559_VBST_A_ON_B_ON (TAS2559_VBST_A_ON | TAS2559_VBST_B_ON) /* both DevA and DevB always 8.5V */
+#define TAS2559_VBST_NEED_DEFAULT 0xff /* need default value */
+
+#define TAS2559_VBST_8P5V 0 /* coresponding PPG 0dB */
+#define TAS2559_VBST_8P1V 1 /* coresponding PPG -1dB */
+#define TAS2559_VBST_7P6V 2 /* coresponding PPG -2dB */
+#define TAS2559_VBST_6P6V 3 /* coresponding PPG -3dB */
+#define TAS2559_VBST_5P6V 4 /* coresponding PPG -4dB */
+
+#define TAS2559_YRAM_BOOK1 140 /* 0x8c */
+
+#define TAS2559_YRAM1_PAGE 42 /* 0x2a */
+#define TAS2559_YRAM1_START_REG 88
+#define TAS2559_YRAM1_END_REG 127
+
+#define TAS2559_YRAM2_START_PAGE 43 /* 0x2b */
+#define TAS2559_YRAM2_END_PAGE 55
+#define TAS2559_YRAM2_START_REG 8
+#define TAS2559_YRAM2_END_REG 127
+
+#define TAS2559_YRAM3_PAGE 56 /* 0x38 */
+#define TAS2559_YRAM3_START_REG 8
+#define TAS2559_YRAM3_END_REG 47
+
+/* should not include B0_P53_R44-R47 */
+#define TAS2559_YRAM_BOOK2 0
+#define TAS2559_YRAM4_START_PAGE 50 /* 0x32 */
+#define TAS2559_YRAM4_END_PAGE 60 /* 0x3c */
+#define TAS2559_YRAM4_START_REG 8
+#define TAS2559_YRAM4_END_REG 127
+
+#define TAS2559_YRAM5_PAGE 61 /* 0x3d */
+#define TAS2559_YRAM5_START_REG 8
+#define TAS2559_YRAM5_END_REG 27
+
+#define TAS2559_YRAM_BOOK3 120 /* 0x78 */
+#define TAS2559_YRAM6_PAGE 12 /* 0x0c */
+#define TAS2559_YRAM6_START_REG 104 /* 0x68 */
+#define TAS2559_YRAM6_END_REG 107 /* 0x6b */
+
+#define TAS2559_SAFE_GUARD_PATTERN 0x5a
+#define LOW_TEMPERATURE_CHECK_PERIOD 5000 /* 5 second */
+
+/* Page Control Register */
+#define TAS2560_PAGECTL_REG 0
+
+/* Book Control Register (available in page0 of each book) */
+#define TAS2560_BOOKCTL_PAGE 0
+#define TAS2560_BOOKCTL_REG 127
+
+#define TAS2560_REG(book, page, reg) (((book * 256 * 128) + \
+ (page * 128)) + reg)
+
+#define TAS2560_BOOK_ID(reg) (reg / (256 * 128))
+#define TAS2560_PAGE_ID(reg) ((reg % (256 * 128)) / 128)
+#define TAS2560_BOOK_REG(reg) (reg % (256 * 128))
+#define TAS2560_PAGE_REG(reg) ((reg % (256 * 128)) % 128)
+
+/* Book0, Page0 registers */
+#define TAS2560_SW_RESET_REG TAS2560_REG(0, 0, 1)
+#define TAS2560_DEV_MODE_REG TAS2560_REG(0, 0, 2)
+#define TAS2560_SPK_CTRL_REG TAS2560_REG(0, 0, 4)
+#define TAS2560_MUTE_REG TAS2560_REG(0, 0, 7)
+#define TAS2560_PWR_REG TAS2560_REG(0, 0, 7)
+#define TAS2560_PWR_BIT_MASK (0x3 << 6)
+#define TAS2560_MUTE_MASK (0x7)
+
+#define TAS2560_SR_CTRL1 TAS2560_REG(0, 0, 8)
+#define TAS2560_LOAD TAS2560_REG(0, 0, 9)
+#define TAS2560_SR_CTRL2 TAS2560_REG(0, 0, 13) /*B0_P0_R0x0d*/
+#define TAS2560_SR_CTRL3 TAS2560_REG(0, 0, 14) /*B0_P0_R0x0e*/
+
+#define TAS2560_CLK_SEL TAS2560_REG(0, 0, 15)
+#define TAS2560_PLL_SRC_MASK (0xc0)
+#define TAS2560_PLL_CLKIN_BCLK (0)
+#define TAS2560_PLL_CLKIN_MCLK (1)
+#define TAS2560_PLL_CLKIN_PDMCLK (2)
+#define TAS2560_PLL_P_MASK (0x3f)
+
+#define TAS2560_SET_FREQ TAS2560_REG(0, 0, 16)
+#define TAS2560_PLL_J_MASK (0x7f)
+
+#define TAS2560_PLL_D_MSB TAS2560_REG(0, 0, 17) /*B0_P0_R0x11*/
+#define TAS2560_PLL_D_LSB TAS2560_REG(0, 0, 18) /*B0_P0_R0x12*/
+
+#define TAS2560_DAI_FMT TAS2560_REG(0, 0, 20) /* B0_P0_R0x14 */
+#define TAS2560_ASI_CTRL TAS2560_REG(0, 0, 21) /* B0_P0_R0x15 */
+#define TAS2560_ASI_OFFSET_1 TAS2560_REG(0, 0, 22) /*B0_P0_R0x16*/
+#define TAS2560_ASI_CFG_1 TAS2560_REG(0, 0, 24) /* B0_P0_R0x18 */
+#define TAS2560_DIRINV_MASK 0x3c
+#define TAS2560_BCLKINV (1 << 2)
+#define TAS2560_WCLKINV (1 << 3)
+#define TAS2560_BCLKDIR (1 << 4)
+#define TAS2560_WCLKDIR (1 << 5)
+
+#define TAS2560_CLK_ERR_CTRL TAS2560_REG(0, 0, 33) /* B0_P0_R0x21 */
+#define TAS2560_IRQ_PIN_REG TAS2560_REG(0, 0, 35) /* B0_P0_R0x23 */
+#define TAS2560_INT_MODE_REG TAS2560_REG(0, 0, 36) /* B0_P0_R0x24 */
+#define TAS2560_INT_GEN_REG TAS2560_REG(0, 0, 37) /* B0_P0_R0x25 */
+#define TAS2560_FLAGS_1 TAS2560_REG(0, 0, 38) /* B0_P0_R0x26 */
+#define TAS2560_FLAGS_2 TAS2560_REG(0, 0, 39) /* B0_P0_R0x27 */
+#define TAS2560_POWER_UP_FLAG_REG TAS2560_REG(0, 0, 42) /* B0_P0_R0x2a */
+
+#define TAS2560_DR_BOOST_REG_2 TAS2560_REG(0, 0, 60) /* B0_P0_R0x3c */
+#define TAS2560_DR_BOOST_REG_1 TAS2560_REG(0, 0, 73) /* B0_P0_R0x49 */
+#define TAS2560_VBOOST_CTL_REG TAS2560_REG(0, 0, 79) /* B0_P0_R0x4f */
+#define TAS2560_CLK_ERR_CTRL2 TAS2560_REG(0, 0, 80) /* B0_P0_R0x50 */
+#define TAS2560_SLEEPMODE_CTL_REG TAS2560_REG(0, 0, 84) /* B0_P0_R0x54 */
+#define TAS2560_ID_REG TAS2560_REG(0, 0, 125)
+#define TAS2560_CRC_CHK_REG TAS2560_REG(0, 0, 126) /* B0_P0_R0x7e */
+
+/* Book0, Page50 registers */
+#define TAS2560_HPF_CUTOFF_CTL1 TAS2560_REG(0, 50, 28) /* B0_P0x32_R0x1c */
+#define TAS2560_HPF_CUTOFF_CTL2 TAS2560_REG(0, 50, 32) /* B0_P0x32_R0x20 */
+#define TAS2560_HPF_CUTOFF_CTL3 TAS2560_REG(0, 50, 36) /* B0_P0x32_R0x24 */
+
+#define TAS2560_ISENSE_PATH_CTL1 TAS2560_REG(0, 50, 40) /* B0_P0x32_R0x28 */
+#define TAS2560_ISENSE_PATH_CTL2 TAS2560_REG(0, 50, 44) /* B0_P0x32_R0x2c */
+#define TAS2560_ISENSE_PATH_CTL3 TAS2560_REG(0, 50, 48) /* B0_P0x32_R0x30 */
+
+#define TAS2560_VLIMIT_THRESHOLD TAS2560_REG(0, 50, 60)
+#define TAS2560_IDLE_CHNL_DETECT TAS2560_REG(0, 50, 108) /* B0_P0x32_R0x6c */
+
+/* Book0, Page51 registers */
+#define TAS2560_BOOST_HEAD TAS2560_REG(0, 51, 24) /* B0_P0x33_R0x18 */
+#define TAS2560_BOOST_ON TAS2560_REG(0, 51, 16) /* B0_P0x33_R0x10 */
+#define TAS2560_BOOST_OFF TAS2560_REG(0, 51, 20) /* B0_P0x33_R0x14 */
+#define TAS2560_BOOST_TABLE_CTRL1 TAS2560_REG(0, 51, 32) /* B0_P0x33_R0x20 */
+#define TAS2560_BOOST_TABLE_CTRL2 TAS2560_REG(0, 51, 36) /* B0_P0x33_R0x24 */
+#define TAS2560_BOOST_TABLE_CTRL3 TAS2560_REG(0, 51, 40) /* B0_P0x33_R0x28 */
+#define TAS2560_BOOST_TABLE_CTRL4 TAS2560_REG(0, 51, 44) /* B0_P0x33_R0x2c */
+#define TAS2560_BOOST_TABLE_CTRL5 TAS2560_REG(0, 51, 48) /* B0_P0x33_R0x30 */
+#define TAS2560_BOOST_TABLE_CTRL6 TAS2560_REG(0, 51, 52) /* B0_P0x33_R0x34 */
+#define TAS2560_BOOST_TABLE_CTRL7 TAS2560_REG(0, 51, 56) /* B0_P0x33_R0x38 */
+#define TAS2560_BOOST_TABLE_CTRL8 TAS2560_REG(0, 51, 60) /* B0_P0x33_R0x3c */
+#define TAS2560_THERMAL_FOLDBACK TAS2560_REG(0, 51, 100) /* B0_P0x33_R0x64 */
+
+/* Book0, Page52 registers */
+#define TAS2560_VSENSE_DEL_CTL1 TAS2560_REG(0, 52, 52) /* B0_P0x34_R0x34 */
+#define TAS2560_VSENSE_DEL_CTL2 TAS2560_REG(0, 52, 56) /* B0_P0x34_R0x38 */
+#define TAS2560_VSENSE_DEL_CTL3 TAS2560_REG(0, 52, 60) /* B0_P0x34_R0x3c */
+#define TAS2560_VSENSE_DEL_CTL4 TAS2560_REG(0, 52, 64) /* B0_P0x34_R0x40 */
+#define TAS2560_VSENSE_DEL_CTL5 TAS2560_REG(0, 52, 68) /* B0_P0x34_R0x44 */
+
+#define TAS2560_VBST_VOLT_REG TAS2559_REG(0, 253, 54) /* B0_P0xfd_R0x36 */
+
+#define TAS2560_DATAFORMAT_I2S (0x0 << 2)
+#define TAS2560_DATAFORMAT_DSP (0x1 << 2)
+#define TAS2560_DATAFORMAT_RIGHT_J (0x2 << 2)
+#define TAS2560_DATAFORMAT_LEFT_J (0x3 << 2)
+
+#define TAS2560_DAI_FMT_MASK (0x7 << 2)
+#define LOAD_MASK 0x18
+
+#define TAS2560_YRAM_BOOK 0
+#define TAS2560_YRAM_START_PAGE 50
+#define TAS2560_YRAM_END_PAGE 52
+#define TAS2560_YRAM_START_REG 8
+#define TAS2560_YRAM_END_REG 127
+
+#define ERROR_NONE 0x00000000
+#define ERROR_PLL_ABSENT 0x00000001
+#define ERROR_DEVA_I2C_COMM 0x00000002
+#define ERROR_DEVB_I2C_COMM 0x00000004
+#define ERROR_PRAM_CRCCHK 0x00000008
+#define ERROR_YRAM_CRCCHK 0x00000010
+#define ERROR_CLK_DET2 0x00000020
+#define ERROR_CLK_DET1 0x00000040
+#define ERROR_CLK_LOST 0x00000080
+#define ERROR_BROWNOUT 0x00000100
+#define ERROR_DIE_OVERTEMP 0x00000200
+#define ERROR_CLK_HALT 0x00000400
+#define ERROR_UNDER_VOLTAGE 0x00000800
+#define ERROR_OVER_CURRENT 0x00001000
+#define ERROR_CLASSD_PWR 0x00002000
+#define ERROR_SAFE_GUARD 0x00004000
+#define ERROR_FAILSAFE 0x40000000
+
+#define LOW_TEMPERATURE_GAIN 6
+#define LOW_TEMPERATURE_COUNTER 12
+
+#define RESTART_MAX 3
+
+#define TAS2559_UDELAY 0xFFFFFFFE
+#define TAS2559_MDELAY 0xFFFFFFFD
+
+#define FW_ERR_HEADER -1
+#define FW_ERR_SIZE -2
+
+#define TAS2559_BLOCK_PLL 0x00
+#define TAS2559_BLOCK_PGM_ALL 0x0d
+#define TAS2559_BLOCK_PGM_DEV_A 0x01
+#define TAS2559_BLOCK_PGM_DEV_B 0x08
+#define TAS2559_BLOCK_CFG_COEFF_DEV_A 0x03
+#define TAS2559_BLOCK_CFG_COEFF_DEV_B 0x0a
+#define TAS2559_BLOCK_CFG_PRE_DEV_A 0x04
+#define TAS2559_BLOCK_CFG_PRE_DEV_B 0x0b
+#define TAS2559_BLOCK_CFG_POST 0x05
+#define TAS2559_BLOCK_CFG_POST_POWER 0x06
+#define TAS2559_BLOCK_PST_POWERUP_DEV_B 0x0e
+
+#define PPC_DRIVER_CRCCHK 0x00000200
+#define PPC_DRIVER_CONFDEV 0x00000300
+#define PPC_DRIVER_MTPLLSRC 0x00000400
+#define PPC_DRIVER_CFGDEV_NONCRC 0x00000101
+
+#endif /* _TAS2559_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/config.h b/sound/soc/codecs/tfa98xx-downstream/config.h
new file mode 100644
index 00000000000..847608f0c41
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/config.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+
+/*
+ Linux kernel specific definitions used by code shared with
+ Linux/Windows user space.
+*/
+
+#ifndef __CONFIG_LINUX_KERNEL_INC__
+#define __CONFIG_LINUX_KERNEL_INC__
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/crc32.h>
+#include <linux/ftrace.h>
+
+#define _ASSERT(e)
+#define PRINT_ASSERT(e)if ((e)) printk(KERN_ERR "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+
+#if defined(CONFIG_TRACING) && defined(DEBUG)
+ #define tfa98xx_trace_printk(...) trace_printk(__VA_ARGS__)
+#else
+ #define tfa98xx_trace_printk(...)
+#endif
+
+#endif /* __CONFIG_LINUX_KERNEL_INC__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/dbgprint.h b/sound/soc/codecs/tfa98xx-downstream/dbgprint.h
new file mode 100644
index 00000000000..c0886fb2ff6
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/dbgprint.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#ifndef _DBGPRINT_H
+# define _DBGPRINT_H
+
+/* Debugging macro's. */
+# ifndef DEBUG
+# define DEBUG
+# endif
+
+# ifndef ASSERT
+//#define ASSERT
+# endif
+ //TODO wwwim
+# ifndef _ASSERT
+ #define _ASSERT(e)
+# endif
+
+# ifndef PREFIX
+# define PREFIX "tfa98xx: "
+# define DRIVER_NAME "tfa98xx"
+# endif
+
+#ifdef __KERNEL__
+
+# ifdef DEBUG
+# define _DEBUG(level,fmt,va...) do {\
+ if (unlikely(debug >= (level))) \
+ printk(KERN_INFO PREFIX "%s:%d: "fmt,__func__,__LINE__,##va); \
+ } while (0)
+
+# else
+# define _DEBUG(level,fmt,va...) do {} while(0)
+# endif
+
+# define MSG(fmt,va...) printk(KERN_INFO PREFIX "%s:%d: "fmt,__func__,__LINE__,##va)
+# define _ERRORMSG(fmt,va...) printk(KERN_ERR PREFIX "ERROR %s:%d: "fmt,__func__,__LINE__, ##va)
+
+
+# define DEBUG0(x...) MSG(x)
+# define DEBUG1(x...) _DEBUG(1,x)
+# define DEBUG2(x...) _DEBUG(2,x)
+# define DEBUG3(x...) _DEBUG(3,x)
+# define ERRORMSG(x...) _ERRORMSG(x)
+# define PRINT(x...) printk(x)
+# define PRINT_ERROR(x...) printk(KERN_INFO PREFIX " **ERROR** " x)
+# define PRINT_ASSERT(e)if ((e)) printk(KERN_ERR "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+
+# define PRINT_ENTRY DEBUG2("+[%s]\n", __func__)
+# define PRINT_EXIT DEBUG2("-[%s]\n", __func__)
+
+# ifdef ASSERT
+# define assert(cond,action) do { if (unlikely(!(cond))) { DEBUG0("Assert: %s\n",#cond); action; }} while(0)
+# else
+# define assert(cond,action) do { } while (0)
+# endif
+
+#else /* __KERNEL__ */
+#if defined(WIN32) || defined(_X64)
+#include <stdio.h>
+/* user mode */
+# ifdef DEBUG
+# define _DEBUGMSG(level,fmt,...) printf(PREFIX "%s:%d: "fmt,__FUNCTION__,__LINE__,__VA_ARGS__);
+# else
+# define _DEBUGMSG(level,fmt,...) do {} while(0)
+# endif
+
+# define _ERRORMSG(fmt,...) printf(PREFIX "%s:%s:%d: "fmt,__FILE__,__FUNCTION__,__LINE__,__VA_ARGS__)
+
+# define DEBUG0(...) MSG(__VA_ARGS__)
+# define DEBUG1(...) _DEBUGMSG(1,__VA_ARGS__)
+# define DEBUG2(...) _DEBUGMSG(2,__VA_ARGS__)
+# define DEBUG3(...) _DEBUGMSG(3,__VA_ARGS__)
+# define ERRORMSG(fmt,...) _ERRORMSG(fmt,__VA_ARGS__)
+# define PRINT(...) printf(__VA_ARGS__)
+/*
+# define PRINT(...) { FILE *stream; \
+ if((stream = freopen("tfa_tfa.txt", "ab+", stdout)) == NULL) exit(-1); \
+ printf(__VA_ARGS__); \
+ freopen( "CON", "ab+", stdout ); \
+ }
+*/
+# define PRINT_ERROR(...) fprintf(stderr,__VA_ARGS__)
+# define PRINT_FILE(file,...) fprintf(file,__VA_ARGS__)
+# define PRINT_ASSERT(e)if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+//# define PRINT_ASSERT(e) if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) %s\n",__FUNCTION__,__FILE__,__LINE__, Tfa98xx_GetErrorString(e))
+
+#elif defined(__CODE_RED)
+#include "app_global.h"
+# ifdef DEBUG
+# define _DEBUG(level,fmt,va...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,va))
+//printf(PREFIX "%s:%d: "fmt,__func__,__LINE__,##va);
+# else
+# define _DEBUG(level,fmt,va...) do {} while(0)
+# endif
+
+# define MSG(fmt,...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,__VA_ARGS__))
+//printf(PREFIX "%s:%s:%d: "fmt,__FILE__,__func__,__LINE__,##va)
+//TB_TRACE_INF(TbTracePfx2(APP_PFX,TB_FUNC,"path=%s, chan=%u, muted=%s, vol=%d\n",
+// path->isRecording ? "recording" : "playback",
+// i,
+// channelVol.currentMuteValue ? "YES" : "NO",
+// channelVol.currentVolumeValue
+// ));
+//# define _ERRORMSG(fmt,va...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,va))
+# define ERRORMSG(...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,__VA_ARGS__))
+//fprintf(stderr, PREFIX "ERROR %s:%s:%d: "fmt,__FILE__,__func__,__LINE__, ##va)
+
+# define DEBUG0(x...) MSG(x)
+# define DEBUG1(x...) _DEBUG(1,x)
+# define DEBUG2(x...) _DEBUG(2,x)
+# define DEBUG3(x...) _DEBUG(3,x)
+//# define ERRORMSG(x...) _ERRORMSG(x)
+# define PRINT(x...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,x))
+//printf(x)
+# define PRINT_ERROR(x...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,x))
+//fprintf(stderr,__VA_ARGS__)
+# define PRINT_FILE(file,x...) TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,x))
+//fprintf(file,__VA_ARGS__)
+# define PRINT_ASSERT(e)
+//TB_TRACE_INF(TbTracePfx2("tfa",TB_FUNC,Tfa98xx_GetErrorString(e)))
+//if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) %s\n",__FUNCTION__,__FILE__,__LINE__, Tfa98xx_GetErrorString(e))
+#else
+#include <stdio.h>
+/* user mode */
+# ifdef DEBUG
+# define _DEBUG(level,fmt,va...) printf(PREFIX "%s:%d: "fmt,__func__,__LINE__,##va);
+# else
+# define _DEBUG(level,fmt,va...) do {} while(0)
+# endif
+
+# define MSG(fmt,va...) printf(PREFIX "%s:%s:%d: "fmt,__FILE__,__func__,__LINE__,##va)
+# define _ERRORMSG(fmt,va...) fprintf(stderr, PREFIX "ERROR %s:%s:%d: "fmt,__FILE__,__func__,__LINE__, ##va)
+
+# define DEBUG0(x...) MSG(x)
+# define DEBUG1(x...) _DEBUG(1,x)
+# define DEBUG2(x...) _DEBUG(2,x)
+# define DEBUG3(x...) _DEBUG(3,x)
+# define ERRORMSG(x...) _ERRORMSG(x)
+# define PRINT(x...) printf(x)
+# define PRINT_ERROR(...) fprintf(stderr,__VA_ARGS__)
+# define PRINT_FILE(file,...) fprintf(file,__VA_ARGS__)
+# define PRINT_ASSERT(e)if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) error code:%d\n",__FUNCTION__,__FILE__,__LINE__, e)
+//# define PRINT_ASSERT(e) if ((e)) fprintf(stderr, "PrintAssert:%s (%s:%d) %s\n",__FUNCTION__,__FILE__,__LINE__, Tfa98xx_GetErrorString(e))
+
+
+#endif /* WIN32 */
+
+#endif /* user */
+
+#endif /* _DBGPRINT_H --------------- */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa.h b/sound/soc/codecs/tfa98xx-downstream/tfa.h
new file mode 100644
index 00000000000..71faf323562
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#ifndef TFA_H_
+#define TFA_H_
+
+/* set the limit for the container file length */
+#define TFA_MAX_CNT_LENGTH (256*1024)
+
+extern struct tfa_device **devs;
+
+/**
+ * tfa error return codes
+ */
+enum tfa_error {
+ tfa_error_ok, /**< no error */
+ tfa_error_device, /**< no response from device */
+ tfa_error_bad_param,/**< parameter no accepted */
+ tfa_error_noclock, /**< required clock not present */
+ tfa_error_timeout, /**< a timeout occurred */
+ tfa_error_dsp, /**< a DSP error was returned */
+ tfa_error_container,/**< no or wrong container file */
+ tfa_error_max /**< impossible value, max enum */
+};
+
+enum Tfa98xx_Error tfa_write_filters(struct tfa_device *tfa, int prof_idx);
+
+struct tfa_device ** tfa_devs_create(int count);
+void tfa_devs_destroy(int count);
+
+struct tfa_device ** tfa_get_device_struct(void);
+
+int tfa_plop_noise_interrupt(struct tfa_device *tfa, int profile, int vstep);
+void tfa_lp_mode_interrupt(struct tfa_device *tfa);
+void tfa_adapt_noisemode(struct tfa_device *tfa);
+
+#endif /* TFA_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa1_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa1_tfafieldnames.h
new file mode 100644
index 00000000000..400716de139
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa1_tfafieldnames.h
@@ -0,0 +1,911 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa1_TfaFieldnames.h
+ * This file was generated automatically on 03/20/2015 at 01:55:46 PM.
+ * Source file: TFA9897N1B_I2C_list_URT_Source_v34.xls
+ */
+#define TFA9897_I2CVERSION 34
+typedef enum Tfa1BfEnumList {
+ TFA1_BF_VDDS = 0x0000, /*!< Power-on-reset flag */
+ TFA1_BF_PLLS = 0x0010, /*!< PLL lock */
+ TFA1_BF_OTDS = 0x0020, /*!< Over Temperature Protection alarm */
+ TFA1_BF_OVDS = 0x0030, /*!< Over Voltage Protection alarm */
+ TFA1_BF_UVDS = 0x0040, /*!< Under Voltage Protection alarm */
+ TFA1_BF_OCDS = 0x0050, /*!< Over Current Protection alarm */
+ TFA1_BF_CLKS = 0x0060, /*!< Clocks stable flag */
+ TFA1_BF_CLIPS = 0x0070, /*!< Amplifier clipping */
+ TFA1_BF_MTPB = 0x0080, /*!< MTP busy */
+ TFA1_BF_NOCLK = 0x0090, /*!< Flag lost clock from clock generation unit */
+ TFA1_BF_SPKS = 0x00a0, /*!< Speaker error flag */
+ TFA1_BF_ACS = 0x00b0, /*!< Cold Start flag */
+ TFA1_BF_SWS = 0x00c0, /*!< Flag Engage */
+ TFA1_BF_WDS = 0x00d0, /*!< Flag watchdog reset */
+ TFA1_BF_AMPS = 0x00e0, /*!< Amplifier is enabled by manager */
+ TFA1_BF_AREFS = 0x00f0, /*!< References are enabled by manager */
+ TFA1_BF_BATS = 0x0109, /*!< Battery voltage readout; 0 .. 5.5 [V] */
+ TFA1_BF_TEMPS = 0x0208, /*!< Temperature readout from the temperature sensor */
+ TFA1_BF_REV = 0x030b, /*!< Device type number is B97 */
+ TFA1_BF_RCV = 0x0420, /*!< Enable Receiver Mode */
+ TFA1_BF_CHS12 = 0x0431, /*!< Channel Selection TDM input for Coolflux */
+ TFA1_BF_INPLVL= 0x0450, /*!< Input level selection control */
+ TFA1_BF_CHSA = 0x0461, /*!< Input selection for amplifier */
+ TFA1_BF_I2SDOE= 0x04b0, /*!< Enable data output */
+ TFA1_BF_AUDFS = 0x04c3, /*!< Audio sample rate setting */
+ TFA1_BF_BSSCR = 0x0501, /*!< Protection Attack Time */
+ TFA1_BF_BSST = 0x0523, /*!< ProtectionThreshold */
+ TFA1_BF_BSSRL = 0x0561, /*!< Protection Maximum Reduction */
+ TFA1_BF_BSSRR = 0x0582, /*!< Battery Protection Release Time */
+ TFA1_BF_BSSHY = 0x05b1, /*!< Battery Protection Hysteresis */
+ TFA1_BF_BSSR = 0x05e0, /*!< battery voltage for I2C read out only */
+ TFA1_BF_BSSBY = 0x05f0, /*!< bypass clipper battery protection */
+ TFA1_BF_DPSA = 0x0600, /*!< Enable dynamic powerstage activation */
+ TFA1_BF_CFSM = 0x0650, /*!< Soft mute in CoolFlux */
+ TFA1_BF_BSSS = 0x0670, /*!< BatSenseSteepness */
+ TFA1_BF_VOL = 0x0687, /*!< volume control (in CoolFlux) */
+ TFA1_BF_DCVO = 0x0702, /*!< Boost Voltage */
+ TFA1_BF_DCMCC = 0x0733, /*!< Max boost coil current - step of 175 mA */
+ TFA1_BF_DCIE = 0x07a0, /*!< Adaptive boost mode */
+ TFA1_BF_DCSR = 0x07b0, /*!< Soft RampUp/Down mode for DCDC controller */
+ TFA1_BF_DCPAVG= 0x07c0, /*!< ctrl_peak2avg for analog part of DCDC */
+ TFA1_BF_TROS = 0x0800, /*!< Select external temperature also the ext_temp will be put on the temp read out */
+ TFA1_BF_EXTTS = 0x0818, /*!< external temperature setting to be given by host */
+ TFA1_BF_PWDN = 0x0900, /*!< Device Mode */
+ TFA1_BF_I2CR = 0x0910, /*!< I2C Reset */
+ TFA1_BF_CFE = 0x0920, /*!< Enable CoolFlux */
+ TFA1_BF_AMPE = 0x0930, /*!< Enable Amplifier */
+ TFA1_BF_DCA = 0x0940, /*!< EnableBoost */
+ TFA1_BF_SBSL = 0x0950, /*!< Coolflux configured */
+ TFA1_BF_AMPC = 0x0960, /*!< Selection on how Amplifier is enabled */
+ TFA1_BF_DCDIS = 0x0970, /*!< DCDC not connected */
+ TFA1_BF_PSDR = 0x0980, /*!< IDDQ test amplifier */
+ TFA1_BF_DCCV = 0x0991, /*!< Coil Value */
+ TFA1_BF_CCFD = 0x09b0, /*!< Selection CoolFlux Clock */
+ TFA1_BF_INTPAD= 0x09c1, /*!< INT pad configuration control */
+ TFA1_BF_IPLL = 0x09e0, /*!< PLL input reference clock selection */
+ TFA1_BF_MTPK = 0x0b07, /*!< 5Ah, 90d To access KEY1_Protected registers (Default for engineering) */
+ TFA1_BF_CVFDLY= 0x0c25, /*!< Fractional delay adjustment between current and voltage sense */
+ TFA1_BF_TDMPRF= 0x1011, /*!< TDM_usecase */
+ TFA1_BF_TDMEN = 0x1030, /*!< TDM interface control */
+ TFA1_BF_TDMCKINV= 0x1040, /*!< TDM clock inversion */
+ TFA1_BF_TDMFSLN= 0x1053, /*!< TDM FS length */
+ TFA1_BF_TDMFSPOL= 0x1090, /*!< TDM FS polarity */
+ TFA1_BF_TDMSAMSZ= 0x10a4, /*!< TDM Sample Size for all tdm sinks/sources */
+ TFA1_BF_TDMSLOTS= 0x1103, /*!< Number of slots */
+ TFA1_BF_TDMSLLN= 0x1144, /*!< Slot length */
+ TFA1_BF_TDMBRMG= 0x1194, /*!< Bits remaining */
+ TFA1_BF_TDMDDEL= 0x11e0, /*!< Data delay */
+ TFA1_BF_TDMDADJ= 0x11f0, /*!< Data adjustment */
+ TFA1_BF_TDMTXFRM= 0x1201, /*!< TXDATA format */
+ TFA1_BF_TDMUUS0= 0x1221, /*!< TXDATA format unused slot sd0 */
+ TFA1_BF_TDMUUS1= 0x1241, /*!< TXDATA format unused slot sd1 */
+ TFA1_BF_TDMSI0EN= 0x1270, /*!< TDM sink0 enable */
+ TFA1_BF_TDMSI1EN= 0x1280, /*!< TDM sink1 enable */
+ TFA1_BF_TDMSI2EN= 0x1290, /*!< TDM sink2 enable */
+ TFA1_BF_TDMSO0EN= 0x12a0, /*!< TDM source0 enable */
+ TFA1_BF_TDMSO1EN= 0x12b0, /*!< TDM source1 enable */
+ TFA1_BF_TDMSO2EN= 0x12c0, /*!< TDM source2 enable */
+ TFA1_BF_TDMSI0IO= 0x12d0, /*!< tdm_sink0_io */
+ TFA1_BF_TDMSI1IO= 0x12e0, /*!< tdm_sink1_io */
+ TFA1_BF_TDMSI2IO= 0x12f0, /*!< tdm_sink2_io */
+ TFA1_BF_TDMSO0IO= 0x1300, /*!< tdm_source0_io */
+ TFA1_BF_TDMSO1IO= 0x1310, /*!< tdm_source1_io */
+ TFA1_BF_TDMSO2IO= 0x1320, /*!< tdm_source2_io */
+ TFA1_BF_TDMSI0SL= 0x1333, /*!< sink0_slot [GAIN IN] */
+ TFA1_BF_TDMSI1SL= 0x1373, /*!< sink1_slot [CH1 IN] */
+ TFA1_BF_TDMSI2SL= 0x13b3, /*!< sink2_slot [CH2 IN] */
+ TFA1_BF_TDMSO0SL= 0x1403, /*!< source0_slot [GAIN OUT] */
+ TFA1_BF_TDMSO1SL= 0x1443, /*!< source1_slot [Voltage Sense] */
+ TFA1_BF_TDMSO2SL= 0x1483, /*!< source2_slot [Current Sense] */
+ TFA1_BF_NBCK = 0x14c3, /*!< NBCK */
+ TFA1_BF_INTOVDDS= 0x2000, /*!< flag_por_int_out */
+ TFA1_BF_INTOPLLS= 0x2010, /*!< flag_pll_lock_int_out */
+ TFA1_BF_INTOOTDS= 0x2020, /*!< flag_otpok_int_out */
+ TFA1_BF_INTOOVDS= 0x2030, /*!< flag_ovpok_int_out */
+ TFA1_BF_INTOUVDS= 0x2040, /*!< flag_uvpok_int_out */
+ TFA1_BF_INTOOCDS= 0x2050, /*!< flag_ocp_alarm_int_out */
+ TFA1_BF_INTOCLKS= 0x2060, /*!< flag_clocks_stable_int_out */
+ TFA1_BF_INTOCLIPS= 0x2070, /*!< flag_clip_int_out */
+ TFA1_BF_INTOMTPB= 0x2080, /*!< mtp_busy_int_out */
+ TFA1_BF_INTONOCLK= 0x2090, /*!< flag_lost_clk_int_out */
+ TFA1_BF_INTOSPKS= 0x20a0, /*!< flag_cf_speakererror_int_out */
+ TFA1_BF_INTOACS= 0x20b0, /*!< flag_cold_started_int_out */
+ TFA1_BF_INTOSWS= 0x20c0, /*!< flag_engage_int_out */
+ TFA1_BF_INTOWDS= 0x20d0, /*!< flag_watchdog_reset_int_out */
+ TFA1_BF_INTOAMPS= 0x20e0, /*!< flag_enbl_amp_int_out */
+ TFA1_BF_INTOAREFS= 0x20f0, /*!< flag_enbl_ref_int_out */
+ TFA1_BF_INTOACK= 0x2201, /*!< Interrupt status register output - Corresponding flag */
+ TFA1_BF_INTIVDDS= 0x2300, /*!< flag_por_int_in */
+ TFA1_BF_INTIPLLS= 0x2310, /*!< flag_pll_lock_int_in */
+ TFA1_BF_INTIOTDS= 0x2320, /*!< flag_otpok_int_in */
+ TFA1_BF_INTIOVDS= 0x2330, /*!< flag_ovpok_int_in */
+ TFA1_BF_INTIUVDS= 0x2340, /*!< flag_uvpok_int_in */
+ TFA1_BF_INTIOCDS= 0x2350, /*!< flag_ocp_alarm_int_in */
+ TFA1_BF_INTICLKS= 0x2360, /*!< flag_clocks_stable_int_in */
+ TFA1_BF_INTICLIPS= 0x2370, /*!< flag_clip_int_in */
+ TFA1_BF_INTIMTPB= 0x2380, /*!< mtp_busy_int_in */
+ TFA1_BF_INTINOCLK= 0x2390, /*!< flag_lost_clk_int_in */
+ TFA1_BF_INTISPKS= 0x23a0, /*!< flag_cf_speakererror_int_in */
+ TFA1_BF_INTIACS= 0x23b0, /*!< flag_cold_started_int_in */
+ TFA1_BF_INTISWS= 0x23c0, /*!< flag_engage_int_in */
+ TFA1_BF_INTIWDS= 0x23d0, /*!< flag_watchdog_reset_int_in */
+ TFA1_BF_INTIAMPS= 0x23e0, /*!< flag_enbl_amp_int_in */
+ TFA1_BF_INTIAREFS= 0x23f0, /*!< flag_enbl_ref_int_in */
+ TFA1_BF_INTIACK= 0x2501, /*!< Interrupt register input */
+ TFA1_BF_INTENVDDS= 0x2600, /*!< flag_por_int_enable */
+ TFA1_BF_INTENPLLS= 0x2610, /*!< flag_pll_lock_int_enable */
+ TFA1_BF_INTENOTDS= 0x2620, /*!< flag_otpok_int_enable */
+ TFA1_BF_INTENOVDS= 0x2630, /*!< flag_ovpok_int_enable */
+ TFA1_BF_INTENUVDS= 0x2640, /*!< flag_uvpok_int_enable */
+ TFA1_BF_INTENOCDS= 0x2650, /*!< flag_ocp_alarm_int_enable */
+ TFA1_BF_INTENCLKS= 0x2660, /*!< flag_clocks_stable_int_enable */
+ TFA1_BF_INTENCLIPS= 0x2670, /*!< flag_clip_int_enable */
+ TFA1_BF_INTENMTPB= 0x2680, /*!< mtp_busy_int_enable */
+ TFA1_BF_INTENNOCLK= 0x2690, /*!< flag_lost_clk_int_enable */
+ TFA1_BF_INTENSPKS= 0x26a0, /*!< flag_cf_speakererror_int_enable */
+ TFA1_BF_INTENACS= 0x26b0, /*!< flag_cold_started_int_enable */
+ TFA1_BF_INTENSWS= 0x26c0, /*!< flag_engage_int_enable */
+ TFA1_BF_INTENWDS= 0x26d0, /*!< flag_watchdog_reset_int_enable */
+ TFA1_BF_INTENAMPS= 0x26e0, /*!< flag_enbl_amp_int_enable */
+ TFA1_BF_INTENAREFS= 0x26f0, /*!< flag_enbl_ref_int_enable */
+ TFA1_BF_INTENACK= 0x2801, /*!< Interrupt enable register */
+ TFA1_BF_INTPOLVDDS= 0x2900, /*!< flag_por_int_pol */
+ TFA1_BF_INTPOLPLLS= 0x2910, /*!< flag_pll_lock_int_pol */
+ TFA1_BF_INTPOLOTDS= 0x2920, /*!< flag_otpok_int_pol */
+ TFA1_BF_INTPOLOVDS= 0x2930, /*!< flag_ovpok_int_pol */
+ TFA1_BF_INTPOLUVDS= 0x2940, /*!< flag_uvpok_int_pol */
+ TFA1_BF_INTPOLOCDS= 0x2950, /*!< flag_ocp_alarm_int_pol */
+ TFA1_BF_INTPOLCLKS= 0x2960, /*!< flag_clocks_stable_int_pol */
+ TFA1_BF_INTPOLCLIPS= 0x2970, /*!< flag_clip_int_pol */
+ TFA1_BF_INTPOLMTPB= 0x2980, /*!< mtp_busy_int_pol */
+ TFA1_BF_INTPOLNOCLK= 0x2990, /*!< flag_lost_clk_int_pol */
+ TFA1_BF_INTPOLSPKS= 0x29a0, /*!< flag_cf_speakererror_int_pol */
+ TFA1_BF_INTPOLACS= 0x29b0, /*!< flag_cold_started_int_pol */
+ TFA1_BF_INTPOLSWS= 0x29c0, /*!< flag_engage_int_pol */
+ TFA1_BF_INTPOLWDS= 0x29d0, /*!< flag_watchdog_reset_int_pol */
+ TFA1_BF_INTPOLAMPS= 0x29e0, /*!< flag_enbl_amp_int_pol */
+ TFA1_BF_INTPOLAREFS= 0x29f0, /*!< flag_enbl_ref_int_pol */
+ TFA1_BF_INTPOLACK= 0x2b01, /*!< Interrupt status flags polarity register */
+ TFA1_BF_CLIP = 0x4900, /*!< Bypass clip control */
+ TFA1_BF_CIMTP = 0x62b0, /*!< start copying all the data from i2cregs_mtp to mtp [Key 2 protected] */
+ TFA1_BF_RST = 0x7000, /*!< Reset CoolFlux DSP */
+ TFA1_BF_DMEM = 0x7011, /*!< Target memory for access */
+ TFA1_BF_AIF = 0x7030, /*!< Autoincrement-flag for memory-address */
+ TFA1_BF_CFINT = 0x7040, /*!< Interrupt CoolFlux DSP */
+ TFA1_BF_REQ = 0x7087, /*!< request for access (8 channels) */
+ TFA1_BF_REQCMD= 0x7080, /*!< Firmware event request rpc command */
+ TFA1_BF_REQRST= 0x7090, /*!< Firmware event request reset restart */
+ TFA1_BF_REQMIPS= 0x70a0, /*!< Firmware event request short on mips */
+ TFA1_BF_REQMUTED= 0x70b0, /*!< Firmware event request mute sequence ready */
+ TFA1_BF_REQVOL= 0x70c0, /*!< Firmware event request volume ready */
+ TFA1_BF_REQDMG= 0x70d0, /*!< Firmware event request speaker damage detected */
+ TFA1_BF_REQCAL= 0x70e0, /*!< Firmware event request calibration completed */
+ TFA1_BF_REQRSV= 0x70f0, /*!< Firmware event request reserved */
+ TFA1_BF_MADD = 0x710f, /*!< memory-address to be accessed */
+ TFA1_BF_MEMA = 0x720f, /*!< activate memory access (24- or 32-bits data is written/read to/from memory */
+ TFA1_BF_ERR = 0x7307, /*!< Coolflux error flags */
+ TFA1_BF_ACK = 0x7387, /*!< acknowledge of requests (8 channels) */
+ TFA1_BF_MTPOTC= 0x8000, /*!< Calibration schedule (key2 protected) */
+ TFA1_BF_MTPEX = 0x8010, /*!< (key2 protected) */
+} Tfa1BfEnumList_t;
+#define TFA1_NAMETABLE static tfaBfName_t Tfa1DatasheetNames[]= {\
+ { 0x0, "VDDS"}, /* Power-on-reset flag , */\
+ { 0x10, "PLLS"}, /* PLL lock , */\
+ { 0x20, "OTDS"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "OVDS"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "UVDS"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "OCDS"}, /* Over Current Protection alarm , */\
+ { 0x60, "CLKS"}, /* Clocks stable flag , */\
+ { 0x70, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x80, "MTPB"}, /* MTP busy , */\
+ { 0x90, "NOCLK"}, /* Flag lost clock from clock generation unit , */\
+ { 0xa0, "SPKS"}, /* Speaker error flag , */\
+ { 0xb0, "ACS"}, /* Cold Start flag , */\
+ { 0xc0, "SWS"}, /* Flag Engage , */\
+ { 0xd0, "WDS"}, /* Flag watchdog reset , */\
+ { 0xe0, "AMPS"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "AREFS"}, /* References are enabled by manager , */\
+ { 0x109, "BATS"}, /* Battery voltage readout; 0 .. 5.5 [V] , */\
+ { 0x208, "TEMPS"}, /* Temperature readout from the temperature sensor , */\
+ { 0x30b, "REV"}, /* Device type number is B97 , */\
+ { 0x420, "RCV"}, /* Enable Receiver Mode , */\
+ { 0x431, "CHS12"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "INPLVL"}, /* Input level selection control , */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "AUDFS"}, /* Audio sample rate setting , */\
+ { 0x501, "SSCR"}, /* Protection Attack Time , */\
+ { 0x523, "SST"}, /* ProtectionThreshold , */\
+ { 0x561, "SSRL"}, /* Protection Maximum Reduction , */\
+ { 0x582, "SSRR"}, /* Battery Protection Release Time , */\
+ { 0x5b1, "SSHY"}, /* Battery Protection Hysteresis , */\
+ { 0x5e0, "SSR"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "SSBY"}, /* bypass clipper battery protection , */\
+ { 0x600, "DPSA"}, /* Enable dynamic powerstage activation , */\
+ { 0x650, "CFSM"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "SSS"}, /* BatSenseSteepness , */\
+ { 0x687, "VOL"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "DCVO"}, /* Boost Voltage , */\
+ { 0x733, "DCMCC"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x7a0, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7b0, "DCSR"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x7c0, "DCPAVG"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x800, "TROS"}, /* Select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "EXTTS"}, /* external temperature setting to be given by host , */\
+ { 0x900, "PWDN"}, /* Device Mode , */\
+ { 0x910, "I2CR"}, /* I2C Reset , */\
+ { 0x920, "CFE"}, /* Enable CoolFlux , */\
+ { 0x930, "AMPE"}, /* Enable Amplifier , */\
+ { 0x940, "DCA"}, /* EnableBoost , */\
+ { 0x950, "SBSL"}, /* Coolflux configured , */\
+ { 0x960, "AMPC"}, /* Selection on how Amplifier is enabled , */\
+ { 0x970, "DCDIS"}, /* DCDC not connected , */\
+ { 0x980, "PSDR"}, /* IDDQ test amplifier , */\
+ { 0x991, "DCCV"}, /* Coil Value , */\
+ { 0x9b0, "CCFD"}, /* Selection CoolFlux Clock , */\
+ { 0x9c1, "INTPAD"}, /* INT pad configuration control , */\
+ { 0x9e0, "IPLL"}, /* PLL input reference clock selection , */\
+ { 0xb07, "MTPK"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xc25, "CVFDLY"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0x1011, "TDMPRF"}, /* TDM_usecase , */\
+ { 0x1030, "TDMEN"}, /* TDM interface control , */\
+ { 0x1040, "TDMCKINV"}, /* TDM clock inversion , */\
+ { 0x1053, "TDMFSLN"}, /* TDM FS length , */\
+ { 0x1090, "TDMFSPOL"}, /* TDM FS polarity , */\
+ { 0x10a4, "TDMSAMSZ"}, /* TDM Sample Size for all tdm sinks/sources , */\
+ { 0x1103, "TDMSLOTS"}, /* Number of slots , */\
+ { 0x1144, "TDMSLLN"}, /* Slot length , */\
+ { 0x1194, "TDMBRMG"}, /* Bits remaining , */\
+ { 0x11e0, "TDMDDEL"}, /* Data delay , */\
+ { 0x11f0, "TDMDADJ"}, /* Data adjustment , */\
+ { 0x1201, "TDMTXFRM"}, /* TXDATA format , */\
+ { 0x1221, "TDMUUS0"}, /* TXDATA format unused slot sd0 , */\
+ { 0x1241, "TDMUUS1"}, /* TXDATA format unused slot sd1 , */\
+ { 0x1270, "TDMSI0EN"}, /* TDM sink0 enable , */\
+ { 0x1280, "TDMSI1EN"}, /* TDM sink1 enable , */\
+ { 0x1290, "TDMSI2EN"}, /* TDM sink2 enable , */\
+ { 0x12a0, "TDMSO0EN"}, /* TDM source0 enable , */\
+ { 0x12b0, "TDMSO1EN"}, /* TDM source1 enable , */\
+ { 0x12c0, "TDMSO2EN"}, /* TDM source2 enable , */\
+ { 0x12d0, "TDMSI0IO"}, /* tdm_sink0_io , */\
+ { 0x12e0, "TDMSI1IO"}, /* tdm_sink1_io , */\
+ { 0x12f0, "TDMSI2IO"}, /* tdm_sink2_io , */\
+ { 0x1300, "TDMSO0IO"}, /* tdm_source0_io , */\
+ { 0x1310, "TDMSO1IO"}, /* tdm_source1_io , */\
+ { 0x1320, "TDMSO2IO"}, /* tdm_source2_io , */\
+ { 0x1333, "TDMSI0SL"}, /* sink0_slot [GAIN IN] , */\
+ { 0x1373, "TDMSI1SL"}, /* sink1_slot [CH1 IN] , */\
+ { 0x13b3, "TDMSI2SL"}, /* sink2_slot [CH2 IN] , */\
+ { 0x1403, "TDMSO0SL"}, /* source0_slot [GAIN OUT] , */\
+ { 0x1443, "TDMSO1SL"}, /* source1_slot [Voltage Sense] , */\
+ { 0x1483, "TDMSO2SL"}, /* source2_slot [Current Sense] , */\
+ { 0x14c3, "NBCK"}, /* NBCK , */\
+ { 0x2000, "INTOVDDS"}, /* flag_por_int_out , */\
+ { 0x2010, "INTOPLLS"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "INTOOTDS"}, /* flag_otpok_int_out , */\
+ { 0x2030, "INTOOVDS"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "INTOUVDS"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "INTOOCDS"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "INTOCLKS"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "INTOCLIPS"}, /* flag_clip_int_out , */\
+ { 0x2080, "INTOMTPB"}, /* mtp_busy_int_out , */\
+ { 0x2090, "INTONOCLK"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "INTOSPKS"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "INTOACS"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "INTOSWS"}, /* flag_engage_int_out , */\
+ { 0x20d0, "INTOWDS"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "INTOAMPS"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "INTOAREFS"}, /* flag_enbl_ref_int_out , */\
+ { 0x2201, "INTOACK"}, /* Interrupt status register output - Corresponding flag, */\
+ { 0x2300, "INTIVDDS"}, /* flag_por_int_in , */\
+ { 0x2310, "INTIPLLS"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "INTIOTDS"}, /* flag_otpok_int_in , */\
+ { 0x2330, "INTIOVDS"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "INTIUVDS"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "INTIOCDS"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "INTICLKS"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "INTICLIPS"}, /* flag_clip_int_in , */\
+ { 0x2380, "INTIMTPB"}, /* mtp_busy_int_in , */\
+ { 0x2390, "INTINOCLK"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "INTISPKS"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "INTIACS"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "INTISWS"}, /* flag_engage_int_in , */\
+ { 0x23d0, "INTIWDS"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "INTIAMPS"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "INTIAREFS"}, /* flag_enbl_ref_int_in , */\
+ { 0x2501, "INTIACK"}, /* Interrupt register input , */\
+ { 0x2600, "INTENVDDS"}, /* flag_por_int_enable , */\
+ { 0x2610, "INTENPLLS"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "INTENOTDS"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "INTENOVDS"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "INTENUVDS"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "INTENOCDS"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "INTENCLKS"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "INTENCLIPS"}, /* flag_clip_int_enable , */\
+ { 0x2680, "INTENMTPB"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "INTENNOCLK"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "INTENSPKS"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "INTENACS"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "INTENSWS"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "INTENWDS"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "INTENAMPS"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "INTENAREFS"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2801, "INTENACK"}, /* Interrupt enable register , */\
+ { 0x2900, "INTPOLVDDS"}, /* flag_por_int_pol , */\
+ { 0x2910, "INTPOLPLLS"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "INTPOLOTDS"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "INTPOLOVDS"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "INTPOLUVDS"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "INTPOLOCDS"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "INTPOLCLKS"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "INTPOLCLIPS"}, /* flag_clip_int_pol , */\
+ { 0x2980, "INTPOLMTPB"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "INTPOLNOCLK"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "INTPOLSPKS"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "INTPOLACS"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "INTPOLSWS"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "INTPOLWDS"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "INTPOLAMPS"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "INTPOLAREFS"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2b01, "INTPOLACK"}, /* Interrupt status flags polarity register , */\
+ { 0x4900, "CLIP"}, /* Bypass clip control , */\
+ { 0x62b0, "CIMTP"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x7000, "RST"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "DMEM"}, /* Target memory for access , */\
+ { 0x7030, "AIF"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "CFINT"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "REQ"}, /* request for access (8 channels) , */\
+ { 0x7080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x7090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x70a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x70b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x70c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x70d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x70e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x70f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x710f, "MADD"}, /* memory-address to be accessed , */\
+ { 0x720f, "MEMA"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "ERR"}, /* Coolflux error flags , */\
+ { 0x7387, "ACK"}, /* acknowledge of requests (8 channels) , */\
+ { 0x7380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x7390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x73a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x73b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x73c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x73d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x73e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x73f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0x8000, "MTPOTC"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "MTPEX"}, /* (key2 protected) , */\
+ { 0x8045, "SWPROFIL" },\
+ { 0x80a5, "SWVSTEP" },\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA1_BITNAMETABLE static tfaBfName_t Tfa1BitNames[]= {\
+ { 0x0, "flag_por"}, /* Power-on-reset flag , */\
+ { 0x10, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x20, "flag_otpok"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "flag_ovpok"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "flag_uvpok"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "flag_ocp_alarm"}, /* Over Current Protection alarm , */\
+ { 0x60, "flag_clocks_stable"}, /* Clocks stable flag , */\
+ { 0x70, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x80, "mtp_busy"}, /* MTP busy , */\
+ { 0x90, "flag_lost_clk"}, /* Flag lost clock from clock generation unit , */\
+ { 0xa0, "flag_cf_speakererror"}, /* Speaker error flag , */\
+ { 0xb0, "flag_cold_started"}, /* Cold Start flag , */\
+ { 0xc0, "flag_engage"}, /* Flag Engage , */\
+ { 0xd0, "flag_watchdog_reset"}, /* Flag watchdog reset , */\
+ { 0xe0, "flag_enbl_amp"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "flag_enbl_ref"}, /* References are enabled by manager , */\
+ { 0x109, "bat_adc"}, /* Battery voltage readout; 0 .. 5.5 [V] , */\
+ { 0x208, "temp_adc"}, /* Temperature readout from the temperature sensor , */\
+ { 0x30b, "rev_reg"}, /* Device type number is B97 , */\
+ { 0x420, "ctrl_rcv"}, /* Enable Receiver Mode , */\
+ { 0x431, "chan_sel"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "input_level"}, /* Input level selection control , */\
+ { 0x461, "vamp_sel"}, /* Input selection for amplifier , */\
+ { 0x4c3, "audio_fs"}, /* Audio sample rate setting , */\
+ { 0x501, "vbat_prot_attacktime"}, /* Protection Attack Time , */\
+ { 0x523, "vbat_prot_thlevel"}, /* ProtectionThreshold , */\
+ { 0x561, "vbat_prot_max_reduct"}, /* Protection Maximum Reduction , */\
+ { 0x582, "vbat_prot_release_t"}, /* Battery Protection Release Time , */\
+ { 0x5b1, "vbat_prot_hysterese"}, /* Battery Protection Hysteresis , */\
+ { 0x5d0, "reset_min_vbat"}, /* reset clipper , */\
+ { 0x5e0, "sel_vbat"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "bypass_clipper"}, /* bypass clipper battery protection , */\
+ { 0x600, "dpsa"}, /* Enable dynamic powerstage activation , */\
+ { 0x650, "cf_mute"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "batsense_steepness"}, /* BatSenseSteepness , */\
+ { 0x687, "vol"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "boost_volt"}, /* Boost Voltage , */\
+ { 0x733, "boost_cur"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x7a0, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7b0, "boost_speed"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x7c0, "boost_peak2avg"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x800, "ext_temp_sel"}, /* Select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "ext_temp"}, /* external temperature setting to be given by host , */\
+ { 0x8b2, "dcdc_synchronisation"}, /* DCDC synchronisation off + 7 positions , */\
+ { 0x900, "powerdown"}, /* Device Mode , */\
+ { 0x910, "reset"}, /* I2C Reset , */\
+ { 0x920, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x930, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x940, "enbl_boost"}, /* EnableBoost , */\
+ { 0x950, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x960, "sel_enbl_amplifier"}, /* Selection on how Amplifier is enabled , */\
+ { 0x970, "dcdcoff_mode"}, /* DCDC not connected , */\
+ { 0x980, "iddqtest"}, /* IDDQ test amplifier , */\
+ { 0x991, "coil_value"}, /* Coil Value , */\
+ { 0x9b0, "sel_cf_clock"}, /* Selection CoolFlux Clock , */\
+ { 0x9c1, "int_pad_io"}, /* INT pad configuration control , */\
+ { 0x9e0, "sel_fs_bck"}, /* PLL input reference clock selection , */\
+ { 0x9f0, "sel_scl_cf_clock"}, /* Coolflux sub-system clock , */\
+ { 0xb07, "mtpkey2"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xc00, "enbl_volt_sense"}, /* Voltage sense enabling control bit , */\
+ { 0xc10, "vsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0xc25, "vi_frac_delay"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0xc80, "sel_voltsense_out"}, /* TDM output data selection control , */\
+ { 0xc90, "vsense_bypass_avg"}, /* Voltage Sense Average Block Bypass , */\
+ { 0xd05, "cf_frac_delay"}, /* Fractional delay adjustment between current and voltage sense by firmware, */\
+ { 0xe00, "bypass_dcdc_curr_prot"}, /* Control to switch off dcdc current reduction with bat protection, */\
+ { 0xe80, "disable_clock_sh_prot"}, /* disable clock_sh protection , */\
+ { 0xe96, "reserve_reg_1_15_9"}, /* , */\
+ { 0x1011, "tdm_usecase"}, /* TDM_usecase , */\
+ { 0x1030, "tdm_enable"}, /* TDM interface control , */\
+ { 0x1040, "tdm_clk_inversion"}, /* TDM clock inversion , */\
+ { 0x1053, "tdm_fs_ws_length"}, /* TDM FS length , */\
+ { 0x1090, "tdm_fs_ws_polarity"}, /* TDM FS polarity , */\
+ { 0x10a4, "tdm_sample_size"}, /* TDM Sample Size for all tdm sinks/sources , */\
+ { 0x1103, "tdm_nb_of_slots"}, /* Number of slots , */\
+ { 0x1144, "tdm_slot_length"}, /* Slot length , */\
+ { 0x1194, "tdm_bits_remaining"}, /* Bits remaining , */\
+ { 0x11e0, "tdm_data_delay"}, /* Data delay , */\
+ { 0x11f0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x1201, "tdm_txdata_format"}, /* TXDATA format , */\
+ { 0x1221, "tdm_txdata_format_unused_slot_sd0"}, /* TXDATA format unused slot sd0 , */\
+ { 0x1241, "tdm_txdata_format_unused_slot_sd1"}, /* TXDATA format unused slot sd1 , */\
+ { 0x1270, "tdm_sink0_enable"}, /* TDM sink0 enable , */\
+ { 0x1280, "tdm_sink1_enable"}, /* TDM sink1 enable , */\
+ { 0x1290, "tdm_sink2_enable"}, /* TDM sink2 enable , */\
+ { 0x12a0, "tdm_source0_enable"}, /* TDM source0 enable , */\
+ { 0x12b0, "tdm_source1_enable"}, /* TDM source1 enable , */\
+ { 0x12c0, "tdm_source2_enable"}, /* TDM source2 enable , */\
+ { 0x12d0, "tdm_sink0_io"}, /* tdm_sink0_io , */\
+ { 0x12e0, "tdm_sink1_io"}, /* tdm_sink1_io , */\
+ { 0x12f0, "tdm_sink2_io"}, /* tdm_sink2_io , */\
+ { 0x1300, "tdm_source0_io"}, /* tdm_source0_io , */\
+ { 0x1310, "tdm_source1_io"}, /* tdm_source1_io , */\
+ { 0x1320, "tdm_source2_io"}, /* tdm_source2_io , */\
+ { 0x1333, "tdm_sink0_slot"}, /* sink0_slot [GAIN IN] , */\
+ { 0x1373, "tdm_sink1_slot"}, /* sink1_slot [CH1 IN] , */\
+ { 0x13b3, "tdm_sink2_slot"}, /* sink2_slot [CH2 IN] , */\
+ { 0x1403, "tdm_source0_slot"}, /* source0_slot [GAIN OUT] , */\
+ { 0x1443, "tdm_source1_slot"}, /* source1_slot [Voltage Sense] , */\
+ { 0x1483, "tdm_source2_slot"}, /* source2_slot [Current Sense] , */\
+ { 0x14c3, "tdm_nbck"}, /* NBCK , */\
+ { 0x1500, "flag_tdm_lut_error"}, /* TDM LUT error flag , */\
+ { 0x1512, "flag_tdm_status"}, /* TDM interface status bits , */\
+ { 0x1540, "flag_tdm_error"}, /* TDM interface error indicator , */\
+ { 0x2000, "flag_por_int_out"}, /* flag_por_int_out , */\
+ { 0x2010, "flag_pll_lock_int_out"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "flag_otpok_int_out"}, /* flag_otpok_int_out , */\
+ { 0x2030, "flag_ovpok_int_out"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "flag_uvpok_int_out"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "flag_ocp_alarm_int_out"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "flag_clocks_stable_int_out"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "flag_clip_int_out"}, /* flag_clip_int_out , */\
+ { 0x2080, "mtp_busy_int_out"}, /* mtp_busy_int_out , */\
+ { 0x2090, "flag_lost_clk_int_out"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "flag_cf_speakererror_int_out"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "flag_cold_started_int_out"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "flag_engage_int_out"}, /* flag_engage_int_out , */\
+ { 0x20d0, "flag_watchdog_reset_int_out"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "flag_enbl_amp_int_out"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "flag_enbl_ref_int_out"}, /* flag_enbl_ref_int_out , */\
+ { 0x2100, "flag_voutcomp_int_out"}, /* flag_voutcomp_int_out , */\
+ { 0x2110, "flag_voutcomp93_int_out"}, /* flag_voutcomp93_int_out , */\
+ { 0x2120, "flag_voutcomp86_int_out"}, /* flag_voutcomp86_int_out , */\
+ { 0x2130, "flag_hiz_int_out"}, /* flag_hiz_int_out , */\
+ { 0x2140, "flag_ocpokbst_int_out"}, /* flag_ocpokbst_int_out , */\
+ { 0x2150, "flag_peakcur_int_out"}, /* flag_peakcur_int_out , */\
+ { 0x2160, "flag_ocpokap_int_out"}, /* flag_ocpokap_int_out , */\
+ { 0x2170, "flag_ocpokan_int_out"}, /* flag_ocpokan_int_out , */\
+ { 0x2180, "flag_ocpokbp_int_out"}, /* flag_ocpokbp_int_out , */\
+ { 0x2190, "flag_ocpokbn_int_out"}, /* flag_ocpokbn_int_out , */\
+ { 0x21a0, "flag_adc10_ready_int_out"}, /* flag_adc10_ready_int_out , */\
+ { 0x21b0, "flag_clipa_high_int_out"}, /* flag_clipa_high_int_out , */\
+ { 0x21c0, "flag_clipa_low_int_out"}, /* flag_clipa_low_int_out , */\
+ { 0x21d0, "flag_clipb_high_int_out"}, /* flag_clipb_high_int_out , */\
+ { 0x21e0, "flag_clipb_low_int_out"}, /* flag_clipb_low_int_out , */\
+ { 0x21f0, "flag_tdm_error_int_out"}, /* flag_tdm_error_int_out , */\
+ { 0x2201, "interrupt_out3"}, /* Interrupt status register output - Corresponding flag, */\
+ { 0x2300, "flag_por_int_in"}, /* flag_por_int_in , */\
+ { 0x2310, "flag_pll_lock_int_in"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "flag_otpok_int_in"}, /* flag_otpok_int_in , */\
+ { 0x2330, "flag_ovpok_int_in"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "flag_uvpok_int_in"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "flag_ocp_alarm_int_in"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "flag_clocks_stable_int_in"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "flag_clip_int_in"}, /* flag_clip_int_in , */\
+ { 0x2380, "mtp_busy_int_in"}, /* mtp_busy_int_in , */\
+ { 0x2390, "flag_lost_clk_int_in"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "flag_cf_speakererror_int_in"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "flag_cold_started_int_in"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "flag_engage_int_in"}, /* flag_engage_int_in , */\
+ { 0x23d0, "flag_watchdog_reset_int_in"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "flag_enbl_amp_int_in"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "flag_enbl_ref_int_in"}, /* flag_enbl_ref_int_in , */\
+ { 0x2400, "flag_voutcomp_int_in"}, /* flag_voutcomp_int_in , */\
+ { 0x2410, "flag_voutcomp93_int_in"}, /* flag_voutcomp93_int_in , */\
+ { 0x2420, "flag_voutcomp86_int_in"}, /* flag_voutcomp86_int_in , */\
+ { 0x2430, "flag_hiz_int_in"}, /* flag_hiz_int_in , */\
+ { 0x2440, "flag_ocpokbst_int_in"}, /* flag_ocpokbst_int_in , */\
+ { 0x2450, "flag_peakcur_int_in"}, /* flag_peakcur_int_in , */\
+ { 0x2460, "flag_ocpokap_int_in"}, /* flag_ocpokap_int_in , */\
+ { 0x2470, "flag_ocpokan_int_in"}, /* flag_ocpokan_int_in , */\
+ { 0x2480, "flag_ocpokbp_int_in"}, /* flag_ocpokbp_int_in , */\
+ { 0x2490, "flag_ocpokbn_int_in"}, /* flag_ocpokbn_int_in , */\
+ { 0x24a0, "flag_adc10_ready_int_in"}, /* flag_adc10_ready_int_in , */\
+ { 0x24b0, "flag_clipa_high_int_in"}, /* flag_clipa_high_int_in , */\
+ { 0x24c0, "flag_clipa_low_int_in"}, /* flag_clipa_low_int_in , */\
+ { 0x24d0, "flag_clipb_high_int_in"}, /* flag_clipb_high_int_in , */\
+ { 0x24e0, "flag_clipb_low_int_in"}, /* flag_clipb_low_int_in , */\
+ { 0x24f0, "flag_tdm_error_int_in"}, /* flag_tdm_error_int_in , */\
+ { 0x2501, "interrupt_in3"}, /* Interrupt register input , */\
+ { 0x2600, "flag_por_int_enable"}, /* flag_por_int_enable , */\
+ { 0x2610, "flag_pll_lock_int_enable"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "flag_otpok_int_enable"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "flag_ovpok_int_enable"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "flag_uvpok_int_enable"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "flag_ocp_alarm_int_enable"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "flag_clocks_stable_int_enable"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "flag_clip_int_enable"}, /* flag_clip_int_enable , */\
+ { 0x2680, "mtp_busy_int_enable"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "flag_lost_clk_int_enable"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "flag_cf_speakererror_int_enable"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "flag_cold_started_int_enable"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "flag_engage_int_enable"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "flag_watchdog_reset_int_enable"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "flag_enbl_amp_int_enable"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "flag_enbl_ref_int_enable"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2700, "flag_voutcomp_int_enable"}, /* flag_voutcomp_int_enable , */\
+ { 0x2710, "flag_voutcomp93_int_enable"}, /* flag_voutcomp93_int_enable , */\
+ { 0x2720, "flag_voutcomp86_int_enable"}, /* flag_voutcomp86_int_enable , */\
+ { 0x2730, "flag_hiz_int_enable"}, /* flag_hiz_int_enable , */\
+ { 0x2740, "flag_ocpokbst_int_enable"}, /* flag_ocpokbst_int_enable , */\
+ { 0x2750, "flag_peakcur_int_enable"}, /* flag_peakcur_int_enable , */\
+ { 0x2760, "flag_ocpokap_int_enable"}, /* flag_ocpokap_int_enable , */\
+ { 0x2770, "flag_ocpokan_int_enable"}, /* flag_ocpokan_int_enable , */\
+ { 0x2780, "flag_ocpokbp_int_enable"}, /* flag_ocpokbp_int_enable , */\
+ { 0x2790, "flag_ocpokbn_int_enable"}, /* flag_ocpokbn_int_enable , */\
+ { 0x27a0, "flag_adc10_ready_int_enable"}, /* flag_adc10_ready_int_enable , */\
+ { 0x27b0, "flag_clipa_high_int_enable"}, /* flag_clipa_high_int_enable , */\
+ { 0x27c0, "flag_clipa_low_int_enable"}, /* flag_clipa_low_int_enable , */\
+ { 0x27d0, "flag_clipb_high_int_enable"}, /* flag_clipb_high_int_enable , */\
+ { 0x27e0, "flag_clipb_low_int_enable"}, /* flag_clipb_low_int_enable , */\
+ { 0x27f0, "flag_tdm_error_int_enable"}, /* flag_tdm_error_int_enable , */\
+ { 0x2801, "interrupt_enable3"}, /* Interrupt enable register , */\
+ { 0x2900, "flag_por_int_pol"}, /* flag_por_int_pol , */\
+ { 0x2910, "flag_pll_lock_int_pol"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "flag_otpok_int_pol"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "flag_ovpok_int_pol"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "flag_uvpok_int_pol"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "flag_ocp_alarm_int_pol"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "flag_clocks_stable_int_pol"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "flag_clip_int_pol"}, /* flag_clip_int_pol , */\
+ { 0x2980, "mtp_busy_int_pol"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "flag_lost_clk_int_pol"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "flag_cf_speakererror_int_pol"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "flag_cold_started_int_pol"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "flag_engage_int_pol"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "flag_watchdog_reset_int_pol"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "flag_enbl_amp_int_pol"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "flag_enbl_ref_int_pol"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2a00, "flag_voutcomp_int_pol"}, /* flag_voutcomp_int_pol , */\
+ { 0x2a10, "flag_voutcomp93_int_pol"}, /* flag_voutcomp93_int_pol , */\
+ { 0x2a20, "flag_voutcomp86_int_pol"}, /* flag_voutcomp86_int_pol , */\
+ { 0x2a30, "flag_hiz_int_pol"}, /* flag_hiz_int_pol , */\
+ { 0x2a40, "flag_ocpokbst_int_pol"}, /* flag_ocpokbst_int_pol , */\
+ { 0x2a50, "flag_peakcur_int_pol"}, /* flag_peakcur_int_pol , */\
+ { 0x2a60, "flag_ocpokap_int_pol"}, /* flag_ocpokap_int_pol , */\
+ { 0x2a70, "flag_ocpokan_int_pol"}, /* flag_ocpokan_int_pol , */\
+ { 0x2a80, "flag_ocpokbp_int_pol"}, /* flag_ocpokbp_int_pol , */\
+ { 0x2a90, "flag_ocpokbn_int_pol"}, /* flag_ocpokbn_int_pol , */\
+ { 0x2aa0, "flag_adc10_ready_int_pol"}, /* flag_adc10_ready_int_pol , */\
+ { 0x2ab0, "flag_clipa_high_int_pol"}, /* flag_clipa_high_int_pol , */\
+ { 0x2ac0, "flag_clipa_low_int_pol"}, /* flag_clipa_low_int_pol , */\
+ { 0x2ad0, "flag_clipb_high_int_pol"}, /* flag_clipb_high_int_pol , */\
+ { 0x2ae0, "flag_clipb_low_int_pol"}, /* flag_clipb_low_int_pol , */\
+ { 0x2af0, "flag_tdm_error_int_pol"}, /* flag_tdm_error_int_pol , */\
+ { 0x2b01, "status_polarity3"}, /* Interrupt status flags polarity register , */\
+ { 0x3000, "flag_voutcomp"}, /* flag_voutcomp, indication Vset is larger than Vbat, */\
+ { 0x3010, "flag_voutcomp93"}, /* flag_voutcomp93, indication Vset is larger than 1.07* Vbat, */\
+ { 0x3020, "flag_voutcomp86"}, /* flag_voutcomp86, indication Vset is larger than 1.14* Vbat, */\
+ { 0x3030, "flag_hiz"}, /* flag_hiz, indication Vbst is larger than Vbat , */\
+ { 0x3040, "flag_ocpokbst"}, /* flag_ocpokbst, indication no over current in boost converter pmos switch, */\
+ { 0x3050, "flag_peakcur"}, /* flag_peakcur, indication current is max in dcdc converter, */\
+ { 0x3060, "flag_ocpokap"}, /* flag_ocpokap, indication no over current in amplifier "a" pmos output stage, */\
+ { 0x3070, "flag_ocpokan"}, /* flag_ocpokan, indication no over current in amplifier "a" nmos output stage, */\
+ { 0x3080, "flag_ocpokbp"}, /* flag_ocpokbp, indication no over current in amplifier "b" pmos output stage, */\
+ { 0x3090, "flag_ocpokbn"}, /* flag_ocpokbn, indication no over current in amplifier"b" nmos output stage, */\
+ { 0x30a0, "flag_adc10_ready"}, /* flag_adc10_ready, indication adc10 is ready , */\
+ { 0x30b0, "flag_clipa_high"}, /* flag_clipa_high, indication pmos amplifier "a" is clipping, */\
+ { 0x30c0, "flag_clipa_low"}, /* flag_clipa_low, indication nmos amplifier "a" is clipping, */\
+ { 0x30d0, "flag_clipb_high"}, /* flag_clipb_high, indication pmos amplifier "b" is clipping, */\
+ { 0x30e0, "flag_clipb_low"}, /* flag_clipb_low, indication nmos amplifier "b" is clipping, */\
+ { 0x310f, "mtp_man_data_out"}, /* single word read from MTP (manual copy) , */\
+ { 0x3200, "key01_locked"}, /* key01_locked, indication key 1 is locked , */\
+ { 0x3210, "key02_locked"}, /* key02_locked, indication key 2 is locked , */\
+ { 0x3225, "mtp_ecc_tcout"}, /* mtp_ecc_tcout , */\
+ { 0x3280, "mtpctrl_valid_test_rd"}, /* mtp test readout for read , */\
+ { 0x3290, "mtpctrl_valid_test_wr"}, /* mtp test readout for write , */\
+ { 0x32a0, "flag_in_alarm_state"}, /* Alarm state , */\
+ { 0x32b0, "mtp_ecc_err2"}, /* two or more bit errors detected in MTP, can not reconstruct value, */\
+ { 0x32c0, "mtp_ecc_err1"}, /* one bit error detected in MTP, reconstructed value, */\
+ { 0x32d0, "mtp_mtp_hvf"}, /* high voltage ready flag for MTP , */\
+ { 0x32f0, "mtp_zero_check_fail"}, /* zero check failed (tbd) for MTP , */\
+ { 0x3309, "data_adc10_tempbat"}, /* data_adc10_tempbat[9;0], adc 10 data output for testing, */\
+ { 0x400f, "hid_code"}, /* 5A6Bh, 23147d to access registers (Default for engineering), */\
+ { 0x4100, "bypass_hp"}, /* Bypass_High Pass Filter , */\
+ { 0x4110, "hard_mute"}, /* Hard Mute , */\
+ { 0x4120, "soft_mute"}, /* Soft Mute , */\
+ { 0x4134, "pwm_delay"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "pwm_shape"}, /* PWM Shape , */\
+ { 0x4190, "pwm_bitlength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4203, "drive"}, /* Drive bits to select amount of power stage amplifier, */\
+ { 0x4240, "reclock_pwm"}, /* , */\
+ { 0x4250, "reclock_voltsense"}, /* , */\
+ { 0x4281, "dpsalevel"}, /* DPSA Threshold level , */\
+ { 0x42a1, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x42c0, "coincidence"}, /* Prevent simultaneously switching of output stage , */\
+ { 0x42d0, "kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x4306, "drivebst"}, /* Drive bits to select the powertransistor sections boost converter, */\
+ { 0x43a0, "ocptestbst"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0);For new ocp (ctrl_reversebst is 1);, */\
+ { 0x43d0, "test_abistfft_enbl"}, /* FFT coolflux , */\
+ { 0x43f0, "test_bcontrol"}, /* test _bcontrol , */\
+ { 0x4400, "reversebst"}, /* OverCurrent Protection selection of power stage boost converter, */\
+ { 0x4410, "sensetest"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0x4420, "enbl_engagebst"}, /* Enable power stage dcdc controller , */\
+ { 0x4470, "enbl_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x4480, "enbl_voutcomp"}, /* Enable vout comparators , */\
+ { 0x4490, "enbl_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x44a0, "enbl_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x44b0, "enbl_hizcom"}, /* Enable hiz comparator , */\
+ { 0x44c0, "enbl_peakcur"}, /* Enable peak current , */\
+ { 0x44d0, "bypass_ovpglitch"}, /* Bypass OVP Glitch Filter , */\
+ { 0x44e0, "enbl_windac"}, /* Enable window dac , */\
+ { 0x44f0, "enbl_powerbst"}, /* Enable line of the powerstage , */\
+ { 0x4507, "ocp_thr"}, /* ocp_thr threshold level for OCP , */\
+ { 0x4580, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0x4590, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0x45a0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0x45b0, "bypass_otp"}, /* Bypass OTP , */\
+ { 0x45c0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0x45d0, "bypass_ocpcounter"}, /* BypassOCPCounter , */\
+ { 0x45e0, "bypass_lost_clk"}, /* Bypasslost_clk detector , */\
+ { 0x45f0, "vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0x4600, "bypass_gc"}, /* bypass_gc, bypasses the CS gain correction , */\
+ { 0x4610, "cs_gain_control"}, /* gain control by means of MTP or i2c; 0 is MTP , */\
+ { 0x4627, "cs_gain"}, /* + / - 128 steps in steps of 1/4 percent 2's compliment, */\
+ { 0x46a0, "bypass_lp"}, /* bypass Low-Pass filter in temperature sensor , */\
+ { 0x46b0, "bypass_pwmcounter"}, /* bypass_pwmcounter , */\
+ { 0x46c0, "cs_negfixed"}, /* does not switch to neg , */\
+ { 0x46d2, "cs_neghyst"}, /* switches to neg depending on level , */\
+ { 0x4700, "switch_fb"}, /* switch_fb , */\
+ { 0x4713, "se_hyst"}, /* se_hyst , */\
+ { 0x4754, "se_level"}, /* se_level , */\
+ { 0x47a5, "ktemp"}, /* temperature compensation trimming , */\
+ { 0x4800, "cs_negin"}, /* negin , */\
+ { 0x4810, "cs_sein"}, /* cs_sein , */\
+ { 0x4820, "cs_coincidence"}, /* Coincidence current sense , */\
+ { 0x4830, "iddqtestbst"}, /* for iddq testing in powerstage of boost convertor , */\
+ { 0x4840, "coincidencebst"}, /* Switch protection on to prevent simultaneously switching power stages bst and amp, */\
+ { 0x4876, "delay_se_neg"}, /* delay of se and neg , */\
+ { 0x48e1, "cs_ttrack"}, /* sample & hold track time , */\
+ { 0x4900, "bypass_clip"}, /* Bypass clip control , */\
+ { 0x4920, "cf_cgate_off"}, /* to disable clock gating in the coolflux , */\
+ { 0x4940, "clipfast"}, /* clock switch for battery protection clipper, it switches back to old frequency, */\
+ { 0x4950, "cs_8ohm"}, /* 8 ohm mode for current sense (gain mode) , */\
+ { 0x4974, "delay_clock_sh"}, /* delay_sh, tunes S7H delay , */\
+ { 0x49c0, "inv_clksh"}, /* Invert the sample/hold clock for current sense ADC, */\
+ { 0x49d0, "inv_neg"}, /* Invert neg signal , */\
+ { 0x49e0, "inv_se"}, /* Invert se signal , */\
+ { 0x49f0, "setse"}, /* switches between Single Ende and differential mode; 1 is single ended, */\
+ { 0x4a12, "adc10_sel"}, /* select the input to convert the 10b ADC , */\
+ { 0x4a60, "adc10_reset"}, /* Global asynchronous reset (active HIGH) 10 bit ADC, */\
+ { 0x4a81, "adc10_test"}, /* Test mode selection signal 10 bit ADC , */\
+ { 0x4aa0, "bypass_lp_vbat"}, /* lp filter in batt sensor , */\
+ { 0x4ae0, "dc_offset"}, /* switch offset control on/off, is decimator offset control, */\
+ { 0x4af0, "tsense_hibias"}, /* bit to set the biasing in temp sensor to high , */\
+ { 0x4b00, "adc13_iset"}, /* Micadc Setting of current consumption. Debug use only, */\
+ { 0x4b14, "adc13_gain"}, /* Micadc gain setting (2-compl) , */\
+ { 0x4b61, "adc13_slowdel"}, /* Micadc Delay setting for internal clock. Debug use only, */\
+ { 0x4b83, "adc13_offset"}, /* Micadc ADC offset setting , */\
+ { 0x4bc0, "adc13_bsoinv"}, /* Micadc bit stream output invert mode for test , */\
+ { 0x4bd0, "adc13_resonator_enable"}, /* Micadc Give extra SNR with less stability. Debug use only, */\
+ { 0x4be0, "testmicadc"}, /* Mux at input of MICADC for test purpose , */\
+ { 0x4c0f, "abist_offset"}, /* offset control for ABIST testing , */\
+ { 0x4d05, "windac"}, /* for testing direct control windac , */\
+ { 0x4dc3, "pwm_dcc_cnt"}, /* control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0x4e04, "slopecur"}, /* for testing direct control slopecur , */\
+ { 0x4e50, "ctrl_dem"}, /* dyn element matching control, rest of codes are optional, */\
+ { 0x4ed0, "enbl_pwm_dcc"}, /* to enable direct control of pwm duty cycle , */\
+ { 0x5007, "gain"}, /* Gain setting of the gain multiplier , */\
+ { 0x5081, "sourceb"}, /* Set OUTB to , */\
+ { 0x50a1, "sourcea"}, /* Set OUTA to , */\
+ { 0x50c1, "sourcebst"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0x50e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0x5104, "pulselengthbst"}, /* pulse length setting test input for boost converter, */\
+ { 0x5150, "bypasslatchbst"}, /* bypass_latch in boost converter , */\
+ { 0x5160, "invertbst"}, /* invert pwmbst test signal , */\
+ { 0x5174, "pulselength"}, /* pulse length setting test input for amplifier , */\
+ { 0x51c0, "bypasslatch"}, /* bypass_latch in PWM source selection module , */\
+ { 0x51d0, "invertb"}, /* invert pwmb test signal , */\
+ { 0x51e0, "inverta"}, /* invert pwma test signal , */\
+ { 0x51f0, "bypass_ctrlloop"}, /* bypass_ctrlloop bypasses the control loop of the amplifier, */\
+ { 0x5210, "test_rdsona"}, /* tbd for rdson testing , */\
+ { 0x5220, "test_rdsonb"}, /* tbd for rdson testing , */\
+ { 0x5230, "test_rdsonbst"}, /* tbd for rdson testing , */\
+ { 0x5240, "test_cvia"}, /* tbd for rdson testing , */\
+ { 0x5250, "test_cvib"}, /* tbd for rdson testing , */\
+ { 0x5260, "test_cvibst"}, /* tbd for rdson testing , */\
+ { 0x5306, "digimuxa_sel"}, /* DigimuxA input selection control (see Digimux list for details), */\
+ { 0x5376, "digimuxb_sel"}, /* DigimuxB input selection control (see Digimux list for details), */\
+ { 0x5400, "hs_mode"}, /* hs_mode, high speed mode I2C bus , */\
+ { 0x5412, "test_parametric_io"}, /* test_parametric_io for testing pads , */\
+ { 0x5440, "enbl_ringo"}, /* enbl_ringo, for test purpose to check with ringo , */\
+ { 0x5456, "digimuxc_sel"}, /* DigimuxC input selection control (see Digimux list for details), */\
+ { 0x54c0, "dio_ehs"}, /* Slew control for DIO in output mode , */\
+ { 0x54d0, "gainio_ehs"}, /* Slew control for GAINIO in output mode , */\
+ { 0x550d, "enbl_amp"}, /* enbl_amp for testing to enable all analoge blocks in amplifier, */\
+ { 0x5600, "use_direct_ctrls"}, /* use_direct_ctrls, to overrule several functions direct for testing, */\
+ { 0x5610, "rst_datapath"}, /* rst_datapath, datapath reset , */\
+ { 0x5620, "rst_cgu"}, /* rst_cgu, cgu reset , */\
+ { 0x5637, "enbl_ref"}, /* for testing to enable all analoge blocks in references, */\
+ { 0x56b0, "enbl_engage"}, /* Enable output stage amplifier , */\
+ { 0x56c0, "use_direct_clk_ctrl"}, /* use_direct_clk_ctrl, to overrule several functions direct for testing, */\
+ { 0x56d0, "use_direct_pll_ctrl"}, /* use_direct_pll_ctrl, to overrule several functions direct for testing, */\
+ { 0x56e0, "use_direct_ctrls_2"}, /* use_direct_sourseamp_ctrls, to overrule several functions direct for testing, */\
+ { 0x5707, "anamux"}, /* Anamux control , */\
+ { 0x57c0, "ocptest"}, /* ctrl_ocptest, deactivates the over current protection in the power stages of the amplifier. The ocp flag signals stay active., */\
+ { 0x57e0, "otptest"}, /* otptest, test mode otp amplifier , */\
+ { 0x57f0, "reverse"}, /* 1: Normal mode, slope is controlled , */\
+ { 0x5813, "pll_selr"}, /* pll_selr , */\
+ { 0x5854, "pll_selp"}, /* pll_selp , */\
+ { 0x58a5, "pll_seli"}, /* pll_seli , */\
+ { 0x5950, "pll_mdec_msb"}, /* most significant bits of pll_mdec[16] , */\
+ { 0x5960, "pll_ndec_msb"}, /* most significant bits of pll_ndec[9] , */\
+ { 0x5970, "pll_frm"}, /* pll_frm , */\
+ { 0x5980, "pll_directi"}, /* pll_directi , */\
+ { 0x5990, "pll_directo"}, /* pll_directo , */\
+ { 0x59a0, "enbl_pll"}, /* enbl_pll , */\
+ { 0x59f0, "pll_bypass"}, /* pll_bypass , */\
+ { 0x5a0f, "tsig_freq"}, /* tsig_freq, internal sinus test generator, frequency control, */\
+ { 0x5b02, "tsig_freq_msb"}, /* select internal sinus test generator, frequency control msb bits, */\
+ { 0x5b30, "inject_tsig"}, /* inject_tsig, control bit to switch to internal sinus test generator, */\
+ { 0x5b44, "adc10_prog_sample"}, /* control ADC10 , */\
+ { 0x5c0f, "pll_mdec"}, /* bits 15..0 of pll_mdec[16;0] , */\
+ { 0x5d06, "pll_pdec"}, /* pll_pdec , */\
+ { 0x5d78, "pll_ndec"}, /* bits 8..0 of pll_ndec[9;0] , */\
+ { 0x6007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0x6185, "mtp_ecc_tcin"}, /* Mtp_ecc_tcin , */\
+ { 0x6203, "mtp_man_address_in"}, /* address from I2C regs for writing one word single mtp, */\
+ { 0x6260, "mtp_ecc_eeb"}, /* enable code bit generation (active low!) , */\
+ { 0x6270, "mtp_ecc_ecb"}, /* enable correction signal (active low!) , */\
+ { 0x6280, "man_copy_mtp_to_iic"}, /* start copying single word from mtp to i2cregs_mtp , */\
+ { 0x6290, "man_copy_iic_to_mtp"}, /* start copying single word from i2cregs_mtp to mtp [Key 1 protected], */\
+ { 0x62a0, "auto_copy_mtp_to_iic"}, /* start copying all the data from mtp to i2cregs_mtp, */\
+ { 0x62b0, "auto_copy_iic_to_mtp"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x62d2, "mtp_speed_mode"}, /* Speed mode , */\
+ { 0x6340, "mtp_direct_enable"}, /* mtp_direct_enable (key1 protected) , */\
+ { 0x6350, "mtp_direct_wr"}, /* mtp_direct_wr (key1 protected) , */\
+ { 0x6360, "mtp_direct_rd"}, /* mtp_direct_rd (key1 protected) , */\
+ { 0x6370, "mtp_direct_rst"}, /* mtp_direct_rst (key1 protected) , */\
+ { 0x6380, "mtp_direct_ers"}, /* mtp_direct_ers (key1 protected) , */\
+ { 0x6390, "mtp_direct_prg"}, /* mtp_direct_prg (key1 protected) , */\
+ { 0x63a0, "mtp_direct_epp"}, /* mtp_direct_epp (key1 protected) , */\
+ { 0x63b4, "mtp_direct_test"}, /* mtp_direct_test (key1 protected) , */\
+ { 0x640f, "mtp_man_data_in"}, /* single word to be written to MTP (manual copy) , */\
+ { 0x7000, "cf_rst_dsp"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "cf_dmem"}, /* Target memory for access , */\
+ { 0x7030, "cf_aif"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "cf_int"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "cf_req"}, /* request for access (8 channels) , */\
+ { 0x710f, "cf_madd"}, /* memory-address to be accessed , */\
+ { 0x720f, "cf_mema"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "cf_err"}, /* Coolflux error flags , */\
+ { 0x7387, "cf_ack"}, /* acknowledge of requests (8 channels) , */\
+ { 0x8000, "calibration_onetime"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "calibr_ron_done"}, /* (key2 protected) , */\
+ { 0x8105, "calibr_vout_offset"}, /* calibr_vout_offset (DCDCoffset) 2's compliment (key1 protected), */\
+ { 0x8163, "calibr_delta_gain"}, /* delta gain for vamp (alpha) 2's compliment (key1 protected), */\
+ { 0x81a5, "calibr_offs_amp"}, /* offset for vamp (Ampoffset) 2's compliment (key1 protected), */\
+ { 0x8207, "calibr_gain_cs"}, /* gain current sense (Imeasalpha) 2's compliment (key1 protected), */\
+ { 0x8284, "calibr_temp_offset"}, /* temperature offset 2's compliment (key1 protected), */\
+ { 0x82d2, "calibr_temp_gain"}, /* temperature gain 2's compliment (key1 protected) , */\
+ { 0x830f, "calibr_ron"}, /* Ron resistance of coil (key1 protected) , */\
+ { 0x8505, "type_bits_HW"}, /* Key1_Protected_MTP5 , */\
+ { 0x8601, "type_bits_1_0_SW"}, /* MTP-control SW , */\
+ { 0x8681, "type_bits_8_9_SW"}, /* MTP-control SW , */\
+ { 0x870f, "type_bits2_SW"}, /* MTP-control SW2 , */\
+ { 0x8806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0x8870, "htol_iic_addr_en"}, /* HTOL_I2C_Address_Enable , */\
+ { 0x8881, "ctrl_ovp_response"}, /* OVP response control , */\
+ { 0x88a0, "disable_ovp_alarm_state"}, /* OVP alarm state control , */\
+ { 0x88b0, "enbl_stretch_ovp"}, /* OVP alram strech control , */\
+ { 0x88c0, "cf_debug_mode"}, /* Coolflux debug mode , */\
+ { 0x8a0f, "production_data1"}, /* (key1 protected) , */\
+ { 0x8b0f, "production_data2"}, /* (key1 protected) , */\
+ { 0x8c0f, "production_data3"}, /* (key1 protected) , */\
+ { 0x8d0f, "production_data4"}, /* (key1 protected) , */\
+ { 0x8e0f, "production_data5"}, /* (key1 protected) , */\
+ { 0x8f0f, "production_data6"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa1_irq {
+ tfa1_irq_vdds = 0,
+ tfa1_irq_plls = 1,
+ tfa1_irq_ds = 2,
+ tfa1_irq_vds = 3,
+ tfa1_irq_uvds = 4,
+ tfa1_irq_cds = 5,
+ tfa1_irq_clks = 6,
+ tfa1_irq_clips = 7,
+ tfa1_irq_mtpb = 8,
+ tfa1_irq_clk = 9,
+ tfa1_irq_spks = 10,
+ tfa1_irq_acs = 11,
+ tfa1_irq_sws = 12,
+ tfa1_irq_wds = 13,
+ tfa1_irq_amps = 14,
+ tfa1_irq_arefs = 15,
+ tfa1_irq_ack = 32,
+ tfa1_irq_max = 33,
+ tfa1_irq_all = -1 /* all irqs */};
+
+#define TFA1_IRQ_NAMETABLE static tfaIrqName_t Tfa1IrqNames[]= {\
+ { 0, "VDDS"},\
+ { 1, "PLLS"},\
+ { 2, "DS"},\
+ { 3, "VDS"},\
+ { 4, "UVDS"},\
+ { 5, "CDS"},\
+ { 6, "CLKS"},\
+ { 7, "CLIPS"},\
+ { 8, "MTPB"},\
+ { 9, "CLK"},\
+ { 10, "SPKS"},\
+ { 11, "ACS"},\
+ { 12, "SWS"},\
+ { 13, "WDS"},\
+ { 14, "AMPS"},\
+ { 15, "AREFS"},\
+ { 16, "16"},\
+ { 17, "17"},\
+ { 18, "18"},\
+ { 19, "19"},\
+ { 20, "20"},\
+ { 21, "21"},\
+ { 22, "22"},\
+ { 23, "23"},\
+ { 24, "24"},\
+ { 25, "25"},\
+ { 26, "26"},\
+ { 27, "27"},\
+ { 28, "28"},\
+ { 29, "29"},\
+ { 30, "30"},\
+ { 31, "31"},\
+ { 32, "ACK"},\
+ { 33, "33"},\
+};
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa2_tfafieldnames_N1C.h b/sound/soc/codecs/tfa98xx-downstream/tfa2_tfafieldnames_N1C.h
new file mode 100644
index 00000000000..ac0bb040356
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa2_tfafieldnames_N1C.h
@@ -0,0 +1,1533 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa98xx_TfaFieldnames.h
+ * This file was generated automatically on 09/01/15 at 09:40:28.
+ * Source file: TFA9888_N1C_I2C_regmap_V1.xlsx
+ */
+#define TFA9888_I2CVERSION 18
+typedef enum Tfa2BfEnumList {
+ TFA2_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA2_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA2_BF_CFE = 0x0020, /*!< Enable CoolFlux */
+ TFA2_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA2_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA2_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA2_BF_AMPC = 0x0060, /*!< CoolFlux controls amplifier */
+ TFA2_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA2_BF_FSSSEL= 0x0091, /*!< Audio sample reference */
+ TFA2_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA2_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA2_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA2_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA2_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA2_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA2_BF_MANROBOD= 0x0150, /*!< Reaction on BOD */
+ TFA2_BF_BODE = 0x0160, /*!< BOD Enable */
+ TFA2_BF_BODHYS= 0x0170, /*!< BOD Hysteresis */
+ TFA2_BF_BODFILT= 0x0181, /*!< BOD filter */
+ TFA2_BF_BODTHLVL= 0x01a1, /*!< BOD threshold */
+ TFA2_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA2_BF_RCVNS = 0x01e0, /*!< Noise shaper selection */
+ TFA2_BF_MANWDE= 0x01f0, /*!< Watchdog manager reaction */
+ TFA2_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA2_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA2_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA2_BF_BYPHVBF= 0x02b0, /*!< Bypass HVBAT filter */
+ TFA2_BF_LDOBYP= 0x02c0, /*!< Receiver LDO bypass */
+ TFA2_BF_REV = 0x030f, /*!< Revision info */
+ TFA2_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA2_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA2_BF_SSLEFTE= 0x0500, /*!< Enable left channel */
+ TFA2_BF_SSRIGHTE= 0x0510, /*!< Enable right channel */
+ TFA2_BF_VSLEFTE= 0x0520, /*!< Voltage sense left */
+ TFA2_BF_VSRIGHTE= 0x0530, /*!< Voltage sense right */
+ TFA2_BF_CSLEFTE= 0x0540, /*!< Current sense left */
+ TFA2_BF_CSRIGHTE= 0x0550, /*!< Current sense right */
+ TFA2_BF_SSPDME= 0x0560, /*!< Sub-system PDM */
+ TFA2_BF_STGAIN= 0x0d18, /*!< Side tone gain */
+ TFA2_BF_PDMSMUTE= 0x0da0, /*!< Side tone soft mute */
+ TFA2_BF_SWVSTEP= 0x0e06, /*!< Register for the host SW to record the current active vstep */
+ TFA2_BF_VDDS = 0x1000, /*!< POR */
+ TFA2_BF_PLLS = 0x1010, /*!< PLL lock */
+ TFA2_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA2_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA2_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA2_BF_CLKS = 0x1050, /*!< Clocks stable */
+ TFA2_BF_MTPB = 0x1060, /*!< MTP busy */
+ TFA2_BF_NOCLK = 0x1070, /*!< Lost clock */
+ TFA2_BF_SPKS = 0x1080, /*!< Speaker error */
+ TFA2_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA2_BF_SWS = 0x10a0, /*!< Amplifier engage */
+ TFA2_BF_WDS = 0x10b0, /*!< Watchdog */
+ TFA2_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA2_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA2_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA2_BF_BODNOK= 0x10f0, /*!< BOD */
+ TFA2_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA2_BF_DCDCA = 0x1110, /*!< DCDC active */
+ TFA2_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos */
+ TFA2_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA2_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA2_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA2_BF_STMUTEB= 0x1170, /*!< side tone (un)mute busy */
+ TFA2_BF_STMUTE= 0x1180, /*!< side tone mute state */
+ TFA2_BF_TDMLUTER= 0x1190, /*!< TDM LUT error */
+ TFA2_BF_TDMSTAT= 0x11a2, /*!< TDM status bits */
+ TFA2_BF_TDMERR= 0x11d0, /*!< TDM error */
+ TFA2_BF_HAPTIC= 0x11e0, /*!< Status haptic driver */
+ TFA2_BF_OCPOAPL= 0x1200, /*!< OCPOK pmos A left */
+ TFA2_BF_OCPOANL= 0x1210, /*!< OCPOK nmos A left */
+ TFA2_BF_OCPOBPL= 0x1220, /*!< OCPOK pmos B left */
+ TFA2_BF_OCPOBNL= 0x1230, /*!< OCPOK nmos B left */
+ TFA2_BF_CLIPAHL= 0x1240, /*!< Clipping A left to Vddp */
+ TFA2_BF_CLIPALL= 0x1250, /*!< Clipping A left to gnd */
+ TFA2_BF_CLIPBHL= 0x1260, /*!< Clipping B left to Vddp */
+ TFA2_BF_CLIPBLL= 0x1270, /*!< Clipping B left to gnd */
+ TFA2_BF_OCPOAPRC= 0x1280, /*!< OCPOK pmos A RCV */
+ TFA2_BF_OCPOANRC= 0x1290, /*!< OCPOK nmos A RCV */
+ TFA2_BF_OCPOBPRC= 0x12a0, /*!< OCPOK pmos B RCV */
+ TFA2_BF_OCPOBNRC= 0x12b0, /*!< OCPOK nmos B RCV */
+ TFA2_BF_RCVLDOR= 0x12c0, /*!< RCV LDO regulates */
+ TFA2_BF_RCVLDOBR= 0x12d0, /*!< Receiver LDO ready */
+ TFA2_BF_OCDSL = 0x12e0, /*!< OCP left amplifier */
+ TFA2_BF_CLIPSL= 0x12f0, /*!< Amplifier left clipping */
+ TFA2_BF_OCPOAPR= 0x1300, /*!< OCPOK pmos A right */
+ TFA2_BF_OCPOANR= 0x1310, /*!< OCPOK nmos A right */
+ TFA2_BF_OCPOBPR= 0x1320, /*!< OCPOK pmos B right */
+ TFA2_BF_OCPOBNR= 0x1330, /*!< OCPOK nmos B right */
+ TFA2_BF_CLIPAHR= 0x1340, /*!< Clipping A right to Vddp */
+ TFA2_BF_CLIPALR= 0x1350, /*!< Clipping A right to gnd */
+ TFA2_BF_CLIPBHR= 0x1360, /*!< Clipping B left to Vddp */
+ TFA2_BF_CLIPBLR= 0x1370, /*!< Clipping B right to gnd */
+ TFA2_BF_OCDSR = 0x1380, /*!< OCP right amplifier */
+ TFA2_BF_CLIPSR= 0x1390, /*!< Amplifier right clipping */
+ TFA2_BF_OCPOKMC= 0x13a0, /*!< OCPOK MICVDD */
+ TFA2_BF_MANALARM= 0x13b0, /*!< Alarm state */
+ TFA2_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA2_BF_MANWAIT2= 0x13d0, /*!< Wait CF config */
+ TFA2_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA2_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA2_BF_SPKSL = 0x1400, /*!< Left speaker status */
+ TFA2_BF_SPKSR = 0x1410, /*!< Right speaker status */
+ TFA2_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA2_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA2_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA2_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA2_BF_TDMUC = 0x2003, /*!< Usecase setting */
+ TFA2_BF_TDME = 0x2040, /*!< Enable interface */
+ TFA2_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA2_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA2_BF_TDMFSLN= 0x2073, /*!< FS length (master mode only) */
+ TFA2_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA2_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA2_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA2_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA2_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA2_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA2_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA2_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA2_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA2_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA2_BF_TDMTXUS0= 0x2291, /*!< Format unused slots GAINIO */
+ TFA2_BF_TDMTXUS1= 0x22b1, /*!< Format unused slots DIO1 */
+ TFA2_BF_TDMTXUS2= 0x22d1, /*!< Format unused slots DIO2 */
+ TFA2_BF_TDMLE = 0x2310, /*!< Control audio left */
+ TFA2_BF_TDMRE = 0x2320, /*!< Control audio right */
+ TFA2_BF_TDMVSRE= 0x2340, /*!< Control voltage sense right */
+ TFA2_BF_TDMCSRE= 0x2350, /*!< Control current sense right */
+ TFA2_BF_TDMVSLE= 0x2360, /*!< Voltage sense left control */
+ TFA2_BF_TDMCSLE= 0x2370, /*!< Current sense left control */
+ TFA2_BF_TDMCFRE= 0x2380, /*!< DSP out right control */
+ TFA2_BF_TDMCFLE= 0x2390, /*!< DSP out left control */
+ TFA2_BF_TDMCF3E= 0x23a0, /*!< AEC ref left control */
+ TFA2_BF_TDMCF4E= 0x23b0, /*!< AEC ref right control */
+ TFA2_BF_TDMPD1E= 0x23c0, /*!< PDM 1 control */
+ TFA2_BF_TDMPD2E= 0x23d0, /*!< PDM 2 control */
+ TFA2_BF_TDMLIO= 0x2421, /*!< IO audio left */
+ TFA2_BF_TDMRIO= 0x2441, /*!< IO audio right */
+ TFA2_BF_TDMVSRIO= 0x2481, /*!< IO voltage sense right */
+ TFA2_BF_TDMCSRIO= 0x24a1, /*!< IO current sense right */
+ TFA2_BF_TDMVSLIO= 0x24c1, /*!< IO voltage sense left */
+ TFA2_BF_TDMCSLIO= 0x24e1, /*!< IO current sense left */
+ TFA2_BF_TDMCFRIO= 0x2501, /*!< IO dspout right */
+ TFA2_BF_TDMCFLIO= 0x2521, /*!< IO dspout left */
+ TFA2_BF_TDMCF3IO= 0x2541, /*!< IO AEC ref left control */
+ TFA2_BF_TDMCF4IO= 0x2561, /*!< IO AEC ref right control */
+ TFA2_BF_TDMPD1IO= 0x2581, /*!< IO pdm1 */
+ TFA2_BF_TDMPD2IO= 0x25a1, /*!< IO pdm2 */
+ TFA2_BF_TDMLS = 0x2643, /*!< Position audio left */
+ TFA2_BF_TDMRS = 0x2683, /*!< Position audio right */
+ TFA2_BF_TDMVSRS= 0x2703, /*!< Position voltage sense right */
+ TFA2_BF_TDMCSRS= 0x2743, /*!< Position current sense right */
+ TFA2_BF_TDMVSLS= 0x2783, /*!< Position voltage sense left */
+ TFA2_BF_TDMCSLS= 0x27c3, /*!< Position current sense left */
+ TFA2_BF_TDMCFRS= 0x2803, /*!< Position dspout right */
+ TFA2_BF_TDMCFLS= 0x2843, /*!< Position dspout left */
+ TFA2_BF_TDMCF3S= 0x2883, /*!< Position AEC ref left control */
+ TFA2_BF_TDMCF4S= 0x28c3, /*!< Position AEC ref right control */
+ TFA2_BF_TDMPD1S= 0x2903, /*!< Position pdm1 */
+ TFA2_BF_TDMPD2S= 0x2943, /*!< Position pdm2 */
+ TFA2_BF_PDMSM = 0x3100, /*!< PDM control */
+ TFA2_BF_PDMSTSEL= 0x3111, /*!< Side tone input */
+ TFA2_BF_PDMLSEL= 0x3130, /*!< PDM data selection for left channel during PDM direct mode */
+ TFA2_BF_PDMRSEL= 0x3140, /*!< PDM data selection for right channel during PDM direct mode */
+ TFA2_BF_MICVDDE= 0x3150, /*!< Enable MICVDD */
+ TFA2_BF_PDMCLRAT= 0x3201, /*!< PDM BCK/Fs ratio */
+ TFA2_BF_PDMGAIN= 0x3223, /*!< PDM gain */
+ TFA2_BF_PDMOSEL= 0x3263, /*!< PDM output selection - RE/FE data combination */
+ TFA2_BF_SELCFHAPD= 0x32a0, /*!< Select the source for haptic data output (not for customer) */
+ TFA2_BF_HAPTIME= 0x3307, /*!< Duration (ms) */
+ TFA2_BF_HAPLEVEL= 0x3387, /*!< DC value (FFS) */
+ TFA2_BF_GPIODIN= 0x3403, /*!< Receiving value */
+ TFA2_BF_GPIOCTRL= 0x3500, /*!< GPIO master control over GPIO1/2 ports (not for customer) */
+ TFA2_BF_GPIOCONF= 0x3513, /*!< Configuration */
+ TFA2_BF_GPIODOUT= 0x3553, /*!< Transmitting value */
+ TFA2_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA2_BF_ISTPLLS= 0x4010, /*!< Status PLL lock */
+ TFA2_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA2_BF_ISTOVDS= 0x4030, /*!< Status OVP alarm */
+ TFA2_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA2_BF_ISTCLKS= 0x4050, /*!< Status clocks stable */
+ TFA2_BF_ISTMTPB= 0x4060, /*!< Status MTP busy */
+ TFA2_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA2_BF_ISTSPKS= 0x4080, /*!< Status speaker error */
+ TFA2_BF_ISTACS= 0x4090, /*!< Status cold start */
+ TFA2_BF_ISTSWS= 0x40a0, /*!< Status amplifier engage */
+ TFA2_BF_ISTWDS= 0x40b0, /*!< Status watchdog */
+ TFA2_BF_ISTAMPS= 0x40c0, /*!< Status amplifier enable */
+ TFA2_BF_ISTAREFS= 0x40d0, /*!< Status Ref enable */
+ TFA2_BF_ISTADCCR= 0x40e0, /*!< Status Control ADC */
+ TFA2_BF_ISTBODNOK= 0x40f0, /*!< Status BOD */
+ TFA2_BF_ISTBSTCU= 0x4100, /*!< Status DCDC current limiting */
+ TFA2_BF_ISTBSTHI= 0x4110, /*!< Status DCDC active */
+ TFA2_BF_ISTBSTOC= 0x4120, /*!< Status DCDC OCP */
+ TFA2_BF_ISTBSTPKCUR= 0x4130, /*!< Status bst peakcur */
+ TFA2_BF_ISTBSTVC= 0x4140, /*!< Status DCDC level 1x */
+ TFA2_BF_ISTBST86= 0x4150, /*!< Status DCDC level 1.14x */
+ TFA2_BF_ISTBST93= 0x4160, /*!< Status DCDC level 1.07x */
+ TFA2_BF_ISTRCVLD= 0x4170, /*!< Status rcvldop ready */
+ TFA2_BF_ISTOCPL= 0x4180, /*!< Status ocp alarm left */
+ TFA2_BF_ISTOCPR= 0x4190, /*!< Status ocp alarm right */
+ TFA2_BF_ISTMWSRC= 0x41a0, /*!< Status Waits HW I2C settings */
+ TFA2_BF_ISTMWCFC= 0x41b0, /*!< Status waits CF config */
+ TFA2_BF_ISTMWSMU= 0x41c0, /*!< Status Audio mute sequence */
+ TFA2_BF_ISTCFMER= 0x41d0, /*!< Status cfma error */
+ TFA2_BF_ISTCFMAC= 0x41e0, /*!< Status cfma ack */
+ TFA2_BF_ISTCLKOOR= 0x41f0, /*!< Status flag_clk_out_of_range */
+ TFA2_BF_ISTTDMER= 0x4200, /*!< Status tdm error */
+ TFA2_BF_ISTCLPL= 0x4210, /*!< Status clip left */
+ TFA2_BF_ISTCLPR= 0x4220, /*!< Status clip right */
+ TFA2_BF_ISTOCPM= 0x4230, /*!< Status mic ocpok */
+ TFA2_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA2_BF_ICLPLLS= 0x4410, /*!< Clear PLL lock */
+ TFA2_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA2_BF_ICLOVDS= 0x4430, /*!< Clear OVP alarm */
+ TFA2_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA2_BF_ICLCLKS= 0x4450, /*!< Clear clocks stable */
+ TFA2_BF_ICLMTPB= 0x4460, /*!< Clear mtp busy */
+ TFA2_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA2_BF_ICLSPKS= 0x4480, /*!< Clear speaker error */
+ TFA2_BF_ICLACS= 0x4490, /*!< Clear cold started */
+ TFA2_BF_ICLSWS= 0x44a0, /*!< Clear amplifier engage */
+ TFA2_BF_ICLWDS= 0x44b0, /*!< Clear watchdog */
+ TFA2_BF_ICLAMPS= 0x44c0, /*!< Clear enbl amp */
+ TFA2_BF_ICLAREFS= 0x44d0, /*!< Clear ref enable */
+ TFA2_BF_ICLADCCR= 0x44e0, /*!< Clear control ADC */
+ TFA2_BF_ICLBODNOK= 0x44f0, /*!< Clear BOD */
+ TFA2_BF_ICLBSTCU= 0x4500, /*!< Clear DCDC current limiting */
+ TFA2_BF_ICLBSTHI= 0x4510, /*!< Clear DCDC active */
+ TFA2_BF_ICLBSTOC= 0x4520, /*!< Clear DCDC OCP */
+ TFA2_BF_ICLBSTPC= 0x4530, /*!< Clear bst peakcur */
+ TFA2_BF_ICLBSTVC= 0x4540, /*!< Clear DCDC level 1x */
+ TFA2_BF_ICLBST86= 0x4550, /*!< Clear DCDC level 1.14x */
+ TFA2_BF_ICLBST93= 0x4560, /*!< Clear DCDC level 1.07x */
+ TFA2_BF_ICLRCVLD= 0x4570, /*!< Clear rcvldop ready */
+ TFA2_BF_ICLOCPL= 0x4580, /*!< Clear ocp alarm left */
+ TFA2_BF_ICLOCPR= 0x4590, /*!< Clear ocp alarm right */
+ TFA2_BF_ICLMWSRC= 0x45a0, /*!< Clear wait HW I2C settings */
+ TFA2_BF_ICLMWCFC= 0x45b0, /*!< Clear wait cf config */
+ TFA2_BF_ICLMWSMU= 0x45c0, /*!< Clear audio mute sequence */
+ TFA2_BF_ICLCFMER= 0x45d0, /*!< Clear cfma err */
+ TFA2_BF_ICLCFMAC= 0x45e0, /*!< Clear cfma ack */
+ TFA2_BF_ICLCLKOOR= 0x45f0, /*!< Clear flag_clk_out_of_range */
+ TFA2_BF_ICLTDMER= 0x4600, /*!< Clear tdm error */
+ TFA2_BF_ICLCLPL= 0x4610, /*!< Clear clip left */
+ TFA2_BF_ICLCLPR= 0x4620, /*!< Clear clip right */
+ TFA2_BF_ICLOCPM= 0x4630, /*!< Clear mic ocpok */
+ TFA2_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA2_BF_IEPLLS= 0x4810, /*!< Enable pll lock */
+ TFA2_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA2_BF_IEOVDS= 0x4830, /*!< Enable OVP alarm */
+ TFA2_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA2_BF_IECLKS= 0x4850, /*!< Enable clocks stable */
+ TFA2_BF_IEMTPB= 0x4860, /*!< Enable mtp busy */
+ TFA2_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA2_BF_IESPKS= 0x4880, /*!< Enable speaker error */
+ TFA2_BF_IEACS = 0x4890, /*!< Enable cold started */
+ TFA2_BF_IESWS = 0x48a0, /*!< Enable amplifier engage */
+ TFA2_BF_IEWDS = 0x48b0, /*!< Enable watchdog */
+ TFA2_BF_IEAMPS= 0x48c0, /*!< Enable enbl amp */
+ TFA2_BF_IEAREFS= 0x48d0, /*!< Enable ref enable */
+ TFA2_BF_IEADCCR= 0x48e0, /*!< Enable Control ADC */
+ TFA2_BF_IEBODNOK= 0x48f0, /*!< Enable BOD */
+ TFA2_BF_IEBSTCU= 0x4900, /*!< Enable DCDC current limiting */
+ TFA2_BF_IEBSTHI= 0x4910, /*!< Enable DCDC active */
+ TFA2_BF_IEBSTOC= 0x4920, /*!< Enable DCDC OCP */
+ TFA2_BF_IEBSTPC= 0x4930, /*!< Enable bst peakcur */
+ TFA2_BF_IEBSTVC= 0x4940, /*!< Enable DCDC level 1x */
+ TFA2_BF_IEBST86= 0x4950, /*!< Enable DCDC level 1.14x */
+ TFA2_BF_IEBST93= 0x4960, /*!< Enable DCDC level 1.07x */
+ TFA2_BF_IERCVLD= 0x4970, /*!< Enable rcvldop ready */
+ TFA2_BF_IEOCPL= 0x4980, /*!< Enable ocp alarm left */
+ TFA2_BF_IEOCPR= 0x4990, /*!< Enable ocp alarm right */
+ TFA2_BF_IEMWSRC= 0x49a0, /*!< Enable waits HW I2C settings */
+ TFA2_BF_IEMWCFC= 0x49b0, /*!< Enable man wait cf config */
+ TFA2_BF_IEMWSMU= 0x49c0, /*!< Enable man Audio mute sequence */
+ TFA2_BF_IECFMER= 0x49d0, /*!< Enable cfma err */
+ TFA2_BF_IECFMAC= 0x49e0, /*!< Enable cfma ack */
+ TFA2_BF_IECLKOOR= 0x49f0, /*!< Enable flag_clk_out_of_range */
+ TFA2_BF_IETDMER= 0x4a00, /*!< Enable tdm error */
+ TFA2_BF_IECLPL= 0x4a10, /*!< Enable clip left */
+ TFA2_BF_IECLPR= 0x4a20, /*!< Enable clip right */
+ TFA2_BF_IEOCPM1= 0x4a30, /*!< Enable mic ocpok */
+ TFA2_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA2_BF_IPOPLLS= 0x4c10, /*!< Polarity pll lock */
+ TFA2_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA2_BF_IPOOVDS= 0x4c30, /*!< Polarity OVP alarm */
+ TFA2_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA2_BF_IPOCLKS= 0x4c50, /*!< Polarity clocks stable */
+ TFA2_BF_IPOMTPB= 0x4c60, /*!< Polarity mtp busy */
+ TFA2_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA2_BF_IPOSPKS= 0x4c80, /*!< Polarity speaker error */
+ TFA2_BF_IPOACS= 0x4c90, /*!< Polarity cold started */
+ TFA2_BF_IPOSWS= 0x4ca0, /*!< Polarity amplifier engage */
+ TFA2_BF_IPOWDS= 0x4cb0, /*!< Polarity watchdog */
+ TFA2_BF_IPOAMPS= 0x4cc0, /*!< Polarity enbl amp */
+ TFA2_BF_IPOAREFS= 0x4cd0, /*!< Polarity ref enable */
+ TFA2_BF_IPOADCCR= 0x4ce0, /*!< Polarity Control ADC */
+ TFA2_BF_IPOBODNOK= 0x4cf0, /*!< Polarity BOD */
+ TFA2_BF_IPOBSTCU= 0x4d00, /*!< Polarity DCDC current limiting */
+ TFA2_BF_IPOBSTHI= 0x4d10, /*!< Polarity DCDC active */
+ TFA2_BF_IPOBSTOC= 0x4d20, /*!< Polarity DCDC OCP */
+ TFA2_BF_IPOBSTPC= 0x4d30, /*!< Polarity bst peakcur */
+ TFA2_BF_IPOBSTVC= 0x4d40, /*!< Polarity DCDC level 1x */
+ TFA2_BF_IPOBST86= 0x4d50, /*!< Polarity DCDC level 1.14x */
+ TFA2_BF_IPOBST93= 0x4d60, /*!< Polarity DCDC level 1.07x */
+ TFA2_BF_IPORCVLD= 0x4d70, /*!< Polarity rcvldop ready */
+ TFA2_BF_IPOOCPL= 0x4d80, /*!< Polarity ocp alarm left */
+ TFA2_BF_IPOOCPR= 0x4d90, /*!< Polarity ocp alarm right */
+ TFA2_BF_IPOMWSRC= 0x4da0, /*!< Polarity waits HW I2C settings */
+ TFA2_BF_IPOMWCFC= 0x4db0, /*!< Polarity man wait cf config */
+ TFA2_BF_IPOMWSMU= 0x4dc0, /*!< Polarity man audio mute sequence */
+ TFA2_BF_IPOCFMER= 0x4dd0, /*!< Polarity cfma err */
+ TFA2_BF_IPOCFMAC= 0x4de0, /*!< Polarity cfma ack */
+ TFA2_BF_IPCLKOOR= 0x4df0, /*!< Polarity flag_clk_out_of_range */
+ TFA2_BF_IPOTDMER= 0x4e00, /*!< Polarity tdm error */
+ TFA2_BF_IPOCLPL= 0x4e10, /*!< Polarity clip left */
+ TFA2_BF_IPOCLPR= 0x4e20, /*!< Polarity clip right */
+ TFA2_BF_IPOOCPM= 0x4e30, /*!< Polarity mic ocpok */
+ TFA2_BF_BSSCR = 0x5001, /*!< Battery protection attack Time */
+ TFA2_BF_BSST = 0x5023, /*!< Battery protection threshold voltage level */
+ TFA2_BF_BSSRL = 0x5061, /*!< Battery protection maximum reduction */
+ TFA2_BF_BSSRR = 0x5082, /*!< Battery protection release time */
+ TFA2_BF_BSSHY = 0x50b1, /*!< Battery protection hysteresis */
+ TFA2_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA2_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA2_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA2_BF_INTSMUTE= 0x5110, /*!< Soft mute HW */
+ TFA2_BF_CFSML = 0x5120, /*!< Soft mute FW left */
+ TFA2_BF_CFSMR = 0x5130, /*!< Soft mute FW right */
+ TFA2_BF_HPFBYPL= 0x5140, /*!< Bypass HPF left */
+ TFA2_BF_HPFBYPR= 0x5150, /*!< Bypass HPF right */
+ TFA2_BF_DPSAL = 0x5160, /*!< Enable DPSA left */
+ TFA2_BF_DPSAR = 0x5170, /*!< Enable DPSA right */
+ TFA2_BF_VOL = 0x5187, /*!< FW volume control for primary audio channel */
+ TFA2_BF_HNDSFRCV= 0x5200, /*!< Selection receiver */
+ TFA2_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA2_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA2_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA2_BF_SLOPESET= 0x52e1, /*!< Set slope */
+ TFA2_BF_VOLSEC= 0x5a07, /*!< FW volume control for secondary audio channel */
+ TFA2_BF_SWPROFIL= 0x5a87, /*!< Software profile data */
+ TFA2_BF_DCVO = 0x7002, /*!< Boost voltage */
+ TFA2_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA2_BF_DCCV = 0x7071, /*!< Coil Value */
+ TFA2_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA2_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA2_BF_DCSYNCP= 0x70b2, /*!< DCDC synchronization off + 7 positions */
+ TFA2_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA2_BF_RST = 0x9000, /*!< Reset */
+ TFA2_BF_DMEM = 0x9011, /*!< Target memory */
+ TFA2_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA2_BF_CFINT = 0x9040, /*!< Interrupt - auto clear */
+ TFA2_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA2_BF_REQ = 0x9087, /*!< request for access (8 channels) */
+ TFA2_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA2_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA2_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA2_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA2_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA2_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA2_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA2_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA2_BF_MADD = 0x910f, /*!< Memory address */
+ TFA2_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA2_BF_ERR = 0x9307, /*!< Error flags */
+ TFA2_BF_ACK = 0x9387, /*!< Acknowledge of requests */
+ TFA2_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA2_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA2_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA2_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA2_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA2_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA2_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA2_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA2_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA2_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA2_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA2_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA2_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA2_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA2_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA2_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA2_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA2_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA2_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA2_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA2_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA2_BF_R25CL = 0xf40f, /*!< Ron resistance of left channel speaker coil */
+ TFA2_BF_R25CR = 0xf50f, /*!< Ron resistance of right channel speaker coil */
+} Tfa2BfEnumList_t;
+#define TFA2_NAMETABLE static tfaBfName_t Tfa2DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x91, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x150, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x160, "BODE"}, /* BOD Enable , */\
+ { 0x170, "BODHYS"}, /* BOD Hysteresis , */\
+ { 0x181, "BODFILT"}, /* BOD filter , */\
+ { 0x1a1, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "RCVNS"}, /* Noise shaper selection , */\
+ { 0x1f0, "MANWDE"}, /* Watchdog manager reaction , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b0, "BYPHVBF"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "LDOBYP"}, /* Receiver LDO bypass , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x500, "SSLEFTE"}, /* Enable left channel , */\
+ { 0x510, "SSRIGHTE"}, /* Enable right channel , */\
+ { 0x520, "VSLEFTE"}, /* Voltage sense left , */\
+ { 0x530, "VSRIGHTE"}, /* Voltage sense right , */\
+ { 0x540, "CSLEFTE"}, /* Current sense left , */\
+ { 0x550, "CSRIGHTE"}, /* Current sense right , */\
+ { 0x560, "SSPDME"}, /* Sub-system PDM , */\
+ { 0xd18, "STGAIN"}, /* Side tone gain , */\
+ { 0xda0, "PDMSMUTE"}, /* Side tone soft mute , */\
+ { 0xe06, "SWVSTEP"}, /* Register for the host SW to record the current active vstep, */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "CLKS"}, /* Clocks stable , */\
+ { 0x1060, "MTPB"}, /* MTP busy , */\
+ { 0x1070, "NOCLK"}, /* Lost clock , */\
+ { 0x1080, "SPKS"}, /* Speaker error , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "SWS"}, /* Amplifier engage , */\
+ { 0x10b0, "WDS"}, /* Watchdog , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "STMUTEB"}, /* side tone (un)mute busy , */\
+ { 0x1180, "STMUTE"}, /* side tone mute state , */\
+ { 0x1190, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11a2, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11d0, "TDMERR"}, /* TDM error , */\
+ { 0x11e0, "HAPTIC"}, /* Status haptic driver , */\
+ { 0x1200, "OCPOAPL"}, /* OCPOK pmos A left , */\
+ { 0x1210, "OCPOANL"}, /* OCPOK nmos A left , */\
+ { 0x1220, "OCPOBPL"}, /* OCPOK pmos B left , */\
+ { 0x1230, "OCPOBNL"}, /* OCPOK nmos B left , */\
+ { 0x1240, "CLIPAHL"}, /* Clipping A left to Vddp , */\
+ { 0x1250, "CLIPALL"}, /* Clipping A left to gnd , */\
+ { 0x1260, "CLIPBHL"}, /* Clipping B left to Vddp , */\
+ { 0x1270, "CLIPBLL"}, /* Clipping B left to gnd , */\
+ { 0x1280, "OCPOAPRC"}, /* OCPOK pmos A RCV , */\
+ { 0x1290, "OCPOANRC"}, /* OCPOK nmos A RCV , */\
+ { 0x12a0, "OCPOBPRC"}, /* OCPOK pmos B RCV , */\
+ { 0x12b0, "OCPOBNRC"}, /* OCPOK nmos B RCV , */\
+ { 0x12c0, "RCVLDOR"}, /* RCV LDO regulates , */\
+ { 0x12d0, "RCVLDOBR"}, /* Receiver LDO ready , */\
+ { 0x12e0, "OCDSL"}, /* OCP left amplifier , */\
+ { 0x12f0, "CLIPSL"}, /* Amplifier left clipping , */\
+ { 0x1300, "OCPOAPR"}, /* OCPOK pmos A right , */\
+ { 0x1310, "OCPOANR"}, /* OCPOK nmos A right , */\
+ { 0x1320, "OCPOBPR"}, /* OCPOK pmos B right , */\
+ { 0x1330, "OCPOBNR"}, /* OCPOK nmos B right , */\
+ { 0x1340, "CLIPAHR"}, /* Clipping A right to Vddp , */\
+ { 0x1350, "CLIPALR"}, /* Clipping A right to gnd , */\
+ { 0x1360, "CLIPBHR"}, /* Clipping B left to Vddp , */\
+ { 0x1370, "CLIPBLR"}, /* Clipping B right to gnd , */\
+ { 0x1380, "OCDSR"}, /* OCP right amplifier , */\
+ { 0x1390, "CLIPSR"}, /* Amplifier right clipping , */\
+ { 0x13a0, "OCPOKMC"}, /* OCPOK MICVDD , */\
+ { 0x13b0, "MANALARM"}, /* Alarm state , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "MANWAIT2"}, /* Wait CF config , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1400, "SPKSL"}, /* Left speaker status , */\
+ { 0x1410, "SPKSR"}, /* Right speaker status , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x2003, "TDMUC"}, /* Usecase setting , */\
+ { 0x2040, "TDME"}, /* Enable interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "TDMTXUS1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "TDMTXUS2"}, /* Format unused slots DIO2 , */\
+ { 0x2310, "TDMLE"}, /* Control audio left , */\
+ { 0x2320, "TDMRE"}, /* Control audio right , */\
+ { 0x2340, "TDMVSRE"}, /* Control voltage sense right , */\
+ { 0x2350, "TDMCSRE"}, /* Control current sense right , */\
+ { 0x2360, "TDMVSLE"}, /* Voltage sense left control , */\
+ { 0x2370, "TDMCSLE"}, /* Current sense left control , */\
+ { 0x2380, "TDMCFRE"}, /* DSP out right control , */\
+ { 0x2390, "TDMCFLE"}, /* DSP out left control , */\
+ { 0x23a0, "TDMCF3E"}, /* AEC ref left control , */\
+ { 0x23b0, "TDMCF4E"}, /* AEC ref right control , */\
+ { 0x23c0, "TDMPD1E"}, /* PDM 1 control , */\
+ { 0x23d0, "TDMPD2E"}, /* PDM 2 control , */\
+ { 0x2421, "TDMLIO"}, /* IO audio left , */\
+ { 0x2441, "TDMRIO"}, /* IO audio right , */\
+ { 0x2481, "TDMVSRIO"}, /* IO voltage sense right , */\
+ { 0x24a1, "TDMCSRIO"}, /* IO current sense right , */\
+ { 0x24c1, "TDMVSLIO"}, /* IO voltage sense left , */\
+ { 0x24e1, "TDMCSLIO"}, /* IO current sense left , */\
+ { 0x2501, "TDMCFRIO"}, /* IO dspout right , */\
+ { 0x2521, "TDMCFLIO"}, /* IO dspout left , */\
+ { 0x2541, "TDMCF3IO"}, /* IO AEC ref left control , */\
+ { 0x2561, "TDMCF4IO"}, /* IO AEC ref right control , */\
+ { 0x2581, "TDMPD1IO"}, /* IO pdm1 , */\
+ { 0x25a1, "TDMPD2IO"}, /* IO pdm2 , */\
+ { 0x2643, "TDMLS"}, /* Position audio left , */\
+ { 0x2683, "TDMRS"}, /* Position audio right , */\
+ { 0x2703, "TDMVSRS"}, /* Position voltage sense right , */\
+ { 0x2743, "TDMCSRS"}, /* Position current sense right , */\
+ { 0x2783, "TDMVSLS"}, /* Position voltage sense left , */\
+ { 0x27c3, "TDMCSLS"}, /* Position current sense left , */\
+ { 0x2803, "TDMCFRS"}, /* Position dspout right , */\
+ { 0x2843, "TDMCFLS"}, /* Position dspout left , */\
+ { 0x2883, "TDMCF3S"}, /* Position AEC ref left control , */\
+ { 0x28c3, "TDMCF4S"}, /* Position AEC ref right control , */\
+ { 0x2903, "TDMPD1S"}, /* Position pdm1 , */\
+ { 0x2943, "TDMPD2S"}, /* Position pdm2 , */\
+ { 0x3100, "PDMSM"}, /* PDM control , */\
+ { 0x3111, "PDMSTSEL"}, /* Side tone input , */\
+ { 0x3130, "PDMLSEL"}, /* PDM data selection for left channel during PDM direct mode, */\
+ { 0x3140, "PDMRSEL"}, /* PDM data selection for right channel during PDM direct mode, */\
+ { 0x3150, "MICVDDE"}, /* Enable MICVDD , */\
+ { 0x3201, "PDMCLRAT"}, /* PDM BCK/Fs ratio , */\
+ { 0x3223, "PDMGAIN"}, /* PDM gain , */\
+ { 0x3263, "PDMOSEL"}, /* PDM output selection - RE/FE data combination , */\
+ { 0x32a0, "SELCFHAPD"}, /* Select the source for haptic data output (not for customer), */\
+ { 0x3307, "HAPTIME"}, /* Duration (ms) , */\
+ { 0x3387, "HAPLEVEL"}, /* DC value (FFS) , */\
+ { 0x3403, "GPIODIN"}, /* Receiving value , */\
+ { 0x3500, "GPIOCTRL"}, /* GPIO master control over GPIO1/2 ports (not for customer), */\
+ { 0x3513, "GPIOCONF"}, /* Configuration , */\
+ { 0x3553, "GPIODOUT"}, /* Transmitting value , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTPLLS"}, /* Status PLL lock , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOVDS"}, /* Status OVP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTCLKS"}, /* Status clocks stable , */\
+ { 0x4060, "ISTMTPB"}, /* Status MTP busy , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTSPKS"}, /* Status speaker error , */\
+ { 0x4090, "ISTACS"}, /* Status cold start , */\
+ { 0x40a0, "ISTSWS"}, /* Status amplifier engage , */\
+ { 0x40b0, "ISTWDS"}, /* Status watchdog , */\
+ { 0x40c0, "ISTAMPS"}, /* Status amplifier enable , */\
+ { 0x40d0, "ISTAREFS"}, /* Status Ref enable , */\
+ { 0x40e0, "ISTADCCR"}, /* Status Control ADC , */\
+ { 0x40f0, "ISTBODNOK"}, /* Status BOD , */\
+ { 0x4100, "ISTBSTCU"}, /* Status DCDC current limiting , */\
+ { 0x4110, "ISTBSTHI"}, /* Status DCDC active , */\
+ { 0x4120, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4130, "ISTBSTPKCUR"}, /* Status bst peakcur , */\
+ { 0x4140, "ISTBSTVC"}, /* Status DCDC level 1x , */\
+ { 0x4150, "ISTBST86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "ISTBST93"}, /* Status DCDC level 1.07x , */\
+ { 0x4170, "ISTRCVLD"}, /* Status rcvldop ready , */\
+ { 0x4180, "ISTOCPL"}, /* Status ocp alarm left , */\
+ { 0x4190, "ISTOCPR"}, /* Status ocp alarm right , */\
+ { 0x41a0, "ISTMWSRC"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "ISTMWCFC"}, /* Status waits CF config , */\
+ { 0x41c0, "ISTMWSMU"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x41e0, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x41f0, "ISTCLKOOR"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4210, "ISTCLPL"}, /* Status clip left , */\
+ { 0x4220, "ISTCLPR"}, /* Status clip right , */\
+ { 0x4230, "ISTOCPM"}, /* Status mic ocpok , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLPLLS"}, /* Clear PLL lock , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOVDS"}, /* Clear OVP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLCLKS"}, /* Clear clocks stable , */\
+ { 0x4460, "ICLMTPB"}, /* Clear mtp busy , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLSPKS"}, /* Clear speaker error , */\
+ { 0x4490, "ICLACS"}, /* Clear cold started , */\
+ { 0x44a0, "ICLSWS"}, /* Clear amplifier engage , */\
+ { 0x44b0, "ICLWDS"}, /* Clear watchdog , */\
+ { 0x44c0, "ICLAMPS"}, /* Clear enbl amp , */\
+ { 0x44d0, "ICLAREFS"}, /* Clear ref enable , */\
+ { 0x44e0, "ICLADCCR"}, /* Clear control ADC , */\
+ { 0x44f0, "ICLBODNOK"}, /* Clear BOD , */\
+ { 0x4500, "ICLBSTCU"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "ICLBSTHI"}, /* Clear DCDC active , */\
+ { 0x4520, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4530, "ICLBSTPC"}, /* Clear bst peakcur , */\
+ { 0x4540, "ICLBSTVC"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "ICLBST86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "ICLBST93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4570, "ICLRCVLD"}, /* Clear rcvldop ready , */\
+ { 0x4580, "ICLOCPL"}, /* Clear ocp alarm left , */\
+ { 0x4590, "ICLOCPR"}, /* Clear ocp alarm right , */\
+ { 0x45a0, "ICLMWSRC"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "ICLMWCFC"}, /* Clear wait cf config , */\
+ { 0x45c0, "ICLMWSMU"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x45e0, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x45f0, "ICLCLKOOR"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4610, "ICLCLPL"}, /* Clear clip left , */\
+ { 0x4620, "ICLCLPR"}, /* Clear clip right , */\
+ { 0x4630, "ICLOCPM"}, /* Clear mic ocpok , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEPLLS"}, /* Enable pll lock , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOVDS"}, /* Enable OVP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IECLKS"}, /* Enable clocks stable , */\
+ { 0x4860, "IEMTPB"}, /* Enable mtp busy , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IESPKS"}, /* Enable speaker error , */\
+ { 0x4890, "IEACS"}, /* Enable cold started , */\
+ { 0x48a0, "IESWS"}, /* Enable amplifier engage , */\
+ { 0x48b0, "IEWDS"}, /* Enable watchdog , */\
+ { 0x48c0, "IEAMPS"}, /* Enable enbl amp , */\
+ { 0x48d0, "IEAREFS"}, /* Enable ref enable , */\
+ { 0x48e0, "IEADCCR"}, /* Enable Control ADC , */\
+ { 0x48f0, "IEBODNOK"}, /* Enable BOD , */\
+ { 0x4900, "IEBSTCU"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "IEBSTHI"}, /* Enable DCDC active , */\
+ { 0x4920, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4930, "IEBSTPC"}, /* Enable bst peakcur , */\
+ { 0x4940, "IEBSTVC"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "IEBST86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "IEBST93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4970, "IERCVLD"}, /* Enable rcvldop ready , */\
+ { 0x4980, "IEOCPL"}, /* Enable ocp alarm left , */\
+ { 0x4990, "IEOCPR"}, /* Enable ocp alarm right , */\
+ { 0x49a0, "IEMWSRC"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "IEMWCFC"}, /* Enable man wait cf config , */\
+ { 0x49c0, "IEMWSMU"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "IECFMER"}, /* Enable cfma err , */\
+ { 0x49e0, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x49f0, "IECLKOOR"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4a10, "IECLPL"}, /* Enable clip left , */\
+ { 0x4a20, "IECLPR"}, /* Enable clip right , */\
+ { 0x4a30, "IEOCPM1"}, /* Enable mic ocpok , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOPLLS"}, /* Polarity pll lock , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOVDS"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOCLKS"}, /* Polarity clocks stable , */\
+ { 0x4c60, "IPOMTPB"}, /* Polarity mtp busy , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOSPKS"}, /* Polarity speaker error , */\
+ { 0x4c90, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4ca0, "IPOSWS"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "IPOWDS"}, /* Polarity watchdog , */\
+ { 0x4cc0, "IPOAMPS"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "IPOAREFS"}, /* Polarity ref enable , */\
+ { 0x4ce0, "IPOADCCR"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "IPOBODNOK"}, /* Polarity BOD , */\
+ { 0x4d00, "IPOBSTCU"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "IPOBSTHI"}, /* Polarity DCDC active , */\
+ { 0x4d20, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "IPOBSTPC"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "IPOBSTVC"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "IPOBST86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "IPOBST93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d70, "IPORCVLD"}, /* Polarity rcvldop ready , */\
+ { 0x4d80, "IPOOCPL"}, /* Polarity ocp alarm left , */\
+ { 0x4d90, "IPOOCPR"}, /* Polarity ocp alarm right , */\
+ { 0x4da0, "IPOMWSRC"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "IPOMWCFC"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "IPOMWSMU"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4de0, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4df0, "IPCLKOOR"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4e10, "IPOCLPL"}, /* Polarity clip left , */\
+ { 0x4e20, "IPOCLPR"}, /* Polarity clip right , */\
+ { 0x4e30, "IPOOCPM"}, /* Polarity mic ocpok , */\
+ { 0x5001, "BSSCR"}, /* Battery protection attack Time , */\
+ { 0x5023, "BSST"}, /* Battery protection threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery protection maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery protection release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery protection hysteresis , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5110, "INTSMUTE"}, /* Soft mute HW , */\
+ { 0x5120, "CFSML"}, /* Soft mute FW left , */\
+ { 0x5130, "CFSMR"}, /* Soft mute FW right , */\
+ { 0x5140, "HPFBYPL"}, /* Bypass HPF left , */\
+ { 0x5150, "HPFBYPR"}, /* Bypass HPF right , */\
+ { 0x5160, "DPSAL"}, /* Enable DPSA left , */\
+ { 0x5170, "DPSAR"}, /* Enable DPSA right , */\
+ { 0x5187, "VOL"}, /* FW volume control for primary audio channel , */\
+ { 0x5200, "HNDSFRCV"}, /* Selection receiver , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e1, "SLOPESET"}, /* Set slope , */\
+ { 0x5a07, "VOLSEC"}, /* FW volume control for secondary audio channel , */\
+ { 0x5a87, "SWPROFIL"}, /* Software profile data , */\
+ { 0x7002, "DCVO"}, /* Boost voltage , */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Coil Value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70b2, "DCSYNCP"}, /* DCDC synchronization off + 7 positions , */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x9000, "RST"}, /* Reset , */\
+ { 0x9011, "DMEM"}, /* Target memory , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* Memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* Error flags , */\
+ { 0x9387, "ACK"}, /* Acknowledge of requests , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf40f, "R25CL"}, /* Ron resistance of left channel speaker coil , */\
+ { 0xf50f, "R25CR"}, /* Ron resistance of right channel speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA2_BITNAMETABLE static tfaBfName_t Tfa2BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x91, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x101, "vamp_sel"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "enbl_osc1m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x150, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x160, "enbl_bod"}, /* BOD Enable , */\
+ { 0x170, "enbl_bod_hyst"}, /* BOD Hysteresis , */\
+ { 0x181, "bod_delay"}, /* BOD filter , */\
+ { 0x1a1, "bod_lvlsel"}, /* BOD threshold , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "pwm_sel_rcv_ns"}, /* Noise shaper selection , */\
+ { 0x1f0, "man_enbl_watchdog"}, /* Watchdog manager reaction , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b0, "bypass_hvbat_filter"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "ctrl_rcvldop_bypass"}, /* Receiver LDO bypass , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x500, "enbl_spkr_ss_left"}, /* Enable left channel , */\
+ { 0x510, "enbl_spkr_ss_right"}, /* Enable right channel , */\
+ { 0x520, "enbl_volsense_left"}, /* Voltage sense left , */\
+ { 0x530, "enbl_volsense_right"}, /* Voltage sense right , */\
+ { 0x540, "enbl_cursense_left"}, /* Current sense left , */\
+ { 0x550, "enbl_cursense_right"}, /* Current sense right , */\
+ { 0x560, "enbl_pdm_ss"}, /* Sub-system PDM , */\
+ { 0xd00, "side_tone_gain_sel"}, /* PDM side tone gain selector , */\
+ { 0xd18, "side_tone_gain"}, /* Side tone gain , */\
+ { 0xda0, "mute_side_tone"}, /* Side tone soft mute , */\
+ { 0xe06, "ctrl_digtoana"}, /* Register for the host SW to record the current active vstep, */\
+ { 0xe70, "enbl_cmfb_left"}, /* Current sense common mode feedback control for left channel, */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1060, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1080, "flag_cf_speakererror"}, /* Speaker error , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10b0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_soft_mute_busy"}, /* side tone (un)mute busy , */\
+ { 0x1180, "flag_soft_mute_state"}, /* side tone mute state , */\
+ { 0x1190, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11a2, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11d0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x11e0, "flag_haptic_busy"}, /* Status haptic driver , */\
+ { 0x1200, "flag_ocpokap_left"}, /* OCPOK pmos A left , */\
+ { 0x1210, "flag_ocpokan_left"}, /* OCPOK nmos A left , */\
+ { 0x1220, "flag_ocpokbp_left"}, /* OCPOK pmos B left , */\
+ { 0x1230, "flag_ocpokbn_left"}, /* OCPOK nmos B left , */\
+ { 0x1240, "flag_clipa_high_left"}, /* Clipping A left to Vddp , */\
+ { 0x1250, "flag_clipa_low_left"}, /* Clipping A left to gnd , */\
+ { 0x1260, "flag_clipb_high_left"}, /* Clipping B left to Vddp , */\
+ { 0x1270, "flag_clipb_low_left"}, /* Clipping B left to gnd , */\
+ { 0x1280, "flag_ocpokap_rcv"}, /* OCPOK pmos A RCV , */\
+ { 0x1290, "flag_ocpokan_rcv"}, /* OCPOK nmos A RCV , */\
+ { 0x12a0, "flag_ocpokbp_rcv"}, /* OCPOK pmos B RCV , */\
+ { 0x12b0, "flag_ocpokbn_rcv"}, /* OCPOK nmos B RCV , */\
+ { 0x12c0, "flag_rcvldop_ready"}, /* RCV LDO regulates , */\
+ { 0x12d0, "flag_rcvldop_bypassready"}, /* Receiver LDO ready , */\
+ { 0x12e0, "flag_ocp_alarm_left"}, /* OCP left amplifier , */\
+ { 0x12f0, "flag_clip_left"}, /* Amplifier left clipping , */\
+ { 0x1300, "flag_ocpokap_right"}, /* OCPOK pmos A right , */\
+ { 0x1310, "flag_ocpokan_right"}, /* OCPOK nmos A right , */\
+ { 0x1320, "flag_ocpokbp_right"}, /* OCPOK pmos B right , */\
+ { 0x1330, "flag_ocpokbn_right"}, /* OCPOK nmos B right , */\
+ { 0x1340, "flag_clipa_high_right"}, /* Clipping A right to Vddp , */\
+ { 0x1350, "flag_clipa_low_right"}, /* Clipping A right to gnd , */\
+ { 0x1360, "flag_clipb_high_right"}, /* Clipping B left to Vddp , */\
+ { 0x1370, "flag_clipb_low_right"}, /* Clipping B right to gnd , */\
+ { 0x1380, "flag_ocp_alarm_right"}, /* OCP right amplifier , */\
+ { 0x1390, "flag_clip_right"}, /* Amplifier right clipping , */\
+ { 0x13a0, "flag_mic_ocpok"}, /* OCPOK MICVDD , */\
+ { 0x13b0, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "flag_man_wait_cf_config"}, /* Wait CF config , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1400, "flag_cf_speakererror_left"}, /* Left speaker status , */\
+ { 0x1410, "flag_cf_speakererror_right"}, /* Right speaker status , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x2003, "tdm_usecase"}, /* Usecase setting , */\
+ { 0x2040, "tdm_enable"}, /* Enable interface , */\
+ { 0x2050, "tdm_mode"}, /* Slave/master , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "tdm_txdata_format_unused_slot_sd1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "tdm_txdata_format_unused_slot_sd2"}, /* Format unused slots DIO2 , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control gainin (not used in DSP) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio left , */\
+ { 0x2320, "tdm_sink2_enable"}, /* Control audio right , */\
+ { 0x2330, "tdm_source0_enable"}, /* Control gainout (not used in DSP) , */\
+ { 0x2340, "tdm_source1_enable"}, /* Control voltage sense right , */\
+ { 0x2350, "tdm_source2_enable"}, /* Control current sense right , */\
+ { 0x2360, "tdm_source3_enable"}, /* Voltage sense left control , */\
+ { 0x2370, "tdm_source4_enable"}, /* Current sense left control , */\
+ { 0x2380, "tdm_source5_enable"}, /* DSP out right control , */\
+ { 0x2390, "tdm_source6_enable"}, /* DSP out left control , */\
+ { 0x23a0, "tdm_source7_enable"}, /* AEC ref left control , */\
+ { 0x23b0, "tdm_source8_enable"}, /* AEC ref right control , */\
+ { 0x23c0, "tdm_source9_enable"}, /* PDM 1 control , */\
+ { 0x23d0, "tdm_source10_enable"}, /* PDM 2 control , */\
+ { 0x2401, "tdm_sink0_io"}, /* IO gainin (not used in DSP) , */\
+ { 0x2421, "tdm_sink1_io"}, /* IO audio left , */\
+ { 0x2441, "tdm_sink2_io"}, /* IO audio right , */\
+ { 0x2461, "tdm_source0_io"}, /* IO gainout (not used in DSP) , */\
+ { 0x2481, "tdm_source1_io"}, /* IO voltage sense right , */\
+ { 0x24a1, "tdm_source2_io"}, /* IO current sense right , */\
+ { 0x24c1, "tdm_source3_io"}, /* IO voltage sense left , */\
+ { 0x24e1, "tdm_source4_io"}, /* IO current sense left , */\
+ { 0x2501, "tdm_source5_io"}, /* IO dspout right , */\
+ { 0x2521, "tdm_source6_io"}, /* IO dspout left , */\
+ { 0x2541, "tdm_source7_io"}, /* IO AEC ref left control , */\
+ { 0x2561, "tdm_source8_io"}, /* IO AEC ref right control , */\
+ { 0x2581, "tdm_source9_io"}, /* IO pdm1 , */\
+ { 0x25a1, "tdm_source10_io"}, /* IO pdm2 , */\
+ { 0x2603, "tdm_sink0_slot"}, /* Position gainin (not used in DSP) , */\
+ { 0x2643, "tdm_sink1_slot"}, /* Position audio left , */\
+ { 0x2683, "tdm_sink2_slot"}, /* Position audio right , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Position gainout (not used in DSP) , */\
+ { 0x2703, "tdm_source1_slot"}, /* Position voltage sense right , */\
+ { 0x2743, "tdm_source2_slot"}, /* Position current sense right , */\
+ { 0x2783, "tdm_source3_slot"}, /* Position voltage sense left , */\
+ { 0x27c3, "tdm_source4_slot"}, /* Position current sense left , */\
+ { 0x2803, "tdm_source5_slot"}, /* Position dspout right , */\
+ { 0x2843, "tdm_source6_slot"}, /* Position dspout left , */\
+ { 0x2883, "tdm_source7_slot"}, /* Position AEC ref left control , */\
+ { 0x28c3, "tdm_source8_slot"}, /* Position AEC ref right control , */\
+ { 0x2903, "tdm_source9_slot"}, /* Position pdm1 , */\
+ { 0x2943, "tdm_source10_slot"}, /* Position pdm2 , */\
+ { 0x3100, "pdm_mode"}, /* PDM control , */\
+ { 0x3111, "pdm_side_tone_sel"}, /* Side tone input , */\
+ { 0x3130, "pdm_left_sel"}, /* PDM data selection for left channel during PDM direct mode, */\
+ { 0x3140, "pdm_right_sel"}, /* PDM data selection for right channel during PDM direct mode, */\
+ { 0x3150, "enbl_micvdd"}, /* Enable MICVDD , */\
+ { 0x3160, "bypass_micvdd_ocp"}, /* Bypass control for the MICVDD OCP flag processing , */\
+ { 0x3201, "pdm_nbck"}, /* PDM BCK/Fs ratio , */\
+ { 0x3223, "pdm_gain"}, /* PDM gain , */\
+ { 0x3263, "sel_pdm_out_data"}, /* PDM output selection - RE/FE data combination , */\
+ { 0x32a0, "sel_cf_haptic_data"}, /* Select the source for haptic data output (not for customer), */\
+ { 0x3307, "haptic_duration"}, /* Duration (ms) , */\
+ { 0x3387, "haptic_data"}, /* DC value (FFS) , */\
+ { 0x3403, "gpio_datain"}, /* Receiving value , */\
+ { 0x3500, "gpio_ctrl"}, /* GPIO master control over GPIO1/2 ports (not for customer), */\
+ { 0x3513, "gpio_dir"}, /* Configuration , */\
+ { 0x3553, "gpio_dataout"}, /* Transmitting value , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_pll_lock"}, /* Status PLL lock , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ovpok"}, /* Status OVP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_clocks_stable"}, /* Status clocks stable , */\
+ { 0x4060, "int_out_flag_mtp_busy"}, /* Status MTP busy , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cf_speakererror"}, /* Status speaker error , */\
+ { 0x4090, "int_out_flag_cold_started"}, /* Status cold start , */\
+ { 0x40a0, "int_out_flag_engage"}, /* Status amplifier engage , */\
+ { 0x40b0, "int_out_flag_watchdog_reset"}, /* Status watchdog , */\
+ { 0x40c0, "int_out_flag_enbl_amp"}, /* Status amplifier enable , */\
+ { 0x40d0, "int_out_flag_enbl_ref"}, /* Status Ref enable , */\
+ { 0x40e0, "int_out_flag_adc10_ready"}, /* Status Control ADC , */\
+ { 0x40f0, "int_out_flag_bod_vddd_nok"}, /* Status BOD , */\
+ { 0x4100, "int_out_flag_bst_bstcur"}, /* Status DCDC current limiting , */\
+ { 0x4110, "int_out_flag_bst_hiz"}, /* Status DCDC active , */\
+ { 0x4120, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4130, "int_out_flag_bst_peakcur"}, /* Status bst peakcur , */\
+ { 0x4140, "int_out_flag_bst_voutcomp"}, /* Status DCDC level 1x , */\
+ { 0x4150, "int_out_flag_bst_voutcomp86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "int_out_flag_bst_voutcomp93"}, /* Status DCDC level 1.07x , */\
+ { 0x4170, "int_out_flag_rcvldop_ready"}, /* Status rcvldop ready , */\
+ { 0x4180, "int_out_flag_ocp_alarm_left"}, /* Status ocp alarm left , */\
+ { 0x4190, "int_out_flag_ocp_alarm_right"}, /* Status ocp alarm right , */\
+ { 0x41a0, "int_out_flag_man_wait_src_settings"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "int_out_flag_man_wait_cf_config"}, /* Status waits CF config , */\
+ { 0x41c0, "int_out_flag_man_start_mute_audio"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x41e0, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x41f0, "int_out_flag_clk_out_of_range"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4210, "int_out_flag_clip_left"}, /* Status clip left , */\
+ { 0x4220, "int_out_flag_clip_right"}, /* Status clip right , */\
+ { 0x4230, "int_out_flag_mic_ocpok"}, /* Status mic ocpok , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_pll_lock"}, /* Clear PLL lock , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ovpok"}, /* Clear OVP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_clocks_stable"}, /* Clear clocks stable , */\
+ { 0x4460, "int_in_flag_mtp_busy"}, /* Clear mtp busy , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cf_speakererror"}, /* Clear speaker error , */\
+ { 0x4490, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44a0, "int_in_flag_engage"}, /* Clear amplifier engage , */\
+ { 0x44b0, "int_in_flag_watchdog_reset"}, /* Clear watchdog , */\
+ { 0x44c0, "int_in_flag_enbl_amp"}, /* Clear enbl amp , */\
+ { 0x44d0, "int_in_flag_enbl_ref"}, /* Clear ref enable , */\
+ { 0x44e0, "int_in_flag_adc10_ready"}, /* Clear control ADC , */\
+ { 0x44f0, "int_in_flag_bod_vddd_nok"}, /* Clear BOD , */\
+ { 0x4500, "int_in_flag_bst_bstcur"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "int_in_flag_bst_hiz"}, /* Clear DCDC active , */\
+ { 0x4520, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4530, "int_in_flag_bst_peakcur"}, /* Clear bst peakcur , */\
+ { 0x4540, "int_in_flag_bst_voutcomp"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "int_in_flag_bst_voutcomp86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "int_in_flag_bst_voutcomp93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4570, "int_in_flag_rcvldop_ready"}, /* Clear rcvldop ready , */\
+ { 0x4580, "int_in_flag_ocp_alarm_left"}, /* Clear ocp alarm left , */\
+ { 0x4590, "int_in_flag_ocp_alarm_right"}, /* Clear ocp alarm right , */\
+ { 0x45a0, "int_in_flag_man_wait_src_settings"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "int_in_flag_man_wait_cf_config"}, /* Clear wait cf config , */\
+ { 0x45c0, "int_in_flag_man_start_mute_audio"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x45e0, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x45f0, "int_in_flag_clk_out_of_range"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4610, "int_in_flag_clip_left"}, /* Clear clip left , */\
+ { 0x4620, "int_in_flag_clip_right"}, /* Clear clip right , */\
+ { 0x4630, "int_in_flag_mic_ocpok"}, /* Clear mic ocpok , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_pll_lock"}, /* Enable pll lock , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ovpok"}, /* Enable OVP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_clocks_stable"}, /* Enable clocks stable , */\
+ { 0x4860, "int_enable_flag_mtp_busy"}, /* Enable mtp busy , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cf_speakererror"}, /* Enable speaker error , */\
+ { 0x4890, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48a0, "int_enable_flag_engage"}, /* Enable amplifier engage , */\
+ { 0x48b0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog , */\
+ { 0x48c0, "int_enable_flag_enbl_amp"}, /* Enable enbl amp , */\
+ { 0x48d0, "int_enable_flag_enbl_ref"}, /* Enable ref enable , */\
+ { 0x48e0, "int_enable_flag_adc10_ready"}, /* Enable Control ADC , */\
+ { 0x48f0, "int_enable_flag_bod_vddd_nok"}, /* Enable BOD , */\
+ { 0x4900, "int_enable_flag_bst_bstcur"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "int_enable_flag_bst_hiz"}, /* Enable DCDC active , */\
+ { 0x4920, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4930, "int_enable_flag_bst_peakcur"}, /* Enable bst peakcur , */\
+ { 0x4940, "int_enable_flag_bst_voutcomp"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "int_enable_flag_bst_voutcomp86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "int_enable_flag_bst_voutcomp93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4970, "int_enable_flag_rcvldop_ready"}, /* Enable rcvldop ready , */\
+ { 0x4980, "int_enable_flag_ocp_alarm_left"}, /* Enable ocp alarm left , */\
+ { 0x4990, "int_enable_flag_ocp_alarm_right"}, /* Enable ocp alarm right , */\
+ { 0x49a0, "int_enable_flag_man_wait_src_settings"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "int_enable_flag_man_wait_cf_config"}, /* Enable man wait cf config , */\
+ { 0x49c0, "int_enable_flag_man_start_mute_audio"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x49e0, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x49f0, "int_enable_flag_clk_out_of_range"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4a10, "int_enable_flag_clip_left"}, /* Enable clip left , */\
+ { 0x4a20, "int_enable_flag_clip_right"}, /* Enable clip right , */\
+ { 0x4a30, "int_enable_flag_mic_ocpok"}, /* Enable mic ocpok , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_pll_lock"}, /* Polarity pll lock , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ovpok"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_clocks_stable"}, /* Polarity clocks stable , */\
+ { 0x4c60, "int_polarity_flag_mtp_busy"}, /* Polarity mtp busy , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cf_speakererror"}, /* Polarity speaker error , */\
+ { 0x4c90, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4ca0, "int_polarity_flag_engage"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog , */\
+ { 0x4cc0, "int_polarity_flag_enbl_amp"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "int_polarity_flag_enbl_ref"}, /* Polarity ref enable , */\
+ { 0x4ce0, "int_polarity_flag_adc10_ready"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity BOD , */\
+ { 0x4d00, "int_polarity_flag_bst_bstcur"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "int_polarity_flag_bst_hiz"}, /* Polarity DCDC active , */\
+ { 0x4d20, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "int_polarity_flag_bst_peakcur"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "int_polarity_flag_bst_voutcomp"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "int_polarity_flag_bst_voutcomp86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "int_polarity_flag_bst_voutcomp93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d70, "int_polarity_flag_rcvldop_ready"}, /* Polarity rcvldop ready , */\
+ { 0x4d80, "int_polarity_flag_ocp_alarm_left"}, /* Polarity ocp alarm left , */\
+ { 0x4d90, "int_polarity_flag_ocp_alarm_right"}, /* Polarity ocp alarm right , */\
+ { 0x4da0, "int_polarity_flag_man_wait_src_settings"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "int_polarity_flag_man_wait_cf_config"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "int_polarity_flag_man_start_mute_audio"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4de0, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4df0, "int_polarity_flag_clk_out_of_range"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4e10, "int_polarity_flag_clip_left"}, /* Polarity clip left , */\
+ { 0x4e20, "int_polarity_flag_clip_right"}, /* Polarity clip right , */\
+ { 0x4e30, "int_polarity_flag_mic_ocpok"}, /* Polarity mic ocpok , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery protection attack Time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery protection threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery protection maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery protection release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery protection hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5110, "soft_mute"}, /* Soft mute HW , */\
+ { 0x5120, "cf_mute_left"}, /* Soft mute FW left , */\
+ { 0x5130, "cf_mute_right"}, /* Soft mute FW right , */\
+ { 0x5140, "bypass_hp_left"}, /* Bypass HPF left , */\
+ { 0x5150, "bypass_hp_right"}, /* Bypass HPF right , */\
+ { 0x5160, "enbl_dpsa_left"}, /* Enable DPSA left , */\
+ { 0x5170, "enbl_dpsa_right"}, /* Enable DPSA right , */\
+ { 0x5187, "cf_volume"}, /* FW volume control for primary audio channel , */\
+ { 0x5200, "ctrl_rcv"}, /* Selection receiver , */\
+ { 0x5210, "ctrl_rcv_fb_100k"}, /* Selection of feedback resistor for receiver mode (not for customer), */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e1, "ctrl_slope"}, /* Set slope , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for battery protection, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "enbl_low_latency"}, /* CF low latency outputs for add module , */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5420, "fb_hz"}, /* Feedback resistor set to high ohmic , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5581, "dpsa_drive"}, /* Control of the number of power stage sections, total of 4 sections. Each section is 1/4 of the total power stages., */\
+ { 0x560a, "enbl_amp_left"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually - Left channel, */\
+ { 0x56b0, "enbl_engage_left"}, /* Enables/engage power stage and control loop - left channel, */\
+ { 0x570a, "enbl_amp_right"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually - Right channel, */\
+ { 0x57b0, "enbl_engage_right"}, /* Enables/engage power stage and control loop - right channel, */\
+ { 0x5800, "hard_mute_left"}, /* Hard mute - PWM module left , */\
+ { 0x5810, "hard_mute_right"}, /* Hard mute - PWM module right , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5830, "pwm_bitlength"}, /* PWM bit length in noise shaper , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58b0, "enbl_pwm_phase_shift_left"}, /* Control for pwm phase shift, inverted function - left channel, */\
+ { 0x58c0, "enbl_pwm_phase_shift_right"}, /* Control for pwm phase shift - right channel , */\
+ { 0x5900, "ctrl_rcvldop_pulldown"}, /* Pulldown of LDO (2.7V) , */\
+ { 0x5910, "ctrl_rcvldop_test_comp"}, /* Enable testing of LDO comparator , */\
+ { 0x5920, "ctrl_rcvldop_test_loadedldo"}, /* Load connected to rcvldo , */\
+ { 0x5930, "enbl_rcvldop"}, /* Enables the LDO (2.7) , */\
+ { 0x5a07, "cf_volume_sec"}, /* FW volume control for secondary audio channel , */\
+ { 0x5a87, "sw_profile"}, /* Software profile data , */\
+ { 0x7002, "boost_volt"}, /* Boost voltage , */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_coil_value"}, /* Coil Value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70b2, "dcdc_synchronisation"}, /* DCDC synchronization off + 7 positions , */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7332, "bst_freq"}, /* DCDC bost frequency control , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8040, "cs_dc_offset"}, /* Current sense decimator offset control , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8110, "invertpwm_left"}, /* Current sense common mode feedback pwm invert control for left channel, */\
+ { 0x8122, "cmfb_gain_left"}, /* Current sense common mode feedback control gain for left channel, */\
+ { 0x8154, "cmfb_offset_left"}, /* Current sense common mode feedback control offset for left channel, */\
+ { 0x8200, "enbl_cmfb_right"}, /* Current sense common mode feedback control for right channel, */\
+ { 0x8210, "invertpwm_right"}, /* Current sense common mode feedback pwm invert control for right channel, */\
+ { 0x8222, "cmfb_gain_right"}, /* Current sense common mode feedback control gain for right channel, */\
+ { 0x8254, "cmfb_offset_right"}, /* Current sense common mode feedback control offset for right channel, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8600, "enbl_cs_adc_left"}, /* Enable current sense ADC , */\
+ { 0x8610, "enbl_cs_inn1_left"}, /* Enable connection of current sense negative1 , */\
+ { 0x8630, "enbl_cs_inp1_left"}, /* Enable connection of current sense positive1 , */\
+ { 0x8650, "enbl_cs_ldo_left"}, /* Enable current sense LDO , */\
+ { 0x8660, "enbl_cs_nofloating_n_left"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8670, "enbl_cs_nofloating_p_left"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8680, "enbl_cs_vbatldo_left"}, /* Enable of current sense LDO , */\
+ { 0x8700, "enbl_cs_adc_right"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1_right"}, /* Enable connection of current sense negative1 , */\
+ { 0x8730, "enbl_cs_inp1_right"}, /* Enable connection of current sense positive1 , */\
+ { 0x8750, "enbl_cs_ldo_right"}, /* Enable current sense LDO , */\
+ { 0x8760, "enbl_cs_nofloating_n_right"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8770, "enbl_cs_nofloating_p_right"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8780, "enbl_cs_vbatldo_right"}, /* Enable of current sense LDO , */\
+ { 0x8800, "volsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0x8810, "volsense_dc_offset"}, /* Voltage sense decimator offset control , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset , */\
+ { 0x9011, "cf_dmem"}, /* Target memory , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* Memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* Error flags , */\
+ { 0x9387, "cf_ack"}, /* Acknowledge of requests , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0x980f, "ivt_addr0_msb"}, /* Coolflux interrupt vector table address0 MSB , */\
+ { 0x990f, "ivt_addr0_lsb"}, /* Coolflux interrupt vector table address0 LSB , */\
+ { 0x9a0f, "ivt_addr1_msb"}, /* Coolflux interrupt vector table address1 MSB , */\
+ { 0x9b0f, "ivt_addr1_lsb"}, /* Coolflux interrupt vector table address1 LSB , */\
+ { 0x9c0f, "ivt_addr2_msb"}, /* Coolflux interrupt vector table address2 MSB , */\
+ { 0x9d0f, "ivt_addr2_lsb"}, /* Coolflux interrupt vector table address2 LSB , */\
+ { 0x9e0f, "ivt_addr3_msb"}, /* Coolflux interrupt vector table address3 MSB , */\
+ { 0x9f0f, "ivt_addr3_lsb"}, /* Coolflux interrupt vector table address3 LSB , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* FFT Coolflux , */\
+ { 0xc3e0, "test_pwr_switch"}, /* Test mode for digital power switches core sw/mem sw/micvdd sw, */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc660, "bypass_diosw_ovp"}, /* Bypass ovp for memory switch diosw , */\
+ { 0xc670, "enbl_powerswitch"}, /* Vddd core power switch control - overrules the manager control, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to GPIO1 (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to GPIO2 (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to GPIO3 (see Digimux list for details), */\
+ { 0xc887, "digimuxd_sel"}, /* DigimuxD input selection control routed to GPIO4 (see Digimux list for details), */\
+ { 0xc901, "dio1_ehs"}, /* Speed/load setting for DIO1 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc921, "dio2_ehs"}, /* Speed/load setting for DIO2 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc941, "gainio_ehs"}, /* Speed/load setting for GAINIO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc961, "pdmo_ehs"}, /* Speed/load setting for PDMO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9a1, "tdo_ehs"}, /* Speed/load setting for TDO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca40, "enbl_anamux5"}, /* Enable anamux5 , */\
+ { 0xca50, "enbl_anamux6"}, /* Enable anamux6 , */\
+ { 0xca60, "enbl_anamux7"}, /* Enable anamux7 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb54, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba4, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcc04, "anamux5"}, /* Anamux selection control - anamux on TEST5 , */\
+ { 0xcc54, "anamux6"}, /* Anamux selection control - anamux on TEST6 , */\
+ { 0xcca4, "anamux7"}, /* Anamux selection control - anamux on TEST7 , */\
+ { 0xcd05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xcd64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcdb3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd243, "tsig_gain_left"}, /* Test signal gain for left channel , */\
+ { 0xd283, "tsig_gain_right"}, /* Test signal gain for right channel , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd506, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd570, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "calibr_gain_left"}, /* HW gain module - left channel (2's complement) , */\
+ { 0xf1a5, "calibr_offset_left"}, /* Offset for amplifier, HW gain module - left channel (2's complement), */\
+ { 0xf203, "calibr_gain_right"}, /* HW gain module - right channel (2's complement) , */\
+ { 0xf245, "calibr_offset_right"}, /* Offset for amplifier, HW gain module - right channel (2's complement), */\
+ { 0xf2a3, "calibr_rcvldop_trim"}, /* Trimming of LDO (2.7V) , */\
+ { 0xf307, "calibr_gain_cs_left"}, /* Current sense gain - left channel (signed two's complement format), */\
+ { 0xf387, "calibr_gain_cs_right"}, /* Current sense gain - right channel (signed two's complement format), */\
+ { 0xf40f, "calibr_R25C_L"}, /* Ron resistance of left channel speaker coil , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of right channel speaker coil , */\
+ { 0xf606, "ctrl_offset_a_left"}, /* Offset of left amplifier level shifter A , */\
+ { 0xf686, "ctrl_offset_b_left"}, /* Offset of left amplifier level shifter B , */\
+ { 0xf706, "ctrl_offset_a_right"}, /* Offset of right amplifier level shifter A , */\
+ { 0xf786, "ctrl_offset_b_right"}, /* Offset of right amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "mtp_lock_enbl_coolflux"}, /* Disable function enbl_coolflux , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Disable programming of max dcdc boost voltage , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf987, "type_bits_fw"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa2_irq {
+ tfa2_irq_stvdds = 0,
+ tfa2_irq_stplls = 1,
+ tfa2_irq_stotds = 2,
+ tfa2_irq_stovds = 3,
+ tfa2_irq_stuvds = 4,
+ tfa2_irq_stclks = 5,
+ tfa2_irq_stmtpb = 6,
+ tfa2_irq_stnoclk = 7,
+ tfa2_irq_stspks = 8,
+ tfa2_irq_stacs = 9,
+ tfa2_irq_stsws = 10,
+ tfa2_irq_stwds = 11,
+ tfa2_irq_stamps = 12,
+ tfa2_irq_starefs = 13,
+ tfa2_irq_stadccr = 14,
+ tfa2_irq_stbodnok = 15,
+ tfa2_irq_stbstcu = 16,
+ tfa2_irq_stbsthi = 17,
+ tfa2_irq_stbstoc = 18,
+ tfa2_irq_stbstpkcur = 19,
+ tfa2_irq_stbstvc = 20,
+ tfa2_irq_stbst86 = 21,
+ tfa2_irq_stbst93 = 22,
+ tfa2_irq_strcvld = 23,
+ tfa2_irq_stocpl = 24,
+ tfa2_irq_stocpr = 25,
+ tfa2_irq_stmwsrc = 26,
+ tfa2_irq_stmwcfc = 27,
+ tfa2_irq_stmwsmu = 28,
+ tfa2_irq_stcfmer = 29,
+ tfa2_irq_stcfmac = 30,
+ tfa2_irq_stclkoor = 31,
+ tfa2_irq_sttdmer = 32,
+ tfa2_irq_stclpl = 33,
+ tfa2_irq_stclpr = 34,
+ tfa2_irq_stocpm = 35,
+ tfa2_irq_max = 36,
+ tfa2_irq_all = -1 /* all irqs */};
+
+#define TFA2_IRQ_NAMETABLE static tfaIrqName_t Tfa2IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STPLLS"},\
+ { 2, "STOTDS"},\
+ { 3, "STOVDS"},\
+ { 4, "STUVDS"},\
+ { 5, "STCLKS"},\
+ { 6, "STMTPB"},\
+ { 7, "STNOCLK"},\
+ { 8, "STSPKS"},\
+ { 9, "STACS"},\
+ { 10, "STSWS"},\
+ { 11, "STWDS"},\
+ { 12, "STAMPS"},\
+ { 13, "STAREFS"},\
+ { 14, "STADCCR"},\
+ { 15, "STBODNOK"},\
+ { 16, "STBSTCU"},\
+ { 17, "STBSTHI"},\
+ { 18, "STBSTOC"},\
+ { 19, "STBSTPKCUR"},\
+ { 20, "STBSTVC"},\
+ { 21, "STBST86"},\
+ { 22, "STBST93"},\
+ { 23, "STRCVLD"},\
+ { 24, "STOCPL"},\
+ { 25, "STOCPR"},\
+ { 26, "STMWSRC"},\
+ { 27, "STMWCFC"},\
+ { 28, "STMWSMU"},\
+ { 29, "STCFMER"},\
+ { 30, "STCFMAC"},\
+ { 31, "STCLKOOR"},\
+ { 32, "STTDMER"},\
+ { 33, "STCLPL"},\
+ { 34, "STCLPR"},\
+ { 35, "STOCPM"},\
+ { 36, "36"},\
+};
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9872_device_genregs_POR.h b/sound/soc/codecs/tfa98xx-downstream/tfa9872_device_genregs_POR.h
new file mode 100644
index 00000000000..9dee345d8d7
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9872_device_genregs_POR.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/** Filename: Tfa98xx_device_genregs.h
+ * This file was generated automatically on 08/11/16 at 07:44:41.
+ * Source file: TFA9872N1B2_DefaultI2CSettings - V1.xlsx
+ */
+
+#ifndef _TFA9872_DEVICE_GENREGS_H
+#define _TFA9872_DEVICE_GENREGS_H
+
+
+#define TFA9872_SYS_CONTROL0 0x00
+#define TFA9872_SYS_CONTROL1 0x01
+#define TFA9872_SYS_CONTROL2 0x02
+#define TFA9872_DEVICE_REVISION 0x03
+#define TFA9872_CLOCK_CONTROL 0x04
+#define TFA9872_CLOCK_GATING_CONTROL 0x05
+#define TFA9872_SIDE_TONE_CONFIG 0x0d
+#define TFA9872_STATUS_FLAGS0 0x10
+#define TFA9872_STATUS_FLAGS1 0x11
+#define TFA9872_STATUS_FLAGS3 0x13
+#define TFA9872_STATUS_FLAGS4 0x14
+#define TFA9872_BATTERY_VOLTAGE 0x15
+#define TFA9872_TEMPERATURE 0x16
+#define TFA9872_VDDP_VOLTAGE 0x17
+#define TFA9872_TDM_CONFIG0 0x20
+#define TFA9872_TDM_CONFIG1 0x21
+#define TFA9872_TDM_CONFIG2 0x22
+#define TFA9872_TDM_CONFIG3 0x23
+#define TFA9872_TDM_CONFIG6 0x26
+#define TFA9872_TDM_CONFIG7 0x27
+#define TFA9872_PDM_CONFIG0 0x31
+#define TFA9872_INTERRUPT_OUT_REG1 0x40
+#define TFA9872_INTERRUPT_OUT_REG2 0x41
+#define TFA9872_INTERRUPT_OUT_REG3 0x42
+#define TFA9872_INTERRUPT_IN_REG1 0x44
+#define TFA9872_INTERRUPT_IN_REG2 0x45
+#define TFA9872_INTERRUPT_IN_REG3 0x46
+#define TFA9872_INTERRUPT_ENABLE_REG1 0x48
+#define TFA9872_INTERRUPT_ENABLE_REG2 0x49
+#define TFA9872_INTERRUPT_ENABLE_REG3 0x4a
+#define TFA9872_STATUS_POLARITY_REG1 0x4c
+#define TFA9872_STATUS_POLARITY_REG2 0x4d
+#define TFA9872_STATUS_POLARITY_REG3 0x4e
+#define TFA9872_BAT_PROT_CONFIG 0x50
+#define TFA9872_AUDIO_CONTROL 0x51
+#define TFA9872_AMPLIFIER_CONFIG 0x52
+#define TFA9872_PGA_CONTROL0 0x60
+#define TFA9872_GAIN_ATT 0x61
+#define TFA9872_TDM_SOURCE_CTRL 0x68
+#define TFA9872_SAM_CTRL 0x69
+#define TFA9872_STATUS_FLAGS5 0x6e
+#define TFA9872_CURSENSE_COMP 0x6f
+#define TFA9872_DCDC_CONTROL0 0x70
+#define TFA9872_DCDC_CONTROL4 0x74
+#define TFA9872_DCDC_CONTROL5 0x75
+#define TFA9872_MTPKEY2_REG 0xa1
+#define TFA9872_MTP_STATUS 0xa2
+#define TFA9872_KEY_PROTECTED_MTP_CONTROL 0xa3
+#define TFA9872_MTP_DATA_OUT_MSB 0xa5
+#define TFA9872_MTP_DATA_OUT_LSB 0xa6
+#define TFA9872_TEMP_SENSOR_CONFIG 0xb1
+#define TFA9872_SOFTWARE_PROFILE 0xee
+#define TFA9872_SOFTWARE_VSTEP 0xef
+#define TFA9872_KEY2_PROTECTED_MTP0 0xf0
+#define TFA9872_KEY2_PROTECTED_MTP5 0xf5
+#define TFA9872_SYS_CONTROL0_POR 0x0001
+#define TFA9872_SYS_CONTROL1_POR 0x0000
+#define TFA9872_SYS_CONTROL2_POR 0x2828
+#define TFA9872_DEVICE_REVISION_POR 0x3b72
+#define TFA9872_CLOCK_CONTROL_POR 0x0000
+#define TFA9872_CLOCK_GATING_CONTROL_POR 0x1f6a
+#define TFA9872_SIDE_TONE_CONFIG_POR 0x0ebe
+#define TFA9872_STATUS_FLAGS0_POR 0x001d
+#define TFA9872_STATUS_FLAGS1_POR 0x0004
+#define TFA9872_STATUS_FLAGS3_POR 0x000f
+#define TFA9872_STATUS_FLAGS4_POR 0x0000
+#define TFA9872_BATTERY_VOLTAGE_POR 0x03ff
+#define TFA9872_TEMPERATURE_POR 0x0100
+#define TFA9872_VDDP_VOLTAGE_POR 0x0000
+#define TFA9872_TDM_CONFIG0_POR 0x2890
+#define TFA9872_TDM_CONFIG1_POR 0xc1f1
+#define TFA9872_TDM_CONFIG2_POR 0x045c
+#define TFA9872_TDM_CONFIG3_POR 0x0003
+#define TFA9872_TDM_CONFIG6_POR 0x0010
+#define TFA9872_TDM_CONFIG7_POR 0x0001
+#define TFA9872_PDM_CONFIG0_POR 0x0000
+#define TFA9872_INTERRUPT_OUT_REG1_POR 0x0081
+#define TFA9872_INTERRUPT_OUT_REG2_POR 0x0000
+#define TFA9872_INTERRUPT_OUT_REG3_POR 0x0000
+#define TFA9872_INTERRUPT_IN_REG1_POR 0x0000
+#define TFA9872_INTERRUPT_IN_REG2_POR 0x0000
+#define TFA9872_INTERRUPT_IN_REG3_POR 0x0000
+#define TFA9872_INTERRUPT_ENABLE_REG1_POR 0x0001
+#define TFA9872_INTERRUPT_ENABLE_REG2_POR 0x0000
+#define TFA9872_INTERRUPT_ENABLE_REG3_POR 0x0000
+#define TFA9872_STATUS_POLARITY_REG1_POR 0x74e3
+#define TFA9872_STATUS_POLARITY_REG2_POR 0x967b
+#define TFA9872_STATUS_POLARITY_REG3_POR 0x0085
+#define TFA9872_BAT_PROT_CONFIG_POR 0x8091
+#define TFA9872_AUDIO_CONTROL_POR 0x0080
+#define TFA9872_AMPLIFIER_CONFIG_POR 0x7a08
+#define TFA9872_PGA_CONTROL0_POR 0x0000
+#define TFA9872_GAIN_ATT_POR 0x0000
+#define TFA9872_TDM_SOURCE_CTRL_POR 0x0400
+#define TFA9872_SAM_CTRL_POR 0x0000
+#define TFA9872_STATUS_FLAGS5_POR 0x0007
+#define TFA9872_CURSENSE_COMP_POR 0x02e4
+#define TFA9872_DCDC_CONTROL0_POR 0x06e6
+#define TFA9872_DCDC_CONTROL4_POR 0xd913
+#define TFA9872_DCDC_CONTROL5_POR 0x118a
+#define TFA9872_MTPKEY2_REG_POR 0x0000
+#define TFA9872_MTP_STATUS_POR 0x0003
+#define TFA9872_KEY_PROTECTED_MTP_CONTROL_POR 0x0000
+#define TFA9872_MTP_DATA_OUT_MSB_POR 0x0000
+#define TFA9872_MTP_DATA_OUT_LSB_POR 0x0000
+#define TFA9872_TEMP_SENSOR_CONFIG_POR 0x0000
+#define TFA9872_SOFTWARE_PROFILE_POR 0x0000
+#define TFA9872_SOFTWARE_VSTEP_POR 0x0000
+#define TFA9872_KEY2_PROTECTED_MTP0_POR 0x0000
+#define TFA9872_KEY2_PROTECTED_MTP5_POR 0x0000
+
+#endif /* _TFA9872_DEVICE_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9872_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9872_tfafieldnames.h
new file mode 100644
index 00000000000..db9929d24c5
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9872_tfafieldnames.h
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9872_tfaFieldnames.h
+ * This file was generated automatically on 09/28/18 at 11:21:43.
+ * Source file: TFA9872N1B2_DefaultI2CSettings -v25.xlsx
+ */
+
+#ifndef _TFA9872_TFAFIELDNAMES_H
+#define _TFA9872_TFAFIELDNAMES_H
+
+#define TFA9872_I2CVERSION_N1A 26
+#define TFA9872_I2CVERSION_N1B 29
+#define TFA9872_I2CVERSION_N1B2 25
+
+typedef enum Tfa9872BfEnumList {
+ TFA9872_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9872_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9872_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA9872_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9872_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9872_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9872_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9872_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9872_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA9872_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA9872_BF_RCVNS = 0x01e0, /*!< Noise shaper selection */
+ TFA9872_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9872_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9872_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9872_BF_BYPHVBF= 0x02b0, /*!< Bypass HVBAT filter */
+ TFA9872_BF_REV = 0x030f, /*!< Revision info */
+ TFA9872_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9872_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9872_BF_SSE = 0x0510, /*!< Enable speaker path */
+ TFA9872_BF_VSE = 0x0530, /*!< Voltage sense */
+ TFA9872_BF_CSE = 0x0550, /*!< Current sense */
+ TFA9872_BF_SSPDME= 0x0560, /*!< Sub-system PDM */
+ TFA9872_BF_PGAE = 0x0580, /*!< Enable PGA chop clock */
+ TFA9872_BF_SSTDME= 0x0590, /*!< Sub-system TDM */
+ TFA9872_BF_SSPBSTE= 0x05a0, /*!< Sub-system boost */
+ TFA9872_BF_SSADCE= 0x05b0, /*!< Sub-system ADC */
+ TFA9872_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9872_BF_STGAIN= 0x0d18, /*!< Side tone gain */
+ TFA9872_BF_STSMUTE= 0x0da0, /*!< Side tone soft mute */
+ TFA9872_BF_ST1C = 0x0db0, /*!< side tone one s complement */
+ TFA9872_BF_VDDS = 0x1000, /*!< POR */
+ TFA9872_BF_PLLS = 0x1010, /*!< PLL lock */
+ TFA9872_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9872_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9872_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9872_BF_CLKS = 0x1050, /*!< Clocks stable */
+ TFA9872_BF_MTPB = 0x1060, /*!< MTP busy */
+ TFA9872_BF_NOCLK = 0x1070, /*!< Lost clock */
+ TFA9872_BF_SWS = 0x10a0, /*!< Amplifier engage */
+ TFA9872_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9872_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9872_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9872_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9872_BF_DCDCA = 0x1110, /*!< DCDC active */
+ TFA9872_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos */
+ TFA9872_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9872_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9872_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9872_BF_STMUTEB= 0x1170, /*!< side tone (un)mute busy */
+ TFA9872_BF_STMUTE= 0x1180, /*!< side tone mute state */
+ TFA9872_BF_TDMLUTER= 0x1190, /*!< TDM LUT error */
+ TFA9872_BF_TDMSTAT= 0x11a2, /*!< TDM status bits */
+ TFA9872_BF_TDMERR= 0x11d0, /*!< TDM error */
+ TFA9872_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9872_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9872_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9872_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9872_BF_CLIPAH= 0x1340, /*!< Clipping A to Vddp */
+ TFA9872_BF_CLIPAL= 0x1350, /*!< Clipping A to gnd */
+ TFA9872_BF_CLIPBH= 0x1360, /*!< Clipping B to Vddp */
+ TFA9872_BF_CLIPBL= 0x1370, /*!< Clipping B to gnd */
+ TFA9872_BF_OCDS = 0x1380, /*!< OCP amplifier */
+ TFA9872_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9872_BF_OCPOKMC= 0x13a0, /*!< OCPOK MICVDD */
+ TFA9872_BF_MANALARM= 0x13b0, /*!< Alarm state */
+ TFA9872_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9872_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9872_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9872_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA9872_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9872_BF_DCMODE= 0x1471, /*!< DCDC mode status bits */
+ TFA9872_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9872_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9872_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/9.5 V) */
+ TFA9872_BF_TDME = 0x2040, /*!< Enable interface */
+ TFA9872_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA9872_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9872_BF_TDMFSLN= 0x2073, /*!< FS length (master mode only) */
+ TFA9872_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9872_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9872_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA9872_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9872_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9872_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9872_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9872_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9872_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9872_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9872_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9872_BF_TDMSPKE= 0x2300, /*!< Control audio tdm channel in 0 (spkr + dcdc) */
+ TFA9872_BF_TDMDCE= 0x2310, /*!< Control audio tdm channel in 1 (dcdc) */
+ TFA9872_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9872_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9872_BF_TDMSPKS= 0x2603, /*!< tdm slot for sink 0 (speaker + dcdc) */
+ TFA9872_BF_TDMDCS= 0x2643, /*!< tdm slot for sink 1 (dcdc) */
+ TFA9872_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9872_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9872_BF_PDMSTSEL= 0x3111, /*!< Side tone input */
+ TFA9872_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9872_BF_ISTPLLS= 0x4010, /*!< Status PLL lock */
+ TFA9872_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9872_BF_ISTOVDS= 0x4030, /*!< Status OVP alarm */
+ TFA9872_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9872_BF_ISTCLKS= 0x4050, /*!< Status clocks stable */
+ TFA9872_BF_ISTMTPB= 0x4060, /*!< Status MTP busy */
+ TFA9872_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9872_BF_ISTSWS= 0x40a0, /*!< Status amplifier engage */
+ TFA9872_BF_ISTAMPS= 0x40c0, /*!< Status amplifier enable */
+ TFA9872_BF_ISTAREFS= 0x40d0, /*!< Status Ref enable */
+ TFA9872_BF_ISTADCCR= 0x40e0, /*!< Status Control ADC */
+ TFA9872_BF_ISTBSTCU= 0x4100, /*!< Status DCDC current limiting */
+ TFA9872_BF_ISTBSTHI= 0x4110, /*!< Status DCDC active */
+ TFA9872_BF_ISTBSTOC= 0x4120, /*!< Status DCDC OCP */
+ TFA9872_BF_ISTBSTPKCUR= 0x4130, /*!< Status bst peakcur */
+ TFA9872_BF_ISTBSTVC= 0x4140, /*!< Status DCDC level 1x */
+ TFA9872_BF_ISTBST86= 0x4150, /*!< Status DCDC level 1.14x */
+ TFA9872_BF_ISTBST93= 0x4160, /*!< Status DCDC level 1.07x */
+ TFA9872_BF_ISTOCPR= 0x4190, /*!< Status ocp alarm */
+ TFA9872_BF_ISTMWSRC= 0x41a0, /*!< Status Waits HW I2C settings */
+ TFA9872_BF_ISTMWSMU= 0x41c0, /*!< Status Audio mute sequence */
+ TFA9872_BF_ISTCLKOOR= 0x41f0, /*!< Status flag_clk_out_of_range */
+ TFA9872_BF_ISTTDMER= 0x4200, /*!< Status tdm error */
+ TFA9872_BF_ISTCLPR= 0x4220, /*!< Status clip */
+ TFA9872_BF_ISTLP0= 0x4240, /*!< Status low power mode0 */
+ TFA9872_BF_ISTLP1= 0x4250, /*!< Status low power mode1 */
+ TFA9872_BF_ISTLA = 0x4260, /*!< Status low noise detection */
+ TFA9872_BF_ISTVDDPH= 0x4270, /*!< Status VDDP greater than VBAT */
+ TFA9872_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9872_BF_ICLPLLS= 0x4410, /*!< Clear PLL lock */
+ TFA9872_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9872_BF_ICLOVDS= 0x4430, /*!< Clear OVP alarm */
+ TFA9872_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9872_BF_ICLCLKS= 0x4450, /*!< Clear clocks stable */
+ TFA9872_BF_ICLMTPB= 0x4460, /*!< Clear mtp busy */
+ TFA9872_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9872_BF_ICLSWS= 0x44a0, /*!< Clear amplifier engage */
+ TFA9872_BF_ICLAMPS= 0x44c0, /*!< Clear enbl amp */
+ TFA9872_BF_ICLAREFS= 0x44d0, /*!< Clear ref enable */
+ TFA9872_BF_ICLADCCR= 0x44e0, /*!< Clear control ADC */
+ TFA9872_BF_ICLBSTCU= 0x4500, /*!< Clear DCDC current limiting */
+ TFA9872_BF_ICLBSTHI= 0x4510, /*!< Clear DCDC active */
+ TFA9872_BF_ICLBSTOC= 0x4520, /*!< Clear DCDC OCP */
+ TFA9872_BF_ICLBSTPC= 0x4530, /*!< Clear bst peakcur */
+ TFA9872_BF_ICLBSTVC= 0x4540, /*!< Clear DCDC level 1x */
+ TFA9872_BF_ICLBST86= 0x4550, /*!< Clear DCDC level 1.14x */
+ TFA9872_BF_ICLBST93= 0x4560, /*!< Clear DCDC level 1.07x */
+ TFA9872_BF_ICLOCPR= 0x4590, /*!< Clear ocp alarm */
+ TFA9872_BF_ICLMWSRC= 0x45a0, /*!< Clear wait HW I2C settings */
+ TFA9872_BF_ICLMWSMU= 0x45c0, /*!< Clear audio mute sequence */
+ TFA9872_BF_ICLCLKOOR= 0x45f0, /*!< Clear flag_clk_out_of_range */
+ TFA9872_BF_ICLTDMER= 0x4600, /*!< Clear tdm error */
+ TFA9872_BF_ICLCLPR= 0x4620, /*!< Clear clip */
+ TFA9872_BF_ICLLP0= 0x4640, /*!< Clear low power mode0 */
+ TFA9872_BF_ICLLP1= 0x4650, /*!< Clear low power mode1 */
+ TFA9872_BF_ICLLA = 0x4660, /*!< Clear low noise detection */
+ TFA9872_BF_ICLVDDPH= 0x4670, /*!< Clear VDDP greater then VBAT */
+ TFA9872_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9872_BF_IEPLLS= 0x4810, /*!< Enable pll lock */
+ TFA9872_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9872_BF_IEOVDS= 0x4830, /*!< Enable OVP alarm */
+ TFA9872_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9872_BF_IECLKS= 0x4850, /*!< Enable clocks stable */
+ TFA9872_BF_IEMTPB= 0x4860, /*!< Enable mtp busy */
+ TFA9872_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9872_BF_IESWS = 0x48a0, /*!< Enable amplifier engage */
+ TFA9872_BF_IEAMPS= 0x48c0, /*!< Enable enbl amp */
+ TFA9872_BF_IEAREFS= 0x48d0, /*!< Enable ref enable */
+ TFA9872_BF_IEADCCR= 0x48e0, /*!< Enable Control ADC */
+ TFA9872_BF_IEBSTCU= 0x4900, /*!< Enable DCDC current limiting */
+ TFA9872_BF_IEBSTHI= 0x4910, /*!< Enable DCDC active */
+ TFA9872_BF_IEBSTOC= 0x4920, /*!< Enable DCDC OCP */
+ TFA9872_BF_IEBSTPC= 0x4930, /*!< Enable bst peakcur */
+ TFA9872_BF_IEBSTVC= 0x4940, /*!< Enable DCDC level 1x */
+ TFA9872_BF_IEBST86= 0x4950, /*!< Enable DCDC level 1.14x */
+ TFA9872_BF_IEBST93= 0x4960, /*!< Enable DCDC level 1.07x */
+ TFA9872_BF_IEOCPR= 0x4990, /*!< Enable ocp alarm */
+ TFA9872_BF_IEMWSRC= 0x49a0, /*!< Enable waits HW I2C settings */
+ TFA9872_BF_IEMWSMU= 0x49c0, /*!< Enable man Audio mute sequence */
+ TFA9872_BF_IECLKOOR= 0x49f0, /*!< Enable flag_clk_out_of_range */
+ TFA9872_BF_IETDMER= 0x4a00, /*!< Enable tdm error */
+ TFA9872_BF_IECLPR= 0x4a20, /*!< Enable clip */
+ TFA9872_BF_IELP0 = 0x4a40, /*!< Enable low power mode0 */
+ TFA9872_BF_IELP1 = 0x4a50, /*!< Enable low power mode1 */
+ TFA9872_BF_IELA = 0x4a60, /*!< Enable low noise detection */
+ TFA9872_BF_IEVDDPH= 0x4a70, /*!< Enable VDDP greater tehn VBAT */
+ TFA9872_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9872_BF_IPOPLLS= 0x4c10, /*!< Polarity pll lock */
+ TFA9872_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9872_BF_IPOOVDS= 0x4c30, /*!< Polarity OVP alarm */
+ TFA9872_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9872_BF_IPOCLKS= 0x4c50, /*!< Polarity clocks stable */
+ TFA9872_BF_IPOMTPB= 0x4c60, /*!< Polarity mtp busy */
+ TFA9872_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9872_BF_IPOSWS= 0x4ca0, /*!< Polarity amplifier engage */
+ TFA9872_BF_IPOAMPS= 0x4cc0, /*!< Polarity enbl amp */
+ TFA9872_BF_IPOAREFS= 0x4cd0, /*!< Polarity ref enable */
+ TFA9872_BF_IPOADCCR= 0x4ce0, /*!< Polarity Control ADC */
+ TFA9872_BF_IPOBSTCU= 0x4d00, /*!< Polarity DCDC current limiting */
+ TFA9872_BF_IPOBSTHI= 0x4d10, /*!< Polarity DCDC active */
+ TFA9872_BF_IPOBSTOC= 0x4d20, /*!< Polarity DCDC OCP */
+ TFA9872_BF_IPOBSTPC= 0x4d30, /*!< Polarity bst peakcur */
+ TFA9872_BF_IPOBSTVC= 0x4d40, /*!< Polarity DCDC level 1x */
+ TFA9872_BF_IPOBST86= 0x4d50, /*!< Polarity DCDC level 1.14x */
+ TFA9872_BF_IPOBST93= 0x4d60, /*!< Polarity DCDC level 1.07x */
+ TFA9872_BF_IPOOCPR= 0x4d90, /*!< Polarity ocp alarm */
+ TFA9872_BF_IPOMWSRC= 0x4da0, /*!< Polarity waits HW I2C settings */
+ TFA9872_BF_IPOMWSMU= 0x4dc0, /*!< Polarity man audio mute sequence */
+ TFA9872_BF_IPCLKOOR= 0x4df0, /*!< Polarity flag_clk_out_of_range */
+ TFA9872_BF_IPOTDMER= 0x4e00, /*!< Polarity tdm error */
+ TFA9872_BF_IPOCLPR= 0x4e20, /*!< Polarity clip right */
+ TFA9872_BF_IPOLP0= 0x4e40, /*!< Polarity low power mode0 */
+ TFA9872_BF_IPOLP1= 0x4e50, /*!< Polarity low power mode1 */
+ TFA9872_BF_IPOLA = 0x4e60, /*!< Polarity low noise mode */
+ TFA9872_BF_IPOVDDPH= 0x4e70, /*!< Polarity VDDP greater than VBAT */
+ TFA9872_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time */
+ TFA9872_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9872_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9872_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9872_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9872_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9872_BF_INTSMUTE= 0x5110, /*!< Soft mute HW */
+ TFA9872_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9872_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9872_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9872_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9872_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9872_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9872_BF_PGAGAIN= 0x6081, /*!< PGA gain selection */
+ TFA9872_BF_PGALPE= 0x60b0, /*!< Lowpass enable */
+ TFA9872_BF_LPM0BYP= 0x6110, /*!< bypass low power idle mode */
+ TFA9872_BF_TDMDCG= 0x6123, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9872_BF_TDMSPKG= 0x6163, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9872_BF_STIDLEEN= 0x61b0, /*!< enable idle feature for channel 1 */
+ TFA9872_BF_LNMODE= 0x62e1, /*!< ctrl select mode */
+ TFA9872_BF_LPM1MODE= 0x64e1, /*!< low power mode control */
+ TFA9872_BF_LPM1DIS= 0x65c0, /*!< low power mode1 detector control */
+ TFA9872_BF_TDMSRCMAP= 0x6801, /*!< tdm source mapping */
+ TFA9872_BF_TDMSRCAS= 0x6821, /*!< Sensed value A */
+ TFA9872_BF_TDMSRCBS= 0x6841, /*!< Sensed value B */
+ TFA9872_BF_ANCSEL= 0x6881, /*!< anc input */
+ TFA9872_BF_ANC1C = 0x68a0, /*!< ANC one s complement */
+ TFA9872_BF_SAMMODE= 0x6901, /*!< sam enable */
+ TFA9872_BF_SAMSEL= 0x6920, /*!< sam source */
+ TFA9872_BF_PDMOSELH= 0x6931, /*!< pdm out value when pdm_clk is higth */
+ TFA9872_BF_PDMOSELL= 0x6951, /*!< pdm out value when pdm_clk is low */
+ TFA9872_BF_SAMOSEL= 0x6970, /*!< ram output on mode sam and audio */
+ TFA9872_BF_LP0 = 0x6e00, /*!< low power mode 0 detection */
+ TFA9872_BF_LP1 = 0x6e10, /*!< low power mode 1 detection */
+ TFA9872_BF_LA = 0x6e20, /*!< low amplitude detection */
+ TFA9872_BF_VDDPH = 0x6e30, /*!< vddp greater than vbat */
+ TFA9872_BF_DELCURCOMP= 0x6f02, /*!< delay to allign compensation signal with current sense signal */
+ TFA9872_BF_SIGCURCOMP= 0x6f40, /*!< polarity of compensation for current sense */
+ TFA9872_BF_ENCURCOMP= 0x6f50, /*!< enable current sense compensation */
+ TFA9872_BF_SELCLPPWM= 0x6f60, /*!< Select pwm clip flag */
+ TFA9872_BF_LVLCLPPWM= 0x6f72, /*!< set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9872_BF_DCVOS = 0x7002, /*!< Second boost voltage level */
+ TFA9872_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA9872_BF_DCCV = 0x7071, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9872_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA9872_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA9872_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9872_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9872_BF_DCVOF = 0x7402, /*!< 1st boost voltage level */
+ TFA9872_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9872_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9872_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9872_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9872_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9872_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9872_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9872_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9872_BF_CMTPI = 0xa350, /*!< Start copying all the data from mtp to I2C mtp registers */
+ TFA9872_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9872_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9872_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9872_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9872_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9872_BF_SWPROFIL= 0xee0f, /*!< Software profile data */
+ TFA9872_BF_SWVSTEP= 0xef0f, /*!< Software vstep information */
+ TFA9872_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9872_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9872_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9872_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9872_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9872_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9872_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9872BfEnumList_t;
+#define TFA9872_NAMETABLE static tfaBfName_t Tfa9872DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "RCVNS"}, /* Noise shaper selection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b0, "BYPHVBF"}, /* Bypass HVBAT filter , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x510, "SSE"}, /* Enable speaker path , */\
+ { 0x530, "VSE"}, /* Voltage sense , */\
+ { 0x550, "CSE"}, /* Current sense , */\
+ { 0x560, "SSPDME"}, /* Sub-system PDM , */\
+ { 0x580, "PGAE"}, /* Enable PGA chop clock , */\
+ { 0x590, "SSTDME"}, /* Sub-system TDM , */\
+ { 0x5a0, "SSPBSTE"}, /* Sub-system boost , */\
+ { 0x5b0, "SSADCE"}, /* Sub-system ADC , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0xd18, "STGAIN"}, /* Side tone gain , */\
+ { 0xda0, "STSMUTE"}, /* Side tone soft mute , */\
+ { 0xdb0, "ST1C"}, /* side tone one s complement , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "CLKS"}, /* Clocks stable , */\
+ { 0x1060, "MTPB"}, /* MTP busy , */\
+ { 0x1070, "NOCLK"}, /* Lost clock , */\
+ { 0x10a0, "SWS"}, /* Amplifier engage , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "STMUTEB"}, /* side tone (un)mute busy , */\
+ { 0x1180, "STMUTE"}, /* side tone mute state , */\
+ { 0x1190, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11a2, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11d0, "TDMERR"}, /* TDM error , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1340, "CLIPAH"}, /* Clipping A to Vddp , */\
+ { 0x1350, "CLIPAL"}, /* Clipping A to gnd , */\
+ { 0x1360, "CLIPBH"}, /* Clipping B to Vddp , */\
+ { 0x1370, "CLIPBL"}, /* Clipping B to gnd , */\
+ { 0x1380, "OCDS"}, /* OCP amplifier , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "OCPOKMC"}, /* OCPOK MICVDD , */\
+ { 0x13b0, "MANALARM"}, /* Alarm state , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1471, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/9.5 V) , */\
+ { 0x2040, "TDME"}, /* Enable interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "TDMDCE"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x3111, "PDMSTSEL"}, /* Side tone input , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTPLLS"}, /* Status PLL lock , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOVDS"}, /* Status OVP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTCLKS"}, /* Status clocks stable , */\
+ { 0x4060, "ISTMTPB"}, /* Status MTP busy , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x40a0, "ISTSWS"}, /* Status amplifier engage , */\
+ { 0x40c0, "ISTAMPS"}, /* Status amplifier enable , */\
+ { 0x40d0, "ISTAREFS"}, /* Status Ref enable , */\
+ { 0x40e0, "ISTADCCR"}, /* Status Control ADC , */\
+ { 0x4100, "ISTBSTCU"}, /* Status DCDC current limiting , */\
+ { 0x4110, "ISTBSTHI"}, /* Status DCDC active , */\
+ { 0x4120, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4130, "ISTBSTPKCUR"}, /* Status bst peakcur , */\
+ { 0x4140, "ISTBSTVC"}, /* Status DCDC level 1x , */\
+ { 0x4150, "ISTBST86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "ISTBST93"}, /* Status DCDC level 1.07x , */\
+ { 0x4190, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x41a0, "ISTMWSRC"}, /* Status Waits HW I2C settings , */\
+ { 0x41c0, "ISTMWSMU"}, /* Status Audio mute sequence , */\
+ { 0x41f0, "ISTCLKOOR"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4220, "ISTCLPR"}, /* Status clip , */\
+ { 0x4240, "ISTLP0"}, /* Status low power mode0 , */\
+ { 0x4250, "ISTLP1"}, /* Status low power mode1 , */\
+ { 0x4260, "ISTLA"}, /* Status low noise detection , */\
+ { 0x4270, "ISTVDDPH"}, /* Status VDDP greater than VBAT , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLPLLS"}, /* Clear PLL lock , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOVDS"}, /* Clear OVP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLCLKS"}, /* Clear clocks stable , */\
+ { 0x4460, "ICLMTPB"}, /* Clear mtp busy , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x44a0, "ICLSWS"}, /* Clear amplifier engage , */\
+ { 0x44c0, "ICLAMPS"}, /* Clear enbl amp , */\
+ { 0x44d0, "ICLAREFS"}, /* Clear ref enable , */\
+ { 0x44e0, "ICLADCCR"}, /* Clear control ADC , */\
+ { 0x4500, "ICLBSTCU"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "ICLBSTHI"}, /* Clear DCDC active , */\
+ { 0x4520, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4530, "ICLBSTPC"}, /* Clear bst peakcur , */\
+ { 0x4540, "ICLBSTVC"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "ICLBST86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "ICLBST93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4590, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x45a0, "ICLMWSRC"}, /* Clear wait HW I2C settings , */\
+ { 0x45c0, "ICLMWSMU"}, /* Clear audio mute sequence , */\
+ { 0x45f0, "ICLCLKOOR"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4620, "ICLCLPR"}, /* Clear clip , */\
+ { 0x4640, "ICLLP0"}, /* Clear low power mode0 , */\
+ { 0x4650, "ICLLP1"}, /* Clear low power mode1 , */\
+ { 0x4660, "ICLLA"}, /* Clear low noise detection , */\
+ { 0x4670, "ICLVDDPH"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEPLLS"}, /* Enable pll lock , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOVDS"}, /* Enable OVP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IECLKS"}, /* Enable clocks stable , */\
+ { 0x4860, "IEMTPB"}, /* Enable mtp busy , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x48a0, "IESWS"}, /* Enable amplifier engage , */\
+ { 0x48c0, "IEAMPS"}, /* Enable enbl amp , */\
+ { 0x48d0, "IEAREFS"}, /* Enable ref enable , */\
+ { 0x48e0, "IEADCCR"}, /* Enable Control ADC , */\
+ { 0x4900, "IEBSTCU"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "IEBSTHI"}, /* Enable DCDC active , */\
+ { 0x4920, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4930, "IEBSTPC"}, /* Enable bst peakcur , */\
+ { 0x4940, "IEBSTVC"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "IEBST86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "IEBST93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4990, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x49a0, "IEMWSRC"}, /* Enable waits HW I2C settings , */\
+ { 0x49c0, "IEMWSMU"}, /* Enable man Audio mute sequence , */\
+ { 0x49f0, "IECLKOOR"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4a20, "IECLPR"}, /* Enable clip , */\
+ { 0x4a40, "IELP0"}, /* Enable low power mode0 , */\
+ { 0x4a50, "IELP1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "IELA"}, /* Enable low noise detection , */\
+ { 0x4a70, "IEVDDPH"}, /* Enable VDDP greater tehn VBAT , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOPLLS"}, /* Polarity pll lock , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOVDS"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOCLKS"}, /* Polarity clocks stable , */\
+ { 0x4c60, "IPOMTPB"}, /* Polarity mtp busy , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4ca0, "IPOSWS"}, /* Polarity amplifier engage , */\
+ { 0x4cc0, "IPOAMPS"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "IPOAREFS"}, /* Polarity ref enable , */\
+ { 0x4ce0, "IPOADCCR"}, /* Polarity Control ADC , */\
+ { 0x4d00, "IPOBSTCU"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "IPOBSTHI"}, /* Polarity DCDC active , */\
+ { 0x4d20, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "IPOBSTPC"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "IPOBSTVC"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "IPOBST86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "IPOBST93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d90, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "IPOMWSRC"}, /* Polarity waits HW I2C settings , */\
+ { 0x4dc0, "IPOMWSMU"}, /* Polarity man audio mute sequence , */\
+ { 0x4df0, "IPCLKOOR"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4e20, "IPOCLPR"}, /* Polarity clip right , */\
+ { 0x4e40, "IPOLP0"}, /* Polarity low power mode0 , */\
+ { 0x4e50, "IPOLP1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "IPOLA"}, /* Polarity low noise mode , */\
+ { 0x4e70, "IPOVDDPH"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5110, "INTSMUTE"}, /* Soft mute HW , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x6081, "PGAGAIN"}, /* PGA gain selection , */\
+ { 0x60b0, "PGALPE"}, /* Lowpass enable , */\
+ { 0x6110, "LPM0BYP"}, /* bypass low power idle mode , */\
+ { 0x6123, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x61b0, "STIDLEEN"}, /* enable idle feature for channel 1 , */\
+ { 0x62e1, "LNMODE"}, /* ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* low power mode control , */\
+ { 0x65c0, "LPM1DIS"}, /* low power mode1 detector control , */\
+ { 0x6801, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6821, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6841, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6881, "ANCSEL"}, /* anc input , */\
+ { 0x68a0, "ANC1C"}, /* ANC one s complement , */\
+ { 0x6901, "SAMMODE"}, /* sam enable , */\
+ { 0x6920, "SAMSEL"}, /* sam source , */\
+ { 0x6931, "PDMOSELH"}, /* pdm out value when pdm_clk is higth , */\
+ { 0x6951, "PDMOSELL"}, /* pdm out value when pdm_clk is low , */\
+ { 0x6970, "SAMOSEL"}, /* ram output on mode sam and audio , */\
+ { 0x6e00, "LP0"}, /* low power mode 0 detection , */\
+ { 0x6e10, "LP1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* vddp greater than vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* enable current sense compensation , */\
+ { 0x6f60, "SELCLPPWM"}, /* Select pwm clip flag , */\
+ { 0x6f72, "LVLCLPPWM"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7002, "DCVOS"}, /* Second boost voltage level , */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7402, "DCVOF"}, /* 1st boost voltage level , */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa350, "CMTPI"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xee0f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xef0f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9872_BITNAMETABLE static tfaBfName_t Tfa9872BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x140, "enbl_osc1m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b0, "bypass_hvbat_filter"}, /* Bypass HVBAT filter , */\
+ { 0x2d0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker path , */\
+ { 0x530, "enbl_volsense"}, /* Voltage sense , */\
+ { 0x550, "enbl_cursense"}, /* Current sense , */\
+ { 0x560, "enbl_pdm_ss"}, /* Sub-system PDM , */\
+ { 0x580, "enbl_pga_chop"}, /* Enable PGA chop clock , */\
+ { 0x590, "enbl_tdm_ss"}, /* Sub-system TDM , */\
+ { 0x5a0, "enbl_bst_ss"}, /* Sub-system boost , */\
+ { 0x5b0, "enbl_adc_ss"}, /* Sub-system ADC , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0xd18, "side_tone_gain"}, /* Side tone gain , */\
+ { 0xda0, "mute_side_tone"}, /* Side tone soft mute , */\
+ { 0xdb0, "side_tone_1scomplement"}, /* side tone one s complement , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1060, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x10a0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_soft_mute_busy"}, /* side tone (un)mute busy , */\
+ { 0x1180, "flag_soft_mute_state"}, /* side tone mute state , */\
+ { 0x1190, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11a2, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11d0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1340, "flag_clipa_high"}, /* Clipping A to Vddp , */\
+ { 0x1350, "flag_clipa_low"}, /* Clipping A to gnd , */\
+ { 0x1360, "flag_clipb_high"}, /* Clipping B to Vddp , */\
+ { 0x1370, "flag_clipb_low"}, /* Clipping B to gnd , */\
+ { 0x1380, "flag_ocp_alarm"}, /* OCP amplifier , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13b0, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1471, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/9.5 V) , */\
+ { 0x2040, "tdm_enable"}, /* Enable interface , */\
+ { 0x2050, "tdm_mode"}, /* Slave/master , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x3111, "pdm_side_tone_sel"}, /* Side tone input , */\
+ { 0x3201, "pdm_nbck"}, /* PDM BCK/Fs ratio , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_pll_lock"}, /* Status PLL lock , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ovpok"}, /* Status OVP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_clocks_stable"}, /* Status clocks stable , */\
+ { 0x4060, "int_out_flag_mtp_busy"}, /* Status MTP busy , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x40a0, "int_out_flag_engage"}, /* Status amplifier engage , */\
+ { 0x40c0, "int_out_flag_enbl_amp"}, /* Status amplifier enable , */\
+ { 0x40d0, "int_out_flag_enbl_ref"}, /* Status Ref enable , */\
+ { 0x40e0, "int_out_flag_adc10_ready"}, /* Status Control ADC , */\
+ { 0x4100, "int_out_flag_bst_bstcur"}, /* Status DCDC current limiting , */\
+ { 0x4110, "int_out_flag_bst_hiz"}, /* Status DCDC active , */\
+ { 0x4120, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4130, "int_out_flag_bst_peakcur"}, /* Status bst peakcur , */\
+ { 0x4140, "int_out_flag_bst_voutcomp"}, /* Status DCDC level 1x , */\
+ { 0x4150, "int_out_flag_bst_voutcomp86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "int_out_flag_bst_voutcomp93"}, /* Status DCDC level 1.07x , */\
+ { 0x4190, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x41a0, "int_out_flag_man_wait_src_settings"}, /* Status Waits HW I2C settings , */\
+ { 0x41c0, "int_out_flag_man_start_mute_audio"}, /* Status Audio mute sequence , */\
+ { 0x41f0, "int_out_flag_clk_out_of_range"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4220, "int_out_flag_clip"}, /* Status clip , */\
+ { 0x4240, "int_out_flag_lp_detect_mode0"}, /* Status low power mode0 , */\
+ { 0x4250, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 , */\
+ { 0x4260, "int_out_flag_low_amplitude"}, /* Status low noise detection , */\
+ { 0x4270, "int_out_flag_vddp_gt_vbat"}, /* Status VDDP greater than VBAT , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_pll_lock"}, /* Clear PLL lock , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ovpok"}, /* Clear OVP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_clocks_stable"}, /* Clear clocks stable , */\
+ { 0x4460, "int_in_flag_mtp_busy"}, /* Clear mtp busy , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x44a0, "int_in_flag_engage"}, /* Clear amplifier engage , */\
+ { 0x44c0, "int_in_flag_enbl_amp"}, /* Clear enbl amp , */\
+ { 0x44d0, "int_in_flag_enbl_ref"}, /* Clear ref enable , */\
+ { 0x44e0, "int_in_flag_adc10_ready"}, /* Clear control ADC , */\
+ { 0x4500, "int_in_flag_bst_bstcur"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "int_in_flag_bst_hiz"}, /* Clear DCDC active , */\
+ { 0x4520, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4530, "int_in_flag_bst_peakcur"}, /* Clear bst peakcur , */\
+ { 0x4540, "int_in_flag_bst_voutcomp"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "int_in_flag_bst_voutcomp86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "int_in_flag_bst_voutcomp93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4590, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x45a0, "int_in_flag_man_wait_src_settings"}, /* Clear wait HW I2C settings , */\
+ { 0x45c0, "int_in_flag_man_start_mute_audio"}, /* Clear audio mute sequence , */\
+ { 0x45f0, "int_in_flag_clk_out_of_range"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4620, "int_in_flag_clip"}, /* Clear clip , */\
+ { 0x4640, "int_in_flag_lp_detect_mode0"}, /* Clear low power mode0 , */\
+ { 0x4650, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 , */\
+ { 0x4660, "int_in_flag_low_amplitude"}, /* Clear low noise detection , */\
+ { 0x4670, "int_in_flag_vddp_gt_vbat"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_pll_lock"}, /* Enable pll lock , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ovpok"}, /* Enable OVP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_clocks_stable"}, /* Enable clocks stable , */\
+ { 0x4860, "int_enable_flag_mtp_busy"}, /* Enable mtp busy , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x48a0, "int_enable_flag_engage"}, /* Enable amplifier engage , */\
+ { 0x48c0, "int_enable_flag_enbl_amp"}, /* Enable enbl amp , */\
+ { 0x48d0, "int_enable_flag_enbl_ref"}, /* Enable ref enable , */\
+ { 0x48e0, "int_enable_flag_adc10_ready"}, /* Enable Control ADC , */\
+ { 0x4900, "int_enable_flag_bst_bstcur"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "int_enable_flag_bst_hiz"}, /* Enable DCDC active , */\
+ { 0x4920, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4930, "int_enable_flag_bst_peakcur"}, /* Enable bst peakcur , */\
+ { 0x4940, "int_enable_flag_bst_voutcomp"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "int_enable_flag_bst_voutcomp86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "int_enable_flag_bst_voutcomp93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4990, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x49a0, "int_enable_flag_man_wait_src_settings"}, /* Enable waits HW I2C settings , */\
+ { 0x49c0, "int_enable_flag_man_start_mute_audio"}, /* Enable man Audio mute sequence , */\
+ { 0x49f0, "int_enable_flag_clk_out_of_range"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4a20, "int_enable_flag_clip"}, /* Enable clip , */\
+ { 0x4a40, "int_enable_flag_lp_detect_mode0"}, /* Enable low power mode0 , */\
+ { 0x4a50, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "int_enable_flag_low_amplitude"}, /* Enable low noise detection , */\
+ { 0x4a70, "int_enable_flag_vddp_gt_vbat"}, /* Enable VDDP greater tehn VBAT , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_pll_lock"}, /* Polarity pll lock , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ovpok"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_clocks_stable"}, /* Polarity clocks stable , */\
+ { 0x4c60, "int_polarity_flag_mtp_busy"}, /* Polarity mtp busy , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4ca0, "int_polarity_flag_engage"}, /* Polarity amplifier engage , */\
+ { 0x4cc0, "int_polarity_flag_enbl_amp"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "int_polarity_flag_enbl_ref"}, /* Polarity ref enable , */\
+ { 0x4ce0, "int_polarity_flag_adc10_ready"}, /* Polarity Control ADC , */\
+ { 0x4d00, "int_polarity_flag_bst_bstcur"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "int_polarity_flag_bst_hiz"}, /* Polarity DCDC active , */\
+ { 0x4d20, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "int_polarity_flag_bst_peakcur"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "int_polarity_flag_bst_voutcomp"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "int_polarity_flag_bst_voutcomp86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "int_polarity_flag_bst_voutcomp93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d90, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "int_polarity_flag_man_wait_src_settings"}, /* Polarity waits HW I2C settings , */\
+ { 0x4dc0, "int_polarity_flag_man_start_mute_audio"}, /* Polarity man audio mute sequence , */\
+ { 0x4df0, "int_polarity_flag_clk_out_of_range"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4e20, "int_polarity_flag_clip"}, /* Polarity clip right , */\
+ { 0x4e40, "int_polarity_flag_lp_detect_mode0"}, /* Polarity low power mode0 , */\
+ { 0x4e50, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "int_polarity_flag_low_amplitude"}, /* Polarity low noise mode , */\
+ { 0x4e70, "int_polarity_flag_vddp_gt_vbat"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5110, "soft_mute"}, /* Soft mute HW , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for Battery Safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5420, "fb_hz"}, /* Feedback resistor set to high ohmic , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5582, "dpsa_drive"}, /* Drive setting (bin. coded) , */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x6081, "pga_gain_set"}, /* PGA gain selection , */\
+ { 0x60b0, "pga_lowpass_enable"}, /* Lowpass enable , */\
+ { 0x60c0, "pga_pwr_enable"}, /* Power enable, directcontrol mode only , */\
+ { 0x60d0, "pga_switch_enable"}, /* Switch enable, directcontrol mode only , */\
+ { 0x60e0, "pga_switch_aux_enable"}, /* Switch enable aux, directcontrol mode only , */\
+ { 0x6100, "force_idle"}, /* force low power in idle mode , */\
+ { 0x6110, "bypass_idle"}, /* bypass low power idle mode , */\
+ { 0x6123, "ctrl_attl"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x61a0, "idle_cnt"}, /* idle counter , */\
+ { 0x61b0, "enbl_idle_ch1"}, /* enable idle feature for channel 1 , */\
+ { 0x6265, "zero_lvl"}, /* low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_classd"}, /* class D gain ctrl_fb_50k ctrl_fb_100k , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6801, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6821, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6841, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6881, "pdm_anc_sel"}, /* anc input , */\
+ { 0x68a0, "anc_1scomplement"}, /* ANC one s complement , */\
+ { 0x6901, "sam_mode"}, /* sam enable , */\
+ { 0x6920, "sam_src"}, /* sam source , */\
+ { 0x6931, "pdmdat_h_sel"}, /* pdm out value when pdm_clk is higth , */\
+ { 0x6951, "pdmdat_l_sel"}, /* pdm out value when pdm_clk is low , */\
+ { 0x6970, "sam_spkr_sel"}, /* ram output on mode sam and audio , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* disable auto engange , */\
+ { 0x6b10, "sel_tdm_data_valid"}, /* select tdm valid for speaker subsystem , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_lp_detect_mode0"}, /* low power mode 0 detection , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* enable current sense compensation , */\
+ { 0x6f60, "sel_clip_pwms"}, /* Select pwm clip flag , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7002, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7402, "frst_boost_voltage"}, /* 1st boost voltage level , */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Ignore flag_voutcomp86 , */\
+ { 0x7502, "track_decay"}, /* DCDC Boost decay speed after a peak value, effective only when boost_track is set to 1, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x7620, "pga_test_ldo_bypass"}, /* bypass internal PGA LDO , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8200, "enbl_cmfb"}, /* Current sense common mode feedback control , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8222, "cmfb_gain"}, /* Current sense common mode feedback control gain , */\
+ { 0x8254, "cmfb_offset"}, /* Current sense common mode feedback control offset , */\
+ { 0x82a0, "cs_sam_set"}, /* Enable SAM input for current sense , */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8760, "enbl_cs_nofloating_n"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8770, "enbl_cs_nofloating_p"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8800, "volsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0x8810, "vol_cur_sense_dc_offset"}, /* voltage and current sense decimator offset control, */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc5b0, "pga_test_enable"}, /* Enable PGA test mode , */\
+ { 0xc5c0, "pga_test_offset_enable"}, /* Enable PGA test offset , */\
+ { 0xc5d0, "pga_test_shortinput_enable"}, /* Enable PGA test shortinput , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to PDMDAT (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb54, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba4, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xcd64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcdb3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd621, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd641, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd661, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd701, "pdmdat_ehs"}, /* Speed/load setting for PDMDAT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd760, "pdmclk_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* tdm source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_feedback"}, /* gainatt feedback to tdm , */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost , */\
+ { 0xd890, "pdm_loopback"}, /* pdm loop back to tdm , */\
+ { 0xd8a1, "force_pga_clock"}, /* force pga clock , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xee0f, "sw_profile"}, /* Software profile data , */\
+ { 0xef0f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "spare_mpt1_9_6"}, /* HW gain module - left channel (2's complement) , */\
+ { 0xf1a5, "spare_mpt1_15_10"}, /* Offset for amplifier, HW gain module - left channel (2's complement), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a3, "spare_mpt2_13_10"}, /* Trimming of LDO (2.7V) , */\
+ { 0xf307, "spare_mpt3_7_0"}, /* SPARE , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "spare_mtp4_15_0"}, /* SPARE , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf606, "spare_mpt6_6_0"}, /* SPARE , */\
+ { 0xf686, "spare_mpt6_14_8"}, /* Offset of left amplifier level shifter B , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "disable_sam_mode"}, /* Disable same mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Disable programming of max dcdc boost voltage , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf980, "mtp_enbl_amp_in_state_alarm"}, /* Enbl_amp in alarm state , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* pwm delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* ocpclock auto gating , */\
+ { 0xf9b0, "mtp_gate_cgu_clock_for_test"}, /* cgu test clock control , */\
+ { 0xf9c3, "spare_mtp9_15_12"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9872_irq {
+ tfa9872_irq_stvdds = 0,
+ tfa9872_irq_stplls = 1,
+ tfa9872_irq_stotds = 2,
+ tfa9872_irq_stovds = 3,
+ tfa9872_irq_stuvds = 4,
+ tfa9872_irq_stclks = 5,
+ tfa9872_irq_stmtpb = 6,
+ tfa9872_irq_stnoclk = 7,
+ tfa9872_irq_stsws = 10,
+ tfa9872_irq_stamps = 12,
+ tfa9872_irq_starefs = 13,
+ tfa9872_irq_stadccr = 14,
+ tfa9872_irq_stbstcu = 16,
+ tfa9872_irq_stbsthi = 17,
+ tfa9872_irq_stbstoc = 18,
+ tfa9872_irq_stbstpkcur = 19,
+ tfa9872_irq_stbstvc = 20,
+ tfa9872_irq_stbst86 = 21,
+ tfa9872_irq_stbst93 = 22,
+ tfa9872_irq_stocpr = 25,
+ tfa9872_irq_stmwsrc = 26,
+ tfa9872_irq_stmwsmu = 28,
+ tfa9872_irq_stclkoor = 31,
+ tfa9872_irq_sttdmer = 32,
+ tfa9872_irq_stclpr = 34,
+ tfa9872_irq_stlp0 = 36,
+ tfa9872_irq_stlp1 = 37,
+ tfa9872_irq_stla = 38,
+ tfa9872_irq_stvddph = 39,
+ tfa9872_irq_max = 40,
+ tfa9872_irq_all = -1 /* all irqs */};
+
+#define TFA9872_IRQ_NAMETABLE static tfaIrqName_t Tfa9872IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STPLLS"},\
+ { 2, "STOTDS"},\
+ { 3, "STOVDS"},\
+ { 4, "STUVDS"},\
+ { 5, "STCLKS"},\
+ { 6, "STMTPB"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+ { 9, "9"},\
+ { 10, "STSWS"},\
+ { 11, "11"},\
+ { 12, "STAMPS"},\
+ { 13, "STAREFS"},\
+ { 14, "STADCCR"},\
+ { 15, "15"},\
+ { 16, "STBSTCU"},\
+ { 17, "STBSTHI"},\
+ { 18, "STBSTOC"},\
+ { 19, "STBSTPKCUR"},\
+ { 20, "STBSTVC"},\
+ { 21, "STBST86"},\
+ { 22, "STBST93"},\
+ { 23, "23"},\
+ { 24, "24"},\
+ { 25, "STOCPR"},\
+ { 26, "STMWSRC"},\
+ { 27, "27"},\
+ { 28, "STMWSMU"},\
+ { 29, "29"},\
+ { 30, "30"},\
+ { 31, "STCLKOOR"},\
+ { 32, "STTDMER"},\
+ { 33, "33"},\
+ { 34, "STCLPR"},\
+ { 35, "35"},\
+ { 36, "STLP0"},\
+ { 37, "STLP1"},\
+ { 38, "STLA"},\
+ { 39, "STVDDPH"},\
+ { 40, "40"},\
+};
+#endif /* _TFA9872_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames.h
new file mode 100644
index 00000000000..726ffe066a8
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames.h
@@ -0,0 +1,934 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9873_tfaFieldnames.h
+ * This file was generated automatically on 10/21/19 at 17:03:34.
+ * Source file: TFA9873_PRB4_N1A0_I2C_RegisterMap.xlsx
+ */
+
+#ifndef _TFA9873_TFAFIELDNAMES_H
+#define _TFA9873_TFAFIELDNAMES_H
+
+
+#define TFA9873_I2CVERSION 28
+
+typedef enum Tfa9873BfEnumList {
+ TFA9873_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9873_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9873_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9873_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9873_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9873_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9873_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9873_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9873_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9873_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9873_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9873_BF_MUTETO= 0x0160, /*!< Time out SB mute sequence */
+ TFA9873_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9873_BF_DISFCRBST= 0x01f0, /*!< Disable boost control with FRCBST */
+ TFA9873_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9873_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9873_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9873_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9873_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9873_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9873_BF_MANAOOSC= 0x0460, /*!< Internal osc off in power down mode */
+ TFA9873_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9873_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9873_BF_AUTOFROSEL= 0x04a0, /*!< Override automatic OSC selection mechanism */
+ TFA9873_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9873_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9873_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9873_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9873_BF_CLKCHKLO= 0x0707, /*!< Clock check low threshold */
+ TFA9873_BF_CLKCHKHI= 0x0787, /*!< Clock check higher threshold */
+ TFA9873_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9873_BF_VDDS = 0x1000, /*!< POR */
+ TFA9873_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9873_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register, clear on read) */
+ TFA9873_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9873_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register, clear on read) */
+ TFA9873_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9873_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9873_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9873_BF_NOCLK = 0x1080, /*!< Lost clock (sticky register, clear on read) */
+ TFA9873_BF_TDMERR= 0x10a0, /*!< TDM error */
+ TFA9873_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9873_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9873_BF_DCDCPC= 0x1120, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9873_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9873_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9873_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9873_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9873_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9873_BF_CLKOOR= 0x11c0, /*!< External clock status */
+ TFA9873_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9873_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9873_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9873_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9873_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9873_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9873_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9873_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9873_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9873_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9873_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9873_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9873_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9873_BF_TDMSTAT= 0x1402, /*!< TDM status bits */
+ TFA9873_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9873_BF_AMPSTE= 0x1473, /*!< Amplifier control status */
+ TFA9873_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9873_BF_WAITSYNC= 0x14d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9873_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9873_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9873_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9873_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9873_BF_TDMSLOTS= 0x2013, /*!< N-slots in Frame */
+ TFA9873_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9873_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9873_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9873_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9873_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9873_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9873_BF_TDMDEL= 0x21e0, /*!< Data delay to FS */
+ TFA9873_BF_TDMADJ= 0x21f0, /*!< Data adjustment */
+ TFA9873_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9873_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9873_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9873_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9873_BF_TDMSPKE= 0x2300, /*!< Control audio TDM channel in 0 */
+ TFA9873_BF_TDMDCE= 0x2310, /*!< Control audio TDM channel in 1 */
+ TFA9873_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9873_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9873_BF_TDMSPKS= 0x2603, /*!< TDM slot for sink 0 */
+ TFA9873_BF_TDMDCS= 0x2643, /*!< TDM slot for sink 1 */
+ TFA9873_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9873_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9873_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9873_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9873_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9873_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9873_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9873_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9873_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9873_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9873_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9873_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9873_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9873_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9873_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9873_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9873_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9873_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9873_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9873_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9873_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9873_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9873_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9873_BF_IEMANALARM= 0x4850, /*!< Enable manager alarm state */
+ TFA9873_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9873_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9873_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9873_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9873_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9873_BF_IPOOCPR= 0x4c30, /*!< Polarity OCP alarm */
+ TFA9873_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9873_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9873_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9873_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9873_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9873_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9873_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9873_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9873_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9873_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9873_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9873_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9873_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9873_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9873_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9873_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9873_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9873_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9873_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9873_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9873_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9873_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9873_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9873_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9873_BF_TDMSRCACLIP= 0x6871, /*!< Clip information (analog /digital) for source0 */
+ TFA9873_BF_TDMSRCBCLIP= 0x6891, /*!< Clip information (analog /digital) for source1 */
+ TFA9873_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9873_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9873_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9873_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9873_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9873_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9873_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9873_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9873_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9873_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9873_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9873_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9873_BF_DCOVL = 0x7085, /*!< Threshold level to activate active overshoot control */
+ TFA9873_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9873_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9873_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9873_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9873_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9873_BF_ENBSTFLT= 0x7620, /*!< Enable the boost filter */
+ TFA9873_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9873_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9873_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9873_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9873_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9873_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9873_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9873_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9873_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9873_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9873_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9873_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9873_BF_PLLINSI= 0xcd05, /*!< PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1 */
+ TFA9873_BF_PLLINSP= 0xcd64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873_BF_PLLINSR= 0xcdb3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection control, USE WITH CAUTION */
+ TFA9873_BF_PLLNDEC= 0xce09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLMDECM= 0xcea0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLBP = 0xceb0, /*!< PLL bypass control during functional mode */
+ TFA9873_BF_PLLDI = 0xcec0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLDO = 0xced0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLCLKSTB= 0xcee0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLFRM= 0xcef0, /*!< PLL free running mode control in functional mode */
+ TFA9873_BF_PLLMDECL= 0xcf0f, /*!< Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLPDEC= 0xd006, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873_BF_PLLDCTRL= 0xd070, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9873_BF_PLLLIMOFF= 0xd090, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9873_BF_PLLSTRTM= 0xd0a2, /*!< PLL startup time selection control */
+ TFA9873_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9873_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9873_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9873_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9873_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9873_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9873_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9873_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9873_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9873BfEnumList_t;
+#define TFA9873_NAMETABLE static tfaBfName_t Tfa9873DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x160, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "DISFCRBST"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal osc off in power down mode , */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "AUTOFROSEL"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x707, "CLKCHKLO"}, /* Clock check low threshold , */\
+ { 0x787, "CLKCHKHI"}, /* Clock check higher threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "TDMERR"}, /* TDM error , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11c0, "CLKOOR"}, /* External clock status , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1402, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1473, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x14d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2013, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable manager alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7085, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLINSI"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "PLLINSP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "PLLINSR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "PLLMDECM"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "PLLBP"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "PLLDI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "PLLDO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "PLLCLKSTB"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "PLLMDECL"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "PLLDCTRL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9873_BITNAMETABLE static tfaBfName_t Tfa9873BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x160, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "disable_frcbst"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal osc off in power down mode , */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "override_auto_sel_osc"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x707, "clkchk_th_lo"}, /* Clock check low threshold , */\
+ { 0x787, "clkchk_th_hi"}, /* Clock check higher threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11c0, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1402, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x14d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2013, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable manager alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA release time , */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5463, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x5500, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5513, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5552, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x5581, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5631, "ref_irefdist_set_ctrl"}, /* Scaling of reference current for OCP , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5900, "sel_pwm_freq"}, /* Control for selection for PWM switching frequency , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6631, "pfm2pwm_cnt_max"}, /* Number of pulses in PFM mode before going to PWM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* Disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7085, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC , */\
+ { 0x72a5, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8887, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xb200, "bypass_ovpglitchfilter"}, /* Bypass glitch filter on over voltage protection signal from analog, */\
+ { 0xb210, "enbl_ovp_alarm_state"}, /* Allow manager to go into alarm state when OVP (only when ctrl_vpalarm is 0), */\
+ { 0xb220, "amp_in_tristate_when_ovp"}, /* Brings amplifier in tristate when OVP (only when ctrl_enbl_ovp_alarm_state is 0) , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_tdm_feedback"}, /* GainAtt feedback to TDM , */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd890, "railclamp_disable"}, /* ESD rail clamp control, controls amp and boost rail clamp for ESD, */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xd920, "enbl_irefcal"}, /* Enable IREF calibration , */\
+ { 0xd930, "start_iref_calibration"}, /* Start IREF Calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xda80, "iref_calibration_done"}, /* IREF Calibration done - Read Only , */\
+ { 0xda94, "iref_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xdae0, "iref_calibration_error"}, /* IREF Calibration done - Read Only , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs1"}, /* Voltage sense gain when external voltage sensing input is selected, */\
+ { 0xf387, "calibr_gain_vs2"}, /* Voltage sense gain when internal voltage sensing input is selected, */\
+ { 0xf407, "vs_trim1"}, /* VS Trimming when external voltage sensing input is selected, */\
+ { 0xf487, "vs_trim2"}, /* VS Trimming when internal voltage sensing input is selected, */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9873_irq {
+ tfa9873_irq_stvdds = 0,
+ tfa9873_irq_stbstoc = 1,
+ tfa9873_irq_stotds = 2,
+ tfa9873_irq_stocpr = 3,
+ tfa9873_irq_stuvds = 4,
+ tfa9873_irq_stmanalarm = 5,
+ tfa9873_irq_sttdmer = 6,
+ tfa9873_irq_stnoclk = 7,
+ tfa9873_irq_max = 8,
+ tfa9873_irq_all = -1 /* all irqs */};
+
+#define TFA9873_IRQ_NAMETABLE static tfaIrqName_t Tfa9873IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+};
+#endif /* _TFA9873_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames_B0.h b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames_B0.h
new file mode 100644
index 00000000000..7bd0a99256d
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9873_tfafieldnames_B0.h
@@ -0,0 +1,933 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+
+#ifndef _TFA9873_TFAFIELDNAMES_B0_H
+#define _TFA9873_TFAFIELDNAMES_B0_H
+
+
+#define TFA9873B0_I2CVERSION 20
+
+typedef enum Tfa9873B0BfEnumList {
+ TFA9873B0_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9873B0_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9873B0_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9873B0_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9873B0_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9873B0_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9873B0_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9873B0_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9873B0_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9873B0_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9873B0_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9873B0_BF_MUTETO= 0x0160, /*!< Time out SB mute sequence */
+ TFA9873B0_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9873B0_BF_DISFCRBST= 0x01f0, /*!< Disable boost control with FRCBST */
+ TFA9873B0_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9873B0_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9873B0_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9873B0_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9873B0_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9873B0_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9873B0_BF_MANAOOSC= 0x0460, /*!< Internal osc off in power down mode */
+ TFA9873B0_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9873B0_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9873B0_BF_AUTOFROSEL= 0x04a0, /*!< Override automatic OSC selection mechanism */
+ TFA9873B0_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9873B0_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9873B0_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9873B0_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9873B0_BF_CLKCHKLO= 0x0707, /*!< Clock check low threshold */
+ TFA9873B0_BF_CLKCHKHI= 0x0787, /*!< Clock check higher threshold */
+ TFA9873B0_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9873B0_BF_VDDS = 0x1000, /*!< POR */
+ TFA9873B0_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9873B0_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register, clear on read) */
+ TFA9873B0_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9873B0_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register, clear on read) */
+ TFA9873B0_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9873B0_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9873B0_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9873B0_BF_NOCLK = 0x1080, /*!< Lost clock (sticky register, clear on read) */
+ TFA9873B0_BF_TDMERR= 0x10a0, /*!< TDM error */
+ TFA9873B0_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9873B0_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9873B0_BF_DCDCPC= 0x1120, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9873B0_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9873B0_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9873B0_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9873B0_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9873B0_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9873B0_BF_CLKOOR= 0x11c0, /*!< External clock status */
+ TFA9873B0_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9873B0_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9873B0_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9873B0_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9873B0_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9873B0_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9873B0_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9873B0_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9873B0_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9873B0_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9873B0_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9873B0_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9873B0_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9873B0_BF_TDMSTAT= 0x1402, /*!< TDM status bits */
+ TFA9873B0_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9873B0_BF_AMPSTE= 0x1473, /*!< Amplifier control status */
+ TFA9873B0_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9873B0_BF_WAITSYNC= 0x14d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9873B0_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9873B0_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9873B0_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9873B0_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9873B0_BF_TDMSLOTS= 0x2013, /*!< N-slots in Frame */
+ TFA9873B0_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9873B0_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9873B0_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9873B0_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9873B0_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9873B0_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9873B0_BF_TDMDEL= 0x21e0, /*!< Data delay to FS */
+ TFA9873B0_BF_TDMADJ= 0x21f0, /*!< Data adjustment */
+ TFA9873B0_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9873B0_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9873B0_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9873B0_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9873B0_BF_TDMSPKE= 0x2300, /*!< Control audio TDM channel in 0 */
+ TFA9873B0_BF_TDMDCE= 0x2310, /*!< Control audio TDM channel in 1 */
+ TFA9873B0_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_TDMSPKS= 0x2603, /*!< TDM slot for sink 0 */
+ TFA9873B0_BF_TDMDCS= 0x2643, /*!< TDM slot for sink 1 */
+ TFA9873B0_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9873B0_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9873B0_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9873B0_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9873B0_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9873B0_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9873B0_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9873B0_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9873B0_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9873B0_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9873B0_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9873B0_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9873B0_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9873B0_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9873B0_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9873B0_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9873B0_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9873B0_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9873B0_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9873B0_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9873B0_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9873B0_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9873B0_BF_IEMANALARM= 0x4850, /*!< Enable manager alarm state */
+ TFA9873B0_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9873B0_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9873B0_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9873B0_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9873B0_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9873B0_BF_IPOOCPR= 0x4c30, /*!< Polarity OCP alarm */
+ TFA9873B0_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9873B0_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9873B0_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9873B0_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9873B0_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9873B0_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9873B0_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9873B0_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9873B0_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9873B0_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9873B0_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9873B0_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9873B0_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9873B0_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9873B0_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9873B0_BF_SLOPEE= 0x55a0, /*!< Enables slope control */
+ TFA9873B0_BF_SLOPESET= 0x55b0, /*!< Slope speed setting */
+ TFA9873B0_BF_PWMFREQ= 0x5900, /*!< Control for selection for PWM switching frequency */
+ TFA9873B0_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9873B0_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9873B0_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9873B0_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9873B0_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9873B0_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9873B0_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9873B0_BF_TDMSRCACLIP= 0x6871, /*!< Clip information (analog /digital) for source0 */
+ TFA9873B0_BF_TDMSRCBCLIP= 0x6891, /*!< Clip information (analog /digital) for source1 */
+ TFA9873B0_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9873B0_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9873B0_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9873B0_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9873B0_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9873B0_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9873B0_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9873B0_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9873B0_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9873B0_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9873B0_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9873B0_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9873B0_BF_DCOVL = 0x7085, /*!< Threshold level to activate active overshoot control */
+ TFA9873B0_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9873B0_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9873B0_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9873B0_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873B0_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9873B0_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9873B0_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9873B0_BF_ENBSTFLT= 0x7620, /*!< Enable the boost filter */
+ TFA9873B0_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9873B0_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9873B0_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9873B0_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9873B0_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9873B0_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9873B0_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9873B0_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9873B0_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9873B0_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9873B0_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9873B0_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9873B0_BF_PLLINSI= 0xcd05, /*!< PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLINSP= 0xcd64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLINSR= 0xcdb3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection control, USE WITH CAUTION */
+ TFA9873B0_BF_PLLNDEC= 0xce09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLMDECM= 0xcea0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLBP = 0xceb0, /*!< PLL bypass control during functional mode */
+ TFA9873B0_BF_PLLDI = 0xcec0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLDO = 0xced0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLCLKSTB= 0xcee0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLFRM= 0xcef0, /*!< PLL free running mode control in functional mode */
+ TFA9873B0_BF_PLLMDECL= 0xcf0f, /*!< Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLPDEC= 0xd006, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9873B0_BF_PLLDCTRL= 0xd070, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9873B0_BF_PLLLIMOFF= 0xd090, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9873B0_BF_PLLSTRTM= 0xd0a2, /*!< PLL startup time selection control */
+ TFA9873B0_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9873B0_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9873B0_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9873B0_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9873B0_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9873B0_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9873B0_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9873B0_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9873B0_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9873B0BfEnumList_t;
+#define TFA9873B0_NAMETABLE static tfaBfName_t Tfa9873B0DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x160, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "DISFCRBST"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal osc off in power down mode , */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "AUTOFROSEL"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x707, "CLKCHKLO"}, /* Clock check low threshold , */\
+ { 0x787, "CLKCHKHI"}, /* Clock check higher threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "TDMERR"}, /* TDM error , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11c0, "CLKOOR"}, /* External clock status , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1402, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1473, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x14d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2013, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable manager alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x55a0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x55b0, "SLOPESET"}, /* Slope speed setting , */\
+ { 0x5900, "PWMFREQ"}, /* Control for selection for PWM switching frequency , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7085, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLINSI"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "PLLINSP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "PLLINSR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "PLLMDECM"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "PLLBP"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "PLLDI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "PLLDO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "PLLCLKSTB"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "PLLMDECL"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "PLLDCTRL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9873B0_BITNAMETABLE static tfaBfName_t Tfa9873B0BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x160, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "disable_frcbst"}, /* Disable boost control with FRCBST , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal osc off in power down mode , */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "override_auto_sel_osc"}, /* Override automatic OSC selection mechanism , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x707, "clkchk_th_lo"}, /* Clock check low threshold , */\
+ { 0x787, "clkchk_th_hi"}, /* Clock check higher threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register, clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register, clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock (sticky register, clear on read) , */\
+ { 0x10a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11c0, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1402, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x14d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2013, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2643, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable manager alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA release time , */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5463, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x54a1, "ref_amp_irefdist_set_ctrl"}, /* Scaling of reference current for amplifier OCP , */\
+ { 0x5500, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5513, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5552, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x5581, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x55a0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x55b0, "ctrl_slope"}, /* Slope speed setting , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5900, "sel_pwm_freq"}, /* Control for selection for PWM switching frequency , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* Disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7085, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC , */\
+ { 0x72a5, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7360, "disable_artf676996_fix"}, /* Disables the fix for artf676996 (OCP booster triggered when Vtrgt is just above Vbat), */\
+ { 0x7371, "ref_bst_irefdist_set_ctrl"}, /* Scaling of reference current for booster OCP , */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7620, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8887, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xb200, "bypass_ovpglitchfilter"}, /* Bypass glitch filter on over voltage protection signal from analog, */\
+ { 0xb210, "enbl_ovp_alarm_state"}, /* Allow manager to go into alarm state when OVP (only when ctrl_vpalarm is 0), */\
+ { 0xb220, "amp_in_tristate_when_ovp"}, /* Brings amplifier in tristate when OVP (only when ctrl_enbl_ovp_alarm_state is 0) , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode, only with pll_bandsel set to 1, */\
+ { 0xcd64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15 to 0 of PLL MDEC in direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_tdm_feedback"}, /* GainAtt feedback to TDM , */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xd920, "enbl_irefcal"}, /* Enable IREF calibration , */\
+ { 0xd930, "start_iref_calibration"}, /* Start IREF Calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xda80, "iref_calibration_done"}, /* IREF Calibration done - Read Only , */\
+ { 0xda94, "iref_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xdae0, "iref_calibration_error"}, /* IREF Calibration done - Read Only , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs1"}, /* Voltage sense gain when external voltage sensing input is selected, */\
+ { 0xf387, "calibr_gain_vs2"}, /* Voltage sense gain when internal voltage sensing input is selected, */\
+ { 0xf407, "vs_trim1"}, /* VS Trimming when external voltage sensing input is selected, */\
+ { 0xf487, "vs_trim2"}, /* VS Trimming when internal voltage sensing input is selected, */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "mtp_pll_lut_sel"}, /* PLL lookup table selection control , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+#if 0
+enum tfa9873_irq {
+ tfa9873_irq_stvdds = 0,
+ tfa9873_irq_stbstoc = 1,
+ tfa9873_irq_stotds = 2,
+ tfa9873_irq_stocpr = 3,
+ tfa9873_irq_stuvds = 4,
+ tfa9873_irq_stmanalarm = 5,
+ tfa9873_irq_sttdmer = 6,
+ tfa9873_irq_stnoclk = 7,
+ tfa9873_irq_max = 8,
+ tfa9873_irq_all = -1 /* all irqs */};
+#endif//
+#define TFA9873_IRQ_NAMETABLE static tfaIrqName_t Tfa9873IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+};
+#endif /* _TFA9873_TFAFIELDNAMES_B0_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9874_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9874_tfafieldnames.h
new file mode 100644
index 00000000000..7fba0d68960
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9874_tfafieldnames.h
@@ -0,0 +1,843 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9874_tfaFieldnames_last.h
+ * This file was generated automatically on 09/28/18 at 11:20:52.
+ * Source file: TFA9874N1C0_DefaultI2CSettings.xlsx
+ */
+
+#ifndef _TFA9874_TFAFIELDNAMES_H
+#define _TFA9874_TFAFIELDNAMES_H
+
+
+#define TFA9874_I2CVERSION 1.16
+
+typedef enum Tfa9874BfEnumList {
+ TFA9874_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9874_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9874_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA9874_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9874_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9874_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9874_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9874_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9874_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA9874_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA9874_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9874_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9874_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9874_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9874_BF_REV = 0x030f, /*!< Revision info */
+ TFA9874_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9874_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9874_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9874_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9874_BF_VDDS = 0x1000, /*!< POR */
+ TFA9874_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register , clear on read) */
+ TFA9874_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register , clear on read) */
+ TFA9874_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register , clear on read) */
+ TFA9874_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register , clear on read) */
+ TFA9874_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9874_BF_TDMERR= 0x1060, /*!< TDM error */
+ TFA9874_BF_NOCLK = 0x1070, /*!< Lost clock (sticky register , clear on read) */
+ TFA9874_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9874_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register , clear on read) */
+ TFA9874_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9874_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9874_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9874_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9874_BF_CLKS = 0x1170, /*!< Clocks stable */
+ TFA9874_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9874_BF_TDMSTAT= 0x1192, /*!< TDM status bits */
+ TFA9874_BF_MTPB = 0x11c0, /*!< MTP busy */
+ TFA9874_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9874_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9874_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9874_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9874_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9874_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9874_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9874_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9874_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9874_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9874_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9874_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9874_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9874_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA9874_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9874_BF_DCMODE= 0x1471, /*!< DCDC mode status bits */
+ TFA9874_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9874_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9874_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9874_BF_TDME = 0x2040, /*!< Enable interface */
+ TFA9874_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA9874_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9874_BF_TDMFSLN= 0x2073, /*!< FS length (master mode only) */
+ TFA9874_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9874_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9874_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA9874_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9874_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9874_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9874_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9874_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9874_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9874_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9874_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9874_BF_TDMSPKE= 0x2300, /*!< Control audio tdm channel in 0 (spkr + dcdc) */
+ TFA9874_BF_TDMDCE= 0x2310, /*!< Control audio tdm channel in 1 (dcdc) */
+ TFA9874_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9874_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9874_BF_TDMSPKS= 0x2603, /*!< tdm slot for sink 0 (speaker + dcdc) */
+ TFA9874_BF_TDMDCS= 0x2643, /*!< tdm slot for sink 1 (dcdc) */
+ TFA9874_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9874_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9874_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9874_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9874_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9874_BF_ISTOCPR= 0x4030, /*!< Status ocp alarm */
+ TFA9874_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9874_BF_ISTMANALARM= 0x4050, /*!< Status nanager Alarm state */
+ TFA9874_BF_ISTTDMER= 0x4060, /*!< Status tdm error */
+ TFA9874_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9874_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9874_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9874_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9874_BF_ICLOCPR= 0x4430, /*!< Clear ocp alarm */
+ TFA9874_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9874_BF_ICLMANALARM= 0x4450, /*!< clear nanager Alarm state */
+ TFA9874_BF_ICLTDMER= 0x4460, /*!< Clear tdm error */
+ TFA9874_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9874_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9874_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9874_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9874_BF_IEOCPR= 0x4830, /*!< Enable ocp alarm */
+ TFA9874_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9874_BF_IEMANALARM= 0x4850, /*!< Enable nanager Alarm state */
+ TFA9874_BF_IETDMER= 0x4860, /*!< Enable tdm error */
+ TFA9874_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9874_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9874_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9874_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9874_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9874_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9874_BF_IPOMANALARM= 0x4c50, /*!< Polarity nanager Alarm state */
+ TFA9874_BF_IPOTDMER= 0x4c60, /*!< Polarity tdm error */
+ TFA9874_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9874_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time */
+ TFA9874_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9874_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9874_BF_VBATFLTL= 0x5080, /*!< vbat filter limit */
+ TFA9874_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9874_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9874_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9874_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9874_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9874_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9874_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9874_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9874_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9874_BF_TDMDCG= 0x6123, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9874_BF_TDMSPKG= 0x6163, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9874_BF_LNMODE= 0x62e1, /*!< ctrl select mode */
+ TFA9874_BF_LPM1MODE= 0x64e1, /*!< low power mode control */
+ TFA9874_BF_TDMSRCMAP= 0x6802, /*!< tdm source mapping */
+ TFA9874_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9874_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9874_BF_TDMSRCACLIP= 0x6871, /*!< clip information (analog /digital) for source0 */
+ TFA9874_BF_TDMSRCBCLIP= 0x6891, /*!< clip information (analog /digital) for source1 */
+ TFA9874_BF_LP1 = 0x6e10, /*!< low power mode 1 detection */
+ TFA9874_BF_LA = 0x6e20, /*!< low amplitude detection */
+ TFA9874_BF_VDDPH = 0x6e30, /*!< vddp greater than vbat */
+ TFA9874_BF_DELCURCOMP= 0x6f02, /*!< delay to allign compensation signal with current sense signal */
+ TFA9874_BF_SIGCURCOMP= 0x6f40, /*!< polarity of compensation for current sense */
+ TFA9874_BF_ENCURCOMP= 0x6f50, /*!< enable current sense compensation */
+ TFA9874_BF_LVLCLPPWM= 0x6f72, /*!< set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9874_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA9874_BF_DCCV = 0x7071, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9874_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA9874_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA9874_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9874_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9874_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9874_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9874_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9874_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9874_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9874_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9874_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9874_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9874_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9874_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9874_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9874_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9874_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9874_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9874_BF_SWPROFIL= 0xee0f, /*!< Software profile data */
+ TFA9874_BF_SWVSTEP= 0xef0f, /*!< Software vstep information */
+ TFA9874_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9874_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9874_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9874_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9874_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9874_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9874_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9874BfEnumList_t;
+#define TFA9874_NAMETABLE static tfaBfName_t Tfa9874DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "TDMERR"}, /* TDM error , */\
+ { 0x1070, "NOCLK"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1170, "CLKS"}, /* Clocks stable , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x1192, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11c0, "MTPB"}, /* MTP busy , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1471, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2040, "TDME"}, /* Enable interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "TDMDCE"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status nanager Alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* clear nanager Alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5080, "VBATFLTL"}, /* vbat filter limit , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x6123, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x62e1, "LNMODE"}, /* ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6e10, "LP1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* vddp greater than vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xee0f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xef0f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9874_BITNAMETABLE static tfaBfName_t Tfa9874BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x140, "enbl_osc1m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2d0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1170, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x1192, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11c0, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1471, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2040, "tdm_enable"}, /* Enable interface , */\
+ { 0x2050, "tdm_mode"}, /* Slave/master , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio tdm channel in 0 (spkr + dcdc) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio tdm channel in 1 (dcdc) , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* tdm slot for sink 0 (speaker + dcdc) , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for sink 1 (dcdc) , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status nanager Alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* clear nanager Alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5080, "vbat_flt_limit"}, /* vbat filter limit , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for Battery Safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5582, "dpsa_drive"}, /* Drive setting (bin. coded) , */\
+ { 0x5690, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x56a1, "enbl_odd_up_even_down"}, /* Control for PWM reference sawtooth generartion , */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x6123, "ctrl_attl"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x6163, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6265, "zero_lvl"}, /* low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7360, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8801, "volsense_pwm_sel"}, /* Voltage sense source selection control , */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8870, "vs_igen_supply"}, /* Switch internal supply of current generator , */\
+ { 0x8887, "vs_gain"}, /* voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d10, "vs_classd_tran_skip"}, /* Skip voltage sense connection during a classD amplifier transition, */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* voltage sense Direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to PDMDAT (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xcd64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcdb3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd621, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd641, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd661, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* tdm source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_feedback"}, /* gainatt feedback to tdm , */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xee0f, "sw_profile"}, /* Software profile data , */\
+ { 0xef0f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf169, "spare_mpt1_15_6"}, /* SPARE , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a5, "spare_mtp2_15_10"}, /* SPARE , */\
+ { 0xf307, "calibr_gain_vs"}, /* Voltage sense gain , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf407, "spare_mtp4_15_0"}, /* SPARE , */\
+ { 0xf487, "vs_trim"}, /* VS Trimming , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf60f, "spare_mpt6_6_0"}, /* SPARE , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf770, "spare_mtp7_07"}, /* SPARE , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf7f0, "spare_mtp7_15"}, /* SPARE , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "spare_mtp9_1"}, /* SPARE , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf980, "spare_mtp9_8"}, /* SPARE , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* pwm delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* ocpclock auto gating , */\
+ { 0xf9b0, "mtp_gate_cgu_clock_for_test"}, /* cgu test clock control , */\
+ { 0xf9c0, "mtp_tdm_pad_sel"}, /* tdm pad selection , */\
+ { 0xf9d2, "spare_mtp9_15_12"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xff87, "spare_mtp7_15_08"}, /* SPARE , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9874_irq {
+ tfa9874_irq_stvdds = 0,
+ tfa9874_irq_stbstoc = 1,
+ tfa9874_irq_stotds = 2,
+ tfa9874_irq_stocpr = 3,
+ tfa9874_irq_stuvds = 4,
+ tfa9874_irq_stmanalarm = 5,
+ tfa9874_irq_sttdmer = 6,
+ tfa9874_irq_stnoclk = 7,
+ tfa9874_irq_max = 8,
+ tfa9874_irq_all = -1 /* all irqs */};
+
+#define TFA9874_IRQ_NAMETABLE static tfaIrqName_t Tfa9874IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "8"},\
+};
+#endif /* _TFA9874_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames.h
new file mode 100644
index 00000000000..6f053bf48e6
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames.h
@@ -0,0 +1,936 @@
+/*
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _TFA9875_TFAFIELDNAMES_H
+#define _TFA9875_TFAFIELDNAMES_H
+
+
+#define TFA9875_I2CVERSION 26
+
+typedef enum Tfa9875BfEnumList {
+ TFA9875_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9875_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9875_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9875_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9875_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9875_BF_BYPUVP= 0x00a0, /*!< Bypass UVP */
+ TFA9875_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9875_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9875_BF_MANWTIME= 0x00d0, /*!< Manager wait time selection control */
+ TFA9875_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9875_BF_COORHYS= 0x00f0, /*!< Select hysteresis for clock range detector */
+ TFA9875_BF_MANSCONF= 0x0120, /*!< Configuration setting if I2C settings are uploaded by the host */
+ TFA9875_BF_MUTETO= 0x0160, /*!< Time out mute sequence */
+ TFA9875_BF_MANROBOD= 0x0170, /*!< Controls the reaction of the device on BOD */
+ TFA9875_BF_BODHYS= 0x0180, /*!< Enable Hysteresis of BOD */
+ TFA9875_BF_BODFILT= 0x0191, /*!< BOD filter */
+ TFA9875_BF_BODTHLVL= 0x01b1, /*!< BOD threshold level */
+ TFA9875_BF_MANEDCTH= 0x01d0, /*!< Device response to too high DC level flag (DCTH = 1) */
+ TFA9875_BF_OPENMTP= 0x01e0, /*!< Control for MTP protection */
+ TFA9875_BF_AUDFS = 0x0203, /*!< Sample rate (Fs) */
+ TFA9875_BF_ENLBW = 0x0240, /*!< CS/VS decimator low bandwidth mode control */
+ TFA9875_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9875_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9875_BF_REFCKEXT= 0x0400, /*!< PLL external ref clock */
+ TFA9875_BF_MANAOOSC= 0x0460, /*!< Internal oscillator control during power down mode */
+ TFA9875_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9875_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9875_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9875_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9875_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9875_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM (MTP) */
+ TFA9875_BF_VDDS = 0x1000, /*!< POR (sticky flag, clear on write a '1') */
+ TFA9875_BF_OTDS = 0x1010, /*!< OTP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_UVDS = 0x1020, /*!< UVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OVDS = 0x1030, /*!< OVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCDS = 0x1040, /*!< OCP amplifier (sticky flag, clear on write a '1') */
+ TFA9875_BF_NOCLK = 0x1050, /*!< Lost clock (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKOOR= 0x1060, /*!< External clock status (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCOCPOK= 0x1070, /*!< DCDC OCP nmos (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCIL = 0x1080, /*!< DCDC current limiting (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCDCA = 0x1090, /*!< DCDC active (sticky flag, clear on write a '1') */
+ TFA9875_BF_ADCCR = 0x10a0, /*!< ADC ready flag (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAP= 0x10b0, /*!< OCPOK pmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAN= 0x10c0, /*!< OCPOK nmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBP= 0x10d0, /*!< OCPOK pmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBN= 0x10e0, /*!< OCPOK nmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCTH = 0x10f0, /*!< DC level on audio input stream too high (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKS = 0x1100, /*!< Clocks stable */
+ TFA9875_BF_MTPB = 0x1110, /*!< MTP busy */
+ TFA9875_BF_TDMERR= 0x1120, /*!< TDM error */
+ TFA9875_BF_DCDCPC= 0x1130, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9875_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9875_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9875_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9875_BF_PLLS = 0x1170, /*!< PLL lock */
+ TFA9875_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9875_BF_SWS = 0x1190, /*!< Amplifier engage */
+ TFA9875_BF_AMPS = 0x11a0, /*!< Amplifier enable */
+ TFA9875_BF_AREFS = 0x11b0, /*!< References enable */
+ TFA9875_BF_CLIPS = 0x11c0, /*!< Amplifier clipping */
+ TFA9875_BF_MANSTATE= 0x1203, /*!< Device manager status */
+ TFA9875_BF_AMPSTE= 0x1243, /*!< Amplifier control status */
+ TFA9875_BF_TDMSTAT= 0x1282, /*!< TDM status bits */
+ TFA9875_BF_DCMODE= 0x12b1, /*!< DCDC mode status bits */
+ TFA9875_BF_WAITSYNC= 0x12d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9875_BF_BODNOK= 0x1300, /*!< BOD Flag VDD NOT OK (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCLD = 0x140c, /*!< DC level detected by DC protection module (2s complement) */
+ TFA9875_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9875_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9875_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9875_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9875_BF_AMPINSEL= 0x2011, /*!< Amplifier input selection */
+ TFA9875_BF_INPLEV= 0x2030, /*!< TDM output attenuation */
+ TFA9875_BF_TDMCLINV= 0x2040, /*!< Reception data to BCK clock */
+ TFA9875_BF_TDMFSPOL= 0x2050, /*!< FS polarity */
+ TFA9875_BF_TDMSLOTS= 0x2061, /*!< N-slots in Frame */
+ TFA9875_BF_TDMSLLN= 0x2081, /*!< N-bits in slot */
+ TFA9875_BF_TDMSSIZE= 0x20a1, /*!< Sample size per slot */
+ TFA9875_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9875_BF_TDMDEL= 0x2100, /*!< Data delay to FS */
+ TFA9875_BF_TDMADJ= 0x2110, /*!< Data adjustment */
+ TFA9875_BF_TDMSPKE= 0x2120, /*!< Control audio TDM channel in 0 */
+ TFA9875_BF_TDMDCE= 0x2130, /*!< Control audio TDM channel in 1 */
+ TFA9875_BF_TDMSRC0E= 0x2140, /*!< Enable TDM source0 data channel */
+ TFA9875_BF_TDMSRC1E= 0x2150, /*!< Enable TDM source1 data channel */
+ TFA9875_BF_TDMSRC2E= 0x2160, /*!< Enable TDM source2 data channel */
+ TFA9875_BF_TDMSRC3E= 0x2170, /*!< Enable TDM source3 data channel */
+ TFA9875_BF_TDMSPKS= 0x2183, /*!< TDM slot for sink 0 */
+ TFA9875_BF_TDMDCS= 0x21c3, /*!< TDM slot for sink 1 */
+ TFA9875_BF_TDMSRC0S= 0x2203, /*!< Slot Position of TDM source0 channel data */
+ TFA9875_BF_TDMSRC1S= 0x2243, /*!< Slot Position of TDM source1 channel data */
+ TFA9875_BF_TDMSRC2S= 0x2283, /*!< Slot Position of TDM source2 channel data */
+ TFA9875_BF_TDMSRC3S= 0x22c3, /*!< Slot Position of TDM source3 channel data */
+ TFA9875_BF_ISTVDDS= 0x4000, /*!< Interrupt status POR */
+ TFA9875_BF_ISTBSTOC= 0x4010, /*!< Interrupt status DCDC OCP alarm */
+ TFA9875_BF_ISTOTDS= 0x4020, /*!< Interrupt status OTP alarm */
+ TFA9875_BF_ISTOCPR= 0x4030, /*!< Interrupt status OCP alarm */
+ TFA9875_BF_ISTUVDS= 0x4040, /*!< Interrupt status UVP alarm */
+ TFA9875_BF_ISTTDMER= 0x4050, /*!< Interrupt status TDM error */
+ TFA9875_BF_ISTNOCLK= 0x4060, /*!< Interrupt status lost clock */
+ TFA9875_BF_ISTDCTH= 0x4070, /*!< Interrupt status dc too high */
+ TFA9875_BF_ISTBODNOK= 0x4080, /*!< Interrupt status brown out detected */
+ TFA9875_BF_ISTCOOR= 0x4090, /*!< Interrupt status clock out of range */
+ TFA9875_BF_ICLVDDS= 0x4400, /*!< Clear interrupt status POR */
+ TFA9875_BF_ICLBSTOC= 0x4410, /*!< Clear interrupt status DCDC OCP */
+ TFA9875_BF_ICLOTDS= 0x4420, /*!< Clear interrupt status OTP alarm */
+ TFA9875_BF_ICLOCPR= 0x4430, /*!< Clear interrupt status OCP alarm */
+ TFA9875_BF_ICLUVDS= 0x4440, /*!< Clear interrupt status UVP alarm */
+ TFA9875_BF_ICLTDMER= 0x4450, /*!< Clear interrupt status TDM error */
+ TFA9875_BF_ICLNOCLK= 0x4460, /*!< Clear interrupt status lost clk */
+ TFA9875_BF_ICLDCTH= 0x4470, /*!< Clear interrupt status dc too high */
+ TFA9875_BF_ICLBODNOK= 0x4480, /*!< Clear interrupt status brown out detected */
+ TFA9875_BF_ICLCOOR= 0x4490, /*!< Clear interrupt status clock out of range */
+ TFA9875_BF_IEVDDS= 0x4800, /*!< Enable interrupt POR */
+ TFA9875_BF_IEBSTOC= 0x4810, /*!< Enable interrupt DCDC OCP */
+ TFA9875_BF_IEOTDS= 0x4820, /*!< Enable interrupt OTP alarm */
+ TFA9875_BF_IEOCPR= 0x4830, /*!< Enable interrupt OCP alarm */
+ TFA9875_BF_IEUVDS= 0x4840, /*!< Enable interrupt UVP alarm */
+ TFA9875_BF_IETDMER= 0x4850, /*!< Enable interrupt TDM error */
+ TFA9875_BF_IENOCLK= 0x4860, /*!< Enable interrupt lost clk */
+ TFA9875_BF_IEDCTH= 0x4870, /*!< Enable interrupt dc too high */
+ TFA9875_BF_IEBODNOK= 0x4880, /*!< Enable interrupt brown out detect */
+ TFA9875_BF_IECOOR= 0x4890, /*!< Enable interrupt clock out of range */
+ TFA9875_BF_IPOVDDS= 0x4c00, /*!< Interrupt polarity POR */
+ TFA9875_BF_IPOBSTOC= 0x4c10, /*!< Interrupt polarity DCDC OCP */
+ TFA9875_BF_IPOOTDS= 0x4c20, /*!< Interrupt polarity OTP alarm */
+ TFA9875_BF_IPOOCPR= 0x4c30, /*!< Interrupt polarity OCP alarm */
+ TFA9875_BF_IPOUVDS= 0x4c40, /*!< Interrupt polarity UVP alarm */
+ TFA9875_BF_IPOTDMER= 0x4c50, /*!< Interrupt polarity TDM error */
+ TFA9875_BF_IPONOCLK= 0x4c60, /*!< Interrupt polarity lost clk */
+ TFA9875_BF_IPODCTH= 0x4c70, /*!< Interrupt polarity dc too high */
+ TFA9875_BF_IPOBODNOK= 0x4c80, /*!< Interrupt polarity brown out detect */
+ TFA9875_BF_IPOCOOR= 0x4c90, /*!< Interrupt polarity clock out of range */
+ TFA9875_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9875_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9875_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9875_BF_BSSCLRST= 0x50d0, /*!< Reset clipper - auto clear */
+ TFA9875_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9875_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9875_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9875_BF_DCPTC = 0x5111, /*!< Duration of DC level detection */
+ TFA9875_BF_DCPL = 0x5131, /*!< DC-level detection */
+ TFA9875_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9875_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9875_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9875_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9875_BF_SLOPEE= 0x54a0, /*!< Enables slope control */
+ TFA9875_BF_SLOPESET= 0x54b0, /*!< Slope speed setting */
+ TFA9875_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9875_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9875_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9875_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9875_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9875_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9875_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9875_BF_TDMSRCACLIP= 0x6871, /*!< Clip flag information for TDM Compressed2a/b/c modes */
+ TFA9875_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9875_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9875_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9875_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9875_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9875_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9875_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9875_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9875_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9875_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9875_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9875_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9875_BF_DCOVL = 0x7087, /*!< Threshold level to activate active overshoot control */
+ TFA9875_BF_DCNS = 0x7400, /*!< Disable control of noise shaper in DCDC control */
+ TFA9875_BF_DCNSRST= 0x7410, /*!< Disable control of reset of noise shaper when 8 bit value for dcdc control occurs */
+ TFA9875_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9875_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCTRIP= 0x7444, /*!< Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0 */
+ TFA9875_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCDIS = 0x7500, /*!< DCDC on/off */
+ TFA9875_BF_DCPWM = 0x7510, /*!< DCDC PWM only mode */
+ TFA9875_BF_DCTRIP2= 0x7534, /*!< Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0 */
+ TFA9875_BF_DCTRIPT= 0x7584, /*!< Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1 */
+ TFA9875_BF_BYPDCLPF= 0x75d0, /*!< Bypass control of DCDC control low pass filter for quantization noise suppression */
+ TFA9875_BF_ENBSTFLT= 0x75e0, /*!< Enable the boost filter */
+ TFA9875_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9875_BF_DCVOF = 0x7607, /*!< First boost voltage level */
+ TFA9875_BF_DCVOS = 0x7687, /*!< Second boost voltage level */
+ TFA9875_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9875_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9875_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9875_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9875_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9875_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9875_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9875_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9875_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9875_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9875_BF_PLLSELI= 0xcd05, /*!< PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELP= 0xcd64, /*!< PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELR= 0xcdb3, /*!< PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection direct control, USE WITH CAUTION */
+ TFA9875_BF_PLLFRM= 0xce00, /*!< PLL free running mode control in functional mode */
+ TFA9875_BF_PLLDI = 0xce10, /*!< PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDO = 0xce20, /*!< PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLPDIV= 0xce34, /*!< PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLNDIV= 0xce87, /*!< PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLMDIV= 0xcf0f, /*!< PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDCTRL= 0xd000, /*!< Enable PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9875_BF_PLLENBL= 0xd010, /*!< Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLLIMOFF= 0xd020, /*!< PLL up limiter control in PLL direct bandwidth control mode */
+ TFA9875_BF_PLLCLKSTB= 0xd030, /*!< PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSTRTM= 0xd042, /*!< PLL startup time selection control */
+ TFA9875_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9875_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9875_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9875_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9875_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9875_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9875_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9875_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9875_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9875BfEnumList_t;
+#define TFA9875_NAMETABLE static tfaBfName_t Tfa9875DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xa0, "BYPUVP"}, /* Bypass UVP , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xd0, "MANWTIME"}, /* Manager wait time selection control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "COORHYS"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "MANSCONF"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "MUTETO"}, /* Time out mute sequence , */\
+ { 0x170, "MANROBOD"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "BODFILT"}, /* BOD filter , */\
+ { 0x1b1, "BODTHLVL"}, /* BOD threshold level , */\
+ { 0x1d0, "MANEDCTH"}, /* Device response to too high DC level flag (DCTH = 1) , */\
+ { 0x1e0, "OPENMTP"}, /* Control for MTP protection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (Fs) , */\
+ { 0x240, "ENLBW"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x400, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM (MTP) , */\
+ { 0x1000, "VDDS"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "OTDS"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "UVDS"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "OVDS"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "OCDS"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "NOCLK"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "CLKOOR"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "DCOCPOK"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "DCIL"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "DCDCA"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "ADCCR"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "OCPOAP"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "OCPOAN"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "OCPOBP"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "OCPOBN"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "DCTH"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "CLKS"}, /* Clocks stable , */\
+ { 0x1110, "MTPB"}, /* MTP busy , */\
+ { 0x1120, "TDMERR"}, /* TDM error , */\
+ { 0x1130, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x1190, "SWS"}, /* Amplifier engage , */\
+ { 0x11a0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11b0, "AREFS"}, /* References enable , */\
+ { 0x11c0, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1203, "MANSTATE"}, /* Device manager status , */\
+ { 0x1243, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x1282, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x12b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x12d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "BODNOK"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "DCLD"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2011, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x2030, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x2040, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2050, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2061, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2081, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x20a1, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2100, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x2110, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2120, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "TDMSRC0E"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "TDMSRC1E"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "TDMSRC2E"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "TDMSRC3E"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "TDMSRC0S"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "TDMSRC1S"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "TDMSRC2S"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "TDMSRC3S"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "ISTVDDS"}, /* Interrupt status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "ISTOTDS"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "ISTTDMER"}, /* Interrupt status TDM error , */\
+ { 0x4060, "ISTNOCLK"}, /* Interrupt status lost clock , */\
+ { 0x4070, "ISTDCTH"}, /* Interrupt status dc too high , */\
+ { 0x4080, "ISTBODNOK"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "ISTCOOR"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear interrupt status POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "ICLTDMER"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "ICLNOCLK"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "ICLDCTH"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "ICLBODNOK"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "ICLCOOR"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable interrupt POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "IETDMER"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "IENOCLK"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "IEDCTH"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "IEBODNOK"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "IECOOR"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "IPOTDMER"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "IPONOCLK"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "IPODCTH"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "IPOBODNOK"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "IPOCOOR"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "BSSCLRST"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5111, "DCPTC"}, /* Duration of DC level detection , */\
+ { 0x5131, "DCPL"}, /* DC-level detection , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x54a0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x54b0, "SLOPESET"}, /* Slope speed setting , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7087, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7400, "DCNS"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "DCNSRST"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x7500, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7510, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7534, "DCTRIP2"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "DCTRIPT"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "BYPDCLPF"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7687, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLSELI"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "PLLSELP"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "PLLSELR"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "PLLDI"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "PLLDO"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "PLLPDIV"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "PLLNDIV"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "PLLMDIV"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "PLLDCTRL"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "PLLENBL"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "PLLCLKSTB"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9875_BITNAMETABLE static tfaBfName_t Tfa9875BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xa0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "src_set_configured"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "disable_mute_time_out"}, /* Time out mute sequence , */\
+ { 0x170, "man_enbl_brown"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "bod_delay_set"}, /* BOD filter , */\
+ { 0x1b1, "bod_lvl_set"}, /* BOD threshold level , */\
+ { 0x1d0, "man_enbl_dc_too_high"}, /* Device response to too high DC level flag (DCTH = 1) , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for MTP protection , */\
+ { 0x203, "audio_fs"}, /* Sample rate (Fs) , */\
+ { 0x240, "enbl_low_bandwidth"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x400, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM (MTP) , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to key registers , */\
+ { 0x1000, "flag_por"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "flag_otpok"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "flag_uvpok"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "flag_ocp_alarm"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "flag_lost_clk"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "flag_clk_out_of_range"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "flag_bst_bstcur"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "flag_bst_hiz"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "flag_adc10_ready"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "flag_ocpokap"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "flag_ocpokan"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "flag_ocpokbp"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "flag_ocpokbn"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "flag_dc_too_high"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1110, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1120, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x1190, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11a0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11b0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x11c0, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1203, "man_state"}, /* Device manager status , */\
+ { 0x1243, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x1282, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x12b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x12d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "flag_bod_vddd_nok"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "dc_level_detect"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2011, "tdm_vamp_sel"}, /* Amplifier input selection , */\
+ { 0x2030, "tdm_input_level"}, /* TDM output attenuation , */\
+ { 0x2040, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2050, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2061, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2081, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x20a1, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2100, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x2110, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2120, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "tdm_source0_enable"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "tdm_source1_enable"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "tdm_source2_enable"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "tdm_source3_enable"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "tdm_source0_slot"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "tdm_source1_slot"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "tdm_source2_slot"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "tdm_source3_slot"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "int_out_flag_por"}, /* Interrupt status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "int_out_flag_tdm_error"}, /* Interrupt status TDM error , */\
+ { 0x4060, "int_out_flag_lost_clk"}, /* Interrupt status lost clock , */\
+ { 0x4070, "int_out_flag_dc_too_high"}, /* Interrupt status dc too high , */\
+ { 0x4080, "int_out_flag_bod_vddd_nok"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "int_out_flag_clk_out_of_range"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear interrupt status POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "int_in_flag_tdm_error"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "int_in_flag_lost_clk"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "int_in_flag_dc_too_high"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "int_in_flag_bod_vddd_nok"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "int_in_flag_clk_out_of_range"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable interrupt POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "int_enable_flag_tdm_error"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "int_enable_flag_lost_clk"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "int_enable_flag_dc_too_high"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "int_enable_flag_bod_vddd_nok"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "int_enable_flag_clk_out_of_range"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_tdm_error"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "int_polarity_flag_lost_clk"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "int_polarity_flag_dc_too_high"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "int_polarity_flag_bod_vddd_nok"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "int_polarity_flag_clk_out_of_range"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5111, "dc_prot_time_constant"}, /* Duration of DC level detection , */\
+ { 0x5131, "dc_prot_level"}, /* DC-level detection , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5300, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5310, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5320, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5330, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5343, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x5381, "ref_amp_irefdist_set_ctrl"}, /* Scaling of reference current for amplifier OCP , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5452, "amp_pst_drive_ctrl"}, /* Amplifier powerstage drive control in direct control mode only, */\
+ { 0x5481, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x54a0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x54b0, "ctrl_slope"}, /* Slope speed setting , */\
+ { 0x54c0, "sel_icomp_dem_clk"}, /* Clock selection for icomp_dem , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5610, "ref_iref_test_enbl"}, /* Enable of test function of reference current , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x5705, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually in I2C direct control mode, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage in I2C direct control mode, */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage in I2C direct control mode, */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*4096*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage in I2C direct control mode, */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engage , */\
+ { 0x6b10, "disable_engage"}, /* Disable engage , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* Spare control bits for future use , */\
+ { 0x6d09, "spare_in"}, /* Spare control bit - read only , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7087, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* Scale factor for peak current measurement - ratio between reference current and power transistor current, */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller in I2C direct control mode, */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator in I2C direct control mode , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current in I2C direct control mode , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage in I2C direct control mode, */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC in I2C direct control mode, */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators in I2C direct control mode, */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators in I2C direct control mode, */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators in I2C direct control mode, */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC in I2C direct control mode , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7360, "disable_artf676996_fix"}, /* Disables the fix for artf676996 (OCP booster triggered when Vtrgt is just above Vbat), */\
+ { 0x7371, "ref_bst_irefdist_set_ctrl"}, /* Scaling of reference current for booster OCP , */\
+ { 0x7400, "dcdc_disable_ns"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "dcdc_disable_mod8bit"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7500, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7510, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "bypass_dcdc_lpf"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7687, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7707, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x87a0, "enbl_ana_pre"}, /* Control for enabling the pre-empasis filter for voltage and current sense decimator, */\
+ { 0x8800, "vs1_adc_enbl"}, /* Enable voltage sense VS1 ADC (direct control mode only), */\
+ { 0x8810, "vs1_inn_short_ctrl"}, /* Short voltage sense VS1 negative to common mode , */\
+ { 0x8820, "vs1_inp_short_ctrl"}, /* Short voltage sense VS1 positive to common mode , */\
+ { 0x8830, "vs1_ldo_enbl"}, /* Enable voltage sense VS1 LDO (direct control mode only), */\
+ { 0x8840, "vs1_vbatldo_enbl"}, /* Enable voltage sense VS1 VBAT LDO (direct control mode only), */\
+ { 0x8850, "vs1_gain_control"}, /* Voltage sense VS1 gain control , */\
+ { 0x8860, "vs1_bypass_gc"}, /* Bypasses the VS1 gain correction , */\
+ { 0x8870, "vs1_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8887, "vs1_gain"}, /* Voltage sense VS1 gain , */\
+ { 0x8900, "vs2_adc_enbl"}, /* Enable voltage sense VS2 ADC (direct control mode only), */\
+ { 0x8910, "vs2_inn_short_ctrl"}, /* Short voltage sense VS2 negative to common mode , */\
+ { 0x8920, "vs2_inp_short_ctrl"}, /* Short voltage sense VS2 positive to common mode , */\
+ { 0x8930, "vs2_ldo_enbl"}, /* Enable voltage sense VS2 LDO (direct control mode only), */\
+ { 0x8940, "vs2_vbatldo_enbl"}, /* Enable voltage sense VS2 VBAT LDO (direct control mode only), */\
+ { 0x8950, "vs2_gain_control"}, /* Voltage sense VS2 gain control , */\
+ { 0x8960, "vs2_bypass_gc"}, /* Bypasses the VS2 gain correction , */\
+ { 0x8970, "vs2_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8987, "vs2_gain"}, /* Voltage sense VS2 gain , */\
+ { 0x8a00, "vs_adc_delay_ctrl"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8a10, "vs_adc_nortz_ctrl"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8a20, "vs_ldo_bypass_ctrl"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown_ctrl"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset_ctrl"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "vs_anamux_overrule"}, /* Overrule the disconnection of VS pins , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc0f0, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "cs_test_enbl"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "vs1_test_enbl"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc590, "vs2_test_enbl"}, /* Enable for digimux mode of dual sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "pll_selp"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "pll_selr"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "pll_band_direct"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "pll_directi"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "pll_directo"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "pll_pdiv"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "pll_ndiv"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "pll_mdiv"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "use_direct_pll_ctrl"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "enbl_pll"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "pll_frm_clockstable"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range checker , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf107, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_vs1_gain"}, /* Voltage sense VS1 gain calibration , */\
+ { 0xf387, "calibr_vs2_gain"}, /* Voltage sense VS2 gain calibration , */\
+ { 0xf407, "calibr_vs1_trim"}, /* VS1 ADC trimming , */\
+ { 0xf487, "calibr_vs2_trim"}, /* VS2 ADC Trimming , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9875_irq {
+ tfa9875_irq_max = -1,
+ tfa9875_irq_all = -1 /* all irqs */};
+
+#define TFA9875_IRQ_NAMETABLE static tfaIrqName_t Tfa9875IrqNames[]= {\
+};
+#endif /* _TFA9875_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames_A1.h b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames_A1.h
new file mode 100644
index 00000000000..df919afd30b
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9875_tfafieldnames_A1.h
@@ -0,0 +1,939 @@
+/*
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _TFA9875_TFAFIELDNAMES_A1_H
+#define _TFA9875_TFAFIELDNAMES_A1_H
+
+
+#define TFA9875N1A1_I2CVERSION 26
+#ifndef TFA9875_I2CVERSION
+typedef enum Tfa9875A1BfEnumList {
+ TFA9875_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9875_BF_I2CR = 0x0010, /*!< I2C reset - auto clear */
+ TFA9875_BF_AMPE = 0x0030, /*!< Activate amplifier */
+ TFA9875_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9875_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9875_BF_BYPUVP= 0x00a0, /*!< Bypass UVP */
+ TFA9875_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9875_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9875_BF_MANWTIME= 0x00d0, /*!< Manager wait time selection control */
+ TFA9875_BF_ENPLLSYNC= 0x00e0, /*!< Manager control for enabling synchronisation with PLL FS */
+ TFA9875_BF_COORHYS= 0x00f0, /*!< Select hysteresis for clock range detector */
+ TFA9875_BF_MANSCONF= 0x0120, /*!< Configuration setting if I2C settings are uploaded by the host */
+ TFA9875_BF_MUTETO= 0x0160, /*!< Time out mute sequence */
+ TFA9875_BF_MANROBOD= 0x0170, /*!< Controls the reaction of the device on BOD */
+ TFA9875_BF_BODHYS= 0x0180, /*!< Enable Hysteresis of BOD */
+ TFA9875_BF_BODFILT= 0x0191, /*!< BOD filter */
+ TFA9875_BF_BODTHLVL= 0x01b1, /*!< BOD threshold level */
+ TFA9875_BF_MANEDCTH= 0x01d0, /*!< Device response to too high DC level flag (when DCTH asserts to 1) */
+ TFA9875_BF_OPENMTP= 0x01e0, /*!< Control for MTP protection */
+ TFA9875_BF_AUDFS = 0x0203, /*!< Sample rate (Fs) */
+ TFA9875_BF_ENLBW = 0x0240, /*!< CS/VS decimator low bandwidth mode control */
+ TFA9875_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9875_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9875_BF_REFCKEXT= 0x0400, /*!< PLL external ref clock */
+ TFA9875_BF_MANAOOSC= 0x0460, /*!< Internal oscillator control during power down mode */
+ TFA9875_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9875_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9875_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9875_BF_FRCCLKSPKR= 0x0510, /*!< Force active the speaker sub-system clock when in idle power */
+ TFA9875_BF_BSTCLKLP= 0x0520, /*!< Boost clock control in low power mode1 */
+ TFA9875_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM (MTP) */
+ TFA9875_BF_VDDS = 0x1000, /*!< POR (sticky flag, clear on write a '1') */
+ TFA9875_BF_OTDS = 0x1010, /*!< OTP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_UVDS = 0x1020, /*!< UVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OVDS = 0x1030, /*!< OVP alarm (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCDS = 0x1040, /*!< OCP amplifier (sticky flag, clear on write a '1') */
+ TFA9875_BF_NOCLK = 0x1050, /*!< Lost clock (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKOOR= 0x1060, /*!< External clock status (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCOCPOK= 0x1070, /*!< DCDC OCP nmos (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCIL = 0x1080, /*!< DCDC current limiting (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCDCA = 0x1090, /*!< DCDC active (sticky flag, clear on write a '1') */
+ TFA9875_BF_ADCCR = 0x10a0, /*!< ADC ready flag (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAP= 0x10b0, /*!< OCPOK pmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOAN= 0x10c0, /*!< OCPOK nmos A (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBP= 0x10d0, /*!< OCPOK pmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_OCPOBN= 0x10e0, /*!< OCPOK nmos B (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCTH = 0x10f0, /*!< DC level on audio input stream too high (sticky flag, clear on write a '1') */
+ TFA9875_BF_CLKS = 0x1100, /*!< Clocks stable */
+ TFA9875_BF_MTPB = 0x1110, /*!< MTP busy */
+ TFA9875_BF_TDMERR= 0x1120, /*!< TDM error */
+ TFA9875_BF_DCDCPC= 0x1130, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9875_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9875_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9875_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9875_BF_PLLS = 0x1170, /*!< PLL lock */
+ TFA9875_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9875_BF_SWS = 0x1190, /*!< Amplifier engage */
+ TFA9875_BF_AMPS = 0x11a0, /*!< Amplifier enable */
+ TFA9875_BF_AREFS = 0x11b0, /*!< References enable */
+ TFA9875_BF_CLIPS = 0x11c0, /*!< Amplifier clipping */
+ TFA9875_BF_MANSTATE= 0x1203, /*!< Device manager status */
+ TFA9875_BF_AMPSTE= 0x1243, /*!< Amplifier control status */
+ TFA9875_BF_TDMSTAT= 0x1282, /*!< TDM status bits */
+ TFA9875_BF_DCMODE= 0x12b1, /*!< DCDC mode status bits */
+ TFA9875_BF_WAITSYNC= 0x12d0, /*!< CGU and PLL synchronisation status flag from CGU */
+ TFA9875_BF_BODNOK= 0x1300, /*!< BOD Flag VDD NOT OK (sticky flag, clear on write a '1') */
+ TFA9875_BF_DCLD = 0x140c, /*!< DC level detected by DC protection module (2s complement) */
+ TFA9875_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9875_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9875_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9875_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9875_BF_AMPINSEL= 0x2011, /*!< Amplifier input selection */
+ TFA9875_BF_INPLEV= 0x2030, /*!< TDM output attenuation */
+ TFA9875_BF_TDMCLINV= 0x2040, /*!< Reception data to BCK clock */
+ TFA9875_BF_TDMFSPOL= 0x2050, /*!< FS polarity */
+ TFA9875_BF_TDMSLOTS= 0x2061, /*!< N-slots in Frame */
+ TFA9875_BF_TDMSLLN= 0x2081, /*!< N-bits in slot */
+ TFA9875_BF_TDMSSIZE= 0x20a1, /*!< Sample size per slot */
+ TFA9875_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9875_BF_TDMDEL= 0x2100, /*!< Data delay to FS */
+ TFA9875_BF_TDMADJ= 0x2110, /*!< Data adjustment */
+ TFA9875_BF_TDMSPKE= 0x2120, /*!< Control audio TDM channel in 0 */
+ TFA9875_BF_TDMDCE= 0x2130, /*!< Control audio TDM channel in 1 */
+ TFA9875_BF_TDMSRC0E= 0x2140, /*!< Enable TDM source0 data channel */
+ TFA9875_BF_TDMSRC1E= 0x2150, /*!< Enable TDM source1 data channel */
+ TFA9875_BF_TDMSRC2E= 0x2160, /*!< Enable TDM source2 data channel */
+ TFA9875_BF_TDMSRC3E= 0x2170, /*!< Enable TDM source3 data channel */
+ TFA9875_BF_TDMSPKS= 0x2183, /*!< TDM slot for sink 0 */
+ TFA9875_BF_TDMDCS= 0x21c3, /*!< TDM slot for sink 1 */
+ TFA9875_BF_TDMSRC0S= 0x2203, /*!< Slot Position of TDM source0 channel data */
+ TFA9875_BF_TDMSRC1S= 0x2243, /*!< Slot Position of TDM source1 channel data */
+ TFA9875_BF_TDMSRC2S= 0x2283, /*!< Slot Position of TDM source2 channel data */
+ TFA9875_BF_TDMSRC3S= 0x22c3, /*!< Slot Position of TDM source3 channel data */
+ TFA9875_BF_ISTVDDS= 0x4000, /*!< Interrupt status POR */
+ TFA9875_BF_ISTBSTOC= 0x4010, /*!< Interrupt status DCDC OCP alarm */
+ TFA9875_BF_ISTOTDS= 0x4020, /*!< Interrupt status OTP alarm */
+ TFA9875_BF_ISTOCPR= 0x4030, /*!< Interrupt status OCP alarm */
+ TFA9875_BF_ISTUVDS= 0x4040, /*!< Interrupt status UVP alarm */
+ TFA9875_BF_ISTTDMER= 0x4050, /*!< Interrupt status TDM error */
+ TFA9875_BF_ISTNOCLK= 0x4060, /*!< Interrupt status lost clock */
+ TFA9875_BF_ISTDCTH= 0x4070, /*!< Interrupt status dc too high */
+ TFA9875_BF_ISTBODNOK= 0x4080, /*!< Interrupt status brown out detected */
+ TFA9875_BF_ISTCOOR= 0x4090, /*!< Interrupt status clock out of range */
+ TFA9875_BF_ICLVDDS= 0x4400, /*!< Clear interrupt status POR */
+ TFA9875_BF_ICLBSTOC= 0x4410, /*!< Clear interrupt status DCDC OCP */
+ TFA9875_BF_ICLOTDS= 0x4420, /*!< Clear interrupt status OTP alarm */
+ TFA9875_BF_ICLOCPR= 0x4430, /*!< Clear interrupt status OCP alarm */
+ TFA9875_BF_ICLUVDS= 0x4440, /*!< Clear interrupt status UVP alarm */
+ TFA9875_BF_ICLTDMER= 0x4450, /*!< Clear interrupt status TDM error */
+ TFA9875_BF_ICLNOCLK= 0x4460, /*!< Clear interrupt status lost clk */
+ TFA9875_BF_ICLDCTH= 0x4470, /*!< Clear interrupt status dc too high */
+ TFA9875_BF_ICLBODNOK= 0x4480, /*!< Clear interrupt status brown out detected */
+ TFA9875_BF_ICLCOOR= 0x4490, /*!< Clear interrupt status clock out of range */
+ TFA9875_BF_IEVDDS= 0x4800, /*!< Enable interrupt POR */
+ TFA9875_BF_IEBSTOC= 0x4810, /*!< Enable interrupt DCDC OCP */
+ TFA9875_BF_IEOTDS= 0x4820, /*!< Enable interrupt OTP alarm */
+ TFA9875_BF_IEOCPR= 0x4830, /*!< Enable interrupt OCP alarm */
+ TFA9875_BF_IEUVDS= 0x4840, /*!< Enable interrupt UVP alarm */
+ TFA9875_BF_IETDMER= 0x4850, /*!< Enable interrupt TDM error */
+ TFA9875_BF_IENOCLK= 0x4860, /*!< Enable interrupt lost clk */
+ TFA9875_BF_IEDCTH= 0x4870, /*!< Enable interrupt dc too high */
+ TFA9875_BF_IEBODNOK= 0x4880, /*!< Enable interrupt brown out detect */
+ TFA9875_BF_IECOOR= 0x4890, /*!< Enable interrupt clock out of range */
+ TFA9875_BF_IPOVDDS= 0x4c00, /*!< Interrupt polarity POR */
+ TFA9875_BF_IPOBSTOC= 0x4c10, /*!< Interrupt polarity DCDC OCP */
+ TFA9875_BF_IPOOTDS= 0x4c20, /*!< Interrupt polarity OTP alarm */
+ TFA9875_BF_IPOOCPR= 0x4c30, /*!< Interrupt polarity OCP alarm */
+ TFA9875_BF_IPOUVDS= 0x4c40, /*!< Interrupt polarity UVP alarm */
+ TFA9875_BF_IPOTDMER= 0x4c50, /*!< Interrupt polarity TDM error */
+ TFA9875_BF_IPONOCLK= 0x4c60, /*!< Interrupt polarity lost clk */
+ TFA9875_BF_IPODCTH= 0x4c70, /*!< Interrupt polarity dc too high */
+ TFA9875_BF_IPOBODNOK= 0x4c80, /*!< Interrupt polarity brown out detect */
+ TFA9875_BF_IPOCOOR= 0x4c90, /*!< Interrupt polarity clock out of range */
+ TFA9875_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9875_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9875_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9875_BF_BSSCLRST= 0x50d0, /*!< Reset clipper - auto clear */
+ TFA9875_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9875_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9875_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9875_BF_DCPTC = 0x5111, /*!< Duration of DC level detection */
+ TFA9875_BF_DCPL = 0x5131, /*!< DC-level detection */
+ TFA9875_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9875_BF_BYHWCLIP= 0x5240, /*!< Bypass hardware clipper */
+ TFA9875_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9875_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9875_BF_SLOPEE= 0x54a0, /*!< Enables slope control */
+ TFA9875_BF_SLOPESET= 0x54b0, /*!< Slope speed setting */
+ TFA9875_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9875_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9875_BF_LNMODE= 0x62e1, /*!< Ctrl select mode */
+ TFA9875_BF_LPM1MODE= 0x64e1, /*!< Low power mode control */
+ TFA9875_BF_PFMFREQLIM= 0x66d2, /*!< Lowest PFM frequency limit */
+ TFA9875_BF_TDMSRCMAP= 0x6802, /*!< TDM source mapping */
+ TFA9875_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9875_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9875_BF_TDMSRCACLIP= 0x6871, /*!< Clip flag information for TDM Compressed2a/b/c modes */
+ TFA9875_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9875_BF_LP1 = 0x6e10, /*!< Low power mode 1 detection */
+ TFA9875_BF_LA = 0x6e20, /*!< Low amplitude detection */
+ TFA9875_BF_VDDPH = 0x6e30, /*!< Vddp greater than Vbat */
+ TFA9875_BF_DELCURCOMP= 0x6f02, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9875_BF_SIGCURCOMP= 0x6f40, /*!< Polarity of compensation for current sense */
+ TFA9875_BF_ENCURCOMP= 0x6f50, /*!< Enable current sense compensation */
+ TFA9875_BF_LVLCLPPWM= 0x6f72, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9875_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9875_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) */
+ TFA9875_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9875_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9875_BF_DCOVL = 0x7087, /*!< Threshold level to activate active overshoot control */
+ TFA9875_BF_DCNS = 0x7400, /*!< Disable control of noise shaper in DCDC control */
+ TFA9875_BF_DCNSRST= 0x7410, /*!< Disable control of reset of noise shaper when 8 bit value for dcdc control occurs */
+ TFA9875_BF_DCDYFSW= 0x7420, /*!< Disables the dynamic frequency switching due to flag_voutcomp86/93 */
+ TFA9875_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCTRIP= 0x7444, /*!< Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0 */
+ TFA9875_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1 */
+ TFA9875_BF_DCDIS = 0x7500, /*!< DCDC on/off */
+ TFA9875_BF_DCPWM = 0x7510, /*!< DCDC PWM only mode */
+ TFA9875_BF_DCTRIP2= 0x7534, /*!< Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0 */
+ TFA9875_BF_DCTRIPT= 0x7584, /*!< Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1 */
+ TFA9875_BF_BYPDCLPF= 0x75d0, /*!< Bypass control of DCDC control low pass filter for quantization noise suppression */
+ TFA9875_BF_ENBSTFLT= 0x75e0, /*!< Enable the boost filter */
+ TFA9875_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9875_BF_DCVOF = 0x7607, /*!< First boost voltage level */
+ TFA9875_BF_DCVOS = 0x7687, /*!< Second boost voltage level */
+ TFA9875_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9875_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9875_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9875_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9875_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9875_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9875_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9875_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9875_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9875_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9875_BF_PLLSELI= 0xcd05, /*!< PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELP= 0xcd64, /*!< PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSELR= 0xcdb3, /*!< PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection direct control, USE WITH CAUTION */
+ TFA9875_BF_PLLFRM= 0xce00, /*!< PLL free running mode control in functional mode */
+ TFA9875_BF_PLLDI = 0xce10, /*!< PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDO = 0xce20, /*!< PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLPDIV= 0xce34, /*!< PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLNDIV= 0xce87, /*!< PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLMDIV= 0xcf0f, /*!< PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLDCTRL= 0xd000, /*!< Enable PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9875_BF_PLLENBL= 0xd010, /*!< Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLLIMOFF= 0xd020, /*!< PLL up limiter control in PLL direct bandwidth control mode */
+ TFA9875_BF_PLLCLKSTB= 0xd030, /*!< PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1 */
+ TFA9875_BF_PLLSTRTM= 0xd042, /*!< PLL startup time selection control */
+ TFA9875_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9875_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9875_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9875_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9875_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9875_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9875_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9875_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9875_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+}Tfa9875A1BfEnumList_t;
+#endif
+#define TFA9875A1_NAMETABLE static tfaBfName_t Tfa9875A1DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C reset - auto clear , */\
+ { 0x30, "AMPE"}, /* Activate amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0xa0, "BYPUVP"}, /* Bypass UVP , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xd0, "MANWTIME"}, /* Manager wait time selection control , */\
+ { 0xe0, "ENPLLSYNC"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "COORHYS"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "MANSCONF"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "MUTETO"}, /* Time out mute sequence , */\
+ { 0x170, "MANROBOD"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "BODFILT"}, /* BOD filter , */\
+ { 0x1b1, "BODTHLVL"}, /* BOD threshold level , */\
+ { 0x1d0, "MANEDCTH"}, /* Device response to too high DC level flag (when DCTH asserts to 1) , */\
+ { 0x1e0, "OPENMTP"}, /* Control for MTP protection , */\
+ { 0x203, "AUDFS"}, /* Sample rate (Fs) , */\
+ { 0x240, "ENLBW"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x400, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x460, "MANAOOSC"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "BSTCLKLP"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM (MTP) , */\
+ { 0x1000, "VDDS"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "OTDS"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "UVDS"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "OVDS"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "OCDS"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "NOCLK"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "CLKOOR"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "DCOCPOK"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "DCIL"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "DCDCA"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "ADCCR"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "OCPOAP"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "OCPOAN"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "OCPOBP"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "OCPOBN"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "DCTH"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "CLKS"}, /* Clocks stable , */\
+ { 0x1110, "MTPB"}, /* MTP busy , */\
+ { 0x1120, "TDMERR"}, /* TDM error , */\
+ { 0x1130, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x1190, "SWS"}, /* Amplifier engage , */\
+ { 0x11a0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11b0, "AREFS"}, /* References enable , */\
+ { 0x11c0, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1203, "MANSTATE"}, /* Device manager status , */\
+ { 0x1243, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x1282, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x12b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x12d0, "WAITSYNC"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "BODNOK"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "DCLD"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2011, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x2030, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x2040, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2050, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2061, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2081, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x20a1, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2100, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x2110, "TDMADJ"}, /* Data adjustment , */\
+ { 0x2120, "TDMSPKE"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "TDMDCE"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "TDMSRC0E"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "TDMSRC1E"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "TDMSRC2E"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "TDMSRC3E"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "TDMSRC0S"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "TDMSRC1S"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "TDMSRC2S"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "TDMSRC3S"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "ISTVDDS"}, /* Interrupt status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "ISTOTDS"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "ISTTDMER"}, /* Interrupt status TDM error , */\
+ { 0x4060, "ISTNOCLK"}, /* Interrupt status lost clock , */\
+ { 0x4070, "ISTDCTH"}, /* Interrupt status dc too high , */\
+ { 0x4080, "ISTBODNOK"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "ISTCOOR"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear interrupt status POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "ICLTDMER"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "ICLNOCLK"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "ICLDCTH"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "ICLBODNOK"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "ICLCOOR"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable interrupt POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "IETDMER"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "IENOCLK"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "IEDCTH"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "IEBODNOK"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "IECOOR"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "IPOTDMER"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "IPONOCLK"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "IPODCTH"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "IPOBODNOK"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "IPOCOOR"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "BSSCLRST"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5111, "DCPTC"}, /* Duration of DC level detection , */\
+ { 0x5131, "DCPL"}, /* DC-level detection , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5240, "BYHWCLIP"}, /* Bypass hardware clipper , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x54a0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x54b0, "SLOPESET"}, /* Slope speed setting , */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* Ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x66d2, "PFMFREQLIM"}, /* Lowest PFM frequency limit , */\
+ { 0x6802, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* Low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7087, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7400, "DCNS"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "DCNSRST"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "DCDYFSW"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x7500, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7510, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7534, "DCTRIP2"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "DCTRIPT"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "BYPDCLPF"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "ENBSTFLT"}, /* Enable the boost filter , */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7687, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLSELI"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "PLLSELP"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "PLLSELR"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "PLLDI"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "PLLDO"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "PLLPDIV"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "PLLNDIV"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "PLLMDIV"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "PLLDCTRL"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "PLLENBL"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "PLLCLKSTB"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9875A1_BITNAMETABLE static tfaBfName_t Tfa9875A1BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C reset - auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0xa0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0xe0, "enbl_pll_synchronisation"}, /* Manager control for enabling synchronisation with PLL FS, */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x120, "src_set_configured"}, /* Configuration setting if I2C settings are uploaded by the host, */\
+ { 0x160, "disable_mute_time_out"}, /* Time out mute sequence , */\
+ { 0x170, "man_enbl_brown"}, /* Controls the reaction of the device on BOD , */\
+ { 0x180, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x191, "bod_delay_set"}, /* BOD filter , */\
+ { 0x1b1, "bod_lvl_set"}, /* BOD threshold level , */\
+ { 0x1d0, "man_enbl_dc_too_high"}, /* Device response to too high DC level flag (when DCTH asserts to 1) , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for MTP protection , */\
+ { 0x203, "audio_fs"}, /* Sample rate (Fs) , */\
+ { 0x240, "enbl_low_bandwidth"}, /* CS/VS decimator low bandwidth mode control , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x400, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal oscillator control during power down mode, */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* Force active the speaker sub-system clock when in idle power, */\
+ { 0x520, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM (MTP) , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to key registers , */\
+ { 0x1000, "flag_por"}, /* POR (sticky flag, clear on write a '1') , */\
+ { 0x1010, "flag_otpok"}, /* OTP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1020, "flag_uvpok"}, /* UVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm (sticky flag, clear on write a '1') , */\
+ { 0x1040, "flag_ocp_alarm"}, /* OCP amplifier (sticky flag, clear on write a '1'), */\
+ { 0x1050, "flag_lost_clk"}, /* Lost clock (sticky flag, clear on write a '1') , */\
+ { 0x1060, "flag_clk_out_of_range"}, /* External clock status (sticky flag, clear on write a '1'), */\
+ { 0x1070, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky flag, clear on write a '1'), */\
+ { 0x1080, "flag_bst_bstcur"}, /* DCDC current limiting (sticky flag, clear on write a '1'), */\
+ { 0x1090, "flag_bst_hiz"}, /* DCDC active (sticky flag, clear on write a '1') , */\
+ { 0x10a0, "flag_adc10_ready"}, /* ADC ready flag (sticky flag, clear on write a '1'), */\
+ { 0x10b0, "flag_ocpokap"}, /* OCPOK pmos A (sticky flag, clear on write a '1') , */\
+ { 0x10c0, "flag_ocpokan"}, /* OCPOK nmos A (sticky flag, clear on write a '1') , */\
+ { 0x10d0, "flag_ocpokbp"}, /* OCPOK pmos B (sticky flag, clear on write a '1') , */\
+ { 0x10e0, "flag_ocpokbn"}, /* OCPOK nmos B (sticky flag, clear on write a '1') , */\
+ { 0x10f0, "flag_dc_too_high"}, /* DC level on audio input stream too high (sticky flag, clear on write a '1'), */\
+ { 0x1100, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1110, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1120, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x1190, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11a0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11b0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x11c0, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1203, "man_state"}, /* Device manager status , */\
+ { 0x1243, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x1282, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x12b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x12d0, "flag_waiting_for_sync"}, /* CGU and PLL synchronisation status flag from CGU , */\
+ { 0x1300, "flag_bod_vddd_nok"}, /* BOD Flag VDD NOT OK (sticky flag, clear on write a '1'), */\
+ { 0x140c, "dc_level_detect"}, /* DC level detected by DC protection module (2s complement), */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2011, "tdm_vamp_sel"}, /* Amplifier input selection , */\
+ { 0x2030, "tdm_input_level"}, /* TDM output attenuation , */\
+ { 0x2040, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2050, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2061, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2081, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x20a1, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2100, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x2110, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x2120, "tdm_sink0_enable"}, /* Control audio TDM channel in 0 , */\
+ { 0x2130, "tdm_sink1_enable"}, /* Control audio TDM channel in 1 , */\
+ { 0x2140, "tdm_source0_enable"}, /* Enable TDM source0 data channel , */\
+ { 0x2150, "tdm_source1_enable"}, /* Enable TDM source1 data channel , */\
+ { 0x2160, "tdm_source2_enable"}, /* Enable TDM source2 data channel , */\
+ { 0x2170, "tdm_source3_enable"}, /* Enable TDM source3 data channel , */\
+ { 0x2183, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x21c3, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2203, "tdm_source0_slot"}, /* Slot Position of TDM source0 channel data , */\
+ { 0x2243, "tdm_source1_slot"}, /* Slot Position of TDM source1 channel data , */\
+ { 0x2283, "tdm_source2_slot"}, /* Slot Position of TDM source2 channel data , */\
+ { 0x22c3, "tdm_source3_slot"}, /* Slot Position of TDM source3 channel data , */\
+ { 0x4000, "int_out_flag_por"}, /* Interrupt status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Interrupt status DCDC OCP alarm , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Interrupt status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Interrupt status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Interrupt status UVP alarm , */\
+ { 0x4050, "int_out_flag_tdm_error"}, /* Interrupt status TDM error , */\
+ { 0x4060, "int_out_flag_lost_clk"}, /* Interrupt status lost clock , */\
+ { 0x4070, "int_out_flag_dc_too_high"}, /* Interrupt status dc too high , */\
+ { 0x4080, "int_out_flag_bod_vddd_nok"}, /* Interrupt status brown out detected , */\
+ { 0x4090, "int_out_flag_clk_out_of_range"}, /* Interrupt status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear interrupt status POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear interrupt status DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear interrupt status OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear interrupt status OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear interrupt status UVP alarm , */\
+ { 0x4450, "int_in_flag_tdm_error"}, /* Clear interrupt status TDM error , */\
+ { 0x4460, "int_in_flag_lost_clk"}, /* Clear interrupt status lost clk , */\
+ { 0x4470, "int_in_flag_dc_too_high"}, /* Clear interrupt status dc too high , */\
+ { 0x4480, "int_in_flag_bod_vddd_nok"}, /* Clear interrupt status brown out detected , */\
+ { 0x4490, "int_in_flag_clk_out_of_range"}, /* Clear interrupt status clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable interrupt POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable interrupt DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable interrupt OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable interrupt OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable interrupt UVP alarm , */\
+ { 0x4850, "int_enable_flag_tdm_error"}, /* Enable interrupt TDM error , */\
+ { 0x4860, "int_enable_flag_lost_clk"}, /* Enable interrupt lost clk , */\
+ { 0x4870, "int_enable_flag_dc_too_high"}, /* Enable interrupt dc too high , */\
+ { 0x4880, "int_enable_flag_bod_vddd_nok"}, /* Enable interrupt brown out detect , */\
+ { 0x4890, "int_enable_flag_clk_out_of_range"}, /* Enable interrupt clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Interrupt polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Interrupt polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Interrupt polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Interrupt polarity OCP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Interrupt polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_tdm_error"}, /* Interrupt polarity TDM error , */\
+ { 0x4c60, "int_polarity_flag_lost_clk"}, /* Interrupt polarity lost clk , */\
+ { 0x4c70, "int_polarity_flag_dc_too_high"}, /* Interrupt polarity dc too high , */\
+ { 0x4c80, "int_polarity_flag_bod_vddd_nok"}, /* Interrupt polarity brown out detect , */\
+ { 0x4c90, "int_polarity_flag_clk_out_of_range"}, /* Interrupt polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5111, "dc_prot_time_constant"}, /* Duration of DC level detection , */\
+ { 0x5131, "dc_prot_level"}, /* DC-level detection , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5240, "bypasshwclip"}, /* Bypass hardware clipper , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5300, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5310, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5320, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5330, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5343, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit DAC , */\
+ { 0x5381, "ref_amp_irefdist_set_ctrl"}, /* Scaling of reference current for amplifier OCP , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5481, "ctrlloop_vstress_select"}, /* GO2 capacitor stress selector for control loop , */\
+ { 0x54a0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x54b0, "ctrl_slope"}, /* Slope speed setting , */\
+ { 0x54c0, "sel_icomp_dem_clk"}, /* Clock selection for icomp_dem , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5610, "ref_iref_test_enbl"}, /* Enable of test function of reference current , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x5705, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually in I2C direct control mode, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage the control stage in I2C direct control mode, */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage the power stage in I2C direct control mode, */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock PWM is 1/(K*4096*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* Ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* Low noise gain switch ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC Number of zero current flags to count before going to PFM mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x66d2, "pfmfreq_limit"}, /* Lowest PFM frequency limit , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage in I2C direct control mode, */\
+ { 0x6713, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* Clip flag information for TDM Compressed2a/b/c modes, */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* Disable auto engage , */\
+ { 0x6b10, "disable_engage"}, /* Disable engage , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* Spare control bits for future use , */\
+ { 0x6d09, "spare_in"}, /* Spare control bit - read only , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* Low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* Vddp greater than Vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7087, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* Scale factor for peak current measurement - ratio between reference current and power transistor current, */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller in I2C direct control mode, */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator in I2C direct control mode , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current in I2C direct control mode , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage in I2C direct control mode, */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current DAC in I2C direct control mode, */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators in I2C direct control mode, */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators in I2C direct control mode, */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators in I2C direct control mode, */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window DAC in I2C direct control mode , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7350, "disable_artf654484_fix"}, /* Disables the fix for artf654484 (loss of efficiency when Vbst is close to Vbat), */\
+ { 0x7360, "disable_artf676996_fix"}, /* Disables the fix for artf676996 (OCP booster triggered when Vtrgt is just above Vbat), */\
+ { 0x7371, "ref_bst_irefdist_set_ctrl"}, /* Scaling of reference current for booster OCP , */\
+ { 0x7400, "dcdc_disable_ns"}, /* Disable control of noise shaper in DCDC control , */\
+ { 0x7410, "dcdc_disable_mod8bit"}, /* Disable control of reset of noise shaper when 8 bit value for dcdc control occurs, */\
+ { 0x7420, "disable_dynamic_freq"}, /* Disables the dynamic frequency switching due to flag_voutcomp86/93, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when DCIE is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* Headroom for 1st Adaptive boost trip level, effective only when DCIE is set to 1 and DCTRACK is 0, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when DCIE is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when DCIE is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7500, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7510, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* Headroom for 2nd Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 0, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Headroom for Tracking Adaptive boost trip level, effective only when DCIE is 1 and DCTRACK is 1, */\
+ { 0x75d0, "bypass_dcdc_lpf"}, /* Bypass control of DCDC control low pass filter for quantization noise suppression, */\
+ { 0x75e0, "enbl_bst_filter"}, /* Enable the boost filter , */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7607, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7687, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7707, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x87a0, "enbl_ana_pre"}, /* Control for enabling the pre-empasis filter for voltage and current sense decimator, */\
+ { 0x8800, "vs1_adc_enbl"}, /* Enable voltage sense VS1 ADC (direct control mode only), */\
+ { 0x8810, "vs1_inn_short_ctrl"}, /* Short voltage sense VS1 negative to common mode , */\
+ { 0x8820, "vs1_inp_short_ctrl"}, /* Short voltage sense VS1 positive to common mode , */\
+ { 0x8830, "vs1_ldo_enbl"}, /* Enable voltage sense VS1 LDO (direct control mode only), */\
+ { 0x8840, "vs1_vbatldo_enbl"}, /* Enable voltage sense VS1 VBAT LDO (direct control mode only), */\
+ { 0x8850, "vs1_gain_control"}, /* Voltage sense VS1 gain control , */\
+ { 0x8860, "vs1_bypass_gc"}, /* Bypasses the VS1 gain correction , */\
+ { 0x8870, "vs1_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8887, "vs1_gain"}, /* Voltage sense VS1 gain , */\
+ { 0x8900, "vs2_adc_enbl"}, /* Enable voltage sense VS2 ADC (direct control mode only), */\
+ { 0x8910, "vs2_inn_short_ctrl"}, /* Short voltage sense VS2 negative to common mode , */\
+ { 0x8920, "vs2_inp_short_ctrl"}, /* Short voltage sense VS2 positive to common mode , */\
+ { 0x8930, "vs2_ldo_enbl"}, /* Enable voltage sense VS2 LDO (direct control mode only), */\
+ { 0x8940, "vs2_vbatldo_enbl"}, /* Enable voltage sense VS2 VBAT LDO (direct control mode only), */\
+ { 0x8950, "vs2_gain_control"}, /* Voltage sense VS2 gain control , */\
+ { 0x8960, "vs2_bypass_gc"}, /* Bypasses the VS2 gain correction , */\
+ { 0x8970, "vs2_adc_bsoinv_ctrl"}, /* Bitstream inversion for voltage sense VS1 ADC , */\
+ { 0x8987, "vs2_gain"}, /* Voltage sense VS2 gain , */\
+ { 0x8a00, "vs_adc_delay_ctrl"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8a10, "vs_adc_nortz_ctrl"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8a20, "vs_ldo_bypass_ctrl"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown_ctrl"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset_ctrl"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "vs_anamux_overrule"}, /* Overrule the disconnection of VS pins , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_protected registers (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc0f0, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc376, "pulselength"}, /* Pulse length setting test input for amplifier (PWM clock 2048/4096 Fs), */\
+ { 0xc3e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert PWMbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old OCP (ctrl_reversebst is 0), For new OCP (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "cs_test_enbl"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "vs1_test_enbl"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc590, "vs2_test_enbl"}, /* Enable for digimux mode of dual sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_seli"}, /* PLL seli bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd64, "pll_selp"}, /* PLL selp bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdb3, "pll_selr"}, /* PLL selr bandwidth control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcdf0, "pll_band_direct"}, /* PLL bandwidth selection direct control, USE WITH CAUTION, */\
+ { 0xce00, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xce10, "pll_directi"}, /* PLL directi control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce20, "pll_directo"}, /* PLL directo control in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce34, "pll_pdiv"}, /* PLL PDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xce87, "pll_ndiv"}, /* PLL NDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcf0f, "pll_mdiv"}, /* PLL MDIV in PLL direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd000, "use_direct_pll_ctrl"}, /* Enable PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd010, "enbl_pll"}, /* Enables PLL in PLL direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd020, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, */\
+ { 0xd030, "pll_frm_clockstable"}, /* PLL FRM clock stable in pll direct control mode, use_direct_pll_ctrl set to 1, */\
+ { 0xd042, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd502, "amp_pst_drive_ctrl"}, /* Amplifier powerstage drive control , */\
+ { 0xd534, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range checker , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd822, "test_parametric_io"}, /* Test io parametric , */\
+ { 0xd861, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd8c3, "test_spare_out2"}, /* Test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from auto calibration, to be written into MTP - Read Only, */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf107, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_vs1_gain"}, /* Voltage sense VS1 gain calibration , */\
+ { 0xf387, "calibr_vs2_gain"}, /* Voltage sense VS2 gain calibration , */\
+ { 0xf407, "calibr_vs1_trim"}, /* VS1 ADC trimming , */\
+ { 0xf487, "calibr_vs2_trim"}, /* VS2 ADC Trimming , */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+#if 0
+enum tfa9875_irq {
+ tfa9875_irq_max = -1,
+ tfa9875_irq_all = -1 /* all irqs */};
+#endif
+#define TFA9875_IRQ_NAMETABLE static tfaIrqName_t Tfa9875IrqNames[]= {\
+};
+#endif /* _TFA9875_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9878_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9878_tfafieldnames.h
new file mode 100644
index 00000000000..f015fe7ca6f
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9878_tfafieldnames.h
@@ -0,0 +1,980 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9878_tfaFieldnames.h
+ * This file was generated automatically on 06/28/19 at 10:22:32.
+ * Source file: TFA9878_PRB3_N1A1_DefaultI2CSettings.xlsx
+ */
+
+#ifndef _TFA9878_TFAFIELDNAMES_H
+#define _TFA9878_TFAFIELDNAMES_H
+
+
+#define TFA9878_I2CVERSION 12
+
+typedef enum Tfa9878BfEnumList {
+ TFA9878_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9878_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9878_BF_AMPE = 0x0030, /*!< Activate Amplifier */
+ TFA9878_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9878_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9878_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9878_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9878_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9878_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9878_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9878_BF_DCINSEL= 0x0131, /*!< VAMP_OUT2 input selection */
+ TFA9878_BF_MUTETO= 0x0160, /*!< Time out SB mute sequence */
+ TFA9878_BF_MANROBOD= 0x0170, /*!< Reaction on BOD */
+ TFA9878_BF_BODE = 0x0180, /*!< Enable BOD (only in direct control mode) */
+ TFA9878_BF_BODHYS= 0x0190, /*!< Enable Hysteresis of BOD */
+ TFA9878_BF_BODFILT= 0x01a1, /*!< BOD filter */
+ TFA9878_BF_BODTHLVL= 0x01c1, /*!< BOD threshold */
+ TFA9878_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9878_BF_DISFCRBST= 0x01f0, /*!< disable boost control with FRCBST */
+ TFA9878_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9878_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9878_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9878_BF_AMPINPSEL= 0x02b1, /*!< amp input selection */
+ TFA9878_BF_PDMRATE= 0x02d0, /*!< Pdm rate */
+ TFA9878_BF_REV = 0x030f, /*!< Revision info */
+ TFA9878_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9878_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9878_BF_SWCLKSEL= 0x0432, /*!< Sound Wire clock frequnecy */
+ TFA9878_BF_MANAOOSC= 0x0460, /*!< Internal osc off at PWDN */
+ TFA9878_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9878_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9878_BF_AUTOFROSEL= 0x04a0, /*!< override automatic OSC selection mechanism */
+ TFA9878_BF_SWFRSYNC= 0x04b0, /*!< Selection SW signal reference for Stream Synchronization */
+ TFA9878_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9878_BF_FRCCLKSPKR= 0x0510, /*!< force active the speaker sub-system clock when in idle power */
+ TFA9878_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9878_BF_CLKCHKLO= 0x0707, /*!< Clock check Low Threshold */
+ TFA9878_BF_CLKCHKHI= 0x0787, /*!< Clock check Higher Threshold */
+ TFA9878_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9878_BF_VDDS = 0x1000, /*!< POR */
+ TFA9878_BF_DCOCPOK= 0x1010, /*!< DCDC OCP nmos (sticky register , clear on read) */
+ TFA9878_BF_OTDS = 0x1020, /*!< OTP alarm (sticky register , clear on read) */
+ TFA9878_BF_OCDS = 0x1030, /*!< OCP amplifier (sticky register , clear on read) */
+ TFA9878_BF_UVDS = 0x1040, /*!< UVP alarm (sticky register , clear on read) */
+ TFA9878_BF_MANALARM= 0x1050, /*!< Alarm state */
+ TFA9878_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9878_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9878_BF_NOCLK = 0x1080, /*!< Lost clock (sticky register , clear on read) */
+ TFA9878_BF_BODNOK= 0x1090, /*!< BOD Flag - VDD NOT OK */
+ TFA9878_BF_TDMERR= 0x10a0, /*!< TDM error */
+ TFA9878_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9878_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register , clear on read) */
+ TFA9878_BF_DCDCPC= 0x1120, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9878_BF_DCHVBAT= 0x1130, /*!< DCDC level 1x */
+ TFA9878_BF_DCH114= 0x1140, /*!< DCDC level 1.14x */
+ TFA9878_BF_DCH107= 0x1150, /*!< DCDC level 1.07x */
+ TFA9878_BF_PLLS = 0x1160, /*!< PLL lock */
+ TFA9878_BF_TDMLUTER= 0x1180, /*!< TDM LUT error */
+ TFA9878_BF_CLKOOR= 0x11c0, /*!< External clock status */
+ TFA9878_BF_SWS = 0x11d0, /*!< Amplifier engage */
+ TFA9878_BF_AMPS = 0x11e0, /*!< Amplifier enable */
+ TFA9878_BF_AREFS = 0x11f0, /*!< References enable */
+ TFA9878_BF_OCPOAP= 0x1300, /*!< OCPOK pmos B */
+ TFA9878_BF_OCPOAN= 0x1310, /*!< OCPOK pmos A */
+ TFA9878_BF_OCPOBP= 0x1320, /*!< OCPOK nmos B */
+ TFA9878_BF_OCPOBN= 0x1330, /*!< OCPOK nmos A */
+ TFA9878_BF_OVDS = 0x1380, /*!< OVP alarm */
+ TFA9878_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9878_BF_ADCCR = 0x13a0, /*!< Control ADC */
+ TFA9878_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9878_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9878_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9878_BF_TDMSTAT= 0x1402, /*!< TDM status bits */
+ TFA9878_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9878_BF_AMPSTE= 0x1473, /*!< Amplifier control status */
+ TFA9878_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9878_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9878_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9878_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9878_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9878_BF_TDMSLOTS= 0x2013, /*!< N-slots in Frame */
+ TFA9878_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9878_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9878_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9878_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9878_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9878_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9878_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9878_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9878_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9878_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9878_BF_TDMTXDFO= 0x2271, /*!< Format unused bits */
+ TFA9878_BF_TDMTXUS0= 0x2291, /*!< Format unused slots DATAO */
+ TFA9878_BF_TDMSPKE= 0x2300, /*!< Control audio tdm channel in 0 */
+ TFA9878_BF_TDMDCE= 0x2310, /*!< Control audio tdm channel in 1 */
+ TFA9878_BF_TDMCSE= 0x2330, /*!< current sense vbat temperature and vddp feedback */
+ TFA9878_BF_TDMVSE= 0x2340, /*!< Voltage sense vbat temperature and vddp feedback */
+ TFA9878_BF_TDMSPKS= 0x2603, /*!< tdm slot for sink 0 */
+ TFA9878_BF_TDMDCS= 0x2643, /*!< tdm slot for sink 1 */
+ TFA9878_BF_TDMCSS= 0x26c3, /*!< Slot Position of current sense vbat temperature and vddp feedback */
+ TFA9878_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense vbat temperature and vddp feedback */
+ TFA9878_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9878_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9878_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9878_BF_ISTOCPR= 0x4030, /*!< Status ocp alarm */
+ TFA9878_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9878_BF_ISTMANALARM= 0x4050, /*!< Status nanager Alarm state */
+ TFA9878_BF_ISTTDMER= 0x4060, /*!< Status tdm error */
+ TFA9878_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9878_BF_ISTBODNOK= 0x4080, /*!< Status BOD event */
+ TFA9878_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9878_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9878_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9878_BF_ICLOCPR= 0x4430, /*!< Clear ocp alarm */
+ TFA9878_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9878_BF_ICLMANALARM= 0x4450, /*!< Clear manager Alarm state */
+ TFA9878_BF_ICLTDMER= 0x4460, /*!< Clear tdm error */
+ TFA9878_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9878_BF_ICLBODNOK= 0x4480, /*!< Clear BOD event */
+ TFA9878_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9878_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9878_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9878_BF_IEOCPR= 0x4830, /*!< Enable ocp alarm */
+ TFA9878_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9878_BF_IEMANALARM= 0x4850, /*!< Enable nanager Alarm state */
+ TFA9878_BF_IETDMER= 0x4860, /*!< Enable tdm error */
+ TFA9878_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9878_BF_IEBODNOK= 0x4880, /*!< Enable BOD trigger */
+ TFA9878_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9878_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9878_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9878_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9878_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9878_BF_IPOMANALARM= 0x4c50, /*!< Polarity nanager Alarm state */
+ TFA9878_BF_IPOTDMER= 0x4c60, /*!< Polarity tdm error */
+ TFA9878_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9878_BF_IPOBODNOK= 0x4c80, /*!< Polarity BOD trigger */
+ TFA9878_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time (with K = 1 at sample rate fs of 32kHz, 44,1 kHz or 48kHz ; with K = 2 at sample rate fs 16 kHz . With K =0.5 at sample rate of 96 kHz) */
+ TFA9878_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9878_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9878_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9878_BF_BSSBY = 0x50f0, /*!< Bypass battery safeguard */
+ TFA9878_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9878_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9878_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9878_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9878_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9878_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9878_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9878_BF_BYPDLYLINE= 0x52f0, /*!< Bypass the interpolator delay line */
+ TFA9878_BF_TDMDCG= 0x5f23, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9878_BF_TDMSPKG= 0x5f63, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9878_BF_IPM = 0x60e1, /*!< Idle power mode control */
+ TFA9878_BF_LNMODE= 0x62e1, /*!< ctrl select mode */
+ TFA9878_BF_LPM1MODE= 0x64e1, /*!< low power mode control */
+ TFA9878_BF_TDMSRCMAP= 0x6802, /*!< tdm source mapping */
+ TFA9878_BF_TDMSRCAS= 0x6831, /*!< Sensed value A */
+ TFA9878_BF_TDMSRCBS= 0x6851, /*!< Sensed value B */
+ TFA9878_BF_TDMSRCACLIP= 0x6871, /*!< clip information (analog /digital) for source0 */
+ TFA9878_BF_TDMSRCBCLIP= 0x6891, /*!< clip information (analog /digital) for source1 */
+ TFA9878_BF_LP0 = 0x6e00, /*!< Idle power mode */
+ TFA9878_BF_LP1 = 0x6e10, /*!< low power mode 1 detection */
+ TFA9878_BF_LA = 0x6e20, /*!< low amplitude detection */
+ TFA9878_BF_VDDPH = 0x6e30, /*!< vddp greater than vbat */
+ TFA9878_BF_DELCURCOMP= 0x6f02, /*!< delay to allign compensation signal with current sense signal */
+ TFA9878_BF_SIGCURCOMP= 0x6f40, /*!< polarity of compensation for current sense */
+ TFA9878_BF_ENCURCOMP= 0x6f50, /*!< enable current sense compensation */
+ TFA9878_BF_LVLCLPPWM= 0x6f72, /*!< set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9878_BF_DCMCC = 0x7003, /*!< Max coil current */
+ TFA9878_BF_DCCV = 0x7041, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9878_BF_DCIE = 0x7060, /*!< Adaptive boost mode */
+ TFA9878_BF_DCSR = 0x7070, /*!< Soft ramp up/down */
+ TFA9878_BF_DCOVL = 0x7085, /*!< Threshold level to activate active overshoot control */
+ TFA9878_BF_DCDIS = 0x70e0, /*!< DCDC on/off */
+ TFA9878_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9878_BF_DCTRACK= 0x7430, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCTRIP= 0x7444, /*!< 1st Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9878_BF_DCHOLD= 0x7494, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCINT = 0x74e0, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCTRIP2= 0x7534, /*!< 2nd Adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9878_BF_DCTRIPT= 0x7584, /*!< Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9878_BF_DCTRIPHYSTE= 0x75f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9878_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9878_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9878_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9878_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9878_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9878_BF_MTPADDR= 0xa302, /*!< MTP address from I2C register for read/writing mtp in manual single word mode */
+ TFA9878_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9878_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9878_BF_MTPWRMSB= 0xa70f, /*!< MSB word of write data for MTP manual write */
+ TFA9878_BF_MTPWRLSB= 0xa80f, /*!< LSB word of write data for MTP manual write */
+ TFA9878_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9878_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9878_BF_PLLINSI= 0xcd05, /*!< PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9878_BF_PLLINSP= 0xcd64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9878_BF_PLLINSR= 0xcdb3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9878_BF_PLLBDSEL= 0xcdf0, /*!< PLL bandwidth selection control, USE WITH CAUTION */
+ TFA9878_BF_PLLNDEC= 0xce09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLMDECM= 0xcea0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLBP = 0xceb0, /*!< PLL bypass control during functional mode */
+ TFA9878_BF_PLLDI = 0xcec0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLDO = 0xced0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLCLKSTB= 0xcee0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLFRM= 0xcef0, /*!< PLL free running mode control in functional mode */
+ TFA9878_BF_PLLMDECL= 0xcf0f, /*!< Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLPDEC= 0xd006, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9878_BF_PLLDCTRL= 0xd070, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9878_BF_PLLLIMOFF= 0xd090, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9878_BF_PLLSTRTM= 0xd0a2, /*!< PLL startup time selection control */
+ TFA9878_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9878_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9878_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9878_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9878_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9878_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9878_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9878_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9878_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9878BfEnumList_t;
+#define TFA9878_NAMETABLE static tfaBfName_t Tfa9878DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "AMPE"}, /* Activate Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x131, "DCINSEL"}, /* VAMP_OUT2 input selection , */\
+ { 0x160, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x170, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x180, "BODE"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x190, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x1a1, "BODFILT"}, /* BOD filter , */\
+ { 0x1c1, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "DISFCRBST"}, /* disable boost control with FRCBST , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b1, "AMPINPSEL"}, /* amp input selection , */\
+ { 0x2d0, "PDMRATE"}, /* Pdm rate , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x432, "SWCLKSEL"}, /* Sound Wire clock frequnecy , */\
+ { 0x460, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "AUTOFROSEL"}, /* override automatic OSC selection mechanism , */\
+ { 0x4b0, "SWFRSYNC"}, /* Selection SW signal reference for Stream Synchronization , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "FRCCLKSPKR"}, /* force active the speaker sub-system clock when in idle power, */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x707, "CLKCHKLO"}, /* Clock check Low Threshold , */\
+ { 0x787, "CLKCHKHI"}, /* Clock check Higher Threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "DCOCPOK"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "OTDS"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "OCDS"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "UVDS"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "MANALARM"}, /* Alarm state , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1090, "BODNOK"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x10a0, "TDMERR"}, /* TDM error , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1120, "DCDCPC"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1140, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1150, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1160, "PLLS"}, /* PLL lock , */\
+ { 0x1180, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11c0, "CLKOOR"}, /* External clock status , */\
+ { 0x11d0, "SWS"}, /* Amplifier engage , */\
+ { 0x11e0, "AMPS"}, /* Amplifier enable , */\
+ { 0x11f0, "AREFS"}, /* References enable , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos B , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK pmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK nmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos A , */\
+ { 0x1380, "OVDS"}, /* OVP alarm , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "ADCCR"}, /* Control ADC , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1402, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1473, "AMPSTE"}, /* Amplifier control status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2013, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "TDMSPKE"}, /* Control audio tdm channel in 0 , */\
+ { 0x2310, "TDMDCE"}, /* Control audio tdm channel in 1 , */\
+ { 0x2330, "TDMCSE"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "TDMSPKS"}, /* tdm slot for sink 0 , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for sink 1 , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status nanager Alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTBODNOK"}, /* Status BOD event , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager Alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLBODNOK"}, /* Clear BOD event , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IEBODNOK"}, /* Enable BOD trigger , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOBODNOK"}, /* Polarity BOD trigger , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time (with K = 1 at sample rate fs of 32kHz, 44,1 kHz or 48kHz ; with K = 2 at sample rate fs 16 kHz . With K =0.5 at sample rate of 96 kHz), */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass battery safeguard , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x5f23, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5f63, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x60e1, "IPM"}, /* Idle power mode control , */\
+ { 0x62e1, "LNMODE"}, /* ctrl select mode , */\
+ { 0x64e1, "LPM1MODE"}, /* low power mode control , */\
+ { 0x6802, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6831, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x6851, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x6871, "TDMSRCACLIP"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "TDMSRCBCLIP"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6e00, "LP0"}, /* Idle power mode , */\
+ { 0x6e10, "LP1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "LA"}, /* low amplitude detection , */\
+ { 0x6e30, "VDDPH"}, /* vddp greater than vbat , */\
+ { 0x6f02, "DELCURCOMP"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "SIGCURCOMP"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "ENCURCOMP"}, /* enable current sense compensation , */\
+ { 0x6f72, "LVLCLPPWM"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "DCMCC"}, /* Max coil current , */\
+ { 0x7041, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7060, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7070, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7085, "DCOVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "DCDIS"}, /* DCDC on/off , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7430, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "DCTRIP"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "DCINT"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7534, "DCTRIP2"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "DCTRIPT"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "MTPADDR"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "MTPWRMSB"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "MTPWRLSB"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xcd05, "PLLINSI"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcd64, "PLLINSP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "PLLINSR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "PLLBDSEL"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "PLLMDECM"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "PLLBP"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "PLLDI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "PLLDO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "PLLCLKSTB"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "PLLMDECL"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "PLLDCTRL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "PLLLIMOFF"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "PLLSTRTM"}, /* PLL startup time selection control , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9878_BITNAMETABLE static tfaBfName_t Tfa9878BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x30, "enbl_amplifier"}, /* Activate Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0xd0, "sel_man_wait_time"}, /* Manager wait time selection control , */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x131, "vamp_sel2"}, /* VAMP_OUT2 input selection , */\
+ { 0x160, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x170, "man_enbl_brown"}, /* Reaction on BOD , */\
+ { 0x180, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x190, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x1a1, "bod_delay_set"}, /* BOD filter , */\
+ { 0x1c1, "bod_lvl_set"}, /* BOD threshold , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "disable_frcbst"}, /* disable boost control with FRCBST , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b1, "amp_input_sel"}, /* amp input selection , */\
+ { 0x2d0, "pdm_rate"}, /* Pdm rate , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x432, "sw_clk_sel"}, /* Sound Wire clock frequnecy , */\
+ { 0x460, "enbl_osc_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "override_auto_sel_osc"}, /* override automatic OSC selection mechanism , */\
+ { 0x4b0, "sw_sync_sel"}, /* Selection SW signal reference for Stream Synchronization , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "force_spkr_clk"}, /* force active the speaker sub-system clock when in idle power, */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x707, "clkchk_th_lo"}, /* Clock check Low Threshold , */\
+ { 0x787, "clkchk_th_hi"}, /* Clock check Higher Threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register , clear on read) , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm (sticky register , clear on read) , */\
+ { 0x1030, "flag_ocp_alarm"}, /* OCP amplifier (sticky register , clear on read), */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm (sticky register , clear on read) , */\
+ { 0x1050, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock (sticky register , clear on read) , */\
+ { 0x1090, "flag_bod_vddd_nok"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x10a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register , clear on read) , */\
+ { 0x1120, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1130, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1140, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1150, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1160, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1180, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11c0, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x11d0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x11e0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x11f0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x1300, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1310, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1320, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1330, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1380, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x13f0, "flag_man_operating_state"}, /* Operating state , */\
+ { 0x1402, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2013, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots DATAO , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control audio tdm channel in 0 , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio tdm channel in 1 , */\
+ { 0x2330, "tdm_source0_enable"}, /* current sense vbat temperature and vddp feedback , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense vbat temperature and vddp feedback , */\
+ { 0x2603, "tdm_sink0_slot"}, /* tdm slot for sink 0 , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for sink 1 , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of current sense vbat temperature and vddp feedback, */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense vbat temperature and vddp feedback, */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status nanager Alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_bod_vddd_nok"}, /* Status BOD event , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager Alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_bod_vddd_nok"}, /* Clear BOD event , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable nanager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_bod_vddd_nok"}, /* Enable BOD trigger , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity nanager Alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_bod_vddd_nok"}, /* Polarity BOD trigger , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time (with K = 1 at sample rate fs of 32kHz, 44,1 kHz or 48kHz ; with K = 2 at sample rate fs 16 kHz . With K =0.5 at sample rate of 96 kHz), */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass battery safeguard , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x52f0, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low pass filter inside temperature sensor, */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5463, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5500, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5513, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5552, "dpsa_drive"}, /* Drive setting (bin. coded) , */\
+ { 0x5600, "ref_iref_enbl"}, /* Enable of reference current for OCP , */\
+ { 0x5631, "ref_irefdist_set_ctrl"}, /* Scaling of reference current for OCP , */\
+ { 0x5652, "ref_irefdist_test_enbl"}, /* Enable of test-function of distribution of reference current, used for OCP. When enabled, the current will to to anamux iso powerstages. Using e.g. 011 it will add the current of powerstage P and N., */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x5900, "pwm_clk_sel"}, /* Control for selection for PWM delay line source , */\
+ { 0x5910, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x5f23, "ctrl_attl"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5f63, "ctrl_attr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x6005, "idle_power_cal_offset"}, /* Idle power mode detector ctrl cal_offset from gain module , */\
+ { 0x6065, "idle_power_zero_lvl"}, /* IIdle power mode zero crossing detection level , */\
+ { 0x60e1, "idle_power_mode"}, /* Idle power mode control , */\
+ { 0x6105, "idle_power_threshold_lvl"}, /* Idle power mode amplitude trigger level , */\
+ { 0x6165, "idle_power_hold_time"}, /* Idle power mode detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x61c0, "disable_idle_power_mode"}, /* Idle power mode detector control , */\
+ { 0x6265, "zero_lvl"}, /* low noise gain switch zero trigger level , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* low noise gain switch trigger level , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 zero crossing detection level , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode control , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 amplitude trigger level , */\
+ { 0x6565, "lpm1_hold_time"}, /* low power mode1 detector ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6802, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6831, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x6851, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x6871, "tdm_source0_clip_sel"}, /* clip information (analog /digital) for source0 , */\
+ { 0x6891, "tdm_source1_clip_sel"}, /* clip information (analog /digital) for source1 , */\
+ { 0x6a02, "rst_min_vbat_delay"}, /* rst_min_vbat delay (nb fs) , */\
+ { 0x6b00, "disable_auto_engage"}, /* disable auto engange , */\
+ { 0x6b10, "disable_engage"}, /* disable engange , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c69, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e00, "flag_idle_power_mode"}, /* Idle power mode , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x6f02, "cursense_comp_delay"}, /* delay to allign compensation signal with current sense signal, */\
+ { 0x6f40, "cursense_comp_sign"}, /* polarity of compensation for current sense , */\
+ { 0x6f50, "enbl_cursense_comp"}, /* enable current sense compensation , */\
+ { 0x6f72, "pwms_clip_lvl"}, /* set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7003, "boost_cur"}, /* Max coil current , */\
+ { 0x7041, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7060, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7070, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7085, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x70e0, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac , */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7360, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7444, "boost_trip_lvl_1st"}, /* 1st Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7534, "boost_trip_lvl_2nd"}, /* 2nd Adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7584, "boost_trip_lvl_track"}, /* Track Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x75f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8305, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP)*signal, */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8440, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8790, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8850, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8860, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8887, "vs_gain"}, /* voltage sense gain , */\
+ { 0x8c00, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8c40, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8c90, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8d30, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8d40, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8d50, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8d60, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8d74, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8f00, "enbl_vs_adc"}, /* Enable voltage sense ADC (Direct Control only only others done by manager), */\
+ { 0x8f10, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8f20, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8f30, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8f40, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8f50, "enbl_vs_ldo"}, /* Enable voltage sense LDO (Direct Control only only others done by manager), */\
+ { 0x8f80, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO (Direct Control only others done by manager), */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the faim controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the faim are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the faim are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* voltage sense Direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_fro"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs ), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc580, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 (see Digimux list for details), */\
+ { 0xc981, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xc9d1, "sw_hs_mode"}, /* Speed/load setting for SW IO cell, clk or data mode range (see SWMF IO cell datasheet), */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcac0, "open_frcbst_ensw_switch"}, /* Save test2 configuration before enable anamux2 (open test2 switch and save test2 setting) , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on FRCBST/TEST2 , */\
+ { 0xcb53, "anamux3"}, /* Anamux selection control - anamux on VSN/TEST3 , */\
+ { 0xcba3, "anamux4"}, /* Anamux selection control - anamux on VSP/TEST4 , */\
+ { 0xcd05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcd64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdb3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcdf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xceb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcec0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xced0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcee0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcef0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xd070, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xd090, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xd0a2, "sel_pll_startup_time"}, /* PLL startup time selection control , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd721, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xd740, "bck_ehs"}, /* High-speed and standard/fast mode selection for BCK IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd750, "datai_ehs"}, /* High-speed and standard/fast mode selection for DATAI IO cell (see IIC3V3 IO cell datasheet), */\
+ { 0xd800, "source_in_testmode"}, /* tdm source in test mode (return only current and voltage sense), */\
+ { 0xd810, "gainatt_tdm_feedback"}, /* gainatt feedback to tdm , */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost , */\
+ { 0xd890, "gainatt_sw_feedback"}, /* gainatt feedback to sw , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xd900, "enbl_frocal"}, /* Enable FRO calibration , */\
+ { 0xd910, "start_fro_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xd920, "enbl_irefcal"}, /* Enable IREF calibration , */\
+ { 0xd930, "start_iref_calibration"}, /* Start IREF Calibration , */\
+ { 0xda00, "fro_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xda15, "fro_auto_trim_val"}, /* Calibration value from Auto Calibration block, to be written into MTP - Read Only, */\
+ { 0xda80, "iref_calibration_done"}, /* IREF Calibration done - Read Only , */\
+ { 0xda94, "iref_auto_trim_val"}, /* Calibration value from Auto Calibration block, to be written into MTP - Read Only, */\
+ { 0xdae0, "iref_calibration_error"}, /* IREF Calibration done - Read Only , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf169, "spare_mtp1_15_6"}, /* SPARE , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a4, "optimal_pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0xf2f0, "enbl_optimal_pwm_delay"}, /* optimized pwm delay function enabled , */\
+ { 0xf307, "calibr_gain_vs1"}, /* Voltage sense gain when external voltage sensing input is selected, */\
+ { 0xf387, "calibr_gain_vs2"}, /* Voltage sense gain when internal voltage sensing input is selected, */\
+ { 0xf407, "vs_trim1"}, /* VS Trimming when external voltage sensing input is selected, */\
+ { 0xf487, "vs_trim2"}, /* VS Trimming when internal voltage sensing input is selected, */\
+ { 0xf50f, "calibr_R25C_R"}, /* Ron resistance of speaker coil , */\
+ { 0xf607, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf687, "spare_mpt6_15_06"}, /* SPARE , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf770, "spare_mtp7_07"}, /* SPARE , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf7f0, "spare_mtp7_15"}, /* SPARE , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable function dcdcoff_mode , */\
+ { 0xf910, "spare_mtp9_1"}, /* SPARE , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Force Boost in follower mode , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf980, "spare_mtp9_8"}, /* SPARE , */\
+ { 0xf990, "mtp_enbl_pwm_delay_clock_gating"}, /* pwm delay clock auto gating , */\
+ { 0xf9a0, "mtp_enbl_ocp_clock_gating"}, /* ocpclock auto gating , */\
+ { 0xf9b0, "mtp_gate_cgu_clock_for_test"}, /* cgu test clock control , */\
+ { 0xf9c0, "mtp_tdm_pad_sel"}, /* tdm pad selection , */\
+ { 0xf9d2, "spare_mtp9_15_12"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro_shortnwell"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro_boost"}, /* Self bias current selection , */\
+ { 0xffa4, "calibr_iref_trim"}, /* Trimming control of reference current for OCP , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9878_irq {
+ tfa9878_irq_stvdds = 0,
+ tfa9878_irq_stbstoc = 1,
+ tfa9878_irq_stotds = 2,
+ tfa9878_irq_stocpr = 3,
+ tfa9878_irq_stuvds = 4,
+ tfa9878_irq_stmanalarm = 5,
+ tfa9878_irq_sttdmer = 6,
+ tfa9878_irq_stnoclk = 7,
+ tfa9878_irq_stbodnok = 8,
+ tfa9878_irq_max = 9,
+ tfa9878_irq_all = -1 /* all irqs */};
+
+#define TFA9878_IRQ_NAMETABLE static tfaIrqName_t Tfa9878IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STBSTOC"},\
+ { 2, "STOTDS"},\
+ { 3, "STOCPR"},\
+ { 4, "STUVDS"},\
+ { 5, "STMANALARM"},\
+ { 6, "STTDMER"},\
+ { 7, "STNOCLK"},\
+ { 8, "STBODNOK"},\
+ { 9, "9"},\
+};
+#endif /* _TFA9878_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9887_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9887_tfafieldnames.h
new file mode 100644
index 00000000000..ace434854f3
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9887_tfafieldnames.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa9887_TfaFieldnames.h
+ * This file was generated automatically on 04/14/15 at 10:23:40.
+ * Source file: TFA9897N1B_I2C_list_URT_source_v34_87Only.xls
+ */
+#define TFA9887_I2CVERSION 34
+#define TFA9895_I2CVERSION 34
+#define TFA9887_NAMETABLE static tfaBfName_t Tfa9887DatasheetNames[]= {\
+ { 0x402, "I2SF"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "CHS12"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "CHS3"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "I2SSR"}, /* sample rate setting , */\
+ { 0x500, "BSSBY"}, /* , */\
+ { 0x511, "BSSCR"}, /* 00 = 0.56 dB/Sample , */\
+ { 0x532, "BSST"}, /* 000 = 2.92V , */\
+ { 0x5f0, "I2SDOC"}, /* selection data out , */\
+ { 0xa02, "DOLS"}, /* Output selection dataout left channel , */\
+ { 0xa32, "DORS"}, /* Output selection dataout right channel , */\
+ { 0xa62, "SPKL"}, /* Selection speaker induction , */\
+ { 0xa91, "SPKR"}, /* Selection speaker impedance , */\
+ { 0xab3, "DCFG"}, /* DCDC speaker current compensation gain , */\
+ { 0x4134, "PWMDEL"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "PWMSH"}, /* PWM Shape , */\
+ { 0x4190, "PWMRE"}, /* PWM Bitlength in noise shaper , */\
+ { 0x48e1, "TCC"}, /* sample & hold track time: , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9887_BITNAMETABLE static tfaBfName_t Tfa9887BitNames[]= {\
+ { 0x402, "i2s_seti"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "chan_sel1"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "lr_sw_i2si2"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "input_sel"}, /* Input selection for amplifier , */\
+ { 0x4b0, "enbl_datao"}, /* Enable data output , */\
+ { 0x4c3, "i2s_fs"}, /* sample rate setting , */\
+ { 0x500, "bypass_clipper"}, /* , */\
+ { 0x511, "vbat_prot_attacktime[1:0]"}, /* 00 = 0.56 dB/Sample , */\
+ { 0x532, "vbat_prot_thlevel[2:0]"}, /* 000 = 2.92V , */\
+ { 0x5d0, "reset_min_vbat"}, /* to reset the clipper via I2C in case the CF is bypassed, */\
+ { 0x5f0, "datao_sel"}, /* selection data out , */\
+ { 0xa02, "sel_i2so_l"}, /* Output selection dataout left channel , */\
+ { 0xa32, "sel_i2so_r"}, /* Output selection dataout right channel , */\
+ { 0xa62, "ctrl_spkr_coil"}, /* Selection speaker induction , */\
+ { 0xa91, "ctrl_spr_res"}, /* Selection speaker impedance , */\
+ { 0xab3, "ctrl_dcdc_spkr_i_comp_gain"}, /* DCDC speaker current compensation gain , */\
+ { 0xaf0, "ctrl_dcdc_spkr_i_comp_sign"}, /* DCDC speaker current compensation sign , */\
+ { 0x4100, "bypass_hp"}, /* bypass_hp, to bypass the hp filter byhind the CoolFlux, */\
+ { 0x4110, "hard_mute"}, /* hard mute setting in HW , */\
+ { 0x4120, "soft_mute"}, /* Soft mute setting in HW , */\
+ { 0x4134, "PWM_Delay[4:0]"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "PWM_Shape"}, /* PWM Shape , */\
+ { 0x4190, "PWM_BitLength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4800, "ctrl_negin"}, /* , */\
+ { 0x4810, "ctrl_cs_sein"}, /* , */\
+ { 0x4820, "ctrl_coincidencecs"}, /* HIGH => Prevent dcdc switching during clk_cs_clksh, */\
+ { 0x4876, "delay_se_neg[6:0]"}, /* delayshiftse2 , */\
+ { 0x48e1, "ctrl_cs_ttrack[1:0]"}, /* sample & hold track time: , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9890_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9890_tfafieldnames.h
new file mode 100644
index 00000000000..4bdeff6ac07
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9890_tfafieldnames.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa9890_TfaFieldnames.h
+ * This file was generated automatically on 04/07/15 at 14:46:37.
+ * Source file: TFA9897N1B_I2C_list_URT_source_v34_90Only.xls
+ */
+#define TFA9890_I2CVERSION 34
+#define TFA9890_NAMETABLE static tfaBfName_t Tfa9890DatasheetNames[]= {\
+ { 0x402, "I2SF"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "CHS12"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "CHS3"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x481, "I2SDOC"}, /* selection data out , */\
+ { 0x4a0, "DISP"}, /* idp protection , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "I2SSR"}, /* sample rate setting , */\
+ { 0x732, "DCMCC"}, /* Max boost coil current - step of 500 mA , */\
+ { 0x9c0, "CCFD"}, /* Selection CoolFlux Clock , */\
+ { 0x9d0, "ISEL"}, /* selection input 1 or 2 , */\
+ { 0xa02, "DOLS"}, /* Output selection dataout left channel , */\
+ { 0xa32, "DORS"}, /* Output selection dataout right channel , */\
+ { 0xa62, "SPKL"}, /* Selection speaker induction , */\
+ { 0xa91, "SPKR"}, /* Selection speaker impedance , */\
+ { 0xab3, "DCFG"}, /* DCDC speaker current compensation gain , */\
+ { 0xf00, "VDDD"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "OTDD"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "OVDD"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "UVDD"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "OCDD"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "CLKD"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "DCCD"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "SPKD"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "WDD"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xf90, "LCLK"}, /* mask flag_lost_clk for interupt generation , */\
+ { 0xfe0, "INT"}, /* enabling interrupt , */\
+ { 0xff0, "INTP"}, /* Setting polarity interupt , */\
+ { 0x8f0f, "VERSION"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9890_BITNAMETABLE static tfaBfName_t Tfa9890BitNames[]= {\
+ { 0x402, "i2s_seti"}, /* I2SFormat data 1 input: , */\
+ { 0x431, "chan_sel1"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "lr_sw_i2si2"}, /* ChannelSelection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "input_sel"}, /* Input selection for amplifier , */\
+ { 0x481, "datao_sel"}, /* selection data out , */\
+ { 0x4a0, "disable_idp"}, /* idp protection , */\
+ { 0x4b0, "enbl_datao"}, /* Enable data output , */\
+ { 0x4c3, "i2s_fs"}, /* sample rate setting , */\
+ { 0x732, "ctrl_bstcur"}, /* Max boost coil current - step of 500 mA , */\
+ { 0x9c0, "sel_cf_clk"}, /* Selection CoolFlux Clock , */\
+ { 0x9d0, "intf_sel"}, /* selection input 1 or 2 , */\
+ { 0xa02, "sel_i2so_l"}, /* Output selection dataout left channel , */\
+ { 0xa32, "sel_i2so_r"}, /* Output selection dataout right channel , */\
+ { 0xa62, "ctrl_spkr_coil"}, /* Selection speaker induction , */\
+ { 0xa91, "ctrl_spr_res"}, /* Selection speaker impedance , */\
+ { 0xab3, "ctrl_dcdc_spkr_i_comp_gain"}, /* DCDC speaker current compensation gain , */\
+ { 0xaf0, "ctrl_dcdc_spkr_i_comp_sign"}, /* DCDC speaker current compensation sign , */\
+ { 0xf00, "flag_por_mask"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "flag_otpok_mask"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "flag_ovpok_mask"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "flag_uvpok_mask"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "flag_ocp_alarm_mask"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "flag_clocks_stable_mask"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "flag_pwrokbst_mask"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "flag_cf_speakererror_mask"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "flag_watchdog_reset_mask"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xf90, "flag_lost_clk_mask"}, /* mask flag_lost_clk for interupt generation , */\
+ { 0xfe0, "enable_interrupt"}, /* enabling interrupt , */\
+ { 0xff0, "invert_int_polarity"}, /* Setting polarity interupt , */\
+ { 0x4700, "switch_fb"}, /* switch_fb , */\
+ { 0x4713, "se_hyst"}, /* se_hyst , */\
+ { 0x4754, "se_level"}, /* se_level , */\
+ { 0x47a5, "ktemp"}, /* temperature compensation trimming , */\
+ { 0x8f0f, "production_data6"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9891_genregs.h b/sound/soc/codecs/tfa98xx-downstream/tfa9891_genregs.h
new file mode 100644
index 00000000000..7e5de58d334
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9891_genregs.h
@@ -0,0 +1,1136 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa98xx_genregs.h
+ * This file was generated automatically on 07/01/15 at 10:25:08.
+ * Source file: TFA9891_I2C_list_V11.xls
+ */
+
+#ifndef TFA9891_GENREGS_H
+#define TFA9891_GENREGS_H
+
+
+#define TFA98XX_STATUSREG 0x00
+#define TFA98XX_BATTERYVOLTAGE 0x01
+#define TFA9891_TEMPERATURE 0x02
+#define TFA98XX_REVISIONNUMBER 0x03
+#define TFA98XX_I2SREG 0x04
+#define TFA98XX_BAT_PROT 0x05
+#define TFA98XX_AUDIO_CTR 0x06
+#define TFA98XX_DCDCBOOST 0x07
+#define TFA98XX_SPKR_CALIBRATION 0x08
+#define TFA98XX_SYS_CTRL 0x09
+#define TFA98XX_I2S_SEL_REG 0x0a
+#define TFA98XX_HIDDEN_MTP_KEY2 0x0b
+#define TFA98XX_INTERRUPT_REG 0x0f
+#define TFA98XX_PDM_CTRL 0x10
+#define TFA98XX_PDM_OUT_CTRL 0x11
+#define TFA98XX_PDM_DS4_R 0x12
+#define TFA98XX_PDM_DS4_L 0x13
+#define TFA98XX_CTRL_SAAM_PGA 0x22
+#define TFA98XX_MISC_CTRL 0x25
+#define TFA98XX_CURRENTSENSE1 0x46
+#define TFA98XX_CURRENTSENSE4 0x49
+#define TFA98XX_HIDDEN_MTP_CTRL_REG3 0x62
+#define TFA9891_CF_CONTROLS 0x70
+#define TFA9891_CF_MAD 0x71
+#define TFA9891_CF_MEM 0x72
+#define TFA9891_CF_STATUS 0x73
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP 0x80
+
+/*
+ * (0x00)-StatusReg
+ */
+
+/*
+ * POR
+ */
+#define TFA98XX_STATUSREG_VDDS (0x1<<0)
+#define TFA98XX_STATUSREG_VDDS_POS 0
+#define TFA98XX_STATUSREG_VDDS_LEN 1
+#define TFA98XX_STATUSREG_VDDS_MAX 1
+#define TFA98XX_STATUSREG_VDDS_MSK 0x1
+
+/*
+ * PLL_LOCK
+ */
+#define TFA98XX_STATUSREG_PLLS (0x1<<1)
+#define TFA98XX_STATUSREG_PLLS_POS 1
+#define TFA98XX_STATUSREG_PLLS_LEN 1
+#define TFA98XX_STATUSREG_PLLS_MAX 1
+#define TFA98XX_STATUSREG_PLLS_MSK 0x2
+
+/*
+ * flag_otpok
+ */
+#define TFA98XX_STATUSREG_OTDS (0x1<<2)
+#define TFA98XX_STATUSREG_OTDS_POS 2
+#define TFA98XX_STATUSREG_OTDS_LEN 1
+#define TFA98XX_STATUSREG_OTDS_MAX 1
+#define TFA98XX_STATUSREG_OTDS_MSK 0x4
+
+/*
+ * flag_ovpok
+ */
+#define TFA98XX_STATUSREG_OVDS (0x1<<3)
+#define TFA98XX_STATUSREG_OVDS_POS 3
+#define TFA98XX_STATUSREG_OVDS_LEN 1
+#define TFA98XX_STATUSREG_OVDS_MAX 1
+#define TFA98XX_STATUSREG_OVDS_MSK 0x8
+
+/*
+ * flag_uvpok
+ */
+#define TFA98XX_STATUSREG_UVDS (0x1<<4)
+#define TFA98XX_STATUSREG_UVDS_POS 4
+#define TFA98XX_STATUSREG_UVDS_LEN 1
+#define TFA98XX_STATUSREG_UVDS_MAX 1
+#define TFA98XX_STATUSREG_UVDS_MSK 0x10
+
+/*
+ * flag_OCP_alarm
+ */
+#define TFA98XX_STATUSREG_OCDS (0x1<<5)
+#define TFA98XX_STATUSREG_OCDS_POS 5
+#define TFA98XX_STATUSREG_OCDS_LEN 1
+#define TFA98XX_STATUSREG_OCDS_MAX 1
+#define TFA98XX_STATUSREG_OCDS_MSK 0x20
+
+/*
+ * flag_clocks_stable
+ */
+#define TFA98XX_STATUSREG_CLKS (0x1<<6)
+#define TFA98XX_STATUSREG_CLKS_POS 6
+#define TFA98XX_STATUSREG_CLKS_LEN 1
+#define TFA98XX_STATUSREG_CLKS_MAX 1
+#define TFA98XX_STATUSREG_CLKS_MSK 0x40
+
+/*
+ * CLIP
+ */
+#define TFA98XX_STATUSREG_CLIPS (0x1<<7)
+#define TFA98XX_STATUSREG_CLIPS_POS 7
+#define TFA98XX_STATUSREG_CLIPS_LEN 1
+#define TFA98XX_STATUSREG_CLIPS_MAX 1
+#define TFA98XX_STATUSREG_CLIPS_MSK 0x80
+
+/*
+ * mtp_busy
+ */
+#define TFA98XX_STATUSREG_MTPB (0x1<<8)
+#define TFA98XX_STATUSREG_MTPB_POS 8
+#define TFA98XX_STATUSREG_MTPB_LEN 1
+#define TFA98XX_STATUSREG_MTPB_MAX 1
+#define TFA98XX_STATUSREG_MTPB_MSK 0x100
+
+/*
+ * flag_pwrokbst
+ */
+#define TFA98XX_STATUSREG_DCCS (0x1<<9)
+#define TFA98XX_STATUSREG_DCCS_POS 9
+#define TFA98XX_STATUSREG_DCCS_LEN 1
+#define TFA98XX_STATUSREG_DCCS_MAX 1
+#define TFA98XX_STATUSREG_DCCS_MSK 0x200
+
+/*
+ * flag_cf_speakererror
+ */
+#define TFA98XX_STATUSREG_SPKS (0x1<<10)
+#define TFA98XX_STATUSREG_SPKS_POS 10
+#define TFA98XX_STATUSREG_SPKS_LEN 1
+#define TFA98XX_STATUSREG_SPKS_MAX 1
+#define TFA98XX_STATUSREG_SPKS_MSK 0x400
+
+/*
+ * flag_cold_started
+ */
+#define TFA98XX_STATUSREG_ACS (0x1<<11)
+#define TFA98XX_STATUSREG_ACS_POS 11
+#define TFA98XX_STATUSREG_ACS_LEN 1
+#define TFA98XX_STATUSREG_ACS_MAX 1
+#define TFA98XX_STATUSREG_ACS_MSK 0x800
+
+/*
+ * flag_engage
+ */
+#define TFA98XX_STATUSREG_SWS (0x1<<12)
+#define TFA98XX_STATUSREG_SWS_POS 12
+#define TFA98XX_STATUSREG_SWS_LEN 1
+#define TFA98XX_STATUSREG_SWS_MAX 1
+#define TFA98XX_STATUSREG_SWS_MSK 0x1000
+
+/*
+ * flag_watchdog_reset
+ */
+#define TFA98XX_STATUSREG_WDS (0x1<<13)
+#define TFA98XX_STATUSREG_WDS_POS 13
+#define TFA98XX_STATUSREG_WDS_LEN 1
+#define TFA98XX_STATUSREG_WDS_MAX 1
+#define TFA98XX_STATUSREG_WDS_MSK 0x2000
+
+/*
+ * flag_enbl_amp
+ */
+#define TFA98XX_STATUSREG_AMPS (0x1<<14)
+#define TFA98XX_STATUSREG_AMPS_POS 14
+#define TFA98XX_STATUSREG_AMPS_LEN 1
+#define TFA98XX_STATUSREG_AMPS_MAX 1
+#define TFA98XX_STATUSREG_AMPS_MSK 0x4000
+
+/*
+ * flag_enbl_ref
+ */
+#define TFA98XX_STATUSREG_AREFS (0x1<<15)
+#define TFA98XX_STATUSREG_AREFS_POS 15
+#define TFA98XX_STATUSREG_AREFS_LEN 1
+#define TFA98XX_STATUSREG_AREFS_MAX 1
+#define TFA98XX_STATUSREG_AREFS_MSK 0x8000
+
+/*
+ * (0x01)-BatteryVoltage
+ */
+
+/*
+ * bat_adc
+ */
+#define TFA98XX_BATTERYVOLTAGE_BATS (0x3ff<<0)
+#define TFA98XX_BATTERYVOLTAGE_BATS_POS 0
+#define TFA98XX_BATTERYVOLTAGE_BATS_LEN 10
+#define TFA98XX_BATTERYVOLTAGE_BATS_MAX 1023
+#define TFA98XX_BATTERYVOLTAGE_BATS_MSK 0x3ff
+
+
+/*
+ * (0x02)-Temperature
+ */
+
+/*
+ * temp_adc
+ */
+#define TFA9891_TEMPERATURE_TEMPS (0x1ff<<0)
+#define TFA9891_TEMPERATURE_TEMPS_POS 0
+#define TFA9891_TEMPERATURE_TEMPS_LEN 9
+#define TFA9891_TEMPERATURE_TEMPS_MAX 511
+#define TFA9891_TEMPERATURE_TEMPS_MSK 0x1ff
+
+
+/*
+ * (0x03)-RevisionNumber
+ */
+
+/*
+ * rev_reg
+ */
+#define TFA98XX_REVISIONNUMBER_REV (0xff<<0)
+#define TFA98XX_REVISIONNUMBER_REV_POS 0
+#define TFA98XX_REVISIONNUMBER_REV_LEN 8
+#define TFA98XX_REVISIONNUMBER_REV_MAX 255
+#define TFA98XX_REVISIONNUMBER_REV_MSK 0xff
+
+
+/*
+ * (0x04)-I2SReg
+ */
+
+/*
+ * i2s_seti
+ */
+#define TFA98XX_I2SREG_I2SF (0x7<<0)
+#define TFA98XX_I2SREG_I2SF_POS 0
+#define TFA98XX_I2SREG_I2SF_LEN 3
+#define TFA98XX_I2SREG_I2SF_MAX 7
+#define TFA98XX_I2SREG_I2SF_MSK 0x7
+
+/*
+ * chan_sel1
+ */
+#define TFA98XX_I2SREG_CHS12 (0x3<<3)
+#define TFA98XX_I2SREG_CHS12_POS 3
+#define TFA98XX_I2SREG_CHS12_LEN 2
+#define TFA98XX_I2SREG_CHS12_MAX 3
+#define TFA98XX_I2SREG_CHS12_MSK 0x18
+
+/*
+ * lr_sw_i2si2
+ */
+#define TFA98XX_I2SREG_CHS3 (0x1<<5)
+#define TFA98XX_I2SREG_CHS3_POS 5
+#define TFA98XX_I2SREG_CHS3_LEN 1
+#define TFA98XX_I2SREG_CHS3_MAX 1
+#define TFA98XX_I2SREG_CHS3_MSK 0x20
+
+/*
+ * input_sel
+ */
+#define TFA98XX_I2SREG_CHSA (0x3<<6)
+#define TFA98XX_I2SREG_CHSA_POS 6
+#define TFA98XX_I2SREG_CHSA_LEN 2
+#define TFA98XX_I2SREG_CHSA_MAX 3
+#define TFA98XX_I2SREG_CHSA_MSK 0xc0
+
+/*
+ * datao_sel
+ */
+#define TFA98XX_I2SREG_I2SDOC (0x3<<8)
+#define TFA98XX_I2SREG_I2SDOC_POS 8
+#define TFA98XX_I2SREG_I2SDOC_LEN 2
+#define TFA98XX_I2SREG_I2SDOC_MAX 3
+#define TFA98XX_I2SREG_I2SDOC_MSK 0x300
+
+/*
+ * disable_idp
+ */
+#define TFA98XX_I2SREG_DISP (0x1<<10)
+#define TFA98XX_I2SREG_DISP_POS 10
+#define TFA98XX_I2SREG_DISP_LEN 1
+#define TFA98XX_I2SREG_DISP_MAX 1
+#define TFA98XX_I2SREG_DISP_MSK 0x400
+
+/*
+ * enbl_datao
+ */
+#define TFA98XX_I2SREG_I2SDOE (0x1<<11)
+#define TFA98XX_I2SREG_I2SDOE_POS 11
+#define TFA98XX_I2SREG_I2SDOE_LEN 1
+#define TFA98XX_I2SREG_I2SDOE_MAX 1
+#define TFA98XX_I2SREG_I2SDOE_MSK 0x800
+
+/*
+ * i2s_fs
+ */
+#define TFA98XX_I2SREG_I2SSR (0xf<<12)
+#define TFA98XX_I2SREG_I2SSR_POS 12
+#define TFA98XX_I2SREG_I2SSR_LEN 4
+#define TFA98XX_I2SREG_I2SSR_MAX 15
+#define TFA98XX_I2SREG_I2SSR_MSK 0xf000
+
+
+/*
+ * (0x05)-bat_prot
+ */
+
+/*
+ * vbat_prot_attacktime
+ */
+#define TFA98XX_BAT_PROT_BSSCR (0x3<<0)
+#define TFA98XX_BAT_PROT_BSSCR_POS 0
+#define TFA98XX_BAT_PROT_BSSCR_LEN 2
+#define TFA98XX_BAT_PROT_BSSCR_MAX 3
+#define TFA98XX_BAT_PROT_BSSCR_MSK 0x3
+
+/*
+ * vbat_prot_thlevel
+ */
+#define TFA98XX_BAT_PROT_BSST (0xf<<2)
+#define TFA98XX_BAT_PROT_BSST_POS 2
+#define TFA98XX_BAT_PROT_BSST_LEN 4
+#define TFA98XX_BAT_PROT_BSST_MAX 15
+#define TFA98XX_BAT_PROT_BSST_MSK 0x3c
+
+/*
+ * vbat_prot_max_reduct
+ */
+#define TFA98XX_BAT_PROT_BSSRL (0x3<<6)
+#define TFA98XX_BAT_PROT_BSSRL_POS 6
+#define TFA98XX_BAT_PROT_BSSRL_LEN 2
+#define TFA98XX_BAT_PROT_BSSRL_MAX 3
+#define TFA98XX_BAT_PROT_BSSRL_MSK 0xc0
+
+/*
+ * vbat_prot_release_t
+ */
+#define TFA98XX_BAT_PROT_BSSRR (0x7<<8)
+#define TFA98XX_BAT_PROT_BSSRR_POS 8
+#define TFA98XX_BAT_PROT_BSSRR_LEN 3
+#define TFA98XX_BAT_PROT_BSSRR_MAX 7
+#define TFA98XX_BAT_PROT_BSSRR_MSK 0x700
+
+/*
+ * vbat_prot_hysterese
+ */
+#define TFA98XX_BAT_PROT_BSSHY (0x3<<11)
+#define TFA98XX_BAT_PROT_BSSHY_POS 11
+#define TFA98XX_BAT_PROT_BSSHY_LEN 2
+#define TFA98XX_BAT_PROT_BSSHY_MAX 3
+#define TFA98XX_BAT_PROT_BSSHY_MSK 0x1800
+
+/*
+ * sel_vbat
+ */
+#define TFA98XX_BAT_PROT_BSSR (0x1<<14)
+#define TFA98XX_BAT_PROT_BSSR_POS 14
+#define TFA98XX_BAT_PROT_BSSR_LEN 1
+#define TFA98XX_BAT_PROT_BSSR_MAX 1
+#define TFA98XX_BAT_PROT_BSSR_MSK 0x4000
+
+/*
+ * bypass_clipper
+ */
+#define TFA98XX_BAT_PROT_BSSBY (0x1<<15)
+#define TFA98XX_BAT_PROT_BSSBY_POS 15
+#define TFA98XX_BAT_PROT_BSSBY_LEN 1
+#define TFA98XX_BAT_PROT_BSSBY_MAX 1
+#define TFA98XX_BAT_PROT_BSSBY_MSK 0x8000
+
+
+/*
+ * (0x06)-audio_ctr
+ */
+
+/*
+ * dpsa
+ */
+#define TFA98XX_AUDIO_CTR_DPSA (0x1<<0)
+#define TFA98XX_AUDIO_CTR_DPSA_POS 0
+#define TFA98XX_AUDIO_CTR_DPSA_LEN 1
+#define TFA98XX_AUDIO_CTR_DPSA_MAX 1
+#define TFA98XX_AUDIO_CTR_DPSA_MSK 0x1
+
+/*
+ * ctrl_slope
+ */
+#define TFA98XX_AUDIO_CTR_AMPSL (0xf<<1)
+#define TFA98XX_AUDIO_CTR_AMPSL_POS 1
+#define TFA98XX_AUDIO_CTR_AMPSL_LEN 4
+#define TFA98XX_AUDIO_CTR_AMPSL_MAX 15
+#define TFA98XX_AUDIO_CTR_AMPSL_MSK 0x1e
+
+/*
+ * cf_mute
+ */
+#define TFA98XX_AUDIO_CTR_CFSM (0x1<<5)
+#define TFA98XX_AUDIO_CTR_CFSM_POS 5
+#define TFA98XX_AUDIO_CTR_CFSM_LEN 1
+#define TFA98XX_AUDIO_CTR_CFSM_MAX 1
+#define TFA98XX_AUDIO_CTR_CFSM_MSK 0x20
+
+/*
+ * ctrl_batsensesteepness
+ */
+#define TFA98XX_AUDIO_CTR_BSSS (0x1<<7)
+#define TFA98XX_AUDIO_CTR_BSSS_POS 7
+#define TFA98XX_AUDIO_CTR_BSSS_LEN 1
+#define TFA98XX_AUDIO_CTR_BSSS_MAX 1
+#define TFA98XX_AUDIO_CTR_BSSS_MSK 0x80
+
+/*
+ * vol
+ */
+#define TFA98XX_AUDIO_CTR_VOL (0xff<<8)
+#define TFA98XX_AUDIO_CTR_VOL_POS 8
+#define TFA98XX_AUDIO_CTR_VOL_LEN 8
+#define TFA98XX_AUDIO_CTR_VOL_MAX 255
+#define TFA98XX_AUDIO_CTR_VOL_MSK 0xff00
+
+
+/*
+ * (0x07)-DCDCboost
+ */
+
+/*
+ * ctrl_bstvolt
+ */
+#define TFA98XX_DCDCBOOST_DCVO (0x7<<0)
+#define TFA98XX_DCDCBOOST_DCVO_POS 0
+#define TFA98XX_DCDCBOOST_DCVO_LEN 3
+#define TFA98XX_DCDCBOOST_DCVO_MAX 7
+#define TFA98XX_DCDCBOOST_DCVO_MSK 0x7
+
+/*
+ * ctrl_bstcur
+ */
+#define TFA98XX_DCDCBOOST_DCMCC (0x7<<3)
+#define TFA98XX_DCDCBOOST_DCMCC_POS 3
+#define TFA98XX_DCDCBOOST_DCMCC_LEN 3
+#define TFA98XX_DCDCBOOST_DCMCC_MAX 7
+#define TFA98XX_DCDCBOOST_DCMCC_MSK 0x38
+
+/*
+ * boost_intel
+ */
+#define TFA98XX_DCDCBOOST_DCIE (0x1<<10)
+#define TFA98XX_DCDCBOOST_DCIE_POS 10
+#define TFA98XX_DCDCBOOST_DCIE_LEN 1
+#define TFA98XX_DCDCBOOST_DCIE_MAX 1
+#define TFA98XX_DCDCBOOST_DCIE_MSK 0x400
+
+/*
+ * boost_speed
+ */
+#define TFA98XX_DCDCBOOST_DCSR (0x1<<11)
+#define TFA98XX_DCDCBOOST_DCSR_POS 11
+#define TFA98XX_DCDCBOOST_DCSR_LEN 1
+#define TFA98XX_DCDCBOOST_DCSR_MAX 1
+#define TFA98XX_DCDCBOOST_DCSR_MSK 0x800
+
+
+/*
+ * (0x08)-spkr_calibration
+ */
+
+/*
+ * ext_temp_sel
+ */
+#define TFA98XX_SPKR_CALIBRATION_TROS (0x1<<0)
+#define TFA98XX_SPKR_CALIBRATION_TROS_POS 0
+#define TFA98XX_SPKR_CALIBRATION_TROS_LEN 1
+#define TFA98XX_SPKR_CALIBRATION_TROS_MAX 1
+#define TFA98XX_SPKR_CALIBRATION_TROS_MSK 0x1
+
+/*
+ * ext_temp
+ */
+#define TFA98XX_SPKR_CALIBRATION_EXTTS (0x1ff<<1)
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_POS 1
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_LEN 9
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_MAX 511
+#define TFA98XX_SPKR_CALIBRATION_EXTTS_MSK 0x3fe
+
+
+/*
+ * (0x09)-sys_ctrl
+ */
+
+/*
+ * PowerDown
+ */
+#define TFA98XX_SYS_CTRL_PWDN (0x1<<0)
+#define TFA98XX_SYS_CTRL_PWDN_POS 0
+#define TFA98XX_SYS_CTRL_PWDN_LEN 1
+#define TFA98XX_SYS_CTRL_PWDN_MAX 1
+#define TFA98XX_SYS_CTRL_PWDN_MSK 0x1
+
+/*
+ * reset
+ */
+#define TFA98XX_SYS_CTRL_I2CR (0x1<<1)
+#define TFA98XX_SYS_CTRL_I2CR_POS 1
+#define TFA98XX_SYS_CTRL_I2CR_LEN 1
+#define TFA98XX_SYS_CTRL_I2CR_MAX 1
+#define TFA98XX_SYS_CTRL_I2CR_MSK 0x2
+
+/*
+ * enbl_coolflux
+ */
+#define TFA98XX_SYS_CTRL_CFE (0x1<<2)
+#define TFA98XX_SYS_CTRL_CFE_POS 2
+#define TFA98XX_SYS_CTRL_CFE_LEN 1
+#define TFA98XX_SYS_CTRL_CFE_MAX 1
+#define TFA98XX_SYS_CTRL_CFE_MSK 0x4
+
+/*
+ * enbl_amplifier
+ */
+#define TFA98XX_SYS_CTRL_AMPE (0x1<<3)
+#define TFA98XX_SYS_CTRL_AMPE_POS 3
+#define TFA98XX_SYS_CTRL_AMPE_LEN 1
+#define TFA98XX_SYS_CTRL_AMPE_MAX 1
+#define TFA98XX_SYS_CTRL_AMPE_MSK 0x8
+
+/*
+ * enbl_boost
+ */
+#define TFA98XX_SYS_CTRL_DCA (0x1<<4)
+#define TFA98XX_SYS_CTRL_DCA_POS 4
+#define TFA98XX_SYS_CTRL_DCA_LEN 1
+#define TFA98XX_SYS_CTRL_DCA_MAX 1
+#define TFA98XX_SYS_CTRL_DCA_MSK 0x10
+
+/*
+ * cf_configured
+ */
+#define TFA98XX_SYS_CTRL_SBSL (0x1<<5)
+#define TFA98XX_SYS_CTRL_SBSL_POS 5
+#define TFA98XX_SYS_CTRL_SBSL_LEN 1
+#define TFA98XX_SYS_CTRL_SBSL_MAX 1
+#define TFA98XX_SYS_CTRL_SBSL_MSK 0x20
+
+/*
+ * sel_enbl_amplifier
+ */
+#define TFA98XX_SYS_CTRL_AMPC (0x1<<6)
+#define TFA98XX_SYS_CTRL_AMPC_POS 6
+#define TFA98XX_SYS_CTRL_AMPC_LEN 1
+#define TFA98XX_SYS_CTRL_AMPC_MAX 1
+#define TFA98XX_SYS_CTRL_AMPC_MSK 0x40
+
+/*
+ * dcdcoff_mode
+ */
+#define TFA98XX_SYS_CTRL_DCDIS (0x1<<7)
+#define TFA98XX_SYS_CTRL_DCDIS_POS 7
+#define TFA98XX_SYS_CTRL_DCDIS_LEN 1
+#define TFA98XX_SYS_CTRL_DCDIS_MAX 1
+#define TFA98XX_SYS_CTRL_DCDIS_MSK 0x80
+
+/*
+ * cttr_iddqtest
+ */
+#define TFA98XX_SYS_CTRL_PSDR (0x1<<8)
+#define TFA98XX_SYS_CTRL_PSDR_POS 8
+#define TFA98XX_SYS_CTRL_PSDR_LEN 1
+#define TFA98XX_SYS_CTRL_PSDR_MAX 1
+#define TFA98XX_SYS_CTRL_PSDR_MSK 0x100
+
+/*
+ * ctrl_coil_value
+ */
+#define TFA98XX_SYS_CTRL_DCCV (0x3<<9)
+#define TFA98XX_SYS_CTRL_DCCV_POS 9
+#define TFA98XX_SYS_CTRL_DCCV_LEN 2
+#define TFA98XX_SYS_CTRL_DCCV_MAX 3
+#define TFA98XX_SYS_CTRL_DCCV_MSK 0x600
+
+/*
+ * ctrl_sel_cf_clock
+ */
+#define TFA98XX_SYS_CTRL_CCFD (0x3<<11)
+#define TFA98XX_SYS_CTRL_CCFD_POS 11
+#define TFA98XX_SYS_CTRL_CCFD_LEN 2
+#define TFA98XX_SYS_CTRL_CCFD_MAX 3
+#define TFA98XX_SYS_CTRL_CCFD_MSK 0x1800
+
+/*
+ * intf_sel
+ */
+#define TFA98XX_SYS_CTRL_ISEL (0x1<<13)
+#define TFA98XX_SYS_CTRL_ISEL_POS 13
+#define TFA98XX_SYS_CTRL_ISEL_LEN 1
+#define TFA98XX_SYS_CTRL_ISEL_MAX 1
+#define TFA98XX_SYS_CTRL_ISEL_MSK 0x2000
+
+/*
+ * sel_ws_bck
+ */
+#define TFA98XX_SYS_CTRL_IPLL (0x1<<14)
+#define TFA98XX_SYS_CTRL_IPLL_POS 14
+#define TFA98XX_SYS_CTRL_IPLL_LEN 1
+#define TFA98XX_SYS_CTRL_IPLL_MAX 1
+#define TFA98XX_SYS_CTRL_IPLL_MSK 0x4000
+
+
+/*
+ * (0x0a)-I2S_sel_reg
+ */
+
+/*
+ * sel_i2so_l
+ */
+#define TFA98XX_I2S_SEL_REG_DOLS (0x7<<0)
+#define TFA98XX_I2S_SEL_REG_DOLS_POS 0
+#define TFA98XX_I2S_SEL_REG_DOLS_LEN 3
+#define TFA98XX_I2S_SEL_REG_DOLS_MAX 7
+#define TFA98XX_I2S_SEL_REG_DOLS_MSK 0x7
+
+/*
+ * sel_i2so_r
+ */
+#define TFA98XX_I2S_SEL_REG_DORS (0x7<<3)
+#define TFA98XX_I2S_SEL_REG_DORS_POS 3
+#define TFA98XX_I2S_SEL_REG_DORS_LEN 3
+#define TFA98XX_I2S_SEL_REG_DORS_MAX 7
+#define TFA98XX_I2S_SEL_REG_DORS_MSK 0x38
+
+/*
+ * ctrl_spkr_coil
+ */
+#define TFA98XX_I2S_SEL_REG_SPKL (0x7<<6)
+#define TFA98XX_I2S_SEL_REG_SPKL_POS 6
+#define TFA98XX_I2S_SEL_REG_SPKL_LEN 3
+#define TFA98XX_I2S_SEL_REG_SPKL_MAX 7
+#define TFA98XX_I2S_SEL_REG_SPKL_MSK 0x1c0
+
+/*
+ * ctrl_spr_res
+ */
+#define TFA98XX_I2S_SEL_REG_SPKR (0x3<<9)
+#define TFA98XX_I2S_SEL_REG_SPKR_POS 9
+#define TFA98XX_I2S_SEL_REG_SPKR_LEN 2
+#define TFA98XX_I2S_SEL_REG_SPKR_MAX 3
+#define TFA98XX_I2S_SEL_REG_SPKR_MSK 0x600
+
+/*
+ * ctrl_dcdc_spkr_i_comp_gain
+ */
+#define TFA98XX_I2S_SEL_REG_DCFG (0xf<<11)
+#define TFA98XX_I2S_SEL_REG_DCFG_POS 11
+#define TFA98XX_I2S_SEL_REG_DCFG_LEN 4
+#define TFA98XX_I2S_SEL_REG_DCFG_MAX 15
+#define TFA98XX_I2S_SEL_REG_DCFG_MSK 0x7800
+
+
+/*
+ * (0x0b)-Hidden_mtp_key2
+ */
+
+/*
+ * MTP_key2
+ */
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK (0xff<<0)
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_POS 0
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_LEN 8
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_MAX 255
+#define TFA98XX_HIDDEN_MTP_KEY2_MTPK_MSK 0xff
+
+
+/*
+ * (0x0f)-interrupt_reg
+ */
+
+/*
+ * flag_por_mask
+ */
+#define TFA98XX_INTERRUPT_REG_VDDD (0x1<<0)
+#define TFA98XX_INTERRUPT_REG_VDDD_POS 0
+#define TFA98XX_INTERRUPT_REG_VDDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_VDDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_VDDD_MSK 0x1
+
+/*
+ * flag_otpok_mask
+ */
+#define TFA98XX_INTERRUPT_REG_OTDD (0x1<<1)
+#define TFA98XX_INTERRUPT_REG_OTDD_POS 1
+#define TFA98XX_INTERRUPT_REG_OTDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_OTDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_OTDD_MSK 0x2
+
+/*
+ * flag_ovpok_mask
+ */
+#define TFA98XX_INTERRUPT_REG_OVDD (0x1<<2)
+#define TFA98XX_INTERRUPT_REG_OVDD_POS 2
+#define TFA98XX_INTERRUPT_REG_OVDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_OVDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_OVDD_MSK 0x4
+
+/*
+ * flag_uvpok_mask
+ */
+#define TFA98XX_INTERRUPT_REG_UVDD (0x1<<3)
+#define TFA98XX_INTERRUPT_REG_UVDD_POS 3
+#define TFA98XX_INTERRUPT_REG_UVDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_UVDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_UVDD_MSK 0x8
+
+/*
+ * flag_ocp_alarm_mask
+ */
+#define TFA98XX_INTERRUPT_REG_OCDD (0x1<<4)
+#define TFA98XX_INTERRUPT_REG_OCDD_POS 4
+#define TFA98XX_INTERRUPT_REG_OCDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_OCDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_OCDD_MSK 0x10
+
+/*
+ * flag_clocks_stable_mask
+ */
+#define TFA98XX_INTERRUPT_REG_CLKD (0x1<<5)
+#define TFA98XX_INTERRUPT_REG_CLKD_POS 5
+#define TFA98XX_INTERRUPT_REG_CLKD_LEN 1
+#define TFA98XX_INTERRUPT_REG_CLKD_MAX 1
+#define TFA98XX_INTERRUPT_REG_CLKD_MSK 0x20
+
+/*
+ * flag_pwrokbst_mask
+ */
+#define TFA98XX_INTERRUPT_REG_DCCD (0x1<<6)
+#define TFA98XX_INTERRUPT_REG_DCCD_POS 6
+#define TFA98XX_INTERRUPT_REG_DCCD_LEN 1
+#define TFA98XX_INTERRUPT_REG_DCCD_MAX 1
+#define TFA98XX_INTERRUPT_REG_DCCD_MSK 0x40
+
+/*
+ * flag_cf_speakererror_mask
+ */
+#define TFA98XX_INTERRUPT_REG_SPKD (0x1<<7)
+#define TFA98XX_INTERRUPT_REG_SPKD_POS 7
+#define TFA98XX_INTERRUPT_REG_SPKD_LEN 1
+#define TFA98XX_INTERRUPT_REG_SPKD_MAX 1
+#define TFA98XX_INTERRUPT_REG_SPKD_MSK 0x80
+
+/*
+ * flag_watchdog_reset_mask
+ */
+#define TFA98XX_INTERRUPT_REG_WDD (0x1<<8)
+#define TFA98XX_INTERRUPT_REG_WDD_POS 8
+#define TFA98XX_INTERRUPT_REG_WDD_LEN 1
+#define TFA98XX_INTERRUPT_REG_WDD_MAX 1
+#define TFA98XX_INTERRUPT_REG_WDD_MSK 0x100
+
+/*
+ * enable_interrupt
+ */
+#define TFA98XX_INTERRUPT_REG_INT (0x1<<14)
+#define TFA98XX_INTERRUPT_REG_INT_POS 14
+#define TFA98XX_INTERRUPT_REG_INT_LEN 1
+#define TFA98XX_INTERRUPT_REG_INT_MAX 1
+#define TFA98XX_INTERRUPT_REG_INT_MSK 0x4000
+
+/*
+ * invert_int_polarity
+ */
+#define TFA98XX_INTERRUPT_REG_INTP (0x1<<15)
+#define TFA98XX_INTERRUPT_REG_INTP_POS 15
+#define TFA98XX_INTERRUPT_REG_INTP_LEN 1
+#define TFA98XX_INTERRUPT_REG_INTP_MAX 1
+#define TFA98XX_INTERRUPT_REG_INTP_MSK 0x8000
+
+
+/*
+ * (0x10)-pdm_ctrl
+ */
+
+/*
+ * pdm_i2s_input
+ */
+#define TFA98XX_PDM_CTRL_PDMSEL (0x1<<0)
+#define TFA98XX_PDM_CTRL_PDMSEL_POS 0
+#define TFA98XX_PDM_CTRL_PDMSEL_LEN 1
+#define TFA98XX_PDM_CTRL_PDMSEL_MAX 1
+#define TFA98XX_PDM_CTRL_PDMSEL_MSK 0x1
+
+/*
+ * I2S_master_ena
+ */
+#define TFA98XX_PDM_CTRL_I2SMOUTEN (0x1<<1)
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_POS 1
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_LEN 1
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_MAX 1
+#define TFA98XX_PDM_CTRL_I2SMOUTEN_MSK 0x2
+
+/*
+ * pdm_out_sel_r
+ */
+#define TFA98XX_PDM_CTRL_PDMORSEL (0x3<<2)
+#define TFA98XX_PDM_CTRL_PDMORSEL_POS 2
+#define TFA98XX_PDM_CTRL_PDMORSEL_LEN 2
+#define TFA98XX_PDM_CTRL_PDMORSEL_MAX 3
+#define TFA98XX_PDM_CTRL_PDMORSEL_MSK 0xc
+
+/*
+ * pdm_out_sel_l
+ */
+#define TFA98XX_PDM_CTRL_PDMOLSEL (0x3<<4)
+#define TFA98XX_PDM_CTRL_PDMOLSEL_POS 4
+#define TFA98XX_PDM_CTRL_PDMOLSEL_LEN 2
+#define TFA98XX_PDM_CTRL_PDMOLSEL_MAX 3
+#define TFA98XX_PDM_CTRL_PDMOLSEL_MSK 0x30
+
+/*
+ * micdat_out_sel
+ */
+#define TFA98XX_PDM_CTRL_PADSEL (0x3<<6)
+#define TFA98XX_PDM_CTRL_PADSEL_POS 6
+#define TFA98XX_PDM_CTRL_PADSEL_LEN 2
+#define TFA98XX_PDM_CTRL_PADSEL_MAX 3
+#define TFA98XX_PDM_CTRL_PADSEL_MSK 0xc0
+
+
+/*
+ * (0x11)-pdm_out_ctrl
+ */
+
+/*
+ * secure_dly
+ */
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN (0x1<<0)
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_POS 0
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDEN_MSK 0x1
+
+/*
+ * d_out_valid_rf_mux
+ */
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF (0x1<<1)
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_POS 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOSDCF_MSK 0x2
+
+/*
+ * Speak_As_Mic_en
+ */
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN (0x1<<4)
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_POS 4
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMEN_MSK 0x10
+
+/*
+ * speak_as_mic_lp_mode
+ */
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN (0x1<<5)
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_POS 5
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_SAAMLPEN_MSK 0x20
+
+/*
+ * pdm_out_rate
+ */
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN (0x1<<6)
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_POS 6
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_LEN 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_MAX 1
+#define TFA98XX_PDM_OUT_CTRL_PDMOINTEN_MSK 0x40
+
+
+/*
+ * (0x12)-pdm_ds4_r
+ */
+
+/*
+ * ds4_g1_r
+ */
+#define TFA98XX_PDM_DS4_R_PDMORG1 (0xf<<0)
+#define TFA98XX_PDM_DS4_R_PDMORG1_POS 0
+#define TFA98XX_PDM_DS4_R_PDMORG1_LEN 4
+#define TFA98XX_PDM_DS4_R_PDMORG1_MAX 15
+#define TFA98XX_PDM_DS4_R_PDMORG1_MSK 0xf
+
+/*
+ * ds4_g2_r
+ */
+#define TFA98XX_PDM_DS4_R_PDMORG2 (0xf<<4)
+#define TFA98XX_PDM_DS4_R_PDMORG2_POS 4
+#define TFA98XX_PDM_DS4_R_PDMORG2_LEN 4
+#define TFA98XX_PDM_DS4_R_PDMORG2_MAX 15
+#define TFA98XX_PDM_DS4_R_PDMORG2_MSK 0xf0
+
+
+/*
+ * (0x13)-pdm_ds4_l
+ */
+
+/*
+ * ds4_g1_l
+ */
+#define TFA98XX_PDM_DS4_L_PDMOLG1 (0xf<<0)
+#define TFA98XX_PDM_DS4_L_PDMOLG1_POS 0
+#define TFA98XX_PDM_DS4_L_PDMOLG1_LEN 4
+#define TFA98XX_PDM_DS4_L_PDMOLG1_MAX 15
+#define TFA98XX_PDM_DS4_L_PDMOLG1_MSK 0xf
+
+/*
+ * ds4_g2_l
+ */
+#define TFA98XX_PDM_DS4_L_PDMOLG2 (0xf<<4)
+#define TFA98XX_PDM_DS4_L_PDMOLG2_POS 4
+#define TFA98XX_PDM_DS4_L_PDMOLG2_LEN 4
+#define TFA98XX_PDM_DS4_L_PDMOLG2_MAX 15
+#define TFA98XX_PDM_DS4_L_PDMOLG2_MSK 0xf0
+
+
+/*
+ * (0x22)-ctrl_saam_pga
+ */
+
+/*
+ * Ctrl_saam_pga_gain
+ */
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN (0x7<<0)
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_POS 0
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_LEN 3
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_MAX 7
+#define TFA98XX_CTRL_SAAM_PGA_SAAMGAIN_MSK 0x7
+
+/*
+ * ctrl_saam_pga_src
+ */
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL (0x1<<5)
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_POS 5
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_LEN 1
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_MAX 1
+#define TFA98XX_CTRL_SAAM_PGA_SAAMPGACTRL_MSK 0x20
+
+
+/*
+ * (0x25)-misc_ctrl
+ */
+
+/*
+ * pll_fcco
+ */
+#define TFA98XX_MISC_CTRL_PLLCCOSEL (0x1<<0)
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_POS 0
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_LEN 1
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_MAX 1
+#define TFA98XX_MISC_CTRL_PLLCCOSEL_MSK 0x1
+
+
+/*
+ * (0x46)-CurrentSense1
+ */
+
+/*
+ * bypass_gc
+ */
+#define TFA98XX_CURRENTSENSE1_CSBYPGC (0x1<<0)
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_POS 0
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_LEN 1
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_MAX 1
+#define TFA98XX_CURRENTSENSE1_CSBYPGC_MSK 0x1
+
+
+/*
+ * (0x49)-CurrentSense4
+ */
+
+/*
+ * ctrl_bypassclip
+ */
+#define TFA98XX_CURRENTSENSE4_CLIP (0x1<<0)
+#define TFA98XX_CURRENTSENSE4_CLIP_POS 0
+#define TFA98XX_CURRENTSENSE4_CLIP_LEN 1
+#define TFA98XX_CURRENTSENSE4_CLIP_MAX 1
+#define TFA98XX_CURRENTSENSE4_CLIP_MSK 0x1
+
+/*
+ * ctrl_bypassclip2
+ */
+#define TFA98XX_CURRENTSENSE4_CLIP2 (0x1<<1)
+#define TFA98XX_CURRENTSENSE4_CLIP2_POS 1
+#define TFA98XX_CURRENTSENSE4_CLIP2_LEN 1
+#define TFA98XX_CURRENTSENSE4_CLIP2_MAX 1
+#define TFA98XX_CURRENTSENSE4_CLIP2_MSK 0x2
+
+
+/*
+ * (0x62)-Hidden_mtp_ctrl_reg3
+ */
+
+
+/*
+ * (0x70)-cf_controls
+ */
+
+/*
+ * cf_rst_dsp
+ */
+#define TFA98XX_CF_CONTROLS_RST (0x1<<0)
+#define TFA98XX_CF_CONTROLS_RST_POS 0
+#define TFA98XX_CF_CONTROLS_RST_LEN 1
+#define TFA98XX_CF_CONTROLS_RST_MAX 1
+#define TFA98XX_CF_CONTROLS_RST_MSK 0x1
+
+/*
+ * cf_dmem
+ */
+#define TFA98XX_CF_CONTROLS_DMEM (0x3<<1)
+#define TFA98XX_CF_CONTROLS_DMEM_POS 1
+#define TFA98XX_CF_CONTROLS_DMEM_LEN 2
+#define TFA98XX_CF_CONTROLS_DMEM_MAX 3
+#define TFA98XX_CF_CONTROLS_DMEM_MSK 0x6
+
+/*
+ * cf_aif
+ */
+#define TFA98XX_CF_CONTROLS_AIF (0x1<<3)
+#define TFA98XX_CF_CONTROLS_AIF_POS 3
+#define TFA98XX_CF_CONTROLS_AIF_LEN 1
+#define TFA98XX_CF_CONTROLS_AIF_MAX 1
+#define TFA98XX_CF_CONTROLS_AIF_MSK 0x8
+
+/*
+ * cf_int
+ */
+#define TFA98XX_CF_CONTROLS_CFINT (0x1<<4)
+#define TFA98XX_CF_CONTROLS_CFINT_POS 4
+#define TFA98XX_CF_CONTROLS_CFINT_LEN 1
+#define TFA98XX_CF_CONTROLS_CFINT_MAX 1
+#define TFA98XX_CF_CONTROLS_CFINT_MSK 0x10
+
+/*
+ * cf_req
+ */
+#define TFA98XX_CF_CONTROLS_REQ (0xff<<8)
+#define TFA98XX_CF_CONTROLS_REQ_POS 8
+#define TFA98XX_CF_CONTROLS_REQ_LEN 8
+#define TFA98XX_CF_CONTROLS_REQ_MAX 255
+#define TFA98XX_CF_CONTROLS_REQ_MSK 0xff00
+
+
+/*
+ * (0x71)-cf_mad
+ */
+
+/*
+ * cf_madd
+ */
+#define TFA9891_CF_MAD_MADD (0xffff<<0)
+#define TFA9891_CF_MAD_MADD_POS 0
+#define TFA9891_CF_MAD_MADD_LEN 16
+#define TFA9891_CF_MAD_MADD_MAX 65535
+#define TFA9891_CF_MAD_MADD_MSK 0xffff
+
+
+/*
+ * (0x72)-cf_mem
+ */
+
+/*
+ * cf_mema
+ */
+#define TFA9891_CF_MEM_MEMA (0xffff<<0)
+#define TFA9891_CF_MEM_MEMA_POS 0
+#define TFA9891_CF_MEM_MEMA_LEN 16
+#define TFA9891_CF_MEM_MEMA_MAX 65535
+#define TFA9891_CF_MEM_MEMA_MSK 0xffff
+
+
+/*
+ * (0x73)-cf_status
+ */
+
+/*
+ * cf_err
+ */
+#define TFA9891_CF_STATUS_ERR (0xff<<0)
+#define TFA9891_CF_STATUS_ERR_POS 0
+#define TFA9891_CF_STATUS_ERR_LEN 8
+#define TFA9891_CF_STATUS_ERR_MAX 255
+#define TFA9891_CF_STATUS_ERR_MSK 0xff
+
+/*
+ * cf_ack
+ */
+#define TFA9891_CF_STATUS_ACK (0xff<<8)
+#define TFA9891_CF_STATUS_ACK_POS 8
+#define TFA9891_CF_STATUS_ACK_LEN 8
+#define TFA9891_CF_STATUS_ACK_MAX 255
+#define TFA9891_CF_STATUS_ACK_MSK 0xff00
+
+
+/*
+ * (0x80)-Key2Protected_spkr_cal_mtp
+ */
+
+/*
+ * calibration_onetime
+ */
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC (0x1<<0)
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_POS 0
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_LEN 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_MAX 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPOTC_MSK 0x1
+
+/*
+ * calibr_ron_done
+ */
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX (0x1<<1)
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_POS 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_LEN 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_MAX 1
+#define TFA98XX_KEY2PROTECTED_SPKR_CAL_MTP_MTPEX_MSK 0x2
+
+#endif /* TFA9891_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9891_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9891_tfafieldnames.h
new file mode 100644
index 00000000000..99cb5ab6bec
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9891_tfafieldnames.h
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*
+ * tfa9891_tfafieldnames.h
+ *
+ * Created on: Jul 16, 2015
+ * Author: wim
+ */
+
+#ifndef TFA_INC_TFA9891_TFAFIELDNAMES_H_
+#define TFA_INC_TFA9891_TFAFIELDNAMES_H_
+
+/** Filename: Tfa9891_TfaFieldnames.h
+ * This file was generated automatically on 07/16/15 at 15:00:02.
+ * Source file: TFA9891_I2C_list_V13.xls
+ */
+
+#define TFA9891_I2CVERSION 13
+
+
+#define TFA9891_NAMETABLE static tfaBfName_t Tfa9891DatasheetNames[]= {\
+ { 0x0, "VDDS"}, /* POR , */\
+ { 0x10, "PLLS"}, /* PLL , */\
+ { 0x20, "OTDS"}, /* OTP , */\
+ { 0x30, "OVDS"}, /* OVP , */\
+ { 0x40, "UVDS"}, /* UVP , */\
+ { 0x50, "OCDS"}, /* OCP , */\
+ { 0x60, "CLKS"}, /* Clocks , */\
+ { 0x70, "CLIPS"}, /* CLIP , */\
+ { 0x80, "MTPB"}, /* MTP , */\
+ { 0x90, "DCCS"}, /* BOOST , */\
+ { 0xa0, "SPKS"}, /* Speaker , */\
+ { 0xb0, "ACS"}, /* cold start flag , */\
+ { 0xc0, "SWS"}, /* flag engage , */\
+ { 0xd0, "WDS"}, /* flag watchdog reset , */\
+ { 0xe0, "AMPS"}, /* amplifier is enabled by manager , */\
+ { 0xf0, "AREFS"}, /* references are enabled by manager , */\
+ { 0x109, "BATS"}, /* Battery voltage readout; 0[V]..5.5[V] , */\
+ { 0x208, "TEMPS"}, /* Temperature readout , */\
+ { 0x307, "REV"}, /* Device Revision , */\
+ { 0x402, "I2SF"}, /* I2SFormat data 1 input , */\
+ { 0x431, "CHS12"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "CHS3"}, /* Channel Selection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x481, "I2SDOC"}, /* Selection for I2S data out , */\
+ { 0x4a0, "DISP"}, /* idp protection , */\
+ { 0x4b0, "I2SDOE"}, /* Enable data output , */\
+ { 0x4c3, "I2SSR"}, /* sample rate setting , */\
+ { 0x501, "BSSCR"}, /* ProtectionAttackTime , */\
+ { 0x523, "BSST"}, /* ProtectionThreshold , */\
+ { 0x561, "BSSRL"}, /* ProtectionMaximumReduction , */\
+ { 0x582, "BSSRR"}, /* Protection Release Timer , */\
+ { 0x5b1, "BSSHY"}, /* ProtectionHysterese , */\
+ { 0x5e0, "BSSR"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "BSSBY"}, /* bypass clipper battery protection , */\
+ { 0x600, "DPSA"}, /* Enable dynamic powerstage activation , */\
+ { 0x613, "AMPSL"}, /* control slope , */\
+ { 0x650, "CFSM"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "BSSS"}, /* batsensesteepness , */\
+ { 0x687, "VOL"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "DCVO"}, /* Boost voltage , */\
+ { 0x732, "DCMCC"}, /* Max boost coil current , */\
+ { 0x7a0, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7b0, "DCSR"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x800, "TROS"}, /* select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "EXTTS"}, /* external temperature setting to be given by host , */\
+ { 0x900, "PWDN"}, /* ON/OFF , */\
+ { 0x910, "I2CR"}, /* I2CReset , */\
+ { 0x920, "CFE"}, /* EnableCoolFlux , */\
+ { 0x930, "AMPE"}, /* EnableAmplifier , */\
+ { 0x940, "DCA"}, /* EnableBoost , */\
+ { 0x950, "SBSL"}, /* Coolflux configured , */\
+ { 0x960, "AMPC"}, /* Selection on how AmplifierEnabling , */\
+ { 0x970, "DCDIS"}, /* DCDC not connected , */\
+ { 0x980, "PSDR"}, /* Iddq test amplifier , */\
+ { 0x991, "DCCV"}, /* Coil Value , */\
+ { 0x9b1, "CCFD"}, /* Selection CoolFluxClock , */\
+ { 0x9d0, "ISEL"}, /* Interface Selection , */\
+ { 0x9e0, "IPLL"}, /* selection input PLL for lock , */\
+ { 0xa02, "DOLS"}, /* Output selection dataout left channel , */\
+ { 0xa32, "DORS"}, /* Output selection dataout right channel , */\
+ { 0xa62, "SPKL"}, /* Selection speaker induction , */\
+ { 0xa91, "SPKR"}, /* Selection speaker impedance , */\
+ { 0xab3, "DCFG"}, /* DCDC speaker current compensation gain , */\
+ { 0xb07, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xf00, "VDDD"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "OTDD"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "OVDD"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "UVDD"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "OCDD"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "CLKD"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "DCCD"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "SPKD"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "WDD"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xfe0, "INT"}, /* enabling interrupt , */\
+ { 0xff0, "INTP"}, /* Setting polarity interupt , */\
+ { 0x1000, "PDMSEL"}, /* Audio input interface mode , */\
+ { 0x1010, "I2SMOUTEN"}, /* I2S Master enable (CLK and WS pads) , */\
+ { 0x1021, "PDMORSEL"}, /* PDM Output right channel source selection , */\
+ { 0x1041, "PDMOLSEL"}, /* PDM Output Left/Mono channel source selection , */\
+ { 0x1061, "PADSEL"}, /* Output interface mode and ball selection , */\
+ { 0x1100, "PDMOSDEN"}, /* Secure delay Cell , */\
+ { 0x1110, "PDMOSDCF"}, /* Rising Falling Resync control Mux , */\
+ { 0x1140, "SAAMEN"}, /* Speaker As a Mic feature ON/OFF , */\
+ { 0x1150, "SAAMLPEN"}, /* speaker_as_mic low power mode (only in PDM_out mode), */\
+ { 0x1160, "PDMOINTEN"}, /* PDM output interpolation ratio , */\
+ { 0x1203, "PDMORG1"}, /* PDM Interpolator Right Channel DS4 G1 Gain Value , */\
+ { 0x1243, "PDMORG2"}, /* PDM Interpolator Right Channel DS4 G2 Gain Value , */\
+ { 0x1303, "PDMOLG1"}, /* PDM Interpolator Left Channel DS4 G1 Gain Value , */\
+ { 0x1343, "PDMOLG2"}, /* PDM Interpolator Left Channel DS4 G2 Gain Value , */\
+ { 0x2202, "SAAMGAIN"}, /* pga gain , */\
+ { 0x2250, "SAAMPGACTRL"}, /* 0 = active input common mode voltage source at the attenuator/PGA level, */\
+ { 0x2500, "PLLCCOSEL"}, /* pll cco frequency , */\
+ { 0x4600, "CSBYPGC"}, /* bypass_gc, bypasses the CS gain correction , */\
+ { 0x4900, "CLIP"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x4910, "CLIP2"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x62b0, "CIMTP"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x7000, "RST"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "DMEM"}, /* Target memory for access , */\
+ { 0x7030, "AIF"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "CFINT"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "REQ"}, /* request for access (8 channels) , */\
+ { 0x710f, "MADD"}, /* memory-address to be accessed , */\
+ { 0x720f, "MEMA"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "ERR"}, /* cf error Flags , */\
+ { 0x7387, "ACK"}, /* acknowledge of requests (8 channels")" , */\
+ { 0x8000, "MTPOTC"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "MTPEX"}, /* (key2 protected) calibration of Ron has been executed, */\
+ { 0x8045, "SWPROFIL" },\
+ { 0x80a5, "SWVSTEP" },\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9891_BITNAMETABLE static tfaBfName_t Tfa9891BitNames[]= {\
+ { 0x0, "POR"}, /* POR , */\
+ { 0x10, "PLL_LOCK"}, /* PLL , */\
+ { 0x20, "flag_otpok"}, /* OTP , */\
+ { 0x30, "flag_ovpok"}, /* OVP , */\
+ { 0x40, "flag_uvpok"}, /* UVP , */\
+ { 0x50, "flag_OCP_alarm"}, /* OCP , */\
+ { 0x60, "flag_clocks_stable"}, /* Clocks , */\
+ { 0x70, "CLIP"}, /* CLIP , */\
+ { 0x80, "mtp_busy"}, /* MTP , */\
+ { 0x90, "flag_pwrokbst"}, /* BOOST , */\
+ { 0xa0, "flag_cf_speakererror"}, /* Speaker , */\
+ { 0xb0, "flag_cold_started"}, /* cold start flag , */\
+ { 0xc0, "flag_engage"}, /* flag engage , */\
+ { 0xd0, "flag_watchdog_reset"}, /* flag watchdog reset , */\
+ { 0xe0, "flag_enbl_amp"}, /* amplifier is enabled by manager , */\
+ { 0xf0, "flag_enbl_ref"}, /* references are enabled by manager , */\
+ { 0x109, "bat_adc"}, /* Battery voltage readout; 0[V]..5.5[V] , */\
+ { 0x208, "temp_adc"}, /* Temperature readout , */\
+ { 0x307, "rev_reg"}, /* Device Revision , */\
+ { 0x402, "i2s_seti"}, /* I2SFormat data 1 input , */\
+ { 0x431, "chan_sel1"}, /* ChannelSelection data1 input (In CoolFlux) , */\
+ { 0x450, "lr_sw_i2si2"}, /* Channel Selection data 2 input (coolflux input, the DCDC converter gets the other signal), */\
+ { 0x461, "input_sel"}, /* Input selection for amplifier , */\
+ { 0x481, "datao_sel"}, /* Selection for I2S data out , */\
+ { 0x4a0, "disable_idp"}, /* idp protection , */\
+ { 0x4b0, "enbl_datao"}, /* Enable data output , */\
+ { 0x4c3, "i2s_fs"}, /* sample rate setting , */\
+ { 0x501, "vbat_prot_attacktime"}, /* ProtectionAttackTime , */\
+ { 0x523, "vbat_prot_thlevel"}, /* ProtectionThreshold , */\
+ { 0x561, "vbat_prot_max_reduct"}, /* ProtectionMaximumReduction , */\
+ { 0x582, "vbat_prot_release_t"}, /* Protection Release Timer , */\
+ { 0x5b1, "vbat_prot_hysterese"}, /* ProtectionHysterese , */\
+ { 0x5d0, "reset_min_vbat"}, /* reset clipper , */\
+ { 0x5e0, "sel_vbat"}, /* battery voltage for I2C read out only , */\
+ { 0x5f0, "bypass_clipper"}, /* bypass clipper battery protection , */\
+ { 0x600, "dpsa"}, /* Enable dynamic powerstage activation , */\
+ { 0x613, "ctrl_slope"}, /* control slope , */\
+ { 0x650, "cf_mute"}, /* Soft mute in CoolFlux , */\
+ { 0x660, "sel_other_vamp"}, /* Input selection for the second channel of the DCDC inteligent mode detector, */\
+ { 0x670, "ctrl_batsensesteepness"}, /* batsensesteepness , */\
+ { 0x687, "vol"}, /* volume control (in CoolFlux) , */\
+ { 0x702, "ctrl_bstvolt"}, /* Boost voltage , */\
+ { 0x732, "ctrl_bstcur"}, /* Max boost coil current , */\
+ { 0x761, "ctrl_slopebst_1_0"}, /* Setting for the slope of the boost converter power stage, */\
+ { 0x781, "ctrl_slopebst_3_2"}, /* Setting for the part of the power transistor voltage to be used in peak current mode control, */\
+ { 0x7a0, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7b0, "boost_speed"}, /* Soft RampUp/Down mode for DCDC controller , */\
+ { 0x7c1, "ctrl_delay_comp_dcdc"}, /* delay compensation in current patg compared to delay in the audio path (relative) , */\
+ { 0x7e0, "boost_input"}, /* Selection intelligent boost detector input , */\
+ { 0x7f0, "ctrl_supplysense"}, /* ADC10 input selection , */\
+ { 0x800, "ext_temp_sel"}, /* select external temperature also the ext_temp will be put on the temp read out , */\
+ { 0x818, "ext_temp"}, /* external temperature setting to be given by host , */\
+ { 0x8a0, "ctrl_spk_coilpvp_bst"}, /* Peak voltage protection boost converter , */\
+ { 0x8b2, "ctrl_dcdc_synchronisation"}, /* DCDC synchronisation off + 7 positions , */\
+ { 0x8e0, "ctrl_cs_samplevalid"}, /* sample valid moment for CS in single sample moment mode, */\
+ { 0x900, "PowerDown"}, /* ON/OFF , */\
+ { 0x910, "reset"}, /* I2CReset , */\
+ { 0x920, "enbl_coolflux"}, /* EnableCoolFlux , */\
+ { 0x930, "enbl_amplifier"}, /* EnableAmplifier , */\
+ { 0x940, "enbl_boost"}, /* EnableBoost , */\
+ { 0x950, "cf_configured"}, /* Coolflux configured , */\
+ { 0x960, "sel_enbl_amplifier"}, /* Selection on how AmplifierEnabling , */\
+ { 0x970, "dcdcoff_mode"}, /* DCDC not connected , */\
+ { 0x980, "cttr_iddqtest"}, /* Iddq test amplifier , */\
+ { 0x991, "ctrl_coil_value"}, /* Coil Value , */\
+ { 0x9b1, "ctrl_sel_cf_clock"}, /* Selection CoolFluxClock , */\
+ { 0x9d0, "intf_sel"}, /* Interface Selection , */\
+ { 0x9e0, "sel_ws_bck"}, /* selection input PLL for lock , */\
+ { 0xa02, "sel_i2so_l"}, /* Output selection dataout left channel , */\
+ { 0xa32, "sel_i2so_r"}, /* Output selection dataout right channel , */\
+ { 0xa62, "ctrl_spkr_coil"}, /* Selection speaker induction , */\
+ { 0xa91, "ctrl_spr_res"}, /* Selection speaker impedance , */\
+ { 0xab3, "ctrl_dcdc_spkr_i_comp_gain"}, /* DCDC speaker current compensation gain , */\
+ { 0xaf0, "ctrl_dcdc_spkr_i_comp_sign"}, /* DCDC speaker current compensation sign , */\
+ { 0xb07, "MTP_key2"}, /* MTP KEY2 register , */\
+ { 0xc0c, "clk_sync_delay"}, /* Delay count for clock synchronisation , */\
+ { 0xcf0, "enbl_clk_sync"}, /* Enable CGU clock synchronisation , */\
+ { 0xd0c, "adc_sync_delay"}, /* Delay count for ADC synchronisation , */\
+ { 0xdf0, "enable_adc_sync"}, /* Enable ADC synchronisation , */\
+ { 0xe00, "bypass_dcdc_curr_prot"}, /* to switch off dcdc reduction with bat prot , */\
+ { 0xe24, "ctrl_digtoana6_2"}, /* for extra connections digital to analog , */\
+ { 0xe70, "switch_on_icomp"}, /* icomp dem switch , */\
+ { 0xe87, "reserve_reg_1_7_0"}, /* reserved , */\
+ { 0xf00, "flag_por_mask"}, /* mask flag_por for interupt generation , */\
+ { 0xf10, "flag_otpok_mask"}, /* mask flag_otpok for interupt generation , */\
+ { 0xf20, "flag_ovpok_mask"}, /* mask flag_ovpok for interupt generation , */\
+ { 0xf30, "flag_uvpok_mask"}, /* mask flag_uvpok for interupt generation , */\
+ { 0xf40, "flag_ocp_alarm_mask"}, /* mask flag_ocp_alarm for interupt generation , */\
+ { 0xf50, "flag_clocks_stable_mask"}, /* mask flag_clocks_stable for interupt generation , */\
+ { 0xf60, "flag_pwrokbst_mask"}, /* mask flag_pwrokbst for interupt generation , */\
+ { 0xf70, "flag_cf_speakererror_mask"}, /* mask flag_cf_speakererror for interupt generation , */\
+ { 0xf80, "flag_watchdog_reset_mask"}, /* mask flag_watchdog_reset for interupt generation , */\
+ { 0xf90, "flag_lost_clk_mask"}, /* mask flag_lost_clk for interupt generation , */\
+ { 0xfe0, "enable_interrupt"}, /* enabling interrupt , */\
+ { 0xff0, "invert_int_polarity"}, /* Setting polarity interupt , */\
+ { 0x1000, "pdm_i2s_input"}, /* Audio input interface mode , */\
+ { 0x1010, "I2S_master_ena"}, /* I2S Master enable (CLK and WS pads) , */\
+ { 0x1021, "pdm_out_sel_r"}, /* PDM Output right channel source selection , */\
+ { 0x1041, "pdm_out_sel_l"}, /* PDM Output Left/Mono channel source selection , */\
+ { 0x1061, "micdat_out_sel"}, /* Output interface mode and ball selection , */\
+ { 0x1100, "secure_dly"}, /* Secure delay Cell , */\
+ { 0x1110, "d_out_valid_rf_mux"}, /* Rising Falling Resync control Mux , */\
+ { 0x1140, "Speak_As_Mic_en"}, /* Speaker As a Mic feature ON/OFF , */\
+ { 0x1150, "speak_as_mic_lp_mode"}, /* speaker_as_mic low power mode (only in PDM_out mode), */\
+ { 0x1160, "pdm_out_rate"}, /* PDM output interpolation ratio , */\
+ { 0x1203, "ds4_g1_r"}, /* PDM Interpolator Right Channel DS4 G1 Gain Value , */\
+ { 0x1243, "ds4_g2_r"}, /* PDM Interpolator Right Channel DS4 G2 Gain Value , */\
+ { 0x1303, "ds4_g1_l"}, /* PDM Interpolator Left Channel DS4 G1 Gain Value , */\
+ { 0x1343, "ds4_g2_l"}, /* PDM Interpolator Left Channel DS4 G2 Gain Value , */\
+ { 0x1400, "clk_secure_dly"}, /* Secure delay Cell on clock path , */\
+ { 0x1410, "data_secure_dly"}, /* Secure delay Cell enable on PDM data path , */\
+ { 0x2202, "Ctrl_saam_pga_gain"}, /* pga gain , */\
+ { 0x2250, "ctrl_saam_pga_src"}, /* 0 = active input common mode voltage source at the attenuator/PGA level, */\
+ { 0x2300, "flag_saam_spare"}, /* spare flag , */\
+ { 0x2400, "ctrl_saam_pga_tm"}, /* enables PGA test mode , */\
+ { 0x2500, "pll_fcco"}, /* pll cco frequency , */\
+ { 0x3000, "flag_hi_small"}, /* positive small window dcdc converter , */\
+ { 0x3010, "flag_hi_large"}, /* positive large window dcdc converter , */\
+ { 0x3020, "flag_lo_small"}, /* negative small window dcdc converter , */\
+ { 0x3030, "flag_lo_large"}, /* negative large window dcdc converter , */\
+ { 0x3040, "flag_voutcomp"}, /* flag_voutcomp, indication Vset is larger than Vbat, */\
+ { 0x3050, "flag_voutcomp93"}, /* flag_voutcomp93, indication Vset is larger than 1.07* Vbat , */\
+ { 0x3060, "flag_voutcomp86"}, /* flag_voutcomp86, indication Vset is larger than 1.14* Vbat , */\
+ { 0x3070, "flag_hiz"}, /* flag_hiz, indication Vbst is larger than Vbat , */\
+ { 0x3080, "flag_hi_peak"}, /* flag_hi_peak, indication hi_peak , */\
+ { 0x3090, "flag_ocpokbst"}, /* flag_ocpokbst, indication no over current in boost converter pmos switch, */\
+ { 0x30a0, "flag_peakcur"}, /* flag_peakcur, indication current is max in dcdc converter, */\
+ { 0x30b0, "flag_ocpokap"}, /* flag_ocpokap, indication no over current in amplifier "a" pmos output stage, */\
+ { 0x30c0, "flag_ocpokan"}, /* flag_ocpokan, indication no over current in amplifier "a" nmos output stage, */\
+ { 0x30d0, "flag_ocpokbp"}, /* flag_ocpokbp, indication no over current in amplifier "b" pmos output stage, */\
+ { 0x30e0, "flag_ocpokbn"}, /* flag_ocpokbn, indication no over current in amplifier"b" nmos output stage, */\
+ { 0x30f0, "lost_clk"}, /* lost_clk, lost clock indication CGU , */\
+ { 0x310f, "mtp_man_data_out"}, /* single word read from MTP (manual copy) , */\
+ { 0x3200, "key01_locked"}, /* key01_locked, indication key 1 is locked , */\
+ { 0x3210, "key02_locked"}, /* key02_locked, indication key 2 is locked , */\
+ { 0x3225, "mtp_ecc_tcout"}, /* mtp_ecc_tcout , */\
+ { 0x3280, "mtpctrl_valid_test_rd"}, /* mtp test readout for read , */\
+ { 0x3290, "mtpctrl_valid_test_wr"}, /* mtp test readout for write , */\
+ { 0x32a0, "flag_in_alarm_state"}, /* alarm state , */\
+ { 0x32b0, "mtp_ecc_err2"}, /* two or more bit errors detected in MTP, can not reconstruct value, */\
+ { 0x32c0, "mtp_ecc_err1"}, /* one bit error detected in MTP, reconstructed value, */\
+ { 0x32d0, "mtp_mtp_hvf"}, /* high voltage ready flag for MTP , */\
+ { 0x32f0, "mtp_zero_check_fail"}, /* zero check failed (tbd) for MTP , */\
+ { 0x3300, "flag_adc10_ready"}, /* flag_adc10_ready, indication adc10 is ready , */\
+ { 0x3310, "flag_clipa_high"}, /* flag_clipa_high, indication pmos amplifier "a" is clipping, */\
+ { 0x3320, "flag_clipa_low"}, /* flag_clipa_low, indication nmos amplifier "a" is clipping, */\
+ { 0x3330, "flag_clipb_high"}, /* flag_clipb_high, indication pmos amplifier "b" is clipping, */\
+ { 0x3340, "flag_clipb_low"}, /* flag_clipb_low, indication nmos amplifier "b" is clipping, */\
+ { 0x3359, "data_adc10_tempbat"}, /* adc 10 data output for testing , */\
+ { 0x33f0, "flag_vddd_comp_nok"}, /* power switch flag 2 for testing , */\
+ { 0x400f, "hid_code"}, /* hidden code , */\
+ { 0x4100, "bypass_hp"}, /* Bypass_High Pass Filter , */\
+ { 0x4110, "hard_mute"}, /* Hard Mute , */\
+ { 0x4120, "soft_mute"}, /* Soft Mute , */\
+ { 0x4134, "PWM_Delay"}, /* PWM DelayBits to set the delay , */\
+ { 0x4180, "PWM_Shape"}, /* PWM Shape , */\
+ { 0x4190, "PWM_BitLength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4207, "ctrl_drive"}, /* drive bits to select amount of power stages amplifier, */\
+ { 0x4281, "dpsalevel"}, /* DPSA Threshold level , */\
+ { 0x42a1, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x42c0, "ctrl_coincidence"}, /* Prevent simultaneously switching of output stage , */\
+ { 0x42d0, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x42e0, "ctrl_test_sdeltaoffset"}, /* ctrl_test_sdeltaoffset , */\
+ { 0x42f0, "ctrl_test_sdeltaclk"}, /* ctrl_test_sdeltaclk , */\
+ { 0x4309, "ctrl_drivebst"}, /* Drive bits to select the powertransistor sections boost converter, */\
+ { 0x43a0, "ctrl_ocptestbst"}, /* Boost OCP. , */\
+ { 0x43c0, "enbl_hi_peak"}, /* enable for high peak comparator , */\
+ { 0x43d0, "test_abistfft_enbl"}, /* FFT coolflux , */\
+ { 0x43e0, "ctrl_sensetest_amp"}, /* sensetest amplifier , */\
+ { 0x43f0, "test_bcontrol"}, /* test _bcontrol , */\
+ { 0x4400, "ctrl_reversebst"}, /* OverCurrent Protection selection of power stage boost converter, */\
+ { 0x4410, "ctrl_sensetest"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0x4420, "enbl_engagebst"}, /* Enable power stage dcdc controller , */\
+ { 0x4430, "enbl_hi_small"}, /* Enable bit of hi (small) comparator , */\
+ { 0x4440, "enbl_hi_large"}, /* Enable bit of hi (large) comparator , */\
+ { 0x4450, "enbl_lo_small"}, /* Enable bit of lo (small) comparator , */\
+ { 0x4460, "enbl_lo_large"}, /* Enable bit of lo (large) comparator , */\
+ { 0x4470, "enbl_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x4480, "enbl_voutcomp"}, /* Enable vout comparators , */\
+ { 0x4490, "enbl_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x44a0, "enbl_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x44b0, "enbl_hizcom"}, /* Enable hiz comparator , */\
+ { 0x44c0, "enbl_pcdac"}, /* Enable peak current dac , */\
+ { 0x44d0, "enbl_pccomp"}, /* Enable peak current comparator , */\
+ { 0x44e0, "enbl_windac"}, /* Enable window dac , */\
+ { 0x44f0, "enbl_powerbst"}, /* Enable line of the powerstage , */\
+ { 0x4507, "ocp_thr"}, /* ocp_thr threshold level for OCP , */\
+ { 0x4580, "bypass_glitchfilter"}, /* Bypass glitchfilter , */\
+ { 0x4590, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0x45a0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0x45b0, "bypass_otp"}, /* Bypass OTP , */\
+ { 0x45c0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0x45d0, "bypass_ocpcounter"}, /* BypassOCPCounter , */\
+ { 0x45e0, "bypass_lost_clk"}, /* Bypasslost_clk detector , */\
+ { 0x45f0, "vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0x4600, "bypass_gc"}, /* bypass_gc, bypasses the CS gain correction , */\
+ { 0x4610, "cs_gain_control"}, /* gain control by means of MTP or i2c , */\
+ { 0x4627, "cs_gain"}, /* + / - 128 steps in steps of 1/4 % 2's compliment , */\
+ { 0x46a0, "bypass_lp"}, /* bypass Low-Pass filter in temperature sensor , */\
+ { 0x46b0, "bypass_pwmcounter"}, /* bypass_pwmcounter , */\
+ { 0x46c0, "ctrl_cs_negfixed"}, /* does not switch to neg , */\
+ { 0x46d2, "ctrl_cs_neghyst"}, /* switches to neg depending on level , */\
+ { 0x4700, "switch_fb"}, /* switch_fb , */\
+ { 0x4713, "se_hyst"}, /* se_hyst , */\
+ { 0x4754, "se_level"}, /* se_level , */\
+ { 0x47a5, "ktemp"}, /* temperature compensation trimming , */\
+ { 0x4800, "ctrl_negin"}, /* negin , */\
+ { 0x4810, "ctrl_cs_sein"}, /* cs_sein , */\
+ { 0x4820, "ctrl_coincidencecs"}, /* Coincidence current sense , */\
+ { 0x4830, "ctrl_iddqtestbst"}, /* for iddq testing in powerstage of boost convertor , */\
+ { 0x4840, "ctrl_coincidencebst"}, /* Switch protection on to prevent simultaniously switching power stages bst and amp, */\
+ { 0x4851, "clock_sh_sel"}, /* Clock SH selection , */\
+ { 0x4876, "delay_se_neg"}, /* delay of se and neg , */\
+ { 0x48e1, "ctrl_cs_ttrack"}, /* sample & hold track time , */\
+ { 0x4900, "ctrl_bypassclip"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x4910, "ctrl_bypassclip2"}, /* Bypass clip control (function depending on digimux clip_x), */\
+ { 0x4920, "ctrl_clkgateCFoff"}, /* to disable clock gating in the coolflux , */\
+ { 0x4930, "ctrl_testabst"}, /* testabst , */\
+ { 0x4940, "ctrl_clipfast"}, /* clock switch for battery protection clipper, it switches back to old frequency, */\
+ { 0x4950, "ctrl_cs_8ohm"}, /* 8 ohm mode for current sense (gain mode) , */\
+ { 0x4960, "reserved"}, /* reserved , */\
+ { 0x4974, "delay_clock_sh"}, /* delay_sh, tunes S7H delay , */\
+ { 0x49c0, "inv_clksh"}, /* Invert the sample/hold clock for current sense ADC, */\
+ { 0x49d0, "inv_neg"}, /* Invert neg signal , */\
+ { 0x49e0, "inv_se"}, /* Invert se signal , */\
+ { 0x49f0, "setse"}, /* switches between Single Ende and differentail mode, */\
+ { 0x4a12, "ctrl_adc10_sel"}, /* select the input to convert the 10b ADC , */\
+ { 0x4a60, "ctrl_adc10_reset"}, /* Global asynchronous reset (active HIGH) 10 bit ADC, */\
+ { 0x4a81, "ctrl_adc10_test"}, /* Test mode selection signal 10 bit ADC , */\
+ { 0x4aa0, "ctrl_bypass_lp_vbat"}, /* lp filter in batt sensor , */\
+ { 0x4ae0, "ctrl_dc_offset"}, /* switch offset control on/off, is decimator offset control, */\
+ { 0x4af0, "ctrl_tsense_hibias"}, /* bit to set the biasing in temp sensor to high , */\
+ { 0x4b00, "ctrl_adc13_iset"}, /* Micadc Setting of current consumption. Debug use only, */\
+ { 0x4b14, "ctrl_adc13_gain"}, /* Micadc gain setting (2-compl) , */\
+ { 0x4b61, "ctrl_adc13_slowdel"}, /* Micadc Delay setting for internal clock. Debug use only, */\
+ { 0x4b83, "ctrl_adc13_offset"}, /* Micadc ADC offset setting , */\
+ { 0x4bc0, "ctrl_adc13_bsoinv"}, /* Micadc bit stream output invert mode for test , */\
+ { 0x4bd0, "ctrl_adc13_resonator_enable"}, /* Micadc Give extra SNR with less stability. Debug use only, */\
+ { 0x4be0, "ctrl_testmicadc"}, /* Mux at input of MICADC for test purpose , */\
+ { 0x4c0f, "ctrl_offset"}, /* offset control for ABIST testing , */\
+ { 0x4d05, "ctrl_windac"}, /* for testing direct control windac , */\
+ { 0x4d65, "ctrl_peakcur"}, /* Control peakcur , */\
+ { 0x4dc3, "pwm_dcc_cnt"}, /* control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0x4e04, "ctrl_slopecur"}, /* for testing direct control slopecur , */\
+ { 0x4e53, "ctrl_dem"}, /* dyn element matching control, rest of codes are optional, */\
+ { 0x4e93, "ctrl_demmismatch"}, /* dyn element matching add offset , */\
+ { 0x4ed0, "enbl_pwm_dcc"}, /* to enable direct control of pwm duty cycle , */\
+ { 0x5007, "gain"}, /* gain setting of the gain multiplier gain need to increase with factor 1.41 (3dB), */\
+ { 0x5081, "ctrl_sourceb"}, /* Set OUTB to , */\
+ { 0x50a1, "ctrl_sourcea"}, /* Set OUTA to , */\
+ { 0x50c1, "ctrl_sourcebst"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0x50e1, "ctrl_test_mono"}, /* ABIST mode to add both amplifier halfs as stereo or one amplifier half as mono, */\
+ { 0x5104, "pulselengthbst"}, /* pulselength setting test input for boost converter , */\
+ { 0x5150, "ctrl_bypasslatchbst"}, /* bypass_latch in boost converter , */\
+ { 0x5160, "invertbst"}, /* invert pwmbst test signal , */\
+ { 0x5174, "pulselength"}, /* pulselength setting test input for amplifier , */\
+ { 0x51c0, "ctrl_bypasslatch"}, /* bypass_latch in boost convert , */\
+ { 0x51d0, "invertb"}, /* invert pwmb test signal , */\
+ { 0x51e0, "inverta"}, /* invert pwma test signal , */\
+ { 0x51f0, "ctrl_bypass_ctrlloop"}, /* bypass_ctrlloop bypasses the control loop of the amplifier, */\
+ { 0x5200, "ctrl_test_discrete"}, /* tbd for rdson testing , */\
+ { 0x5210, "ctrl_test_rdsona"}, /* tbd for rdson testing , */\
+ { 0x5220, "ctrl_test_rdsonb"}, /* tbd for rdson testing , */\
+ { 0x5230, "ctrl_test_rdsonbst"}, /* tbd for rdson testing , */\
+ { 0x5240, "ctrl_test_cvia"}, /* tbd for rdson testing , */\
+ { 0x5250, "ctrl_test_cvib"}, /* tbd for rdson testing , */\
+ { 0x5260, "ctrl_test_cvibst"}, /* tbd for rdson testing , */\
+ { 0x5290, "test_bypass_pwmdiscretea"}, /* for testing ( ABIST) , */\
+ { 0x52a0, "test_bypass_pwmdiscreteb"}, /* for testing ( ABIST) , */\
+ { 0x52b0, "ctrl_clipc_forcehigh"}, /* test signal for clipcontrol , */\
+ { 0x52c0, "ctrl_clipc_forcelow"}, /* test signal for clipcontrol , */\
+ { 0x52d0, "ctrl_test_sdelta"}, /* for testing ( ABIST) , */\
+ { 0x52e0, "ctrl_test_swhvp"}, /* for testing ( ABIST) , */\
+ { 0x52f0, "test_gain_reduction"}, /* test gain reduction , */\
+ { 0x5303, "ctrl_digimux_out_test1"}, /* Digimux TEST1 out , */\
+ { 0x5343, "ctrl_digimux_out_test2"}, /* Digimux TEST2 out. output flag_clipa_low depending on cntr_bypassclip setting, */\
+ { 0x5383, "ctrl_digimux_out_data1"}, /* Digimux DATA1 out (output flag_clipb_high depending on cntr_bypassclip setting), */\
+ { 0x53c3, "ctrl_digimux_out_data3"}, /* Digimux DATA3 out (output flag_clipx_x depending on cntr_bypassclip setting), */\
+ { 0x5400, "hs_mode"}, /* hs_mode, high speed mode I2C bus , */\
+ { 0x5412, "test_parametric_io"}, /* test_parametric_io for testing pads , */\
+ { 0x5440, "enbl_ringo"}, /* enbl_ringo, for test purpose to check with ringo , */\
+ { 0x5480, "ctrl_cliplevel"}, /* Clip level , */\
+ { 0x5491, "ctrl_anamux_sel"}, /* anamux selection , */\
+ { 0x54b0, "test_vdddsw_dio"}, /* to overrule the power switches for memory , */\
+ { 0x54c0, "ctrl_bypass_diosw_ovp"}, /* To disable the overvoltage protection of vddd_dio_sw, */\
+ { 0x54d0, "test_vddd_sw"}, /* test vdd sw , */\
+ { 0x54e0, "test_vddd_sw_comp"}, /* test vdd sw comp , */\
+ { 0x550e, "enbl_amp"}, /* enbl_amp for testing to enable all analoge blocks in amplifier, */\
+ { 0x55f0, "fr_fsp"}, /* extr free running clock mode for testing , */\
+ { 0x5600, "use_direct_ctrls"}, /* use_direct_ctrls, to overrule several functions direct for testing, */\
+ { 0x5610, "rst_datapath"}, /* rst_datapath, datapath reset , */\
+ { 0x5620, "rst_cgu"}, /* rst_cgu, cgu reset , */\
+ { 0x5637, "enbl_ref"}, /* for testing to enable all analoge blocks in references, */\
+ { 0x56b0, "enbl_engage"}, /* Enable output stage amplifier , */\
+ { 0x56c0, "use_direct_clk_ctrl"}, /* use_direct_clk_ctrl, to overrule several functions direct for testing, */\
+ { 0x56d0, "use_direct_pll_ctrl"}, /* use_direct_pll_ctrl, to overrule several functions direct for test, */\
+ { 0x56e0, "use_direct_ctrls_2"}, /* use_direct_sourseamp_ctrls, to overrule several functions direct for testing, */\
+ { 0x5707, "ctrl_anamux_out_test1"}, /* Anamux control , */\
+ { 0x5782, "ctrl_zero"}, /* Bandwith control feedbackloop , */\
+ { 0x57b0, "enbl_ldo_stress"}, /* LDO stress function frinch capacitors , */\
+ { 0x57c0, "ctrl_ocptest"}, /* ctrl_ocptest, deactivates the over current protection in the power stages of the amplifier. The ocp flag signals stay active., */\
+ { 0x57e0, "ctrl_otptest"}, /* otptest, test mode otp amplifier , */\
+ { 0x57f0, "ctrl_reverse"}, /* CTRL revers , */\
+ { 0x5802, "pll_mdec_msb"}, /* most significant bits pll_mdec , */\
+ { 0x5833, "pll_selr"}, /* pll_selr , */\
+ { 0x5874, "pll_selp"}, /* pll_selp , */\
+ { 0x58c3, "pll_seli"}, /* pll_seli , */\
+ { 0x5900, "pll_psel"}, /* pll_psel , */\
+ { 0x5910, "use_direct_pll_psel"}, /* use_direct_pll_psel , */\
+ { 0x5923, "nbck"}, /* NBCK , */\
+ { 0x5960, "auto_nbck"}, /* AUTO_NBCK , */\
+ { 0x5970, "pll_frm"}, /* pll_frm , */\
+ { 0x5980, "pll_directi"}, /* pll_directi , */\
+ { 0x5990, "pll_directo"}, /* pll_directo , */\
+ { 0x59a0, "enbl_PLL"}, /* enbl_PLL , */\
+ { 0x59b0, "sel_clkout"}, /* SEL_CLKOUT , */\
+ { 0x59e0, "fr_lost_clk"}, /* fr_lost_clk , */\
+ { 0x59f0, "pll_bypass"}, /* pll_bypass , */\
+ { 0x5a0f, "tsig_freq"}, /* tsig_freq, internal sinus test generator, frequency control, */\
+ { 0x5b02, "tsig_freq_msb"}, /* select internal sinus test generator, frequency control msb bits, */\
+ { 0x5b30, "inject_tsig"}, /* inject_tsig, control bit to switch to internal sinus test generator, */\
+ { 0x5b44, "ctrl_adc10_prog_sample"}, /* control ADC10 , */\
+ { 0x5c01, "pll_ndec_msb"}, /* most significant bits of pll_ndec , */\
+ { 0x5c2d, "pll_mdec"}, /* bits 13..0 of pll_mdec , */\
+ { 0x5d06, "pll_pdec"}, /* pll_pdec , */\
+ { 0x5d87, "pll_ndec"}, /* bits 7..0 of pll_ndec , */\
+ { 0x5e00, "pdm_ch_sel_reg"}, /* PDM channel selection , */\
+ { 0x5e10, "pdm_iis_rst_reg"}, /* PDM Interface reset , */\
+ { 0x5e20, "clk_src_sel_reg"}, /* WS Source Selection , */\
+ { 0x5e70, "pdm_resync_bypass"}, /* PDM resynchronization bypass , */\
+ { 0x6007, "MTP_key1"}, /* MTP Key1 , */\
+ { 0x6185, "mtp_ecc_tcin"}, /* Mtp_ecc_tcin , */\
+ { 0x6203, "mtp_man_address_in"}, /* address from i2cregs for writing one word single mtp, */\
+ { 0x6260, "mtp_ecc_eeb"}, /* enable code bit generation (active low!) , */\
+ { 0x6270, "mtp_ecc_ecb"}, /* enable correction signal (active low!) , */\
+ { 0x6280, "man_copy_mtp_to_iic"}, /* start copying single word from mtp to i2cregs_mtp , */\
+ { 0x6290, "man_copy_iic_to_mtp"}, /* start copying single word from i2cregs_mtp to mtp [Key 1 protected], */\
+ { 0x62a0, "auto_copy_mtp_to_iic"}, /* start copying all the data from mtp to i2cregs_mtp, */\
+ { 0x62b0, "auto_copy_iic_to_mtp"}, /* start copying all the data from i2cregs_mtp to mtp [Key 2 protected], */\
+ { 0x62d2, "mtp_speed_mode"}, /* Speed mode , */\
+ { 0x6340, "mtp_dircet_enable"}, /* mtp_direct_enable (key1 protected) , */\
+ { 0x6350, "mtp_direct_wr"}, /* mtp_direct_wr (key1 protected) direct value for mtp pin wr. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6360, "mtp_direct_rd"}, /* mtp_direct_rd (key1 protected) direct value for mtp pin rd. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6370, "mtp_direct_rst"}, /* mtp_direct_rst (key1 protected) direct value for mtp pin rst. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6380, "mtp_direct_ers"}, /* mtp_direct_ers (key1 protected) direct value for mtp pin ers. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x6390, "mtp_direct_prg"}, /* mtp_direct_prg (key1 protected) direct value for mtp pin prg. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x63a0, "mtp_direct_epp"}, /* mtp_direct_epp (key1 protected) direct value for mtp pin epp. To be enabled via iic2mtp_mtp_direct_enable, */\
+ { 0x63b4, "mtp_direct_test"}, /* mtp_direct_test (key1 protected) , */\
+ { 0x640f, "mtp_man_data_in"}, /* single wordt be written to MTP (manual copy) , */\
+ { 0x7000, "cf_rst_dsp"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "cf_dmem"}, /* Target memory for access , */\
+ { 0x7030, "cf_aif"}, /* Autoincrement-flag for memory-address , */\
+ { 0x7040, "cf_int"}, /* Interrupt CoolFlux DSP , */\
+ { 0x7087, "cf_req"}, /* request for access (8 channels) , */\
+ { 0x710f, "cf_madd"}, /* memory-address to be accessed , */\
+ { 0x720f, "cf_mema"}, /* activate memory access (24- or 32-bits data is written/read to/from memory, */\
+ { 0x7307, "cf_err"}, /* cf error Flags , */\
+ { 0x7387, "cf_ack"}, /* acknowledge of requests (8 channels")" , */\
+ { 0x8000, "calibration_onetime"}, /* Calibration schedule (key2 protected) , */\
+ { 0x8010, "calibr_ron_done"}, /* (key2 protected) calibration of Ron has been executed, */\
+ { 0x8105, "calibr_vout_offset"}, /* calibr_vout_offset (DCDCoffset) 2's compliment (key1 protected), */\
+ { 0x8163, "calibr_delta_gain"}, /* delta gain for vamp (alpha) 2's compliment (key1 protected), */\
+ { 0x81a5, "calibr_offs_amp"}, /* offset for vamp (Ampoffset) 2's compliment (key1 protected), */\
+ { 0x8207, "calibr_gain_cs"}, /* gain current sense (Imeasalpha) 2's compliment (key1 protected), */\
+ { 0x8284, "calibr_temp_offset"}, /* temperature offset 2's compliment (key1 protected), */\
+ { 0x82d2, "calibr_temp_gain"}, /* temperature gain 2's compliment (key1 protected) , */\
+ { 0x830f, "calibr_ron"}, /* Ron resistance of coil (key1 protected) , */\
+ { 0x8406, "ctrl_offset_a"}, /* Offset of amplifier level shifter , */\
+ { 0x8486, "ctrl_offset_b"}, /* Offset of amplifier level shifter , */\
+ { 0x850f, "type_bits_HW"}, /* HW Bits , */\
+ { 0x860f, "type_bits1_SW"}, /* MTP-control SW1 , */\
+ { 0x870f, "type_bits2_SW"}, /* MTP-control SW2 , */\
+ { 0x8a0f, "production_data1"}, /* (key1 protected) , */\
+ { 0x8b0f, "production_data2"}, /* (key1 protected) , */\
+ { 0x8c0f, "production_data3"}, /* (key1 protected) , */\
+ { 0x8d0f, "production_data4"}, /* (key1 protected) , */\
+ { 0x8e0f, "production_data5"}, /* (key1 protected) , */\
+ { 0x8f0f, "production_data6"}, /* (key1 protected) , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+
+#endif /* TFA_INC_TFA9891_TFAFIELDNAMES_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames.h
new file mode 100644
index 00000000000..afdf6f5e7e0
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames.h
@@ -0,0 +1,1079 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9894_tfaFieldnames_N1Last.h
+ * This file was generated automatically on 09/28/18 at 11:24:56.
+ * Source file: TFA9894_N1A1_I2C_RegisterMap.xlsx
+ */
+
+#ifndef _TFA9894_TFAFIELDNAMES_H
+#define _TFA9894_TFAFIELDNAMES_H
+
+
+#define TFA9894_I2CVERSION 17.0
+
+typedef enum Tfa9894BfEnumList {
+ TFA9894_BF_PWDN = 0x0000, /*!< Powerdown control */
+ TFA9894_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9894_BF_CFE = 0x0020, /*!< Enable CoolFlux DSP */
+ TFA9894_BF_AMPE = 0x0030, /*!< Enable Amplifier */
+ TFA9894_BF_DCA = 0x0040, /*!< Enable DCDC Boost converter */
+ TFA9894_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA9894_BF_AMPC = 0x0060, /*!< CoolFlux control over amplifier */
+ TFA9894_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9894_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9894_BF_BYPOCP= 0x00a0, /*!< Bypass OCP */
+ TFA9894_BF_TSTOCP= 0x00b0, /*!< OCP testing control */
+ TFA9894_BF_BSSS = 0x00c0, /*!< Vbat protection steepness */
+ TFA9894_BF_HPFBYP= 0x00d0, /*!< Bypass High Pass Filter */
+ TFA9894_BF_DPSA = 0x00e0, /*!< Enable DPSA */
+ TFA9894_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9894_BF_MANSCONF= 0x0120, /*!< Device I2C settings configured */
+ TFA9894_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA9894_BF_MANROBOD= 0x0140, /*!< Reaction on BOD */
+ TFA9894_BF_BODE = 0x0150, /*!< Enable BOD (only in direct control mode) */
+ TFA9894_BF_BODHYS= 0x0160, /*!< Enable Hysteresis of BOD */
+ TFA9894_BF_BODFILT= 0x0171, /*!< BOD filter */
+ TFA9894_BF_BODTHLVL= 0x0191, /*!< BOD threshold */
+ TFA9894_BF_MUTETO= 0x01b0, /*!< Time out SB mute sequence */
+ TFA9894_BF_MANWDE= 0x01c0, /*!< Watchdog enable */
+ TFA9894_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9894_BF_FAIMVBGOVRRL= 0x01f0, /*!< Overrule the enabling of VBG for faim erase/write access */
+ TFA9894_BF_AUDFS = 0x0203, /*!< Audio sample rate Fs */
+ TFA9894_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9894_BF_FRACTDEL= 0x0255, /*!< Current sense fractional delay */
+ TFA9894_BF_TDMPRES= 0x02b1, /*!< Control for HW manager */
+ TFA9894_BF_AMPOCRT= 0x02d2, /*!< Amplifier on-off criteria for shutdown */
+ TFA9894_BF_REV = 0x030f, /*!< Revision info */
+ TFA9894_BF_REFCKEXT= 0x0401, /*!< PLL external reference clock */
+ TFA9894_BF_REFCKSEL= 0x0420, /*!< PLL internal reference clock */
+ TFA9894_BF_MCLKSEL= 0x0432, /*!< Master Clock Selection */
+ TFA9894_BF_MANAOOSC= 0x0460, /*!< Internal OSC1M off at PWDN */
+ TFA9894_BF_ACKCLDDIS= 0x0470, /*!< Automatic PLL reference clock selection for cold start */
+ TFA9894_BF_SPKSSEN= 0x0510, /*!< Enable speaker sub-system */
+ TFA9894_BF_MTPSSEN= 0x0520, /*!< Enable FAIM sub-system */
+ TFA9894_BF_WDTCLKEN= 0x0530, /*!< Enable Coolflux watchdog clock */
+ TFA9894_BF_VDDS = 0x1000, /*!< POR */
+ TFA9894_BF_PLLS = 0x1010, /*!< PLL Lock */
+ TFA9894_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9894_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9894_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9894_BF_OCDS = 0x1050, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9894_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9894_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9894_BF_NOCLK = 0x1080, /*!< Lost clock */
+ TFA9894_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA9894_BF_WDS = 0x10a0, /*!< Watchdog */
+ TFA9894_BF_SWS = 0x10b0, /*!< Amplifier engage */
+ TFA9894_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9894_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9894_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9894_BF_BODNOK= 0x10f0, /*!< BOD Flag - VDD NOT OK */
+ TFA9894_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9894_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9894_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9894_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9894_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9894_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9894_BF_SPKS = 0x1170, /*!< Speaker status */
+ TFA9894_BF_CLKOOR= 0x1180, /*!< External clock status */
+ TFA9894_BF_MANALARM= 0x1190, /*!< Alarm state */
+ TFA9894_BF_TDMERR= 0x11a0, /*!< TDM error */
+ TFA9894_BF_TDMLUTER= 0x11b0, /*!< TDM lookup table error */
+ TFA9894_BF_OCPOAP= 0x1200, /*!< OCPOK pmos A */
+ TFA9894_BF_OCPOAN= 0x1210, /*!< OCPOK nmos A */
+ TFA9894_BF_OCPOBP= 0x1220, /*!< OCPOK pmos B */
+ TFA9894_BF_OCPOBN= 0x1230, /*!< OCPOK nmos B */
+ TFA9894_BF_CLIPS = 0x1240, /*!< Amplifier clipping */
+ TFA9894_BF_MANMUTE= 0x1250, /*!< Audio mute sequence */
+ TFA9894_BF_MANOPER= 0x1260, /*!< Device in Operating state */
+ TFA9894_BF_LP1 = 0x1270, /*!< Low power MODE1 detection */
+ TFA9894_BF_LA = 0x1280, /*!< Low amplitude detection */
+ TFA9894_BF_VDDPH = 0x1290, /*!< VDDP greater than VBAT flag */
+ TFA9894_BF_TDMSTAT= 0x1402, /*!< TDM Status bits */
+ TFA9894_BF_MANSTATE= 0x1433, /*!< Device Manager status */
+ TFA9894_BF_DCMODE= 0x14b1, /*!< DCDC mode status bits */
+ TFA9894_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9894_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9894_BF_VDDPS = 0x1709, /*!< IC VDDP voltage (1023*VDDP/13V) */
+ TFA9894_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9894_BF_TDMSPKE= 0x2010, /*!< Control audio tdm channel in sink0 */
+ TFA9894_BF_TDMDCE= 0x2020, /*!< Control audio tdm channel in sink1 */
+ TFA9894_BF_TDMCSE= 0x2030, /*!< Source 0 enable */
+ TFA9894_BF_TDMVSE= 0x2040, /*!< Source 1 enable */
+ TFA9894_BF_TDMCFE= 0x2050, /*!< Source 2 enable */
+ TFA9894_BF_TDMCF2E= 0x2060, /*!< Source 3 enable */
+ TFA9894_BF_TDMCLINV= 0x2070, /*!< Reception data to BCK clock */
+ TFA9894_BF_TDMFSPOL= 0x2080, /*!< FS polarity */
+ TFA9894_BF_TDMDEL= 0x2090, /*!< Data delay to FS */
+ TFA9894_BF_TDMADJ= 0x20a0, /*!< Data adjustment */
+ TFA9894_BF_TDMOOMP= 0x20b1, /*!< Received audio compression */
+ TFA9894_BF_TDMNBCK= 0x2103, /*!< TDM NBCK - Bit clock to FS ratio */
+ TFA9894_BF_TDMFSLN= 0x2143, /*!< FS length (master mode only) */
+ TFA9894_BF_TDMSLOTS= 0x2183, /*!< N-slots in Frame */
+ TFA9894_BF_TDMTXDFO= 0x21c1, /*!< Format unused bits */
+ TFA9894_BF_TDMTXUS0= 0x21e1, /*!< Format unused slots DATAO */
+ TFA9894_BF_TDMSLLN= 0x2204, /*!< N-bits in slot */
+ TFA9894_BF_TDMBRMG= 0x2254, /*!< N-bits remaining */
+ TFA9894_BF_TDMSSIZE= 0x22a4, /*!< Sample size per slot */
+ TFA9894_BF_TDMSPKS= 0x2303, /*!< TDM slot for sink 0 */
+ TFA9894_BF_TDMDCS= 0x2343, /*!< TDM slot for sink 1 */
+ TFA9894_BF_TDMCFSEL= 0x2381, /*!< TDM Source 2 data selection */
+ TFA9894_BF_TDMCF2SEL= 0x23a1, /*!< TDM Source 3 data selection */
+ TFA9894_BF_TDMCSS= 0x2403, /*!< Slot Position of source 0 data */
+ TFA9894_BF_TDMVSS= 0x2443, /*!< Slot Position of source 1 data */
+ TFA9894_BF_TDMCFS= 0x2483, /*!< Slot Position of source 2 data */
+ TFA9894_BF_TDMCF2S= 0x24c3, /*!< Slot Position of source 3 data */
+ TFA9894_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9894_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9894_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9894_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9894_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9894_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9894_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9894_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9894_BF_ISTCFMER= 0x4080, /*!< Status cfma error */
+ TFA9894_BF_ISTCFMAC= 0x4090, /*!< Status cfma ack */
+ TFA9894_BF_ISTSPKS= 0x40a0, /*!< Status coolflux speaker error */
+ TFA9894_BF_ISTACS= 0x40b0, /*!< Status cold started */
+ TFA9894_BF_ISTWDS= 0x40c0, /*!< Status watchdog reset */
+ TFA9894_BF_ISTBODNOK= 0x40d0, /*!< Status brown out detect */
+ TFA9894_BF_ISTLP1= 0x40e0, /*!< Status low power mode1 detect */
+ TFA9894_BF_ISTCLKOOR= 0x40f0, /*!< Status clock out of range */
+ TFA9894_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9894_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9894_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9894_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9894_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9894_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9894_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9894_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9894_BF_ICLCFMER= 0x4480, /*!< Clear cfma err */
+ TFA9894_BF_ICLCFMAC= 0x4490, /*!< Clear cfma ack */
+ TFA9894_BF_ICLSPKS= 0x44a0, /*!< Clear coolflux speaker error */
+ TFA9894_BF_ICLACS= 0x44b0, /*!< Clear cold started */
+ TFA9894_BF_ICLWDS= 0x44c0, /*!< Clear watchdog reset */
+ TFA9894_BF_ICLBODNOK= 0x44d0, /*!< Clear brown out detect */
+ TFA9894_BF_ICLLP1= 0x44e0, /*!< Clear low power mode1 detect */
+ TFA9894_BF_ICLCLKOOR= 0x44f0, /*!< Clear clock out of range */
+ TFA9894_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9894_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9894_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9894_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9894_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9894_BF_IEMANALARM= 0x4850, /*!< Enable Manager Alarm state */
+ TFA9894_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9894_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9894_BF_IECFMER= 0x4880, /*!< Enable cfma err */
+ TFA9894_BF_IECFMAC= 0x4890, /*!< Enable cfma ack */
+ TFA9894_BF_IESPKS= 0x48a0, /*!< Enable coolflux speaker error */
+ TFA9894_BF_IEACS = 0x48b0, /*!< Enable cold started */
+ TFA9894_BF_IEWDS = 0x48c0, /*!< Enable watchdog reset */
+ TFA9894_BF_IEBODNOK= 0x48d0, /*!< Enable brown out detect */
+ TFA9894_BF_IELP1 = 0x48e0, /*!< Enable low power mode1 detect */
+ TFA9894_BF_IECLKOOR= 0x48f0, /*!< Enable clock out of range */
+ TFA9894_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9894_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9894_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9894_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9894_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9894_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9894_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9894_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9894_BF_IPOCFMER= 0x4c80, /*!< Polarity cfma err */
+ TFA9894_BF_IPOCFMAC= 0x4c90, /*!< Polarity cfma ack */
+ TFA9894_BF_IPOSPKS= 0x4ca0, /*!< Polarity coolflux speaker error */
+ TFA9894_BF_IPOACS= 0x4cb0, /*!< Polarity cold started */
+ TFA9894_BF_IPOWDS= 0x4cc0, /*!< Polarity watchdog reset */
+ TFA9894_BF_IPOBODNOK= 0x4cd0, /*!< Polarity brown out detect */
+ TFA9894_BF_IPOLP1= 0x4ce0, /*!< Polarity low power mode1 detect */
+ TFA9894_BF_IPOCLKOOR= 0x4cf0, /*!< Polarity clock out of range */
+ TFA9894_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9894_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9894_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9894_BF_BSSRR = 0x5082, /*!< Battery safeguard release time */
+ TFA9894_BF_BSSHY = 0x50b1, /*!< Battery Safeguard hysteresis */
+ TFA9894_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9894_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA9894_BF_CFSM = 0x5130, /*!< Coolflux firmware soft mute control */
+ TFA9894_BF_VOL = 0x5187, /*!< CF firmware volume control */
+ TFA9894_BF_CLIPCTRL= 0x5202, /*!< Clip control setting */
+ TFA9894_BF_SLOPEE= 0x5230, /*!< Enables slope control */
+ TFA9894_BF_SLOPESET= 0x5240, /*!< Slope speed setting (binary coded) */
+ TFA9894_BF_AMPGAIN= 0x5287, /*!< Amplifier gain */
+ TFA9894_BF_TDMDCG= 0x5703, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9894_BF_TDMSPKG= 0x5743, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9894_BF_DCINSEL= 0x5781, /*!< VAMP_OUT2 input selection */
+ TFA9894_BF_LNMODE= 0x5881, /*!< Low noise gain mode control */
+ TFA9894_BF_LPM1MODE= 0x5ac1, /*!< Low power mode control */
+ TFA9894_BF_TDMSRCMAP= 0x5d02, /*!< TDM source mapping */
+ TFA9894_BF_TDMSRCAS= 0x5d31, /*!< Sensed value A */
+ TFA9894_BF_TDMSRCBS= 0x5d51, /*!< Sensed value B */
+ TFA9894_BF_TDMSRCACLIP= 0x5d71, /*!< Clip information (analog /digital) for source0 */
+ TFA9894_BF_TDMSRCBCLIP= 0x5d91, /*!< Clip information (analog /digital) for source1 */
+ TFA9894_BF_DELCURCOMP= 0x6102, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9894_BF_SIGCURCOMP= 0x6130, /*!< Polarity of compensation for current sense */
+ TFA9894_BF_ENCURCOMP= 0x6140, /*!< Enable current sense compensation */
+ TFA9894_BF_LVLCLPPWM= 0x6152, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9894_BF_DCVOF = 0x7005, /*!< First Boost Voltage Level */
+ TFA9894_BF_DCVOS = 0x7065, /*!< Second Boost Voltage Level */
+ TFA9894_BF_DCMCC = 0x70c3, /*!< Max Coil Current */
+ TFA9894_BF_DCCV = 0x7101, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9894_BF_DCIE = 0x7120, /*!< Adaptive boost mode */
+ TFA9894_BF_DCSR = 0x7130, /*!< Soft ramp up/down */
+ TFA9894_BF_DCDIS = 0x7140, /*!< DCDC on/off */
+ TFA9894_BF_DCPWM = 0x7150, /*!< DCDC PWM only mode */
+ TFA9894_BF_DCTRACK= 0x7160, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_DCENVSEL= 0x7170, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_DCTRIP= 0x7204, /*!< 1st adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894_BF_DCTRIP2= 0x7254, /*!< 2nd adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894_BF_DCTRIPT= 0x72a4, /*!< Track adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_DCTRIPHYSTE= 0x72f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9894_BF_DCHOLD= 0x7304, /*!< Hold time for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9894_BF_RST = 0x9000, /*!< Reset for Coolflux DSP */
+ TFA9894_BF_DMEM = 0x9011, /*!< Target memory for CFMA using I2C interface */
+ TFA9894_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA9894_BF_CFINT = 0x9040, /*!< Coolflux Interrupt - auto clear */
+ TFA9894_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA9894_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA9894_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA9894_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA9894_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA9894_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA9894_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA9894_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA9894_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA9894_BF_MADD = 0x910f, /*!< CF memory address */
+ TFA9894_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA9894_BF_ERR = 0x9307, /*!< CF error flags */
+ TFA9894_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA9894_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA9894_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA9894_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA9894_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA9894_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA9894_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA9894_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA9894_BF_MTPK = 0xa107, /*!< KEY2 to access KEY2 protected registers, customer key */
+ TFA9894_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9894_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9894_BF_CMTPI = 0xa350, /*!< Start copying all the data from mtp to I2C mtp registers - auto clear */
+ TFA9894_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp - auto clear */
+ TFA9894_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9894_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9894_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9894_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9894_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9894_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9894_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9894_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9894_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9894_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9894_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9894_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9894_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9894BfEnumList_t;
+#define TFA9894_NAMETABLE static tfaBfName_t Tfa9894DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown control , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "AMPE"}, /* Enable Amplifier , */\
+ { 0x40, "DCA"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xa0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xb0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xc0, "BSSS"}, /* Vbat protection steepness , */\
+ { 0xd0, "HPFBYP"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "DPSA"}, /* Enable DPSA , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* Device I2C settings configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x150, "BODE"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "BODFILT"}, /* BOD filter , */\
+ { 0x191, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1b0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "MANWDE"}, /* Watchdog enable , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "FAIMVBGOVRRL"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "AUDFS"}, /* Audio sample rate Fs , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* Current sense fractional delay , */\
+ { 0x2b1, "TDMPRES"}, /* Control for HW manager , */\
+ { 0x2d2, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external reference clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal reference clock , */\
+ { 0x432, "MCLKSEL"}, /* Master Clock Selection , */\
+ { 0x460, "MANAOOSC"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "ACKCLDDIS"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x510, "SPKSSEN"}, /* Enable speaker sub-system , */\
+ { 0x520, "MTPSSEN"}, /* Enable FAIM sub-system , */\
+ { 0x530, "WDTCLKEN"}, /* Enable Coolflux watchdog clock , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL Lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "WDS"}, /* Watchdog , */\
+ { 0x10b0, "SWS"}, /* Amplifier engage , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "SPKS"}, /* Speaker status , */\
+ { 0x1180, "CLKOOR"}, /* External clock status , */\
+ { 0x1190, "MANALARM"}, /* Alarm state , */\
+ { 0x11a0, "TDMERR"}, /* TDM error , */\
+ { 0x11b0, "TDMLUTER"}, /* TDM lookup table error , */\
+ { 0x1200, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1210, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1220, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1230, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1240, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1250, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x1260, "MANOPER"}, /* Device in Operating state , */\
+ { 0x1270, "LP1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "LA"}, /* Low amplitude detection , */\
+ { 0x1290, "VDDPH"}, /* VDDP greater than VBAT flag , */\
+ { 0x1402, "TDMSTAT"}, /* TDM Status bits , */\
+ { 0x1433, "MANSTATE"}, /* Device Manager status , */\
+ { 0x14b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2010, "TDMSPKE"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "TDMDCE"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "TDMCSE"}, /* Source 0 enable , */\
+ { 0x2040, "TDMVSE"}, /* Source 1 enable , */\
+ { 0x2050, "TDMCFE"}, /* Source 2 enable , */\
+ { 0x2060, "TDMCF2E"}, /* Source 3 enable , */\
+ { 0x2070, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2080, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2090, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x20a0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x20b1, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2103, "TDMNBCK"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x2183, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x21c1, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x21e1, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2204, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2254, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x22a4, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2303, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "TDMCFSEL"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "TDMCF2SEL"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "TDMCSS"}, /* Slot Position of source 0 data , */\
+ { 0x2443, "TDMVSS"}, /* Slot Position of source 1 data , */\
+ { 0x2483, "TDMCFS"}, /* Slot Position of source 2 data , */\
+ { 0x24c3, "TDMCF2S"}, /* Slot Position of source 3 data , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x4090, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x40a0, "ISTSPKS"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "ISTACS"}, /* Status cold started , */\
+ { 0x40c0, "ISTWDS"}, /* Status watchdog reset , */\
+ { 0x40d0, "ISTBODNOK"}, /* Status brown out detect , */\
+ { 0x40e0, "ISTLP1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "ISTCLKOOR"}, /* Status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x4490, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x44a0, "ICLSPKS"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "ICLACS"}, /* Clear cold started , */\
+ { 0x44c0, "ICLWDS"}, /* Clear watchdog reset , */\
+ { 0x44d0, "ICLBODNOK"}, /* Clear brown out detect , */\
+ { 0x44e0, "ICLLP1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "ICLCLKOOR"}, /* Clear clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IECFMER"}, /* Enable cfma err , */\
+ { 0x4890, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x48a0, "IESPKS"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "IEACS"}, /* Enable cold started , */\
+ { 0x48c0, "IEWDS"}, /* Enable watchdog reset , */\
+ { 0x48d0, "IEBODNOK"}, /* Enable brown out detect , */\
+ { 0x48e0, "IELP1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "IECLKOOR"}, /* Enable clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4c90, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "IPOSPKS"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4cc0, "IPOWDS"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "IPOBODNOK"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "IPOLP1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "IPOCLKOOR"}, /* Polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery safeguard release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery Safeguard hysteresis , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5130, "CFSM"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "VOL"}, /* CF firmware volume control , */\
+ { 0x5202, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5230, "SLOPEE"}, /* Enables slope control , */\
+ { 0x5240, "SLOPESET"}, /* Slope speed setting (binary coded) , */\
+ { 0x5287, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x5703, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "DCINSEL"}, /* VAMP_OUT2 input selection , */\
+ { 0x5881, "LNMODE"}, /* Low noise gain mode control , */\
+ { 0x5ac1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x5d02, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x5d31, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x5d51, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x5d71, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6102, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6152, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "DCVOF"}, /* First Boost Voltage Level , */\
+ { 0x7065, "DCVOS"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "DCMCC"}, /* Max Coil Current , */\
+ { 0x7101, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7130, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7140, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7150, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7160, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "DCENVSEL"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7204, "DCTRIP"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "DCTRIP2"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "DCTRIPT"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "DCHOLD"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x9000, "RST"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "DMEM"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* CF memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* CF error flags , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa350, "CMTPI"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9894_BITNAMETABLE static tfaBfName_t Tfa9894BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown control , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xa0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xb0, "test_ocp"}, /* OCP testing control , */\
+ { 0xc0, "batsense_steepness"}, /* Vbat protection steepness , */\
+ { 0xd0, "bypass_hp"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* Device I2C settings configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x150, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "bod_delay_set"}, /* BOD filter , */\
+ { 0x191, "bod_lvl_set"}, /* BOD threshold , */\
+ { 0x1b0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "man_enbl_watchdog"}, /* Watchdog enable , */\
+ { 0x1d0, "disable_engage"}, /* Disable Engage , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "faim_enable_vbg"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "audio_fs"}, /* Audio sample rate Fs , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* Current sense fractional delay , */\
+ { 0x2b1, "use_tdm_presence"}, /* Control for HW manager , */\
+ { 0x2d2, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external reference clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal reference clock , */\
+ { 0x432, "mclk_sel"}, /* Master Clock Selection , */\
+ { 0x460, "enbl_osc1m_auto_off"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "disable_auto_sel_refclk"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker sub-system , */\
+ { 0x520, "enbl_faim_ss"}, /* Enable FAIM sub-system , */\
+ { 0x530, "enbl_wdt_clk"}, /* Enable Coolflux watchdog clock , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to hidden register. (0x5A6B/23147 default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL Lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10b0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_cf_speakererror"}, /* Speaker status , */\
+ { 0x1180, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1190, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x11a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x11b0, "flag_tdm_lut_error"}, /* TDM lookup table error , */\
+ { 0x1200, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1210, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1220, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1230, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1240, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1250, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x1260, "flag_man_operating_state"}, /* Device in Operating state , */\
+ { 0x1270, "flag_lp_detect_mode1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x1290, "flag_vddp_gt_vbat"}, /* VDDP greater than VBAT flag , */\
+ { 0x1402, "tdm_status"}, /* TDM Status bits , */\
+ { 0x1433, "man_state"}, /* Device Manager status , */\
+ { 0x1473, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x14b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2010, "tdm_sink0_enable"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "tdm_sink1_enable"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "tdm_source0_enable"}, /* Source 0 enable , */\
+ { 0x2040, "tdm_source1_enable"}, /* Source 1 enable , */\
+ { 0x2050, "tdm_source2_enable"}, /* Source 2 enable , */\
+ { 0x2060, "tdm_source3_enable"}, /* Source 3 enable , */\
+ { 0x2070, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2080, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2090, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x20a0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x20b1, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2103, "tdm_nbck"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x2183, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x21c1, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x21e1, "tdm_txdata_format_unused_slot"}, /* Format unused slots DATAO , */\
+ { 0x2204, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2254, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x22a4, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2303, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "tdm_source2_sel"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "tdm_source3_sel"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "tdm_source0_slot"}, /* Slot Position of source 0 data , */\
+ { 0x2443, "tdm_source1_slot"}, /* Slot Position of source 1 data , */\
+ { 0x2483, "tdm_source2_slot"}, /* Slot Position of source 2 data , */\
+ { 0x24c3, "tdm_source3_slot"}, /* Slot Position of source 3 data , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x4090, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x40a0, "int_out_flag_cf_speakererror"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "int_out_flag_cold_started"}, /* Status cold started , */\
+ { 0x40c0, "int_out_flag_watchdog_reset"}, /* Status watchdog reset , */\
+ { 0x40d0, "int_out_flag_bod_vddd_nok"}, /* Status brown out detect , */\
+ { 0x40e0, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "int_out_flag_clk_out_of_range"}, /* Status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x4490, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x44a0, "int_in_flag_cf_speakererror"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44c0, "int_in_flag_watchdog_reset"}, /* Clear watchdog reset , */\
+ { 0x44d0, "int_in_flag_bod_vddd_nok"}, /* Clear brown out detect , */\
+ { 0x44e0, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "int_in_flag_clk_out_of_range"}, /* Clear clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x4890, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x48a0, "int_enable_flag_cf_speakererror"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48c0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog reset , */\
+ { 0x48d0, "int_enable_flag_bod_vddd_nok"}, /* Enable brown out detect , */\
+ { 0x48e0, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "int_enable_flag_clk_out_of_range"}, /* Enable clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4c90, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "int_polarity_flag_cf_speakererror"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4cc0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "int_polarity_flag_clk_out_of_range"}, /* Polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery safeguard release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5130, "cf_mute"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "cf_volume"}, /* CF firmware volume control , */\
+ { 0x5202, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5230, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x5240, "ctrl_slope"}, /* Slope speed setting (binary coded) , */\
+ { 0x5287, "gain"}, /* Amplifier gain , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for battery safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5370, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5380, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5390, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x53a3, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5452, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x550a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x55b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x55c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5600, "pwm_shape"}, /* PWM shape , */\
+ { 0x5614, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5660, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x5670, "reclock_voltsense"}, /* Reclock the voltage sense PWM signal , */\
+ { 0x5680, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5690, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x56a1, "enbl_odd_up_even_down"}, /* Control for PWM reference sawtooth generartion , */\
+ { 0x5703, "ctrl_att_dcdc"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "ctrl_att_spkr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "vamp_sel2"}, /* VAMP_OUT2 input selection , */\
+ { 0x5805, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x5861, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x5881, "lownoisegain_mode"}, /* Low noise gain mode control , */\
+ { 0x5905, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x5965, "hold_time"}, /* Low noise mode hold time before entering into low noise mode, */\
+ { 0x5a05, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x5a65, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x5ac1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x5b05, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x5b65, "lpm1_hold_time"}, /* Low power mode hold time before entering into low power mode, */\
+ { 0x5bc0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x5c00, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x5c13, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x5c50, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x5c61, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x5d02, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x5d31, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x5d51, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x5d71, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x5e02, "rst_min_vbat_delay"}, /* Delay for reseting the min_vbat value inside HW Clipper (number of Fs pulses), */\
+ { 0x5e30, "rst_min_vbat_sel"}, /* Control for selecting reset signal for min_bat , */\
+ { 0x5f00, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5f12, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x5f42, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x5f78, "spare_out"}, /* Spare out register , */\
+ { 0x600f, "spare_in"}, /* Spare IN , */\
+ { 0x6102, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6152, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "frst_boost_voltage"}, /* First Boost Voltage Level , */\
+ { 0x7065, "scnd_boost_voltage"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "boost_cur"}, /* Max Coil Current , */\
+ { 0x7101, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7130, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7140, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7150, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7160, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7180, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7204, "boost_trip_lvl_1st"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "boost_trip_lvl_2nd"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "boost_trip_lvl_track"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x7350, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x7361, "dcdc_ctrl_maxzercnt"}, /* Number of zero current flags to count before going to pfm mode, */\
+ { 0x7386, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x73f0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x7404, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7451, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7474, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x74c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x74e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x74f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7500, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7510, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7520, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7530, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7540, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7550, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7560, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7570, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7580, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x7595, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7600, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7611, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7631, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7650, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7660, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8040, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8050, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8060, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8105, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP) * signal, */\
+ { 0x8164, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x81b0, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x81c0, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x81d0, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x81e0, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x81f0, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8200, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8210, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8220, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8231, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8250, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8263, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x82a0, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x82b4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8300, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8310, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8320, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8330, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8340, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8350, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8364, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8800, "ctrl_vs_igen_supply"}, /* Control for selecting supply for VS current generator, */\
+ { 0x8810, "ctrl_vs_force_div2"}, /* Select input resistive divider gain , */\
+ { 0x8820, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8901, "volsense_pwm_sel"}, /* Voltage sense source selection control , */\
+ { 0x8920, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8930, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8940, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8950, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8960, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8970, "vs_classd_tran_skip"}, /* Skip voltage sense connection during a classD amplifier transition, */\
+ { 0x8987, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8a00, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8a10, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8a20, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "enbl_vs_adc"}, /* Enable voltage sense ADC , */\
+ { 0x8aa0, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8ab0, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8ac0, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8ad0, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8ae0, "enbl_vs_ldo"}, /* Enable voltage sense LDO , */\
+ { 0x8af0, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "cf_dmem"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* CF memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* CF error flags , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0xa007, "mtpkey1"}, /* KEY1 To access KEY1 protected registers 0x5A/90d (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from MTP to I2C mtp register - auto clear, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp - auto clear, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the FaIM controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the FaIM are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the FaIM are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb000, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb010, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb020, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb030, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb040, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb050, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb060, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb070, "disable_main_ctrl_change_prot"}, /* Disable main control change protection , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* Enable ABIST with FFT on Coolflux DSP , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc530, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc540, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc550, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc560, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc570, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc583, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc5c0, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc607, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO , */\
+ { 0xc687, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT , */\
+ { 0xc707, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 , */\
+ { 0xc800, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xc810, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xc820, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xc830, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xc844, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xc894, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xc903, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xc943, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xca05, "pll_seli"}, /* PLL SELI - I2C direct PLL control mode only , */\
+ { 0xca64, "pll_selp"}, /* PLL SELP - I2C direct PLL control mode only , */\
+ { 0xcab3, "pll_selr"}, /* PLL SELR - I2C direct PLL control mode only , */\
+ { 0xcaf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xcb09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcba0, "pll_mdec_msb"}, /* MSB of PLL_mdec - I2C direct PLL control mode only, */\
+ { 0xcbb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcbc0, "enbl_osc"}, /* Enables OSC1M in I2C direct control mode only , */\
+ { 0xcbd0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcbe0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcbf0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcc0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xcd06, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xce0f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xcf02, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xcf33, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd000, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd011, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd032, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd064, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd0b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd0c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd109, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd201, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd221, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd241, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd301, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd321, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd340, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xd407, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd480, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd491, "sel_wdt_clk"}, /* Watch dog clock divider settings , */\
+ { 0xd4b0, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd500, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd510, "gainatt_feedback"}, /* Gainatt feedback to tdm , */\
+ { 0xd522, "test_parametric_io"}, /* Test IO parametric , */\
+ { 0xd550, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0xd561, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd580, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd593, "test_spare_out2"}, /* Test spare out 2 , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs"}, /* Voltage sense gain , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "mtpdata4"}, /* MTP4 data , */\
+ { 0xf50f, "calibr_R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xf60f, "mtpdata6"}, /* MTP6 data , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable functionality of dcdcoff_mode bit , */\
+ { 0xf910, "mtp_lock_enbl_coolflux"}, /* Disable functionality of enbl_coolflux bit , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf940, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xf950, "mtp_gate_cgu_clock_for_test"}, /* CGU test clock control , */\
+ { 0xf987, "type_bits_fw"}, /* MTP control for firmware features - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9894_irq {
+ tfa9894_irq_max = -1,
+ tfa9894_irq_all = -1 /* all irqs */};
+
+#define TFA9894_IRQ_NAMETABLE static tfaIrqName_t Tfa9894IrqNames[]= {\
+};
+#endif /* _TFA9894_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames_N2.h b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames_N2.h
new file mode 100644
index 00000000000..ff9ed8a5338
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9894_tfafieldnames_N2.h
@@ -0,0 +1,1130 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9894_tfaFieldnames_N2.h
+ * This file was generated automatically on 09/28/18 at 12:19:41.
+ * Source file: TFA9894_N2A1_I2C_RegisterMap.xlsx
+ */
+
+#ifndef _TFA9894_TFAFIELDNAMES_N2_H
+#define _TFA9894_TFAFIELDNAMES_N2_H
+
+
+#define TFA9894N2_I2CVERSION 25.0
+
+typedef enum Tfa9894N2BfEnumList {
+ TFA9894N2_BF_PWDN = 0x0000, /*!< Powerdown control */
+ TFA9894N2_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9894N2_BF_CFE = 0x0020, /*!< Enable CoolFlux DSP */
+ TFA9894N2_BF_AMPE = 0x0030, /*!< Enable Amplifier */
+ TFA9894N2_BF_DCA = 0x0040, /*!< Enable DCDC Boost converter */
+ TFA9894N2_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA9894N2_BF_AMPC = 0x0060, /*!< CoolFlux control over amplifier */
+ TFA9894N2_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9894N2_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9894N2_BF_BYPOCP= 0x00a0, /*!< Bypass OCP */
+ TFA9894N2_BF_TSTOCP= 0x00b0, /*!< OCP testing control */
+ TFA9894N2_BF_BSSS = 0x00c0, /*!< Vbat protection steepness */
+ TFA9894N2_BF_HPFBYP= 0x00d0, /*!< Bypass High Pass Filter */
+ TFA9894N2_BF_DPSA = 0x00e0, /*!< Enable DPSA */
+ TFA9894N2_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9894N2_BF_MANSCONF= 0x0120, /*!< Device I2C settings configured */
+ TFA9894N2_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA9894N2_BF_MANROBOD= 0x0140, /*!< Reaction on BOD */
+ TFA9894N2_BF_BODE = 0x0150, /*!< Enable BOD (only in direct control mode) */
+ TFA9894N2_BF_BODHYS= 0x0160, /*!< Enable Hysteresis of BOD */
+ TFA9894N2_BF_BODFILT= 0x0171, /*!< BOD filter */
+ TFA9894N2_BF_BODTHLVL= 0x0191, /*!< BOD threshold */
+ TFA9894N2_BF_MUTETO= 0x01b0, /*!< Time out SB mute sequence */
+ TFA9894N2_BF_MANWDE= 0x01c0, /*!< Watchdog enable */
+ TFA9894N2_BF_OPENMTP= 0x01e0, /*!< Control for FAIM protection */
+ TFA9894N2_BF_FAIMVBGOVRRL= 0x01f0, /*!< Overrule the enabling of VBG for faim erase/write access */
+ TFA9894N2_BF_AUDFS = 0x0203, /*!< Audio sample rate Fs */
+ TFA9894N2_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9894N2_BF_FRACTDEL= 0x0255, /*!< Current sense fractional delay */
+ TFA9894N2_BF_TDMPRES= 0x02b1, /*!< Control for HW manager */
+ TFA9894N2_BF_AMPOCRT= 0x02d2, /*!< Amplifier on-off criteria for shutdown */
+ TFA9894N2_BF_REV = 0x030f, /*!< Revision info */
+ TFA9894N2_BF_REFCKEXT= 0x0401, /*!< PLL external reference clock */
+ TFA9894N2_BF_REFCKSEL= 0x0420, /*!< PLL internal reference clock */
+ TFA9894N2_BF_MCLKSEL= 0x0432, /*!< Master Clock Selection */
+ TFA9894N2_BF_MANAOOSC= 0x0460, /*!< Internal OSC1M off at PWDN */
+ TFA9894N2_BF_ACKCLDDIS= 0x0470, /*!< Automatic PLL reference clock selection for cold start */
+ TFA9894N2_BF_FSSYNCEN= 0x0480, /*!< Enable FS synchronisation for clock divider */
+ TFA9894N2_BF_CLKREFSYNCEN= 0x0490, /*!< Enable PLL reference clock synchronisation for clock divider */
+ TFA9894N2_BF_PLLSTUP= 0x04a0, /*!< PLL startup time configuration */
+ TFA9894N2_BF_CGUSYNCDCG= 0x0500, /*!< Clock gating control for CGU synchronisation module */
+ TFA9894N2_BF_SPKSSEN= 0x0510, /*!< Enable speaker sub-system */
+ TFA9894N2_BF_MTPSSEN= 0x0520, /*!< Enable FAIM sub-system */
+ TFA9894N2_BF_WDTCLKEN= 0x0530, /*!< Enable Coolflux watchdog clock */
+ TFA9894N2_BF_VDDS = 0x1000, /*!< POR */
+ TFA9894N2_BF_PLLS = 0x1010, /*!< PLL Lock */
+ TFA9894N2_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9894N2_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9894N2_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9894N2_BF_OCDS = 0x1050, /*!< OCP amplifier (sticky register, clear on read) */
+ TFA9894N2_BF_CLKS = 0x1060, /*!< Clocks stable */
+ TFA9894N2_BF_MTPB = 0x1070, /*!< MTP busy */
+ TFA9894N2_BF_NOCLK = 0x1080, /*!< Lost clock */
+ TFA9894N2_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA9894N2_BF_WDS = 0x10a0, /*!< Watchdog */
+ TFA9894N2_BF_SWS = 0x10b0, /*!< Amplifier engage */
+ TFA9894N2_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9894N2_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9894N2_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9894N2_BF_BODNOK= 0x10f0, /*!< BOD Flag - VDD NOT OK */
+ TFA9894N2_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9894N2_BF_DCDCA = 0x1110, /*!< DCDC active (sticky register, clear on read) */
+ TFA9894N2_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos (sticky register, clear on read) */
+ TFA9894N2_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9894N2_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9894N2_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9894N2_BF_SPKS = 0x1170, /*!< Speaker status */
+ TFA9894N2_BF_CLKOOR= 0x1180, /*!< External clock status */
+ TFA9894N2_BF_MANALARM= 0x1190, /*!< Alarm state */
+ TFA9894N2_BF_TDMERR= 0x11a0, /*!< TDM error */
+ TFA9894N2_BF_TDMLUTER= 0x11b0, /*!< TDM lookup table error */
+ TFA9894N2_BF_NOAUDCLK= 0x11c0, /*!< Lost Audio clock */
+ TFA9894N2_BF_OCPOAP= 0x1200, /*!< OCPOK pmos A */
+ TFA9894N2_BF_OCPOAN= 0x1210, /*!< OCPOK nmos A */
+ TFA9894N2_BF_OCPOBP= 0x1220, /*!< OCPOK pmos B */
+ TFA9894N2_BF_OCPOBN= 0x1230, /*!< OCPOK nmos B */
+ TFA9894N2_BF_CLIPS = 0x1240, /*!< Amplifier clipping */
+ TFA9894N2_BF_MANMUTE= 0x1250, /*!< Audio mute sequence */
+ TFA9894N2_BF_MANOPER= 0x1260, /*!< Device in Operating state */
+ TFA9894N2_BF_LP1 = 0x1270, /*!< Low power MODE1 detection */
+ TFA9894N2_BF_LA = 0x1280, /*!< Low amplitude detection */
+ TFA9894N2_BF_VDDPH = 0x1290, /*!< VDDP greater than VBAT flag */
+ TFA9894N2_BF_TDMSTAT= 0x1302, /*!< TDM Status bits */
+ TFA9894N2_BF_MANSTATE= 0x1333, /*!< Device Manager status */
+ TFA9894N2_BF_DCMODE= 0x13b1, /*!< DCDC mode status bits */
+ TFA9894N2_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9894N2_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9894N2_BF_VDDPS = 0x1709, /*!< IC VDDP voltage (1023*VDDP/13V) */
+ TFA9894N2_BF_TDME = 0x2000, /*!< Enable interface */
+ TFA9894N2_BF_TDMSPKE= 0x2010, /*!< Control audio tdm channel in sink0 */
+ TFA9894N2_BF_TDMDCE= 0x2020, /*!< Control audio tdm channel in sink1 */
+ TFA9894N2_BF_TDMCSE= 0x2030, /*!< Source 0 enable */
+ TFA9894N2_BF_TDMVSE= 0x2040, /*!< Source 1 enable */
+ TFA9894N2_BF_TDMCFE= 0x2050, /*!< Source 2 enable */
+ TFA9894N2_BF_TDMCF2E= 0x2060, /*!< Source 3 enable */
+ TFA9894N2_BF_TDMCLINV= 0x2070, /*!< Reception data to BCK clock */
+ TFA9894N2_BF_TDMFSPOL= 0x2080, /*!< FS polarity */
+ TFA9894N2_BF_TDMDEL= 0x2090, /*!< Data delay to FS */
+ TFA9894N2_BF_TDMADJ= 0x20a0, /*!< Data adjustment */
+ TFA9894N2_BF_TDMOOMP= 0x20b1, /*!< Received audio compression */
+ TFA9894N2_BF_TDMNBCK= 0x2103, /*!< TDM NBCK - Bit clock to FS ratio */
+ TFA9894N2_BF_TDMFSLN= 0x2143, /*!< FS length (master mode only) */
+ TFA9894N2_BF_TDMSLOTS= 0x2183, /*!< N-slots in Frame */
+ TFA9894N2_BF_TDMTXDFO= 0x21c1, /*!< Format unused bits */
+ TFA9894N2_BF_TDMTXUS0= 0x21e1, /*!< Format unused slots DATAO */
+ TFA9894N2_BF_TDMSLLN= 0x2204, /*!< N-bits in slot */
+ TFA9894N2_BF_TDMBRMG= 0x2254, /*!< N-bits remaining */
+ TFA9894N2_BF_TDMSSIZE= 0x22a4, /*!< Sample size per slot */
+ TFA9894N2_BF_TDMSPKS= 0x2303, /*!< TDM slot for sink 0 */
+ TFA9894N2_BF_TDMDCS= 0x2343, /*!< TDM slot for sink 1 */
+ TFA9894N2_BF_TDMCFSEL= 0x2381, /*!< TDM Source 2 data selection */
+ TFA9894N2_BF_TDMCF2SEL= 0x23a1, /*!< TDM Source 3 data selection */
+ TFA9894N2_BF_TDMCSS= 0x2403, /*!< Slot position of source 0 data */
+ TFA9894N2_BF_TDMVSS= 0x2443, /*!< Slot position of source 1 data */
+ TFA9894N2_BF_TDMCFS= 0x2483, /*!< Slot position of source 2 data */
+ TFA9894N2_BF_TDMCF2S= 0x24c3, /*!< Slot position of source 3 data */
+ TFA9894N2_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9894N2_BF_ISTBSTOC= 0x4010, /*!< Status DCDC OCP */
+ TFA9894N2_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9894N2_BF_ISTOCPR= 0x4030, /*!< Status OCP alarm */
+ TFA9894N2_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9894N2_BF_ISTMANALARM= 0x4050, /*!< Status manager alarm state */
+ TFA9894N2_BF_ISTTDMER= 0x4060, /*!< Status TDM error */
+ TFA9894N2_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9894N2_BF_ISTCFMER= 0x4080, /*!< Status cfma error */
+ TFA9894N2_BF_ISTCFMAC= 0x4090, /*!< Status cfma ack */
+ TFA9894N2_BF_ISTSPKS= 0x40a0, /*!< Status coolflux speaker error */
+ TFA9894N2_BF_ISTACS= 0x40b0, /*!< Status cold started */
+ TFA9894N2_BF_ISTWDS= 0x40c0, /*!< Status watchdog reset */
+ TFA9894N2_BF_ISTBODNOK= 0x40d0, /*!< Status brown out detect */
+ TFA9894N2_BF_ISTLP1= 0x40e0, /*!< Status low power mode1 detect */
+ TFA9894N2_BF_ISTCLKOOR= 0x40f0, /*!< Status clock out of range */
+ TFA9894N2_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9894N2_BF_ICLBSTOC= 0x4410, /*!< Clear DCDC OCP */
+ TFA9894N2_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9894N2_BF_ICLOCPR= 0x4430, /*!< Clear OCP alarm */
+ TFA9894N2_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9894N2_BF_ICLMANALARM= 0x4450, /*!< Clear manager alarm state */
+ TFA9894N2_BF_ICLTDMER= 0x4460, /*!< Clear TDM error */
+ TFA9894N2_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9894N2_BF_ICLCFMER= 0x4480, /*!< Clear cfma err */
+ TFA9894N2_BF_ICLCFMAC= 0x4490, /*!< Clear cfma ack */
+ TFA9894N2_BF_ICLSPKS= 0x44a0, /*!< Clear coolflux speaker error */
+ TFA9894N2_BF_ICLACS= 0x44b0, /*!< Clear cold started */
+ TFA9894N2_BF_ICLWDS= 0x44c0, /*!< Clear watchdog reset */
+ TFA9894N2_BF_ICLBODNOK= 0x44d0, /*!< Clear brown out detect */
+ TFA9894N2_BF_ICLLP1= 0x44e0, /*!< Clear low power mode1 detect */
+ TFA9894N2_BF_ICLCLKOOR= 0x44f0, /*!< Clear clock out of range */
+ TFA9894N2_BF_IEVDDS= 0x4800, /*!< Enable POR */
+ TFA9894N2_BF_IEBSTOC= 0x4810, /*!< Enable DCDC OCP */
+ TFA9894N2_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9894N2_BF_IEOCPR= 0x4830, /*!< Enable OCP alarm */
+ TFA9894N2_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9894N2_BF_IEMANALARM= 0x4850, /*!< Enable Manager Alarm state */
+ TFA9894N2_BF_IETDMER= 0x4860, /*!< Enable TDM error */
+ TFA9894N2_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9894N2_BF_IECFMER= 0x4880, /*!< Enable cfma err */
+ TFA9894N2_BF_IECFMAC= 0x4890, /*!< Enable cfma ack */
+ TFA9894N2_BF_IESPKS= 0x48a0, /*!< Enable coolflux speaker error */
+ TFA9894N2_BF_IEACS = 0x48b0, /*!< Enable cold started */
+ TFA9894N2_BF_IEWDS = 0x48c0, /*!< Enable watchdog reset */
+ TFA9894N2_BF_IEBODNOK= 0x48d0, /*!< Enable brown out detect */
+ TFA9894N2_BF_IELP1 = 0x48e0, /*!< Enable low power mode1 detect */
+ TFA9894N2_BF_IECLKOOR= 0x48f0, /*!< Enable clock out of range */
+ TFA9894N2_BF_IPOVDDS= 0x4c00, /*!< Polarity POR */
+ TFA9894N2_BF_IPOBSTOC= 0x4c10, /*!< Polarity DCDC OCP */
+ TFA9894N2_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9894N2_BF_IPOOCPR= 0x4c30, /*!< Polarity ocp alarm */
+ TFA9894N2_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9894N2_BF_IPOMANALARM= 0x4c50, /*!< Polarity manager alarm state */
+ TFA9894N2_BF_IPOTDMER= 0x4c60, /*!< Polarity TDM error */
+ TFA9894N2_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9894N2_BF_IPOCFMER= 0x4c80, /*!< Polarity cfma err */
+ TFA9894N2_BF_IPOCFMAC= 0x4c90, /*!< Polarity cfma ack */
+ TFA9894N2_BF_IPOSPKS= 0x4ca0, /*!< Polarity coolflux speaker error */
+ TFA9894N2_BF_IPOACS= 0x4cb0, /*!< Polarity cold started */
+ TFA9894N2_BF_IPOWDS= 0x4cc0, /*!< Polarity watchdog reset */
+ TFA9894N2_BF_IPOBODNOK= 0x4cd0, /*!< Polarity brown out detect */
+ TFA9894N2_BF_IPOLP1= 0x4ce0, /*!< Polarity low power mode1 detect */
+ TFA9894N2_BF_IPOCLKOOR= 0x4cf0, /*!< Polarity clock out of range */
+ TFA9894N2_BF_BSSCR = 0x5001, /*!< Battery safeguard attack time */
+ TFA9894N2_BF_BSST = 0x5023, /*!< Battery safeguard threshold voltage level */
+ TFA9894N2_BF_BSSRL = 0x5061, /*!< Battery safeguard maximum reduction */
+ TFA9894N2_BF_BSSRR = 0x5082, /*!< Battery safeguard release time */
+ TFA9894N2_BF_BSSHY = 0x50b1, /*!< Battery Safeguard hysteresis */
+ TFA9894N2_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9894N2_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA9894N2_BF_CFSM = 0x5130, /*!< Coolflux firmware soft mute control */
+ TFA9894N2_BF_VOL = 0x5187, /*!< CF firmware volume control */
+ TFA9894N2_BF_CLIPCTRL= 0x5202, /*!< Clip control setting */
+ TFA9894N2_BF_SLOPEE= 0x5230, /*!< Enables slope control */
+ TFA9894N2_BF_SLOPESET= 0x5240, /*!< Slope speed setting (binary coded) */
+ TFA9894N2_BF_BYPDLYLINE= 0x5250, /*!< Bypass the interpolator delay line */
+ TFA9894N2_BF_AMPGAIN= 0x5287, /*!< Amplifier gain */
+ TFA9894N2_BF_TDMDCG= 0x5703, /*!< Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE) */
+ TFA9894N2_BF_TDMSPKG= 0x5743, /*!< Total gain depending on INPLEV setting (channel 0) */
+ TFA9894N2_BF_DCINSEL= 0x5781, /*!< VAMP_OUT2 input selection */
+ TFA9894N2_BF_LNMODE= 0x5881, /*!< Low noise gain mode control */
+ TFA9894N2_BF_LPM1MODE= 0x5ac1, /*!< Low power mode control */
+ TFA9894N2_BF_TDMSRCMAP= 0x5d02, /*!< TDM source mapping */
+ TFA9894N2_BF_TDMSRCAS= 0x5d31, /*!< Sensed value A */
+ TFA9894N2_BF_TDMSRCBS= 0x5d51, /*!< Sensed value B */
+ TFA9894N2_BF_TDMSRCACLIP= 0x5d71, /*!< Clip information (analog /digital) for source0 */
+ TFA9894N2_BF_TDMSRCBCLIP= 0x5d91, /*!< Clip information (analog /digital) for source1 */
+ TFA9894N2_BF_DELCURCOMP= 0x6102, /*!< Delay to allign compensation signal with current sense signal */
+ TFA9894N2_BF_SIGCURCOMP= 0x6130, /*!< Polarity of compensation for current sense */
+ TFA9894N2_BF_ENCURCOMP= 0x6140, /*!< Enable current sense compensation */
+ TFA9894N2_BF_LVLCLPPWM= 0x6152, /*!< Set the amount of pwm pulse that may be skipped before clip-flag is triggered */
+ TFA9894N2_BF_DCVOF = 0x7005, /*!< First Boost Voltage Level */
+ TFA9894N2_BF_DCVOS = 0x7065, /*!< Second Boost Voltage Level */
+ TFA9894N2_BF_DCMCC = 0x70c3, /*!< Max Coil Current */
+ TFA9894N2_BF_DCCV = 0x7101, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9894N2_BF_DCIE = 0x7120, /*!< Adaptive boost mode */
+ TFA9894N2_BF_DCSR = 0x7130, /*!< Soft ramp up/down */
+ TFA9894N2_BF_DCDIS = 0x7140, /*!< DCDC on/off */
+ TFA9894N2_BF_DCPWM = 0x7150, /*!< DCDC PWM only mode */
+ TFA9894N2_BF_DCTRACK= 0x7160, /*!< Boost algorithm selection, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_DCENVSEL= 0x7170, /*!< Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_OVSCTLVL= 0x7195, /*!< Threshold level to activate active overshoot control */
+ TFA9894N2_BF_DCTRIP= 0x7204, /*!< 1st adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894N2_BF_DCTRIP2= 0x7254, /*!< 2nd adaptive boost trip levels, effective only when DCIE is set to 1 */
+ TFA9894N2_BF_DCTRIPT= 0x72a4, /*!< Track adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_DCTRIPHYSTE= 0x72f0, /*!< Enable hysteresis on booster trip levels */
+ TFA9894N2_BF_DCHOLD= 0x7304, /*!< Hold time / Hysteresis for DCDC booster, effective only when boost_intelligent is set to 1 */
+ TFA9894N2_BF_RST = 0x9000, /*!< Reset for Coolflux DSP */
+ TFA9894N2_BF_DMEM = 0x9011, /*!< Target memory for CFMA using I2C interface */
+ TFA9894N2_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA9894N2_BF_CFINT = 0x9040, /*!< Coolflux Interrupt - auto clear */
+ TFA9894N2_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA9894N2_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA9894N2_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA9894N2_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA9894N2_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA9894N2_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA9894N2_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA9894N2_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA9894N2_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA9894N2_BF_MADD = 0x910f, /*!< CF memory address */
+ TFA9894N2_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA9894N2_BF_ERR = 0x9307, /*!< CF error flags */
+ TFA9894N2_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA9894N2_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA9894N2_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA9894N2_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA9894N2_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA9894N2_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA9894N2_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA9894N2_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA9894N2_BF_MTPK = 0xa107, /*!< KEY2 to access KEY2 protected registers, customer key */
+ TFA9894N2_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9894N2_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9894N2_BF_CMTPI = 0xa350, /*!< Start copying all the data from mtp to I2C mtp registers - auto clear */
+ TFA9894N2_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp - auto clear */
+ TFA9894N2_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9894N2_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9894N2_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9894N2_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9894N2_BF_PLLINSELI= 0xca05, /*!< PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9894N2_BF_PLLINSELP= 0xca64, /*!< PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9894N2_BF_PLLINSELR= 0xcab3, /*!< PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1 */
+ TFA9894N2_BF_PLLNDEC= 0xcb09, /*!< PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLMDECMSB= 0xcba0, /*!< MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLBYPASS= 0xcbb0, /*!< PLL bypass control during functional mode */
+ TFA9894N2_BF_PLLDIRECTI= 0xcbc0, /*!< PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLDIRECTO= 0xcbd0, /*!< PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLFRMSTBL= 0xcbe0, /*!< PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLFRM= 0xcbf0, /*!< PLL free running mode control in functional mode */
+ TFA9894N2_BF_PLLMDECLSB= 0xcc0f, /*!< Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_PLLPDEC= 0xcd06, /*!< PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1 */
+ TFA9894N2_BF_DIRECTPLL= 0xcd70, /*!< Enabled PLL direct control mode, overrules the PLL LUT with I2C register values */
+ TFA9894N2_BF_DIRECTCLK= 0xcd80, /*!< Enabled CGU clock divider direct control mode */
+ TFA9894N2_BF_PLLLIM= 0xcd90, /*!< PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1 */
+ TFA9894N2_BF_SWPROFIL= 0xe00f, /*!< Software profile data */
+ TFA9894N2_BF_SWVSTEP= 0xe10f, /*!< Software vstep information */
+ TFA9894N2_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9894N2_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9894N2_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9894N2_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9894N2_BF_USERDEF= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9894N2_BF_CUSTINFO= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9894N2_BF_R25C = 0xf50f, /*!< Ron resistance of speaker coil */
+} Tfa9894N2BfEnumList_t;
+#define TFA9894N2_NAMETABLE static tfaBfName_t Tfa9894N2DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown control , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "AMPE"}, /* Enable Amplifier , */\
+ { 0x40, "DCA"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xa0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xb0, "TSTOCP"}, /* OCP testing control , */\
+ { 0xc0, "BSSS"}, /* Vbat protection steepness , */\
+ { 0xd0, "HPFBYP"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "DPSA"}, /* Enable DPSA , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* Device I2C settings configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x150, "BODE"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "BODHYS"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "BODFILT"}, /* BOD filter , */\
+ { 0x191, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1b0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "MANWDE"}, /* Watchdog enable , */\
+ { 0x1e0, "OPENMTP"}, /* Control for FAIM protection , */\
+ { 0x1f0, "FAIMVBGOVRRL"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "AUDFS"}, /* Audio sample rate Fs , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* Current sense fractional delay , */\
+ { 0x2b1, "TDMPRES"}, /* Control for HW manager , */\
+ { 0x2d2, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external reference clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal reference clock , */\
+ { 0x432, "MCLKSEL"}, /* Master Clock Selection , */\
+ { 0x460, "MANAOOSC"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "ACKCLDDIS"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x480, "FSSYNCEN"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "CLKREFSYNCEN"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "PLLSTUP"}, /* PLL startup time configuration , */\
+ { 0x500, "CGUSYNCDCG"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "SPKSSEN"}, /* Enable speaker sub-system , */\
+ { 0x520, "MTPSSEN"}, /* Enable FAIM sub-system , */\
+ { 0x530, "WDTCLKEN"}, /* Enable Coolflux watchdog clock , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL Lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "OCDS"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "CLKS"}, /* Clocks stable , */\
+ { 0x1070, "MTPB"}, /* MTP busy , */\
+ { 0x1080, "NOCLK"}, /* Lost clock , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "WDS"}, /* Watchdog , */\
+ { 0x10b0, "SWS"}, /* Amplifier engage , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "SPKS"}, /* Speaker status , */\
+ { 0x1180, "CLKOOR"}, /* External clock status , */\
+ { 0x1190, "MANALARM"}, /* Alarm state , */\
+ { 0x11a0, "TDMERR"}, /* TDM error , */\
+ { 0x11b0, "TDMLUTER"}, /* TDM lookup table error , */\
+ { 0x11c0, "NOAUDCLK"}, /* Lost Audio clock , */\
+ { 0x1200, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1210, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1220, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1230, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1240, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x1250, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x1260, "MANOPER"}, /* Device in Operating state , */\
+ { 0x1270, "LP1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "LA"}, /* Low amplitude detection , */\
+ { 0x1290, "VDDPH"}, /* VDDP greater than VBAT flag , */\
+ { 0x1302, "TDMSTAT"}, /* TDM Status bits , */\
+ { 0x1333, "MANSTATE"}, /* Device Manager status , */\
+ { 0x13b1, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "TDME"}, /* Enable interface , */\
+ { 0x2010, "TDMSPKE"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "TDMDCE"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "TDMCSE"}, /* Source 0 enable , */\
+ { 0x2040, "TDMVSE"}, /* Source 1 enable , */\
+ { 0x2050, "TDMCFE"}, /* Source 2 enable , */\
+ { 0x2060, "TDMCF2E"}, /* Source 3 enable , */\
+ { 0x2070, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2080, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x2090, "TDMDEL"}, /* Data delay to FS , */\
+ { 0x20a0, "TDMADJ"}, /* Data adjustment , */\
+ { 0x20b1, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2103, "TDMNBCK"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "TDMFSLN"}, /* FS length (master mode only) , */\
+ { 0x2183, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x21c1, "TDMTXDFO"}, /* Format unused bits , */\
+ { 0x21e1, "TDMTXUS0"}, /* Format unused slots DATAO , */\
+ { 0x2204, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2254, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x22a4, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2303, "TDMSPKS"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "TDMDCS"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "TDMCFSEL"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "TDMCF2SEL"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "TDMCSS"}, /* Slot position of source 0 data , */\
+ { 0x2443, "TDMVSS"}, /* Slot position of source 1 data , */\
+ { 0x2483, "TDMCFS"}, /* Slot position of source 2 data , */\
+ { 0x24c3, "TDMCF2S"}, /* Slot position of source 3 data , */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOCPR"}, /* Status OCP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTMANALARM"}, /* Status manager alarm state , */\
+ { 0x4060, "ISTTDMER"}, /* Status TDM error , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x4090, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x40a0, "ISTSPKS"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "ISTACS"}, /* Status cold started , */\
+ { 0x40c0, "ISTWDS"}, /* Status watchdog reset , */\
+ { 0x40d0, "ISTBODNOK"}, /* Status brown out detect , */\
+ { 0x40e0, "ISTLP1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "ISTCLKOOR"}, /* Status clock out of range , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOCPR"}, /* Clear OCP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLMANALARM"}, /* Clear manager alarm state , */\
+ { 0x4460, "ICLTDMER"}, /* Clear TDM error , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x4490, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x44a0, "ICLSPKS"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "ICLACS"}, /* Clear cold started , */\
+ { 0x44c0, "ICLWDS"}, /* Clear watchdog reset , */\
+ { 0x44d0, "ICLBODNOK"}, /* Clear brown out detect , */\
+ { 0x44e0, "ICLLP1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "ICLCLKOOR"}, /* Clear clock out of range , */\
+ { 0x4800, "IEVDDS"}, /* Enable POR , */\
+ { 0x4810, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOCPR"}, /* Enable OCP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IEMANALARM"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "IETDMER"}, /* Enable TDM error , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IECFMER"}, /* Enable cfma err , */\
+ { 0x4890, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x48a0, "IESPKS"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "IEACS"}, /* Enable cold started , */\
+ { 0x48c0, "IEWDS"}, /* Enable watchdog reset , */\
+ { 0x48d0, "IEBODNOK"}, /* Enable brown out detect , */\
+ { 0x48e0, "IELP1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "IECLKOOR"}, /* Enable clock out of range , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity POR , */\
+ { 0x4c10, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOMANALARM"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "IPOTDMER"}, /* Polarity TDM error , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4c90, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "IPOSPKS"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4cc0, "IPOWDS"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "IPOBODNOK"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "IPOLP1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "IPOCLKOOR"}, /* Polarity clock out of range , */\
+ { 0x5001, "BSSCR"}, /* Battery safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery safeguard release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery Safeguard hysteresis , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5130, "CFSM"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "VOL"}, /* CF firmware volume control , */\
+ { 0x5202, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5230, "SLOPEE"}, /* Enables slope control , */\
+ { 0x5240, "SLOPESET"}, /* Slope speed setting (binary coded) , */\
+ { 0x5250, "BYPDLYLINE"}, /* Bypass the interpolator delay line , */\
+ { 0x5287, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x5703, "TDMDCG"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "TDMSPKG"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "DCINSEL"}, /* VAMP_OUT2 input selection , */\
+ { 0x5881, "LNMODE"}, /* Low noise gain mode control , */\
+ { 0x5ac1, "LPM1MODE"}, /* Low power mode control , */\
+ { 0x5d02, "TDMSRCMAP"}, /* TDM source mapping , */\
+ { 0x5d31, "TDMSRCAS"}, /* Sensed value A , */\
+ { 0x5d51, "TDMSRCBS"}, /* Sensed value B , */\
+ { 0x5d71, "TDMSRCACLIP"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "TDMSRCBCLIP"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x6102, "DELCURCOMP"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "SIGCURCOMP"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "ENCURCOMP"}, /* Enable current sense compensation , */\
+ { 0x6152, "LVLCLPPWM"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "DCVOF"}, /* First Boost Voltage Level , */\
+ { 0x7065, "DCVOS"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "DCMCC"}, /* Max Coil Current , */\
+ { 0x7101, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7130, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x7140, "DCDIS"}, /* DCDC on/off , */\
+ { 0x7150, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7160, "DCTRACK"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "DCENVSEL"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7195, "OVSCTLVL"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7204, "DCTRIP"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "DCTRIP2"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "DCTRIPT"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "DCTRIPHYSTE"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "DCHOLD"}, /* Hold time / Hysteresis for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x9000, "RST"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "DMEM"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* CF memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* CF error flags , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa350, "CMTPI"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xca05, "PLLINSELI"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xca64, "PLLINSELP"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcab3, "PLLINSELR"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcb09, "PLLNDEC"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcba0, "PLLMDECMSB"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbb0, "PLLBYPASS"}, /* PLL bypass control during functional mode , */\
+ { 0xcbc0, "PLLDIRECTI"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbd0, "PLLDIRECTO"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbe0, "PLLFRMSTBL"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbf0, "PLLFRM"}, /* PLL free running mode control in functional mode , */\
+ { 0xcc0f, "PLLMDECLSB"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd06, "PLLPDEC"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd70, "DIRECTPLL"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xcd80, "DIRECTCLK"}, /* Enabled CGU clock divider direct control mode , */\
+ { 0xcd90, "PLLLIM"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xe00f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xe10f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "USERDEF"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "CUSTINFO"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf50f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9894N2_BITNAMETABLE static tfaBfName_t Tfa9894N2BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown control , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux DSP , */\
+ { 0x30, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Enable DCDC Boost converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux control over amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xa0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xb0, "test_ocp"}, /* OCP testing control , */\
+ { 0xc0, "batsense_steepness"}, /* Vbat protection steepness , */\
+ { 0xd0, "bypass_hp"}, /* Bypass High Pass Filter , */\
+ { 0xe0, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0xf0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x101, "vamp_sel1"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* Device I2C settings configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x150, "bod_enbl"}, /* Enable BOD (only in direct control mode) , */\
+ { 0x160, "bod_hyst_enbl"}, /* Enable Hysteresis of BOD , */\
+ { 0x171, "bod_delay_set"}, /* BOD filter , */\
+ { 0x191, "bod_lvl_set"}, /* BOD threshold , */\
+ { 0x1b0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1c0, "man_enbl_watchdog"}, /* Watchdog enable , */\
+ { 0x1d0, "disable_engage"}, /* Disable Engage , */\
+ { 0x1e0, "unprotect_faim"}, /* Control for FAIM protection , */\
+ { 0x1f0, "faim_enable_vbg"}, /* Overrule the enabling of VBG for faim erase/write access, */\
+ { 0x203, "audio_fs"}, /* Audio sample rate Fs , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* Current sense fractional delay , */\
+ { 0x2b1, "use_tdm_presence"}, /* Control for HW manager , */\
+ { 0x2d2, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external reference clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal reference clock , */\
+ { 0x432, "mclk_sel"}, /* Master Clock Selection , */\
+ { 0x460, "enbl_osc1m_auto_off"}, /* Internal OSC1M off at PWDN , */\
+ { 0x470, "disable_auto_sel_refclk"}, /* Automatic PLL reference clock selection for cold start, */\
+ { 0x480, "enbl_fs_sync"}, /* Enable FS synchronisation for clock divider , */\
+ { 0x490, "enbl_clkref_sync"}, /* Enable PLL reference clock synchronisation for clock divider, */\
+ { 0x4a0, "pll_slow_startup"}, /* PLL startup time configuration , */\
+ { 0x500, "disable_cgu_sync_cgate"}, /* Clock gating control for CGU synchronisation module, */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker sub-system , */\
+ { 0x520, "enbl_faim_ss"}, /* Enable FAIM sub-system , */\
+ { 0x530, "enbl_wdt_clk"}, /* Enable Coolflux watchdog clock , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* Hidden code to enable access to hidden register. (0x5A6B/23147 default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL Lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_ocp_alarm"}, /* OCP amplifier (sticky register, clear on read) , */\
+ { 0x1060, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1070, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1080, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10b0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD Flag - VDD NOT OK , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active (sticky register, clear on read) , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos (sticky register, clear on read) , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_cf_speakererror"}, /* Speaker status , */\
+ { 0x1180, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1190, "flag_man_alarm_state"}, /* Alarm state , */\
+ { 0x11a0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x11b0, "flag_tdm_lut_error"}, /* TDM lookup table error , */\
+ { 0x11c0, "flag_lost_audio_clk"}, /* Lost Audio clock , */\
+ { 0x1200, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1210, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1220, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1230, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1240, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x1250, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x1260, "flag_man_operating_state"}, /* Device in Operating state , */\
+ { 0x1270, "flag_lp_detect_mode1"}, /* Low power MODE1 detection , */\
+ { 0x1280, "flag_low_amplitude"}, /* Low amplitude detection , */\
+ { 0x1290, "flag_vddp_gt_vbat"}, /* VDDP greater than VBAT flag , */\
+ { 0x1302, "tdm_status"}, /* TDM Status bits , */\
+ { 0x1333, "man_state"}, /* Device Manager status , */\
+ { 0x1373, "amp_ctrl_state"}, /* Amplifier control status , */\
+ { 0x13b1, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage (1023*VDDP/13V) , */\
+ { 0x2000, "tdm_enable"}, /* Enable interface , */\
+ { 0x2010, "tdm_sink0_enable"}, /* Control audio tdm channel in sink0 , */\
+ { 0x2020, "tdm_sink1_enable"}, /* Control audio tdm channel in sink1 , */\
+ { 0x2030, "tdm_source0_enable"}, /* Source 0 enable , */\
+ { 0x2040, "tdm_source1_enable"}, /* Source 1 enable , */\
+ { 0x2050, "tdm_source2_enable"}, /* Source 2 enable , */\
+ { 0x2060, "tdm_source3_enable"}, /* Source 3 enable , */\
+ { 0x2070, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2080, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x2090, "tdm_data_delay"}, /* Data delay to FS , */\
+ { 0x20a0, "tdm_data_adjustment"}, /* Data adjustment , */\
+ { 0x20b1, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2103, "tdm_nbck"}, /* TDM NBCK - Bit clock to FS ratio , */\
+ { 0x2143, "tdm_fs_ws_length"}, /* FS length (master mode only) , */\
+ { 0x2183, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x21c1, "tdm_txdata_format"}, /* Format unused bits , */\
+ { 0x21e1, "tdm_txdata_format_unused_slot"}, /* Format unused slots DATAO , */\
+ { 0x2204, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2254, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x22a4, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2303, "tdm_sink0_slot"}, /* TDM slot for sink 0 , */\
+ { 0x2343, "tdm_sink1_slot"}, /* TDM slot for sink 1 , */\
+ { 0x2381, "tdm_source2_sel"}, /* TDM Source 2 data selection , */\
+ { 0x23a1, "tdm_source3_sel"}, /* TDM Source 3 data selection , */\
+ { 0x2403, "tdm_source0_slot"}, /* Slot position of source 0 data , */\
+ { 0x2443, "tdm_source1_slot"}, /* Slot position of source 1 data , */\
+ { 0x2483, "tdm_source2_slot"}, /* Slot position of source 2 data , */\
+ { 0x24c3, "tdm_source3_slot"}, /* Slot position of source 3 data , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ocp_alarm"}, /* Status OCP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_man_alarm_state"}, /* Status manager alarm state , */\
+ { 0x4060, "int_out_flag_tdm_error"}, /* Status TDM error , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x4090, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x40a0, "int_out_flag_cf_speakererror"}, /* Status coolflux speaker error , */\
+ { 0x40b0, "int_out_flag_cold_started"}, /* Status cold started , */\
+ { 0x40c0, "int_out_flag_watchdog_reset"}, /* Status watchdog reset , */\
+ { 0x40d0, "int_out_flag_bod_vddd_nok"}, /* Status brown out detect , */\
+ { 0x40e0, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 detect , */\
+ { 0x40f0, "int_out_flag_clk_out_of_range"}, /* Status clock out of range , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ocp_alarm"}, /* Clear OCP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_man_alarm_state"}, /* Clear manager alarm state , */\
+ { 0x4460, "int_in_flag_tdm_error"}, /* Clear TDM error , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x4490, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x44a0, "int_in_flag_cf_speakererror"}, /* Clear coolflux speaker error , */\
+ { 0x44b0, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44c0, "int_in_flag_watchdog_reset"}, /* Clear watchdog reset , */\
+ { 0x44d0, "int_in_flag_bod_vddd_nok"}, /* Clear brown out detect , */\
+ { 0x44e0, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 detect , */\
+ { 0x44f0, "int_in_flag_clk_out_of_range"}, /* Clear clock out of range , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable POR , */\
+ { 0x4810, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ocp_alarm"}, /* Enable OCP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_man_alarm_state"}, /* Enable Manager Alarm state , */\
+ { 0x4860, "int_enable_flag_tdm_error"}, /* Enable TDM error , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x4890, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x48a0, "int_enable_flag_cf_speakererror"}, /* Enable coolflux speaker error , */\
+ { 0x48b0, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48c0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog reset , */\
+ { 0x48d0, "int_enable_flag_bod_vddd_nok"}, /* Enable brown out detect , */\
+ { 0x48e0, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 detect , */\
+ { 0x48f0, "int_enable_flag_clk_out_of_range"}, /* Enable clock out of range , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity POR , */\
+ { 0x4c10, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_man_alarm_state"}, /* Polarity manager alarm state , */\
+ { 0x4c60, "int_polarity_flag_tdm_error"}, /* Polarity TDM error , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4c90, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4ca0, "int_polarity_flag_cf_speakererror"}, /* Polarity coolflux speaker error , */\
+ { 0x4cb0, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4cc0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog reset , */\
+ { 0x4cd0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity brown out detect , */\
+ { 0x4ce0, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 detect , */\
+ { 0x4cf0, "int_polarity_flag_clk_out_of_range"}, /* Polarity clock out of range , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery safeguard maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery safeguard release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5130, "cf_mute"}, /* Coolflux firmware soft mute control , */\
+ { 0x5187, "cf_volume"}, /* CF firmware volume control , */\
+ { 0x5202, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5230, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x5240, "ctrl_slope"}, /* Slope speed setting (binary coded) , */\
+ { 0x5250, "bypass_dly_line"}, /* Bypass the interpolator delay line , */\
+ { 0x5287, "gain"}, /* Amplifier gain , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for battery safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5370, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5380, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5390, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x53a3, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5400, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5413, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5452, "dpsa_drive"}, /* Drive setting (binary coded) , */\
+ { 0x550a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually, */\
+ { 0x55b0, "enbl_engage"}, /* Enables/engage power stage and control loop , */\
+ { 0x55c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5600, "pwm_shape"}, /* PWM shape , */\
+ { 0x5614, "pwm_delay"}, /* PWM delay bits to set the delay, clockd is 1/(k*2048*fs), */\
+ { 0x5660, "reclock_pwm"}, /* Reclock the PWM signal inside analog , */\
+ { 0x5670, "reclock_voltsense"}, /* Reclock the voltage sense PWM signal , */\
+ { 0x5680, "enbl_pwm_phase_shift"}, /* Control for PWM phase shift , */\
+ { 0x5690, "sel_pwm_delay_src"}, /* Control for selection for PWM delay line source , */\
+ { 0x56a1, "enbl_odd_up_even_down"}, /* Control for PWM reference sawtooth generartion , */\
+ { 0x5703, "ctrl_att_dcdc"}, /* Second channel gain in case of stereo using a single coil. (Total gain depending on INPLEV). (In case of mono OR stereo using 2 separate DCDC channel 1 should be disabled using TDMDCE), */\
+ { 0x5743, "ctrl_att_spkr"}, /* Total gain depending on INPLEV setting (channel 0), */\
+ { 0x5781, "vamp_sel2"}, /* VAMP_OUT2 input selection , */\
+ { 0x5805, "zero_lvl"}, /* Low noise gain switch zero trigger level , */\
+ { 0x5861, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x5881, "lownoisegain_mode"}, /* Low noise gain mode control , */\
+ { 0x5905, "threshold_lvl"}, /* Low noise gain switch trigger level , */\
+ { 0x5965, "hold_time"}, /* Low noise mode hold time before entering into low noise mode, */\
+ { 0x5a05, "lpm1_cal_offset"}, /* Low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x5a65, "lpm1_zero_lvl"}, /* Low power mode1 zero crossing detection level , */\
+ { 0x5ac1, "lpm1_mode"}, /* Low power mode control , */\
+ { 0x5b05, "lpm1_threshold_lvl"}, /* Low power mode1 amplitude trigger level , */\
+ { 0x5b65, "lpm1_hold_time"}, /* Low power mode hold time before entering into low power mode, */\
+ { 0x5bc0, "disable_low_power_mode"}, /* Low power mode1 detector control , */\
+ { 0x5c00, "enbl_minion"}, /* Enables minion (small) power stage , */\
+ { 0x5c13, "vth_vddpvbat"}, /* Select vddp-vbat threshold signal , */\
+ { 0x5c50, "lpen_vddpvbat"}, /* Select vddp-vbat filtred vs unfiltered compare , */\
+ { 0x5c61, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x5d02, "tdm_source_mapping"}, /* TDM source mapping , */\
+ { 0x5d31, "tdm_sourcea_frame_sel"}, /* Sensed value A , */\
+ { 0x5d51, "tdm_sourceb_frame_sel"}, /* Sensed value B , */\
+ { 0x5d71, "tdm_source0_clip_sel"}, /* Clip information (analog /digital) for source0 , */\
+ { 0x5d91, "tdm_source1_clip_sel"}, /* Clip information (analog /digital) for source1 , */\
+ { 0x5e02, "rst_min_vbat_delay"}, /* Delay for reseting the min_vbat value inside HW Clipper (number of Fs pulses), */\
+ { 0x5e30, "rst_min_vbat_sel"}, /* Control for selecting reset signal for min_bat , */\
+ { 0x5f00, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5f12, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x5f42, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x5f78, "spare_out"}, /* Spare out register , */\
+ { 0x600f, "spare_in"}, /* Spare IN , */\
+ { 0x6102, "cursense_comp_delay"}, /* Delay to allign compensation signal with current sense signal, */\
+ { 0x6130, "cursense_comp_sign"}, /* Polarity of compensation for current sense , */\
+ { 0x6140, "enbl_cursense_comp"}, /* Enable current sense compensation , */\
+ { 0x6152, "pwms_clip_lvl"}, /* Set the amount of pwm pulse that may be skipped before clip-flag is triggered, */\
+ { 0x7005, "frst_boost_voltage"}, /* First Boost Voltage Level , */\
+ { 0x7065, "scnd_boost_voltage"}, /* Second Boost Voltage Level , */\
+ { 0x70c3, "boost_cur"}, /* Max Coil Current , */\
+ { 0x7101, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7120, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7130, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x7140, "dcdcoff_mode"}, /* DCDC on/off , */\
+ { 0x7150, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7160, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7170, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x7180, "ignore_flag_voutcomp86"}, /* Determines the maximum PWM frequency be the most efficient in relation to the Booster inductor value, */\
+ { 0x7195, "overshoot_correction_lvl"}, /* Threshold level to activate active overshoot control, */\
+ { 0x7204, "boost_trip_lvl_1st"}, /* 1st adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x7254, "boost_trip_lvl_2nd"}, /* 2nd adaptive boost trip levels, effective only when DCIE is set to 1, */\
+ { 0x72a4, "boost_trip_lvl_track"}, /* Track adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x72f0, "enbl_trip_hyst"}, /* Enable hysteresis on booster trip levels , */\
+ { 0x7304, "boost_hold_time"}, /* Hold time / Hysteresis for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x7350, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x7361, "dcdc_ctrl_maxzercnt"}, /* Number of zero current flags to count before going to pfm mode, */\
+ { 0x7386, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x73f0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x7404, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7451, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7474, "bst_slopecur"}, /* For testing direct control slope current , */\
+ { 0x74c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x74e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x74f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7500, "enbl_bst_engage"}, /* Enable power stage dcdc controller , */\
+ { 0x7510, "enbl_bst_hizcom"}, /* Enable hiz comparator , */\
+ { 0x7520, "enbl_bst_peakcur"}, /* Enable peak current , */\
+ { 0x7530, "enbl_bst_power"}, /* Enable line of the powerstage , */\
+ { 0x7540, "enbl_bst_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x7550, "enbl_bst_voutcomp"}, /* Enable vout comparators , */\
+ { 0x7560, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x7570, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x7580, "enbl_bst_windac"}, /* Enable window dac , */\
+ { 0x7595, "bst_windac"}, /* For testing direct control windac , */\
+ { 0x7600, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7611, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7631, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7650, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7660, "bst_use_new_zercur_detect"}, /* Enable new zero current detection for boost control, */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8040, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8050, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8060, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8105, "cs_ktemp"}, /* Current sense temperature compensation trimming (1 - VALUE*TEMP) * signal, */\
+ { 0x8164, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x81b0, "enbl_cs_adc"}, /* Enable current sense ADC , */\
+ { 0x81c0, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 , */\
+ { 0x81d0, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 , */\
+ { 0x81e0, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x81f0, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 , */\
+ { 0x8200, "enbl_cs_ldo"}, /* Enable current sense LDO , */\
+ { 0x8210, "enbl_cs_vbatldo"}, /* Enable of current sense LDO , */\
+ { 0x8220, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8231, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8250, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x8263, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x82a0, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x82b4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8300, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8310, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8320, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8330, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8340, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8350, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8364, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8800, "ctrl_vs_igen_supply"}, /* Control for selecting supply for VS current generator, */\
+ { 0x8810, "ctrl_vs_force_div2"}, /* Select input resistive divider gain , */\
+ { 0x8820, "enbl_dc_filter"}, /* Control for enabling the DC blocking filter for voltage and current sense, */\
+ { 0x8901, "volsense_pwm_sel"}, /* Voltage sense source selection control , */\
+ { 0x8920, "vs_gain_control"}, /* Voltage sense gain control , */\
+ { 0x8930, "vs_bypass_gc"}, /* Bypasses the VS gain correction , */\
+ { 0x8940, "vs_adc_bsoinv"}, /* Bitstream inversion for voltage sense ADC , */\
+ { 0x8950, "vs_adc_nortz"}, /* Return to zero for voltage sense ADC , */\
+ { 0x8960, "vs_adc_slowdel"}, /* Select delay for voltage sense ADC (internal decision circuitry), */\
+ { 0x8970, "vs_classd_tran_skip"}, /* Skip voltage sense connection during a classD amplifier transition, */\
+ { 0x8987, "vs_gain"}, /* Voltage sense gain , */\
+ { 0x8a00, "vs_inn_short"}, /* Short voltage sense negative to common mode , */\
+ { 0x8a10, "vs_inp_short"}, /* Short voltage sense positive to common mode , */\
+ { 0x8a20, "vs_ldo_bypass"}, /* Bypass voltage sense LDO , */\
+ { 0x8a30, "vs_ldo_pulldown"}, /* Pull down voltage sense LDO, only valid if enbl_cs_ldo is high, */\
+ { 0x8a44, "vs_ldo_voset"}, /* Voltage sense LDO voltage level setting (two's complement), */\
+ { 0x8a90, "enbl_vs_adc"}, /* Enable voltage sense ADC , */\
+ { 0x8aa0, "enbl_vs_inn1"}, /* Enable connection of voltage sense negative1 , */\
+ { 0x8ab0, "enbl_vs_inn2"}, /* Enable connection of voltage sense negative2 , */\
+ { 0x8ac0, "enbl_vs_inp1"}, /* Enable connection of voltage sense positive1 , */\
+ { 0x8ad0, "enbl_vs_inp2"}, /* Enable connection of voltage sense positive2 , */\
+ { 0x8ae0, "enbl_vs_ldo"}, /* Enable voltage sense LDO , */\
+ { 0x8af0, "enbl_vs_vbatldo"}, /* Enable of voltage sense LDO , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset for Coolflux DSP , */\
+ { 0x9011, "cf_dmem"}, /* Target memory for CFMA using I2C interface , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Coolflux Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* CF memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* CF error flags , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0xa007, "mtpkey1"}, /* KEY1 To access KEY1 protected registers 0x5A/90d (default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* KEY2 to access KEY2 protected registers, customer key, */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from MTP to I2C mtp register - auto clear, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp - auto clear, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers - auto clear, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp - auto clear, */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the FaIM controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the FaIM are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the FaIM are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb000, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb010, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb020, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb030, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb040, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb050, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb060, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb070, "disable_main_ctrl_change_prot"}, /* Disable main control change protection , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually, */\
+ { 0xc0c0, "use_direct_vs_ctrls"}, /* Voltage sense direct control to overrule several functions for testing, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "enbl_pll"}, /* Enables PLL in I2C direct control mode only , */\
+ { 0xc0f0, "enbl_osc"}, /* Enables OSC in I2C direct control mode only , */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* Enable ABIST with FFT on Coolflux DSP , */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost Converter Over Current Protection , */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc530, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc540, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc550, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc560, "test_enbl_vs"}, /* Enable for digimux mode of voltage sense , */\
+ { 0xc570, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc583, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc5c0, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc607, "digimuxa_sel"}, /* DigimuxA input selection control routed to DATAO , */\
+ { 0xc687, "digimuxb_sel"}, /* DigimuxB input selection control routed to INT , */\
+ { 0xc707, "digimuxc_sel"}, /* DigimuxC input selection control routed to ADS1 , */\
+ { 0xc800, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xc810, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xc820, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xc830, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xc844, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xc894, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xc903, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xc943, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xca05, "pll_inseli"}, /* PLL INSELI - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xca64, "pll_inselp"}, /* PLL INSELP - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcab3, "pll_inselr"}, /* PLL INSELR - PLL direct bandwidth control mode only with pll_bandsel set to 1, */\
+ { 0xcaf0, "pll_bandsel"}, /* PLL bandwidth selection control, USE WITH CAUTION , */\
+ { 0xcb09, "pll_ndec"}, /* PLL NDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcba0, "pll_mdec_msb"}, /* MSB of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbb0, "pll_bypass"}, /* PLL bypass control during functional mode , */\
+ { 0xcbc0, "pll_directi"}, /* PLL directi control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbd0, "pll_directo"}, /* PLL directo control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbe0, "pll_frm_clockstable"}, /* PLL FRM clock stable control in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcbf0, "pll_frm"}, /* PLL free running mode control in functional mode , */\
+ { 0xcc0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd06, "pll_pdec"}, /* PLL PDEC in direct control mode only, use_direct_pll_ctrl set to 1, */\
+ { 0xcd70, "use_direct_pll_ctrl"}, /* Enabled PLL direct control mode, overrules the PLL LUT with I2C register values, */\
+ { 0xcd80, "use_direct_clk_ctrl"}, /* Enabled CGU clock divider direct control mode , */\
+ { 0xcd90, "pll_limup_off"}, /* PLL up limiter control in PLL direct bandwidth control mode, pll_bandsel set to 1, */\
+ { 0xce0f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xcf02, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xcf33, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd000, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd011, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd032, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd064, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd0b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd0c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd109, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd201, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd301, "int_ehs"}, /* Speed/load setting for INT IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd321, "datao_ehs"}, /* Speed/load setting for DATAO IO cell, clk or data mode range (see SLIMMF IO datasheet), */\
+ { 0xd340, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xd407, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd480, "enbl_clk_out_of_range"}, /* Clock out of range , */\
+ { 0xd491, "sel_wdt_clk"}, /* Watch dog clock divider settings , */\
+ { 0xd4b0, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd500, "source_in_testmode"}, /* TDM source in test mode (return only current and voltage sense), */\
+ { 0xd510, "gainatt_feedback"}, /* Gainatt feedback to tdm , */\
+ { 0xd522, "test_parametric_io"}, /* Test IO parametric , */\
+ { 0xd550, "ctrl_bst_clk_lp1"}, /* Boost clock control in low power mode1 , */\
+ { 0xd561, "test_spare_out1"}, /* Test spare out 1 , */\
+ { 0xd580, "bst_dcmbst"}, /* DCM boost , */\
+ { 0xd593, "test_spare_out2"}, /* Test spare out 2 , */\
+ { 0xe00f, "sw_profile"}, /* Software profile data , */\
+ { 0xe10f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf307, "calibr_gain_vs"}, /* Voltage sense gain , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "mtpdata4"}, /* MTP4 data , */\
+ { 0xf50f, "calibr_R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xf60f, "mtpdata6"}, /* MTP6 data , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf900, "mtp_lock_dcdcoff_mode"}, /* Disable functionality of dcdcoff_mode bit , */\
+ { 0xf910, "mtp_lock_enbl_coolflux"}, /* Disable functionality of enbl_coolflux bit , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_enbl_pwm_delay_clock_gating"}, /* PWM delay clock auto gating , */\
+ { 0xf940, "mtp_enbl_ocp_clock_gating"}, /* OCP clock auto gating , */\
+ { 0xf987, "type_bits_fw"}, /* MTP control for firmware features - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE , */\
+ { 0xff07, "calibr_osc_delta_ndiv"}, /* Calibration data for OSC1M, signed number representation, */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+#if 0
+enum tfa9894_irq {
+ tfa9894_irq_max = -1,
+ tfa9894_irq_all = -1 /* all irqs */};
+#endif//
+#define TFA9894_IRQ_NAMETABLE static tfaIrqName_t Tfa9894IrqNames[]= {\
+};
+#endif /* _TFA9894_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9896_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9896_tfafieldnames.h
new file mode 100644
index 00000000000..e1583a0ddb7
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9896_tfafieldnames.h
@@ -0,0 +1,930 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9896_tfafieldnames.h
+ * This file was generated automatically on 08/15/16 at 09:43:38.
+ * Source file: TFA9896_N1B1_I2C_regmap_V16.xlsx
+ */
+
+#ifndef _TFA9896_TFAFIELDNAMES_H
+#define _TFA9896_TFAFIELDNAMES_H
+
+
+#define TFA9896_I2CVERSION 16
+
+typedef enum TFA9896BfEnumList {
+ TFA9896_BF_VDDS = 0x0000, /*!< Power-on-reset flag (auto clear by reading) */
+ TFA9896_BF_PLLS = 0x0010, /*!< PLL lock to programmed frequency */
+ TFA9896_BF_OTDS = 0x0020, /*!< Over Temperature Protection alarm */
+ TFA9896_BF_OVDS = 0x0030, /*!< Over Voltage Protection alarm */
+ TFA9896_BF_UVDS = 0x0040, /*!< Under Voltage Protection alarm */
+ TFA9896_BF_OCDS = 0x0050, /*!< Over Current Protection alarm */
+ TFA9896_BF_CLKS = 0x0060, /*!< Clocks stable flag */
+ TFA9896_BF_CLIPS = 0x0070, /*!< Amplifier clipping */
+ TFA9896_BF_MTPB = 0x0080, /*!< MTP busy copying data to/from I2C registers */
+ TFA9896_BF_NOCLK = 0x0090, /*!< lost clock detection (reference input clock) */
+ TFA9896_BF_SPKS = 0x00a0, /*!< Speaker error */
+ TFA9896_BF_ACS = 0x00b0, /*!< Cold Start required */
+ TFA9896_BF_SWS = 0x00c0, /*!< Amplifier engage (Amp Switching) */
+ TFA9896_BF_WDS = 0x00d0, /*!< watchdog reset (activates reset) */
+ TFA9896_BF_AMPS = 0x00e0, /*!< Amplifier is enabled by manager */
+ TFA9896_BF_AREFS = 0x00f0, /*!< References are enabled by manager */
+ TFA9896_BF_BATS = 0x0109, /*!< Battery voltage from ADC readout */
+ TFA9896_BF_TEMPS = 0x0208, /*!< Temperature readout from the temperature sensor ( C) */
+ TFA9896_BF_REV = 0x030f, /*!< Device revision information */
+ TFA9896_BF_RCV = 0x0420, /*!< Enable receiver mode */
+ TFA9896_BF_CHS12 = 0x0431, /*!< Channel Selection TDM input for Coolflux */
+ TFA9896_BF_INPLVL= 0x0450, /*!< Input level selection attenuator ( */
+ TFA9896_BF_CHSA = 0x0461, /*!< Input selection for amplifier */
+ TFA9896_BF_AUDFS = 0x04c3, /*!< Audio sample rate setting */
+ TFA9896_BF_BSSCR = 0x0501, /*!< Batteery protection attack time */
+ TFA9896_BF_BSST = 0x0523, /*!< Battery protection threshold level */
+ TFA9896_BF_BSSRL = 0x0561, /*!< Battery protection maximum reduction */
+ TFA9896_BF_BSSRR = 0x0582, /*!< Battery protection release time */
+ TFA9896_BF_BSSHY = 0x05b1, /*!< Battery Protection Hysteresis */
+ TFA9896_BF_BSSR = 0x05e0, /*!< Battery voltage value for read out (only) */
+ TFA9896_BF_BSSBY = 0x05f0, /*!< Bypass clipper battery protection */
+ TFA9896_BF_DPSA = 0x0600, /*!< Enable dynamic powerstage activation (DPSA) */
+ TFA9896_BF_ATTEN = 0x0613, /*!< Gain attenuation setting */
+ TFA9896_BF_CFSM = 0x0650, /*!< Soft mute in CoolFlux */
+ TFA9896_BF_BSSS = 0x0670, /*!< Battery sense steepness */
+ TFA9896_BF_VOL = 0x0687, /*!< Coolflux volume control */
+ TFA9896_BF_DCVO2 = 0x0702, /*!< Second Boost Voltage */
+ TFA9896_BF_DCMCC = 0x0733, /*!< Max boost coil current - step of 175 mA */
+ TFA9896_BF_DCVO1 = 0x0772, /*!< First Boost Voltage */
+ TFA9896_BF_DCIE = 0x07a0, /*!< Adaptive boost mode */
+ TFA9896_BF_DCSR = 0x07b0, /*!< Soft Rampup/down mode for DCDC controller */
+ TFA9896_BF_DCPAVG= 0x07c0, /*!< ctrl_peak2avg for analog part of DCDC */
+ TFA9896_BF_DCPWM = 0x07d0, /*!< DCDC PWM only mode */
+ TFA9896_BF_TROS = 0x0800, /*!< Selection ambient temperature for speaker calibration */
+ TFA9896_BF_EXTTS = 0x0818, /*!< External temperature for speaker calibration (C) */
+ TFA9896_BF_PWDN = 0x0900, /*!< powerdown selection */
+ TFA9896_BF_I2CR = 0x0910, /*!< All I2C registers reset to default */
+ TFA9896_BF_CFE = 0x0920, /*!< Enable CoolFlux */
+ TFA9896_BF_AMPE = 0x0930, /*!< Enable Amplifier */
+ TFA9896_BF_DCA = 0x0940, /*!< Enable DCDC Boost converter */
+ TFA9896_BF_SBSL = 0x0950, /*!< Coolflux configured */
+ TFA9896_BF_AMPC = 0x0960, /*!< Selection if Coolflux enables amplifier */
+ TFA9896_BF_DCDIS = 0x0970, /*!< DCDC boost converter not connected */
+ TFA9896_BF_PSDR = 0x0980, /*!< IDDQ amplifier test selection */
+ TFA9896_BF_INTPAD= 0x09c1, /*!< INT pad (interrupt bump output) configuration */
+ TFA9896_BF_IPLL = 0x09e0, /*!< PLL input reference clock selection */
+ TFA9896_BF_DCTRIP= 0x0a04, /*!< Adaptive boost trip levels (effective only when boost_intel is set to 1) */
+ TFA9896_BF_DCHOLD= 0x0a54, /*!< Hold time for DCDC booster (effective only when boost_intel is set to 1) */
+ TFA9896_BF_MTPK = 0x0b07, /*!< KEY2 to access key2 protected registers (default for engineering) */
+ TFA9896_BF_CVFDLY= 0x0c25, /*!< Fractional delay adjustment between current and voltage sense */
+ TFA9896_BF_OPENMTP= 0x0ec0, /*!< Enable programming of the MTP memory */
+ TFA9896_BF_TDMPRF= 0x1011, /*!< TDM usecase selection control */
+ TFA9896_BF_TDMEN = 0x1030, /*!< TDM interface enable */
+ TFA9896_BF_TDMCKINV= 0x1040, /*!< TDM clock inversion, receive on */
+ TFA9896_BF_TDMFSLN= 0x1053, /*!< TDM FS length */
+ TFA9896_BF_TDMFSPOL= 0x1090, /*!< TDM FS polarity (start frame) */
+ TFA9896_BF_TDMSAMSZ= 0x10a4, /*!< TDM sample size for all TDM sinks and sources */
+ TFA9896_BF_TDMSLOTS= 0x1103, /*!< TDM number of slots */
+ TFA9896_BF_TDMSLLN= 0x1144, /*!< TDM slot length */
+ TFA9896_BF_TDMBRMG= 0x1194, /*!< TDM bits remaining after the last slot */
+ TFA9896_BF_TDMDDEL= 0x11e0, /*!< TDM data delay */
+ TFA9896_BF_TDMDADJ= 0x11f0, /*!< TDM data adjustment */
+ TFA9896_BF_TDMTXFRM= 0x1201, /*!< TDM TXDATA format */
+ TFA9896_BF_TDMUUS0= 0x1221, /*!< TDM TXDATA format unused slot SD0 */
+ TFA9896_BF_TDMUUS1= 0x1241, /*!< TDM TXDATA format unused slot SD1 */
+ TFA9896_BF_TDMSI0EN= 0x1270, /*!< TDM sink0 enable */
+ TFA9896_BF_TDMSI1EN= 0x1280, /*!< TDM sink1 enable */
+ TFA9896_BF_TDMSI2EN= 0x1290, /*!< TDM sink2 enable */
+ TFA9896_BF_TDMSO0EN= 0x12a0, /*!< TDM source0 enable */
+ TFA9896_BF_TDMSO1EN= 0x12b0, /*!< TDM source1 enable */
+ TFA9896_BF_TDMSO2EN= 0x12c0, /*!< TDM source2 enable */
+ TFA9896_BF_TDMSI0IO= 0x12d0, /*!< TDM sink0 IO selection */
+ TFA9896_BF_TDMSI1IO= 0x12e0, /*!< TDM sink1 IO selection */
+ TFA9896_BF_TDMSI2IO= 0x12f0, /*!< TDM sink2 IO selection */
+ TFA9896_BF_TDMSO0IO= 0x1300, /*!< TDM source0 IO selection */
+ TFA9896_BF_TDMSO1IO= 0x1310, /*!< TDM source1 IO selection */
+ TFA9896_BF_TDMSO2IO= 0x1320, /*!< TDM source2 IO selection */
+ TFA9896_BF_TDMSI0SL= 0x1333, /*!< TDM sink0 slot position [GAIN IN] */
+ TFA9896_BF_TDMSI1SL= 0x1373, /*!< TDM sink1 slot position [CH1 IN] */
+ TFA9896_BF_TDMSI2SL= 0x13b3, /*!< TDM sink2 slot position [CH2 IN] */
+ TFA9896_BF_TDMSO0SL= 0x1403, /*!< TDM source0 slot position [GAIN OUT] */
+ TFA9896_BF_TDMSO1SL= 0x1443, /*!< TDM source1 slot position [Voltage Sense] */
+ TFA9896_BF_TDMSO2SL= 0x1483, /*!< TDM source2 slot position [Current Sense] */
+ TFA9896_BF_NBCK = 0x14c3, /*!< TDM NBCK bit clock ratio */
+ TFA9896_BF_INTOVDDS= 0x2000, /*!< flag_por_int_out */
+ TFA9896_BF_INTOPLLS= 0x2010, /*!< flag_pll_lock_int_out */
+ TFA9896_BF_INTOOTDS= 0x2020, /*!< flag_otpok_int_out */
+ TFA9896_BF_INTOOVDS= 0x2030, /*!< flag_ovpok_int_out */
+ TFA9896_BF_INTOUVDS= 0x2040, /*!< flag_uvpok_int_out */
+ TFA9896_BF_INTOOCDS= 0x2050, /*!< flag_ocp_alarm_int_out */
+ TFA9896_BF_INTOCLKS= 0x2060, /*!< flag_clocks_stable_int_out */
+ TFA9896_BF_INTOCLIPS= 0x2070, /*!< flag_clip_int_out */
+ TFA9896_BF_INTOMTPB= 0x2080, /*!< mtp_busy_int_out */
+ TFA9896_BF_INTONOCLK= 0x2090, /*!< flag_lost_clk_int_out */
+ TFA9896_BF_INTOSPKS= 0x20a0, /*!< flag_cf_speakererror_int_out */
+ TFA9896_BF_INTOACS= 0x20b0, /*!< flag_cold_started_int_out */
+ TFA9896_BF_INTOSWS= 0x20c0, /*!< flag_engage_int_out */
+ TFA9896_BF_INTOWDS= 0x20d0, /*!< flag_watchdog_reset_int_out */
+ TFA9896_BF_INTOAMPS= 0x20e0, /*!< flag_enbl_amp_int_out */
+ TFA9896_BF_INTOAREFS= 0x20f0, /*!< flag_enbl_ref_int_out */
+ TFA9896_BF_INTOERR= 0x2200, /*!< flag_cfma_err_int_out */
+ TFA9896_BF_INTOACK= 0x2210, /*!< flag_cfma_ack_int_out */
+ TFA9896_BF_INTIVDDS= 0x2300, /*!< flag_por_int_in */
+ TFA9896_BF_INTIPLLS= 0x2310, /*!< flag_pll_lock_int_in */
+ TFA9896_BF_INTIOTDS= 0x2320, /*!< flag_otpok_int_in */
+ TFA9896_BF_INTIOVDS= 0x2330, /*!< flag_ovpok_int_in */
+ TFA9896_BF_INTIUVDS= 0x2340, /*!< flag_uvpok_int_in */
+ TFA9896_BF_INTIOCDS= 0x2350, /*!< flag_ocp_alarm_int_in */
+ TFA9896_BF_INTICLKS= 0x2360, /*!< flag_clocks_stable_int_in */
+ TFA9896_BF_INTICLIPS= 0x2370, /*!< flag_clip_int_in */
+ TFA9896_BF_INTIMTPB= 0x2380, /*!< mtp_busy_int_in */
+ TFA9896_BF_INTINOCLK= 0x2390, /*!< flag_lost_clk_int_in */
+ TFA9896_BF_INTISPKS= 0x23a0, /*!< flag_cf_speakererror_int_in */
+ TFA9896_BF_INTIACS= 0x23b0, /*!< flag_cold_started_int_in */
+ TFA9896_BF_INTISWS= 0x23c0, /*!< flag_engage_int_in */
+ TFA9896_BF_INTIWDS= 0x23d0, /*!< flag_watchdog_reset_int_in */
+ TFA9896_BF_INTIAMPS= 0x23e0, /*!< flag_enbl_amp_int_in */
+ TFA9896_BF_INTIAREFS= 0x23f0, /*!< flag_enbl_ref_int_in */
+ TFA9896_BF_INTIERR= 0x2500, /*!< flag_cfma_err_int_in */
+ TFA9896_BF_INTIACK= 0x2510, /*!< flag_cfma_ack_int_in */
+ TFA9896_BF_INTENVDDS= 0x2600, /*!< flag_por_int_enable */
+ TFA9896_BF_INTENPLLS= 0x2610, /*!< flag_pll_lock_int_enable */
+ TFA9896_BF_INTENOTDS= 0x2620, /*!< flag_otpok_int_enable */
+ TFA9896_BF_INTENOVDS= 0x2630, /*!< flag_ovpok_int_enable */
+ TFA9896_BF_INTENUVDS= 0x2640, /*!< flag_uvpok_int_enable */
+ TFA9896_BF_INTENOCDS= 0x2650, /*!< flag_ocp_alarm_int_enable */
+ TFA9896_BF_INTENCLKS= 0x2660, /*!< flag_clocks_stable_int_enable */
+ TFA9896_BF_INTENCLIPS= 0x2670, /*!< flag_clip_int_enable */
+ TFA9896_BF_INTENMTPB= 0x2680, /*!< mtp_busy_int_enable */
+ TFA9896_BF_INTENNOCLK= 0x2690, /*!< flag_lost_clk_int_enable */
+ TFA9896_BF_INTENSPKS= 0x26a0, /*!< flag_cf_speakererror_int_enable */
+ TFA9896_BF_INTENACS= 0x26b0, /*!< flag_cold_started_int_enable */
+ TFA9896_BF_INTENSWS= 0x26c0, /*!< flag_engage_int_enable */
+ TFA9896_BF_INTENWDS= 0x26d0, /*!< flag_watchdog_reset_int_enable */
+ TFA9896_BF_INTENAMPS= 0x26e0, /*!< flag_enbl_amp_int_enable */
+ TFA9896_BF_INTENAREFS= 0x26f0, /*!< flag_enbl_ref_int_enable */
+ TFA9896_BF_INTENERR= 0x2800, /*!< flag_cfma_err_int_enable */
+ TFA9896_BF_INTENACK= 0x2810, /*!< flag_cfma_ack_int_enable */
+ TFA9896_BF_INTPOLVDDS= 0x2900, /*!< flag_por_int_pol */
+ TFA9896_BF_INTPOLPLLS= 0x2910, /*!< flag_pll_lock_int_pol */
+ TFA9896_BF_INTPOLOTDS= 0x2920, /*!< flag_otpok_int_pol */
+ TFA9896_BF_INTPOLOVDS= 0x2930, /*!< flag_ovpok_int_pol */
+ TFA9896_BF_INTPOLUVDS= 0x2940, /*!< flag_uvpok_int_pol */
+ TFA9896_BF_INTPOLOCDS= 0x2950, /*!< flag_ocp_alarm_int_pol */
+ TFA9896_BF_INTPOLCLKS= 0x2960, /*!< flag_clocks_stable_int_pol */
+ TFA9896_BF_INTPOLCLIPS= 0x2970, /*!< flag_clip_int_pol */
+ TFA9896_BF_INTPOLMTPB= 0x2980, /*!< mtp_busy_int_pol */
+ TFA9896_BF_INTPOLNOCLK= 0x2990, /*!< flag_lost_clk_int_pol */
+ TFA9896_BF_INTPOLSPKS= 0x29a0, /*!< flag_cf_speakererror_int_pol */
+ TFA9896_BF_INTPOLACS= 0x29b0, /*!< flag_cold_started_int_pol */
+ TFA9896_BF_INTPOLSWS= 0x29c0, /*!< flag_engage_int_pol */
+ TFA9896_BF_INTPOLWDS= 0x29d0, /*!< flag_watchdog_reset_int_pol */
+ TFA9896_BF_INTPOLAMPS= 0x29e0, /*!< flag_enbl_amp_int_pol */
+ TFA9896_BF_INTPOLAREFS= 0x29f0, /*!< flag_enbl_ref_int_pol */
+ TFA9896_BF_INTPOLERR= 0x2b00, /*!< flag_cfma_err_int_pol */
+ TFA9896_BF_INTPOLACK= 0x2b10, /*!< flag_cfma_ack_int_pol */
+ TFA9896_BF_CLIP = 0x4900, /*!< Bypass clip control */
+ TFA9896_BF_CIMTP = 0x62b0, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9896_BF_RST = 0x7000, /*!< Reset CoolFlux DSP */
+ TFA9896_BF_DMEM = 0x7011, /*!< Target memory for access */
+ TFA9896_BF_AIF = 0x7030, /*!< Auto increment flag for memory-address */
+ TFA9896_BF_CFINT = 0x7040, /*!< CF Interrupt - auto clear */
+ TFA9896_BF_REQ = 0x7087, /*!< CF request for accessing the 8 channels */
+ TFA9896_BF_MADD = 0x710f, /*!< Memory address */
+ TFA9896_BF_MEMA = 0x720f, /*!< Activate memory access */
+ TFA9896_BF_ERR = 0x7307, /*!< CF error flags */
+ TFA9896_BF_ACK = 0x7387, /*!< CF acknowledgement of the requests channels */
+ TFA9896_BF_MTPOTC= 0x8000, /*!< Calibration schedule selection */
+ TFA9896_BF_MTPEX = 0x8010, /*!< Calibration of RON status bit */
+} TFA9896BfEnumList_t;
+#define TFA9896_NAMETABLE static tfaBfName_t Tfa9896DatasheetNames[]= {\
+ { 0x0, "VDDS"}, /* Power-on-reset flag (auto clear by reading) , */\
+ { 0x10, "PLLS"}, /* PLL lock to programmed frequency , */\
+ { 0x20, "OTDS"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "OVDS"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "UVDS"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "OCDS"}, /* Over Current Protection alarm , */\
+ { 0x60, "CLKS"}, /* Clocks stable flag , */\
+ { 0x70, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x80, "MTPB"}, /* MTP busy copying data to/from I2C registers , */\
+ { 0x90, "NOCLK"}, /* lost clock detection (reference input clock) , */\
+ { 0xa0, "SPKS"}, /* Speaker error , */\
+ { 0xb0, "ACS"}, /* Cold Start required , */\
+ { 0xc0, "SWS"}, /* Amplifier engage (Amp Switching) , */\
+ { 0xd0, "WDS"}, /* watchdog reset (activates reset) , */\
+ { 0xe0, "AMPS"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "AREFS"}, /* References are enabled by manager , */\
+ { 0x109, "BATS"}, /* Battery voltage from ADC readout , */\
+ { 0x208, "TEMPS"}, /* Temperature readout from the temperature sensor ( C), */\
+ { 0x30f, "REV"}, /* Device revision information , */\
+ { 0x420, "RCV"}, /* Enable receiver mode , */\
+ { 0x431, "CHS12"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "INPLVL"}, /* Input level selection attenuator ( , */\
+ { 0x461, "CHSA"}, /* Input selection for amplifier , */\
+ { 0x4c3, "AUDFS"}, /* Audio sample rate setting , */\
+ { 0x501, "BSSCR"}, /* Batteery protection attack time , */\
+ { 0x523, "BSST"}, /* Battery protection threshold level , */\
+ { 0x561, "BSSRL"}, /* Battery protection maximum reduction , */\
+ { 0x582, "BSSRR"}, /* Battery protection release time , */\
+ { 0x5b1, "BSSHY"}, /* Battery Protection Hysteresis , */\
+ { 0x5e0, "BSSR"}, /* Battery voltage value for read out (only) , */\
+ { 0x5f0, "BSSBY"}, /* Bypass clipper battery protection , */\
+ { 0x600, "DPSA"}, /* Enable dynamic powerstage activation (DPSA) , */\
+ { 0x613, "ATTEN"}, /* Gain attenuation setting , */\
+ { 0x650, "CFSM"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "BSSS"}, /* Battery sense steepness , */\
+ { 0x687, "VOL"}, /* Coolflux volume control , */\
+ { 0x702, "DCVO2"}, /* Second Boost Voltage , */\
+ { 0x733, "DCMCC"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x772, "DCVO1"}, /* First Boost Voltage , */\
+ { 0x7a0, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x7b0, "DCSR"}, /* Soft Rampup/down mode for DCDC controller , */\
+ { 0x7c0, "DCPAVG"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x7d0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x800, "TROS"}, /* Selection ambient temperature for speaker calibration , */\
+ { 0x818, "EXTTS"}, /* External temperature for speaker calibration (C) , */\
+ { 0x900, "PWDN"}, /* powerdown selection , */\
+ { 0x910, "I2CR"}, /* All I2C registers reset to default , */\
+ { 0x920, "CFE"}, /* Enable CoolFlux , */\
+ { 0x930, "AMPE"}, /* Enable Amplifier , */\
+ { 0x940, "DCA"}, /* Enable DCDC Boost converter , */\
+ { 0x950, "SBSL"}, /* Coolflux configured , */\
+ { 0x960, "AMPC"}, /* Selection if Coolflux enables amplifier , */\
+ { 0x970, "DCDIS"}, /* DCDC boost converter not connected , */\
+ { 0x980, "PSDR"}, /* IDDQ amplifier test selection , */\
+ { 0x9c1, "INTPAD"}, /* INT pad (interrupt bump output) configuration , */\
+ { 0x9e0, "IPLL"}, /* PLL input reference clock selection , */\
+ { 0xa04, "DCTRIP"}, /* Adaptive boost trip levels (effective only when boost_intel is set to 1), */\
+ { 0xa54, "DCHOLD"}, /* Hold time for DCDC booster (effective only when boost_intel is set to 1), */\
+ { 0xb07, "MTPK"}, /* KEY2 to access key2 protected registers (default for engineering), */\
+ { 0xc25, "CVFDLY"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0xec0, "OPENMTP"}, /* Enable programming of the MTP memory , */\
+ { 0x1011, "TDMPRF"}, /* TDM usecase selection control , */\
+ { 0x1030, "TDMEN"}, /* TDM interface enable , */\
+ { 0x1040, "TDMCKINV"}, /* TDM clock inversion, receive on , */\
+ { 0x1053, "TDMFSLN"}, /* TDM FS length , */\
+ { 0x1090, "TDMFSPOL"}, /* TDM FS polarity (start frame) , */\
+ { 0x10a4, "TDMSAMSZ"}, /* TDM sample size for all TDM sinks and sources , */\
+ { 0x1103, "TDMSLOTS"}, /* TDM number of slots , */\
+ { 0x1144, "TDMSLLN"}, /* TDM slot length , */\
+ { 0x1194, "TDMBRMG"}, /* TDM bits remaining after the last slot , */\
+ { 0x11e0, "TDMDDEL"}, /* TDM data delay , */\
+ { 0x11f0, "TDMDADJ"}, /* TDM data adjustment , */\
+ { 0x1201, "TDMTXFRM"}, /* TDM TXDATA format , */\
+ { 0x1221, "TDMUUS0"}, /* TDM TXDATA format unused slot SD0 , */\
+ { 0x1241, "TDMUUS1"}, /* TDM TXDATA format unused slot SD1 , */\
+ { 0x1270, "TDMSI0EN"}, /* TDM sink0 enable , */\
+ { 0x1280, "TDMSI1EN"}, /* TDM sink1 enable , */\
+ { 0x1290, "TDMSI2EN"}, /* TDM sink2 enable , */\
+ { 0x12a0, "TDMSO0EN"}, /* TDM source0 enable , */\
+ { 0x12b0, "TDMSO1EN"}, /* TDM source1 enable , */\
+ { 0x12c0, "TDMSO2EN"}, /* TDM source2 enable , */\
+ { 0x12d0, "TDMSI0IO"}, /* TDM sink0 IO selection , */\
+ { 0x12e0, "TDMSI1IO"}, /* TDM sink1 IO selection , */\
+ { 0x12f0, "TDMSI2IO"}, /* TDM sink2 IO selection , */\
+ { 0x1300, "TDMSO0IO"}, /* TDM source0 IO selection , */\
+ { 0x1310, "TDMSO1IO"}, /* TDM source1 IO selection , */\
+ { 0x1320, "TDMSO2IO"}, /* TDM source2 IO selection , */\
+ { 0x1333, "TDMSI0SL"}, /* TDM sink0 slot position [GAIN IN] , */\
+ { 0x1373, "TDMSI1SL"}, /* TDM sink1 slot position [CH1 IN] , */\
+ { 0x13b3, "TDMSI2SL"}, /* TDM sink2 slot position [CH2 IN] , */\
+ { 0x1403, "TDMSO0SL"}, /* TDM source0 slot position [GAIN OUT] , */\
+ { 0x1443, "TDMSO1SL"}, /* TDM source1 slot position [Voltage Sense] , */\
+ { 0x1483, "TDMSO2SL"}, /* TDM source2 slot position [Current Sense] , */\
+ { 0x14c3, "NBCK"}, /* TDM NBCK bit clock ratio , */\
+ { 0x2000, "INTOVDDS"}, /* flag_por_int_out , */\
+ { 0x2010, "INTOPLLS"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "INTOOTDS"}, /* flag_otpok_int_out , */\
+ { 0x2030, "INTOOVDS"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "INTOUVDS"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "INTOOCDS"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "INTOCLKS"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "INTOCLIPS"}, /* flag_clip_int_out , */\
+ { 0x2080, "INTOMTPB"}, /* mtp_busy_int_out , */\
+ { 0x2090, "INTONOCLK"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "INTOSPKS"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "INTOACS"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "INTOSWS"}, /* flag_engage_int_out , */\
+ { 0x20d0, "INTOWDS"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "INTOAMPS"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "INTOAREFS"}, /* flag_enbl_ref_int_out , */\
+ { 0x2200, "INTOERR"}, /* flag_cfma_err_int_out , */\
+ { 0x2210, "INTOACK"}, /* flag_cfma_ack_int_out , */\
+ { 0x2300, "INTIVDDS"}, /* flag_por_int_in , */\
+ { 0x2310, "INTIPLLS"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "INTIOTDS"}, /* flag_otpok_int_in , */\
+ { 0x2330, "INTIOVDS"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "INTIUVDS"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "INTIOCDS"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "INTICLKS"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "INTICLIPS"}, /* flag_clip_int_in , */\
+ { 0x2380, "INTIMTPB"}, /* mtp_busy_int_in , */\
+ { 0x2390, "INTINOCLK"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "INTISPKS"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "INTIACS"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "INTISWS"}, /* flag_engage_int_in , */\
+ { 0x23d0, "INTIWDS"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "INTIAMPS"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "INTIAREFS"}, /* flag_enbl_ref_int_in , */\
+ { 0x2500, "INTIERR"}, /* flag_cfma_err_int_in , */\
+ { 0x2510, "INTIACK"}, /* flag_cfma_ack_int_in , */\
+ { 0x2600, "INTENVDDS"}, /* flag_por_int_enable , */\
+ { 0x2610, "INTENPLLS"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "INTENOTDS"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "INTENOVDS"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "INTENUVDS"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "INTENOCDS"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "INTENCLKS"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "INTENCLIPS"}, /* flag_clip_int_enable , */\
+ { 0x2680, "INTENMTPB"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "INTENNOCLK"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "INTENSPKS"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "INTENACS"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "INTENSWS"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "INTENWDS"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "INTENAMPS"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "INTENAREFS"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2800, "INTENERR"}, /* flag_cfma_err_int_enable , */\
+ { 0x2810, "INTENACK"}, /* flag_cfma_ack_int_enable , */\
+ { 0x2900, "INTPOLVDDS"}, /* flag_por_int_pol , */\
+ { 0x2910, "INTPOLPLLS"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "INTPOLOTDS"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "INTPOLOVDS"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "INTPOLUVDS"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "INTPOLOCDS"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "INTPOLCLKS"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "INTPOLCLIPS"}, /* flag_clip_int_pol , */\
+ { 0x2980, "INTPOLMTPB"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "INTPOLNOCLK"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "INTPOLSPKS"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "INTPOLACS"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "INTPOLSWS"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "INTPOLWDS"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "INTPOLAMPS"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "INTPOLAREFS"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2b00, "INTPOLERR"}, /* flag_cfma_err_int_pol , */\
+ { 0x2b10, "INTPOLACK"}, /* flag_cfma_ack_int_pol , */\
+ { 0x4900, "CLIP"}, /* Bypass clip control , */\
+ { 0x62b0, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0x7000, "RST"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "DMEM"}, /* Target memory for access , */\
+ { 0x7030, "AIF"}, /* Auto increment flag for memory-address , */\
+ { 0x7040, "CFINT"}, /* CF Interrupt - auto clear , */\
+ { 0x7087, "REQ"}, /* CF request for accessing the 8 channels , */\
+ { 0x710f, "MADD"}, /* Memory address , */\
+ { 0x720f, "MEMA"}, /* Activate memory access , */\
+ { 0x7307, "ERR"}, /* CF error flags , */\
+ { 0x7387, "ACK"}, /* CF acknowledgement of the requests channels , */\
+ { 0x8000, "MTPOTC"}, /* Calibration schedule selection , */\
+ { 0x8010, "MTPEX"}, /* Calibration of RON status bit , */\
+ { 0x8045, "SWPROFIL" },\
+ { 0x80a5, "SWVSTEP" },\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9896_BITNAMETABLE static tfaBfName_t Tfa9896BitNames[]= {\
+ { 0x0, "flag_por"}, /* Power-on-reset flag (auto clear by reading) , */\
+ { 0x10, "flag_pll_lock"}, /* PLL lock to programmed frequency , */\
+ { 0x20, "flag_otpok"}, /* Over Temperature Protection alarm , */\
+ { 0x30, "flag_ovpok"}, /* Over Voltage Protection alarm , */\
+ { 0x40, "flag_uvpok"}, /* Under Voltage Protection alarm , */\
+ { 0x50, "flag_ocp_alarm"}, /* Over Current Protection alarm , */\
+ { 0x60, "flag_clocks_stable"}, /* Clocks stable flag , */\
+ { 0x70, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x80, "mtp_busy"}, /* MTP busy copying data to/from I2C registers , */\
+ { 0x90, "flag_lost_clk"}, /* lost clock detection (reference input clock) , */\
+ { 0xa0, "flag_cf_speakererror"}, /* Speaker error , */\
+ { 0xb0, "flag_cold_started"}, /* Cold Start required , */\
+ { 0xc0, "flag_engage"}, /* Amplifier engage (Amp Switching) , */\
+ { 0xd0, "flag_watchdog_reset"}, /* watchdog reset (activates reset) , */\
+ { 0xe0, "flag_enbl_amp"}, /* Amplifier is enabled by manager , */\
+ { 0xf0, "flag_enbl_ref"}, /* References are enabled by manager , */\
+ { 0x109, "bat_adc"}, /* Battery voltage from ADC readout , */\
+ { 0x208, "temp_adc"}, /* Temperature readout from the temperature sensor ( C), */\
+ { 0x30f, "device_rev"}, /* Device revision information , */\
+ { 0x420, "ctrl_rcv"}, /* Enable receiver mode , */\
+ { 0x431, "chan_sel"}, /* Channel Selection TDM input for Coolflux , */\
+ { 0x450, "input_level"}, /* Input level selection attenuator ( , */\
+ { 0x461, "vamp_sel"}, /* Input selection for amplifier , */\
+ { 0x4c3, "audio_fs"}, /* Audio sample rate setting , */\
+ { 0x501, "vbat_prot_attacktime"}, /* Batteery protection attack time , */\
+ { 0x523, "vbat_prot_thlevel"}, /* Battery protection threshold level , */\
+ { 0x561, "vbat_prot_max_reduct"}, /* Battery protection maximum reduction , */\
+ { 0x582, "vbat_prot_release_t"}, /* Battery protection release time , */\
+ { 0x5b1, "vbat_prot_hysterese"}, /* Battery Protection Hysteresis , */\
+ { 0x5d0, "reset_min_vbat"}, /* Battery supply safeguard clipper reset ( if CF_DSP is bypassed), */\
+ { 0x5e0, "sel_vbat"}, /* Battery voltage value for read out (only) , */\
+ { 0x5f0, "bypass_clipper"}, /* Bypass clipper battery protection , */\
+ { 0x600, "dpsa"}, /* Enable dynamic powerstage activation (DPSA) , */\
+ { 0x613, "ctrl_att"}, /* Gain attenuation setting , */\
+ { 0x650, "cf_mute"}, /* Soft mute in CoolFlux , */\
+ { 0x670, "batsense_steepness"}, /* Battery sense steepness , */\
+ { 0x687, "vol"}, /* Coolflux volume control , */\
+ { 0x702, "scnd_boost_voltage"}, /* Second Boost Voltage , */\
+ { 0x733, "boost_cur"}, /* Max boost coil current - step of 175 mA , */\
+ { 0x772, "frst_boost_voltage"}, /* First Boost Voltage , */\
+ { 0x7a0, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x7b0, "boost_speed"}, /* Soft Rampup/down mode for DCDC controller , */\
+ { 0x7c0, "boost_peak2avg"}, /* ctrl_peak2avg for analog part of DCDC , */\
+ { 0x7d0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7e0, "ignore_flag_voutcomp86"}, /* Ignore flag_voutcomp86 (flag from analog) , */\
+ { 0x800, "ext_temp_sel"}, /* Selection ambient temperature for speaker calibration , */\
+ { 0x818, "ext_temp"}, /* External temperature for speaker calibration (C) , */\
+ { 0x900, "powerdown"}, /* powerdown selection , */\
+ { 0x910, "reset"}, /* All I2C registers reset to default , */\
+ { 0x920, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x930, "enbl_amplifier"}, /* Enable Amplifier , */\
+ { 0x940, "enbl_boost"}, /* Enable DCDC Boost converter , */\
+ { 0x950, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x960, "sel_enbl_amplifier"}, /* Selection if Coolflux enables amplifier , */\
+ { 0x970, "dcdcoff_mode"}, /* DCDC boost converter not connected , */\
+ { 0x980, "iddqtest"}, /* IDDQ amplifier test selection , */\
+ { 0x9c1, "int_pad_io"}, /* INT pad (interrupt bump output) configuration , */\
+ { 0x9e0, "sel_fs_bck"}, /* PLL input reference clock selection , */\
+ { 0x9f0, "sel_scl_cf_clock"}, /* Coolflux sub-system clock selection , */\
+ { 0xa04, "boost_trip_lvl"}, /* Adaptive boost trip levels (effective only when boost_intel is set to 1), */\
+ { 0xa54, "boost_hold_time"}, /* Hold time for DCDC booster (effective only when boost_intel is set to 1), */\
+ { 0xaa1, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0xb07, "mtpkey2"}, /* KEY2 to access key2 protected registers (default for engineering), */\
+ { 0xc00, "enbl_volt_sense"}, /* Voltage sense enabling control bit , */\
+ { 0xc10, "vsense_pwm_sel"}, /* Voltage sense source selection , */\
+ { 0xc25, "vi_frac_delay"}, /* Fractional delay adjustment between current and voltage sense, */\
+ { 0xc80, "sel_voltsense_out"}, /* TDM output data selection for AEC , */\
+ { 0xc90, "vsense_bypass_avg"}, /* Voltage sense average block bypass , */\
+ { 0xd05, "cf_frac_delay"}, /* Fractional delay adjustment between current and voltage sense by firmware, */\
+ { 0xe00, "bypass_dcdc_curr_prot"}, /* Control to switch off dcdc current reduction with bat protection, */\
+ { 0xe10, "bypass_ocp"}, /* Bypass OCP (digital IP block) , */\
+ { 0xe20, "ocptest"}, /* ocptest (analog IP block) enable , */\
+ { 0xe80, "disable_clock_sh_prot"}, /* Disable clock_sh protection , */\
+ { 0xe92, "reserve_reg_15_09"}, /* Spare control bits for future usage , */\
+ { 0xec0, "unprotect_mtp"}, /* Enable programming of the MTP memory , */\
+ { 0xed2, "reserve_reg_15_13"}, /* Spare control bits for future usage , */\
+ { 0xf00, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode forcing each 50us a pwm pulse , */\
+ { 0xf11, "dcdc_ctrl_maxzercnt"}, /* DCDC number of zero current flags required to go to pfm mode, */\
+ { 0xf36, "dcdc_vbat_delta_detect"}, /* DCDC threshold required on a delta Vbat (in PFM mode) switching to PWM mode, */\
+ { 0xfa0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x1011, "tdm_usecase"}, /* TDM usecase selection control , */\
+ { 0x1030, "tdm_enable"}, /* TDM interface enable , */\
+ { 0x1040, "tdm_clk_inversion"}, /* TDM clock inversion, receive on , */\
+ { 0x1053, "tdm_fs_ws_length"}, /* TDM FS length , */\
+ { 0x1090, "tdm_fs_ws_polarity"}, /* TDM FS polarity (start frame) , */\
+ { 0x10a4, "tdm_sample_size"}, /* TDM sample size for all TDM sinks and sources , */\
+ { 0x1103, "tdm_nb_of_slots"}, /* TDM number of slots , */\
+ { 0x1144, "tdm_slot_length"}, /* TDM slot length , */\
+ { 0x1194, "tdm_bits_remaining"}, /* TDM bits remaining after the last slot , */\
+ { 0x11e0, "tdm_data_delay"}, /* TDM data delay , */\
+ { 0x11f0, "tdm_data_adjustment"}, /* TDM data adjustment , */\
+ { 0x1201, "tdm_txdata_format"}, /* TDM TXDATA format , */\
+ { 0x1221, "tdm_txdata_format_unused_slot_sd0"}, /* TDM TXDATA format unused slot SD0 , */\
+ { 0x1241, "tdm_txdata_format_unused_slot_sd1"}, /* TDM TXDATA format unused slot SD1 , */\
+ { 0x1270, "tdm_sink0_enable"}, /* TDM sink0 enable , */\
+ { 0x1280, "tdm_sink1_enable"}, /* TDM sink1 enable , */\
+ { 0x1290, "tdm_sink2_enable"}, /* TDM sink2 enable , */\
+ { 0x12a0, "tdm_source0_enable"}, /* TDM source0 enable , */\
+ { 0x12b0, "tdm_source1_enable"}, /* TDM source1 enable , */\
+ { 0x12c0, "tdm_source2_enable"}, /* TDM source2 enable , */\
+ { 0x12d0, "tdm_sink0_io"}, /* TDM sink0 IO selection , */\
+ { 0x12e0, "tdm_sink1_io"}, /* TDM sink1 IO selection , */\
+ { 0x12f0, "tdm_sink2_io"}, /* TDM sink2 IO selection , */\
+ { 0x1300, "tdm_source0_io"}, /* TDM source0 IO selection , */\
+ { 0x1310, "tdm_source1_io"}, /* TDM source1 IO selection , */\
+ { 0x1320, "tdm_source2_io"}, /* TDM source2 IO selection , */\
+ { 0x1333, "tdm_sink0_slot"}, /* TDM sink0 slot position [GAIN IN] , */\
+ { 0x1373, "tdm_sink1_slot"}, /* TDM sink1 slot position [CH1 IN] , */\
+ { 0x13b3, "tdm_sink2_slot"}, /* TDM sink2 slot position [CH2 IN] , */\
+ { 0x1403, "tdm_source0_slot"}, /* TDM source0 slot position [GAIN OUT] , */\
+ { 0x1443, "tdm_source1_slot"}, /* TDM source1 slot position [Voltage Sense] , */\
+ { 0x1483, "tdm_source2_slot"}, /* TDM source2 slot position [Current Sense] , */\
+ { 0x14c3, "tdm_nbck"}, /* TDM NBCK bit clock ratio , */\
+ { 0x1500, "flag_tdm_lut_error"}, /* TDM LUT error flag , */\
+ { 0x1512, "flag_tdm_status"}, /* TDM interface status bits , */\
+ { 0x1540, "flag_tdm_error"}, /* TDM interface error indicator , */\
+ { 0x1551, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x2000, "flag_por_int_out"}, /* flag_por_int_out , */\
+ { 0x2010, "flag_pll_lock_int_out"}, /* flag_pll_lock_int_out , */\
+ { 0x2020, "flag_otpok_int_out"}, /* flag_otpok_int_out , */\
+ { 0x2030, "flag_ovpok_int_out"}, /* flag_ovpok_int_out , */\
+ { 0x2040, "flag_uvpok_int_out"}, /* flag_uvpok_int_out , */\
+ { 0x2050, "flag_ocp_alarm_int_out"}, /* flag_ocp_alarm_int_out , */\
+ { 0x2060, "flag_clocks_stable_int_out"}, /* flag_clocks_stable_int_out , */\
+ { 0x2070, "flag_clip_int_out"}, /* flag_clip_int_out , */\
+ { 0x2080, "mtp_busy_int_out"}, /* mtp_busy_int_out , */\
+ { 0x2090, "flag_lost_clk_int_out"}, /* flag_lost_clk_int_out , */\
+ { 0x20a0, "flag_cf_speakererror_int_out"}, /* flag_cf_speakererror_int_out , */\
+ { 0x20b0, "flag_cold_started_int_out"}, /* flag_cold_started_int_out , */\
+ { 0x20c0, "flag_engage_int_out"}, /* flag_engage_int_out , */\
+ { 0x20d0, "flag_watchdog_reset_int_out"}, /* flag_watchdog_reset_int_out , */\
+ { 0x20e0, "flag_enbl_amp_int_out"}, /* flag_enbl_amp_int_out , */\
+ { 0x20f0, "flag_enbl_ref_int_out"}, /* flag_enbl_ref_int_out , */\
+ { 0x2100, "flag_voutcomp_int_out"}, /* flag_voutcomp_int_out , */\
+ { 0x2110, "flag_voutcomp93_int_out"}, /* flag_voutcomp93_int_out , */\
+ { 0x2120, "flag_voutcomp86_int_out"}, /* flag_voutcomp86_int_out , */\
+ { 0x2130, "flag_hiz_int_out"}, /* flag_hiz_int_out , */\
+ { 0x2140, "flag_ocpokbst_int_out"}, /* flag_ocpokbst_int_out , */\
+ { 0x2150, "flag_peakcur_int_out"}, /* flag_peakcur_int_out , */\
+ { 0x2160, "flag_ocpokap_int_out"}, /* flag_ocpokap_int_out , */\
+ { 0x2170, "flag_ocpokan_int_out"}, /* flag_ocpokan_int_out , */\
+ { 0x2180, "flag_ocpokbp_int_out"}, /* flag_ocpokbp_int_out , */\
+ { 0x2190, "flag_ocpokbn_int_out"}, /* flag_ocpokbn_int_out , */\
+ { 0x21a0, "flag_adc10_ready_int_out"}, /* flag_adc10_ready_int_out , */\
+ { 0x21b0, "flag_clipa_high_int_out"}, /* flag_clipa_high_int_out , */\
+ { 0x21c0, "flag_clipa_low_int_out"}, /* flag_clipa_low_int_out , */\
+ { 0x21d0, "flag_clipb_high_int_out"}, /* flag_clipb_high_int_out , */\
+ { 0x21e0, "flag_clipb_low_int_out"}, /* flag_clipb_low_int_out , */\
+ { 0x21f0, "flag_tdm_error_int_out"}, /* flag_tdm_error_int_out , */\
+ { 0x2200, "flag_cfma_err_int_out"}, /* flag_cfma_err_int_out , */\
+ { 0x2210, "flag_cfma_ack_int_out"}, /* flag_cfma_ack_int_out , */\
+ { 0x2300, "flag_por_int_in"}, /* flag_por_int_in , */\
+ { 0x2310, "flag_pll_lock_int_in"}, /* flag_pll_lock_int_in , */\
+ { 0x2320, "flag_otpok_int_in"}, /* flag_otpok_int_in , */\
+ { 0x2330, "flag_ovpok_int_in"}, /* flag_ovpok_int_in , */\
+ { 0x2340, "flag_uvpok_int_in"}, /* flag_uvpok_int_in , */\
+ { 0x2350, "flag_ocp_alarm_int_in"}, /* flag_ocp_alarm_int_in , */\
+ { 0x2360, "flag_clocks_stable_int_in"}, /* flag_clocks_stable_int_in , */\
+ { 0x2370, "flag_clip_int_in"}, /* flag_clip_int_in , */\
+ { 0x2380, "mtp_busy_int_in"}, /* mtp_busy_int_in , */\
+ { 0x2390, "flag_lost_clk_int_in"}, /* flag_lost_clk_int_in , */\
+ { 0x23a0, "flag_cf_speakererror_int_in"}, /* flag_cf_speakererror_int_in , */\
+ { 0x23b0, "flag_cold_started_int_in"}, /* flag_cold_started_int_in , */\
+ { 0x23c0, "flag_engage_int_in"}, /* flag_engage_int_in , */\
+ { 0x23d0, "flag_watchdog_reset_int_in"}, /* flag_watchdog_reset_int_in , */\
+ { 0x23e0, "flag_enbl_amp_int_in"}, /* flag_enbl_amp_int_in , */\
+ { 0x23f0, "flag_enbl_ref_int_in"}, /* flag_enbl_ref_int_in , */\
+ { 0x2400, "flag_voutcomp_int_in"}, /* flag_voutcomp_int_in , */\
+ { 0x2410, "flag_voutcomp93_int_in"}, /* flag_voutcomp93_int_in , */\
+ { 0x2420, "flag_voutcomp86_int_in"}, /* flag_voutcomp86_int_in , */\
+ { 0x2430, "flag_hiz_int_in"}, /* flag_hiz_int_in , */\
+ { 0x2440, "flag_ocpokbst_int_in"}, /* flag_ocpokbst_int_in , */\
+ { 0x2450, "flag_peakcur_int_in"}, /* flag_peakcur_int_in , */\
+ { 0x2460, "flag_ocpokap_int_in"}, /* flag_ocpokap_int_in , */\
+ { 0x2470, "flag_ocpokan_int_in"}, /* flag_ocpokan_int_in , */\
+ { 0x2480, "flag_ocpokbp_int_in"}, /* flag_ocpokbp_int_in , */\
+ { 0x2490, "flag_ocpokbn_int_in"}, /* flag_ocpokbn_int_in , */\
+ { 0x24a0, "flag_adc10_ready_int_in"}, /* flag_adc10_ready_int_in , */\
+ { 0x24b0, "flag_clipa_high_int_in"}, /* flag_clipa_high_int_in , */\
+ { 0x24c0, "flag_clipa_low_int_in"}, /* flag_clipa_low_int_in , */\
+ { 0x24d0, "flag_clipb_high_int_in"}, /* flag_clipb_high_int_in , */\
+ { 0x24e0, "flag_clipb_low_int_in"}, /* flag_clipb_low_int_in , */\
+ { 0x24f0, "flag_tdm_error_int_in"}, /* flag_tdm_error_int_in , */\
+ { 0x2500, "flag_cfma_err_int_in"}, /* flag_cfma_err_int_in , */\
+ { 0x2510, "flag_cfma_ack_int_in"}, /* flag_cfma_ack_int_in , */\
+ { 0x2600, "flag_por_int_enable"}, /* flag_por_int_enable , */\
+ { 0x2610, "flag_pll_lock_int_enable"}, /* flag_pll_lock_int_enable , */\
+ { 0x2620, "flag_otpok_int_enable"}, /* flag_otpok_int_enable , */\
+ { 0x2630, "flag_ovpok_int_enable"}, /* flag_ovpok_int_enable , */\
+ { 0x2640, "flag_uvpok_int_enable"}, /* flag_uvpok_int_enable , */\
+ { 0x2650, "flag_ocp_alarm_int_enable"}, /* flag_ocp_alarm_int_enable , */\
+ { 0x2660, "flag_clocks_stable_int_enable"}, /* flag_clocks_stable_int_enable , */\
+ { 0x2670, "flag_clip_int_enable"}, /* flag_clip_int_enable , */\
+ { 0x2680, "mtp_busy_int_enable"}, /* mtp_busy_int_enable , */\
+ { 0x2690, "flag_lost_clk_int_enable"}, /* flag_lost_clk_int_enable , */\
+ { 0x26a0, "flag_cf_speakererror_int_enable"}, /* flag_cf_speakererror_int_enable , */\
+ { 0x26b0, "flag_cold_started_int_enable"}, /* flag_cold_started_int_enable , */\
+ { 0x26c0, "flag_engage_int_enable"}, /* flag_engage_int_enable , */\
+ { 0x26d0, "flag_watchdog_reset_int_enable"}, /* flag_watchdog_reset_int_enable , */\
+ { 0x26e0, "flag_enbl_amp_int_enable"}, /* flag_enbl_amp_int_enable , */\
+ { 0x26f0, "flag_enbl_ref_int_enable"}, /* flag_enbl_ref_int_enable , */\
+ { 0x2700, "flag_voutcomp_int_enable"}, /* flag_voutcomp_int_enable , */\
+ { 0x2710, "flag_voutcomp93_int_enable"}, /* flag_voutcomp93_int_enable , */\
+ { 0x2720, "flag_voutcomp86_int_enable"}, /* flag_voutcomp86_int_enable , */\
+ { 0x2730, "flag_hiz_int_enable"}, /* flag_hiz_int_enable , */\
+ { 0x2740, "flag_ocpokbst_int_enable"}, /* flag_ocpokbst_int_enable , */\
+ { 0x2750, "flag_peakcur_int_enable"}, /* flag_peakcur_int_enable , */\
+ { 0x2760, "flag_ocpokap_int_enable"}, /* flag_ocpokap_int_enable , */\
+ { 0x2770, "flag_ocpokan_int_enable"}, /* flag_ocpokan_int_enable , */\
+ { 0x2780, "flag_ocpokbp_int_enable"}, /* flag_ocpokbp_int_enable , */\
+ { 0x2790, "flag_ocpokbn_int_enable"}, /* flag_ocpokbn_int_enable , */\
+ { 0x27a0, "flag_adc10_ready_int_enable"}, /* flag_adc10_ready_int_enable , */\
+ { 0x27b0, "flag_clipa_high_int_enable"}, /* flag_clipa_high_int_enable , */\
+ { 0x27c0, "flag_clipa_low_int_enable"}, /* flag_clipa_low_int_enable , */\
+ { 0x27d0, "flag_clipb_high_int_enable"}, /* flag_clipb_high_int_enable , */\
+ { 0x27e0, "flag_clipb_low_int_enable"}, /* flag_clipb_low_int_enable , */\
+ { 0x27f0, "flag_tdm_error_int_enable"}, /* flag_tdm_error_int_enable , */\
+ { 0x2800, "flag_cfma_err_int_enable"}, /* flag_cfma_err_int_enable , */\
+ { 0x2810, "flag_cfma_ack_int_enable"}, /* flag_cfma_ack_int_enable , */\
+ { 0x2900, "flag_por_int_pol"}, /* flag_por_int_pol , */\
+ { 0x2910, "flag_pll_lock_int_pol"}, /* flag_pll_lock_int_pol , */\
+ { 0x2920, "flag_otpok_int_pol"}, /* flag_otpok_int_pol , */\
+ { 0x2930, "flag_ovpok_int_pol"}, /* flag_ovpok_int_pol , */\
+ { 0x2940, "flag_uvpok_int_pol"}, /* flag_uvpok_int_pol , */\
+ { 0x2950, "flag_ocp_alarm_int_pol"}, /* flag_ocp_alarm_int_pol , */\
+ { 0x2960, "flag_clocks_stable_int_pol"}, /* flag_clocks_stable_int_pol , */\
+ { 0x2970, "flag_clip_int_pol"}, /* flag_clip_int_pol , */\
+ { 0x2980, "mtp_busy_int_pol"}, /* mtp_busy_int_pol , */\
+ { 0x2990, "flag_lost_clk_int_pol"}, /* flag_lost_clk_int_pol , */\
+ { 0x29a0, "flag_cf_speakererror_int_pol"}, /* flag_cf_speakererror_int_pol , */\
+ { 0x29b0, "flag_cold_started_int_pol"}, /* flag_cold_started_int_pol , */\
+ { 0x29c0, "flag_engage_int_pol"}, /* flag_engage_int_pol , */\
+ { 0x29d0, "flag_watchdog_reset_int_pol"}, /* flag_watchdog_reset_int_pol , */\
+ { 0x29e0, "flag_enbl_amp_int_pol"}, /* flag_enbl_amp_int_pol , */\
+ { 0x29f0, "flag_enbl_ref_int_pol"}, /* flag_enbl_ref_int_pol , */\
+ { 0x2a00, "flag_voutcomp_int_pol"}, /* flag_voutcomp_int_pol , */\
+ { 0x2a10, "flag_voutcomp93_int_pol"}, /* flag_voutcomp93_int_pol , */\
+ { 0x2a20, "flag_voutcomp86_int_pol"}, /* flag_voutcomp86_int_pol , */\
+ { 0x2a30, "flag_hiz_int_pol"}, /* flag_hiz_int_pol , */\
+ { 0x2a40, "flag_ocpokbst_int_pol"}, /* flag_ocpokbst_int_pol , */\
+ { 0x2a50, "flag_peakcur_int_pol"}, /* flag_peakcur_int_pol , */\
+ { 0x2a60, "flag_ocpokap_int_pol"}, /* flag_ocpokap_int_pol , */\
+ { 0x2a70, "flag_ocpokan_int_pol"}, /* flag_ocpokan_int_pol , */\
+ { 0x2a80, "flag_ocpokbp_int_pol"}, /* flag_ocpokbp_int_pol , */\
+ { 0x2a90, "flag_ocpokbn_int_pol"}, /* flag_ocpokbn_int_pol , */\
+ { 0x2aa0, "flag_adc10_ready_int_pol"}, /* flag_adc10_ready_int_pol , */\
+ { 0x2ab0, "flag_clipa_high_int_pol"}, /* flag_clipa_high_int_pol , */\
+ { 0x2ac0, "flag_clipa_low_int_pol"}, /* flag_clipa_low_int_pol , */\
+ { 0x2ad0, "flag_clipb_high_int_pol"}, /* flag_clipb_high_int_pol , */\
+ { 0x2ae0, "flag_clipb_low_int_pol"}, /* flag_clipb_low_int_pol , */\
+ { 0x2af0, "flag_tdm_error_int_pol"}, /* flag_tdm_error_int_pol , */\
+ { 0x2b00, "flag_cfma_err_int_pol"}, /* flag_cfma_err_int_pol , */\
+ { 0x2b10, "flag_cfma_ack_int_pol"}, /* flag_cfma_ack_int_pol , */\
+ { 0x3000, "flag_voutcomp"}, /* Status flag_voutcomp, indication Vset is larger than Vbat, */\
+ { 0x3010, "flag_voutcomp93"}, /* Status flag_voutcomp93, indication Vset is larger than 1.07 x Vbat, */\
+ { 0x3020, "flag_voutcomp86"}, /* Status flag voutcomp86, indication Vset is larger than 1.14 x Vbat, */\
+ { 0x3030, "flag_hiz"}, /* Status flag_hiz, indication Vbst is larger than Vbat, */\
+ { 0x3040, "flag_ocpokbst"}, /* Status flag_ocpokbst, indication no over current in boost converter PMOS switch, */\
+ { 0x3050, "flag_peakcur"}, /* Status flag_peakcur, indication current is max in dcdc converter, */\
+ { 0x3060, "flag_ocpokap"}, /* Status flag_ocpokap, indication no over current in amplifier A PMOS output stage, */\
+ { 0x3070, "flag_ocpokan"}, /* Status flag_ocpokan, indication no over current in amplifier A NMOS output stage, */\
+ { 0x3080, "flag_ocpokbp"}, /* Status flag_ocpokbp, indication no over current in amplifier B PMOS output stage, */\
+ { 0x3090, "flag_ocpokbn"}, /* Status flag_ocpokbn, indication no over current in amplifier B NMOS output stage, */\
+ { 0x30a0, "flag_adc10_ready"}, /* Status flag_adc10_ready, indication adc10 is ready, */\
+ { 0x30b0, "flag_clipa_high"}, /* Status flag_clipa_high, indication pmos amplifier A is clipping, */\
+ { 0x30c0, "flag_clipa_low"}, /* Status flag_clipa_low, indication nmos amplifier A is clipping, */\
+ { 0x30d0, "flag_clipb_high"}, /* Status flag_clipb_high, indication pmos amplifier B is clipping, */\
+ { 0x30e0, "flag_clipb_low"}, /* Status flag_clipb_low, indication nmos amplifier B is clipping, */\
+ { 0x310f, "mtp_man_data_out"}, /* MTP manual read out data , */\
+ { 0x3200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0x3210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0x3225, "mtp_ecc_tcout"}, /* MTP error correction test data out , */\
+ { 0x3280, "mtpctrl_valid_test_rd"}, /* MTP test readout for read , */\
+ { 0x3290, "mtpctrl_valid_test_wr"}, /* MTP test readout for write , */\
+ { 0x32a0, "flag_in_alarm_state"}, /* Flag alarm state , */\
+ { 0x32b0, "mtp_ecc_err2"}, /* Two or more bit errors detected in MTP, can not reconstruct value, */\
+ { 0x32c0, "mtp_ecc_err1"}, /* One bit error detected in MTP, reconstructed value, */\
+ { 0x32d0, "mtp_mtp_hvf"}, /* High voltage ready flag for MTP , */\
+ { 0x32f0, "mtp_zero_check_fail"}, /* Zero check failed for MTP , */\
+ { 0x3309, "data_adc10_tempbat"}, /* ADC10 data output for testing battery voltage and temperature, */\
+ { 0x400f, "hid_code"}, /* 5A6Bh, 23147d to access hidden registers (default for engineering), */\
+ { 0x4100, "bypass_hp"}, /* Bypass High Pass Filter , */\
+ { 0x4110, "hard_mute"}, /* Hard Mute , */\
+ { 0x4120, "soft_mute"}, /* Soft Mute , */\
+ { 0x4134, "pwm_delay"}, /* PWM delay setting , */\
+ { 0x4180, "pwm_shape"}, /* PWM Shape , */\
+ { 0x4190, "pwm_bitlength"}, /* PWM Bitlength in noise shaper , */\
+ { 0x4203, "drive"}, /* Drive bits to select number of amplifier power stages, */\
+ { 0x4240, "reclock_pwm"}, /* Control for enabling reclocking of PWM signal , */\
+ { 0x4250, "reclock_voltsense"}, /* Control for enabling reclocking of voltage sense signal, */\
+ { 0x4281, "dpsalevel"}, /* DPSA threshold level , */\
+ { 0x42a1, "dpsa_release"}, /* DPSA release time , */\
+ { 0x42c0, "coincidence"}, /* Prevent simultaneously switching of output stage , */\
+ { 0x42d0, "kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x4306, "drivebst"}, /* Drive bits to select the power transistor sections boost converter, */\
+ { 0x4370, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x4381, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x43a0, "ocptestbst"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0); For new ocp (ctrl_reversebst is 1), */\
+ { 0x43d0, "test_abistfft_enbl"}, /* FFT Coolflux , */\
+ { 0x43e0, "bst_dcmbst"}, /* DCM mode control for DCDC during I2C direct control mode, */\
+ { 0x43f0, "test_bcontrol"}, /* test_bcontrol , */\
+ { 0x4400, "reversebst"}, /* OverCurrent Protection selection of power stage boost converter, */\
+ { 0x4410, "sensetest"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0x4420, "enbl_engagebst"}, /* Enable power stage of dcdc controller , */\
+ { 0x4470, "enbl_slopecur"}, /* Enable bit of max-current dac , */\
+ { 0x4480, "enbl_voutcomp"}, /* Enable vout comparators , */\
+ { 0x4490, "enbl_voutcomp93"}, /* Enable vout-93 comparators , */\
+ { 0x44a0, "enbl_voutcomp86"}, /* Enable vout-86 comparators , */\
+ { 0x44b0, "enbl_hizcom"}, /* Enable hiz comparator , */\
+ { 0x44c0, "enbl_peakcur"}, /* Enable peak current , */\
+ { 0x44d0, "bypass_ovpglitch"}, /* Bypass OVP Glitch Filter , */\
+ { 0x44e0, "enbl_windac"}, /* Enable window dac , */\
+ { 0x44f0, "enbl_powerbst"}, /* Enable line of the powerstage , */\
+ { 0x4507, "ocp_thr"}, /* OCP threshold level , */\
+ { 0x4580, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0x4590, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0x45a0, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0x45b0, "bypass_otp"}, /* Bypass OTP , */\
+ { 0x45d0, "bypass_ocpcounter"}, /* Bypass OCP counter , */\
+ { 0x45e0, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0x45f0, "vpalarm"}, /* vpalarm (UVP/OUP handling) , */\
+ { 0x4600, "bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x4610, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x4627, "cs_gain"}, /* Current sense gain , */\
+ { 0x46a0, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x46b0, "bypass_pwmcounter"}, /* Bypass PWM Counter , */\
+ { 0x46c0, "cs_negfixed"}, /* Current sense does not switch to neg , */\
+ { 0x46d2, "cs_neghyst"}, /* Current sense switches to neg depending on hyseteris level, */\
+ { 0x4700, "switch_fb"}, /* Current sense control switch_fb , */\
+ { 0x4713, "se_hyst"}, /* Current sense control se_hyst , */\
+ { 0x4754, "se_level"}, /* Current sense control se_level , */\
+ { 0x47a5, "ktemp"}, /* Current sense control temperature compensation trimming, */\
+ { 0x4800, "cs_negin"}, /* Current sense control negin , */\
+ { 0x4810, "cs_sein"}, /* Current sense control cs_sein , */\
+ { 0x4820, "cs_coincidence"}, /* Coincidence current sense , */\
+ { 0x4830, "iddqtestbst"}, /* IDDQ testing in powerstage of DCDC boost converter, */\
+ { 0x4840, "coincidencebst"}, /* Switch protection on to prevent simultaneously switching power stages bst and amp, */\
+ { 0x4876, "delay_se_neg"}, /* delay of se and neg , */\
+ { 0x48e1, "cs_ttrack"}, /* Sample and hold track time , */\
+ { 0x4900, "bypass_clip"}, /* Bypass clip control , */\
+ { 0x4920, "cf_cgate_off"}, /* Disable clock gating in the coolflux , */\
+ { 0x4940, "clipfast"}, /* Clock selection for HW clipper for battery safeguard, */\
+ { 0x4950, "cs_8ohm"}, /* 8 ohm mode for current sense (gain mode) , */\
+ { 0x4974, "delay_clock_sh"}, /* delay_sh, tunes S7H delay , */\
+ { 0x49c0, "inv_clksh"}, /* Invert the sample/hold clock for current sense ADC, */\
+ { 0x49d0, "inv_neg"}, /* Invert neg signal , */\
+ { 0x49e0, "inv_se"}, /* Invert se signal , */\
+ { 0x49f0, "setse"}, /* Switches between Single Ended and differential mode; 1 is single ended, */\
+ { 0x4a12, "adc10_sel"}, /* Select the input to convert the 10b ADC , */\
+ { 0x4a60, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0x4a81, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0x4aa0, "bypass_lp_vbat"}, /* LP filter in batt sensor , */\
+ { 0x4ae0, "dc_offset"}, /* Current sense decimator offset control , */\
+ { 0x4af0, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high , */\
+ { 0x4b00, "adc13_iset"}, /* MICADC setting of current consumption (debug use only), */\
+ { 0x4b14, "adc13_gain"}, /* MICADC gain setting (two's complement format) , */\
+ { 0x4b61, "adc13_slowdel"}, /* MICADC delay setting for internal clock (debug use only), */\
+ { 0x4b83, "adc13_offset"}, /* MICADC offset setting , */\
+ { 0x4bc0, "adc13_bsoinv"}, /* MICADC bit stream output invert mode for test , */\
+ { 0x4bd0, "adc13_resonator_enable"}, /* MICADC give extra SNR with less stability (debug use only), */\
+ { 0x4be0, "testmicadc"}, /* Mux at input of MICADC for test purpose , */\
+ { 0x4c0f, "abist_offset"}, /* Offset control for ABIST testing , */\
+ { 0x4d05, "windac"}, /* For testing direct control windac , */\
+ { 0x4dc3, "pwm_dcc_cnt"}, /* control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0x4e04, "slopecur"}, /* For testing direct control slopecur , */\
+ { 0x4e50, "ctrl_dem"}, /* Dynamic element matching control, rest of codes are optional, */\
+ { 0x4ed0, "enbl_pwm_dcc"}, /* Enable direct control of pwm duty cycle , */\
+ { 0x4f00, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x4f10, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x4f20, "bst_ctrl_azbst"}, /* Control of auto-zeroing of zero current comparator, */\
+ { 0x5007, "gain"}, /* Gain setting of the gain multiplier , */\
+ { 0x5081, "sourceb"}, /* PWM OUTB selection control , */\
+ { 0x50a1, "sourcea"}, /* PWM OUTA selection control , */\
+ { 0x50c1, "sourcebst"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0x50e0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0x5104, "pulselengthbst"}, /* Pulse length setting test input for boost converter, */\
+ { 0x5150, "bypasslatchbst"}, /* Bypass latch in boost converter , */\
+ { 0x5160, "invertbst"}, /* Invert pwmbst test signal , */\
+ { 0x5174, "pulselength"}, /* Pulse length setting test input for amplifier , */\
+ { 0x51c0, "bypasslatch"}, /* Bypass latch in PWM source selection module , */\
+ { 0x51d0, "invertb"}, /* invert pwmb test signal , */\
+ { 0x51e0, "inverta"}, /* invert pwma test signal , */\
+ { 0x51f0, "bypass_ctrlloop"}, /* bypass_ctrlloop bypasses the control loop of the amplifier, */\
+ { 0x5210, "test_rdsona"}, /* tbd for rdson testing , */\
+ { 0x5220, "test_rdsonb"}, /* tbd for rdson testing , */\
+ { 0x5230, "test_rdsonbst"}, /* tbd for rdson testing , */\
+ { 0x5240, "test_cvia"}, /* tbd for rdson testing , */\
+ { 0x5250, "test_cvib"}, /* tbd for rdson testing , */\
+ { 0x5260, "test_cvibst"}, /* tbd for rdson testing , */\
+ { 0x5306, "digimuxa_sel"}, /* DigimuxA input selection control (see Digimux list for details), */\
+ { 0x5376, "digimuxb_sel"}, /* DigimuxB input selection control (see Digimux list for details), */\
+ { 0x5400, "hs_mode"}, /* I2C high speed mode selection control , */\
+ { 0x5412, "test_parametric_io"}, /* Control for parametric tests of IO cells , */\
+ { 0x5440, "enbl_ringo"}, /* Enable ring oscillator control, for test purpose to check with ringo, */\
+ { 0x5456, "digimuxc_sel"}, /* DigimuxC input selection control (see Digimux list for details), */\
+ { 0x54c0, "dio_ehs"}, /* Slew control for DIO in output mode , */\
+ { 0x54d0, "gainio_ehs"}, /* Slew control for GAINIO in output mode , */\
+ { 0x550d, "enbl_amp"}, /* enbl_amp for testing to enable all analoge blocks in amplifier, */\
+ { 0x5600, "use_direct_ctrls"}, /* Use direct controls to overrule several functions for testing - I2C direct control mode, */\
+ { 0x5610, "rst_datapath"}, /* Reset datapath during direct control mode , */\
+ { 0x5620, "rst_cgu"}, /* Reset CGU during durect control mode , */\
+ { 0x5637, "enbl_ref"}, /* For testing to enable all analoge blocks in references, */\
+ { 0x56b0, "enbl_engage"}, /* Enable output stage amplifier , */\
+ { 0x56c0, "use_direct_clk_ctrl"}, /* use_direct_clk_ctrl, to overrule several functions direct for testing, */\
+ { 0x56d0, "use_direct_pll_ctrl"}, /* use_direct_pll_ctrl, to overrule several functions direct for testing, */\
+ { 0x5707, "anamux"}, /* Anamux control , */\
+ { 0x57e0, "otptest"}, /* otptest, test mode otp amplifier , */\
+ { 0x57f0, "reverse"}, /* 1b = Normal mode, slope is controlled , */\
+ { 0x5813, "pll_selr"}, /* PLL pll_selr , */\
+ { 0x5854, "pll_selp"}, /* PLL pll_selp , */\
+ { 0x58a5, "pll_seli"}, /* PLL pll_seli , */\
+ { 0x5950, "pll_mdec_msb"}, /* Most significant bits of pll_mdec[16] , */\
+ { 0x5960, "pll_ndec_msb"}, /* Most significant bits of pll_ndec[9] , */\
+ { 0x5970, "pll_frm"}, /* PLL pll_frm , */\
+ { 0x5980, "pll_directi"}, /* PLL pll_directi , */\
+ { 0x5990, "pll_directo"}, /* PLL pll_directo , */\
+ { 0x59a0, "enbl_pll"}, /* PLL enbl_pll , */\
+ { 0x59f0, "pll_bypass"}, /* PLL bypass , */\
+ { 0x5a0f, "tsig_freq"}, /* Internal sinus test generator frequency control LSB bits, */\
+ { 0x5b02, "tsig_freq_msb"}, /* Select internal sine wave generator, frequency control MSB bits, */\
+ { 0x5b30, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0x5b44, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0x5c0f, "pll_mdec"}, /* PLL MDEC - I2C direct PLL control mode only , */\
+ { 0x5d06, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0x5d78, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0x6007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0x6185, "mtp_ecc_tcin"}, /* MTP ECC TCIN data , */\
+ { 0x6203, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0x6260, "mtp_ecc_eeb"}, /* Enable code bit generation (active low!) , */\
+ { 0x6270, "mtp_ecc_ecb"}, /* Enable correction signal (active low!) , */\
+ { 0x6280, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0x6290, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0x62a0, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0x62b0, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0x62d2, "mtp_speed_mode"}, /* MTP speed mode , */\
+ { 0x6340, "mtp_direct_enable"}, /* mtp_direct_enable , */\
+ { 0x6350, "mtp_direct_wr"}, /* mtp_direct_wr , */\
+ { 0x6360, "mtp_direct_rd"}, /* mtp_direct_rd , */\
+ { 0x6370, "mtp_direct_rst"}, /* mtp_direct_rst , */\
+ { 0x6380, "mtp_direct_ers"}, /* mtp_direct_ers , */\
+ { 0x6390, "mtp_direct_prg"}, /* mtp_direct_prg , */\
+ { 0x63a0, "mtp_direct_epp"}, /* mtp_direct_epp , */\
+ { 0x63b4, "mtp_direct_test"}, /* mtp_direct_test , */\
+ { 0x640f, "mtp_man_data_in"}, /* Write data for MTP manual write , */\
+ { 0x7000, "cf_rst_dsp"}, /* Reset CoolFlux DSP , */\
+ { 0x7011, "cf_dmem"}, /* Target memory for access , */\
+ { 0x7030, "cf_aif"}, /* Auto increment flag for memory-address , */\
+ { 0x7040, "cf_int"}, /* CF Interrupt - auto clear , */\
+ { 0x7087, "cf_req"}, /* CF request for accessing the 8 channels , */\
+ { 0x710f, "cf_madd"}, /* Memory address , */\
+ { 0x720f, "cf_mema"}, /* Activate memory access , */\
+ { 0x7307, "cf_err"}, /* CF error flags , */\
+ { 0x7387, "cf_ack"}, /* CF acknowledgement of the requests channels , */\
+ { 0x8000, "calibration_onetime"}, /* Calibration schedule selection , */\
+ { 0x8010, "calibr_ron_done"}, /* Calibration of RON status bit , */\
+ { 0x8105, "calibr_vout_offset"}, /* calibr_vout_offset (DCDCoffset) 2's compliment (key1 protected), */\
+ { 0x8163, "calibr_delta_gain"}, /* delta gain for vamp (alpha) 2's compliment (key1 protected), */\
+ { 0x81a5, "calibr_offs_amp"}, /* offset for vamp (Ampoffset) 2's compliment (key1 protected), */\
+ { 0x8207, "calibr_gain_cs"}, /* gain current sense (Imeasalpha) 2's compliment (key1 protected), */\
+ { 0x8284, "calibr_temp_offset"}, /* temperature offset 2's compliment (key1 protected), */\
+ { 0x82d2, "calibr_temp_gain"}, /* temperature gain 2's compliment (key1 protected) , */\
+ { 0x830f, "calibr_ron"}, /* calibration value of the RON resistance of the coil, */\
+ { 0x8505, "type_bits_hw"}, /* bit0 = disable function dcdcoff_mode ($09[7]) , */\
+ { 0x8601, "type_bits_1_0_sw"}, /* MTP control SW , */\
+ { 0x8681, "type_bits_9_8_sw"}, /* MTP control SW , */\
+ { 0x870f, "type_bits2_sw"}, /* MTP-control SW2 , */\
+ { 0x8806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0x8870, "htol_iic_addr_en"}, /* HTOL I2C_Address_Enable , */\
+ { 0x8881, "ctrl_ovp_response"}, /* OVP response control , */\
+ { 0x88a0, "disable_ovp_alarm_state"}, /* OVP alarm state control , */\
+ { 0x88b0, "enbl_stretch_ovp"}, /* OVP alram strech control , */\
+ { 0x88c0, "cf_debug_mode"}, /* Coolflux debug mode , */\
+ { 0x8a0f, "production_data1"}, /* production_data1 , */\
+ { 0x8b0f, "production_data2"}, /* production_data2 , */\
+ { 0x8c0f, "production_data3"}, /* production_data3 , */\
+ { 0x8d0f, "production_data4"}, /* production_data4 , */\
+ { 0x8e0f, "production_data5"}, /* production_data5 , */\
+ { 0x8f0f, "production_data6"}, /* production_data6 , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum TFA9896_irq {
+ TFA9896_irq_vdds = 0,
+ TFA9896_irq_plls = 1,
+ TFA9896_irq_ds = 2,
+ TFA9896_irq_vds = 3,
+ TFA9896_irq_uvds = 4,
+ TFA9896_irq_cds = 5,
+ TFA9896_irq_clks = 6,
+ TFA9896_irq_clips = 7,
+ TFA9896_irq_mtpb = 8,
+ TFA9896_irq_clk = 9,
+ TFA9896_irq_spks = 10,
+ TFA9896_irq_acs = 11,
+ TFA9896_irq_sws = 12,
+ TFA9896_irq_wds = 13,
+ TFA9896_irq_amps = 14,
+ TFA9896_irq_arefs = 15,
+ TFA9896_irq_err = 32,
+ TFA9896_irq_ack = 33,
+ TFA9896_irq_max = 34,
+ TFA9896_irq_all = -1 /* all irqs */};
+
+#define TFA9896_IRQ_NAMETABLE static tfaIrqName_t TFA9896IrqNames[]= {\
+ { 0, "VDDS"},\
+ { 1, "PLLS"},\
+ { 2, "DS"},\
+ { 3, "VDS"},\
+ { 4, "UVDS"},\
+ { 5, "CDS"},\
+ { 6, "CLKS"},\
+ { 7, "CLIPS"},\
+ { 8, "MTPB"},\
+ { 9, "CLK"},\
+ { 10, "SPKS"},\
+ { 11, "ACS"},\
+ { 12, "SWS"},\
+ { 13, "WDS"},\
+ { 14, "AMPS"},\
+ { 15, "AREFS"},\
+ { 16, "16"},\
+ { 17, "17"},\
+ { 18, "18"},\
+ { 19, "19"},\
+ { 20, "20"},\
+ { 21, "21"},\
+ { 22, "22"},\
+ { 23, "23"},\
+ { 24, "24"},\
+ { 25, "25"},\
+ { 26, "26"},\
+ { 27, "27"},\
+ { 28, "28"},\
+ { 29, "29"},\
+ { 30, "30"},\
+ { 31, "31"},\
+ { 32, "ERR"},\
+ { 33, "ACK"},\
+ { 34, "34"},\
+};
+#endif /* _TFA9896_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c
new file mode 100644
index 00000000000..7058604d504
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.c
@@ -0,0 +1,3391 @@
+/*
+ * tfa98xx.c tfa98xx codec module
+ *
+ *
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#define pr_fmt(fmt) "%s(): " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/version.h>
+#include <linux/input.h>
+#include "config.h"
+#include "tfa98xx.h"
+#include "tfa.h"
+
+ /* required for enum tfa9912_irq */
+#include "tfa98xx_tfafieldnames.h"
+
+#define TFA98XX_VERSION TFA98XX_API_REV_STR
+
+#define I2C_RETRIES 50
+#define I2C_RETRY_DELAY 5 /* ms */
+
+/* Change volume selection behavior:
+ * Uncomment following line to generate a profile change when updating
+ * a volume control (also changes to the profile of the modified volume
+ * control)
+ */
+ /*#define TFA98XX_ALSA_CTRL_PROF_CHG_ON_VOL 1
+ */
+
+ /* Supported rates and data formats */
+#define TFA98XX_RATES SNDRV_PCM_RATE_8000_48000
+#define TFA98XX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+#define TF98XX_MAX_DSP_START_TRY_COUNT 10
+
+/* data accessible by all instances */
+static struct kmem_cache *tfa98xx_cache = NULL; /* Memory pool used for DSP messages */
+/* Mutex protected data */
+static DEFINE_MUTEX(tfa98xx_mutex);
+static LIST_HEAD(tfa98xx_device_list);
+static int tfa98xx_device_count = 0;
+static int tfa98xx_sync_count = 0;
+static LIST_HEAD(profile_list); /* list of user selectable profiles */
+static int tfa98xx_mixer_profiles = 0; /* number of user selectable profiles */
+static int tfa98xx_mixer_profile = 0; /* current mixer profile */
+static struct snd_kcontrol_new *tfa98xx_controls;
+static TfaContainer_t *tfa98xx_container = NULL;
+
+static int tfa98xx_kmsg_regs = 0;
+static int tfa98xx_ftrace_regs = 0;
+
+static char *fw_name = "tfa98xx.cnt";
+module_param(fw_name, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(fw_name, "TFA98xx DSP firmware (container file) name.");
+
+static int trace_level = 0;
+module_param(trace_level, int, S_IRUGO);
+MODULE_PARM_DESC(trace_level, "TFA98xx debug trace level (0=off, bits:1=verbose,2=regdmesg,3=regftrace,4=timing).");
+
+static char *dflt_prof_name = "";
+module_param(dflt_prof_name, charp, S_IRUGO);
+
+static int no_start = 0;
+module_param(no_start, int, S_IRUGO);
+MODULE_PARM_DESC(no_start, "do not start the work queue; for debugging via user\n");
+
+static int no_reset = 0;
+module_param(no_reset, int, S_IRUGO);
+MODULE_PARM_DESC(no_reset, "do not use the reset line; for debugging via user\n");
+
+static int pcm_sample_format = 0; /*Be carefull: setting pcm_sample_format to 3 means TDM settings will be dynamically adapted, please do not set the
+HW TDM Setting in the container file in case of dynamic sample format seletcion*/
+module_param(pcm_sample_format, int, S_IRUGO);
+MODULE_PARM_DESC(pcm_sample_format, "PCM sample format: 0=S16_LE, 1=S24_LE, 2=S32_LE, 3=dynamic\n");
+
+static int pcm_no_constraint = 0;
+module_param(pcm_no_constraint, int, S_IRUGO);
+MODULE_PARM_DESC(pcm_no_constraint, "do not use constraints for PCM parameters\n");
+
+static void tfa98xx_tapdet_check_update(struct tfa98xx *tfa98xx);
+static int tfa98xx_get_fssel(unsigned int rate);
+static void tfa98xx_interrupt_enable(struct tfa98xx *tfa98xx, bool enable);
+
+static int get_profile_from_list(char *buf, int id);
+static int get_profile_id_for_sr(int id, unsigned int rate);
+
+struct tfa98xx_rate {
+ unsigned int rate;
+ unsigned int fssel;
+};
+
+static const struct tfa98xx_rate rate_to_fssel[] = {
+ { 8000, 0 },
+ { 11025, 1 },
+ { 12000, 2 },
+ { 16000, 3 },
+ { 22050, 4 },
+ { 24000, 5 },
+ { 32000, 6 },
+ { 44100, 7 },
+ { 48000, 8 },
+};
+
+
+static inline char *tfa_cont_profile_name(struct tfa98xx *tfa98xx, int prof_idx)
+{
+ if (tfa98xx->tfa->cnt == NULL)
+ return NULL;
+ return tfaContProfileName(tfa98xx->tfa->cnt, tfa98xx->tfa->dev_idx, prof_idx);
+}
+
+static enum tfa_error tfa98xx_write_re25(struct tfa_device *tfa, int value)
+{
+ enum tfa_error err;
+
+ /* clear MTPEX */
+ err = tfa_dev_mtp_set(tfa, TFA_MTP_EX, 0);
+ if (err == tfa_error_ok) {
+ /* set RE25 in shadow regiser */
+ err = tfa_dev_mtp_set(tfa, TFA_MTP_RE25_PRIM, value);
+ }
+ if (err == tfa_error_ok) {
+ /* set MTPEX to copy RE25 into MTP */
+ err = tfa_dev_mtp_set(tfa, TFA_MTP_EX, 2);
+ }
+
+ return err;
+}
+
+/* Wrapper for tfa start */
+static enum tfa_error tfa98xx_tfa_start(struct tfa98xx *tfa98xx, int next_profile, int vstep)
+{
+ enum tfa_error err;
+ ktime_t start_time, stop_time;
+ u64 delta_time;
+
+ start_time = ktime_get_boottime();
+ err = tfa_dev_start(tfa98xx->tfa, next_profile, vstep);
+
+ if (trace_level & 8) {
+ stop_time = ktime_get_boottime();
+ delta_time = ktime_to_ns(ktime_sub(stop_time, start_time));
+ do_div(delta_time, 1000);
+ dev_dbg(&tfa98xx->i2c->dev, "tfa_dev_start(%d,%d) time = %lld us\n",
+ next_profile, vstep, delta_time);
+ }
+
+ if ((err == tfa_error_ok) && (tfa98xx->set_mtp_cal)) {
+ enum tfa_error err_cal;
+ err_cal = tfa98xx_write_re25(tfa98xx->tfa, tfa98xx->cal_data);
+ if (err_cal != tfa_error_ok) {
+ pr_err("Error, setting calibration value in mtp, err=%d\n", err_cal);
+ }
+ else {
+ tfa98xx->set_mtp_cal = false;
+ pr_info("Calibration value (%d) set in mtp\n",
+ tfa98xx->cal_data);
+ }
+ }
+
+ /* Check and update tap-detection state (in case of profile change) */
+ tfa98xx_tapdet_check_update(tfa98xx);
+
+ /* Remove sticky bit by reading it once */
+ tfa_get_noclk(tfa98xx->tfa);
+
+ /* A cold start erases the configuration, including interrupts setting.
+ * Restore it if required
+ */
+ tfa98xx_interrupt_enable(tfa98xx, true);
+
+ return err;
+}
+
+static int tfa98xx_input_open(struct input_dev *dev)
+{
+ struct tfa98xx *tfa98xx = input_get_drvdata(dev);
+ dev_dbg(tfa98xx->codec->dev, "opening device file\n");
+
+ /* note: open function is called only once by the framework.
+ * No need to count number of open file instances.
+ */
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK) {
+ dev_dbg(&tfa98xx->i2c->dev,
+ "DSP not loaded, cannot start tap-detection\n");
+ return -EIO;
+ }
+
+ /* enable tap-detection service */
+ tfa98xx->tapdet_open = true;
+ tfa98xx_tapdet_check_update(tfa98xx);
+
+ return 0;
+}
+
+static void tfa98xx_input_close(struct input_dev *dev)
+{
+ struct tfa98xx *tfa98xx = input_get_drvdata(dev);
+
+ dev_dbg(tfa98xx->codec->dev, "closing device file\n");
+
+ /* Note: close function is called if the device is unregistered */
+
+ /* disable tap-detection service */
+ tfa98xx->tapdet_open = false;
+ tfa98xx_tapdet_check_update(tfa98xx);
+}
+
+static int tfa98xx_register_inputdev(struct tfa98xx *tfa98xx)
+{
+ int err;
+ struct input_dev *input;
+ input = input_allocate_device();
+
+ if (!input) {
+ dev_err(tfa98xx->codec->dev, "Unable to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ input->evbit[0] = BIT_MASK(EV_KEY);
+ input->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
+ input->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
+ input->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
+ input->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
+ input->keybit[BIT_WORD(BTN_4)] |= BIT_MASK(BTN_4);
+ input->keybit[BIT_WORD(BTN_5)] |= BIT_MASK(BTN_5);
+ input->keybit[BIT_WORD(BTN_6)] |= BIT_MASK(BTN_6);
+ input->keybit[BIT_WORD(BTN_7)] |= BIT_MASK(BTN_7);
+ input->keybit[BIT_WORD(BTN_8)] |= BIT_MASK(BTN_8);
+ input->keybit[BIT_WORD(BTN_9)] |= BIT_MASK(BTN_9);
+
+ input->open = tfa98xx_input_open;
+ input->close = tfa98xx_input_close;
+
+ input->name = "tfa98xx-tapdetect";
+
+ input->id.bustype = BUS_I2C;
+ input_set_drvdata(input, tfa98xx);
+
+ err = input_register_device(input);
+ if (err) {
+ dev_err(tfa98xx->codec->dev, "Unable to register input device\n");
+ goto err_free_dev;
+ }
+
+ dev_dbg(tfa98xx->codec->dev, "Input device for tap-detection registered: %s\n",
+ input->name);
+ tfa98xx->input = input;
+ return 0;
+
+err_free_dev:
+ input_free_device(input);
+ return err;
+}
+
+/*
+ * Check if an input device for tap-detection can and shall be registered.
+ * Register it if appropriate.
+ * If already registered, check if still relevant and remove it if necessary.
+ * unregister: true to request inputdev unregistration.
+ */
+static void __tfa98xx_inputdev_check_register(struct tfa98xx *tfa98xx, bool unregister)
+{
+ bool tap_profile = false;
+ unsigned int i;
+ for (i = 0; i < tfa_cnt_get_dev_nprof(tfa98xx->tfa); i++) {
+ if (strstr(tfa_cont_profile_name(tfa98xx, i), ".tap")) {
+ tap_profile = true;
+ tfa98xx->tapdet_profiles |= 1 << i;
+ dev_dbg(tfa98xx->codec->dev,
+ "found a tap-detection profile (%d - %s)\n",
+ i, tfa_cont_profile_name(tfa98xx, i));
+ }
+ }
+
+ /* Check for device support:
+ * - at device level
+ * - at container (profile) level
+ */
+ if (!(tfa98xx->flags & TFA98XX_FLAG_TAPDET_AVAILABLE) ||
+ !tap_profile ||
+ unregister) {
+ /* No input device supported or required */
+ if (tfa98xx->input) {
+ input_unregister_device(tfa98xx->input);
+ tfa98xx->input = NULL;
+ }
+ return;
+ }
+
+ /* input device required */
+ if (tfa98xx->input)
+ dev_dbg(tfa98xx->codec->dev, "Input device already registered, skipping\n");
+ else
+ tfa98xx_register_inputdev(tfa98xx);
+}
+
+static void tfa98xx_inputdev_check_register(struct tfa98xx *tfa98xx)
+{
+ __tfa98xx_inputdev_check_register(tfa98xx, false);
+}
+
+static void tfa98xx_inputdev_unregister(struct tfa98xx *tfa98xx)
+{
+ __tfa98xx_inputdev_check_register(tfa98xx, true);
+}
+
+#ifdef CONFIG_DEBUG_FS
+/* OTC reporting
+ * Returns the MTP0 OTC bit value
+ */
+static int tfa98xx_dbgfs_otc_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int value;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ value = tfa_dev_mtp_get(tfa98xx->tfa, TFA_MTP_OTC);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (value < 0) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, value);
+ return -EIO;
+ }
+
+ *val = value;
+ /* pr_debug("[0x%x] OTC : %d\n", tfa98xx->i2c->addr, value); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_otc_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error err;
+
+ if (val != 0 && val != 1) {
+ pr_err("[0x%x] Unexpected value %llu\n", tfa98xx->i2c->addr, val);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ err = tfa_dev_mtp_set(tfa98xx->tfa, TFA_MTP_OTC, val);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (err != tfa_error_ok) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, err);
+ return -EIO;
+ }
+
+ /* pr_debug("[0x%x] OTC < %llu\n", tfa98xx->i2c->addr, val); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_mtpex_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int value;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ value = tfa_dev_mtp_get(tfa98xx->tfa, TFA_MTP_EX);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (value < 0) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, value);
+ return -EIO;
+ }
+
+
+ *val = value;
+ /* pr_debug("[0x%x] MTPEX : %d\n", tfa98xx->i2c->addr, value); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_mtpex_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error err;
+
+ if (val != 0) {
+ pr_err("[0x%x] Can only clear MTPEX (0 value expected)\n", tfa98xx->i2c->addr);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ err = tfa_dev_mtp_set(tfa98xx->tfa, TFA_MTP_EX, val);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (err != tfa_error_ok) {
+ pr_err("[0x%x] Unable to check DSP access: %d\n", tfa98xx->i2c->addr, err);
+ return -EIO;
+ }
+
+ /* pr_debug("[0x%x] MTPEX < 0\n", tfa98xx->i2c->addr); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_temp_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ *val = tfa98xx_get_exttemp(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ /* pr_debug("[0x%x] TEMP : %llu\n", tfa98xx->i2c->addr, *val); */
+
+ return 0;
+}
+
+static int tfa98xx_dbgfs_temp_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa98xx_set_exttemp(tfa98xx->tfa, (short)val);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ /* pr_debug("[0x%x] TEMP < %llu\n", tfa98xx->i2c->addr, val); */
+
+ return 0;
+}
+
+static ssize_t tfa98xx_dbgfs_start_set(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error ret;
+ char buf[32];
+ const char ref[] = "please calibrate now";
+ int buf_size, cal_profile = 0;
+
+ /* check string length, and account for eol */
+ if (count > sizeof(ref) + 1 || count < (sizeof(ref) - 1))
+ return -EINVAL;
+
+ buf_size = min(count, (size_t)(sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ /* Compare string, excluding the trailing \0 and the potentials eol */
+ if (strncmp(buf, ref, sizeof(ref) - 1))
+ return -EINVAL;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa_calibrate(tfa98xx->tfa);
+ if (ret == tfa_error_ok) {
+ cal_profile = tfaContGetCalProfile(tfa98xx->tfa);
+ if (cal_profile < 0) {
+ pr_warn("[0x%x] Calibration profile not found\n",
+ tfa98xx->i2c->addr);
+ }
+
+ ret = tfa98xx_tfa_start(tfa98xx, cal_profile, tfa98xx->vstep);
+ }
+ if (ret == tfa_error_ok)
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (ret) {
+ pr_info("[0x%x] Calibration start failed (%d)\n", tfa98xx->i2c->addr, ret);
+ return -EIO;
+ }
+ else {
+ pr_info("[0x%x] Calibration started\n", tfa98xx->i2c->addr);
+ }
+
+ return count;
+}
+
+static ssize_t tfa98xx_dbgfs_r_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ char *str;
+ uint16_t status;
+ int ret;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+
+ /* Need to ensure DSP is access-able, use mtp read access for this
+ * purpose
+ */
+ ret = tfa98xx_get_mtp(tfa98xx->tfa, &status);
+ if (ret) {
+ ret = -EIO;
+ pr_err("[0x%x] MTP read failed\n", tfa98xx->i2c->addr);
+ goto r_c_err;
+ }
+
+ ret = tfaRunSpeakerCalibration(tfa98xx->tfa);
+ if (ret) {
+ ret = -EIO;
+ pr_err("[0x%x] calibration failed\n", tfa98xx->i2c->addr);
+ goto r_c_err;
+ }
+
+ str = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!str) {
+ ret = -ENOMEM;
+ pr_err("[0x%x] memory allocation failed\n", tfa98xx->i2c->addr);
+ goto r_c_err;
+ }
+
+ if (tfa98xx->tfa->spkr_count > 1) {
+ ret = snprintf(str, PAGE_SIZE,
+ "Prim:%d mOhms, Sec:%d mOhms\n",
+ tfa98xx->tfa->mohm[0],
+ tfa98xx->tfa->mohm[1]);
+ }
+ else {
+ ret = snprintf(str, PAGE_SIZE,
+ "Prim:%d mOhms\n",
+ tfa98xx->tfa->mohm[0]);
+ }
+
+ /* pr_debug("[0x%x] calib_done: %s", tfa98xx->i2c->addr, str); */
+
+ if (ret < 0)
+ goto r_err;
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, str, ret);
+
+r_err:
+ kfree(str);
+r_c_err:
+ mutex_unlock(&tfa98xx->dsp_lock);
+ return ret;
+}
+
+static ssize_t tfa98xx_dbgfs_version_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ char str[] = TFA98XX_VERSION "\n";
+ int ret;
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, str, sizeof(str));
+
+ return ret;
+}
+
+static ssize_t tfa98xx_dbgfs_dsp_state_get(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int ret = 0;
+ char *str;
+
+ switch (tfa98xx->dsp_init) {
+ case TFA98XX_DSP_INIT_STOPPED:
+ str = "Stopped\n";
+ break;
+ case TFA98XX_DSP_INIT_RECOVER:
+ str = "Recover requested\n";
+ break;
+ case TFA98XX_DSP_INIT_FAIL:
+ str = "Failed init\n";
+ break;
+ case TFA98XX_DSP_INIT_PENDING:
+ str = "Pending init\n";
+ break;
+ case TFA98XX_DSP_INIT_DONE:
+ str = "Init complete\n";
+ break;
+ default:
+ str = "Invalid\n";
+ }
+
+ /* pr_debug("[0x%x] dsp_state : %s\n", tfa98xx->i2c->addr, str); */
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, str, strlen(str));
+ return ret;
+}
+
+static ssize_t tfa98xx_dbgfs_dsp_state_set(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ enum tfa_error ret;
+ char buf[32];
+ const char start_cmd[] = "start";
+ const char stop_cmd[] = "stop";
+ const char mon_start_cmd[] = "monitor start";
+ const char mon_stop_cmd[] = "monitor stop";
+ int buf_size;
+
+ buf_size = min(count, (size_t)(sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ /* Compare strings, excluding the trailing \0 */
+ if (!strncmp(buf, start_cmd, sizeof(start_cmd) - 1)) {
+ pr_info("[0x%x] Manual triggering of dsp start...\n", tfa98xx->i2c->addr);
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ /* pr_debug("[0x%x] tfa_dev_start complete: %d\n", tfa98xx->i2c->addr, ret); */
+ }
+ else if (!strncmp(buf, stop_cmd, sizeof(stop_cmd) - 1)) {
+ pr_info("[0x%x] Manual triggering of dsp stop...\n", tfa98xx->i2c->addr);
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa_dev_stop(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ /* pr_debug("[0x%x] tfa_dev_stop complete: %d\n", tfa98xx->i2c->addr, ret); */
+ }
+ else if (!strncmp(buf, mon_start_cmd, sizeof(mon_start_cmd) - 1)) {
+ pr_info("[0x%x] Manual start of monitor thread...\n", tfa98xx->i2c->addr);
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->monitor_work, HZ);
+ }
+ else if (!strncmp(buf, mon_stop_cmd, sizeof(mon_stop_cmd) - 1)) {
+ pr_info("[0x%x] Manual stop of monitor thread...\n", tfa98xx->i2c->addr);
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+ }
+ else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t tfa98xx_dbgfs_fw_state_get(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ char *str;
+
+ switch (tfa98xx->dsp_fw_state) {
+ case TFA98XX_DSP_FW_NONE:
+ str = "None\n";
+ break;
+ case TFA98XX_DSP_FW_PENDING:
+ str = "Pending\n";
+ break;
+ case TFA98XX_DSP_FW_FAIL:
+ str = "Fail\n";
+ break;
+ case TFA98XX_DSP_FW_OK:
+ str = "Ok\n";
+ break;
+ default:
+ str = "Invalid\n";
+ }
+
+ /* pr_debug("[0x%x] fw_state : %s", tfa98xx->i2c->addr, str); */
+
+ return simple_read_from_buffer(user_buf, count, ppos, str, strlen(str));
+}
+
+static ssize_t tfa98xx_dbgfs_rpc_read(struct file *file,
+ char __user *user_buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ int ret = 0;
+ uint8_t *buffer;
+ enum Tfa98xx_Error error;
+
+ if (tfa98xx->tfa == NULL) {
+ /* pr_debug("[0x%x] dsp is not available\n", tfa98xx->i2c->addr); */
+ return -ENODEV;
+ }
+
+ if (count == 0)
+ return 0;
+
+ buffer = kmalloc(count, GFP_KERNEL);
+ if (buffer == NULL) {
+ /* pr_debug("[0x%x] can not allocate memory\n", tfa98xx->i2c->addr); */
+ return -ENOMEM;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ error = tfa_dsp_msg_read(tfa98xx->tfa, count, buffer);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ if (error != Tfa98xx_Error_Ok) {
+ /* pr_debug("[0x%x] tfa_dsp_msg_read error: %d\n", tfa98xx->i2c->addr, error); */
+ kfree(buffer);
+ return -EFAULT;
+ }
+
+ ret = copy_to_user(user_buf, buffer, count);
+ kfree(buffer);
+ if (ret)
+ return -EFAULT;
+
+ *ppos += count;
+ return count;
+}
+
+static ssize_t tfa98xx_dbgfs_rpc_send(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct i2c_client *i2c = file->private_data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ TfaFileDsc_t *msg_file;
+ enum Tfa98xx_Error error;
+ int err = 0;
+
+ if (tfa98xx->tfa == NULL) {
+ /* pr_debug("[0x%x] dsp is not available\n", tfa98xx->i2c->addr); */
+ return -ENODEV;
+ }
+
+ if (count == 0)
+ return 0;
+
+ /* msg_file.name is not used */
+ msg_file = kmalloc(count + sizeof(TfaFileDsc_t), GFP_KERNEL);
+ if (msg_file == NULL) {
+ /* pr_debug("[0x%x] can not allocate memory\n", tfa98xx->i2c->addr); */
+ return -ENOMEM;
+ }
+ msg_file->size = count;
+
+ if (copy_from_user(msg_file->data, user_buf, count))
+ return -EFAULT;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ if ((msg_file->data[0] == 'M') && (msg_file->data[1] == 'G')) {
+ error = tfaContWriteFile(tfa98xx->tfa, msg_file, 0, 0); /* int vstep_idx, int vstep_msg_idx both 0 */
+ if (error != Tfa98xx_Error_Ok) {
+ /* pr_debug("[0x%x] tfaContWriteFile error: %d\n", tfa98xx->i2c->addr, error); */
+ err = -EIO;
+ }
+ }
+ else {
+ error = tfa_dsp_msg(tfa98xx->tfa, msg_file->size, msg_file->data);
+ if (error != Tfa98xx_Error_Ok) {
+ /* pr_debug("[0x%x] dsp_msg error: %d\n", tfa98xx->i2c->addr, error); */
+ err = -EIO;
+ }
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ kfree(msg_file);
+
+ if (err)
+ return err;
+ return count;
+}
+/* -- RPC */
+
+static int tfa98xx_dbgfs_pga_gain_get(void *data, u64 *val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ unsigned int value;
+
+ value = tfa_get_pga_gain(tfa98xx->tfa);
+ if (value < 0)
+ return -EINVAL;
+
+ *val = value;
+ return 0;
+}
+
+static int tfa98xx_dbgfs_pga_gain_set(void *data, u64 val)
+{
+ struct i2c_client *i2c = (struct i2c_client *)data;
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+ uint16_t value;
+ int err;
+
+ value = val & 0xffff;
+ if (value > 7)
+ return -EINVAL;
+
+ err = tfa_set_pga_gain(tfa98xx->tfa, value);
+ if (err < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_calib_otc_fops, tfa98xx_dbgfs_otc_get,
+ tfa98xx_dbgfs_otc_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_calib_mtpex_fops, tfa98xx_dbgfs_mtpex_get,
+ tfa98xx_dbgfs_mtpex_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_calib_temp_fops, tfa98xx_dbgfs_temp_get,
+ tfa98xx_dbgfs_temp_set, "%llu\n");
+
+DEFINE_SIMPLE_ATTRIBUTE(tfa98xx_dbgfs_pga_gain_fops, tfa98xx_dbgfs_pga_gain_get,
+ tfa98xx_dbgfs_pga_gain_set, "%llu\n");
+
+static const struct file_operations tfa98xx_dbgfs_calib_start_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .write = tfa98xx_dbgfs_start_set,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_r_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_r_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_version_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_version_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_dsp_state_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_dsp_state_get,
+ .write = tfa98xx_dbgfs_dsp_state_set,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_fw_state_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_fw_state_get,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations tfa98xx_dbgfs_rpc_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = tfa98xx_dbgfs_rpc_read,
+ .write = tfa98xx_dbgfs_rpc_send,
+ .llseek = default_llseek,
+};
+
+static void tfa98xx_debug_init(struct tfa98xx *tfa98xx, struct i2c_client *i2c)
+{
+ char name[50];
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s-%x", i2c->name, i2c->addr);
+ tfa98xx->dbg_dir = debugfs_create_dir(name, NULL);
+ debugfs_create_file("OTC", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_otc_fops);
+ debugfs_create_file("MTPEX", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_mtpex_fops);
+ debugfs_create_file("TEMP", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_temp_fops);
+ debugfs_create_file("calibrate", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_calib_start_fops);
+ debugfs_create_file("R", S_IRUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_r_fops);
+ debugfs_create_file("version", S_IRUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_version_fops);
+ debugfs_create_file("dsp-state", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_dsp_state_fops);
+ debugfs_create_file("fw-state", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_fw_state_fops);
+ debugfs_create_file("rpc", S_IRUGO | S_IWUGO, tfa98xx->dbg_dir,
+ i2c, &tfa98xx_dbgfs_rpc_fops);
+
+ if (tfa98xx->flags & TFA98XX_FLAG_SAAM_AVAILABLE) {
+ dev_dbg(tfa98xx->dev, "Adding pga_gain debug interface\n");
+ debugfs_create_file("pga_gain", S_IRUGO, tfa98xx->dbg_dir,
+ tfa98xx->i2c,
+ &tfa98xx_dbgfs_pga_gain_fops);
+ }
+}
+
+static void tfa98xx_debug_remove(struct tfa98xx *tfa98xx)
+{
+ if (tfa98xx->dbg_dir)
+ debugfs_remove_recursive(tfa98xx->dbg_dir);
+}
+#endif
+
+
+/* copies the profile basename (i.e. part until .) into buf */
+static void get_profile_basename(char* buf, char* profile)
+{
+ int cp_len = 0, idx = 0;
+ char *pch;
+
+ pch = strchr(profile, '.');
+ idx = pch - profile;
+ cp_len = (pch != NULL) ? idx : (int)strlen(profile);
+ memcpy(buf, profile, cp_len);
+ buf[cp_len] = 0;
+}
+
+/* return the profile name accociated with id from the profile list */
+static int get_profile_from_list(char *buf, int id)
+{
+ struct tfa98xx_baseprofile *bprof;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+ if (bprof->item_id == id) {
+ strcpy(buf, bprof->basename);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* search for the profile in the profile list */
+static int is_profile_in_list(char *profile, int len)
+{
+ struct tfa98xx_baseprofile *bprof;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+
+ if ((len == bprof->len) && (0 == strncmp(bprof->basename, profile, len)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * for the profile with id, look if the requested samplerate is
+ * supported, if found return the (container)profile for this
+ * samplerate, on error or if not found return -1
+ */
+static int get_profile_id_for_sr(int id, unsigned int rate)
+{
+ int idx = 0;
+ struct tfa98xx_baseprofile *bprof;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+ if (id == bprof->item_id) {
+ idx = tfa98xx_get_fssel(rate);
+ if (idx < 0) {
+ /* samplerate not supported */
+ return -1;
+ }
+
+ return bprof->sr_rate_sup[idx];
+ }
+ }
+
+ /* profile not found */
+ return -1;
+}
+
+/* check if this profile is a calibration profile */
+static int is_calibration_profile(char *profile)
+{
+ if (strstr(profile, ".cal") != NULL)
+ return 1;
+ return 0;
+}
+
+/*
+ * adds the (container)profile index of the samplerate found in
+ * the (container)profile to a fixed samplerate table in the (mixer)profile
+ */
+static int add_sr_to_profile(struct tfa98xx *tfa98xx, char *basename, int len, int profile)
+{
+ struct tfa98xx_baseprofile *bprof;
+ int idx = 0;
+ unsigned int sr = 0;
+
+ list_for_each_entry(bprof, &profile_list, list) {
+ if ((len == bprof->len) && (0 == strncmp(bprof->basename, basename, len))) {
+ /* add supported samplerate for this profile */
+ sr = tfa98xx_get_profile_sr(tfa98xx->tfa, profile);
+ if (!sr) {
+ pr_err("unable to identify supported sample rate for %s\n", bprof->basename);
+ return -1;
+ }
+
+ /* get the index for this samplerate */
+ idx = tfa98xx_get_fssel(sr);
+ if (idx < 0 || idx >= TFA98XX_NUM_RATES) {
+ pr_err("invalid index for samplerate %d\n", idx);
+ return -1;
+ }
+
+ /* enter the (container)profile for this samplerate at the corresponding index */
+ bprof->sr_rate_sup[idx] = profile;
+
+ /* pr_debug("added profile:samplerate = [%d:%d] for mixer profile: %s\n", profile, sr, bprof->basename); */
+ }
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
+static struct snd_soc_codec *snd_soc_kcontrol_codec(struct snd_kcontrol *kcontrol)
+{
+ return snd_kcontrol_chip(kcontrol);
+}
+#endif
+
+static int tfa98xx_get_vstep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int mixer_profile = kcontrol->private_value;
+ int ret = 0;
+ int profile;
+
+ profile = get_profile_id_for_sr(mixer_profile, tfa98xx->rate);
+ if (profile < 0) {
+ pr_err("tfa98xx: tfa98xx_get_vstep: invalid profile %d (mixer_profile=%d, rate=%d)\n", profile, mixer_profile, tfa98xx->rate);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int vstep = tfa98xx->prof_vsteps[profile];
+
+ ucontrol->value.integer.value[tfa98xx->tfa->dev_idx] =
+ tfacont_get_max_vstep(tfa98xx->tfa, profile)
+ - vstep - 1;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return ret;
+}
+
+static int tfa98xx_set_vstep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int mixer_profile = kcontrol->private_value;
+ int profile;
+ int err = 0;
+ int change = 0;
+
+ if (no_start != 0)
+ return 0;
+
+ profile = get_profile_id_for_sr(mixer_profile, tfa98xx->rate);
+ if (profile < 0) {
+ pr_err("tfa98xx: tfa98xx_set_vstep: invalid profile %d (mixer_profile=%d, rate=%d)\n", profile, mixer_profile, tfa98xx->rate);
+ return -EINVAL;
+ }
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int vstep, vsteps;
+ int ready = 0;
+ int new_vstep;
+ int value = ucontrol->value.integer.value[tfa98xx->tfa->dev_idx];
+
+ vstep = tfa98xx->prof_vsteps[profile];
+ vsteps = tfacont_get_max_vstep(tfa98xx->tfa, profile);
+
+ if (vstep == vsteps - value - 1)
+ continue;
+
+ new_vstep = vsteps - value - 1;
+
+ if (new_vstep < 0)
+ new_vstep = 0;
+
+ tfa98xx->prof_vsteps[profile] = new_vstep;
+
+#ifndef TFA98XX_ALSA_CTRL_PROF_CHG_ON_VOL
+ if (profile == tfa98xx->profile) {
+#endif
+ /* this is the active profile, program the new vstep */
+ tfa98xx->vstep = new_vstep;
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa98xx_dsp_system_stable(tfa98xx->tfa, &ready);
+
+ if (ready) {
+ err = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ if (err) {
+ pr_err("Write vstep error: %d\n", err);
+ }
+ else {
+ /* pr_debug("Succesfully changed vstep index!\n"); */
+ change = 1;
+ }
+ }
+
+ mutex_unlock(&tfa98xx->dsp_lock);
+#ifndef TFA98XX_ALSA_CTRL_PROF_CHG_ON_VOL
+ }
+#endif
+ /* pr_debug("%d: vstep:%d, (control value: %d) - profile %d\n",
+ tfa98xx->tfa->dev_idx, new_vstep, value, profile); */
+ }
+
+ if (change) {
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ }
+
+ mutex_unlock(&tfa98xx_mutex);
+
+ return change;
+}
+
+static int tfa98xx_info_vstep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+
+ int mixer_profile = tfa98xx_mixer_profile;
+ int profile = get_profile_id_for_sr(mixer_profile, tfa98xx->rate);
+ if (profile < 0) {
+ pr_err("tfa98xx: tfa98xx_info_vstep: invalid profile %d (mixer_profile=%d, rate=%d)\n", profile, mixer_profile, tfa98xx->rate);
+ return -EINVAL;
+ }
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ mutex_lock(&tfa98xx_mutex);
+ uinfo->count = tfa98xx_device_count;
+ mutex_unlock(&tfa98xx_mutex);
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = max(0, tfacont_get_max_vstep(tfa98xx->tfa, profile) - 1);
+ /* pr_debug("vsteps count: %d [prof=%d]\n", tfacont_get_max_vstep(tfa98xx->tfa, profile),
+ profile); */
+ return 0;
+}
+
+static int tfa98xx_get_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&tfa98xx_mutex);
+ ucontrol->value.integer.value[0] = tfa98xx_mixer_profile;
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static int tfa98xx_set_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int change = 0;
+ int new_profile;
+ int prof_idx, cur_prof_idx;
+ int profile_count = tfa98xx_mixer_profiles;
+ int profile = tfa98xx_mixer_profile;
+
+ if (no_start != 0)
+ return 0;
+
+ new_profile = ucontrol->value.integer.value[0];
+ if (new_profile == profile)
+ return 0;
+
+ if ((new_profile < 0) || (new_profile >= profile_count)) {
+ pr_err("not existing profile (%d)\n", new_profile);
+ return -EINVAL;
+ }
+
+ /* get the container profile for the requested sample rate */
+ prof_idx = get_profile_id_for_sr(new_profile, tfa98xx->rate);
+ cur_prof_idx = get_profile_id_for_sr(profile, tfa98xx->rate);
+ if (prof_idx < 0 || cur_prof_idx < 0) {
+ pr_err("tfa98xx: sample rate [%d] not supported for this mixer profile [%d -> %d].\n",
+ tfa98xx->rate, profile, new_profile);
+ return 0;
+ }
+ /* pr_debug("selected container profile [%d -> %d]\n", cur_prof_idx, prof_idx); */
+ /* pr_debug("switch profile [%s -> %s]\n",
+ tfa_cont_profile_name(tfa98xx, cur_prof_idx),
+ tfa_cont_profile_name(tfa98xx, prof_idx)); */
+
+ /* update mixer profile */
+ tfa98xx_mixer_profile = new_profile;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int err;
+ int ready = 0;
+
+ /* update 'real' profile (container profile) */
+ tfa98xx->profile = prof_idx;
+ tfa98xx->vstep = tfa98xx->prof_vsteps[prof_idx];
+
+ /* Don't call tfa_dev_start() if there is no clock. */
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa98xx_dsp_system_stable(tfa98xx->tfa, &ready);
+ if (strstr(tfa_cont_profile_name(tfa98xx, cur_prof_idx), ".standby") != NULL) {
+ pr_info("Force to start at exiting from standby: [%d -> %d]\n",
+ cur_prof_idx, prof_idx);
+ ready = 1;
+ }
+ if (ready) {
+ /* Also re-enables the interrupts */
+ err = tfa98xx_tfa_start(tfa98xx, prof_idx, tfa98xx->vstep);
+ if (err) {
+ pr_info("Write profile error: %d\n", err);
+ }
+ else {
+ /* pr_debug("Changed to profile %d (vstep = %d)\n",
+ prof_idx, tfa98xx->vstep); */
+ change = 1;
+ }
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ /* Flag DSP as invalidated as the profile change may invalidate the
+ * current DSP configuration. That way, further stream start can
+ * trigger a tfa_dev_start.
+ */
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_INVALIDATED;
+ }
+
+ if (change) {
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ }
+
+ mutex_unlock(&tfa98xx_mutex);
+
+ return change;
+}
+
+static int tfa98xx_info_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ char profile_name[MAX_CONTROL_NAME] = { 0 };
+ int count = tfa98xx_mixer_profiles, err = -1;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = count;
+
+ if (uinfo->value.enumerated.item >= count)
+ uinfo->value.enumerated.item = count - 1;
+
+ err = get_profile_from_list(profile_name, uinfo->value.enumerated.item);
+ if (err != 0)
+ return -EINVAL;
+
+ strcpy(uinfo->value.enumerated.name, profile_name);
+
+ return 0;
+}
+
+static int tfa98xx_info_stop_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ mutex_lock(&tfa98xx_mutex);
+ uinfo->count = tfa98xx_device_count;
+ mutex_unlock(&tfa98xx_mutex);
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+
+ return 0;
+}
+
+static int tfa98xx_get_stop_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ ucontrol->value.integer.value[tfa98xx->tfa->dev_idx] = 0;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static int tfa98xx_set_stop_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ int ready = 0;
+ int i = tfa98xx->tfa->dev_idx;
+
+ /* pr_debug("%d: %ld\n", i, ucontrol->value.integer.value[i]); */
+
+ tfa98xx_dsp_system_stable(tfa98xx->tfa, &ready);
+
+ if ((ucontrol->value.integer.value[i] != 0) && ready) {
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK)
+ continue;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_stop(tfa98xx->tfa);
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_STOPPED;
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+
+ ucontrol->value.integer.value[i] = 0;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 1;
+}
+
+static int tfa98xx_info_cal_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ mutex_lock(&tfa98xx_mutex);
+ uinfo->count = tfa98xx_device_count;
+ mutex_unlock(&tfa98xx_mutex);
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xffff; /* 16 bit value */
+
+ return 0;
+}
+
+static int tfa98xx_set_cal_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ enum tfa_error err;
+ int i = tfa98xx->tfa->dev_idx;
+
+ tfa98xx->cal_data = (uint16_t)ucontrol->value.integer.value[i];
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ err = tfa98xx_write_re25(tfa98xx->tfa, tfa98xx->cal_data);
+ tfa98xx->set_mtp_cal = (err != tfa_error_ok);
+ if (tfa98xx->set_mtp_cal == false) {
+ pr_info("Calibration value (%d) set in mtp\n",
+ tfa98xx->cal_data);
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 1;
+}
+
+static int tfa98xx_get_cal_ctl(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tfa98xx *tfa98xx;
+
+ mutex_lock(&tfa98xx_mutex);
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ ucontrol->value.integer.value[tfa98xx->tfa->dev_idx] = tfa_dev_mtp_get(tfa98xx->tfa, TFA_MTP_RE25_PRIM);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static int tfa98xx_create_controls(struct tfa98xx *tfa98xx)
+{
+ int prof, nprof, mix_index = 0;
+ int nr_controls = 0, id = 0;
+ char *name;
+ struct tfa98xx_baseprofile *bprofile;
+
+ /* Create the following controls:
+ * - enum control to select the active profile
+ * - one volume control for each profile hosting a vstep
+ * - Stop control on TFA1 devices
+ */
+
+ nr_controls = 2; /* Profile and stop control */
+
+ if (tfa98xx->flags & TFA98XX_FLAG_CALIBRATION_CTL)
+ nr_controls += 1; /* calibration */
+
+ /* allocate the tfa98xx_controls base on the nr of profiles */
+ nprof = tfa_cnt_get_dev_nprof(tfa98xx->tfa);
+ for (prof = 0; prof < nprof; prof++) {
+ if (tfacont_get_max_vstep(tfa98xx->tfa, prof))
+ nr_controls++; /* Playback Volume control */
+ }
+
+ tfa98xx_controls = devm_kzalloc(tfa98xx->codec->dev,
+ nr_controls * sizeof(tfa98xx_controls[0]), GFP_KERNEL);
+ if (!tfa98xx_controls)
+ return -ENOMEM;
+
+ /* Create a mixer item for selecting the active profile */
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+ scnprintf(name, MAX_CONTROL_NAME, "%s Profile", tfa98xx->fw.name);
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_profile;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_profile;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_profile;
+ // tfa98xx_controls[mix_index].private_value = profs; /* save number of profiles */
+ mix_index++;
+
+ /* create mixer items for each profile that has volume */
+ for (prof = 0; prof < nprof; prof++) {
+ /* create an new empty profile */
+ bprofile = devm_kzalloc(tfa98xx->codec->dev, sizeof(*bprofile), GFP_KERNEL);
+ if (!bprofile)
+ return -ENOMEM;
+
+ bprofile->len = 0;
+ bprofile->item_id = -1;
+ INIT_LIST_HEAD(&bprofile->list);
+
+ /* copy profile name into basename until the . */
+ get_profile_basename(bprofile->basename, tfa_cont_profile_name(tfa98xx, prof));
+ bprofile->len = strlen(bprofile->basename);
+
+ /*
+ * search the profile list for a profile with basename, if it is not found then
+ * add it to the list and add a new mixer control (if it has vsteps)
+ * also, if it is a calibration profile, do not add it to the list
+ */
+ if ((is_profile_in_list(bprofile->basename, bprofile->len) == 0) &&
+ is_calibration_profile(tfa_cont_profile_name(tfa98xx, prof)) == 0) {
+ /* the profile is not present, add it to the list */
+ list_add(&bprofile->list, &profile_list);
+ bprofile->item_id = id++;
+
+ /* pr_debug("profile added [%d]: %s\n", bprofile->item_id, bprofile->basename); */
+
+ if (tfacont_get_max_vstep(tfa98xx->tfa, prof)) {
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s %s Playback Volume",
+ tfa98xx->fw.name, bprofile->basename);
+
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_vstep;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_vstep;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_vstep;
+ tfa98xx_controls[mix_index].private_value = bprofile->item_id; /* save profile index */
+ mix_index++;
+ }
+ }
+
+ /* look for the basename profile in the list of mixer profiles and add the
+ container profile index to the supported samplerates of this mixer profile */
+ add_sr_to_profile(tfa98xx, bprofile->basename, bprofile->len, prof);
+ }
+
+ /* set the number of user selectable profiles in the mixer */
+ tfa98xx_mixer_profiles = id;
+
+ /* Create a mixer item for stop control on TFA1 */
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s Stop", tfa98xx->fw.name);
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_stop_ctl;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_stop_ctl;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_stop_ctl;
+ mix_index++;
+
+ if (tfa98xx->flags & TFA98XX_FLAG_CALIBRATION_CTL) {
+ name = devm_kzalloc(tfa98xx->codec->dev, MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
+ scnprintf(name, MAX_CONTROL_NAME, "%s Calibration", tfa98xx->fw.name);
+ tfa98xx_controls[mix_index].name = name;
+ tfa98xx_controls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ tfa98xx_controls[mix_index].info = tfa98xx_info_cal_ctl;
+ tfa98xx_controls[mix_index].get = tfa98xx_get_cal_ctl;
+ tfa98xx_controls[mix_index].put = tfa98xx_set_cal_ctl;
+ mix_index++;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ return snd_soc_add_component_controls(tfa98xx->codec,
+ tfa98xx_controls, mix_index);
+#else
+ return snd_soc_add_codec_controls(tfa98xx->codec,
+ tfa98xx_controls, mix_index);
+#endif
+}
+
+static void *tfa98xx_devm_kstrdup(struct device *dev, char *buf)
+{
+ char *str = devm_kzalloc(dev, strlen(buf) + 1, GFP_KERNEL);
+ if (!str)
+ return str;
+ memcpy(str, buf, strlen(buf));
+ return str;
+}
+
+static int tfa98xx_append_i2c_address(struct device *dev,
+ struct i2c_client *i2c,
+ struct snd_soc_dapm_widget *widgets,
+ int num_widgets,
+ struct snd_soc_dai_driver *dai_drv,
+ int num_dai)
+{
+ char buf[50];
+ int i;
+ int i2cbus = i2c->adapter->nr;
+ int addr = i2c->addr;
+ if (dai_drv && num_dai > 0)
+ for (i = 0; i < num_dai; i++) {
+ snprintf(buf, 50, "%s-%x-%x", dai_drv[i].name, i2cbus,
+ addr);
+ dai_drv[i].name = tfa98xx_devm_kstrdup(dev, buf);
+
+ snprintf(buf, 50, "%s-%x-%x",
+ dai_drv[i].playback.stream_name,
+ i2cbus, addr);
+ dai_drv[i].playback.stream_name = tfa98xx_devm_kstrdup(dev, buf);
+
+ snprintf(buf, 50, "%s-%x-%x",
+ dai_drv[i].capture.stream_name,
+ i2cbus, addr);
+ dai_drv[i].capture.stream_name = tfa98xx_devm_kstrdup(dev, buf);
+ }
+
+ /* the idea behind this is convert:
+ * SND_SOC_DAPM_AIF_IN("AIF IN", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
+ * into:
+ * SND_SOC_DAPM_AIF_IN("AIF IN", "AIF Playback-2-36", 0, SND_SOC_NOPM, 0, 0),
+ */
+ if (widgets && num_widgets > 0)
+ for (i = 0; i < num_widgets; i++) {
+ if (!widgets[i].sname)
+ continue;
+ if ((widgets[i].id == snd_soc_dapm_aif_in)
+ || (widgets[i].id == snd_soc_dapm_aif_out)) {
+ snprintf(buf, 50, "%s-%x-%x", widgets[i].sname,
+ i2cbus, addr);
+ widgets[i].sname = tfa98xx_devm_kstrdup(dev, buf);
+ }
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dapm_widget tfa98xx_dapm_widgets_common[] = {
+ /* Stream widgets */
+ SND_SOC_DAPM_AIF_IN("AIF IN", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF OUT", "AIF Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_OUTPUT("OUTL"),
+ SND_SOC_DAPM_INPUT("AEC Loopback"),
+};
+
+static struct snd_soc_dapm_widget tfa98xx_dapm_widgets_stereo[] = {
+ SND_SOC_DAPM_OUTPUT("OUTR"),
+};
+
+static struct snd_soc_dapm_widget tfa98xx_dapm_widgets_saam[] = {
+ SND_SOC_DAPM_INPUT("SAAM MIC"),
+};
+
+static struct snd_soc_dapm_widget tfa9888_dapm_inputs[] = {
+ SND_SOC_DAPM_INPUT("DMIC1"),
+ SND_SOC_DAPM_INPUT("DMIC2"),
+ SND_SOC_DAPM_INPUT("DMIC3"),
+ SND_SOC_DAPM_INPUT("DMIC4"),
+};
+
+static const struct snd_soc_dapm_route tfa98xx_dapm_routes_common[] = {
+ { "OUTL", NULL, "AIF IN" },
+ { "AIF OUT", NULL, "AEC Loopback" },
+};
+
+static const struct snd_soc_dapm_route tfa98xx_dapm_routes_saam[] = {
+ { "AIF OUT", NULL, "SAAM MIC" },
+};
+
+static const struct snd_soc_dapm_route tfa98xx_dapm_routes_stereo[] = {
+ { "OUTR", NULL, "AIF IN" },
+};
+
+static const struct snd_soc_dapm_route tfa9888_input_dapm_routes[] = {
+ { "AIF OUT", NULL, "DMIC1" },
+ { "AIF OUT", NULL, "DMIC2" },
+ { "AIF OUT", NULL, "DMIC3" },
+ { "AIF OUT", NULL, "DMIC4" },
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
+static struct snd_soc_dapm_context *snd_soc_codec_get_dapm(struct snd_soc_codec *codec)
+{
+ return &codec->dapm;
+}
+#endif
+
+static void tfa98xx_add_widgets(struct tfa98xx *tfa98xx)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(tfa98xx->codec);
+#else
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(tfa98xx->codec);
+#endif
+ struct snd_soc_dapm_widget *widgets;
+ unsigned int num_dapm_widgets = ARRAY_SIZE(tfa98xx_dapm_widgets_common);
+
+ widgets = devm_kzalloc(&tfa98xx->i2c->dev,
+ sizeof(struct snd_soc_dapm_widget) *
+ ARRAY_SIZE(tfa98xx_dapm_widgets_common),
+ GFP_KERNEL);
+ if (!widgets)
+ return;
+ memcpy(widgets, tfa98xx_dapm_widgets_common,
+ sizeof(struct snd_soc_dapm_widget) *
+ ARRAY_SIZE(tfa98xx_dapm_widgets_common));
+
+ tfa98xx_append_i2c_address(&tfa98xx->i2c->dev,
+ tfa98xx->i2c,
+ widgets,
+ num_dapm_widgets,
+ NULL,
+ 0);
+
+ snd_soc_dapm_new_controls(dapm, widgets,
+ ARRAY_SIZE(tfa98xx_dapm_widgets_common));
+ snd_soc_dapm_add_routes(dapm, tfa98xx_dapm_routes_common,
+ ARRAY_SIZE(tfa98xx_dapm_routes_common));
+
+ if (tfa98xx->flags & TFA98XX_FLAG_STEREO_DEVICE) {
+ snd_soc_dapm_new_controls(dapm, tfa98xx_dapm_widgets_stereo,
+ ARRAY_SIZE(tfa98xx_dapm_widgets_stereo));
+ snd_soc_dapm_add_routes(dapm, tfa98xx_dapm_routes_stereo,
+ ARRAY_SIZE(tfa98xx_dapm_routes_stereo));
+ }
+
+ if (tfa98xx->flags & TFA98XX_FLAG_MULTI_MIC_INPUTS) {
+ snd_soc_dapm_new_controls(dapm, tfa9888_dapm_inputs,
+ ARRAY_SIZE(tfa9888_dapm_inputs));
+ snd_soc_dapm_add_routes(dapm, tfa9888_input_dapm_routes,
+ ARRAY_SIZE(tfa9888_input_dapm_routes));
+ }
+
+ if (tfa98xx->flags & TFA98XX_FLAG_SAAM_AVAILABLE) {
+ snd_soc_dapm_new_controls(dapm, tfa98xx_dapm_widgets_saam,
+ ARRAY_SIZE(tfa98xx_dapm_widgets_saam));
+ snd_soc_dapm_add_routes(dapm, tfa98xx_dapm_routes_saam,
+ ARRAY_SIZE(tfa98xx_dapm_routes_saam));
+ }
+}
+
+/* I2C wrapper functions */
+enum Tfa98xx_Error tfa98xx_write_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short value)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ int ret;
+ int retries = I2C_RETRIES;
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+ if (!tfa98xx || !tfa98xx->regmap) {
+ pr_err("No tfa98xx regmap available\n");
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+retry:
+ ret = regmap_write(tfa98xx->regmap, subaddress, value);
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ return Tfa98xx_Error_Fail;
+ }
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx->i2c->dev, " WR reg=0x%02x, val=0x%04x %s\n",
+ subaddress, value,
+ ret < 0 ? "Error!!" : "");
+
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\tWR reg=0x%02x, val=0x%04x %s\n",
+ subaddress, value,
+ ret < 0 ? "Error!!" : "");
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_read_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short *val)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ unsigned int value;
+ int retries = I2C_RETRIES;
+ int ret;
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+ if (!tfa98xx || !tfa98xx->regmap) {
+ pr_err("No tfa98xx regmap available\n");
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+retry:
+ ret = regmap_read(tfa98xx->regmap, subaddress, &value);
+ if (ret < 0) {
+ pr_warn("i2c error at subaddress 0x%x, retries left: %d\n", subaddress, retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ return Tfa98xx_Error_Fail;
+ }
+ *val = value & 0xffff;
+
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx->i2c->dev, "RD reg=0x%02x, val=0x%04x %s\n",
+ subaddress, *val,
+ ret < 0 ? "Error!!" : "");
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\tRD reg=0x%02x, val=0x%04x %s\n",
+ subaddress, *val,
+ ret < 0 ? "Error!!" : "");
+
+ return error;
+}
+
+
+/*
+ * init external dsp
+ */
+enum Tfa98xx_Error
+ tfa98xx_init_dsp(struct tfa_device *tfa)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+
+int tfa98xx_get_dsp_status(struct tfa_device *tfa)
+{
+ return 0;
+}
+
+/*
+ * write external dsp message
+ */
+enum Tfa98xx_Error
+ tfa98xx_write_dsp(struct tfa_device *tfa, int num_bytes, const char *command_buffer)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+
+/*
+ * read external dsp message
+ */
+enum Tfa98xx_Error
+ tfa98xx_read_dsp(struct tfa_device *tfa, int num_bytes, unsigned char *result_buffer)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+/*
+ * write/read external dsp message
+ */
+enum Tfa98xx_Error
+ tfa98xx_writeread_dsp(struct tfa_device *tfa, int command_length, void *command_buffer,
+ int result_length, void *result_buffer)
+{
+ return Tfa98xx_Error_Not_Supported;
+}
+
+enum Tfa98xx_Error tfa98xx_read_data(struct tfa_device *tfa,
+ unsigned char reg,
+ int len, unsigned char value[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ struct i2c_client *tfa98xx_client;
+ int err;
+ int tries = 0;
+ unsigned char *reg_buf = NULL;
+ struct i2c_msg msgs[] = {
+ {
+ .flags = 0,
+ .len = 1,
+ .buf = NULL,
+ }, {
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = value,
+ },
+ };
+ reg_buf = (unsigned char *)kmalloc(sizeof(reg), GFP_DMA); //GRP_KERNEL also works,
+ if (!reg_buf) {
+ return -ENOMEM;;
+ }
+
+ *reg_buf = reg;
+ msgs[0].buf = reg_buf;
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+ if (tfa98xx->i2c) {
+ tfa98xx_client = tfa98xx->i2c;
+ msgs[0].addr = tfa98xx_client->addr;
+ msgs[1].addr = tfa98xx_client->addr;
+
+ do {
+ err = i2c_transfer(tfa98xx_client->adapter, msgs,
+ ARRAY_SIZE(msgs));
+ if (err != ARRAY_SIZE(msgs))
+ msleep_interruptible(I2C_RETRY_DELAY);
+ } while ((err != ARRAY_SIZE(msgs)) && (++tries < I2C_RETRIES));
+
+ if (err != ARRAY_SIZE(msgs)) {
+ dev_err(&tfa98xx_client->dev, "read transfer error %d\n",
+ err);
+ error = Tfa98xx_Error_Fail;
+ }
+
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx_client->dev, "RD-DAT reg=0x%02x, len=%d\n",
+ reg, len);
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\t\tRD-DAT reg=0x%02x, len=%d\n",
+ reg, len);
+ }
+ else {
+ pr_err("No device available\n");
+ error = Tfa98xx_Error_Fail;
+ }
+ kfree(reg_buf);
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_write_raw(struct tfa_device *tfa,
+ int len,
+ const unsigned char data[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ struct tfa98xx *tfa98xx;
+ int ret;
+ int retries = I2C_RETRIES;
+
+
+ if (tfa == NULL) {
+ pr_err("No device available\n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ tfa98xx = (struct tfa98xx *)tfa->data;
+
+retry:
+ ret = i2c_master_send(tfa98xx->i2c, data, len);
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ }
+
+ if (ret == len) {
+ if (tfa98xx_kmsg_regs)
+ dev_dbg(&tfa98xx->i2c->dev, " WR-RAW len=%d\n", len);
+ if (tfa98xx_ftrace_regs)
+ tfa98xx_trace_printk("\t\tWR-RAW len=%d\n", len);
+ return Tfa98xx_Error_Ok;
+ }
+ pr_err(" WR-RAW (len=%d) Error I2C send size mismatch %d\n", len, ret);
+ error = Tfa98xx_Error_Fail;
+
+ return error;
+}
+
+/* Interrupts management */
+
+static void tfa98xx_interrupt_enable_tfa2(struct tfa98xx *tfa98xx, bool enable)
+{
+ /* Only for 0x72 we need to enable NOCLK interrupts */
+ if (tfa98xx->flags & TFA98XX_FLAG_REMOVE_PLOP_NOISE)
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_stnoclk, enable);
+
+ if (tfa98xx->flags & TFA98XX_FLAG_LP_MODES) {
+ tfa_irq_ena(tfa98xx->tfa, 36, enable); /* FIXME: IELP0 does not excist for 9912 */
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_stclpr, enable);
+ }
+}
+
+/* Check if tap-detection can and shall be enabled.
+ * Configure SPK interrupt accordingly or setup polling mode
+ * Tap-detection shall be active if:
+ * - the service is enabled (tapdet_open), AND
+ * - the current profile is a tap-detection profile
+ * On TFA1 familiy of devices, activating tap-detection means enabling the SPK
+ * interrupt if available.
+ * We also update the tapdet_enabled and tapdet_poll variables.
+ */
+static void tfa98xx_tapdet_check_update(struct tfa98xx *tfa98xx)
+{
+ unsigned int enable = false;
+
+ /* Support tap-detection on TFA1 family of devices */
+ if ((tfa98xx->flags & TFA98XX_FLAG_TAPDET_AVAILABLE) == 0)
+ return;
+
+ if (tfa98xx->tapdet_open &&
+ (tfa98xx->tapdet_profiles & (1 << tfa98xx->profile)))
+ enable = true;
+
+ if (!gpio_is_valid(tfa98xx->irq_gpio)) {
+ /* interrupt not available, setup polling mode */
+ tfa98xx->tapdet_poll = true;
+ if (enable)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->tapdet_work, HZ / 10);
+ else
+ cancel_delayed_work_sync(&tfa98xx->tapdet_work);
+ dev_dbg(tfa98xx->codec->dev,
+ "Polling for tap-detection: %s (%d; 0x%x, %d)\n",
+ enable ? "enabled" : "disabled",
+ tfa98xx->tapdet_open, tfa98xx->tapdet_profiles,
+ tfa98xx->profile);
+
+ }
+ else {
+ dev_dbg(tfa98xx->codec->dev,
+ "Interrupt for tap-detection: %s (%d; 0x%x, %d)\n",
+ enable ? "enabled" : "disabled",
+ tfa98xx->tapdet_open, tfa98xx->tapdet_profiles,
+ tfa98xx->profile);
+ /* enabled interrupt */
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_sttapdet, enable);
+ }
+
+ /* check disabled => enabled transition to clear pending events */
+ if (!tfa98xx->tapdet_enabled && enable) {
+ /* clear pending event if any */
+ tfa_irq_clear(tfa98xx->tfa, tfa9912_irq_sttapdet);
+ }
+
+ if (!tfa98xx->tapdet_poll)
+ tfa_irq_ena(tfa98xx->tfa, tfa9912_irq_sttapdet, 1); /* enable again */
+}
+
+/* global enable / disable interrupts */
+static void tfa98xx_interrupt_enable(struct tfa98xx *tfa98xx, bool enable)
+{
+ if (tfa98xx->flags & TFA98XX_FLAG_SKIP_INTERRUPTS)
+ return;
+
+ if (tfa98xx->tfa->tfa_family == 2)
+ tfa98xx_interrupt_enable_tfa2(tfa98xx, enable);
+}
+
+/* Firmware management */
+static void tfa98xx_container_loaded(const struct firmware *cont, void *context)
+{
+ TfaContainer_t *container;
+ struct tfa98xx *tfa98xx = context;
+ enum tfa_error tfa_err;
+ int container_size;
+ int ret;
+
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_FAIL;
+
+ if (!cont) {
+ pr_err("Failed to read %s\n", fw_name);
+ return;
+ }
+
+ /* pr_debug("loaded %s - size: %zu\n", fw_name, cont->size); */
+
+ mutex_lock(&tfa98xx_mutex);
+ if (tfa98xx_container == NULL) {
+ container = kzalloc(cont->size, GFP_KERNEL);
+ if (container == NULL) {
+ mutex_unlock(&tfa98xx_mutex);
+ release_firmware(cont);
+ pr_err("Error allocating memory\n");
+ return;
+ }
+
+ container_size = cont->size;
+ memcpy(container, cont->data, container_size);
+ release_firmware(cont);
+
+ /* pr_debug("%.2s%.2s\n", container->version, container->subversion); */
+ /* pr_debug("%.8s\n", container->customer); */
+ /* pr_debug("%.8s\n", container->application); */
+ /* pr_debug("%.8s\n", container->type); */
+ /* pr_debug("%d ndev\n", container->ndev); */
+ /* pr_debug("%d nprof\n", container->nprof); */
+
+ tfa_err = tfa_load_cnt(container, container_size);
+ if (tfa_err != tfa_error_ok) {
+ mutex_unlock(&tfa98xx_mutex);
+ kfree(container);
+ dev_err(tfa98xx->dev, "Cannot load container file, aborting\n");
+ return;
+ }
+
+ tfa98xx_container = container;
+ }
+ else {
+ /* pr_debug("container file already loaded...\n"); */
+ container = tfa98xx_container;
+ release_firmware(cont);
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ tfa98xx->tfa->cnt = container;
+
+ /*
+ i2c transaction limited to 64k
+ (Documentation/i2c/writing-clients)
+ */
+ tfa98xx->tfa->buffer_size = 65536;
+
+ /* DSP messages via i2c */
+ tfa98xx->tfa->has_msg = 0;
+
+ if (tfa_dev_probe(tfa98xx->i2c->addr, tfa98xx->tfa) != 0) {
+ dev_err(tfa98xx->dev, "Failed to probe TFA98xx @ 0x%.2x\n", tfa98xx->i2c->addr);
+ return;
+ }
+
+ tfa98xx->tfa->dev_idx = tfa_cont_get_idx(tfa98xx->tfa);
+ if (tfa98xx->tfa->dev_idx < 0) {
+ dev_err(tfa98xx->dev, "Failed to find TFA98xx @ 0x%.2x in container file\n", tfa98xx->i2c->addr);
+ return;
+ }
+
+ /* Enable debug traces */
+ tfa98xx->tfa->verbose = trace_level & 1;
+
+ /* prefix is the application name from the cnt */
+ tfa_cnt_get_app_name(tfa98xx->tfa, tfa98xx->fw.name);
+
+ /* set default profile/vstep */
+ tfa98xx->profile = 0;
+ tfa98xx->vstep = 0;
+
+ /* Override default profile if requested */
+ if (strcmp(dflt_prof_name, "")) {
+ unsigned int i;
+ int nprof = tfa_cnt_get_dev_nprof(tfa98xx->tfa);
+ for (i = 0; i < nprof; i++) {
+ if (strcmp(tfa_cont_profile_name(tfa98xx, i),
+ dflt_prof_name) == 0) {
+ tfa98xx->profile = i;
+ dev_dbg(tfa98xx->dev,
+ "changing default profile to %s (%d)\n",
+ dflt_prof_name, tfa98xx->profile);
+ break;
+ }
+ }
+ if (i >= nprof)
+ dev_dbg(tfa98xx->dev,
+ "Default profile override failed (%s profile not found)\n",
+ dflt_prof_name);
+ }
+
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_OK;
+ /* pr_debug("Firmware init complete\n"); */
+
+ if (no_start != 0)
+ return;
+
+ /* Only controls for master device */
+ if (tfa98xx->tfa->dev_idx == 0)
+ tfa98xx_create_controls(tfa98xx);
+
+ tfa98xx_inputdev_check_register(tfa98xx);
+
+ if (tfa_is_cold(tfa98xx->tfa) == 0) {
+ /* pr_debug("Warning: device 0x%.2x is still warm\n", tfa98xx->i2c->addr); */
+ tfa_reset(tfa98xx->tfa);
+ }
+
+ /* Preload settings using internal clock on TFA2 */
+ if (tfa98xx->tfa->tfa_family == 2) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ ret = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ if (ret == Tfa98xx_Error_Not_Supported)
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_FAIL;
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+ tfa98xx_interrupt_enable(tfa98xx, true);
+}
+
+static int tfa98xx_load_container(struct tfa98xx *tfa98xx)
+{
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_PENDING;
+
+ return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ fw_name, tfa98xx->dev, GFP_KERNEL,
+ tfa98xx, tfa98xx_container_loaded);
+}
+
+
+static void tfa98xx_tapdet(struct tfa98xx *tfa98xx)
+{
+ unsigned int tap_pattern;
+ int btn;
+
+ /* check tap pattern (BTN_0 is "error" wrong tap indication */
+ tap_pattern = tfa_get_tap_pattern(tfa98xx->tfa);
+ switch (tap_pattern) {
+ case 0xffffffff:
+ pr_info("More than 4 taps detected! (flagTapPattern = -1)\n");
+ btn = BTN_0;
+ break;
+ case 0xfffffffe:
+ case 0xfe:
+ pr_info("Illegal tap detected!\n");
+ btn = BTN_0;
+ break;
+ case 0:
+ pr_info("Unrecognized pattern! (flagTapPattern = 0)\n");
+ btn = BTN_0;
+ break;
+ default:
+ pr_info("Detected pattern: %d\n", tap_pattern);
+ btn = BTN_0 + tap_pattern;
+ break;
+ }
+
+ input_report_key(tfa98xx->input, btn, 1);
+ input_report_key(tfa98xx->input, btn, 0);
+ input_sync(tfa98xx->input);
+
+ /* acknowledge event done by clearing interrupt */
+
+}
+
+static void tfa98xx_tapdet_work(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx;
+
+ //TODO check is this is still needed for tap polling
+ tfa98xx = container_of(work, struct tfa98xx, tapdet_work.work);
+
+ if (tfa_irq_get(tfa98xx->tfa, tfa9912_irq_sttapdet))
+ tfa98xx_tapdet(tfa98xx);
+
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->tapdet_work, HZ / 10);
+}
+static void tfa98xx_nmode_update_work(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx;
+
+ //MCH_TO_TEST, checking if noise mode update is required or not
+ tfa98xx = container_of(work, struct tfa98xx, nmodeupdate_work.work);
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_adapt_noisemode(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->nmodeupdate_work,5 * HZ);
+}
+static void tfa98xx_monitor(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ tfa98xx = container_of(work, struct tfa98xx, monitor_work.work);
+
+ /* Check for tap-detection - bypass monitor if it is active */
+ if (!tfa98xx->input) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ error = tfa_status(tfa98xx->tfa);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ if (error == Tfa98xx_Error_DSP_not_running) {
+ if (tfa98xx->dsp_init == TFA98XX_DSP_INIT_DONE) {
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_RECOVER;
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->init_work, 0);
+ }
+ }
+ }
+
+ /* reschedule */
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->monitor_work, 5 * HZ);
+}
+
+static void tfa98xx_dsp_init(struct tfa98xx *tfa98xx)
+{
+ int ret;
+ bool failed = false;
+ bool reschedule = false;
+ bool sync = false;
+
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK) {
+ /* pr_debug("Skipping tfa_dev_start (no FW: %d)\n", tfa98xx->dsp_fw_state); */
+ return;
+ }
+
+ if (tfa98xx->dsp_init == TFA98XX_DSP_INIT_DONE) {
+ /* pr_debug("Stream already started, skipping DSP power-on\n"); */
+ return;
+ }
+
+ mutex_lock(&tfa98xx->dsp_lock);
+
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_PENDING;
+
+ if (tfa98xx->init_count < TF98XX_MAX_DSP_START_TRY_COUNT) {
+ /* directly try to start DSP */
+ ret = tfa98xx_tfa_start(tfa98xx, tfa98xx->profile, tfa98xx->vstep);
+ if (ret == Tfa98xx_Error_Not_Supported) {
+ tfa98xx->dsp_fw_state = TFA98XX_DSP_FW_FAIL;
+ dev_err(&tfa98xx->i2c->dev, "Failed starting device\n");
+ failed = true;
+ }
+ else if (ret != Tfa98xx_Error_Ok) {
+ /* It may fail as we may not have a valid clock at that
+ * time, so re-schedule and re-try later.
+ */
+ dev_err(&tfa98xx->i2c->dev,
+ "tfa_dev_start failed! (err %d) - %d\n",
+ ret, tfa98xx->init_count);
+ reschedule = true;
+ }
+ else {
+ sync = true;
+
+ /* Subsystem ready, tfa init complete */
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_DONE;
+ dev_dbg(&tfa98xx->i2c->dev,
+ "tfa_dev_start success (%d)\n",
+ tfa98xx->init_count);
+ /* cancel other pending init works */
+ cancel_delayed_work(&tfa98xx->init_work);
+ tfa98xx->init_count = 0;
+ }
+ }
+ else {
+ /* exceeded max number ot start tentatives, cancel start */
+ dev_err(&tfa98xx->i2c->dev,
+ "Failed starting device (%d)\n",
+ tfa98xx->init_count);
+ failed = true;
+ }
+ if (reschedule) {
+ /* reschedule this init work for later */
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->init_work,
+ msecs_to_jiffies(5));
+ tfa98xx->init_count++;
+ }
+ if (failed) {
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_FAIL;
+ /* cancel other pending init works */
+ cancel_delayed_work(&tfa98xx->init_work);
+ tfa98xx->init_count = 0;
+ }
+ mutex_unlock(&tfa98xx->dsp_lock);
+
+ if (sync) {
+ /* check if all devices have started */
+ bool do_sync;
+ mutex_lock(&tfa98xx_mutex);
+
+ if (tfa98xx_sync_count < tfa98xx_device_count)
+ tfa98xx_sync_count++;
+
+ do_sync = (tfa98xx_sync_count >= tfa98xx_device_count);
+ mutex_unlock(&tfa98xx_mutex);
+
+ /* when all devices have started then unmute */
+ if (do_sync) {
+ tfa98xx_sync_count = 0;
+ list_for_each_entry(tfa98xx, &tfa98xx_device_list, list) {
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_set_state(tfa98xx->tfa, TFA_STATE_UNMUTE, 0);
+
+ /*
+ * start monitor thread to check IC status bit
+ * periodically, and re-init IC to recover if
+ * needed.
+ */
+ if (tfa98xx->tfa->tfa_family == 1 || tfa98xx->tfa->dev_ops.tfa_status != NULL)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->monitor_work,
+ 1 * HZ);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ }
+
+ }
+ }
+
+
+ return;
+}
+
+
+static void tfa98xx_dsp_init_work(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx = container_of(work, struct tfa98xx, init_work.work);
+
+ tfa98xx_dsp_init(tfa98xx);
+}
+
+static void tfa98xx_interrupt(struct work_struct *work)
+{
+ struct tfa98xx *tfa98xx = container_of(work, struct tfa98xx, interrupt_work.work);
+
+ pr_info("\n");
+
+ if (tfa98xx->flags & TFA98XX_FLAG_TAPDET_AVAILABLE) {
+ /* check for tap interrupt */
+ if (tfa_irq_get(tfa98xx->tfa, tfa9912_irq_sttapdet)) {
+ tfa98xx_tapdet(tfa98xx);
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa98xx->tfa, tfa9912_irq_sttapdet);
+ }
+ } /* TFA98XX_FLAG_TAPDET_AVAILABLE */
+
+ if (tfa98xx->flags & TFA98XX_FLAG_REMOVE_PLOP_NOISE) {
+ int start_triggered;
+
+ mutex_lock(&tfa98xx->dsp_lock);
+ start_triggered = tfa_plop_noise_interrupt(tfa98xx->tfa, tfa98xx->profile, tfa98xx->vstep);
+ /* Only enable when the return value is 1, otherwise the interrupt is triggered twice */
+ if (start_triggered)
+ tfa98xx_interrupt_enable(tfa98xx, true);
+ mutex_unlock(&tfa98xx->dsp_lock);
+ } /* TFA98XX_FLAG_REMOVE_PLOP_NOISE */
+
+ if (tfa98xx->flags & TFA98XX_FLAG_LP_MODES) {
+ tfa_lp_mode_interrupt(tfa98xx->tfa);
+ } /* TFA98XX_FLAG_LP_MODES */
+
+ /* unmask interrupts masked in IRQ handler */
+ tfa_irq_unmask(tfa98xx->tfa);
+}
+
+static int tfa98xx_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = dai->component;
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = dai->codec;
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ unsigned int sr;
+ int len, prof, nprof, idx = 0;
+ char *basename;
+ u64 formats;
+ int err;
+
+ /*
+ * Support CODEC to CODEC links,
+ * these are called with a NULL runtime pointer.
+ */
+ if (!substream->runtime)
+ return 0;
+
+ if (pcm_no_constraint != 0)
+ return 0;
+
+ switch (pcm_sample_format) {
+ case 0:
+ formats = SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ case 1:
+ formats = SNDRV_PCM_FMTBIT_S24_LE;
+ break;
+ case 2:
+ formats = SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ default:
+ formats = TFA98XX_FORMATS;
+ break;
+ }
+
+ err = snd_pcm_hw_constraint_mask64(substream->runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT, formats);
+ if (err < 0)
+ return err;
+
+ if (no_start != 0)
+ return 0;
+
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK) {
+ dev_dbg(codec->dev, "Container file not loaded\n");
+ return -EINVAL;
+ }
+
+ basename = kzalloc(MAX_CONTROL_NAME, GFP_KERNEL);
+ if (!basename)
+ return -ENOMEM;
+
+ /* copy profile name into basename until the . */
+ get_profile_basename(basename, tfa_cont_profile_name(tfa98xx, tfa98xx->profile));
+ len = strlen(basename);
+
+ /* loop over all profiles and get the supported samples rate(s) from
+ * the profiles with the same basename
+ */
+ nprof = tfa_cnt_get_dev_nprof(tfa98xx->tfa);
+ tfa98xx->rate_constraint.list = &tfa98xx->rate_constraint_list[0];
+ tfa98xx->rate_constraint.count = 0;
+ for (prof = 0; prof < nprof; prof++) {
+ if (0 == strncmp(basename, tfa_cont_profile_name(tfa98xx, prof), len)) {
+ /* Check which sample rate is supported with current profile,
+ * and enforce this.
+ */
+ sr = tfa98xx_get_profile_sr(tfa98xx->tfa, prof);
+ if (!sr)
+ dev_dbg(codec->dev, "Unable to identify supported sample rate\n");
+
+ if (tfa98xx->rate_constraint.count >= TFA98XX_NUM_RATES) {
+ dev_err(codec->dev, "too many sample rates\n");
+ }
+ else {
+ tfa98xx->rate_constraint_list[idx++] = sr;
+ tfa98xx->rate_constraint.count += 1;
+ }
+ }
+ }
+
+ kfree(basename);
+
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &tfa98xx->rate_constraint);
+}
+
+static int tfa98xx_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec_dai->component);
+#else
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec_dai->codec);
+#endif
+ tfa98xx->sysclk = freq;
+ return 0;
+}
+
+static int tfa98xx_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int slot_width)
+{
+ /* pr_debug("\n"); */
+ return 0;
+}
+
+static int tfa98xx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(dai->component);
+ struct snd_soc_component *codec = dai->component;
+#else
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(dai->codec);
+ struct snd_soc_codec *codec = dai->codec;
+#endif
+ /* pr_debug("fmt=0x%x\n", fmt); */
+
+ /* Supported mode: regular I2S, slave, or PDM */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_DSP_A:
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
+ dev_err(codec->dev, "Invalid Codec master mode\n");
+ return -EINVAL;
+ }
+ break;
+ case SND_SOC_DAIFMT_PDM:
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported DAI format %d\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ tfa98xx->audio_mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ return 0;
+}
+
+static int tfa98xx_get_fssel(unsigned int rate)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(rate_to_fssel); i++) {
+ if (rate_to_fssel[i].rate == rate) {
+ return rate_to_fssel[i].fssel;
+ }
+ }
+ return -EINVAL;
+}
+
+static int tfa98xx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = dai->component;
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = dai->codec;
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ unsigned int rate;
+ int prof_idx;
+
+ /* Supported */
+ rate = params_rate(params);
+ tfa98xx->tfa->bitwidth = params_width(params);
+ tfa98xx->tfa->dynamicTDMmode = pcm_sample_format;
+ /* pr_debug("Requested rate: %d, sample size: %d, physical size: %d\n",
+ rate, snd_pcm_format_width(params_format(params)),
+ snd_pcm_format_physical_width(params_format(params))); */
+
+ if (no_start != 0)
+ return 0;
+ /* set TDM bit width */
+ /* pr_debug("%s: Requested width: %d\n", __func__,
+ params_width(params)); */
+ if ((tfa98xx->tfa->dynamicTDMmode == 3) && tfa_dev_set_tdm_bitwidth(tfa98xx->tfa,tfa98xx->tfa->bitwidth))
+ return -EINVAL;
+ /* check if samplerate is supported for this mixer profile */
+ prof_idx = get_profile_id_for_sr(tfa98xx_mixer_profile, rate);
+ if (prof_idx < 0) {
+ pr_err("tfa98xx: invalid sample rate %d.\n", rate);
+ return -EINVAL;
+ }
+ /* pr_debug("mixer profile:container profile = [%d:%d]\n", tfa98xx_mixer_profile, prof_idx); */
+
+
+ /* update 'real' profile (container profile) */
+ tfa98xx->profile = prof_idx;
+
+ /* update to new rate */
+ tfa98xx->rate = tfa98xx->tfa->rate = rate;
+
+ return 0;
+}
+
+static int tfa98xx_mute(struct snd_soc_dai *dai, int mute, int stream)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec = dai->component;
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+ struct snd_soc_codec *codec = dai->codec;
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ dev_dbg(&tfa98xx->i2c->dev, "%s: state: %d\n", __func__, mute);
+
+ if (no_start) {
+ /* pr_debug("no_start parameter set no tfa_dev_start or tfa_dev_stop, returning\n"); */
+ return 0;
+ }
+
+ if (mute) {
+ /* stop DSP only when both playback and capture streams
+ * are deactivated
+ */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tfa98xx->pstream = 0;
+ else
+ tfa98xx->cstream = 0;
+ if (tfa98xx->pstream != 0 || tfa98xx->cstream != 0)
+ return 0;
+
+ mutex_lock(&tfa98xx_mutex);
+ tfa98xx_sync_count = 0;
+ mutex_unlock(&tfa98xx_mutex);
+
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ if (tfa98xx->dsp_fw_state != TFA98XX_DSP_FW_OK)
+ return 0;
+ mutex_lock(&tfa98xx->dsp_lock);
+ tfa_dev_stop(tfa98xx->tfa);
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_STOPPED;
+ mutex_unlock(&tfa98xx->dsp_lock);
+ if(tfa98xx->flags & TFA98XX_FLAG_ADAPT_NOISE_MODE)
+ cancel_delayed_work_sync(&tfa98xx->nmodeupdate_work);
+ }
+ else {
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tfa98xx->pstream = 1;
+ else
+ tfa98xx->cstream = 1;
+
+ /* Start DSP */
+#if 1
+ if (tfa98xx->dsp_init != TFA98XX_DSP_INIT_PENDING)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->init_work, 0);
+#else
+ tfa98xx_dsp_init(tfa98xx);
+#endif//
+ if(tfa98xx->flags & TFA98XX_FLAG_ADAPT_NOISE_MODE)
+ queue_delayed_work(tfa98xx->tfa98xx_wq,
+ &tfa98xx->nmodeupdate_work,
+ 0);
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops tfa98xx_dai_ops = {
+ .startup = tfa98xx_startup,
+ .set_fmt = tfa98xx_set_fmt,
+ .set_sysclk = tfa98xx_set_dai_sysclk,
+ .set_tdm_slot = tfa98xx_set_tdm_slot,
+ .hw_params = tfa98xx_hw_params,
+ .mute_stream = tfa98xx_mute,
+};
+
+static struct snd_soc_dai_driver tfa98xx_dai[] = {
+ {
+ .name = "tfa98xx-aif",
+ .id = 1,
+ .playback = {
+ .stream_name = "AIF Playback",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TFA98XX_RATES,
+ .formats = TFA98XX_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TFA98XX_RATES,
+ .formats = TFA98XX_FORMATS,
+ },
+ .ops = &tfa98xx_dai_ops,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+ .symmetric_rates = 1,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ .symmetric_rate = 1,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) && LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
+ .symmetric_channels = 1,
+ .symmetric_samplebits = 1,
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+ .symmetric_channels = 1,
+ .symmetric_sample_bits = 1,
+#endif
+ },
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+static int tfa98xx_probe(struct snd_soc_component *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+static int tfa98xx_probe(struct snd_soc_codec *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ int ret;
+
+ /* pr_debug("\n"); */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ snd_soc_component_init_regmap(codec, tfa98xx->regmap);
+#endif
+ /* setup work queue, will be used to initial DSP on first boot up */
+ tfa98xx->tfa98xx_wq = create_singlethread_workqueue("tfa98xx");
+ if (!tfa98xx->tfa98xx_wq)
+ return -ENOMEM;
+
+ INIT_DELAYED_WORK(&tfa98xx->init_work, tfa98xx_dsp_init_work);
+ INIT_DELAYED_WORK(&tfa98xx->monitor_work, tfa98xx_monitor);
+ INIT_DELAYED_WORK(&tfa98xx->interrupt_work, tfa98xx_interrupt);
+ INIT_DELAYED_WORK(&tfa98xx->tapdet_work, tfa98xx_tapdet_work);
+ INIT_DELAYED_WORK(&tfa98xx->nmodeupdate_work, tfa98xx_nmode_update_work);
+
+ tfa98xx->codec = codec;
+
+ ret = tfa98xx_load_container(tfa98xx);
+ /* pr_debug("Container loading requested: %d\n", ret); */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
+ codec->control_data = tfa98xx->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+#endif
+ tfa98xx_add_widgets(tfa98xx);
+
+ dev_dbg(codec->dev, "tfa98xx codec registered (%s)",
+ tfa98xx->fw.name);
+
+ return ret;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+static void tfa98xx_remove(struct snd_soc_component *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_component_get_drvdata(codec);
+#else
+static int tfa98xx_remove(struct snd_soc_codec *codec)
+{
+ struct tfa98xx *tfa98xx = snd_soc_codec_get_drvdata(codec);
+#endif
+ /* pr_debug("\n"); */
+
+ tfa98xx_interrupt_enable(tfa98xx, false);
+
+ tfa98xx_inputdev_unregister(tfa98xx);
+
+ cancel_delayed_work_sync(&tfa98xx->interrupt_work);
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ cancel_delayed_work_sync(&tfa98xx->tapdet_work);
+ cancel_delayed_work_sync(&tfa98xx->nmodeupdate_work);
+
+ if (tfa98xx->tfa98xx_wq)
+ destroy_workqueue(tfa98xx->tfa98xx_wq);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ return;
+#else
+ return 0;
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
+static struct regmap *tfa98xx_get_regmap(struct device *dev)
+{
+ struct tfa98xx *tfa98xx = dev_get_drvdata(dev);
+
+ return tfa98xx->regmap;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+static struct snd_soc_component_driver soc_codec_dev_tfa98xx = {
+#else
+static struct snd_soc_codec_driver soc_codec_dev_tfa98xx = {
+#endif
+ .probe = tfa98xx_probe,
+ .remove = tfa98xx_remove,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
+ .get_regmap = tfa98xx_get_regmap,
+#endif
+};
+
+
+static bool tfa98xx_writeable_register(struct device *dev, unsigned int reg)
+{
+ /* enable read access for all registers */
+ return 1;
+}
+
+static bool tfa98xx_readable_register(struct device *dev, unsigned int reg)
+{
+ /* enable read access for all registers */
+ return 1;
+}
+
+static bool tfa98xx_volatile_register(struct device *dev, unsigned int reg)
+{
+ /* enable read access for all registers */
+ return 1;
+}
+
+static const struct regmap_config tfa98xx_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = TFA98XX_MAX_REGISTER,
+ .writeable_reg = tfa98xx_writeable_register,
+ .readable_reg = tfa98xx_readable_register,
+ .volatile_reg = tfa98xx_volatile_register,
+ .cache_type = REGCACHE_NONE,
+};
+
+static void tfa98xx_irq_tfa2(struct tfa98xx *tfa98xx)
+{
+ pr_info("\n");
+
+ /*
+ * mask interrupts
+ * will be unmasked after handling interrupts in workqueue
+ */
+ tfa_irq_mask(tfa98xx->tfa);
+ queue_delayed_work(tfa98xx->tfa98xx_wq, &tfa98xx->interrupt_work, 0);
+}
+
+
+static irqreturn_t tfa98xx_irq(int irq, void *data)
+{
+ struct tfa98xx *tfa98xx = data;
+
+ if (tfa98xx->tfa->tfa_family == 2)
+ tfa98xx_irq_tfa2(tfa98xx);
+
+ return IRQ_HANDLED;
+}
+
+static int tfa98xx_ext_reset(struct tfa98xx *tfa98xx)
+{
+ if (tfa98xx && gpio_is_valid(tfa98xx->reset_gpio)) {
+ int reset = tfa98xx->reset_polarity;
+ gpio_set_value_cansleep(tfa98xx->reset_gpio, reset);
+ mdelay(1);
+ gpio_set_value_cansleep(tfa98xx->reset_gpio, !reset);
+ mdelay(1);
+ }
+ return 0;
+}
+
+static int tfa98xx_parse_dt(struct device *dev, struct tfa98xx *tfa98xx,
+ struct device_node *np) {
+ u32 value;
+ int ret;
+ tfa98xx->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
+ if (tfa98xx->reset_gpio < 0)
+ dev_dbg(dev, "No reset GPIO provided, will not HW reset device\n");
+
+ tfa98xx->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0);
+ if (tfa98xx->irq_gpio < 0)
+ dev_dbg(dev, "No IRQ GPIO provided.\n");
+ ret = of_property_read_u32(np,"reset-polarity",&value);
+ if(ret< 0)
+ {
+ tfa98xx->reset_polarity = HIGH;
+ }else {
+ tfa98xx->reset_polarity = (value == 0) ? LOW : HIGH;
+ }
+ dev_dbg(dev, "reset-polarity:%d\n",tfa98xx->reset_polarity);
+ return 0;
+}
+
+static ssize_t tfa98xx_reg_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tfa98xx *tfa98xx = dev_get_drvdata(dev);
+
+ if (count != 1) {
+ /* pr_debug("invalid register address"); */
+ return -EINVAL;
+ }
+
+ tfa98xx->reg = buf[0];
+
+ return 1;
+}
+
+static ssize_t tfa98xx_rw_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tfa98xx *tfa98xx = dev_get_drvdata(dev);
+ u8 *data;
+ int ret;
+ int retries = I2C_RETRIES;
+
+ data = kmalloc(count + 1, GFP_KERNEL);
+ if (data == NULL) {
+ /* pr_debug("can not allocate memory\n"); */
+ return -ENOMEM;
+ }
+
+ data[0] = tfa98xx->reg;
+ memcpy(&data[1], buf, count);
+
+retry:
+ ret = i2c_master_send(tfa98xx->i2c, data, count + 1);
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ }
+
+ kfree(data);
+
+ /* the number of data bytes written without the register address */
+ return ((ret > 1) ? count : -EIO);
+}
+
+static ssize_t tfa98xx_rw_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tfa98xx *tfa98xx = dev_get_drvdata(dev);
+ struct i2c_msg msgs[] = {
+ {
+ .addr = tfa98xx->i2c->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &tfa98xx->reg,
+ },
+ {
+ .addr = tfa98xx->i2c->addr,
+ .flags = I2C_M_RD,
+ .len = count,
+ .buf = buf,
+ },
+ };
+ int ret;
+ int retries = I2C_RETRIES;
+retry:
+ ret = i2c_transfer(tfa98xx->i2c->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0) {
+ pr_warn("i2c error, retries left: %d\n", retries);
+ if (retries) {
+ retries--;
+ msleep(I2C_RETRY_DELAY);
+ goto retry;
+ }
+ return ret;
+ }
+ /* ret contains the number of i2c transaction */
+ /* return the number of bytes read */
+ return ((ret > 1) ? count : -EIO);
+}
+
+static struct bin_attribute dev_attr_rw = {
+ .attr = {
+ .name = "rw",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .size = 0,
+ .read = tfa98xx_rw_read,
+ .write = tfa98xx_rw_write,
+};
+
+static struct bin_attribute dev_attr_reg = {
+ .attr = {
+ .name = "reg",
+ .mode = S_IWUSR,
+ },
+ .size = 0,
+ .read = NULL,
+ .write = tfa98xx_reg_write,
+};
+
+static int tfa98xx_i2c_probe(struct i2c_client *i2c)
+{
+ struct snd_soc_dai_driver *dai;
+ struct tfa98xx *tfa98xx;
+ struct device_node *np = i2c->dev.of_node;
+ int irq_flags;
+ unsigned int reg;
+ int ret;
+
+ pr_info("addr=0x%x\n", i2c->addr);
+
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
+ dev_err(&i2c->dev, "check_functionality failed\n");
+ return -EIO;
+ }
+
+ tfa98xx = devm_kzalloc(&i2c->dev, sizeof(struct tfa98xx), GFP_KERNEL);
+ if (tfa98xx == NULL)
+ return -ENOMEM;
+
+ tfa98xx->dev = &i2c->dev;
+ tfa98xx->i2c = i2c;
+ tfa98xx->dsp_init = TFA98XX_DSP_INIT_STOPPED;
+ tfa98xx->rate = 48000; /* init to the default sample rate (48kHz) */
+ tfa98xx->tfa = NULL;
+
+ tfa98xx->regmap = devm_regmap_init_i2c(i2c, &tfa98xx_regmap);
+ if (IS_ERR(tfa98xx->regmap)) {
+ ret = PTR_ERR(tfa98xx->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ i2c_set_clientdata(i2c, tfa98xx);
+ mutex_init(&tfa98xx->dsp_lock);
+ init_waitqueue_head(&tfa98xx->wq);
+
+ if (np) {
+ ret = tfa98xx_parse_dt(&i2c->dev, tfa98xx, np);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to parse DT node\n");
+ return ret;
+ }
+ if (no_start)
+ tfa98xx->irq_gpio = -1;
+ if (no_reset)
+ tfa98xx->reset_gpio = -1;
+ }
+ else {
+ tfa98xx->reset_gpio = -1;
+ tfa98xx->irq_gpio = -1;
+ }
+
+ if (gpio_is_valid(tfa98xx->reset_gpio)) {
+ ret = devm_gpio_request_one(&i2c->dev, tfa98xx->reset_gpio,
+ GPIOF_OUT_INIT_LOW, "TFA98XX_RST");
+ if (ret)
+ return ret;
+ }
+
+ if (gpio_is_valid(tfa98xx->irq_gpio)) {
+ ret = devm_gpio_request_one(&i2c->dev, tfa98xx->irq_gpio,
+ GPIOF_DIR_IN, "TFA98XX_INT");
+ if (ret)
+ return ret;
+ }
+
+ /* Power up! */
+ tfa98xx_ext_reset(tfa98xx);
+
+ if ((no_start == 0) && (no_reset == 0)) {
+ ret = regmap_read(tfa98xx->regmap, 0x03, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read Revision register: %d\n",
+ ret);
+ return -EIO;
+ }
+ switch (reg & 0xff) {
+ case 0x72: /* tfa9872 */
+ pr_info("TFA9872 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_REMOVE_PLOP_NOISE;
+ /* tfa98xx->flags |= TFA98XX_FLAG_LP_MODES; */
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x73: /* tfa9873 */
+ pr_info("TFA9873 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ tfa98xx->flags |= TFA98XX_FLAG_ADAPT_NOISE_MODE; /***MCH_TO_TEST***/
+ break;
+ case 0x74: /* tfa9874 */
+ pr_info("TFA9874 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x75: /* tfa9875*/
+ pr_info("TFA9875 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x78: /* tfa9878 */
+ pr_info("TFA9878 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_CALIBRATION_CTL;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x88: /* tfa9888 */
+ pr_info("TFA9888 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_STEREO_DEVICE;
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x13: /* tfa9912 */
+ pr_info("TFA9912 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ /* tfa98xx->flags |= TFA98XX_FLAG_TAPDET_AVAILABLE; */
+ break;
+ case 0x94: /* tfa9894 */
+ pr_info("TFA9894 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_MULTI_MIC_INPUTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x80: /* tfa9890 */
+ case 0x81: /* tfa9890 */
+ pr_info("TFA9890 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ break;
+ case 0x92: /* tfa9891 */
+ pr_info("TFA9891 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SAAM_AVAILABLE;
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ break;
+ case 0x12: /* tfa9895 */
+ pr_info("TFA9895 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ break;
+ case 0x97:
+ pr_info("TFA9897 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ case 0x96:
+ pr_info("TFA9896 detected\n");
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ tfa98xx->flags |= TFA98XX_FLAG_TDM_DEVICE;
+ break;
+ default:
+ pr_info("Unsupported device revision (0x%x)\n", reg & 0xff);
+ return -EINVAL;
+ }
+ }
+
+ tfa98xx->tfa = devm_kzalloc(&i2c->dev, sizeof(struct tfa_device), GFP_KERNEL);
+ if (tfa98xx->tfa == NULL)
+ return -ENOMEM;
+
+ tfa98xx->tfa->data = (void *)tfa98xx;
+ tfa98xx->tfa->cachep = tfa98xx_cache;
+
+ /* Modify the stream names, by appending the i2c device address.
+ * This is used with multicodec, in order to discriminate the devices.
+ * Stream names appear in the dai definition and in the stream .
+ * We create copies of original structures because each device will
+ * have its own instance of this structure, with its own address.
+ */
+ dai = devm_kzalloc(&i2c->dev, sizeof(tfa98xx_dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+ memcpy(dai, tfa98xx_dai, sizeof(tfa98xx_dai));
+
+ tfa98xx_append_i2c_address(&i2c->dev,
+ i2c,
+ NULL,
+ 0,
+ dai,
+ ARRAY_SIZE(tfa98xx_dai));
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ ret = devm_snd_soc_register_component(&i2c->dev,
+ &soc_codec_dev_tfa98xx, dai,
+ ARRAY_SIZE(tfa98xx_dai));
+#else
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_tfa98xx, dai,
+ ARRAY_SIZE(tfa98xx_dai));
+#endif
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register TFA98xx: %d\n", ret);
+ return ret;
+ }
+
+ if (gpio_is_valid(tfa98xx->irq_gpio) &&
+ !(tfa98xx->flags & TFA98XX_FLAG_SKIP_INTERRUPTS)) {
+ /* register irq handler */
+ irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ ret = devm_request_threaded_irq(&i2c->dev,
+ gpio_to_irq(tfa98xx->irq_gpio),
+ NULL, tfa98xx_irq, irq_flags,
+ "tfa98xx", tfa98xx);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ gpio_to_irq(tfa98xx->irq_gpio), ret);
+ return ret;
+ }
+ }
+ else {
+ dev_dbg(&i2c->dev, "Skipping IRQ registration\n");
+ /* disable feature support if gpio was invalid */
+ tfa98xx->flags |= TFA98XX_FLAG_SKIP_INTERRUPTS;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ if (no_start == 0)
+ tfa98xx_debug_init(tfa98xx, i2c);
+#endif
+ /* Register the sysfs files for climax backdoor access */
+ ret = device_create_bin_file(&i2c->dev, &dev_attr_rw);
+ if (ret)
+ dev_dbg(&i2c->dev, "error creating sysfs files\n");
+ ret = device_create_bin_file(&i2c->dev, &dev_attr_reg);
+ if (ret)
+ dev_dbg(&i2c->dev, "error creating sysfs files\n");
+
+ pr_info("%s Probe completed successfully!\n", __func__);
+
+ INIT_LIST_HEAD(&tfa98xx->list);
+
+ mutex_lock(&tfa98xx_mutex);
+ tfa98xx_device_count++;
+ list_add(&tfa98xx->list, &tfa98xx_device_list);
+ mutex_unlock(&tfa98xx_mutex);
+
+ return 0;
+}
+
+static void tfa98xx_i2c_remove(struct i2c_client *i2c)
+{
+ struct tfa98xx *tfa98xx = i2c_get_clientdata(i2c);
+
+ /* pr_debug("addr=0x%x\n", i2c->addr); */
+
+ tfa98xx_interrupt_enable(tfa98xx, false);
+
+ cancel_delayed_work_sync(&tfa98xx->interrupt_work);
+ cancel_delayed_work_sync(&tfa98xx->monitor_work);
+ cancel_delayed_work_sync(&tfa98xx->init_work);
+ cancel_delayed_work_sync(&tfa98xx->tapdet_work);
+ cancel_delayed_work_sync(&tfa98xx->nmodeupdate_work);
+
+ device_remove_bin_file(&i2c->dev, &dev_attr_reg);
+ device_remove_bin_file(&i2c->dev, &dev_attr_rw);
+#ifdef CONFIG_DEBUG_FS
+ tfa98xx_debug_remove(tfa98xx);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ snd_soc_unregister_component(&i2c->dev);
+#else
+ snd_soc_unregister_codec(&i2c->dev);
+#endif
+ if (gpio_is_valid(tfa98xx->irq_gpio))
+ devm_gpiod_put(&i2c->dev, gpio_to_desc(tfa98xx->irq_gpio));
+ if (gpio_is_valid(tfa98xx->reset_gpio))
+ devm_gpiod_put(&i2c->dev, gpio_to_desc(tfa98xx->reset_gpio));
+
+ mutex_lock(&tfa98xx_mutex);
+ list_del(&tfa98xx->list);
+ tfa98xx_device_count--;
+ if (tfa98xx_device_count == 0) {
+ kfree(tfa98xx_container);
+ tfa98xx_container = NULL;
+ }
+ mutex_unlock(&tfa98xx_mutex);
+
+ return;
+}
+
+static const struct i2c_device_id tfa98xx_i2c_id[] = {
+ { "tfa98xx", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tfa98xx_i2c_id);
+
+#ifdef CONFIG_OF
+static struct of_device_id tfa98xx_dt_match[] = {
+ {.compatible = "nxp,tfa9894" },
+ {.compatible = "tfa,tfa98xx" },
+ {.compatible = "tfa,tfa9872" },
+ {.compatible = "tfa,tfa9873" },
+ {.compatible = "tfa,tfa9875" },
+ {.compatible = "tfa,tfa9874" },
+ {.compatible = "tfa,tfa9878" },
+ {.compatible = "tfa,tfa9888" },
+ {.compatible = "tfa,tfa9890" },
+ {.compatible = "tfa,tfa9891" },
+ {.compatible = "tfa,tfa9894" },
+ {.compatible = "tfa,tfa9895" },
+ {.compatible = "tfa,tfa9896" },
+ {.compatible = "tfa,tfa9897" },
+ {.compatible = "tfa,tfa9912" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tfa98xx_dt_match);
+#endif
+
+static struct i2c_driver tfa98xx_i2c_driver = {
+ .driver = {
+ .name = "tfa98xx",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tfa98xx_dt_match),
+ },
+ .probe = tfa98xx_i2c_probe,
+ .remove = tfa98xx_i2c_remove,
+ .id_table = tfa98xx_i2c_id,
+};
+
+static int __init tfa98xx_i2c_init(void)
+{
+ int ret = 0;
+
+ pr_info("TFA98XX driver version %s\n", TFA98XX_VERSION);
+
+ /* Enable debug traces */
+ tfa98xx_kmsg_regs = trace_level & 2;
+ tfa98xx_ftrace_regs = trace_level & 4;
+
+ /* Initialize kmem_cache */
+ tfa98xx_cache = kmem_cache_create("tfa98xx_cache", /* Cache name /proc/slabinfo */
+ PAGE_SIZE, /* Structure size, we should fit in single page */
+ 0, /* Structure alignment */
+ (SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT |
+ SLAB_MEM_SPREAD), /* Cache property */
+ NULL); /* Object constructor */
+ if (!tfa98xx_cache) {
+ pr_err("tfa98xx can't create memory pool\n");
+ ret = -ENOMEM;
+ }
+
+ ret = i2c_add_driver(&tfa98xx_i2c_driver);
+
+ return ret;
+}
+module_init(tfa98xx_i2c_init);
+
+static void __exit tfa98xx_i2c_exit(void)
+{
+ i2c_del_driver(&tfa98xx_i2c_driver);
+ kmem_cache_destroy(tfa98xx_cache);
+}
+module_exit(tfa98xx_i2c_exit);
+
+MODULE_DESCRIPTION("ASoC TFA98XX driver");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.h
new file mode 100644
index 00000000000..cedb1169e38
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __TFA98XX_INC__
+#define __TFA98XX_INC__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+
+#include "tfa_device.h"
+#include "tfa_container.h"
+#include "config.h"
+
+/* max. length of a alsa mixer control name */
+#define MAX_CONTROL_NAME 48
+
+#define TFA98XX_MAX_REGISTER 0xff
+
+#define TFA98XX_FLAG_SKIP_INTERRUPTS (1 << 0)
+#define TFA98XX_FLAG_SAAM_AVAILABLE (1 << 1)
+#define TFA98XX_FLAG_STEREO_DEVICE (1 << 2)
+#define TFA98XX_FLAG_MULTI_MIC_INPUTS (1 << 3)
+#define TFA98XX_FLAG_TAPDET_AVAILABLE (1 << 4)
+#define TFA98XX_FLAG_CALIBRATION_CTL (1 << 5)
+#define TFA98XX_FLAG_REMOVE_PLOP_NOISE (1 << 6)
+#define TFA98XX_FLAG_LP_MODES (1 << 7)
+#define TFA98XX_FLAG_TDM_DEVICE (1 << 8)
+#define TFA98XX_FLAG_ADAPT_NOISE_MODE (1 << 9)
+
+#define TFA98XX_NUM_RATES 9
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)
+#define FW_ACTION_HOTPLUG 1
+#endif
+
+/* DSP init status */
+enum tfa98xx_dsp_init_state {
+ TFA98XX_DSP_INIT_STOPPED, /* DSP not running */
+ TFA98XX_DSP_INIT_RECOVER, /* DSP error detected at runtime */
+ TFA98XX_DSP_INIT_FAIL, /* DSP init failed */
+ TFA98XX_DSP_INIT_PENDING, /* DSP start requested */
+ TFA98XX_DSP_INIT_DONE, /* DSP running */
+ TFA98XX_DSP_INIT_INVALIDATED, /* DSP was running, requires re-init */
+};
+
+enum tfa98xx_dsp_fw_state {
+ TFA98XX_DSP_FW_NONE = 0,
+ TFA98XX_DSP_FW_PENDING,
+ TFA98XX_DSP_FW_FAIL,
+ TFA98XX_DSP_FW_OK,
+};
+
+struct tfa98xx_firmware {
+ void *base;
+ struct tfa98xx_device *dev;
+ char name[9]; //TODO get length from tfa parameter defs
+};
+
+struct tfa98xx_baseprofile {
+ char basename[MAX_CONTROL_NAME]; /* profile basename */
+ int len; /* profile length */
+ int item_id; /* profile id */
+ int sr_rate_sup[TFA98XX_NUM_RATES]; /* sample rates supported by this profile */
+ struct list_head list; /* list of all profiles */
+};
+enum tfa_reset_polarity{
+ LOW=0,
+ HIGH=1
+};
+struct tfa98xx {
+ struct regmap *regmap;
+ struct i2c_client *i2c;
+ struct regulator *vdd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
+ struct snd_soc_component *codec;
+#else
+ struct snd_soc_codec *codec;
+#endif
+ struct workqueue_struct *tfa98xx_wq;
+ struct delayed_work init_work;
+ struct delayed_work monitor_work;
+ struct delayed_work interrupt_work;
+ struct delayed_work tapdet_work;
+ struct delayed_work nmodeupdate_work;
+ struct mutex dsp_lock;
+ int dsp_init;
+ int dsp_fw_state;
+ int sysclk;
+ int rst_gpio;
+ u16 rev;
+ int audio_mode;
+ struct tfa98xx_firmware fw;
+ char *fw_name;
+ int rate;
+ wait_queue_head_t wq;
+ struct device *dev;
+ unsigned int init_count;
+ int pstream;
+ int cstream;
+ struct input_dev *input;
+ bool tapdet_enabled; /* service enabled */
+ bool tapdet_open; /* device file opened */
+ unsigned int tapdet_profiles; /* tapdet profile bitfield */
+ bool tapdet_poll; /* tapdet running on polling mode */
+
+ unsigned int rate_constraint_list[TFA98XX_NUM_RATES];
+ struct snd_pcm_hw_constraint_list rate_constraint;
+
+ int reset_gpio;
+ int power_gpio;
+ int irq_gpio;
+ enum tfa_reset_polarity reset_polarity;
+ struct list_head list;
+ struct tfa_device *tfa;
+ int vstep;
+ int profile;
+ int prof_vsteps[TFACONT_MAXPROFS]; /* store vstep per profile (single device) */
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dbg_dir;
+#endif
+ u8 reg;
+ unsigned int flags;
+ bool set_mtp_cal;
+ uint16_t cal_data;
+};
+
+
+#endif /* __TFA98XX_INC__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx_genregs_N1C.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_genregs_N1C.h
new file mode 100644
index 00000000000..5ccc2db5baf
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_genregs_N1C.h
@@ -0,0 +1,3864 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: Tfa98xx_genregs.h
+ * This file was generated automatically on 09/01/15 at 09:40:23.
+ * Source file: TFA9888_N1C_I2C_regmap_V1.xlsx
+ */
+
+#ifndef TFA2_GENREGS_H
+#define TFA2_GENREGS_H
+
+
+#define TFA98XX_SYS_CONTROL0 0x00
+#define TFA98XX_SYS_CONTROL1 0x01
+#define TFA98XX_SYS_CONTROL2 0x02
+#define TFA98XX_DEVICE_REVISION 0x03
+#define TFA98XX_CLOCK_CONTROL 0x04
+#define TFA98XX_CLOCK_GATING_CONTROL 0x05
+#define TFA98XX_SIDE_TONE_CONFIG 0x0d
+#define TFA98XX_CTRL_DIGTOANA_REG 0x0e
+#define TFA98XX_STATUS_FLAGS0 0x10
+#define TFA98XX_STATUS_FLAGS1 0x11
+#define TFA98XX_STATUS_FLAGS2 0x12
+#define TFA98XX_STATUS_FLAGS3 0x13
+#define TFA98XX_STATUS_FLAGS4 0x14
+#define TFA98XX_BATTERY_VOLTAGE 0x15
+#define TFA98XX_TEMPERATURE 0x16
+#define TFA98XX_TDM_CONFIG0 0x20
+#define TFA98XX_TDM_CONFIG1 0x21
+#define TFA98XX_TDM_CONFIG2 0x22
+#define TFA98XX_TDM_CONFIG3 0x23
+#define TFA98XX_TDM_CONFIG4 0x24
+#define TFA98XX_TDM_CONFIG5 0x25
+#define TFA98XX_TDM_CONFIG6 0x26
+#define TFA98XX_TDM_CONFIG7 0x27
+#define TFA98XX_TDM_CONFIG8 0x28
+#define TFA98XX_TDM_CONFIG9 0x29
+#define TFA98XX_PDM_CONFIG0 0x31
+#define TFA98XX_PDM_CONFIG1 0x32
+#define TFA98XX_HAPTIC_DRIVER_CONFIG 0x33
+#define TFA98XX_GPIO_DATAIN_REG 0x34
+#define TFA98XX_GPIO_CONFIG 0x35
+#define TFA98XX_INTERRUPT_OUT_REG1 0x40
+#define TFA98XX_INTERRUPT_OUT_REG2 0x41
+#define TFA98XX_INTERRUPT_OUT_REG3 0x42
+#define TFA98XX_INTERRUPT_IN_REG1 0x44
+#define TFA98XX_INTERRUPT_IN_REG2 0x45
+#define TFA98XX_INTERRUPT_IN_REG3 0x46
+#define TFA98XX_INTERRUPT_ENABLE_REG1 0x48
+#define TFA98XX_INTERRUPT_ENABLE_REG2 0x49
+#define TFA98XX_INTERRUPT_ENABLE_REG3 0x4a
+#define TFA98XX_STATUS_POLARITY_REG1 0x4c
+#define TFA98XX_STATUS_POLARITY_REG2 0x4d
+#define TFA98XX_STATUS_POLARITY_REG3 0x4e
+#define TFA98XX_BAT_PROT_CONFIG 0x50
+#define TFA98XX_AUDIO_CONTROL 0x51
+#define TFA98XX_AMPLIFIER_CONFIG 0x52
+#define TFA98XX_AUDIO_CONTROL2 0x5a
+#define TFA98XX_DCDC_CONTROL0 0x70
+#define TFA98XX_CF_CONTROLS 0x90
+#define TFA98XX_CF_MAD 0x91
+#define TFA98XX_CF_MEM 0x92
+#define TFA98XX_CF_STATUS 0x93
+#define TFA98XX_MTPKEY2_REG 0xa1
+#define TFA98XX_MTP_STATUS 0xa2
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL 0xa3
+#define TFA98XX_MTP_DATA_OUT_MSB 0xa5
+#define TFA98XX_MTP_DATA_OUT_LSB 0xa6
+#define TFA98XX_TEMP_SENSOR_CONFIG 0xb1
+#define TFA98XX_KEY2_PROTECTED_MTP0 0xf0
+#define TFA98XX_KEY1_PROTECTED_MTP4 0xf4
+#define TFA98XX_KEY1_PROTECTED_MTP5 0xf5
+
+/*
+ * (0x00)-sys_control0
+ */
+
+/*
+ * powerdown
+ */
+#define TFA98XX_SYS_CONTROL0_PWDN (0x1<<0)
+#define TFA98XX_SYS_CONTROL0_PWDN_POS 0
+#define TFA98XX_SYS_CONTROL0_PWDN_LEN 1
+#define TFA98XX_SYS_CONTROL0_PWDN_MAX 1
+#define TFA98XX_SYS_CONTROL0_PWDN_MSK 0x1
+
+/*
+ * reset
+ */
+#define TFA98XX_SYS_CONTROL0_I2CR (0x1<<1)
+#define TFA98XX_SYS_CONTROL0_I2CR_POS 1
+#define TFA98XX_SYS_CONTROL0_I2CR_LEN 1
+#define TFA98XX_SYS_CONTROL0_I2CR_MAX 1
+#define TFA98XX_SYS_CONTROL0_I2CR_MSK 0x2
+
+/*
+ * enbl_coolflux
+ */
+#define TFA98XX_SYS_CONTROL0_CFE (0x1<<2)
+#define TFA98XX_SYS_CONTROL0_CFE_POS 2
+#define TFA98XX_SYS_CONTROL0_CFE_LEN 1
+#define TFA98XX_SYS_CONTROL0_CFE_MAX 1
+#define TFA98XX_SYS_CONTROL0_CFE_MSK 0x4
+
+/*
+ * enbl_amplifier
+ */
+#define TFA98XX_SYS_CONTROL0_AMPE (0x1<<3)
+#define TFA98XX_SYS_CONTROL0_AMPE_POS 3
+#define TFA98XX_SYS_CONTROL0_AMPE_LEN 1
+#define TFA98XX_SYS_CONTROL0_AMPE_MAX 1
+#define TFA98XX_SYS_CONTROL0_AMPE_MSK 0x8
+
+/*
+ * enbl_boost
+ */
+#define TFA98XX_SYS_CONTROL0_DCA (0x1<<4)
+#define TFA98XX_SYS_CONTROL0_DCA_POS 4
+#define TFA98XX_SYS_CONTROL0_DCA_LEN 1
+#define TFA98XX_SYS_CONTROL0_DCA_MAX 1
+#define TFA98XX_SYS_CONTROL0_DCA_MSK 0x10
+
+/*
+ * coolflux_configured
+ */
+#define TFA98XX_SYS_CONTROL0_SBSL (0x1<<5)
+#define TFA98XX_SYS_CONTROL0_SBSL_POS 5
+#define TFA98XX_SYS_CONTROL0_SBSL_LEN 1
+#define TFA98XX_SYS_CONTROL0_SBSL_MAX 1
+#define TFA98XX_SYS_CONTROL0_SBSL_MSK 0x20
+
+/*
+ * sel_enbl_amplifier
+ */
+#define TFA98XX_SYS_CONTROL0_AMPC (0x1<<6)
+#define TFA98XX_SYS_CONTROL0_AMPC_POS 6
+#define TFA98XX_SYS_CONTROL0_AMPC_LEN 1
+#define TFA98XX_SYS_CONTROL0_AMPC_MAX 1
+#define TFA98XX_SYS_CONTROL0_AMPC_MSK 0x40
+
+/*
+ * int_pad_io
+ */
+#define TFA98XX_SYS_CONTROL0_INTP (0x3<<7)
+#define TFA98XX_SYS_CONTROL0_INTP_POS 7
+#define TFA98XX_SYS_CONTROL0_INTP_LEN 2
+#define TFA98XX_SYS_CONTROL0_INTP_MAX 3
+#define TFA98XX_SYS_CONTROL0_INTP_MSK 0x180
+
+/*
+ * fs_pulse_sel
+ */
+#define TFA98XX_SYS_CONTROL0_FSSSEL (0x3<<9)
+#define TFA98XX_SYS_CONTROL0_FSSSEL_POS 9
+#define TFA98XX_SYS_CONTROL0_FSSSEL_LEN 2
+#define TFA98XX_SYS_CONTROL0_FSSSEL_MAX 3
+#define TFA98XX_SYS_CONTROL0_FSSSEL_MSK 0x600
+
+/*
+ * bypass_ocp
+ */
+#define TFA98XX_SYS_CONTROL0_BYPOCP (0x1<<11)
+#define TFA98XX_SYS_CONTROL0_BYPOCP_POS 11
+#define TFA98XX_SYS_CONTROL0_BYPOCP_LEN 1
+#define TFA98XX_SYS_CONTROL0_BYPOCP_MAX 1
+#define TFA98XX_SYS_CONTROL0_BYPOCP_MSK 0x800
+
+/*
+ * test_ocp
+ */
+#define TFA98XX_SYS_CONTROL0_TSTOCP (0x1<<12)
+#define TFA98XX_SYS_CONTROL0_TSTOCP_POS 12
+#define TFA98XX_SYS_CONTROL0_TSTOCP_LEN 1
+#define TFA98XX_SYS_CONTROL0_TSTOCP_MAX 1
+#define TFA98XX_SYS_CONTROL0_TSTOCP_MSK 0x1000
+
+
+/*
+ * (0x01)-sys_control1
+ */
+
+/*
+ * vamp_sel
+ */
+#define TFA98XX_SYS_CONTROL1_AMPINSEL (0x3<<0)
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_POS 0
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_LEN 2
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_MAX 3
+#define TFA98XX_SYS_CONTROL1_AMPINSEL_MSK 0x3
+
+/*
+ * src_set_configured
+ */
+#define TFA98XX_SYS_CONTROL1_MANSCONF (0x1<<2)
+#define TFA98XX_SYS_CONTROL1_MANSCONF_POS 2
+#define TFA98XX_SYS_CONTROL1_MANSCONF_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANSCONF_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANSCONF_MSK 0x4
+
+/*
+ * execute_cold_start
+ */
+#define TFA98XX_SYS_CONTROL1_MANCOLD (0x1<<3)
+#define TFA98XX_SYS_CONTROL1_MANCOLD_POS 3
+#define TFA98XX_SYS_CONTROL1_MANCOLD_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANCOLD_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANCOLD_MSK 0x8
+
+/*
+ * enbl_osc1m_auto_off
+ */
+#define TFA98XX_SYS_CONTROL1_MANAOOSC (0x1<<4)
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_POS 4
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANAOOSC_MSK 0x10
+
+/*
+ * man_enbl_brown_out
+ */
+#define TFA98XX_SYS_CONTROL1_MANROBOD (0x1<<5)
+#define TFA98XX_SYS_CONTROL1_MANROBOD_POS 5
+#define TFA98XX_SYS_CONTROL1_MANROBOD_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANROBOD_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANROBOD_MSK 0x20
+
+/*
+ * enbl_bod
+ */
+#define TFA98XX_SYS_CONTROL1_BODE (0x1<<6)
+#define TFA98XX_SYS_CONTROL1_BODE_POS 6
+#define TFA98XX_SYS_CONTROL1_BODE_LEN 1
+#define TFA98XX_SYS_CONTROL1_BODE_MAX 1
+#define TFA98XX_SYS_CONTROL1_BODE_MSK 0x40
+
+/*
+ * enbl_bod_hyst
+ */
+#define TFA98XX_SYS_CONTROL1_BODHYS (0x1<<7)
+#define TFA98XX_SYS_CONTROL1_BODHYS_POS 7
+#define TFA98XX_SYS_CONTROL1_BODHYS_LEN 1
+#define TFA98XX_SYS_CONTROL1_BODHYS_MAX 1
+#define TFA98XX_SYS_CONTROL1_BODHYS_MSK 0x80
+
+/*
+ * bod_delay
+ */
+#define TFA98XX_SYS_CONTROL1_BODFILT (0x3<<8)
+#define TFA98XX_SYS_CONTROL1_BODFILT_POS 8
+#define TFA98XX_SYS_CONTROL1_BODFILT_LEN 2
+#define TFA98XX_SYS_CONTROL1_BODFILT_MAX 3
+#define TFA98XX_SYS_CONTROL1_BODFILT_MSK 0x300
+
+/*
+ * bod_lvlsel
+ */
+#define TFA98XX_SYS_CONTROL1_BODTHLVL (0x3<<10)
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_POS 10
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_LEN 2
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_MAX 3
+#define TFA98XX_SYS_CONTROL1_BODTHLVL_MSK 0xc00
+
+/*
+ * disable_mute_time_out
+ */
+#define TFA98XX_SYS_CONTROL1_MUTETO (0x1<<13)
+#define TFA98XX_SYS_CONTROL1_MUTETO_POS 13
+#define TFA98XX_SYS_CONTROL1_MUTETO_LEN 1
+#define TFA98XX_SYS_CONTROL1_MUTETO_MAX 1
+#define TFA98XX_SYS_CONTROL1_MUTETO_MSK 0x2000
+
+/*
+ * pwm_sel_rcv_ns
+ */
+#define TFA98XX_SYS_CONTROL1_RCVNS (0x1<<14)
+#define TFA98XX_SYS_CONTROL1_RCVNS_POS 14
+#define TFA98XX_SYS_CONTROL1_RCVNS_LEN 1
+#define TFA98XX_SYS_CONTROL1_RCVNS_MAX 1
+#define TFA98XX_SYS_CONTROL1_RCVNS_MSK 0x4000
+
+/*
+ * man_enbl_watchdog
+ */
+#define TFA98XX_SYS_CONTROL1_MANWDE (0x1<<15)
+#define TFA98XX_SYS_CONTROL1_MANWDE_POS 15
+#define TFA98XX_SYS_CONTROL1_MANWDE_LEN 1
+#define TFA98XX_SYS_CONTROL1_MANWDE_MAX 1
+#define TFA98XX_SYS_CONTROL1_MANWDE_MSK 0x8000
+
+
+/*
+ * (0x02)-sys_control2
+ */
+
+/*
+ * audio_fs
+ */
+#define TFA98XX_SYS_CONTROL2_AUDFS (0xf<<0)
+#define TFA98XX_SYS_CONTROL2_AUDFS_POS 0
+#define TFA98XX_SYS_CONTROL2_AUDFS_LEN 4
+#define TFA98XX_SYS_CONTROL2_AUDFS_MAX 15
+#define TFA98XX_SYS_CONTROL2_AUDFS_MSK 0xf
+
+/*
+ * input_level
+ */
+#define TFA98XX_SYS_CONTROL2_INPLEV (0x1<<4)
+#define TFA98XX_SYS_CONTROL2_INPLEV_POS 4
+#define TFA98XX_SYS_CONTROL2_INPLEV_LEN 1
+#define TFA98XX_SYS_CONTROL2_INPLEV_MAX 1
+#define TFA98XX_SYS_CONTROL2_INPLEV_MSK 0x10
+
+/*
+ * cs_frac_delay
+ */
+#define TFA98XX_SYS_CONTROL2_FRACTDEL (0x3f<<5)
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_POS 5
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_LEN 6
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_MAX 63
+#define TFA98XX_SYS_CONTROL2_FRACTDEL_MSK 0x7e0
+
+/*
+ * bypass_hvbat_filter
+ */
+#define TFA98XX_SYS_CONTROL2_BYPHVBF (0x1<<11)
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_POS 11
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_LEN 1
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_MAX 1
+#define TFA98XX_SYS_CONTROL2_BYPHVBF_MSK 0x800
+
+/*
+ * ctrl_rcvldop_bypass
+ */
+#define TFA98XX_SYS_CONTROL2_LDOBYP (0x1<<12)
+#define TFA98XX_SYS_CONTROL2_LDOBYP_POS 12
+#define TFA98XX_SYS_CONTROL2_LDOBYP_LEN 1
+#define TFA98XX_SYS_CONTROL2_LDOBYP_MAX 1
+#define TFA98XX_SYS_CONTROL2_LDOBYP_MSK 0x1000
+
+
+/*
+ * (0x03)-device_revision
+ */
+
+/*
+ * device_rev
+ */
+#define TFA98XX_DEVICE_REVISION_REV (0xffff<<0)
+#define TFA98XX_DEVICE_REVISION_REV_POS 0
+#define TFA98XX_DEVICE_REVISION_REV_LEN 16
+#define TFA98XX_DEVICE_REVISION_REV_MAX 65535
+#define TFA98XX_DEVICE_REVISION_REV_MSK 0xffff
+
+
+/*
+ * (0x04)-clock_control
+ */
+
+/*
+ * pll_clkin_sel
+ */
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT (0x3<<0)
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_POS 0
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_LEN 2
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_MAX 3
+#define TFA98XX_CLOCK_CONTROL_REFCKEXT_MSK 0x3
+
+/*
+ * pll_clkin_sel_osc
+ */
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL (0x1<<2)
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_POS 2
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_LEN 1
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_MAX 1
+#define TFA98XX_CLOCK_CONTROL_REFCKSEL_MSK 0x4
+
+
+/*
+ * (0x05)-clock_gating_control
+ */
+
+/*
+ * enbl_spkr_ss_left
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE (0x1<<0)
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_POS 0
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSLEFTE_MSK 0x1
+
+/*
+ * enbl_spkr_ss_right
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE (0x1<<1)
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_POS 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSRIGHTE_MSK 0x2
+
+/*
+ * enbl_volsense_left
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE (0x1<<2)
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_POS 2
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSLEFTE_MSK 0x4
+
+/*
+ * enbl_volsense_right
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE (0x1<<3)
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_POS 3
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_VSRIGHTE_MSK 0x8
+
+/*
+ * enbl_cursense_left
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE (0x1<<4)
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_POS 4
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSLEFTE_MSK 0x10
+
+/*
+ * enbl_cursense_right
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE (0x1<<5)
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_POS 5
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_CSRIGHTE_MSK 0x20
+
+/*
+ * enbl_pdm_ss
+ */
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME (0x1<<6)
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_POS 6
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_LEN 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_MAX 1
+#define TFA98XX_CLOCK_GATING_CONTROL_SSPDME_MSK 0x40
+
+
+/*
+ * (0x0d)-side_tone_config
+ */
+
+/*
+ * side_tone_gain
+ */
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN (0x1ff<<1)
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_POS 1
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_LEN 9
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_MAX 511
+#define TFA98XX_SIDE_TONE_CONFIG_STGAIN_MSK 0x3fe
+
+/*
+ * mute_side_tone
+ */
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE (0x1<<10)
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_POS 10
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_LEN 1
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_MAX 1
+#define TFA98XX_SIDE_TONE_CONFIG_PDMSMUTE_MSK 0x400
+
+
+/*
+ * (0x0e)-ctrl_digtoana_reg
+ */
+
+/*
+ * ctrl_digtoana
+ */
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP (0x7f<<0)
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_POS 0
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_LEN 7
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_MAX 127
+#define TFA98XX_CTRL_DIGTOANA_REG_SWVSTEP_MSK 0x7f
+
+
+/*
+ * (0x10)-status_flags0
+ */
+
+/*
+ * flag_por
+ */
+#define TFA98XX_STATUS_FLAGS0_VDDS (0x1<<0)
+#define TFA98XX_STATUS_FLAGS0_VDDS_POS 0
+#define TFA98XX_STATUS_FLAGS0_VDDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_VDDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_VDDS_MSK 0x1
+
+/*
+ * flag_pll_lock
+ */
+#define TFA98XX_STATUS_FLAGS0_PLLS (0x1<<1)
+#define TFA98XX_STATUS_FLAGS0_PLLS_POS 1
+#define TFA98XX_STATUS_FLAGS0_PLLS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_PLLS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_PLLS_MSK 0x2
+
+/*
+ * flag_otpok
+ */
+#define TFA98XX_STATUS_FLAGS0_OTDS (0x1<<2)
+#define TFA98XX_STATUS_FLAGS0_OTDS_POS 2
+#define TFA98XX_STATUS_FLAGS0_OTDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_OTDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_OTDS_MSK 0x4
+
+/*
+ * flag_ovpok
+ */
+#define TFA98XX_STATUS_FLAGS0_OVDS (0x1<<3)
+#define TFA98XX_STATUS_FLAGS0_OVDS_POS 3
+#define TFA98XX_STATUS_FLAGS0_OVDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_OVDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_OVDS_MSK 0x8
+
+/*
+ * flag_uvpok
+ */
+#define TFA98XX_STATUS_FLAGS0_UVDS (0x1<<4)
+#define TFA98XX_STATUS_FLAGS0_UVDS_POS 4
+#define TFA98XX_STATUS_FLAGS0_UVDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_UVDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_UVDS_MSK 0x10
+
+/*
+ * flag_clocks_stable
+ */
+#define TFA98XX_STATUS_FLAGS0_CLKS (0x1<<6)
+#define TFA98XX_STATUS_FLAGS0_CLKS_POS 5
+#define TFA98XX_STATUS_FLAGS0_CLKS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_CLKS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_CLKS_MSK 0x20
+
+/*
+ * flag_mtp_busy
+ */
+#define TFA98XX_STATUS_FLAGS0_MTPB (0x1<<6)
+#define TFA98XX_STATUS_FLAGS0_MTPB_POS 6
+#define TFA98XX_STATUS_FLAGS0_MTPB_LEN 1
+#define TFA98XX_STATUS_FLAGS0_MTPB_MAX 1
+#define TFA98XX_STATUS_FLAGS0_MTPB_MSK 0x40
+
+/*
+ * flag_lost_clk
+ */
+#define TFA98XX_STATUS_FLAGS0_NOCLK (0x1<<7)
+#define TFA98XX_STATUS_FLAGS0_NOCLK_POS 7
+#define TFA98XX_STATUS_FLAGS0_NOCLK_LEN 1
+#define TFA98XX_STATUS_FLAGS0_NOCLK_MAX 1
+#define TFA98XX_STATUS_FLAGS0_NOCLK_MSK 0x80
+
+/*
+ * flag_cf_speakererror
+ */
+#define TFA98XX_STATUS_FLAGS0_SPKS (0x1<<8)
+#define TFA98XX_STATUS_FLAGS0_SPKS_POS 8
+#define TFA98XX_STATUS_FLAGS0_SPKS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_SPKS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_SPKS_MSK 0x100
+
+/*
+ * flag_cold_started
+ */
+#define TFA98XX_STATUS_FLAGS0_ACS (0x1<<9)
+#define TFA98XX_STATUS_FLAGS0_ACS_POS 9
+#define TFA98XX_STATUS_FLAGS0_ACS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_ACS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_ACS_MSK 0x200
+
+/*
+ * flag_engage
+ */
+#define TFA98XX_STATUS_FLAGS0_SWS (0x1<<10)
+#define TFA98XX_STATUS_FLAGS0_SWS_POS 10
+#define TFA98XX_STATUS_FLAGS0_SWS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_SWS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_SWS_MSK 0x400
+
+/*
+ * flag_watchdog_reset
+ */
+#define TFA98XX_STATUS_FLAGS0_WDS (0x1<<11)
+#define TFA98XX_STATUS_FLAGS0_WDS_POS 11
+#define TFA98XX_STATUS_FLAGS0_WDS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_WDS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_WDS_MSK 0x800
+
+/*
+ * flag_enbl_amp
+ */
+#define TFA98XX_STATUS_FLAGS0_AMPS (0x1<<12)
+#define TFA98XX_STATUS_FLAGS0_AMPS_POS 12
+#define TFA98XX_STATUS_FLAGS0_AMPS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_AMPS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_AMPS_MSK 0x1000
+
+/*
+ * flag_enbl_ref
+ */
+#define TFA98XX_STATUS_FLAGS0_AREFS (0x1<<13)
+#define TFA98XX_STATUS_FLAGS0_AREFS_POS 13
+#define TFA98XX_STATUS_FLAGS0_AREFS_LEN 1
+#define TFA98XX_STATUS_FLAGS0_AREFS_MAX 1
+#define TFA98XX_STATUS_FLAGS0_AREFS_MSK 0x2000
+
+/*
+ * flag_adc10_ready
+ */
+#define TFA98XX_STATUS_FLAGS0_ADCCR (0x1<<14)
+#define TFA98XX_STATUS_FLAGS0_ADCCR_POS 14
+#define TFA98XX_STATUS_FLAGS0_ADCCR_LEN 1
+#define TFA98XX_STATUS_FLAGS0_ADCCR_MAX 1
+#define TFA98XX_STATUS_FLAGS0_ADCCR_MSK 0x4000
+
+/*
+ * flag_bod_vddd_nok
+ */
+#define TFA98XX_STATUS_FLAGS0_BODNOK (0x1<<15)
+#define TFA98XX_STATUS_FLAGS0_BODNOK_POS 15
+#define TFA98XX_STATUS_FLAGS0_BODNOK_LEN 1
+#define TFA98XX_STATUS_FLAGS0_BODNOK_MAX 1
+#define TFA98XX_STATUS_FLAGS0_BODNOK_MSK 0x8000
+
+
+/*
+ * (0x11)-status_flags1
+ */
+
+/*
+ * flag_bst_bstcur
+ */
+#define TFA98XX_STATUS_FLAGS1_DCIL (0x1<<0)
+#define TFA98XX_STATUS_FLAGS1_DCIL_POS 0
+#define TFA98XX_STATUS_FLAGS1_DCIL_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCIL_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCIL_MSK 0x1
+
+/*
+ * flag_bst_hiz
+ */
+#define TFA98XX_STATUS_FLAGS1_DCDCA (0x1<<1)
+#define TFA98XX_STATUS_FLAGS1_DCDCA_POS 1
+#define TFA98XX_STATUS_FLAGS1_DCDCA_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCDCA_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCDCA_MSK 0x2
+
+/*
+ * flag_bst_ocpok
+ */
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK (0x1<<2)
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_POS 2
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCOCPOK_MSK 0x4
+
+/*
+ * flag_bst_voutcomp
+ */
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT (0x1<<4)
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_POS 4
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCHVBAT_MSK 0x10
+
+/*
+ * flag_bst_voutcomp86
+ */
+#define TFA98XX_STATUS_FLAGS1_DCH114 (0x1<<5)
+#define TFA98XX_STATUS_FLAGS1_DCH114_POS 5
+#define TFA98XX_STATUS_FLAGS1_DCH114_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCH114_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCH114_MSK 0x20
+
+/*
+ * flag_bst_voutcomp93
+ */
+#define TFA98XX_STATUS_FLAGS1_DCH107 (0x1<<6)
+#define TFA98XX_STATUS_FLAGS1_DCH107_POS 6
+#define TFA98XX_STATUS_FLAGS1_DCH107_LEN 1
+#define TFA98XX_STATUS_FLAGS1_DCH107_MAX 1
+#define TFA98XX_STATUS_FLAGS1_DCH107_MSK 0x40
+
+/*
+ * flag_soft_mute_busy
+ */
+#define TFA98XX_STATUS_FLAGS1_STMUTEB (0x1<<7)
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_POS 7
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_LEN 1
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_MAX 1
+#define TFA98XX_STATUS_FLAGS1_STMUTEB_MSK 0x80
+
+/*
+ * flag_soft_mute_state
+ */
+#define TFA98XX_STATUS_FLAGS1_STMUTE (0x1<<8)
+#define TFA98XX_STATUS_FLAGS1_STMUTE_POS 8
+#define TFA98XX_STATUS_FLAGS1_STMUTE_LEN 1
+#define TFA98XX_STATUS_FLAGS1_STMUTE_MAX 1
+#define TFA98XX_STATUS_FLAGS1_STMUTE_MSK 0x100
+
+/*
+ * flag_tdm_lut_error
+ */
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER (0x1<<9)
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_POS 9
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_LEN 1
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_MAX 1
+#define TFA98XX_STATUS_FLAGS1_TDMLUTER_MSK 0x200
+
+/*
+ * flag_tdm_status
+ */
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT (0x7<<10)
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_POS 10
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_LEN 3
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_MAX 7
+#define TFA98XX_STATUS_FLAGS1_TDMSTAT_MSK 0x1c00
+
+/*
+ * flag_tdm_error
+ */
+#define TFA98XX_STATUS_FLAGS1_TDMERR (0x1<<13)
+#define TFA98XX_STATUS_FLAGS1_TDMERR_POS 13
+#define TFA98XX_STATUS_FLAGS1_TDMERR_LEN 1
+#define TFA98XX_STATUS_FLAGS1_TDMERR_MAX 1
+#define TFA98XX_STATUS_FLAGS1_TDMERR_MSK 0x2000
+
+/*
+ * flag_haptic_busy
+ */
+#define TFA98XX_STATUS_FLAGS1_HAPTIC (0x1<<14)
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_POS 14
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_LEN 1
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_MAX 1
+#define TFA98XX_STATUS_FLAGS1_HAPTIC_MSK 0x4000
+
+
+/*
+ * (0x12)-status_flags2
+ */
+
+/*
+ * flag_ocpokap_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL (0x1<<0)
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_POS 0
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPL_MSK 0x1
+
+/*
+ * flag_ocpokan_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOANL (0x1<<1)
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_POS 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANL_MSK 0x2
+
+/*
+ * flag_ocpokbp_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL (0x1<<2)
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_POS 2
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPL_MSK 0x4
+
+/*
+ * flag_ocpokbn_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL (0x1<<3)
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_POS 3
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNL_MSK 0x8
+
+/*
+ * flag_clipa_high_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL (0x1<<4)
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_POS 4
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPAHL_MSK 0x10
+
+/*
+ * flag_clipa_low_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPALL (0x1<<5)
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_POS 5
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPALL_MSK 0x20
+
+/*
+ * flag_clipb_high_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL (0x1<<6)
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_POS 6
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBHL_MSK 0x40
+
+/*
+ * flag_clipb_low_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL (0x1<<7)
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_POS 7
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPBLL_MSK 0x80
+
+/*
+ * flag_ocpokap_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC (0x1<<8)
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_POS 8
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOAPRC_MSK 0x100
+
+/*
+ * flag_ocpokan_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC (0x1<<9)
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_POS 9
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOANRC_MSK 0x200
+
+/*
+ * flag_ocpokbp_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC (0x1<<10)
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_POS 10
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBPRC_MSK 0x400
+
+/*
+ * flag_ocpokbn_rcv
+ */
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC (0x1<<11)
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_POS 11
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCPOBNRC_MSK 0x800
+
+/*
+ * flag_rcvldop_ready
+ */
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR (0x1<<12)
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_POS 12
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_LEN 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_MAX 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOR_MSK 0x1000
+
+/*
+ * flag_rcvldop_bypassready
+ */
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR (0x1<<13)
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_POS 13
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_LEN 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_MAX 1
+#define TFA98XX_STATUS_FLAGS2_RCVLDOBR_MSK 0x2000
+
+/*
+ * flag_ocp_alarm_left
+ */
+#define TFA98XX_STATUS_FLAGS2_OCDSL (0x1<<14)
+#define TFA98XX_STATUS_FLAGS2_OCDSL_POS 14
+#define TFA98XX_STATUS_FLAGS2_OCDSL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_OCDSL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_OCDSL_MSK 0x4000
+
+/*
+ * flag_clip_left
+ */
+#define TFA98XX_STATUS_FLAGS2_CLIPSL (0x1<<15)
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_POS 15
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_LEN 1
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_MAX 1
+#define TFA98XX_STATUS_FLAGS2_CLIPSL_MSK 0x8000
+
+
+/*
+ * (0x13)-status_flags3
+ */
+
+/*
+ * flag_ocpokap_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR (0x1<<0)
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_POS 0
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOAPR_MSK 0x1
+
+/*
+ * flag_ocpokan_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOANR (0x1<<1)
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_POS 1
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOANR_MSK 0x2
+
+/*
+ * flag_ocpokbp_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR (0x1<<2)
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_POS 2
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBPR_MSK 0x4
+
+/*
+ * flag_ocpokbn_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR (0x1<<3)
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_POS 3
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOBNR_MSK 0x8
+
+/*
+ * flag_clipa_high_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR (0x1<<4)
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_POS 4
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPAHR_MSK 0x10
+
+/*
+ * flag_clipa_low_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPALR (0x1<<5)
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_POS 5
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPALR_MSK 0x20
+
+/*
+ * flag_clipb_high_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR (0x1<<6)
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_POS 6
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBHR_MSK 0x40
+
+/*
+ * flag_clipb_low_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR (0x1<<7)
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_POS 7
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPBLR_MSK 0x80
+
+/*
+ * flag_ocp_alarm_right
+ */
+#define TFA98XX_STATUS_FLAGS3_OCDSR (0x1<<8)
+#define TFA98XX_STATUS_FLAGS3_OCDSR_POS 8
+#define TFA98XX_STATUS_FLAGS3_OCDSR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCDSR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCDSR_MSK 0x100
+
+/*
+ * flag_clip_right
+ */
+#define TFA98XX_STATUS_FLAGS3_CLIPSR (0x1<<9)
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_POS 9
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_LEN 1
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_MAX 1
+#define TFA98XX_STATUS_FLAGS3_CLIPSR_MSK 0x200
+
+/*
+ * flag_mic_ocpok
+ */
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC (0x1<<10)
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_POS 10
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_LEN 1
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_MAX 1
+#define TFA98XX_STATUS_FLAGS3_OCPOKMC_MSK 0x400
+
+/*
+ * flag_man_alarm_state
+ */
+#define TFA98XX_STATUS_FLAGS3_MANALARM (0x1<<11)
+#define TFA98XX_STATUS_FLAGS3_MANALARM_POS 11
+#define TFA98XX_STATUS_FLAGS3_MANALARM_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANALARM_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANALARM_MSK 0x800
+
+/*
+ * flag_man_wait_src_settings
+ */
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1 (0x1<<12)
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_POS 12
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT1_MSK 0x1000
+
+/*
+ * flag_man_wait_cf_config
+ */
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2 (0x1<<13)
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_POS 13
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANWAIT2_MSK 0x2000
+
+/*
+ * flag_man_start_mute_audio
+ */
+#define TFA98XX_STATUS_FLAGS3_MANMUTE (0x1<<14)
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_POS 14
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANMUTE_MSK 0x4000
+
+/*
+ * flag_man_operating_state
+ */
+#define TFA98XX_STATUS_FLAGS3_MANOPER (0x1<<15)
+#define TFA98XX_STATUS_FLAGS3_MANOPER_POS 15
+#define TFA98XX_STATUS_FLAGS3_MANOPER_LEN 1
+#define TFA98XX_STATUS_FLAGS3_MANOPER_MAX 1
+#define TFA98XX_STATUS_FLAGS3_MANOPER_MSK 0x8000
+
+
+/*
+ * (0x14)-status_flags4
+ */
+
+/*
+ * flag_cf_speakererror_left
+ */
+#define TFA98XX_STATUS_FLAGS4_SPKSL (0x1<<0)
+#define TFA98XX_STATUS_FLAGS4_SPKSL_POS 0
+#define TFA98XX_STATUS_FLAGS4_SPKSL_LEN 1
+#define TFA98XX_STATUS_FLAGS4_SPKSL_MAX 1
+#define TFA98XX_STATUS_FLAGS4_SPKSL_MSK 0x1
+
+/*
+ * flag_cf_speakererror_right
+ */
+#define TFA98XX_STATUS_FLAGS4_SPKSR (0x1<<1)
+#define TFA98XX_STATUS_FLAGS4_SPKSR_POS 1
+#define TFA98XX_STATUS_FLAGS4_SPKSR_LEN 1
+#define TFA98XX_STATUS_FLAGS4_SPKSR_MAX 1
+#define TFA98XX_STATUS_FLAGS4_SPKSR_MSK 0x2
+
+/*
+ * flag_clk_out_of_range
+ */
+#define TFA98XX_STATUS_FLAGS4_CLKOOR (0x1<<2)
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_POS 2
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_LEN 1
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_MAX 1
+#define TFA98XX_STATUS_FLAGS4_CLKOOR_MSK 0x4
+
+/*
+ * man_state
+ */
+#define TFA98XX_STATUS_FLAGS4_MANSTATE (0xf<<3)
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_POS 3
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_LEN 4
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_MAX 15
+#define TFA98XX_STATUS_FLAGS4_MANSTATE_MSK 0x78
+
+
+/*
+ * (0x15)-battery_voltage
+ */
+
+/*
+ * bat_adc
+ */
+#define TFA98XX_BATTERY_VOLTAGE_BATS (0x3ff<<0)
+#define TFA98XX_BATTERY_VOLTAGE_BATS_POS 0
+#define TFA98XX_BATTERY_VOLTAGE_BATS_LEN 10
+#define TFA98XX_BATTERY_VOLTAGE_BATS_MAX 1023
+#define TFA98XX_BATTERY_VOLTAGE_BATS_MSK 0x3ff
+
+
+/*
+ * (0x16)-temperature
+ */
+
+/*
+ * temp_adc
+ */
+#define TFA98XX_TEMPERATURE_TEMPS (0x1ff<<0)
+#define TFA98XX_TEMPERATURE_TEMPS_POS 0
+#define TFA98XX_TEMPERATURE_TEMPS_LEN 9
+#define TFA98XX_TEMPERATURE_TEMPS_MAX 511
+#define TFA98XX_TEMPERATURE_TEMPS_MSK 0x1ff
+
+
+/*
+ * (0x20)-tdm_config0
+ */
+
+/*
+ * tdm_usecase
+ */
+#define TFA98XX_TDM_CONFIG0_TDMUC (0xf<<0)
+#define TFA98XX_TDM_CONFIG0_TDMUC_POS 0
+#define TFA98XX_TDM_CONFIG0_TDMUC_LEN 4
+#define TFA98XX_TDM_CONFIG0_TDMUC_MAX 15
+#define TFA98XX_TDM_CONFIG0_TDMUC_MSK 0xf
+
+/*
+ * tdm_enable
+ */
+#define TFA98XX_TDM_CONFIG0_TDME (0x1<<4)
+#define TFA98XX_TDM_CONFIG0_TDME_POS 4
+#define TFA98XX_TDM_CONFIG0_TDME_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDME_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDME_MSK 0x10
+
+/*
+ * tdm_mode
+ */
+#define TFA98XX_TDM_CONFIG0_TDMMODE (0x1<<5)
+#define TFA98XX_TDM_CONFIG0_TDMMODE_POS 5
+#define TFA98XX_TDM_CONFIG0_TDMMODE_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDMMODE_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDMMODE_MSK 0x20
+
+/*
+ * tdm_clk_inversion
+ */
+#define TFA98XX_TDM_CONFIG0_TDMCLINV (0x1<<6)
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_POS 6
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDMCLINV_MSK 0x40
+
+/*
+ * tdm_fs_ws_length
+ */
+#define TFA98XX_TDM_CONFIG0_TDMFSLN (0xf<<7)
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_POS 7
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_LEN 4
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_MAX 15
+#define TFA98XX_TDM_CONFIG0_TDMFSLN_MSK 0x780
+
+/*
+ * tdm_fs_ws_polarity
+ */
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL (0x1<<11)
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_POS 11
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_LEN 1
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_MAX 1
+#define TFA98XX_TDM_CONFIG0_TDMFSPOL_MSK 0x800
+
+/*
+ * tdm_nbck
+ */
+#define TFA98XX_TDM_CONFIG0_TDMNBCK (0xf<<12)
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_POS 12
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_LEN 4
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_MAX 15
+#define TFA98XX_TDM_CONFIG0_TDMNBCK_MSK 0xf000
+
+
+/*
+ * (0x21)-tdm_config1
+ */
+
+/*
+ * tdm_nb_of_slots
+ */
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS (0xf<<0)
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_POS 0
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_LEN 4
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_MAX 15
+#define TFA98XX_TDM_CONFIG1_TDMSLOTS_MSK 0xf
+
+/*
+ * tdm_slot_length
+ */
+#define TFA98XX_TDM_CONFIG1_TDMSLLN (0x1f<<4)
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_POS 4
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_LEN 5
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_MAX 31
+#define TFA98XX_TDM_CONFIG1_TDMSLLN_MSK 0x1f0
+
+/*
+ * tdm_bits_remaining
+ */
+#define TFA98XX_TDM_CONFIG1_TDMBRMG (0x1f<<9)
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_POS 9
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_LEN 5
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_MAX 31
+#define TFA98XX_TDM_CONFIG1_TDMBRMG_MSK 0x3e00
+
+/*
+ * tdm_data_delay
+ */
+#define TFA98XX_TDM_CONFIG1_TDMDEL (0x1<<14)
+#define TFA98XX_TDM_CONFIG1_TDMDEL_POS 14
+#define TFA98XX_TDM_CONFIG1_TDMDEL_LEN 1
+#define TFA98XX_TDM_CONFIG1_TDMDEL_MAX 1
+#define TFA98XX_TDM_CONFIG1_TDMDEL_MSK 0x4000
+
+/*
+ * tdm_data_adjustment
+ */
+#define TFA98XX_TDM_CONFIG1_TDMADJ (0x1<<15)
+#define TFA98XX_TDM_CONFIG1_TDMADJ_POS 15
+#define TFA98XX_TDM_CONFIG1_TDMADJ_LEN 1
+#define TFA98XX_TDM_CONFIG1_TDMADJ_MAX 1
+#define TFA98XX_TDM_CONFIG1_TDMADJ_MSK 0x8000
+
+
+/*
+ * (0x22)-tdm_config2
+ */
+
+/*
+ * tdm_audio_sample_compression
+ */
+#define TFA98XX_TDM_CONFIG2_TDMOOMP (0x3<<0)
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_POS 0
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMOOMP_MSK 0x3
+
+/*
+ * tdm_sample_size
+ */
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE (0x1f<<2)
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_POS 2
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_LEN 5
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_MAX 31
+#define TFA98XX_TDM_CONFIG2_TDMSSIZE_MSK 0x7c
+
+/*
+ * tdm_txdata_format
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO (0x3<<7)
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_POS 7
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXDFO_MSK 0x180
+
+/*
+ * tdm_txdata_format_unused_slot_sd0
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0 (0x3<<9)
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_POS 9
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXUS0_MSK 0x600
+
+/*
+ * tdm_txdata_format_unused_slot_sd1
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1 (0x3<<11)
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_POS 11
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXUS1_MSK 0x1800
+
+/*
+ * tdm_txdata_format_unused_slot_sd2
+ */
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2 (0x3<<13)
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_POS 13
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_LEN 2
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_MAX 3
+#define TFA98XX_TDM_CONFIG2_TDMTXUS2_MSK 0x6000
+
+
+/*
+ * (0x23)-tdm_config3
+ */
+
+/*
+ * tdm_sink1_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMLE (0x1<<1)
+#define TFA98XX_TDM_CONFIG3_TDMLE_POS 1
+#define TFA98XX_TDM_CONFIG3_TDMLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMLE_MSK 0x2
+
+/*
+ * tdm_sink2_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMRE (0x1<<2)
+#define TFA98XX_TDM_CONFIG3_TDMRE_POS 2
+#define TFA98XX_TDM_CONFIG3_TDMRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMRE_MSK 0x4
+
+/*
+ * tdm_source1_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMVSRE (0x1<<4)
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_POS 4
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMVSRE_MSK 0x10
+
+/*
+ * tdm_source2_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCSRE (0x1<<5)
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_POS 5
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCSRE_MSK 0x20
+
+/*
+ * tdm_source3_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMVSLE (0x1<<6)
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_POS 6
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMVSLE_MSK 0x40
+
+/*
+ * tdm_source4_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCSLE (0x1<<7)
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_POS 7
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCSLE_MSK 0x80
+
+/*
+ * tdm_source5_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCFRE (0x1<<8)
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_POS 8
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCFRE_MSK 0x100
+
+/*
+ * tdm_source6_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCFLE (0x1<<9)
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_POS 9
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCFLE_MSK 0x200
+
+/*
+ * tdm_source7_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCF3E (0x1<<10)
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_POS 10
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCF3E_MSK 0x400
+
+/*
+ * tdm_source8_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMCF4E (0x1<<11)
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_POS 11
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMCF4E_MSK 0x800
+
+/*
+ * tdm_source9_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMPD1E (0x1<<12)
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_POS 12
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMPD1E_MSK 0x1000
+
+/*
+ * tdm_source10_enable
+ */
+#define TFA98XX_TDM_CONFIG3_TDMPD2E (0x1<<13)
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_POS 13
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_LEN 1
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_MAX 1
+#define TFA98XX_TDM_CONFIG3_TDMPD2E_MSK 0x2000
+
+
+/*
+ * (0x24)-tdm_config4
+ */
+
+/*
+ * tdm_sink1_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMLIO (0x3<<2)
+#define TFA98XX_TDM_CONFIG4_TDMLIO_POS 2
+#define TFA98XX_TDM_CONFIG4_TDMLIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMLIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMLIO_MSK 0xc
+
+/*
+ * tdm_sink2_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMRIO (0x3<<4)
+#define TFA98XX_TDM_CONFIG4_TDMRIO_POS 4
+#define TFA98XX_TDM_CONFIG4_TDMRIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMRIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMRIO_MSK 0x30
+
+/*
+ * tdm_source1_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO (0x3<<8)
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_POS 8
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMVSRIO_MSK 0x300
+
+/*
+ * tdm_source2_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO (0x3<<10)
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_POS 10
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMCSRIO_MSK 0xc00
+
+/*
+ * tdm_source3_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO (0x3<<12)
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_POS 12
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMVSLIO_MSK 0x3000
+
+/*
+ * tdm_source4_io
+ */
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO (0x3<<14)
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_POS 14
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_LEN 2
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_MAX 3
+#define TFA98XX_TDM_CONFIG4_TDMCSLIO_MSK 0xc000
+
+
+/*
+ * (0x25)-tdm_config5
+ */
+
+/*
+ * tdm_source5_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO (0x3<<0)
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_POS 0
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCFRIO_MSK 0x3
+
+/*
+ * tdm_source6_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO (0x3<<2)
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_POS 2
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCFLIO_MSK 0xc
+
+/*
+ * tdm_source7_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO (0x3<<4)
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_POS 4
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCF3IO_MSK 0x30
+
+/*
+ * tdm_source8_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO (0x3<<6)
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_POS 6
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMCF4IO_MSK 0xc0
+
+/*
+ * tdm_source9_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO (0x3<<8)
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_POS 8
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMPD1IO_MSK 0x300
+
+/*
+ * tdm_source10_io
+ */
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO (0x3<<10)
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_POS 10
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_LEN 2
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_MAX 3
+#define TFA98XX_TDM_CONFIG5_TDMPD2IO_MSK 0xc00
+
+
+/*
+ * (0x26)-tdm_config6
+ */
+
+/*
+ * tdm_sink1_slot
+ */
+#define TFA98XX_TDM_CONFIG6_TDMLS (0xf<<4)
+#define TFA98XX_TDM_CONFIG6_TDMLS_POS 4
+#define TFA98XX_TDM_CONFIG6_TDMLS_LEN 4
+#define TFA98XX_TDM_CONFIG6_TDMLS_MAX 15
+#define TFA98XX_TDM_CONFIG6_TDMLS_MSK 0xf0
+
+/*
+ * tdm_sink2_slot
+ */
+#define TFA98XX_TDM_CONFIG6_TDMRS (0xf<<8)
+#define TFA98XX_TDM_CONFIG6_TDMRS_POS 8
+#define TFA98XX_TDM_CONFIG6_TDMRS_LEN 4
+#define TFA98XX_TDM_CONFIG6_TDMRS_MAX 15
+#define TFA98XX_TDM_CONFIG6_TDMRS_MSK 0xf00
+
+
+/*
+ * (0x27)-tdm_config7
+ */
+
+/*
+ * tdm_source1_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMVSRS (0xf<<0)
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_POS 0
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMVSRS_MSK 0xf
+
+/*
+ * tdm_source2_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMCSRS (0xf<<4)
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_POS 4
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMCSRS_MSK 0xf0
+
+/*
+ * tdm_source3_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMVSLS (0xf<<8)
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_POS 8
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMVSLS_MSK 0xf00
+
+/*
+ * tdm_source4_slot
+ */
+#define TFA98XX_TDM_CONFIG7_TDMCSLS (0xf<<12)
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_POS 12
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_LEN 4
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_MAX 15
+#define TFA98XX_TDM_CONFIG7_TDMCSLS_MSK 0xf000
+
+
+/*
+ * (0x28)-tdm_config8
+ */
+
+/*
+ * tdm_source5_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCFRS (0xf<<0)
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_POS 0
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCFRS_MSK 0xf
+
+/*
+ * tdm_source6_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCFLS (0xf<<4)
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_POS 4
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCFLS_MSK 0xf0
+
+/*
+ * tdm_source7_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCF3S (0xf<<8)
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_POS 8
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCF3S_MSK 0xf00
+
+/*
+ * tdm_source8_slot
+ */
+#define TFA98XX_TDM_CONFIG8_TDMCF4S (0xf<<12)
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_POS 12
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_LEN 4
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_MAX 15
+#define TFA98XX_TDM_CONFIG8_TDMCF4S_MSK 0xf000
+
+
+/*
+ * (0x29)-tdm_config9
+ */
+
+/*
+ * tdm_source9_slot
+ */
+#define TFA98XX_TDM_CONFIG9_TDMPD1S (0xf<<0)
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_POS 0
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_LEN 4
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_MAX 15
+#define TFA98XX_TDM_CONFIG9_TDMPD1S_MSK 0xf
+
+/*
+ * tdm_source10_slot
+ */
+#define TFA98XX_TDM_CONFIG9_TDMPD2S (0xf<<4)
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_POS 4
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_LEN 4
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_MAX 15
+#define TFA98XX_TDM_CONFIG9_TDMPD2S_MSK 0xf0
+
+
+/*
+ * (0x31)-pdm_config0
+ */
+
+/*
+ * pdm_mode
+ */
+#define TFA98XX_PDM_CONFIG0_PDMSM (0x1<<0)
+#define TFA98XX_PDM_CONFIG0_PDMSM_POS 0
+#define TFA98XX_PDM_CONFIG0_PDMSM_LEN 1
+#define TFA98XX_PDM_CONFIG0_PDMSM_MAX 1
+#define TFA98XX_PDM_CONFIG0_PDMSM_MSK 0x1
+
+/*
+ * pdm_side_tone_sel
+ */
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL (0x3<<1)
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_POS 1
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_LEN 2
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_MAX 3
+#define TFA98XX_PDM_CONFIG0_PDMSTSEL_MSK 0x6
+
+/*
+ * pdm_left_sel
+ */
+#define TFA98XX_PDM_CONFIG0_PDMLSEL (0x1<<3)
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_POS 3
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_LEN 1
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_MAX 1
+#define TFA98XX_PDM_CONFIG0_PDMLSEL_MSK 0x8
+
+/*
+ * pdm_right_sel
+ */
+#define TFA98XX_PDM_CONFIG0_PDMRSEL (0x1<<4)
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_POS 4
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_LEN 1
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_MAX 1
+#define TFA98XX_PDM_CONFIG0_PDMRSEL_MSK 0x10
+
+/*
+ * enbl_micvdd
+ */
+#define TFA98XX_PDM_CONFIG0_MICVDDE (0x1<<5)
+#define TFA98XX_PDM_CONFIG0_MICVDDE_POS 5
+#define TFA98XX_PDM_CONFIG0_MICVDDE_LEN 1
+#define TFA98XX_PDM_CONFIG0_MICVDDE_MAX 1
+#define TFA98XX_PDM_CONFIG0_MICVDDE_MSK 0x20
+
+
+/*
+ * (0x32)-pdm_config1
+ */
+
+/*
+ * pdm_nbck
+ */
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT (0x3<<0)
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_POS 0
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_LEN 2
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_MAX 3
+#define TFA98XX_PDM_CONFIG1_PDMCLRAT_MSK 0x3
+
+/*
+ * pdm_gain
+ */
+#define TFA98XX_PDM_CONFIG1_PDMGAIN (0xf<<2)
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_POS 2
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_LEN 4
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_MAX 15
+#define TFA98XX_PDM_CONFIG1_PDMGAIN_MSK 0x3c
+
+/*
+ * sel_pdm_out_data
+ */
+#define TFA98XX_PDM_CONFIG1_PDMOSEL (0xf<<6)
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_POS 6
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_LEN 4
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_MAX 15
+#define TFA98XX_PDM_CONFIG1_PDMOSEL_MSK 0x3c0
+
+/*
+ * sel_cf_haptic_data
+ */
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD (0x1<<10)
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_POS 10
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_LEN 1
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_MAX 1
+#define TFA98XX_PDM_CONFIG1_SELCFHAPD_MSK 0x400
+
+
+/*
+ * (0x33)-haptic_driver_config
+ */
+
+/*
+ * haptic_duration
+ */
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME (0xff<<0)
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_POS 0
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_LEN 8
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_MAX 255
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPTIME_MSK 0xff
+
+/*
+ * haptic_data
+ */
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL (0xff<<8)
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_POS 8
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_LEN 8
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_MAX 255
+#define TFA98XX_HAPTIC_DRIVER_CONFIG_HAPLEVEL_MSK 0xff00
+
+
+/*
+ * (0x34)-gpio_datain_reg
+ */
+
+/*
+ * gpio_datain
+ */
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN (0xf<<0)
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_POS 0
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_LEN 4
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_MAX 15
+#define TFA98XX_GPIO_DATAIN_REG_GPIODIN_MSK 0xf
+
+
+/*
+ * (0x35)-gpio_config
+ */
+
+/*
+ * gpio_ctrl
+ */
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL (0x1<<0)
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_POS 0
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_LEN 1
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_MAX 1
+#define TFA98XX_GPIO_CONFIG_GPIOCTRL_MSK 0x1
+
+/*
+ * gpio_dir
+ */
+#define TFA98XX_GPIO_CONFIG_GPIOCONF (0xf<<1)
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_POS 1
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_LEN 4
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_MAX 15
+#define TFA98XX_GPIO_CONFIG_GPIOCONF_MSK 0x1e
+
+/*
+ * gpio_dataout
+ */
+#define TFA98XX_GPIO_CONFIG_GPIODOUT (0xf<<5)
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_POS 5
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_LEN 4
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_MAX 15
+#define TFA98XX_GPIO_CONFIG_GPIODOUT_MSK 0x1e0
+
+
+/*
+ * (0x40)-interrupt_out_reg1
+ */
+
+/*
+ * int_out_flag_por
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS (0x1<<0)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_POS 0
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTVDDS_MSK 0x1
+
+/*
+ * int_out_flag_pll_lock
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS (0x1<<1)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_POS 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTPLLS_MSK 0x2
+
+/*
+ * int_out_flag_otpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS (0x1<<2)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_POS 2
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOTDS_MSK 0x4
+
+/*
+ * int_out_flag_ovpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS (0x1<<3)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_POS 3
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTOVDS_MSK 0x8
+
+/*
+ * int_out_flag_uvpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS (0x1<<4)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_POS 4
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTUVDS_MSK 0x10
+
+/*
+ * int_out_flag_clocks_stable
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS (0x1<<5)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_POS 5
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTCLKS_MSK 0x20
+
+/*
+ * int_out_flag_mtp_busy
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB (0x1<<6)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_POS 6
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTMTPB_MSK 0x40
+
+/*
+ * int_out_flag_lost_clk
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK (0x1<<7)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_POS 7
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTNOCLK_MSK 0x80
+
+/*
+ * int_out_flag_cf_speakererror
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS (0x1<<8)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_POS 8
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSPKS_MSK 0x100
+
+/*
+ * int_out_flag_cold_started
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS (0x1<<9)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_POS 9
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTACS_MSK 0x200
+
+/*
+ * int_out_flag_engage
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS (0x1<<10)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_POS 10
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTSWS_MSK 0x400
+
+/*
+ * int_out_flag_watchdog_reset
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS (0x1<<11)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_POS 11
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTWDS_MSK 0x800
+
+/*
+ * int_out_flag_enbl_amp
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS (0x1<<12)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_POS 12
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAMPS_MSK 0x1000
+
+/*
+ * int_out_flag_enbl_ref
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS (0x1<<13)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_POS 13
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTAREFS_MSK 0x2000
+
+/*
+ * int_out_flag_adc10_ready
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR (0x1<<14)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_POS 14
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTADCCR_MSK 0x4000
+
+/*
+ * int_out_flag_bod_vddd_nok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK (0x1<<15)
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_POS 15
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG1_ISTBODNOK_MSK 0x8000
+
+
+/*
+ * (0x41)-interrupt_out_reg2
+ */
+
+/*
+ * int_out_flag_bst_bstcur
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU (0x1<<0)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_POS 0
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTCU_MSK 0x1
+
+/*
+ * int_out_flag_bst_hiz
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI (0x1<<1)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_POS 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTHI_MSK 0x2
+
+/*
+ * int_out_flag_bst_ocpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC (0x1<<2)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_POS 2
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTOC_MSK 0x4
+
+/*
+ * int_out_flag_bst_peakcur
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR (0x1<<3)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_POS 3
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTPKCUR_MSK 0x8
+
+/*
+ * int_out_flag_bst_voutcomp
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC (0x1<<4)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_POS 4
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBSTVC_MSK 0x10
+
+/*
+ * int_out_flag_bst_voutcomp86
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86 (0x1<<5)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_POS 5
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST86_MSK 0x20
+
+/*
+ * int_out_flag_bst_voutcomp93
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93 (0x1<<6)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_POS 6
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTBST93_MSK 0x40
+
+/*
+ * int_out_flag_rcvldop_ready
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD (0x1<<7)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_POS 7
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTRCVLD_MSK 0x80
+
+/*
+ * int_out_flag_ocp_alarm_left
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL (0x1<<8)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_POS 8
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPL_MSK 0x100
+
+/*
+ * int_out_flag_ocp_alarm_right
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR (0x1<<9)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_POS 9
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTOCPR_MSK 0x200
+
+/*
+ * int_out_flag_man_wait_src_settings
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC (0x1<<10)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_POS 10
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSRC_MSK 0x400
+
+/*
+ * int_out_flag_man_wait_cf_config
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC (0x1<<11)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_POS 11
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWCFC_MSK 0x800
+
+/*
+ * int_out_flag_man_start_mute_audio
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU (0x1<<12)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_POS 12
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTMWSMU_MSK 0x1000
+
+/*
+ * int_out_flag_cfma_err
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER (0x1<<13)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_POS 13
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMER_MSK 0x2000
+
+/*
+ * int_out_flag_cfma_ack
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC (0x1<<14)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_POS 14
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCFMAC_MSK 0x4000
+
+/*
+ * int_out_flag_clk_out_of_range
+ */
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR (0x1<<15)
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_POS 15
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG2_ISTCLKOOR_MSK 0x8000
+
+
+/*
+ * (0x42)-interrupt_out_reg3
+ */
+
+/*
+ * int_out_flag_tdm_error
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER (0x1<<0)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_POS 0
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTTDMER_MSK 0x1
+
+/*
+ * int_out_flag_clip_left
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL (0x1<<1)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_POS 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPL_MSK 0x2
+
+/*
+ * int_out_flag_clip_right
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR (0x1<<2)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_POS 2
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTCLPR_MSK 0x4
+
+/*
+ * int_out_flag_mic_ocpok
+ */
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM (0x1<<3)
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_POS 3
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_LEN 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_MAX 1
+#define TFA98XX_INTERRUPT_OUT_REG3_ISTOCPM_MSK 0x8
+
+
+/*
+ * (0x44)-interrupt_in_reg1
+ */
+
+/*
+ * int_in_flag_por
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS (0x1<<0)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_POS 0
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLVDDS_MSK 0x1
+
+/*
+ * int_in_flag_pll_lock
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS (0x1<<1)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_POS 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLPLLS_MSK 0x2
+
+/*
+ * int_in_flag_otpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS (0x1<<2)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_POS 2
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOTDS_MSK 0x4
+
+/*
+ * int_in_flag_ovpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS (0x1<<3)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_POS 3
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLOVDS_MSK 0x8
+
+/*
+ * int_in_flag_uvpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS (0x1<<4)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_POS 4
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLUVDS_MSK 0x10
+
+/*
+ * int_in_flag_clocks_stable
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS (0x1<<5)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_POS 5
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLCLKS_MSK 0x20
+
+/*
+ * int_in_flag_mtp_busy
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB (0x1<<6)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_POS 6
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLMTPB_MSK 0x40
+
+/*
+ * int_in_flag_lost_clk
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK (0x1<<7)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_POS 7
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLNOCLK_MSK 0x80
+
+/*
+ * int_in_flag_cf_speakererror
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS (0x1<<8)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_POS 8
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSPKS_MSK 0x100
+
+/*
+ * int_in_flag_cold_started
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS (0x1<<9)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_POS 9
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLACS_MSK 0x200
+
+/*
+ * int_in_flag_engage
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS (0x1<<10)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_POS 10
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLSWS_MSK 0x400
+
+/*
+ * int_in_flag_watchdog_reset
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS (0x1<<11)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_POS 11
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLWDS_MSK 0x800
+
+/*
+ * int_in_flag_enbl_amp
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS (0x1<<12)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_POS 12
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAMPS_MSK 0x1000
+
+/*
+ * int_in_flag_enbl_ref
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS (0x1<<13)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_POS 13
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLAREFS_MSK 0x2000
+
+/*
+ * int_in_flag_adc10_ready
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR (0x1<<14)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_POS 14
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLADCCR_MSK 0x4000
+
+/*
+ * int_in_flag_bod_vddd_nok
+ */
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK (0x1<<15)
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_POS 15
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG1_ICLBODNOK_MSK 0x8000
+
+
+/*
+ * (0x45)-interrupt_in_reg2
+ */
+
+/*
+ * int_in_flag_bst_bstcur
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU (0x1<<0)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_POS 0
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTCU_MSK 0x1
+
+/*
+ * int_in_flag_bst_hiz
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI (0x1<<1)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_POS 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTHI_MSK 0x2
+
+/*
+ * int_in_flag_bst_ocpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC (0x1<<2)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_POS 2
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTOC_MSK 0x4
+
+/*
+ * int_in_flag_bst_peakcur
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC (0x1<<3)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_POS 3
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTPC_MSK 0x8
+
+/*
+ * int_in_flag_bst_voutcomp
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC (0x1<<4)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_POS 4
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBSTVC_MSK 0x10
+
+/*
+ * int_in_flag_bst_voutcomp86
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86 (0x1<<5)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_POS 5
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST86_MSK 0x20
+
+/*
+ * int_in_flag_bst_voutcomp93
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93 (0x1<<6)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_POS 6
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLBST93_MSK 0x40
+
+/*
+ * int_in_flag_rcvldop_ready
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD (0x1<<7)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_POS 7
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLRCVLD_MSK 0x80
+
+/*
+ * int_in_flag_ocp_alarm_left
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL (0x1<<8)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_POS 8
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPL_MSK 0x100
+
+/*
+ * int_in_flag_ocp_alarm_right
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR (0x1<<9)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_POS 9
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLOCPR_MSK 0x200
+
+/*
+ * int_in_flag_man_wait_src_settings
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC (0x1<<10)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_POS 10
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSRC_MSK 0x400
+
+/*
+ * int_in_flag_man_wait_cf_config
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC (0x1<<11)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_POS 11
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWCFC_MSK 0x800
+
+/*
+ * int_in_flag_man_start_mute_audio
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU (0x1<<12)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_POS 12
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLMWSMU_MSK 0x1000
+
+/*
+ * int_in_flag_cfma_err
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER (0x1<<13)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_POS 13
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMER_MSK 0x2000
+
+/*
+ * int_in_flag_cfma_ack
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC (0x1<<14)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_POS 14
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCFMAC_MSK 0x4000
+
+/*
+ * int_in_flag_clk_out_of_range
+ */
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR (0x1<<15)
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_POS 15
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG2_ICLCLKOOR_MSK 0x8000
+
+
+/*
+ * (0x46)-interrupt_in_reg3
+ */
+
+/*
+ * int_in_flag_tdm_error
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER (0x1<<0)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_POS 0
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLTDMER_MSK 0x1
+
+/*
+ * int_in_flag_clip_left
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL (0x1<<1)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_POS 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPL_MSK 0x2
+
+/*
+ * int_in_flag_clip_right
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR (0x1<<2)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_POS 2
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLCLPR_MSK 0x4
+
+/*
+ * int_in_flag_mic_ocpok
+ */
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM (0x1<<3)
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_POS 3
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_LEN 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_MAX 1
+#define TFA98XX_INTERRUPT_IN_REG3_ICLOCPM_MSK 0x8
+
+
+/*
+ * (0x48)-interrupt_enable_reg1
+ */
+
+/*
+ * int_enable_flag_por
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS (0x1<<0)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_POS 0
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEVDDS_MSK 0x1
+
+/*
+ * int_enable_flag_pll_lock
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS (0x1<<1)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_POS 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEPLLS_MSK 0x2
+
+/*
+ * int_enable_flag_otpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS (0x1<<2)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_POS 2
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOTDS_MSK 0x4
+
+/*
+ * int_enable_flag_ovpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS (0x1<<3)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_POS 3
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEOVDS_MSK 0x8
+
+/*
+ * int_enable_flag_uvpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS (0x1<<4)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_POS 4
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEUVDS_MSK 0x10
+
+/*
+ * int_enable_flag_clocks_stable
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS (0x1<<5)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_POS 5
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IECLKS_MSK 0x20
+
+/*
+ * int_enable_flag_mtp_busy
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB (0x1<<6)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_POS 6
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEMTPB_MSK 0x40
+
+/*
+ * int_enable_flag_lost_clk
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK (0x1<<7)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_POS 7
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IENOCLK_MSK 0x80
+
+/*
+ * int_enable_flag_cf_speakererror
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS (0x1<<8)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_POS 8
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESPKS_MSK 0x100
+
+/*
+ * int_enable_flag_cold_started
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS (0x1<<9)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_POS 9
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEACS_MSK 0x200
+
+/*
+ * int_enable_flag_engage
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS (0x1<<10)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_POS 10
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IESWS_MSK 0x400
+
+/*
+ * int_enable_flag_watchdog_reset
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS (0x1<<11)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_POS 11
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEWDS_MSK 0x800
+
+/*
+ * int_enable_flag_enbl_amp
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS (0x1<<12)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_POS 12
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAMPS_MSK 0x1000
+
+/*
+ * int_enable_flag_enbl_ref
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS (0x1<<13)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_POS 13
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEAREFS_MSK 0x2000
+
+/*
+ * int_enable_flag_adc10_ready
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR (0x1<<14)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_POS 14
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEADCCR_MSK 0x4000
+
+/*
+ * int_enable_flag_bod_vddd_nok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK (0x1<<15)
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_POS 15
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG1_IEBODNOK_MSK 0x8000
+
+
+/*
+ * (0x49)-interrupt_enable_reg2
+ */
+
+/*
+ * int_enable_flag_bst_bstcur
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU (0x1<<0)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_POS 0
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTCU_MSK 0x1
+
+/*
+ * int_enable_flag_bst_hiz
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI (0x1<<1)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_POS 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTHI_MSK 0x2
+
+/*
+ * int_enable_flag_bst_ocpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC (0x1<<2)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_POS 2
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTOC_MSK 0x4
+
+/*
+ * int_enable_flag_bst_peakcur
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC (0x1<<3)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_POS 3
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTPC_MSK 0x8
+
+/*
+ * int_enable_flag_bst_voutcomp
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC (0x1<<4)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_POS 4
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBSTVC_MSK 0x10
+
+/*
+ * int_enable_flag_bst_voutcomp86
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86 (0x1<<5)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_POS 5
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST86_MSK 0x20
+
+/*
+ * int_enable_flag_bst_voutcomp93
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93 (0x1<<6)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_POS 6
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEBST93_MSK 0x40
+
+/*
+ * int_enable_flag_rcvldop_ready
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD (0x1<<7)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_POS 7
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IERCVLD_MSK 0x80
+
+/*
+ * int_enable_flag_ocp_alarm_left
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL (0x1<<8)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_POS 8
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPL_MSK 0x100
+
+/*
+ * int_enable_flag_ocp_alarm_right
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR (0x1<<9)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_POS 9
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEOCPR_MSK 0x200
+
+/*
+ * int_enable_flag_man_wait_src_settings
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC (0x1<<10)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_POS 10
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSRC_MSK 0x400
+
+/*
+ * int_enable_flag_man_wait_cf_config
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC (0x1<<11)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_POS 11
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWCFC_MSK 0x800
+
+/*
+ * int_enable_flag_man_start_mute_audio
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU (0x1<<12)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_POS 12
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IEMWSMU_MSK 0x1000
+
+/*
+ * int_enable_flag_cfma_err
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER (0x1<<13)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_POS 13
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMER_MSK 0x2000
+
+/*
+ * int_enable_flag_cfma_ack
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC (0x1<<14)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_POS 14
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECFMAC_MSK 0x4000
+
+/*
+ * int_enable_flag_clk_out_of_range
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR (0x1<<15)
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_POS 15
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG2_IECLKOOR_MSK 0x8000
+
+
+/*
+ * (0x4a)-interrupt_enable_reg3
+ */
+
+/*
+ * int_enable_flag_tdm_error
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER (0x1<<0)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_POS 0
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IETDMER_MSK 0x1
+
+/*
+ * int_enable_flag_clip_left
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL (0x1<<1)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_POS 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPL_MSK 0x2
+
+/*
+ * int_enable_flag_clip_right
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR (0x1<<2)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_POS 2
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IECLPR_MSK 0x4
+
+/*
+ * int_enable_flag_mic_ocpok
+ */
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1 (0x1<<3)
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_POS 3
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_LEN 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_MAX 1
+#define TFA98XX_INTERRUPT_ENABLE_REG3_IEOCPM1_MSK 0x8
+
+
+/*
+ * (0x4c)-status_polarity_reg1
+ */
+
+/*
+ * int_polarity_flag_por
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS (0x1<<0)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_POS 0
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOVDDS_MSK 0x1
+
+/*
+ * int_polarity_flag_pll_lock
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS (0x1<<1)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_POS 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOPLLS_MSK 0x2
+
+/*
+ * int_polarity_flag_otpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS (0x1<<2)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_POS 2
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOTDS_MSK 0x4
+
+/*
+ * int_polarity_flag_ovpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS (0x1<<3)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_POS 3
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOOVDS_MSK 0x8
+
+/*
+ * int_polarity_flag_uvpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS (0x1<<4)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_POS 4
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOUVDS_MSK 0x10
+
+/*
+ * int_polarity_flag_clocks_stable
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS (0x1<<5)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_POS 5
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOCLKS_MSK 0x20
+
+/*
+ * int_polarity_flag_mtp_busy
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB (0x1<<6)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_POS 6
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOMTPB_MSK 0x40
+
+/*
+ * int_polarity_flag_lost_clk
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK (0x1<<7)
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_POS 7
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPONOCLK_MSK 0x80
+
+/*
+ * int_polarity_flag_cf_speakererror
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS (0x1<<8)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_POS 8
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSPKS_MSK 0x100
+
+/*
+ * int_polarity_flag_cold_started
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS (0x1<<9)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_POS 9
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOACS_MSK 0x200
+
+/*
+ * int_polarity_flag_engage
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS (0x1<<10)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_POS 10
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOSWS_MSK 0x400
+
+/*
+ * int_polarity_flag_watchdog_reset
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS (0x1<<11)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_POS 11
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOWDS_MSK 0x800
+
+/*
+ * int_polarity_flag_enbl_amp
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS (0x1<<12)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_POS 12
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAMPS_MSK 0x1000
+
+/*
+ * int_polarity_flag_enbl_ref
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS (0x1<<13)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_POS 13
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOAREFS_MSK 0x2000
+
+/*
+ * int_polarity_flag_adc10_ready
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR (0x1<<14)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_POS 14
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOADCCR_MSK 0x4000
+
+/*
+ * int_polarity_flag_bod_vddd_nok
+ */
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK (0x1<<15)
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_POS 15
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG1_IPOBODNOK_MSK 0x8000
+
+
+/*
+ * (0x4d)-status_polarity_reg2
+ */
+
+/*
+ * int_polarity_flag_bst_bstcur
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU (0x1<<0)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_POS 0
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTCU_MSK 0x1
+
+/*
+ * int_polarity_flag_bst_hiz
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI (0x1<<1)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_POS 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTHI_MSK 0x2
+
+/*
+ * int_polarity_flag_bst_ocpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC (0x1<<2)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_POS 2
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTOC_MSK 0x4
+
+/*
+ * int_polarity_flag_bst_peakcur
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC (0x1<<3)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_POS 3
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTPC_MSK 0x8
+
+/*
+ * int_polarity_flag_bst_voutcomp
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC (0x1<<4)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_POS 4
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBSTVC_MSK 0x10
+
+/*
+ * int_polarity_flag_bst_voutcomp86
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86 (0x1<<5)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_POS 5
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST86_MSK 0x20
+
+/*
+ * int_polarity_flag_bst_voutcomp93
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93 (0x1<<6)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_POS 6
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOBST93_MSK 0x40
+
+/*
+ * int_polarity_flag_rcvldop_ready
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD (0x1<<7)
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_POS 7
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPORCVLD_MSK 0x80
+
+/*
+ * int_polarity_flag_ocp_alarm_left
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL (0x1<<8)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_POS 8
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPL_MSK 0x100
+
+/*
+ * int_polarity_flag_ocp_alarm_right
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR (0x1<<9)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_POS 9
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOOCPR_MSK 0x200
+
+/*
+ * int_polarity_flag_man_wait_src_settings
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC (0x1<<10)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_POS 10
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSRC_MSK 0x400
+
+/*
+ * int_polarity_flag_man_wait_cf_config
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC (0x1<<11)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_POS 11
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWCFC_MSK 0x800
+
+/*
+ * int_polarity_flag_man_start_mute_audio
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU (0x1<<12)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_POS 12
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOMWSMU_MSK 0x1000
+
+/*
+ * int_polarity_flag_cfma_err
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER (0x1<<13)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_POS 13
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMER_MSK 0x2000
+
+/*
+ * int_polarity_flag_cfma_ack
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC (0x1<<14)
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_POS 14
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPOCFMAC_MSK 0x4000
+
+/*
+ * int_polarity_flag_clk_out_of_range
+ */
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR (0x1<<15)
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_POS 15
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG2_IPCLKOOR_MSK 0x8000
+
+
+/*
+ * (0x4e)-status_polarity_reg3
+ */
+
+/*
+ * int_polarity_flag_tdm_error
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER (0x1<<0)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_POS 0
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOTDMER_MSK 0x1
+
+/*
+ * int_polarity_flag_clip_left
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL (0x1<<1)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_POS 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPL_MSK 0x2
+
+/*
+ * int_polarity_flag_clip_right
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR (0x1<<2)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_POS 2
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOCLPR_MSK 0x4
+
+/*
+ * int_polarity_flag_mic_ocpok
+ */
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM (0x1<<3)
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_POS 3
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_LEN 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_MAX 1
+#define TFA98XX_STATUS_POLARITY_REG3_IPOOCPM_MSK 0x8
+
+
+/*
+ * (0x50)-bat_prot_config
+ */
+
+/*
+ * vbat_prot_attack_time
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR (0x3<<0)
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_POS 0
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_LEN 2
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_MAX 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSCR_MSK 0x3
+
+/*
+ * vbat_prot_thlevel
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSST (0xf<<2)
+#define TFA98XX_BAT_PROT_CONFIG_BSST_POS 2
+#define TFA98XX_BAT_PROT_CONFIG_BSST_LEN 4
+#define TFA98XX_BAT_PROT_CONFIG_BSST_MAX 15
+#define TFA98XX_BAT_PROT_CONFIG_BSST_MSK 0x3c
+
+/*
+ * vbat_prot_max_reduct
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL (0x3<<6)
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_POS 6
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_LEN 2
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_MAX 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSRL_MSK 0xc0
+
+/*
+ * vbat_prot_release_time
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR (0x7<<8)
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_POS 8
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_LEN 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_MAX 7
+#define TFA98XX_BAT_PROT_CONFIG_BSSRR_MSK 0x700
+
+/*
+ * vbat_prot_hysterese
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY (0x3<<11)
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_POS 11
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_LEN 2
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_MAX 3
+#define TFA98XX_BAT_PROT_CONFIG_BSSHY_MSK 0x1800
+
+/*
+ * sel_vbat
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSR (0x1<<14)
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_POS 14
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_LEN 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_MAX 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSR_MSK 0x4000
+
+/*
+ * bypass_clipper
+ */
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY (0x1<<15)
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_POS 15
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_LEN 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_MAX 1
+#define TFA98XX_BAT_PROT_CONFIG_BSSBY_MSK 0x8000
+
+
+/*
+ * (0x51)-audio_control
+ */
+
+/*
+ * batsense_steepness
+ */
+#define TFA98XX_AUDIO_CONTROL_BSSS (0x1<<0)
+#define TFA98XX_AUDIO_CONTROL_BSSS_POS 0
+#define TFA98XX_AUDIO_CONTROL_BSSS_LEN 1
+#define TFA98XX_AUDIO_CONTROL_BSSS_MAX 1
+#define TFA98XX_AUDIO_CONTROL_BSSS_MSK 0x1
+
+/*
+ * soft_mute
+ */
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE (0x1<<1)
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_POS 1
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_LEN 1
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_MAX 1
+#define TFA98XX_AUDIO_CONTROL_INTSMUTE_MSK 0x2
+
+/*
+ * cf_mute_left
+ */
+#define TFA98XX_AUDIO_CONTROL_CFSML (0x1<<2)
+#define TFA98XX_AUDIO_CONTROL_CFSML_POS 2
+#define TFA98XX_AUDIO_CONTROL_CFSML_LEN 1
+#define TFA98XX_AUDIO_CONTROL_CFSML_MAX 1
+#define TFA98XX_AUDIO_CONTROL_CFSML_MSK 0x4
+
+/*
+ * cf_mute_right
+ */
+#define TFA98XX_AUDIO_CONTROL_CFSMR (0x1<<3)
+#define TFA98XX_AUDIO_CONTROL_CFSMR_POS 3
+#define TFA98XX_AUDIO_CONTROL_CFSMR_LEN 1
+#define TFA98XX_AUDIO_CONTROL_CFSMR_MAX 1
+#define TFA98XX_AUDIO_CONTROL_CFSMR_MSK 0x8
+
+/*
+ * bypass_hp_left
+ */
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL (0x1<<4)
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_POS 4
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_LEN 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_MAX 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPL_MSK 0x10
+
+/*
+ * bypass_hp_right
+ */
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR (0x1<<5)
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_POS 5
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_LEN 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_MAX 1
+#define TFA98XX_AUDIO_CONTROL_HPFBYPR_MSK 0x20
+
+/*
+ * enbl_dpsa_left
+ */
+#define TFA98XX_AUDIO_CONTROL_DPSAL (0x1<<6)
+#define TFA98XX_AUDIO_CONTROL_DPSAL_POS 6
+#define TFA98XX_AUDIO_CONTROL_DPSAL_LEN 1
+#define TFA98XX_AUDIO_CONTROL_DPSAL_MAX 1
+#define TFA98XX_AUDIO_CONTROL_DPSAL_MSK 0x40
+
+/*
+ * enbl_dpsa_right
+ */
+#define TFA98XX_AUDIO_CONTROL_DPSAR (0x1<<7)
+#define TFA98XX_AUDIO_CONTROL_DPSAR_POS 7
+#define TFA98XX_AUDIO_CONTROL_DPSAR_LEN 1
+#define TFA98XX_AUDIO_CONTROL_DPSAR_MAX 1
+#define TFA98XX_AUDIO_CONTROL_DPSAR_MSK 0x80
+
+/*
+ * cf_volume
+ */
+#define TFA98XX_AUDIO_CONTROL_VOL (0xff<<8)
+#define TFA98XX_AUDIO_CONTROL_VOL_POS 8
+#define TFA98XX_AUDIO_CONTROL_VOL_LEN 8
+#define TFA98XX_AUDIO_CONTROL_VOL_MAX 255
+#define TFA98XX_AUDIO_CONTROL_VOL_MSK 0xff00
+
+
+/*
+ * (0x52)-amplifier_config
+ */
+
+/*
+ * ctrl_rcv
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV (0x1<<0)
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_POS 0
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_LEN 1
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_MAX 1
+#define TFA98XX_AMPLIFIER_CONFIG_HNDSFRCV_MSK 0x1
+
+/*
+ * ctrl_cc
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL (0x7<<2)
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_POS 2
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_LEN 3
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_MAX 7
+#define TFA98XX_AMPLIFIER_CONFIG_CLIPCTRL_MSK 0x1c
+
+/*
+ * gain
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN (0xff<<5)
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_POS 5
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_LEN 8
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_MAX 255
+#define TFA98XX_AMPLIFIER_CONFIG_AMPGAIN_MSK 0x1fe0
+
+/*
+ * ctrl_slopectrl
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE (0x1<<13)
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_POS 13
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_LEN 1
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_MAX 1
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPEE_MSK 0x2000
+
+/*
+ * ctrl_slope
+ */
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET (0x3<<14)
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_POS 14
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_LEN 2
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_MAX 3
+#define TFA98XX_AMPLIFIER_CONFIG_SLOPESET_MSK 0xc000
+
+
+/*
+ * (0x5a)-audio_control2
+ */
+
+/*
+ * cf_volume_sec
+ */
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC (0xff<<0)
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_POS 0
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_LEN 8
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_MAX 255
+#define TFA98XX_AUDIO_CONTROL2_VOLSEC_MSK 0xff
+
+/*
+ * sw_profile
+ */
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL (0xff<<8)
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_POS 8
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_LEN 8
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_MAX 255
+#define TFA98XX_AUDIO_CONTROL2_SWPROFIL_MSK 0xff00
+
+
+/*
+ * (0x70)-dcdc_control0
+ */
+
+/*
+ * boost_volt
+ */
+#define TFA98XX_DCDC_CONTROL0_DCVO (0x7<<0)
+#define TFA98XX_DCDC_CONTROL0_DCVO_POS 0
+#define TFA98XX_DCDC_CONTROL0_DCVO_LEN 3
+#define TFA98XX_DCDC_CONTROL0_DCVO_MAX 7
+#define TFA98XX_DCDC_CONTROL0_DCVO_MSK 0x7
+
+/*
+ * boost_cur
+ */
+#define TFA98XX_DCDC_CONTROL0_DCMCC (0xf<<3)
+#define TFA98XX_DCDC_CONTROL0_DCMCC_POS 3
+#define TFA98XX_DCDC_CONTROL0_DCMCC_LEN 4
+#define TFA98XX_DCDC_CONTROL0_DCMCC_MAX 15
+#define TFA98XX_DCDC_CONTROL0_DCMCC_MSK 0x78
+
+/*
+ * bst_coil_value
+ */
+#define TFA98XX_DCDC_CONTROL0_DCCV (0x3<<7)
+#define TFA98XX_DCDC_CONTROL0_DCCV_POS 7
+#define TFA98XX_DCDC_CONTROL0_DCCV_LEN 2
+#define TFA98XX_DCDC_CONTROL0_DCCV_MAX 3
+#define TFA98XX_DCDC_CONTROL0_DCCV_MSK 0x180
+
+/*
+ * boost_intel
+ */
+#define TFA98XX_DCDC_CONTROL0_DCIE (0x1<<9)
+#define TFA98XX_DCDC_CONTROL0_DCIE_POS 9
+#define TFA98XX_DCDC_CONTROL0_DCIE_LEN 1
+#define TFA98XX_DCDC_CONTROL0_DCIE_MAX 1
+#define TFA98XX_DCDC_CONTROL0_DCIE_MSK 0x200
+
+/*
+ * boost_speed
+ */
+#define TFA98XX_DCDC_CONTROL0_DCSR (0x1<<10)
+#define TFA98XX_DCDC_CONTROL0_DCSR_POS 10
+#define TFA98XX_DCDC_CONTROL0_DCSR_LEN 1
+#define TFA98XX_DCDC_CONTROL0_DCSR_MAX 1
+#define TFA98XX_DCDC_CONTROL0_DCSR_MSK 0x400
+
+/*
+ * dcdc_synchronisation
+ */
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP (0x7<<11)
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_POS 11
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_LEN 3
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_MAX 7
+#define TFA98XX_DCDC_CONTROL0_DCSYNCP_MSK 0x3800
+
+/*
+ * dcdcoff_mode
+ */
+#define TFA98XX_DCDC_CONTROL0_DCDIS (0x1<<14)
+#define TFA98XX_DCDC_CONTROL0_DCDIS_POS 14
+#define TFA98XX_DCDC_CONTROL0_DCDIS_LEN 1
+#define TFA98XX_DCDC_CONTROL0_DCDIS_MAX 1
+#define TFA98XX_DCDC_CONTROL0_DCDIS_MSK 0x4000
+
+
+/*
+ * (0x90)-cf_controls
+ */
+
+/*
+ * cf_rst_dsp
+ */
+#define TFA98XX_CF_CONTROLS_RST (0x1<<0)
+#define TFA98XX_CF_CONTROLS_RST_POS 0
+#define TFA98XX_CF_CONTROLS_RST_LEN 1
+#define TFA98XX_CF_CONTROLS_RST_MAX 1
+#define TFA98XX_CF_CONTROLS_RST_MSK 0x1
+
+/*
+ * cf_dmem
+ */
+#define TFA98XX_CF_CONTROLS_DMEM (0x3<<1)
+#define TFA98XX_CF_CONTROLS_DMEM_POS 1
+#define TFA98XX_CF_CONTROLS_DMEM_LEN 2
+#define TFA98XX_CF_CONTROLS_DMEM_MAX 3
+#define TFA98XX_CF_CONTROLS_DMEM_MSK 0x6
+
+/*
+ * cf_aif
+ */
+#define TFA98XX_CF_CONTROLS_AIF (0x1<<3)
+#define TFA98XX_CF_CONTROLS_AIF_POS 3
+#define TFA98XX_CF_CONTROLS_AIF_LEN 1
+#define TFA98XX_CF_CONTROLS_AIF_MAX 1
+#define TFA98XX_CF_CONTROLS_AIF_MSK 0x8
+
+/*
+ * cf_int
+ */
+#define TFA98XX_CF_CONTROLS_CFINT (0x1<<4)
+#define TFA98XX_CF_CONTROLS_CFINT_POS 4
+#define TFA98XX_CF_CONTROLS_CFINT_LEN 1
+#define TFA98XX_CF_CONTROLS_CFINT_MAX 1
+#define TFA98XX_CF_CONTROLS_CFINT_MSK 0x10
+
+/*
+ * cf_cgate_off
+ */
+#define TFA98XX_CF_CONTROLS_CFCGATE (0x1<<5)
+#define TFA98XX_CF_CONTROLS_CFCGATE_POS 5
+#define TFA98XX_CF_CONTROLS_CFCGATE_LEN 1
+#define TFA98XX_CF_CONTROLS_CFCGATE_MAX 1
+#define TFA98XX_CF_CONTROLS_CFCGATE_MSK 0x20
+
+/*
+ * cf_req_cmd
+ */
+#define TFA98XX_CF_CONTROLS_REQCMD (0x1<<8)
+#define TFA98XX_CF_CONTROLS_REQCMD_POS 8
+#define TFA98XX_CF_CONTROLS_REQCMD_LEN 1
+#define TFA98XX_CF_CONTROLS_REQCMD_MAX 1
+#define TFA98XX_CF_CONTROLS_REQCMD_MSK 0x100
+
+/*
+ * cf_req_reset
+ */
+#define TFA98XX_CF_CONTROLS_REQRST (0x1<<9)
+#define TFA98XX_CF_CONTROLS_REQRST_POS 9
+#define TFA98XX_CF_CONTROLS_REQRST_LEN 1
+#define TFA98XX_CF_CONTROLS_REQRST_MAX 1
+#define TFA98XX_CF_CONTROLS_REQRST_MSK 0x200
+
+/*
+ * cf_req_mips
+ */
+#define TFA98XX_CF_CONTROLS_REQMIPS (0x1<<10)
+#define TFA98XX_CF_CONTROLS_REQMIPS_POS 10
+#define TFA98XX_CF_CONTROLS_REQMIPS_LEN 1
+#define TFA98XX_CF_CONTROLS_REQMIPS_MAX 1
+#define TFA98XX_CF_CONTROLS_REQMIPS_MSK 0x400
+
+/*
+ * cf_req_mute_ready
+ */
+#define TFA98XX_CF_CONTROLS_REQMUTED (0x1<<11)
+#define TFA98XX_CF_CONTROLS_REQMUTED_POS 11
+#define TFA98XX_CF_CONTROLS_REQMUTED_LEN 1
+#define TFA98XX_CF_CONTROLS_REQMUTED_MAX 1
+#define TFA98XX_CF_CONTROLS_REQMUTED_MSK 0x800
+
+/*
+ * cf_req_volume_ready
+ */
+#define TFA98XX_CF_CONTROLS_REQVOL (0x1<<12)
+#define TFA98XX_CF_CONTROLS_REQVOL_POS 12
+#define TFA98XX_CF_CONTROLS_REQVOL_LEN 1
+#define TFA98XX_CF_CONTROLS_REQVOL_MAX 1
+#define TFA98XX_CF_CONTROLS_REQVOL_MSK 0x1000
+
+/*
+ * cf_req_damage
+ */
+#define TFA98XX_CF_CONTROLS_REQDMG (0x1<<13)
+#define TFA98XX_CF_CONTROLS_REQDMG_POS 13
+#define TFA98XX_CF_CONTROLS_REQDMG_LEN 1
+#define TFA98XX_CF_CONTROLS_REQDMG_MAX 1
+#define TFA98XX_CF_CONTROLS_REQDMG_MSK 0x2000
+
+/*
+ * cf_req_calibrate_ready
+ */
+#define TFA98XX_CF_CONTROLS_REQCAL (0x1<<14)
+#define TFA98XX_CF_CONTROLS_REQCAL_POS 14
+#define TFA98XX_CF_CONTROLS_REQCAL_LEN 1
+#define TFA98XX_CF_CONTROLS_REQCAL_MAX 1
+#define TFA98XX_CF_CONTROLS_REQCAL_MSK 0x4000
+
+/*
+ * cf_req_reserved
+ */
+#define TFA98XX_CF_CONTROLS_REQRSV (0x1<<15)
+#define TFA98XX_CF_CONTROLS_REQRSV_POS 15
+#define TFA98XX_CF_CONTROLS_REQRSV_LEN 1
+#define TFA98XX_CF_CONTROLS_REQRSV_MAX 1
+#define TFA98XX_CF_CONTROLS_REQRSV_MSK 0x8000
+
+
+/*
+ * (0x91)-cf_mad
+ */
+
+/*
+ * cf_madd
+ */
+#define TFA98XX_CF_MAD_MADD (0xffff<<0)
+#define TFA98XX_CF_MAD_MADD_POS 0
+#define TFA98XX_CF_MAD_MADD_LEN 16
+#define TFA98XX_CF_MAD_MADD_MAX 65535
+#define TFA98XX_CF_MAD_MADD_MSK 0xffff
+
+
+/*
+ * (0x92)-cf_mem
+ */
+
+/*
+ * cf_mema
+ */
+#define TFA98XX_CF_MEM_MEMA (0xffff<<0)
+#define TFA98XX_CF_MEM_MEMA_POS 0
+#define TFA98XX_CF_MEM_MEMA_LEN 16
+#define TFA98XX_CF_MEM_MEMA_MAX 65535
+#define TFA98XX_CF_MEM_MEMA_MSK 0xffff
+
+
+/*
+ * (0x93)-cf_status
+ */
+
+/*
+ * cf_err
+ */
+#define TFA98XX_CF_STATUS_ERR (0xff<<0)
+#define TFA98XX_CF_STATUS_ERR_POS 0
+#define TFA98XX_CF_STATUS_ERR_LEN 8
+#define TFA98XX_CF_STATUS_ERR_MAX 255
+#define TFA98XX_CF_STATUS_ERR_MSK 0xff
+
+/*
+ * cf_ack_cmd
+ */
+#define TFA98XX_CF_STATUS_ACKCMD (0x1<<8)
+#define TFA98XX_CF_STATUS_ACKCMD_POS 8
+#define TFA98XX_CF_STATUS_ACKCMD_LEN 1
+#define TFA98XX_CF_STATUS_ACKCMD_MAX 1
+#define TFA98XX_CF_STATUS_ACKCMD_MSK 0x100
+
+/*
+ * cf_ack_reset
+ */
+#define TFA98XX_CF_STATUS_ACKRST (0x1<<9)
+#define TFA98XX_CF_STATUS_ACKRST_POS 9
+#define TFA98XX_CF_STATUS_ACKRST_LEN 1
+#define TFA98XX_CF_STATUS_ACKRST_MAX 1
+#define TFA98XX_CF_STATUS_ACKRST_MSK 0x200
+
+/*
+ * cf_ack_mips
+ */
+#define TFA98XX_CF_STATUS_ACKMIPS (0x1<<10)
+#define TFA98XX_CF_STATUS_ACKMIPS_POS 10
+#define TFA98XX_CF_STATUS_ACKMIPS_LEN 1
+#define TFA98XX_CF_STATUS_ACKMIPS_MAX 1
+#define TFA98XX_CF_STATUS_ACKMIPS_MSK 0x400
+
+/*
+ * cf_ack_mute_ready
+ */
+#define TFA98XX_CF_STATUS_ACKMUTED (0x1<<11)
+#define TFA98XX_CF_STATUS_ACKMUTED_POS 11
+#define TFA98XX_CF_STATUS_ACKMUTED_LEN 1
+#define TFA98XX_CF_STATUS_ACKMUTED_MAX 1
+#define TFA98XX_CF_STATUS_ACKMUTED_MSK 0x800
+
+/*
+ * cf_ack_volume_ready
+ */
+#define TFA98XX_CF_STATUS_ACKVOL (0x1<<12)
+#define TFA98XX_CF_STATUS_ACKVOL_POS 12
+#define TFA98XX_CF_STATUS_ACKVOL_LEN 1
+#define TFA98XX_CF_STATUS_ACKVOL_MAX 1
+#define TFA98XX_CF_STATUS_ACKVOL_MSK 0x1000
+
+/*
+ * cf_ack_damage
+ */
+#define TFA98XX_CF_STATUS_ACKDMG (0x1<<13)
+#define TFA98XX_CF_STATUS_ACKDMG_POS 13
+#define TFA98XX_CF_STATUS_ACKDMG_LEN 1
+#define TFA98XX_CF_STATUS_ACKDMG_MAX 1
+#define TFA98XX_CF_STATUS_ACKDMG_MSK 0x2000
+
+/*
+ * cf_ack_calibrate_ready
+ */
+#define TFA98XX_CF_STATUS_ACKCAL (0x1<<14)
+#define TFA98XX_CF_STATUS_ACKCAL_POS 14
+#define TFA98XX_CF_STATUS_ACKCAL_LEN 1
+#define TFA98XX_CF_STATUS_ACKCAL_MAX 1
+#define TFA98XX_CF_STATUS_ACKCAL_MSK 0x4000
+
+/*
+ * cf_ack_reserved
+ */
+#define TFA98XX_CF_STATUS_ACKRSV (0x1<<15)
+#define TFA98XX_CF_STATUS_ACKRSV_POS 15
+#define TFA98XX_CF_STATUS_ACKRSV_LEN 1
+#define TFA98XX_CF_STATUS_ACKRSV_MAX 1
+#define TFA98XX_CF_STATUS_ACKRSV_MSK 0x8000
+
+
+/*
+ * (0xa1)-mtpkey2_reg
+ */
+
+/*
+ * mtpkey2
+ */
+#define TFA98XX_MTPKEY2_REG_MTPK (0xff<<0)
+#define TFA98XX_MTPKEY2_REG_MTPK_POS 0
+#define TFA98XX_MTPKEY2_REG_MTPK_LEN 8
+#define TFA98XX_MTPKEY2_REG_MTPK_MAX 255
+#define TFA98XX_MTPKEY2_REG_MTPK_MSK 0xff
+
+
+/*
+ * (0xa2)-mtp_status
+ */
+
+/*
+ * key01_locked
+ */
+#define TFA98XX_MTP_STATUS_KEY1LOCKED (0x1<<0)
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_POS 0
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_LEN 1
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_MAX 1
+#define TFA98XX_MTP_STATUS_KEY1LOCKED_MSK 0x1
+
+/*
+ * key02_locked
+ */
+#define TFA98XX_MTP_STATUS_KEY2LOCKED (0x1<<1)
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_POS 1
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_LEN 1
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_MAX 1
+#define TFA98XX_MTP_STATUS_KEY2LOCKED_MSK 0x2
+
+
+/*
+ * (0xa3)-KEY_protected_mtp_control
+ */
+
+/*
+ * auto_copy_iic_to_mtp
+ */
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP (0x1<<6)
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_POS 6
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_LEN 1
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_MAX 1
+#define TFA98XX_KEY_PROTECTED_MTP_CONTROL_CIMTP_MSK 0x40
+
+
+/*
+ * (0xa5)-mtp_data_out_msb
+ */
+
+/*
+ * mtp_man_data_out_msb
+ */
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB (0xffff<<0)
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_POS 0
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_LEN 16
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_MAX 65535
+#define TFA98XX_MTP_DATA_OUT_MSB_MTPRDMSB_MSK 0xffff
+
+
+/*
+ * (0xa6)-mtp_data_out_lsb
+ */
+
+/*
+ * mtp_man_data_out_lsb
+ */
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB (0xffff<<0)
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_POS 0
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_LEN 16
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_MAX 65535
+#define TFA98XX_MTP_DATA_OUT_LSB_MTPRDLSB_MSK 0xffff
+
+
+/*
+ * (0xb1)-temp_sensor_config
+ */
+
+/*
+ * ext_temp
+ */
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS (0x1ff<<0)
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_POS 0
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_LEN 9
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_MAX 511
+#define TFA98XX_TEMP_SENSOR_CONFIG_EXTTS_MSK 0x1ff
+
+/*
+ * ext_temp_sel
+ */
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS (0x1<<9)
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_POS 9
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_LEN 1
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_MAX 1
+#define TFA98XX_TEMP_SENSOR_CONFIG_TROS_MSK 0x200
+
+
+/*
+ * (0xf0)-KEY2_protected_MTP0
+ */
+
+/*
+ * calibration_onetime
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC (0x1<<0)
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_POS 0
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MSK 0x1
+
+/*
+ * calibr_ron_done
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX (0x1<<1)
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_POS 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK 0x2
+
+/*
+ * calibr_dcdc_api_calibrate
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI (0x1<<2)
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_POS 2
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCAPI_MSK 0x4
+
+/*
+ * calibr_dcdc_delta_sign
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB (0x1<<3)
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_POS 3
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_LEN 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_MAX 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_DCMCCSB_MSK 0x8
+
+/*
+ * calibr_dcdc_delta
+ */
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF (0x7<<4)
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_POS 4
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_LEN 3
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_MAX 7
+#define TFA98XX_KEY2_PROTECTED_MTP0_USERDEF_MSK 0x70
+
+
+/*
+ * (0xf4)-KEY1_protected_MTP4
+ */
+
+
+/*
+ * (0xf5)-KEY1_protected_MTP5
+ */
+
+#endif /* TFA98XX_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx_parameters.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_parameters.h
new file mode 100644
index 00000000000..4b5c7bd486a
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_parameters.h
@@ -0,0 +1,736 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*
+ * tfa98xx_parameters.h
+ *
+ * Created on: Jul 22, 2013
+ * Author: NLV02095
+ */
+
+#ifndef TFA98XXPARAMETERS_H_
+#define TFA98XXPARAMETERS_H_
+
+//#include "config.h"
+// workaround for Visual Studio:
+// fatal error C1083: Cannot open include file: 'config.h': No such file or directory
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
+#include "tfa_service.h"
+
+#if (defined(WIN32) || defined(_X64))
+/* These warnings are disabled because it is only given by Windows and there is no easy fix */
+#pragma warning(disable:4200)
+#pragma warning(disable:4214)
+#endif
+
+/*
+ * profiles & volumesteps
+ *
+ */
+#define TFA_MAX_PROFILES (64)
+#define TFA_MAX_VSTEPS (64)
+#define TFA_MAX_VSTEP_MSG_MARKER (100) /* This marker is used to indicate if all msgs need to be written to the device */
+#define TFA_MAX_MSGS (10)
+
+// the pack pragma is required to make that the size in memory
+// matches the actual variable lenghts
+// This is to assure that the binary files can be transported between
+// different platforms.
+#pragma pack (push, 1)
+
+/*
+ * typedef for 24 bit value using 3 bytes
+ */
+typedef struct uint24 {
+ uint8_t b[3];
+} uint24_t;
+/*
+ * the generic header
+ * all char types are in ASCII
+ */
+typedef struct TfaHeader {
+ uint16_t id;
+ char version[2]; // "V_" : V=version, vv=subversion
+ char subversion[2]; // "vv" : vv=subversion
+ uint16_t size; // data size in bytes following CRC
+ uint32_t CRC; // 32-bits CRC for following data
+ char customer[8]; // “name of customer”
+ char application[8]; // “application name”
+ char type[8]; // “application type name”
+} TfaHeader_t;
+
+typedef enum TfaSamplerate {
+ fs_8k, // 8kHz
+ fs_11k025, // 11.025kHz
+ fs_12k, // 12kHz
+ fs_16k, // 16kHz
+ fs_22k05, // 22.05kHz
+ fs_24k, // 24kHz
+ fs_32k, // 32kHz
+ fs_44k1, // 44.1kHz
+ fs_48k, // 48kHz
+ fs_96k, // 96kHz
+ fs_count // Should always be last item.
+} TfaSamplerate_t;
+
+// Keep in sync with TfaSamplerate_t !
+static const int TfaSamplerateHz[fs_count] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000 };
+
+
+/*
+ * coolflux direct memory access
+ */
+typedef struct TfaDspMem {
+ uint8_t type; /* 0--3: p, x, y, iomem */
+ uint16_t address; /* target address */
+ uint8_t size; /* data size in words */
+ int words[]; /* payload in signed 32bit integer (two's complement) */
+} TfaDspMem_t;
+
+/*
+ * the biquad coefficients for the API together with index in filter
+ * the biquad_index is the actual index in the equalizer +1
+ */
+#define BIQUAD_COEFF_SIZE 6
+
+/*
+* Output fixed point coeffs structure
+*/
+typedef struct {
+ int a2;
+ int a1;
+ int b2;
+ int b1;
+ int b0;
+}TfaBiquad_t;
+
+typedef struct TfaBiquadOld {
+ uint8_t bytes[BIQUAD_COEFF_SIZE*sizeof(uint24_t)];
+}TfaBiquadOld_t;
+
+typedef struct TfaBiquadFloat {
+ float headroom;
+ float b0;
+ float b1;
+ float b2;
+ float a1;
+ float a2;
+} TfaBiquadFloat_t;
+
+/*
+* EQ filter definitions
+* Note: This is not in line with smartstudio (JV: 12/12/2016)
+*/
+typedef enum TfaFilterType {
+ fCustom, //User defined biquad coefficients
+ fFlat, //Vary only gain
+ fLowpass, //2nd order Butterworth low pass
+ fHighpass, //2nd order Butterworth high pass
+ fLowshelf,
+ fHighshelf,
+ fNotch,
+ fPeak,
+ fBandpass,
+ f1stLP,
+ f1stHP,
+ fElliptic
+} TfaFilterType_t;
+
+/*
+ * filter parameters for biquad (re-)calculation
+ */
+typedef struct TfaFilter {
+ TfaBiquadOld_t biquad;
+ uint8_t enabled;
+ uint8_t type; // (== enum FilterTypes, assure 8bits length)
+ float frequency;
+ float Q;
+ float gain;
+} TfaFilter_t ; //8 * float + int32 + byte == 37
+
+/*
+ * biquad params for calculation
+*/
+
+#define TFA_BQ_EQ_INDEX 0
+#define TFA_BQ_ANTI_ALIAS_INDEX 10
+#define TFA_BQ_INTEGRATOR_INDEX 13
+
+/*
+* Loudspeaker Compensation filter definitions
+*/
+typedef struct TfaLsCompensationFilter {
+ TfaBiquad_t biquad;
+ uint8_t lsCompOn; // Loudspeaker compensation on/off; when 'off', the DSP code doesn't apply the bwExt => bwExtOn GUI flag should be gray to avoid confusion
+ uint8_t bwExtOn; // Bandwidth extension on/off
+ float fRes; // [Hz] speaker resonance frequency
+ float Qt; // Speaker resonance Q-factor
+ float fBwExt; // [Hz] Band width extension frequency
+ float samplingFreq;// [Hz] Sampling frequency
+} TfaLsCompensationFilter_t;
+
+/*
+* Anti Aliasing Elliptic filter definitions
+*/
+typedef struct TfaAntiAliasFilter {
+ TfaBiquad_t biquad; /**< Output results fixed point coeffs */
+ uint8_t enabled;
+ float cutOffFreq; // cut off frequency
+ float samplingFreq; // sampling frequency
+ float rippleDb; // range: [0.1 3.0]
+ float rolloff; // range: [-1.0 1.0]
+} TfaAntiAliasFilter_t;
+
+/**
+* Integrator filter input definitions
+*/
+typedef struct TfaIntegratorFilter {
+ TfaBiquad_t biquad; /**< Output results fixed point coeffs */
+ uint8_t type; /**< Butterworth filter type: high or low pass */
+ float cutOffFreq; /**< cut off frequency in Hertz; range: [100.0 4000.0] */
+ float samplingFreq; /**< sampling frequency in Hertz */
+ float leakage; /**< leakage factor; range [0.0 1.0] */
+} TfaIntegratorFilter_t;
+
+
+typedef struct TfaEqFilter {
+ TfaBiquad_t biquad;
+ uint8_t enabled;
+ uint8_t type; // (== enum FilterTypes, assure 8bits length)
+ float cutOffFreq; // cut off frequency, // range: [100.0 4000.0]
+ float samplingFreq; // sampling frequency
+ float Q; // range: [0.5 5.0]
+ float gainDb; // range: [-10.0 10.0]
+} TfaEqFilter_t ; //8 * float + int32 + byte == 37
+
+typedef struct TfaContAntiAlias {
+ int8_t index; /**< index determines destination type; anti-alias, integrator,eq */
+ uint8_t type;
+ float cutOffFreq; // cut off frequency
+ float samplingFreq;
+ float rippleDb; // integrator leakage
+ float rolloff;
+ uint8_t bytes[5*3]; // payload 5*24buts coeffs
+}TfaContAntiAlias_t;
+
+typedef struct TfaContIntegrator {
+ int8_t index; /**< index determines destination type; anti-alias, integrator,eq */
+ uint8_t type;
+ float cutOffFreq; // cut off frequency
+ float samplingFreq;
+ float leakage; // integrator leakage
+ float reserved;
+ uint8_t bytes[5*3]; // payload 5*24buts coeffs
+}TfaContIntegrator_t;
+
+typedef struct TfaContEq {
+ int8_t index;
+ uint8_t type; // (== enum FilterTypes, assure 8bits length)
+ float cutOffFreq; // cut off frequency, // range: [100.0 4000.0]
+ float samplingFreq; // sampling frequency
+ float Q; // range: [0.5 5.0]
+ float gainDb; // range: [-10.0 10.0]
+ uint8_t bytes[5*3]; // payload 5*24buts coeffs
+} TfaContEq_t ; //8 * float + int32 + byte == 37
+
+typedef union TfaContBiquad {
+ TfaContEq_t eq;
+ TfaContAntiAlias_t aa;
+ TfaContIntegrator_t in;
+}TfaContBiquad_t;
+
+#define TFA_BQ_EQ_INDEX 0
+#define TFA_BQ_ANTI_ALIAS_INDEX 10
+#define TFA_BQ_INTEGRATOR_INDEX 13
+#define TFA98XX_MAX_EQ 10
+
+typedef struct TfaEqualizer {
+ TfaFilter_t filter[TFA98XX_MAX_EQ];
+} TfaEqualizer_t;
+
+/*
+ * files
+ */
+#define HDR(c1,c2) (c2<<8|c1) // little endian
+typedef enum TfaHeaderType {
+ paramsHdr = HDR('P','M'), /* containter file */
+ volstepHdr = HDR('V','P'),
+ patchHdr = HDR('P','A'),
+ speakerHdr = HDR('S','P'),
+ presetHdr = HDR('P','R'),
+ configHdr = HDR('C','O'),
+ equalizerHdr = HDR('E','Q'),
+ drcHdr = HDR('D','R'),
+ msgHdr = HDR('M','G'), /* generic message */
+ infoHdr = HDR('I','N')
+} TfaHeaderType_t;
+
+/*
+ * equalizer file
+ */
+#define TFA_EQ_VERSION '1'
+#define TFA_EQ_SUBVERSION "00"
+typedef struct TfaEqualizerFile {
+ TfaHeader_t hdr;
+ uint8_t samplerate; // ==enum samplerates, assure 8 bits
+ TfaFilter_t filter[TFA98XX_MAX_EQ];// note: API index counts from 1..10
+} TfaEqualizerFile_t;
+
+/*
+ * patch file
+ */
+#define TFA_PA_VERSION '1'
+#define TFA_PA_SUBVERSION "00"
+typedef struct TfaPatchFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaPatch_t;
+
+/*
+ * generic message file
+ * - the payload of this file includes the opcode and is send straight to the DSP
+ */
+#define TFA_MG_VERSION '3'
+#define TFA_MG_SUBVERSION "00"
+typedef struct TfaMsgFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaMsgFile_t;
+
+/*
+ * NOTE the tfa98xx API defines the enum Tfa98xx_config_type that defines
+ * the subtypes as decribes below.
+ * tfa98xx_dsp_config_parameter_type() can be used to get the
+ * supported type for the active device..
+ */
+/*
+ * config file V1 sub 1
+ */
+#define TFA_CO_VERSION '1'
+#define TFA_CO3_VERSION '3'
+#define TFA_CO_SUBVERSION1 "01"
+typedef struct TfaConfigS1File {
+ TfaHeader_t hdr;
+ uint8_t data[55*3];
+} TfaConfigS1_t;
+
+/*
+ * config file V1 sub 2
+ */
+#define TFA_CO_SUBVERSION2 "02"
+typedef struct TfaConfigS2File {
+ TfaHeader_t hdr;
+ uint8_t data[67*3];
+} TfaConfigS2_t;
+
+/*
+ * config file V1 sub 3
+ */
+#define TFA_CO_SUBVERSION3 "03"
+typedef struct TfaConfigS3File {
+ TfaHeader_t hdr;
+ uint8_t data[67*3];
+} TfaConfigS3_t;
+
+/*
+ * config file V1.0
+ */
+#define TFA_CO_SUBVERSION "00"
+typedef struct TfaConfigFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaConfig_t;
+
+/*
+ * preset file
+ */
+#define TFA_PR_VERSION '1'
+#define TFA_PR_SUBVERSION "00"
+typedef struct TfaPresetFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaPreset_t;
+
+/*
+ * drc file
+ */
+#define TFA_DR_VERSION '1'
+#define TFA_DR_SUBVERSION "00"
+typedef struct TfaDrcFile {
+ TfaHeader_t hdr;
+ uint8_t data[];
+} TfaDrc_t;
+
+/*
+ * drc file
+ * for tfa 2 there is also a xml-version
+ */
+#define TFA_DR3_VERSION '3'
+#define TFA_DR3_SUBVERSION "00"
+typedef struct TfaDrcFile2 {
+ TfaHeader_t hdr;
+ uint8_t version[3];
+ uint8_t data[];
+} TfaDrc2_t;
+
+/*
+ * volume step structures
+ */
+// VP01
+#define TFA_VP1_VERSION '1'
+#define TFA_VP1_SUBVERSION "01"
+typedef struct TfaVolumeStep1 {
+ float attenuation; // IEEE single float
+ uint8_t preset[TFA98XX_PRESET_LENGTH];
+} TfaVolumeStep1_t;
+
+// VP02
+#define TFA_VP2_VERSION '2'
+#define TFA_VP2_SUBVERSION "01"
+typedef struct TfaVolumeStep2 {
+ float attenuation; // IEEE single float
+ uint8_t preset[TFA98XX_PRESET_LENGTH];
+ TfaFilter_t filter[TFA98XX_MAX_EQ];// note: API index counts from 1..10
+} TfaVolumeStep2_t;
+
+/*
+ * volumestep file
+ */
+#define TFA_VP_VERSION '1'
+#define TFA_VP_SUBVERSION "00"
+typedef struct TfaVolumeStepFile {
+ TfaHeader_t hdr;
+ uint8_t vsteps; // can also be calulated from size+type
+ uint8_t samplerate; // ==enum samplerates, assure 8 bits
+ uint8_t payload; //start of variable length contents:N times volsteps
+}TfaVolumeStepFile_t;
+/*
+ * volumestep2 file
+ */
+typedef struct TfaVolumeStep2File {
+ TfaHeader_t hdr;
+ uint8_t vsteps; // can also be calulated from size+type
+ uint8_t samplerate; // ==enum samplerates, assure 8 bits
+ TfaVolumeStep2_t vstep[]; //start of variable length contents:N times volsteps
+}TfaVolumeStep2File_t;
+
+/*
+ * volumestepMax2 file
+ */
+typedef struct TfaVolumeStepMax2File {
+ TfaHeader_t hdr;
+ uint8_t version[3];
+ uint8_t NrOfVsteps;
+ uint8_t vstepsBin[];
+}TfaVolumeStepMax2File_t;
+
+/*
+ * volumestepMax2 file
+ * This volumestep should ONLY be used for the use of bin2hdr!
+ * This can only be used to find the messagetype of the vstep (without header)
+ */
+typedef struct TfaVolumeStepMax2_1File {
+ uint8_t version[3];
+ uint8_t NrOfVsteps;
+ uint8_t vstepsBin[];
+}TfaVolumeStepMax2_1File_t;
+
+struct TfaVolumeStepRegisterInfo {
+ uint8_t NrOfRegisters;
+ uint16_t registerInfo[];
+};
+
+struct TfaVolumeStepMessageInfo {
+ uint8_t NrOfMessages;
+ uint8_t MessageType;
+ uint24_t MessageLength;
+ uint8_t CmdId[3];
+ uint8_t ParameterData[];
+};
+/**************************old v2 *************************************************/
+
+/*
+ * subv 00 volumestep file
+ */
+typedef struct TfaOldHeader {
+ uint16_t id;
+ char version[2]; // "V_" : V=version, vv=subversion
+ char subversion[2]; // "vv" : vv=subversion
+ uint16_t size; // data size in bytes following CRC
+ uint32_t CRC; // 32-bits CRC for following data
+} TfaOldHeader_t;
+
+typedef struct TfaOldFilter {
+ double bq[5];
+ int32_t type;
+ double frequency;
+ double Q;
+ double gain;
+ uint8_t enabled;
+} TfaOldFilter_t ;
+
+typedef struct TfaOldVolumeStep2 {
+ float attenuation; // IEEE single float
+ uint8_t preset[TFA98XX_PRESET_LENGTH];
+ TfaOldFilter_t eq[10];
+} TfaOldVolumeStep2_t;
+
+typedef struct TfaOldVolumeStepFile {
+ TfaOldHeader_t hdr;
+ TfaOldVolumeStep2_t step[];
+}TfaOldVolumeStep2File_t;
+/**************************end old v2 *************************************************/
+
+/*
+ * speaker file header
+ */
+struct TfaSpkHeader {
+ struct TfaHeader hdr;
+ char name[8]; // speaker nick name (e.g. “dumbo”)
+ char vendor[16];
+ char type[8];
+ // dimensions (mm)
+ uint8_t height;
+ uint8_t width;
+ uint8_t depth;
+ uint16_t ohm;
+};
+
+/*
+ * speaker file
+ */
+#define TFA_SP_VERSION '1'
+#define TFA_SP_SUBVERSION "00"
+typedef struct TfaSpeakerFile {
+ TfaHeader_t hdr;
+ char name[8]; // speaker nick name (e.g. “dumbo”)
+ char vendor[16];
+ char type[8];
+ // dimensions (mm)
+ uint8_t height;
+ uint8_t width;
+ uint8_t depth;
+ uint8_t ohm_primary;
+ uint8_t ohm_secondary;
+ uint8_t data[]; //payload TFA98XX_SPEAKERPARAMETER_LENGTH
+} TfaSpeakerFile_t;
+
+#define TFA_VP3_VERSION '3'
+#define TFA_VP3_SUBVERSION "00"
+
+struct TfaFWVer {
+ uint8_t Major;
+ uint8_t minor;
+ uint8_t minor_update:6;
+ uint8_t Update:2;
+};
+
+struct TfaFWMsg {
+ struct TfaFWVer fwVersion;
+ struct TfaMsg payload;
+};
+
+typedef struct TfaLiveData {
+ char name[25];
+ char addrs[25];
+ int tracker;
+ int scalefactor;
+} TfaLiveData_t;
+
+#define TFA_SP3_VERSION '3'
+#define TFA_SP3_SUBVERSION "00"
+struct TfaSpeakerFileMax2 {
+ TfaHeader_t hdr;
+ char name[8]; // speaker nick name (e.g. “dumbo”)
+ char vendor[16];
+ char type[8];
+ // dimensions (mm)
+ uint8_t height;
+ uint8_t width;
+ uint8_t depth;
+ uint8_t ohm_primary;
+ uint8_t ohm_secondary;
+ struct TfaFWMsg FWmsg; //payload including FW ver and Cmd ID
+};
+
+/*
+ * parameter container file
+ */
+/*
+ * descriptors
+ * Note 1: append new DescriptorType at the end
+ * Note 2: add new descriptors to dsc_name[] in tfaContUtil.c
+ */
+typedef enum TfaDescriptorType {
+ dscDevice, // device list
+ dscProfile, // profile list
+ dscRegister, // register patch
+ dscString, // ascii, zero terminated string
+ dscFile, // filename + file contents
+ dscPatch, // patch file
+ dscMarker, // marker to indicate end of a list
+ dscMode,
+ dscSetInputSelect,
+ dscSetOutputSelect,
+ dscSetProgramConfig,
+ dscSetLagW,
+ dscSetGains,
+ dscSetvBatFactors,
+ dscSetSensesCal,
+ dscSetSensesDelay,
+ dscBitfield,
+ dscDefault, // used to reset bitfields to there default values
+ dscLiveData,
+ dscLiveDataString,
+ dscGroup,
+ dscCmd,
+ dscSetMBDrc,
+ dscFilter,
+ dscNoInit,
+ dscFeatures,
+ dscCfMem, // coolflux memory x,y,io
+ dscSetFwkUseCase,
+ dscSetVddpConfig,
+ dsc_last // trailer
+} TfaDescriptorType_t;
+
+#define TFA_BITFIELDDSCMSK 0x7fffffff
+typedef struct TfaDescPtr {
+ uint32_t offset:24;
+ uint32_t type:8; // (== enum TfaDescriptorType, assure 8bits length)
+}TfaDescPtr_t;
+
+/*
+ * generic file descriptor
+ */
+typedef struct TfaFileDsc {
+ TfaDescPtr_t name;
+ uint32_t size; // file data length in bytes
+ uint8_t data[]; //payload
+} TfaFileDsc_t;
+
+
+/*
+ * device descriptor list
+ */
+typedef struct TfaDeviceList {
+ uint8_t length; // nr of items in the list
+ uint8_t bus; // bus
+ uint8_t dev; // device
+ uint8_t func; // subfunction or subdevice
+ uint32_t devid; // device hw fw id
+ TfaDescPtr_t name; // device name
+ TfaDescPtr_t list[]; // items list
+} TfaDeviceList_t;
+
+/*
+ * profile descriptor list
+ */
+typedef struct TfaProfileList {
+ uint32_t length:8; // nr of items in the list + name
+ uint32_t group:8; // profile group number
+ uint32_t ID:16; // profile ID
+ TfaDescPtr_t name; // profile name
+ TfaDescPtr_t list[]; // items list (lenght-1 items)
+} TfaProfileList_t;
+#define TFA_PROFID 0x1234
+
+/*
+ * livedata descriptor list
+ */
+typedef struct TfaLiveDataList {
+ uint32_t length:8; // nr of items in the list
+ uint32_t ID:24; // profile ID
+ TfaDescPtr_t name; // livedata name
+ TfaDescPtr_t list[]; // items list
+} TfaLiveDataList_t;
+#define TFA_LIVEDATAID 0x5678
+
+/*
+ * Bitfield descriptor
+ */
+typedef struct TfaBitfield {
+ uint16_t value;
+ uint16_t field; // ==datasheet defined, 16 bits
+} TfaBitfield_t;
+
+/*
+ * Bitfield enumuration bits descriptor
+ */
+typedef struct TfaBfEnum {
+ unsigned int len:4; // this is the actual length-1
+ unsigned int pos:4;
+ unsigned int address:8;
+} TfaBfEnum_t;
+
+/*
+ * Register patch descriptor
+ */
+typedef struct TfaRegpatch {
+ uint8_t address; // register address
+ uint16_t value; // value to write
+ uint16_t mask; // mask of bits to write
+} TfaRegpatch_t;
+
+/*
+ * Mode descriptor
+ */
+typedef struct TfaUseCase {
+ int value; // mode value, maps to enum Tfa98xx_Mode
+} TfaMode_t;
+
+/*
+ * NoInit descriptor
+ */
+typedef struct TfaNoInit {
+ uint8_t value; // noInit value
+} TfaNoInit_t;
+
+/*
+ * Features descriptor
+ */
+typedef struct TfaFeatures {
+ uint16_t value[3]; // features value
+} TfaFeatures_t;
+
+
+/*
+ * the container file
+ * - the size field is 32bits long (generic=16)
+ * - all char types are in ASCII
+ */
+#define TFA_PM_VERSION '1'
+#define TFA_PM3_VERSION '3'
+#define TFA_PM_SUBVERSION '1'
+typedef struct TfaContainer {
+ char id[2]; // "XX" : XX=type
+ char version[2]; // "V_" : V=version, vv=subversion
+ char subversion[2]; // "vv" : vv=subversion
+ uint32_t size; // data size in bytes following CRC
+ uint32_t CRC; // 32-bits CRC for following data
+ uint16_t rev; // "extra chars for rev nr"
+ char customer[8]; // “name of customer”
+ char application[8]; // “application name”
+ char type[8]; // “application type name”
+ uint16_t ndev; // "nr of device lists"
+ uint16_t nprof; // "nr of profile lists"
+ uint16_t nliveData; // "nr of livedata lists"
+ TfaDescPtr_t index[]; // start of item index table
+} TfaContainer_t;
+
+#pragma pack (pop)
+
+#endif /* TFA98XXPARAMETERS_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa98xx_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_tfafieldnames.h
new file mode 100644
index 00000000000..d5b397bf0c4
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa98xx_tfafieldnames.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+typedef struct TfaBfName {
+ unsigned short bfEnum;
+ char *bfName;
+} tfaBfName_t;
+
+typedef struct TfaIrqName {
+ unsigned short irqEnum;
+ char *irqName;
+} tfaIrqName_t;
+
+#include "tfa1_tfafieldnames.h"
+#include "tfa2_tfafieldnames_N1C.h"
+/* diffs for specific devices */
+#include "tfa9887_tfafieldnames.h"
+#include "tfa9890_tfafieldnames.h"
+#include "tfa9891_tfafieldnames.h"
+#include "tfa9872_tfafieldnames.h"
+#include "tfa9912_tfafieldnames.h"
+#include "tfa9896_tfafieldnames.h"
+#include "tfa9873_tfafieldnames.h"
+#include "tfa9873_tfafieldnames_B0.h"
+#include "tfa9874_tfafieldnames.h"
+#include "tfa9878_tfafieldnames.h"
+#include "tfa9894_tfafieldnames.h"
+#include "tfa9894_tfafieldnames_N2.h"
+#include "tfa9875_tfafieldnames.h"
+#include "tfa9875_tfafieldnames_A1.h"
+
+/* missing 'common' defs break the build but unused in TFA1 context */
+#define TFA1_BF_AMPINSEL -1
+#define TFA1_BF_MANSCONF -1
+#define TFA1_BF_MANCOLD -1
+#define TFA1_BF_INTSMUTE -1
+#define TFA1_BF_CFSMR -1
+#define TFA1_BF_CFSML -1
+#define TFA1_BF_DCMCCAPI -1
+#define TFA1_BF_DCMCCSB -1
+#define TFA1_BF_USERDEF -1
+#define TFA1_BF_MANSTATE -1
+#define TFA1_BF_MANOPER -1
+#define TFA1_BF_REFCKSEL -1
+#define TFA1_BF_VOLSEC -1
+#define TFA1_BF_FRACTDEL -1
+#define TFA1_BF_ACKDMG -1
+#define TFA1_BF_SSRIGHTE -1
+#define TFA1_BF_SSLEFTE -1
+#define TFA1_BF_R25CL -1
+#define TFA1_BF_R25CR -1
+#define TFA1_BF_SWPROFIL 0x8045 /*!< profile save */
+#define TFA1_BF_SWVSTEP 0x80a5 /*!< vstep save */
+
+/* missing 'common' defs break the build */
+#define TFA2_BF_CFSM -1
+
+
+/* MTP access uses registers
+ * defs are derived from corresponding bitfield names as used in the BF macros
+ */
+#define MTPKEY2 MTPK /* unlock key2 MTPK */
+#define MTP0 MTPOTC /* MTP data */
+#define MTP_CONTROL CIMTP /* copy i2c to mtp */
+
+/* interrupt enable register uses HW name in TFA2 */
+#define TFA2_BF_INTENVDDS TFA2_BF_IEVDDS
+
+
+/* TFA9891 specific bit field names */
+#define TFA1_BF_SAAMGAIN 0x2202
+#define TFA2_BF_SAAMGAIN -1
+
+/* TFA9872 specific bit field names */
+#define TFA2_BF_IELP0 TFA9872_BF_IELP0
+#define TFA2_BF_ISTLP0 TFA9872_BF_ISTLP0
+#define TFA2_BF_IPOLP0 TFA9872_BF_IPOLP0
+#define TFA2_BF_IELP1 TFA9872_BF_IELP1
+#define TFA2_BF_ISTLP1 TFA9872_BF_ISTLP1
+#define TFA2_BF_IPOLP1 TFA9872_BF_IPOLP1
+#define TFA2_BF_LP0 TFA9872_BF_LP0
+#define TFA2_BF_LP1 TFA9872_BF_LP1
+#define TFA2_BF_R25C TFA9872_BF_R25C
+#define TFA2_BF_SAMMODE TFA9872_BF_SAMMODE
+
+/* interrupt bit field names of TFA2 and TFA1 do not match */
+#define TFA1_BF_IEACS TFA1_BF_INTENACS
+#define TFA1_BF_IPOACS TFA1_BF_INTPOLACS
+#define TFA1_BF_ISTACS TFA1_BF_INTOACS
+#define TFA1_BF_ISTVDDS TFA1_BF_INTOVDDS
+#define TFA1_BF_ICLVDDS TFA1_BF_INTIVDDS
+#define TFA1_BF_IPOVDDS TFA1_BF_INTPOLVDDS
+#define TFA1_BF_IENOCLK TFA1_BF_INTENNOCLK
+#define TFA1_BF_ISTNOCLK TFA1_BF_INTONOCLK
+#define TFA1_BF_IPONOCLK TFA1_BF_INTPOLNOCLK
+
+/* interrupt bit fields not available on TFA1 */
+#define TFA1_BF_IECLKOOR -1
+#define TFA1_BF_ISTCLKOOR -1
+#define TFA1_BF_IEMWSRC -1
+#define TFA1_BF_ISTMWSRC -1
+#define TFA1_BF_IPOMWSRC -1
+#define TFA1_BF_IEMWSMU -1
+#define TFA1_BF_ISTMWSMU -1
+#define TFA1_BF_IPOMWSMU -1
+#define TFA1_BF_IEMWCFC -1
+#define TFA1_BF_ISTMWCFC -1
+#define TFA1_BF_IPOMWCFC -1
+#define TFA1_BF_CLKOOR -1
+#define TFA1_BF_MANWAIT1 -1
+#define TFA1_BF_MANWAIT2 -1
+#define TFA1_BF_MANMUTE -1
+#define TFA1_BF_IPCLKOOR -1
+#define TFA1_BF_ICLCLKOOR -1
+#define TFA1_BF_IPOSWS -1
+#define TFA1_BF_IESWS -1
+#define TFA1_BF_ISTSWS -1
+#define TFA1_BF_IESPKS -1
+#define TFA1_BF_ISTSPKS -1
+#define TFA1_BF_IPOSPKS -1
+#define TFA1_BF_IECLKS -1
+#define TFA1_BF_ISTCLKS -1
+#define TFA1_BF_IPOCLKS -1
+#define TFA1_BF_IEAMPS -1
+#define TFA1_BF_ISTAMPS -1
+#define TFA1_BF_IPOAMPS -1
+#define TFA1_BF_IELP0 -1
+#define TFA1_BF_ISTLP0 -1
+#define TFA1_BF_IPOLP0 -1
+#define TFA1_BF_IELP1 -1
+#define TFA1_BF_ISTLP1 -1
+#define TFA1_BF_IPOLP1 -1
+#define TFA1_BF_LP0 -1
+#define TFA1_BF_LP1 -1
+#define TFA1_BF_R25C -1
+#define TFA1_BF_SAMMODE -1
+
+/* TDM STATUS fields not available on TFA1 */
+#define TFA1_BF_TDMLUTER -1
+#define TFA1_BF_TDMERR -1
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9912_device_genregs.h b/sound/soc/codecs/tfa98xx-downstream/tfa9912_device_genregs.h
new file mode 100644
index 00000000000..99bd0de5730
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9912_device_genregs.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9912_device_genregs.h
+ * This file was generated automatically on 04/19/17 at 12:26:46.
+ * Source file: TFA9912_N1A_I2C_regmap_V1.39.xlsx
+ */
+
+#ifndef _TFA9912_DEVICE_GENREGS_H
+#define _TFA9912_DEVICE_GENREGS_H
+
+
+#define TFA99XX_SYS_CONTROL0 0x00
+#define TFA99XX_SYS_CONTROL1 0x01
+#define TFA99XX_SYS_CONTROL2 0x02
+#define TFA99XX_DEVICE_REVISION 0x03
+#define TFA99XX_CLOCK_CONTROL 0x04
+#define TFA99XX_CLOCK_GATING_CONTROL 0x05
+#define TFA99XX_HW_PATH_CFG 0x06
+#define TFA99XX_CLKCHK_TH 0x07
+#define TFA99XX_AMP_CTRL 0x08
+#define TFA99XX_SIDE_TONE_CONFIG 0x0d
+#define TFA99XX_CTRL_DIGTOANA_REG 0x0e
+#define TFA99XX_STATUS_FLAGS0 0x10
+#define TFA99XX_STATUS_FLAGS1 0x11
+#define TFA99XX_STATUS_FLAGS3 0x13
+#define TFA99XX_STATUS_FLAGS4 0x14
+#define TFA99XX_BATTERY_VOLTAGE 0x15
+#define TFA99XX_TEMPERATURE 0x16
+#define TFA99XX_VDDP_VOLTAGE 0x17
+#define TFA99XX_TDM_CONFIG0 0x20
+#define TFA99XX_TDM_CONFIG1 0x21
+#define TFA99XX_TDM_CONFIG2 0x22
+#define TFA99XX_TDM_CONFIG3 0x23
+#define TFA99XX_TDM_CONFIG4 0x24
+#define TFA99XX_TDM_CONFIG5 0x25
+#define TFA99XX_TDM_CONFIG6 0x26
+#define TFA99XX_TDM_CONFIG7 0x27
+#define TFA99XX_TDM_CONFIG8 0x28
+#define TFA99XX_TDM_CONFIG9 0x29
+#define TFA99XX_PDM_CONFIG0 0x31
+#define TFA99XX_PDM_CONFIG1 0x32
+#define TFA99XX_INTERRUPT_OUT_REG1 0x40
+#define TFA99XX_INTERRUPT_OUT_REG2 0x41
+#define TFA99XX_INTERRUPT_OUT_REG3 0x42
+#define TFA99XX_INTERRUPT_IN_REG1 0x44
+#define TFA99XX_INTERRUPT_IN_REG2 0x45
+#define TFA99XX_INTERRUPT_IN_REG3 0x46
+#define TFA99XX_INTERRUPT_ENABLE_REG1 0x48
+#define TFA99XX_INTERRUPT_ENABLE_REG2 0x49
+#define TFA99XX_INTERRUPT_ENABLE_REG3 0x4a
+#define TFA99XX_STATUS_POLARITY_REG1 0x4c
+#define TFA99XX_STATUS_POLARITY_REG2 0x4d
+#define TFA99XX_STATUS_POLARITY_REG3 0x4e
+#define TFA99XX_BAT_PROT_CONFIG 0x50
+#define TFA99XX_AUDIO_CONTROL 0x51
+#define TFA99XX_AMPLIFIER_CONFIG 0x52
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL0 0x53
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL1 0x54
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL2 0x55
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL4 0x57
+#define TFA99XX_KEY1_PROTECTED_PWM_CONFIG 0x58
+#define TFA99XX_CF_TAP_STATUS_0 0x5c
+#define TFA99XX_CF_TAP_STATUS_1 0x5d
+#define TFA99XX_TAP_CONTROL 0x5f
+#define TFA99XX_PGA_CONTROL0 0x60
+#define TFA99XX_GAIN_ATT 0x61
+#define TFA99XX_LOW_NOISE_GAIN1 0x62
+#define TFA99XX_LOW_NOISE_GAIN2 0x63
+#define TFA99XX_MODE1_DETECTOR1 0x64
+#define TFA99XX_MODE1_DETECTOR2 0x65
+#define TFA99XX_BST_PFM_CTRL 0x66
+#define TFA99XX_LOW_POWER_CTRL 0x67
+#define TFA99XX_TDM_SOURCE_CTRL 0x68
+#define TFA99XX_SAM_CTRL 0x69
+#define TFA99XX_RST_MIN_VBAT_CTRL 0x6a
+#define TFA99XX_SYS_CONTROL3 0x6b
+#define TFA99XX_STATUS_FLAGS5 0x6e
+#define TFA99XX_DCDC_CONTROL0 0x70
+#define TFA99XX_KEY1_PROTECTED_DCDC_CONTROL3 0x73
+#define TFA99XX_DCDC_CONTROL4 0x74
+#define TFA99XX_DCDC_CONTROL5 0x75
+#define TFA99XX_DCDC_CONTROL6 0x76
+#define TFA99XX_KEY2_PROTECTED_DCDC_CONTROL7 0x77
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG0 0x80
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG2 0x82
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG3 0x83
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG4 0x84
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG5 0x85
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG7 0x87
+#define TFA99XX_KEY2_PROTECTED_VOLSENSE_CONFIG 0x88
+#define TFA99XX_CURSENSE_CONFIG 0x89
+#define TFA99XX_CF_CONTROLS 0x90
+#define TFA99XX_CF_MAD 0x91
+#define TFA99XX_CF_MEM 0x92
+#define TFA99XX_CF_STATUS 0x93
+#define TFA99XX_MTPKEY1_REG 0xa0
+#define TFA99XX_MTPKEY2_REG 0xa1
+#define TFA99XX_MTP_STATUS 0xa2
+#define TFA99XX_KEY_PROTECTED_MTP_CONTROL 0xa3
+#define TFA99XX_KEY1_PROTECTED_FAIM_CONTROL 0xa4
+#define TFA99XX_MTP_DATA_OUT_MSB 0xa5
+#define TFA99XX_MTP_DATA_OUT_LSB 0xa6
+#define TFA99XX_KEY1_PROTECTED_PROTECTION_CONFIG 0xb0
+#define TFA99XX_TEMP_SENSOR_CONFIG 0xb1
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL0 0xc0
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL1 0xc1
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG0 0xc3
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG1 0xc4
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG2 0xc5
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG3 0xc6
+#define TFA99XX_KEY1_PROTECTED_DIGIMUX_CONTROL1 0xc8
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL0 0xca
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL1 0xcb
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST0 0xcd
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST3 0xd0
+#define TFA99XX_KEY1_PROTECTED_TSIG_CONTROL1 0xd2
+#define TFA99XX_KEY1_PROTECTED_ADC10_CONTROL 0xd3
+#define TFA99XX_KEY1_PROTECTED_ADC10_DATA 0xd4
+#define TFA99XX_KEY2_PROTECTED_CTRL_DIGTOANA 0xd5
+#define TFA99XX_KEY1_PROTECTED_CLKDIV_CONTROL 0xd6
+#define TFA99XX_KEY1_PROTECTED_IO_CONFIG2 0xd7
+#define TFA99XX_KEY1_PROTECTED_TEST_CTRL1 0xd8
+#define TFA99XX_KEY1_PROTECTED_MODE_OVERRULE 0xd9
+#define TFA99XX_KEY1_PROTECTED_FRO8_CALIB_CTRL 0xed
+#define TFA99XX_SOFTWARE_PROFILE 0xee
+#define TFA99XX_SOFTWARE_VSTEP 0xef
+#define TFA99XX_KEY2_PROTECTED_MTP0 0xf0
+#define TFA99XX_KEY1_PROTECTED_MTP2 0xf2
+#define TFA99XX_KEY2_PROTECTED_MTP4 0xf4
+#define TFA99XX_KEY1_PROTECTED_MTP6 0xf6
+#define TFA99XX_KEY1_PROTECTED_MTP7 0xf7
+#define TFA99XX_KEY1_PROTECTED_MTP9 0xf9
+#define TFA99XX_KEY1_PROTECTED_MTPF 0xff
+#define TFA99XX_SYS_CONTROL0_POR
+#define TFA99XX_SYS_CONTROL1_POR
+#define TFA99XX_SYS_CONTROL2_POR
+#define TFA99XX_DEVICE_REVISION_POR
+#define TFA99XX_CLOCK_CONTROL_POR
+#define TFA99XX_CLOCK_GATING_CONTROL_POR
+#define TFA99XX_HW_PATH_CFG_POR
+#define TFA99XX_CLKCHK_TH_POR
+#define TFA99XX_AMP_CTRL_POR
+#define TFA99XX_SIDE_TONE_CONFIG_POR
+#define TFA99XX_CTRL_DIGTOANA_REG_POR
+#define TFA99XX_STATUS_FLAGS0_POR
+#define TFA99XX_STATUS_FLAGS1_POR
+#define TFA99XX_STATUS_FLAGS3_POR
+#define TFA99XX_STATUS_FLAGS4_POR
+#define TFA99XX_BATTERY_VOLTAGE_POR
+#define TFA99XX_TEMPERATURE_POR
+#define TFA99XX_VDDP_VOLTAGE_POR
+#define TFA99XX_TDM_CONFIG0_POR
+#define TFA99XX_TDM_CONFIG1_POR
+#define TFA99XX_TDM_CONFIG2_POR
+#define TFA99XX_TDM_CONFIG3_POR
+#define TFA99XX_TDM_CONFIG4_POR
+#define TFA99XX_TDM_CONFIG5_POR
+#define TFA99XX_TDM_CONFIG6_POR
+#define TFA99XX_TDM_CONFIG7_POR
+#define TFA99XX_TDM_CONFIG8_POR
+#define TFA99XX_TDM_CONFIG9_POR
+#define TFA99XX_PDM_CONFIG0_POR
+#define TFA99XX_PDM_CONFIG1_POR
+#define TFA99XX_INTERRUPT_OUT_REG1_POR
+#define TFA99XX_INTERRUPT_OUT_REG2_POR
+#define TFA99XX_INTERRUPT_OUT_REG3_POR
+#define TFA99XX_INTERRUPT_IN_REG1_POR
+#define TFA99XX_INTERRUPT_IN_REG2_POR
+#define TFA99XX_INTERRUPT_IN_REG3_POR
+#define TFA99XX_INTERRUPT_ENABLE_REG1_POR
+#define TFA99XX_INTERRUPT_ENABLE_REG2_POR
+#define TFA99XX_INTERRUPT_ENABLE_REG3_POR
+#define TFA99XX_STATUS_POLARITY_REG1_POR
+#define TFA99XX_STATUS_POLARITY_REG2_POR
+#define TFA99XX_STATUS_POLARITY_REG3_POR
+#define TFA99XX_BAT_PROT_CONFIG_POR
+#define TFA99XX_AUDIO_CONTROL_POR
+#define TFA99XX_AMPLIFIER_CONFIG_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL2_POR
+#define TFA99XX_KEY1_PROTECTED_AMPLIFIER_CONTROL4_POR
+#define TFA99XX_KEY1_PROTECTED_PWM_CONFIG_POR
+#define TFA99XX_CF_TAP_STATUS_0_POR
+#define TFA99XX_CF_TAP_STATUS_1_POR
+#define TFA99XX_TAP_CONTROL_POR
+#define TFA99XX_PGA_CONTROL0_POR
+#define TFA99XX_GAIN_ATT_POR
+#define TFA99XX_LOW_NOISE_GAIN1_POR
+#define TFA99XX_LOW_NOISE_GAIN2_POR
+#define TFA99XX_MODE1_DETECTOR1_POR
+#define TFA99XX_MODE1_DETECTOR2_POR
+#define TFA99XX_BST_PFM_CTRL_POR
+#define TFA99XX_LOW_POWER_CTRL_POR
+#define TFA99XX_TDM_SOURCE_CTRL_POR
+#define TFA99XX_SAM_CTRL_POR
+#define TFA99XX_RST_MIN_VBAT_CTRL_POR
+#define TFA99XX_SYS_CONTROL3_POR
+#define TFA99XX_STATUS_FLAGS5_POR
+#define TFA99XX_DCDC_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_DCDC_CONTROL3_POR
+#define TFA99XX_DCDC_CONTROL4_POR
+#define TFA99XX_DCDC_CONTROL5_POR
+#define TFA99XX_DCDC_CONTROL6_POR
+#define TFA99XX_KEY2_PROTECTED_DCDC_CONTROL7_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG0_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG2_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG3_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG4_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG5_POR
+#define TFA99XX_KEY2_PROTECTED_CURSENSE_CONFIG7_POR
+#define TFA99XX_KEY2_PROTECTED_VOLSENSE_CONFIG_POR
+#define TFA99XX_CURSENSE_CONFIG_POR
+#define TFA99XX_CF_CONTROLS_POR
+#define TFA99XX_CF_MAD_POR
+#define TFA99XX_CF_MEM_POR
+#define TFA99XX_CF_STATUS_POR
+#define TFA99XX_MTPKEY1_REG_POR
+#define TFA99XX_MTPKEY2_REG_POR
+#define TFA99XX_MTP_STATUS_POR
+#define TFA99XX_KEY_PROTECTED_MTP_CONTROL_POR
+#define TFA99XX_KEY1_PROTECTED_FAIM_CONTROL_POR
+#define TFA99XX_MTP_DATA_OUT_MSB_POR
+#define TFA99XX_MTP_DATA_OUT_LSB_POR
+#define TFA99XX_KEY1_PROTECTED_PROTECTION_CONFIG_POR
+#define TFA99XX_TEMP_SENSOR_CONFIG_POR
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_DIRECT_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG0_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG1_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG2_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CONFIG3_POR
+#define TFA99XX_KEY1_PROTECTED_DIGIMUX_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL0_POR
+#define TFA99XX_KEY1_PROTECTED_ANAMUX_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST0_POR
+#define TFA99XX_KEY1_PROTECTED_PLL_TEST3_POR
+#define TFA99XX_KEY1_PROTECTED_TSIG_CONTROL1_POR
+#define TFA99XX_KEY1_PROTECTED_ADC10_CONTROL_POR
+#define TFA99XX_KEY1_PROTECTED_ADC10_DATA_POR
+#define TFA99XX_KEY2_PROTECTED_CTRL_DIGTOANA_POR
+#define TFA99XX_KEY1_PROTECTED_CLKDIV_CONTROL_POR
+#define TFA99XX_KEY1_PROTECTED_IO_CONFIG2_POR
+#define TFA99XX_KEY1_PROTECTED_TEST_CTRL1_POR
+#define TFA99XX_KEY1_PROTECTED_MODE_OVERRULE_POR
+#define TFA99XX_KEY1_PROTECTED_FRO8_CALIB_CTRL_POR
+#define TFA99XX_SOFTWARE_PROFILE_POR
+#define TFA99XX_SOFTWARE_VSTEP_POR
+#define TFA99XX_KEY2_PROTECTED_MTP0_POR
+#define TFA99XX_KEY1_PROTECTED_MTP2_POR
+#define TFA99XX_KEY2_PROTECTED_MTP4_POR
+#define TFA99XX_KEY1_PROTECTED_MTP6_POR
+#define TFA99XX_KEY1_PROTECTED_MTP7_POR
+#define TFA99XX_KEY1_PROTECTED_MTP9_POR
+#define TFA99XX_KEY1_PROTECTED_MTPF_POR
+
+#endif /* _TFA9912_DEVICE_GENREGS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa9912_tfafieldnames.h b/sound/soc/codecs/tfa98xx-downstream/tfa9912_tfafieldnames.h
new file mode 100644
index 00000000000..9e5a166ac10
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa9912_tfafieldnames.h
@@ -0,0 +1,1776 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/** Filename: tfa9912_tfaFieldnames.h
+ * This file was generated automatically on 09/28/18 at 12:00:21.
+ * Source file: TFA9912_N1A_I2C_regmap_V1.43.xlsx
+ */
+
+#ifndef _TFA9912_TFAFIELDNAMES_H
+#define _TFA9912_TFAFIELDNAMES_H
+
+
+#define TFA9912_I2CVERSION 1.43
+
+typedef enum Tfa9912BfEnumList {
+ TFA9912_BF_PWDN = 0x0000, /*!< Powerdown selection */
+ TFA9912_BF_I2CR = 0x0010, /*!< I2C Reset - Auto clear */
+ TFA9912_BF_CFE = 0x0020, /*!< Enable CoolFlux */
+ TFA9912_BF_AMPE = 0x0030, /*!< Enables the Amplifier */
+ TFA9912_BF_DCA = 0x0040, /*!< Activate DC-to-DC converter */
+ TFA9912_BF_SBSL = 0x0050, /*!< Coolflux configured */
+ TFA9912_BF_AMPC = 0x0060, /*!< CoolFlux controls amplifier */
+ TFA9912_BF_INTP = 0x0071, /*!< Interrupt config */
+ TFA9912_BF_FSSSEL= 0x0090, /*!< Audio sample reference */
+ TFA9912_BF_BYPOCP= 0x00b0, /*!< Bypass OCP */
+ TFA9912_BF_TSTOCP= 0x00c0, /*!< OCP testing control */
+ TFA9912_BF_AMPINSEL= 0x0101, /*!< Amplifier input selection */
+ TFA9912_BF_MANSCONF= 0x0120, /*!< I2C configured */
+ TFA9912_BF_MANCOLD= 0x0130, /*!< Execute cold start */
+ TFA9912_BF_MANAOOSC= 0x0140, /*!< Internal osc off at PWDN */
+ TFA9912_BF_MANROBOD= 0x0150, /*!< Reaction on BOD */
+ TFA9912_BF_BODE = 0x0160, /*!< BOD Enable */
+ TFA9912_BF_BODHYS= 0x0170, /*!< BOD Hysteresis */
+ TFA9912_BF_BODFILT= 0x0181, /*!< BOD filter */
+ TFA9912_BF_BODTHLVL= 0x01a1, /*!< BOD threshold */
+ TFA9912_BF_MUTETO= 0x01d0, /*!< Time out SB mute sequence */
+ TFA9912_BF_RCVNS = 0x01e0, /*!< Noise shaper selection */
+ TFA9912_BF_MANWDE= 0x01f0, /*!< Watchdog enable */
+ TFA9912_BF_AUDFS = 0x0203, /*!< Sample rate (fs) */
+ TFA9912_BF_INPLEV= 0x0240, /*!< TDM output attenuation */
+ TFA9912_BF_FRACTDEL= 0x0255, /*!< V/I Fractional delay */
+ TFA9912_BF_BYPHVBF= 0x02b0, /*!< Bypass HVBAT filter */
+ TFA9912_BF_TDMC = 0x02c0, /*!< TDM Compatibility with TFA9872 */
+ TFA9912_BF_ENBLADC10= 0x02e0, /*!< ADC10 Enable - I2C direct mode */
+ TFA9912_BF_REV = 0x030f, /*!< Revision info */
+ TFA9912_BF_REFCKEXT= 0x0401, /*!< PLL external ref clock */
+ TFA9912_BF_REFCKSEL= 0x0420, /*!< PLL internal ref clock */
+ TFA9912_BF_ENCFCKSEL= 0x0430, /*!< Coolflux DSP clock scaling, low power mode */
+ TFA9912_BF_CFCKSEL= 0x0441, /*!< Coolflux DSP clock scaler selection for low power mode */
+ TFA9912_BF_TDMINFSEL= 0x0460, /*!< TDM clock selection */
+ TFA9912_BF_DISBLAUTOCLKSEL= 0x0470, /*!< Disable Automatic dsp clock source selection */
+ TFA9912_BF_SELCLKSRC= 0x0480, /*!< I2C selection of DSP clock when auto select is disabled */
+ TFA9912_BF_SELTIMSRC= 0x0490, /*!< I2C selection of Watchdog and Timer clock */
+ TFA9912_BF_SSLEFTE= 0x0500, /*!< */
+ TFA9912_BF_SPKSSEN= 0x0510, /*!< Enable speaker path */
+ TFA9912_BF_VSLEFTE= 0x0520, /*!< */
+ TFA9912_BF_VSRIGHTE= 0x0530, /*!< Voltage sense */
+ TFA9912_BF_CSLEFTE= 0x0540, /*!< */
+ TFA9912_BF_CSRIGHTE= 0x0550, /*!< Current sense */
+ TFA9912_BF_SSPDME= 0x0560, /*!< Sub-system PDM */
+ TFA9912_BF_PGALE = 0x0570, /*!< Enable PGA chop clock for left channel */
+ TFA9912_BF_PGARE = 0x0580, /*!< Enable PGA chop clock */
+ TFA9912_BF_SSTDME= 0x0590, /*!< Sub-system TDM */
+ TFA9912_BF_SSPBSTE= 0x05a0, /*!< Sub-system boost */
+ TFA9912_BF_SSADCE= 0x05b0, /*!< Sub-system ADC */
+ TFA9912_BF_SSFAIME= 0x05c0, /*!< Sub-system FAIM */
+ TFA9912_BF_SSCFTIME= 0x05d0, /*!< CF Sub-system timer */
+ TFA9912_BF_SSCFWDTE= 0x05e0, /*!< CF Sub-system WDT */
+ TFA9912_BF_FAIMVBGOVRRL= 0x05f0, /*!< Over rule of vbg for FaIM access */
+ TFA9912_BF_SAMSPKSEL= 0x0600, /*!< Input selection for TAP/SAM */
+ TFA9912_BF_PDM2IISEN= 0x0610, /*!< PDM2IIS Bridge enable */
+ TFA9912_BF_TAPRSTBYPASS= 0x0620, /*!< Tap decimator reset bypass - Bypass the decimator reset from tapdec */
+ TFA9912_BF_CARDECISEL0= 0x0631, /*!< Cardec input 0 sel */
+ TFA9912_BF_CARDECISEL1= 0x0651, /*!< Cardec input sel */
+ TFA9912_BF_TAPDECSEL= 0x0670, /*!< Select TAP/Cardec for TAP */
+ TFA9912_BF_COMPCOUNT= 0x0680, /*!< Comparator o/p filter selection */
+ TFA9912_BF_STARTUPMODE= 0x0691, /*!< Startup Mode Selection */
+ TFA9912_BF_AUTOTAP= 0x06b0, /*!< Enable auto tap switching */
+ TFA9912_BF_COMPINITIME= 0x06c1, /*!< Comparator initialization time to be used in Tap Machine */
+ TFA9912_BF_ANAPINITIME= 0x06e1, /*!< Analog initialization time to be used in Tap Machine */
+ TFA9912_BF_CCHKTH= 0x0707, /*!< Clock check Higher Threshold */
+ TFA9912_BF_CCHKTL= 0x0787, /*!< Clock check Higher Threshold */
+ TFA9912_BF_AMPOCRT= 0x0802, /*!< Amplifier on-off criteria for shutdown */
+ TFA9912_BF_AMPTCRR= 0x0832, /*!< Amplifier on-off criteria for tap mode entry */
+ TFA9912_BF_STGS = 0x0d00, /*!< PDM side tone gain selector */
+ TFA9912_BF_STGAIN= 0x0d18, /*!< Side tone gain */
+ TFA9912_BF_STSMUTE= 0x0da0, /*!< Side tone soft mute */
+ TFA9912_BF_ST1C = 0x0db0, /*!< side tone one s complement */
+ TFA9912_BF_CMFBEL= 0x0e80, /*!< CMFB enable left */
+ TFA9912_BF_VDDS = 0x1000, /*!< POR */
+ TFA9912_BF_PLLS = 0x1010, /*!< PLL lock */
+ TFA9912_BF_OTDS = 0x1020, /*!< OTP alarm */
+ TFA9912_BF_OVDS = 0x1030, /*!< OVP alarm */
+ TFA9912_BF_UVDS = 0x1040, /*!< UVP alarm */
+ TFA9912_BF_CLKS = 0x1050, /*!< Clocks stable */
+ TFA9912_BF_MTPB = 0x1060, /*!< MTP busy */
+ TFA9912_BF_NOCLK = 0x1070, /*!< Lost clock */
+ TFA9912_BF_ACS = 0x1090, /*!< Cold Start */
+ TFA9912_BF_SWS = 0x10a0, /*!< Amplifier engage */
+ TFA9912_BF_WDS = 0x10b0, /*!< Watchdog */
+ TFA9912_BF_AMPS = 0x10c0, /*!< Amplifier enable */
+ TFA9912_BF_AREFS = 0x10d0, /*!< References enable */
+ TFA9912_BF_ADCCR = 0x10e0, /*!< Control ADC */
+ TFA9912_BF_BODNOK= 0x10f0, /*!< BOD */
+ TFA9912_BF_DCIL = 0x1100, /*!< DCDC current limiting */
+ TFA9912_BF_DCDCA = 0x1110, /*!< DCDC active */
+ TFA9912_BF_DCOCPOK= 0x1120, /*!< DCDC OCP nmos */
+ TFA9912_BF_DCPEAKCUR= 0x1130, /*!< Indicates current is max in DC-to-DC converter */
+ TFA9912_BF_DCHVBAT= 0x1140, /*!< DCDC level 1x */
+ TFA9912_BF_DCH114= 0x1150, /*!< DCDC level 1.14x */
+ TFA9912_BF_DCH107= 0x1160, /*!< DCDC level 1.07x */
+ TFA9912_BF_STMUTEB= 0x1170, /*!< side tone (un)mute busy */
+ TFA9912_BF_STMUTE= 0x1180, /*!< side tone mute state */
+ TFA9912_BF_TDMLUTER= 0x1190, /*!< TDM LUT error */
+ TFA9912_BF_TDMSTAT= 0x11a2, /*!< TDM status bits */
+ TFA9912_BF_TDMERR= 0x11d0, /*!< TDM error */
+ TFA9912_BF_HAPTIC= 0x11e0, /*!< Status haptic driver */
+ TFA9912_BF_OCPOAP= 0x1300, /*!< OCPOK pmos A */
+ TFA9912_BF_OCPOAN= 0x1310, /*!< OCPOK nmos A */
+ TFA9912_BF_OCPOBP= 0x1320, /*!< OCPOK pmos B */
+ TFA9912_BF_OCPOBN= 0x1330, /*!< OCPOK nmos B */
+ TFA9912_BF_CLIPAH= 0x1340, /*!< Clipping A to Vddp */
+ TFA9912_BF_CLIPAL= 0x1350, /*!< Clipping A to gnd */
+ TFA9912_BF_CLIPBH= 0x1360, /*!< Clipping B to Vddp */
+ TFA9912_BF_CLIPBL= 0x1370, /*!< Clipping B to gnd */
+ TFA9912_BF_OCDS = 0x1380, /*!< OCP amplifier */
+ TFA9912_BF_CLIPS = 0x1390, /*!< Amplifier clipping */
+ TFA9912_BF_TCMPTRG= 0x13a0, /*!< Status Tap comparator triggered */
+ TFA9912_BF_TAPDET= 0x13b0, /*!< Status Tap detected */
+ TFA9912_BF_MANWAIT1= 0x13c0, /*!< Wait HW I2C settings */
+ TFA9912_BF_MANWAIT2= 0x13d0, /*!< Wait CF config */
+ TFA9912_BF_MANMUTE= 0x13e0, /*!< Audio mute sequence */
+ TFA9912_BF_MANOPER= 0x13f0, /*!< Operating state */
+ TFA9912_BF_SPKSL = 0x1400, /*!< Left speaker status */
+ TFA9912_BF_SPKS = 0x1410, /*!< Speaker status */
+ TFA9912_BF_CLKOOR= 0x1420, /*!< External clock status */
+ TFA9912_BF_MANSTATE= 0x1433, /*!< Device manager status */
+ TFA9912_BF_DCMODE= 0x1471, /*!< DCDC mode status bits */
+ TFA9912_BF_DSPCLKSRC= 0x1490, /*!< DSP clock source selected by manager */
+ TFA9912_BF_STARTUPMODSTAT= 0x14a1, /*!< Startup Mode Selected by Manager(Read Only) */
+ TFA9912_BF_TSPMSTATE= 0x14c3, /*!< Tap Machine State */
+ TFA9912_BF_BATS = 0x1509, /*!< Battery voltage (V) */
+ TFA9912_BF_TEMPS = 0x1608, /*!< IC Temperature (C) */
+ TFA9912_BF_VDDPS = 0x1709, /*!< IC VDDP voltage ( 1023*VDDP/13 V) */
+ TFA9912_BF_DCILCF= 0x17a0, /*!< DCDC current limiting for DSP */
+ TFA9912_BF_TDMUC = 0x2000, /*!< Mode setting */
+ TFA9912_BF_DIO4SEL= 0x2011, /*!< DIO4 Input selection */
+ TFA9912_BF_TDME = 0x2040, /*!< Enable TDM interface */
+ TFA9912_BF_TDMMODE= 0x2050, /*!< Slave/master */
+ TFA9912_BF_TDMCLINV= 0x2060, /*!< Reception data to BCK clock */
+ TFA9912_BF_TDMFSLN= 0x2073, /*!< FS length */
+ TFA9912_BF_TDMFSPOL= 0x20b0, /*!< FS polarity */
+ TFA9912_BF_TDMNBCK= 0x20c3, /*!< N-BCK's in FS */
+ TFA9912_BF_TDMSLOTS= 0x2103, /*!< N-slots in Frame */
+ TFA9912_BF_TDMSLLN= 0x2144, /*!< N-bits in slot */
+ TFA9912_BF_TDMBRMG= 0x2194, /*!< N-bits remaining */
+ TFA9912_BF_TDMDEL= 0x21e0, /*!< data delay to FS */
+ TFA9912_BF_TDMADJ= 0x21f0, /*!< data adjustment */
+ TFA9912_BF_TDMOOMP= 0x2201, /*!< Received audio compression */
+ TFA9912_BF_TDMSSIZE= 0x2224, /*!< Sample size per slot */
+ TFA9912_BF_TDMTXDFO= 0x2271, /*!< Format unused bits in a slot */
+ TFA9912_BF_TDMTXUS0= 0x2291, /*!< Format unused slots GAINIO */
+ TFA9912_BF_TDMTXUS1= 0x22b1, /*!< Format unused slots DIO1 */
+ TFA9912_BF_TDMTXUS2= 0x22d1, /*!< Format unused slots DIO2 */
+ TFA9912_BF_TDMGIE= 0x2300, /*!< Control gain (channel in 0) */
+ TFA9912_BF_TDMDCE= 0x2310, /*!< Control audio left (channel in 1 ) */
+ TFA9912_BF_TDMSPKE= 0x2320, /*!< Control audio right (channel in 2 ) */
+ TFA9912_BF_TDMCSE= 0x2330, /*!< Current sense */
+ TFA9912_BF_TDMVSE= 0x2340, /*!< Voltage sense */
+ TFA9912_BF_TDMGOE= 0x2350, /*!< DSP Gainout */
+ TFA9912_BF_TDMCF2E= 0x2360, /*!< DSP 2 */
+ TFA9912_BF_TDMCF3E= 0x2370, /*!< DSP 3 */
+ TFA9912_BF_TDMCFE= 0x2380, /*!< DSP */
+ TFA9912_BF_TDMES6= 0x2390, /*!< Loopback of Audio left (channel 1) */
+ TFA9912_BF_TDMES7= 0x23a0, /*!< Loopback of Audio right (channel 2) */
+ TFA9912_BF_TDMCF4E= 0x23b0, /*!< AEC ref right control */
+ TFA9912_BF_TDMPD1E= 0x23c0, /*!< PDM 1 control */
+ TFA9912_BF_TDMPD2E= 0x23d0, /*!< PDM 2 control */
+ TFA9912_BF_TDMGIN= 0x2401, /*!< IO gainin */
+ TFA9912_BF_TDMLIO= 0x2421, /*!< IO audio left */
+ TFA9912_BF_TDMRIO= 0x2441, /*!< IO audio right */
+ TFA9912_BF_TDMCSIO= 0x2461, /*!< IO Current Sense */
+ TFA9912_BF_TDMVSIO= 0x2481, /*!< IO voltage sense */
+ TFA9912_BF_TDMGOIO= 0x24a1, /*!< IO gain out */
+ TFA9912_BF_TDMCFIO2= 0x24c1, /*!< IO DSP 2 */
+ TFA9912_BF_TDMCFIO3= 0x24e1, /*!< IO DSP 3 */
+ TFA9912_BF_TDMCFIO= 0x2501, /*!< IO DSP */
+ TFA9912_BF_TDMLPB6= 0x2521, /*!< IO Source 6 */
+ TFA9912_BF_TDMLPB7= 0x2541, /*!< IO Source 7 */
+ TFA9912_BF_TDMGS = 0x2603, /*!< Control gainin */
+ TFA9912_BF_TDMDCS= 0x2643, /*!< tdm slot for audio left (channel 1) */
+ TFA9912_BF_TDMSPKS= 0x2683, /*!< tdm slot for audio right (channel 2) */
+ TFA9912_BF_TDMCSS= 0x26c3, /*!< Slot Position of Current Sense Out */
+ TFA9912_BF_TDMVSS= 0x2703, /*!< Slot Position of Voltage sense */
+ TFA9912_BF_TDMCGOS= 0x2743, /*!< Slot Position of GAIN out */
+ TFA9912_BF_TDMCF2S= 0x2783, /*!< Slot Position DSPout2 */
+ TFA9912_BF_TDMCF3S= 0x27c3, /*!< Slot Position DSPout3 */
+ TFA9912_BF_TDMCFS= 0x2803, /*!< Slot Position of DSPout */
+ TFA9912_BF_TDMEDAT6S= 0x2843, /*!< Slot Position of loopback channel left */
+ TFA9912_BF_TDMEDAT7S= 0x2883, /*!< Slot Position of loopback channel right */
+ TFA9912_BF_TDMTXUS3= 0x2901, /*!< Format unused slots D3 */
+ TFA9912_BF_PDMSM = 0x3100, /*!< PDM control */
+ TFA9912_BF_PDMSTSEL= 0x3110, /*!< PDM Decimator input selection */
+ TFA9912_BF_PDMSTENBL= 0x3120, /*!< Side tone input enable */
+ TFA9912_BF_PDMLSEL= 0x3130, /*!< PDM data selection for left channel during PDM direct mode */
+ TFA9912_BF_PDMRSEL= 0x3140, /*!< PDM data selection for right channel during PDM direct mode */
+ TFA9912_BF_MICVDDE= 0x3150, /*!< Enable MICVDD */
+ TFA9912_BF_PDMCLRAT= 0x3201, /*!< PDM BCK/Fs ratio */
+ TFA9912_BF_PDMGAIN= 0x3223, /*!< PDM gain */
+ TFA9912_BF_PDMOSEL= 0x3263, /*!< PDM output selection - RE/FE data combination */
+ TFA9912_BF_SELCFHAPD= 0x32a0, /*!< Select the source for haptic data output (not for customer) */
+ TFA9912_BF_ISTVDDS= 0x4000, /*!< Status POR */
+ TFA9912_BF_ISTPLLS= 0x4010, /*!< Status PLL lock */
+ TFA9912_BF_ISTOTDS= 0x4020, /*!< Status OTP alarm */
+ TFA9912_BF_ISTOVDS= 0x4030, /*!< Status OVP alarm */
+ TFA9912_BF_ISTUVDS= 0x4040, /*!< Status UVP alarm */
+ TFA9912_BF_ISTCLKS= 0x4050, /*!< Status clocks stable */
+ TFA9912_BF_ISTMTPB= 0x4060, /*!< Status MTP busy */
+ TFA9912_BF_ISTNOCLK= 0x4070, /*!< Status lost clock */
+ TFA9912_BF_ISTSPKS= 0x4080, /*!< Status speaker error */
+ TFA9912_BF_ISTACS= 0x4090, /*!< Status cold start */
+ TFA9912_BF_ISTSWS= 0x40a0, /*!< Status amplifier engage */
+ TFA9912_BF_ISTWDS= 0x40b0, /*!< Status watchdog */
+ TFA9912_BF_ISTAMPS= 0x40c0, /*!< Status amplifier enable */
+ TFA9912_BF_ISTAREFS= 0x40d0, /*!< Status Ref enable */
+ TFA9912_BF_ISTADCCR= 0x40e0, /*!< Status Control ADC */
+ TFA9912_BF_ISTBODNOK= 0x40f0, /*!< Status BOD */
+ TFA9912_BF_ISTBSTCU= 0x4100, /*!< Status DCDC current limiting */
+ TFA9912_BF_ISTBSTHI= 0x4110, /*!< Status DCDC active */
+ TFA9912_BF_ISTBSTOC= 0x4120, /*!< Status DCDC OCP */
+ TFA9912_BF_ISTBSTPKCUR= 0x4130, /*!< Status bst peakcur */
+ TFA9912_BF_ISTBSTVC= 0x4140, /*!< Status DCDC level 1x */
+ TFA9912_BF_ISTBST86= 0x4150, /*!< Status DCDC level 1.14x */
+ TFA9912_BF_ISTBST93= 0x4160, /*!< Status DCDC level 1.07x */
+ TFA9912_BF_ISTRCVLD= 0x4170, /*!< Status rcvldop ready */
+ TFA9912_BF_ISTOCPL= 0x4180, /*!< Status ocp alarm left */
+ TFA9912_BF_ISTOCPR= 0x4190, /*!< Status ocp alarm */
+ TFA9912_BF_ISTMWSRC= 0x41a0, /*!< Status Waits HW I2C settings */
+ TFA9912_BF_ISTMWCFC= 0x41b0, /*!< Status waits CF config */
+ TFA9912_BF_ISTMWSMU= 0x41c0, /*!< Status Audio mute sequence */
+ TFA9912_BF_ISTCFMER= 0x41d0, /*!< Status cfma error */
+ TFA9912_BF_ISTCFMAC= 0x41e0, /*!< Status cfma ack */
+ TFA9912_BF_ISTCLKOOR= 0x41f0, /*!< Status flag_clk_out_of_range */
+ TFA9912_BF_ISTTDMER= 0x4200, /*!< Status tdm error */
+ TFA9912_BF_ISTCLPL= 0x4210, /*!< Status clip left */
+ TFA9912_BF_ISTCLPR= 0x4220, /*!< Status clip */
+ TFA9912_BF_ISTOCPM= 0x4230, /*!< Status mic ocpok */
+ TFA9912_BF_ISTLP1= 0x4250, /*!< Status low power mode1 */
+ TFA9912_BF_ISTLA = 0x4260, /*!< Status low amplitude detection */
+ TFA9912_BF_ISTVDDP= 0x4270, /*!< Status VDDP greater than VBAT */
+ TFA9912_BF_ISTTAPDET= 0x4280, /*!< Status Tap detected */
+ TFA9912_BF_ISTAUDMOD= 0x4290, /*!< Status Audio Mode activated */
+ TFA9912_BF_ISTSAMMOD= 0x42a0, /*!< Status SAM Mode activated */
+ TFA9912_BF_ISTTAPMOD= 0x42b0, /*!< Status Tap Mode Activated */
+ TFA9912_BF_ISTTAPTRG= 0x42c0, /*!< Status Tap comparator triggered */
+ TFA9912_BF_ICLVDDS= 0x4400, /*!< Clear POR */
+ TFA9912_BF_ICLPLLS= 0x4410, /*!< Clear PLL lock */
+ TFA9912_BF_ICLOTDS= 0x4420, /*!< Clear OTP alarm */
+ TFA9912_BF_ICLOVDS= 0x4430, /*!< Clear OVP alarm */
+ TFA9912_BF_ICLUVDS= 0x4440, /*!< Clear UVP alarm */
+ TFA9912_BF_ICLCLKS= 0x4450, /*!< Clear clocks stable */
+ TFA9912_BF_ICLMTPB= 0x4460, /*!< Clear mtp busy */
+ TFA9912_BF_ICLNOCLK= 0x4470, /*!< Clear lost clk */
+ TFA9912_BF_ICLSPKS= 0x4480, /*!< Clear speaker error */
+ TFA9912_BF_ICLACS= 0x4490, /*!< Clear cold started */
+ TFA9912_BF_ICLSWS= 0x44a0, /*!< Clear amplifier engage */
+ TFA9912_BF_ICLWDS= 0x44b0, /*!< Clear watchdog */
+ TFA9912_BF_ICLAMPS= 0x44c0, /*!< Clear enbl amp */
+ TFA9912_BF_ICLAREFS= 0x44d0, /*!< Clear ref enable */
+ TFA9912_BF_ICLADCCR= 0x44e0, /*!< Clear control ADC */
+ TFA9912_BF_ICLBODNOK= 0x44f0, /*!< Clear BOD */
+ TFA9912_BF_ICLBSTCU= 0x4500, /*!< Clear DCDC current limiting */
+ TFA9912_BF_ICLBSTHI= 0x4510, /*!< Clear DCDC active */
+ TFA9912_BF_ICLBSTOC= 0x4520, /*!< Clear DCDC OCP */
+ TFA9912_BF_ICLBSTPC= 0x4530, /*!< Clear bst peakcur */
+ TFA9912_BF_ICLBSTVC= 0x4540, /*!< Clear DCDC level 1x */
+ TFA9912_BF_ICLBST86= 0x4550, /*!< Clear DCDC level 1.14x */
+ TFA9912_BF_ICLBST93= 0x4560, /*!< Clear DCDC level 1.07x */
+ TFA9912_BF_ICLRCVLD= 0x4570, /*!< Clear rcvldop ready */
+ TFA9912_BF_ICLOCPL= 0x4580, /*!< Clear ocp alarm left */
+ TFA9912_BF_ICLOCPR= 0x4590, /*!< Clear ocp alarm */
+ TFA9912_BF_ICLMWSRC= 0x45a0, /*!< Clear wait HW I2C settings */
+ TFA9912_BF_ICLMWCFC= 0x45b0, /*!< Clear wait cf config */
+ TFA9912_BF_ICLMWSMU= 0x45c0, /*!< Clear audio mute sequence */
+ TFA9912_BF_ICLCFMER= 0x45d0, /*!< Clear cfma err */
+ TFA9912_BF_ICLCFMAC= 0x45e0, /*!< Clear cfma ack */
+ TFA9912_BF_ICLCLKOOR= 0x45f0, /*!< Clear flag_clk_out_of_range */
+ TFA9912_BF_ICLTDMER= 0x4600, /*!< Clear tdm error */
+ TFA9912_BF_ICLCLPL= 0x4610, /*!< Clear clip left */
+ TFA9912_BF_ICLCLP= 0x4620, /*!< Clear clip */
+ TFA9912_BF_ICLOCPM= 0x4630, /*!< Clear mic ocpok */
+ TFA9912_BF_ICLLP1= 0x4650, /*!< Clear low power mode1 */
+ TFA9912_BF_ICLLA = 0x4660, /*!< Clear low amplitude detection */
+ TFA9912_BF_ICLVDDP= 0x4670, /*!< Clear VDDP greater then VBAT */
+ TFA9912_BF_ICLTAPDET= 0x4680, /*!< Clear Tap detected */
+ TFA9912_BF_ICLAUDMOD= 0x4690, /*!< Clear Audio Mode activated */
+ TFA9912_BF_ICLSAMMOD= 0x46a0, /*!< Clear SAM Mode activated */
+ TFA9912_BF_ICLTAPMOD= 0x46b0, /*!< Clear Tap Mode Activated */
+ TFA9912_BF_ICLTAPTRG= 0x46c0, /*!< Clear Comparator Interrupt */
+ TFA9912_BF_IEVDDS= 0x4800, /*!< Enable por */
+ TFA9912_BF_IEPLLS= 0x4810, /*!< Enable pll lock */
+ TFA9912_BF_IEOTDS= 0x4820, /*!< Enable OTP alarm */
+ TFA9912_BF_IEOVDS= 0x4830, /*!< Enable OVP alarm */
+ TFA9912_BF_IEUVDS= 0x4840, /*!< Enable UVP alarm */
+ TFA9912_BF_IECLKS= 0x4850, /*!< Enable clocks stable */
+ TFA9912_BF_IEMTPB= 0x4860, /*!< Enable mtp busy */
+ TFA9912_BF_IENOCLK= 0x4870, /*!< Enable lost clk */
+ TFA9912_BF_IESPKS= 0x4880, /*!< Enable speaker error */
+ TFA9912_BF_IEACS = 0x4890, /*!< Enable cold started */
+ TFA9912_BF_IESWS = 0x48a0, /*!< Enable amplifier engage */
+ TFA9912_BF_IEWDS = 0x48b0, /*!< Enable watchdog */
+ TFA9912_BF_IEAMPS= 0x48c0, /*!< Enable enbl amp */
+ TFA9912_BF_IEAREFS= 0x48d0, /*!< Enable ref enable */
+ TFA9912_BF_IEADCCR= 0x48e0, /*!< Enable Control ADC */
+ TFA9912_BF_IEBODNOK= 0x48f0, /*!< Enable BOD */
+ TFA9912_BF_IEBSTCU= 0x4900, /*!< Enable DCDC current limiting */
+ TFA9912_BF_IEBSTHI= 0x4910, /*!< Enable DCDC active */
+ TFA9912_BF_IEBSTOC= 0x4920, /*!< Enable DCDC OCP */
+ TFA9912_BF_IEBSTPC= 0x4930, /*!< Enable bst peakcur */
+ TFA9912_BF_IEBSTVC= 0x4940, /*!< Enable DCDC level 1x */
+ TFA9912_BF_IEBST86= 0x4950, /*!< Enable DCDC level 1.14x */
+ TFA9912_BF_IEBST93= 0x4960, /*!< Enable DCDC level 1.07x */
+ TFA9912_BF_IERCVLD= 0x4970, /*!< Enable rcvldop ready */
+ TFA9912_BF_IEOCPL= 0x4980, /*!< Enable ocp alarm left */
+ TFA9912_BF_IEOCPR= 0x4990, /*!< Enable ocp alarm */
+ TFA9912_BF_IEMWSRC= 0x49a0, /*!< Enable waits HW I2C settings */
+ TFA9912_BF_IEMWCFC= 0x49b0, /*!< Enable man wait cf config */
+ TFA9912_BF_IEMWSMU= 0x49c0, /*!< Enable man Audio mute sequence */
+ TFA9912_BF_IECFMER= 0x49d0, /*!< Enable cfma err */
+ TFA9912_BF_IECFMAC= 0x49e0, /*!< Enable cfma ack */
+ TFA9912_BF_IECLKOOR= 0x49f0, /*!< Enable flag_clk_out_of_range */
+ TFA9912_BF_IETDMER= 0x4a00, /*!< Enable tdm error */
+ TFA9912_BF_IECLPL= 0x4a10, /*!< Enable clip left */
+ TFA9912_BF_IECLPR= 0x4a20, /*!< Enable clip */
+ TFA9912_BF_IEOCPM1= 0x4a30, /*!< Enable mic ocpok */
+ TFA9912_BF_IELP1 = 0x4a50, /*!< Enable low power mode1 */
+ TFA9912_BF_IELA = 0x4a60, /*!< Enable low amplitude detection */
+ TFA9912_BF_IEVDDP= 0x4a70, /*!< Enable VDDP greater than VBAT */
+ TFA9912_BF_IETAPDET= 0x4a80, /*!< Enable Tap detected */
+ TFA9912_BF_IEAUDMOD= 0x4a90, /*!< Enable Audio Mode activated */
+ TFA9912_BF_IESAMMOD= 0x4aa0, /*!< Enable SAM Mode activated */
+ TFA9912_BF_IETAPMOD= 0x4ab0, /*!< Enable Tap Mode Activated */
+ TFA9912_BF_IETAPTRG= 0x4ac0, /*!< Enable comparator interrupt */
+ TFA9912_BF_IPOVDDS= 0x4c00, /*!< Polarity por */
+ TFA9912_BF_IPOPLLS= 0x4c10, /*!< Polarity pll lock */
+ TFA9912_BF_IPOOTDS= 0x4c20, /*!< Polarity OTP alarm */
+ TFA9912_BF_IPOOVDS= 0x4c30, /*!< Polarity OVP alarm */
+ TFA9912_BF_IPOUVDS= 0x4c40, /*!< Polarity UVP alarm */
+ TFA9912_BF_IPOCLKS= 0x4c50, /*!< Polarity clocks stable */
+ TFA9912_BF_IPOMTPB= 0x4c60, /*!< Polarity mtp busy */
+ TFA9912_BF_IPONOCLK= 0x4c70, /*!< Polarity lost clk */
+ TFA9912_BF_IPOSPKS= 0x4c80, /*!< Polarity speaker error */
+ TFA9912_BF_IPOACS= 0x4c90, /*!< Polarity cold started */
+ TFA9912_BF_IPOSWS= 0x4ca0, /*!< Polarity amplifier engage */
+ TFA9912_BF_IPOWDS= 0x4cb0, /*!< Polarity watchdog */
+ TFA9912_BF_IPOAMPS= 0x4cc0, /*!< Polarity enbl amp */
+ TFA9912_BF_IPOAREFS= 0x4cd0, /*!< Polarity ref enable */
+ TFA9912_BF_IPOADCCR= 0x4ce0, /*!< Polarity Control ADC */
+ TFA9912_BF_IPOBODNOK= 0x4cf0, /*!< Polarity BOD */
+ TFA9912_BF_IPOBSTCU= 0x4d00, /*!< Polarity DCDC current limiting */
+ TFA9912_BF_IPOBSTHI= 0x4d10, /*!< Polarity DCDC active */
+ TFA9912_BF_IPOBSTOC= 0x4d20, /*!< Polarity DCDC OCP */
+ TFA9912_BF_IPOBSTPC= 0x4d30, /*!< Polarity bst peakcur */
+ TFA9912_BF_IPOBSTVC= 0x4d40, /*!< Polarity DCDC level 1x */
+ TFA9912_BF_IPOBST86= 0x4d50, /*!< Polarity DCDC level 1.14x */
+ TFA9912_BF_IPOBST93= 0x4d60, /*!< Polarity DCDC level 1.07x */
+ TFA9912_BF_IPORCVLD= 0x4d70, /*!< Polarity rcvldop ready */
+ TFA9912_BF_IPOOCPL= 0x4d80, /*!< Polarity ocp alarm left */
+ TFA9912_BF_IPOOCPR= 0x4d90, /*!< Polarity ocp alarm */
+ TFA9912_BF_IPOMWSRC= 0x4da0, /*!< Polarity waits HW I2C settings */
+ TFA9912_BF_IPOMWCFC= 0x4db0, /*!< Polarity man wait cf config */
+ TFA9912_BF_IPOMWSMU= 0x4dc0, /*!< Polarity man audio mute sequence */
+ TFA9912_BF_IPOCFMER= 0x4dd0, /*!< Polarity cfma err */
+ TFA9912_BF_IPOCFMAC= 0x4de0, /*!< Polarity cfma ack */
+ TFA9912_BF_IPOCLKOOR= 0x4df0, /*!< Polarity flag_clk_out_of_range */
+ TFA9912_BF_IPOTDMER= 0x4e00, /*!< Polarity tdm error */
+ TFA9912_BF_IPOCLPL= 0x4e10, /*!< Polarity clip left */
+ TFA9912_BF_IPOCLPR= 0x4e20, /*!< Polarity clip */
+ TFA9912_BF_IPOOCPM= 0x4e30, /*!< Polarity mic ocpok */
+ TFA9912_BF_IPOLP1= 0x4e50, /*!< Polarity low power mode1 */
+ TFA9912_BF_IPOLA = 0x4e60, /*!< Polarity low amplitude detection */
+ TFA9912_BF_IPOVDDP= 0x4e70, /*!< Polarity VDDP greater than VBAT */
+ TFA9912_BF_IPOLTAPDET= 0x4e80, /*!< PolarityTap detected */
+ TFA9912_BF_IPOLAUDMOD= 0x4e90, /*!< PolarityAudio Mode activated */
+ TFA9912_BF_IPOLSAMMOD= 0x4ea0, /*!< PolaritySAM Mode activated */
+ TFA9912_BF_IPOLTAPMOD= 0x4eb0, /*!< Polarity Tap Mode Activated */
+ TFA9912_BF_IPOLTAPTRG= 0x4ec0, /*!< PolarityTap Comparator Trigger */
+ TFA9912_BF_BSSCR = 0x5001, /*!< Battery Safeguard attack time */
+ TFA9912_BF_BSST = 0x5023, /*!< Battery Safeguard threshold voltage level */
+ TFA9912_BF_BSSRL = 0x5061, /*!< Battery Safeguard maximum reduction */
+ TFA9912_BF_BSSRR = 0x5082, /*!< Battery Safeguard release time */
+ TFA9912_BF_BSSHY = 0x50b1, /*!< Battery Safeguard hysteresis */
+ TFA9912_BF_BSSAC = 0x50d0, /*!< Reset clipper - Auto clear */
+ TFA9912_BF_BSSR = 0x50e0, /*!< Battery voltage read out */
+ TFA9912_BF_BSSBY = 0x50f0, /*!< Bypass HW clipper */
+ TFA9912_BF_BSSS = 0x5100, /*!< Vbat prot steepness */
+ TFA9912_BF_INTSMUTE= 0x5110, /*!< Soft mute HW */
+ TFA9912_BF_CFSML = 0x5120, /*!< Soft mute FW left */
+ TFA9912_BF_CFSM = 0x5130, /*!< Soft mute FW */
+ TFA9912_BF_HPFBYPL= 0x5140, /*!< Bypass HPF left */
+ TFA9912_BF_HPFBYP= 0x5150, /*!< Bypass HPF */
+ TFA9912_BF_DPSAL = 0x5160, /*!< Enable DPSA left */
+ TFA9912_BF_DPSA = 0x5170, /*!< Enable DPSA */
+ TFA9912_BF_VOL = 0x5187, /*!< FW volume control for primary audio channel */
+ TFA9912_BF_HNDSFRCV= 0x5200, /*!< Selection receiver */
+ TFA9912_BF_CLIPCTRL= 0x5222, /*!< Clip control setting */
+ TFA9912_BF_AMPGAIN= 0x5257, /*!< Amplifier gain */
+ TFA9912_BF_SLOPEE= 0x52d0, /*!< Enables slope control */
+ TFA9912_BF_SLOPESET= 0x52e0, /*!< Slope speed setting (bin. coded) */
+ TFA9912_BF_CFTAPPAT= 0x5c07, /*!< Coolflux tap pattern */
+ TFA9912_BF_TAPDBGINFO= 0x5c83, /*!< Reserved */
+ TFA9912_BF_TATPSTAT1= 0x5d0f, /*!< Tap Status 1 from CF FW */
+ TFA9912_BF_TCOMPTHR= 0x5f03, /*!< Comparator threshold (in uV) */
+ TFA9912_BF_PGAGAIN= 0x6081, /*!< PGA gain selection */
+ TFA9912_BF_TDMSPKG= 0x6123, /*!< System gain (INPLEV 0) */
+ TFA9912_BF_LPM1LVL= 0x6505, /*!< low power mode1 detector ctrl threshold for low_audio_lvl */
+ TFA9912_BF_LPM1HLD= 0x6565, /*!< Low power mode1 detector, ctrl hold time before low audio is reckoned to be low audio */
+ TFA9912_BF_LPM1DIS= 0x65c0, /*!< low power mode1 detector control */
+ TFA9912_BF_DCDIS = 0x6630, /*!< DCDC */
+ TFA9912_BF_TDMSRCMAP= 0x6801, /*!< tdm source mapping */
+ TFA9912_BF_TDMSRCAS= 0x6821, /*!< frame a selection */
+ TFA9912_BF_TDMSRCBS= 0x6841, /*!< frame b selection */
+ TFA9912_BF_ANC1C = 0x68a0, /*!< ANC one s complement */
+ TFA9912_BF_SAMMODE= 0x6901, /*!< Sam mode */
+ TFA9912_BF_DCMCC = 0x7033, /*!< Max coil current */
+ TFA9912_BF_DCCV = 0x7071, /*!< Slope compensation current, represents LxF (inductance x frequency) value */
+ TFA9912_BF_DCIE = 0x7090, /*!< Adaptive boost mode */
+ TFA9912_BF_DCSR = 0x70a0, /*!< Soft ramp up/down */
+ TFA9912_BF_DCINSEL= 0x70c1, /*!< DCDC IIR input Selection */
+ TFA9912_BF_DCPWM = 0x70f0, /*!< DCDC PWM only mode */
+ TFA9912_BF_DCTRIP= 0x7504, /*!< Adaptive boost trip levels 1, effective only when boost_intelligent is set to 1 */
+ TFA9912_BF_DCTRIP2= 0x7554, /*!< Adaptive boost trip level 2, effective only when boost_intelligent is set to 1 */
+ TFA9912_BF_DCTRIPT= 0x75a4, /*!< Adaptive boost trip levels, effective only when boost_intelligent is set to 1 */
+ TFA9912_BF_DCVOF = 0x7635, /*!< First boost voltage level */
+ TFA9912_BF_DCVOS = 0x7695, /*!< Second boost voltage level */
+ TFA9912_BF_RST = 0x9000, /*!< Reset */
+ TFA9912_BF_DMEM = 0x9011, /*!< Target memory */
+ TFA9912_BF_AIF = 0x9030, /*!< Auto increment */
+ TFA9912_BF_CFINT = 0x9040, /*!< Interrupt - auto clear */
+ TFA9912_BF_CFCGATE= 0x9050, /*!< Coolflux clock gating disabling control */
+ TFA9912_BF_REQCMD= 0x9080, /*!< Firmware event request rpc command */
+ TFA9912_BF_REQRST= 0x9090, /*!< Firmware event request reset restart */
+ TFA9912_BF_REQMIPS= 0x90a0, /*!< Firmware event request short on mips */
+ TFA9912_BF_REQMUTED= 0x90b0, /*!< Firmware event request mute sequence ready */
+ TFA9912_BF_REQVOL= 0x90c0, /*!< Firmware event request volume ready */
+ TFA9912_BF_REQDMG= 0x90d0, /*!< Firmware event request speaker damage detected */
+ TFA9912_BF_REQCAL= 0x90e0, /*!< Firmware event request calibration completed */
+ TFA9912_BF_REQRSV= 0x90f0, /*!< Firmware event request reserved */
+ TFA9912_BF_MADD = 0x910f, /*!< Memory address */
+ TFA9912_BF_MEMA = 0x920f, /*!< Activate memory access */
+ TFA9912_BF_ERR = 0x9307, /*!< Error flags */
+ TFA9912_BF_ACKCMD= 0x9380, /*!< Firmware event acknowledge rpc command */
+ TFA9912_BF_ACKRST= 0x9390, /*!< Firmware event acknowledge reset restart */
+ TFA9912_BF_ACKMIPS= 0x93a0, /*!< Firmware event acknowledge short on mips */
+ TFA9912_BF_ACKMUTED= 0x93b0, /*!< Firmware event acknowledge mute sequence ready */
+ TFA9912_BF_ACKVOL= 0x93c0, /*!< Firmware event acknowledge volume ready */
+ TFA9912_BF_ACKDMG= 0x93d0, /*!< Firmware event acknowledge speaker damage detected */
+ TFA9912_BF_ACKCAL= 0x93e0, /*!< Firmware event acknowledge calibration completed */
+ TFA9912_BF_ACKRSV= 0x93f0, /*!< Firmware event acknowledge reserved */
+ TFA9912_BF_MTPK = 0xa107, /*!< MTP KEY2 register */
+ TFA9912_BF_KEY1LOCKED= 0xa200, /*!< Indicates KEY1 is locked */
+ TFA9912_BF_KEY2LOCKED= 0xa210, /*!< Indicates KEY2 is locked */
+ TFA9912_BF_CIMTP = 0xa360, /*!< Start copying data from I2C mtp registers to mtp */
+ TFA9912_BF_MTPRDMSB= 0xa50f, /*!< MSB word of MTP manual read data */
+ TFA9912_BF_MTPRDLSB= 0xa60f, /*!< LSB word of MTP manual read data */
+ TFA9912_BF_EXTTS = 0xb108, /*!< External temperature (C) */
+ TFA9912_BF_TROS = 0xb190, /*!< Select temp Speaker calibration */
+ TFA9912_BF_SWPROFIL= 0xee0f, /*!< Software profile data */
+ TFA9912_BF_SWVSTEP= 0xef0f, /*!< Software vstep information */
+ TFA9912_BF_MTPOTC= 0xf000, /*!< Calibration schedule */
+ TFA9912_BF_MTPEX = 0xf010, /*!< Calibration Ron executed */
+ TFA9912_BF_DCMCCAPI= 0xf020, /*!< Calibration current limit DCDC */
+ TFA9912_BF_DCMCCSB= 0xf030, /*!< Sign bit for delta calibration current limit DCDC */
+ TFA9912_BF_DCMCCCL= 0xf042, /*!< Calibration delta current limit DCDC */
+ TFA9912_BF_USERDEF= 0xf078, /*!< Reserved space for allowing customer to store speaker information */
+ TFA9912_BF_R25C = 0xf40f, /*!< Ron resistance of speaker coil */
+} Tfa9912BfEnumList_t;
+#define TFA9912_NAMETABLE static tfaBfName_t Tfa9912DatasheetNames[]= {\
+ { 0x0, "PWDN"}, /* Powerdown selection , */\
+ { 0x10, "I2CR"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "CFE"}, /* Enable CoolFlux , */\
+ { 0x30, "AMPE"}, /* Enables the Amplifier , */\
+ { 0x40, "DCA"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "SBSL"}, /* Coolflux configured , */\
+ { 0x60, "AMPC"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "INTP"}, /* Interrupt config , */\
+ { 0x90, "FSSSEL"}, /* Audio sample reference , */\
+ { 0xb0, "BYPOCP"}, /* Bypass OCP , */\
+ { 0xc0, "TSTOCP"}, /* OCP testing control , */\
+ { 0x101, "AMPINSEL"}, /* Amplifier input selection , */\
+ { 0x120, "MANSCONF"}, /* I2C configured , */\
+ { 0x130, "MANCOLD"}, /* Execute cold start , */\
+ { 0x140, "MANAOOSC"}, /* Internal osc off at PWDN , */\
+ { 0x150, "MANROBOD"}, /* Reaction on BOD , */\
+ { 0x160, "BODE"}, /* BOD Enable , */\
+ { 0x170, "BODHYS"}, /* BOD Hysteresis , */\
+ { 0x181, "BODFILT"}, /* BOD filter , */\
+ { 0x1a1, "BODTHLVL"}, /* BOD threshold , */\
+ { 0x1d0, "MUTETO"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "RCVNS"}, /* Noise shaper selection , */\
+ { 0x1f0, "MANWDE"}, /* Watchdog enable , */\
+ { 0x203, "AUDFS"}, /* Sample rate (fs) , */\
+ { 0x240, "INPLEV"}, /* TDM output attenuation , */\
+ { 0x255, "FRACTDEL"}, /* V/I Fractional delay , */\
+ { 0x2b0, "BYPHVBF"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "TDMC"}, /* TDM Compatibility with TFA9872 , */\
+ { 0x2e0, "ENBLADC10"}, /* ADC10 Enable - I2C direct mode , */\
+ { 0x30f, "REV"}, /* Revision info , */\
+ { 0x401, "REFCKEXT"}, /* PLL external ref clock , */\
+ { 0x420, "REFCKSEL"}, /* PLL internal ref clock , */\
+ { 0x430, "ENCFCKSEL"}, /* Coolflux DSP clock scaling, low power mode , */\
+ { 0x441, "CFCKSEL"}, /* Coolflux DSP clock scaler selection for low power mode, */\
+ { 0x460, "TDMINFSEL"}, /* TDM clock selection , */\
+ { 0x470, "DISBLAUTOCLKSEL"}, /* Disable Automatic dsp clock source selection , */\
+ { 0x480, "SELCLKSRC"}, /* I2C selection of DSP clock when auto select is disabled, */\
+ { 0x490, "SELTIMSRC"}, /* I2C selection of Watchdog and Timer clock , */\
+ { 0x500, "SSLEFTE"}, /* , */\
+ { 0x510, "SPKSSEN"}, /* Enable speaker path , */\
+ { 0x520, "VSLEFTE"}, /* , */\
+ { 0x530, "VSRIGHTE"}, /* Voltage sense , */\
+ { 0x540, "CSLEFTE"}, /* , */\
+ { 0x550, "CSRIGHTE"}, /* Current sense , */\
+ { 0x560, "SSPDME"}, /* Sub-system PDM , */\
+ { 0x570, "PGALE"}, /* Enable PGA chop clock for left channel , */\
+ { 0x580, "PGARE"}, /* Enable PGA chop clock , */\
+ { 0x590, "SSTDME"}, /* Sub-system TDM , */\
+ { 0x5a0, "SSPBSTE"}, /* Sub-system boost , */\
+ { 0x5b0, "SSADCE"}, /* Sub-system ADC , */\
+ { 0x5c0, "SSFAIME"}, /* Sub-system FAIM , */\
+ { 0x5d0, "SSCFTIME"}, /* CF Sub-system timer , */\
+ { 0x5e0, "SSCFWDTE"}, /* CF Sub-system WDT , */\
+ { 0x5f0, "FAIMVBGOVRRL"}, /* Over rule of vbg for FaIM access , */\
+ { 0x600, "SAMSPKSEL"}, /* Input selection for TAP/SAM , */\
+ { 0x610, "PDM2IISEN"}, /* PDM2IIS Bridge enable , */\
+ { 0x620, "TAPRSTBYPASS"}, /* Tap decimator reset bypass - Bypass the decimator reset from tapdec, */\
+ { 0x631, "CARDECISEL0"}, /* Cardec input 0 sel , */\
+ { 0x651, "CARDECISEL1"}, /* Cardec input sel , */\
+ { 0x670, "TAPDECSEL"}, /* Select TAP/Cardec for TAP , */\
+ { 0x680, "COMPCOUNT"}, /* Comparator o/p filter selection , */\
+ { 0x691, "STARTUPMODE"}, /* Startup Mode Selection , */\
+ { 0x6b0, "AUTOTAP"}, /* Enable auto tap switching , */\
+ { 0x6c1, "COMPINITIME"}, /* Comparator initialization time to be used in Tap Machine, */\
+ { 0x6e1, "ANAPINITIME"}, /* Analog initialization time to be used in Tap Machine, */\
+ { 0x707, "CCHKTH"}, /* Clock check Higher Threshold , */\
+ { 0x787, "CCHKTL"}, /* Clock check Higher Threshold , */\
+ { 0x802, "AMPOCRT"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x832, "AMPTCRR"}, /* Amplifier on-off criteria for tap mode entry , */\
+ { 0xd00, "STGS"}, /* PDM side tone gain selector , */\
+ { 0xd18, "STGAIN"}, /* Side tone gain , */\
+ { 0xda0, "STSMUTE"}, /* Side tone soft mute , */\
+ { 0xdb0, "ST1C"}, /* side tone one s complement , */\
+ { 0xe80, "CMFBEL"}, /* CMFB enable left , */\
+ { 0x1000, "VDDS"}, /* POR , */\
+ { 0x1010, "PLLS"}, /* PLL lock , */\
+ { 0x1020, "OTDS"}, /* OTP alarm , */\
+ { 0x1030, "OVDS"}, /* OVP alarm , */\
+ { 0x1040, "UVDS"}, /* UVP alarm , */\
+ { 0x1050, "CLKS"}, /* Clocks stable , */\
+ { 0x1060, "MTPB"}, /* MTP busy , */\
+ { 0x1070, "NOCLK"}, /* Lost clock , */\
+ { 0x1090, "ACS"}, /* Cold Start , */\
+ { 0x10a0, "SWS"}, /* Amplifier engage , */\
+ { 0x10b0, "WDS"}, /* Watchdog , */\
+ { 0x10c0, "AMPS"}, /* Amplifier enable , */\
+ { 0x10d0, "AREFS"}, /* References enable , */\
+ { 0x10e0, "ADCCR"}, /* Control ADC , */\
+ { 0x10f0, "BODNOK"}, /* BOD , */\
+ { 0x1100, "DCIL"}, /* DCDC current limiting , */\
+ { 0x1110, "DCDCA"}, /* DCDC active , */\
+ { 0x1120, "DCOCPOK"}, /* DCDC OCP nmos , */\
+ { 0x1130, "DCPEAKCUR"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "DCHVBAT"}, /* DCDC level 1x , */\
+ { 0x1150, "DCH114"}, /* DCDC level 1.14x , */\
+ { 0x1160, "DCH107"}, /* DCDC level 1.07x , */\
+ { 0x1170, "STMUTEB"}, /* side tone (un)mute busy , */\
+ { 0x1180, "STMUTE"}, /* side tone mute state , */\
+ { 0x1190, "TDMLUTER"}, /* TDM LUT error , */\
+ { 0x11a2, "TDMSTAT"}, /* TDM status bits , */\
+ { 0x11d0, "TDMERR"}, /* TDM error , */\
+ { 0x11e0, "HAPTIC"}, /* Status haptic driver , */\
+ { 0x1300, "OCPOAP"}, /* OCPOK pmos A , */\
+ { 0x1310, "OCPOAN"}, /* OCPOK nmos A , */\
+ { 0x1320, "OCPOBP"}, /* OCPOK pmos B , */\
+ { 0x1330, "OCPOBN"}, /* OCPOK nmos B , */\
+ { 0x1340, "CLIPAH"}, /* Clipping A to Vddp , */\
+ { 0x1350, "CLIPAL"}, /* Clipping A to gnd , */\
+ { 0x1360, "CLIPBH"}, /* Clipping B to Vddp , */\
+ { 0x1370, "CLIPBL"}, /* Clipping B to gnd , */\
+ { 0x1380, "OCDS"}, /* OCP amplifier , */\
+ { 0x1390, "CLIPS"}, /* Amplifier clipping , */\
+ { 0x13a0, "TCMPTRG"}, /* Status Tap comparator triggered , */\
+ { 0x13b0, "TAPDET"}, /* Status Tap detected , */\
+ { 0x13c0, "MANWAIT1"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "MANWAIT2"}, /* Wait CF config , */\
+ { 0x13e0, "MANMUTE"}, /* Audio mute sequence , */\
+ { 0x13f0, "MANOPER"}, /* Operating state , */\
+ { 0x1400, "SPKSL"}, /* Left speaker status , */\
+ { 0x1410, "SPKS"}, /* Speaker status , */\
+ { 0x1420, "CLKOOR"}, /* External clock status , */\
+ { 0x1433, "MANSTATE"}, /* Device manager status , */\
+ { 0x1471, "DCMODE"}, /* DCDC mode status bits , */\
+ { 0x1490, "DSPCLKSRC"}, /* DSP clock source selected by manager , */\
+ { 0x14a1, "STARTUPMODSTAT"}, /* Startup Mode Selected by Manager(Read Only) , */\
+ { 0x14c3, "TSPMSTATE"}, /* Tap Machine State , */\
+ { 0x1509, "BATS"}, /* Battery voltage (V) , */\
+ { 0x1608, "TEMPS"}, /* IC Temperature (C) , */\
+ { 0x1709, "VDDPS"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x17a0, "DCILCF"}, /* DCDC current limiting for DSP , */\
+ { 0x2000, "TDMUC"}, /* Mode setting , */\
+ { 0x2011, "DIO4SEL"}, /* DIO4 Input selection , */\
+ { 0x2040, "TDME"}, /* Enable TDM interface , */\
+ { 0x2050, "TDMMODE"}, /* Slave/master , */\
+ { 0x2060, "TDMCLINV"}, /* Reception data to BCK clock , */\
+ { 0x2073, "TDMFSLN"}, /* FS length , */\
+ { 0x20b0, "TDMFSPOL"}, /* FS polarity , */\
+ { 0x20c3, "TDMNBCK"}, /* N-BCK's in FS , */\
+ { 0x2103, "TDMSLOTS"}, /* N-slots in Frame , */\
+ { 0x2144, "TDMSLLN"}, /* N-bits in slot , */\
+ { 0x2194, "TDMBRMG"}, /* N-bits remaining , */\
+ { 0x21e0, "TDMDEL"}, /* data delay to FS , */\
+ { 0x21f0, "TDMADJ"}, /* data adjustment , */\
+ { 0x2201, "TDMOOMP"}, /* Received audio compression , */\
+ { 0x2224, "TDMSSIZE"}, /* Sample size per slot , */\
+ { 0x2271, "TDMTXDFO"}, /* Format unused bits in a slot , */\
+ { 0x2291, "TDMTXUS0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "TDMTXUS1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "TDMTXUS2"}, /* Format unused slots DIO2 , */\
+ { 0x2300, "TDMGIE"}, /* Control gain (channel in 0) , */\
+ { 0x2310, "TDMDCE"}, /* Control audio left (channel in 1 ) , */\
+ { 0x2320, "TDMSPKE"}, /* Control audio right (channel in 2 ) , */\
+ { 0x2330, "TDMCSE"}, /* Current sense , */\
+ { 0x2340, "TDMVSE"}, /* Voltage sense , */\
+ { 0x2350, "TDMGOE"}, /* DSP Gainout , */\
+ { 0x2360, "TDMCF2E"}, /* DSP 2 , */\
+ { 0x2370, "TDMCF3E"}, /* DSP 3 , */\
+ { 0x2380, "TDMCFE"}, /* DSP , */\
+ { 0x2390, "TDMES6"}, /* Loopback of Audio left (channel 1) , */\
+ { 0x23a0, "TDMES7"}, /* Loopback of Audio right (channel 2) , */\
+ { 0x23b0, "TDMCF4E"}, /* AEC ref right control , */\
+ { 0x23c0, "TDMPD1E"}, /* PDM 1 control , */\
+ { 0x23d0, "TDMPD2E"}, /* PDM 2 control , */\
+ { 0x2401, "TDMGIN"}, /* IO gainin , */\
+ { 0x2421, "TDMLIO"}, /* IO audio left , */\
+ { 0x2441, "TDMRIO"}, /* IO audio right , */\
+ { 0x2461, "TDMCSIO"}, /* IO Current Sense , */\
+ { 0x2481, "TDMVSIO"}, /* IO voltage sense , */\
+ { 0x24a1, "TDMGOIO"}, /* IO gain out , */\
+ { 0x24c1, "TDMCFIO2"}, /* IO DSP 2 , */\
+ { 0x24e1, "TDMCFIO3"}, /* IO DSP 3 , */\
+ { 0x2501, "TDMCFIO"}, /* IO DSP , */\
+ { 0x2521, "TDMLPB6"}, /* IO Source 6 , */\
+ { 0x2541, "TDMLPB7"}, /* IO Source 7 , */\
+ { 0x2603, "TDMGS"}, /* Control gainin , */\
+ { 0x2643, "TDMDCS"}, /* tdm slot for audio left (channel 1) , */\
+ { 0x2683, "TDMSPKS"}, /* tdm slot for audio right (channel 2) , */\
+ { 0x26c3, "TDMCSS"}, /* Slot Position of Current Sense Out , */\
+ { 0x2703, "TDMVSS"}, /* Slot Position of Voltage sense , */\
+ { 0x2743, "TDMCGOS"}, /* Slot Position of GAIN out , */\
+ { 0x2783, "TDMCF2S"}, /* Slot Position DSPout2 , */\
+ { 0x27c3, "TDMCF3S"}, /* Slot Position DSPout3 , */\
+ { 0x2803, "TDMCFS"}, /* Slot Position of DSPout , */\
+ { 0x2843, "TDMEDAT6S"}, /* Slot Position of loopback channel left , */\
+ { 0x2883, "TDMEDAT7S"}, /* Slot Position of loopback channel right , */\
+ { 0x2901, "TDMTXUS3"}, /* Format unused slots D3 , */\
+ { 0x3100, "PDMSM"}, /* PDM control , */\
+ { 0x3110, "PDMSTSEL"}, /* PDM Decimator input selection , */\
+ { 0x3120, "PDMSTENBL"}, /* Side tone input enable , */\
+ { 0x3130, "PDMLSEL"}, /* PDM data selection for left channel during PDM direct mode, */\
+ { 0x3140, "PDMRSEL"}, /* PDM data selection for right channel during PDM direct mode, */\
+ { 0x3150, "MICVDDE"}, /* Enable MICVDD , */\
+ { 0x3201, "PDMCLRAT"}, /* PDM BCK/Fs ratio , */\
+ { 0x3223, "PDMGAIN"}, /* PDM gain , */\
+ { 0x3263, "PDMOSEL"}, /* PDM output selection - RE/FE data combination , */\
+ { 0x32a0, "SELCFHAPD"}, /* Select the source for haptic data output (not for customer), */\
+ { 0x4000, "ISTVDDS"}, /* Status POR , */\
+ { 0x4010, "ISTPLLS"}, /* Status PLL lock , */\
+ { 0x4020, "ISTOTDS"}, /* Status OTP alarm , */\
+ { 0x4030, "ISTOVDS"}, /* Status OVP alarm , */\
+ { 0x4040, "ISTUVDS"}, /* Status UVP alarm , */\
+ { 0x4050, "ISTCLKS"}, /* Status clocks stable , */\
+ { 0x4060, "ISTMTPB"}, /* Status MTP busy , */\
+ { 0x4070, "ISTNOCLK"}, /* Status lost clock , */\
+ { 0x4080, "ISTSPKS"}, /* Status speaker error , */\
+ { 0x4090, "ISTACS"}, /* Status cold start , */\
+ { 0x40a0, "ISTSWS"}, /* Status amplifier engage , */\
+ { 0x40b0, "ISTWDS"}, /* Status watchdog , */\
+ { 0x40c0, "ISTAMPS"}, /* Status amplifier enable , */\
+ { 0x40d0, "ISTAREFS"}, /* Status Ref enable , */\
+ { 0x40e0, "ISTADCCR"}, /* Status Control ADC , */\
+ { 0x40f0, "ISTBODNOK"}, /* Status BOD , */\
+ { 0x4100, "ISTBSTCU"}, /* Status DCDC current limiting , */\
+ { 0x4110, "ISTBSTHI"}, /* Status DCDC active , */\
+ { 0x4120, "ISTBSTOC"}, /* Status DCDC OCP , */\
+ { 0x4130, "ISTBSTPKCUR"}, /* Status bst peakcur , */\
+ { 0x4140, "ISTBSTVC"}, /* Status DCDC level 1x , */\
+ { 0x4150, "ISTBST86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "ISTBST93"}, /* Status DCDC level 1.07x , */\
+ { 0x4170, "ISTRCVLD"}, /* Status rcvldop ready , */\
+ { 0x4180, "ISTOCPL"}, /* Status ocp alarm left , */\
+ { 0x4190, "ISTOCPR"}, /* Status ocp alarm , */\
+ { 0x41a0, "ISTMWSRC"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "ISTMWCFC"}, /* Status waits CF config , */\
+ { 0x41c0, "ISTMWSMU"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "ISTCFMER"}, /* Status cfma error , */\
+ { 0x41e0, "ISTCFMAC"}, /* Status cfma ack , */\
+ { 0x41f0, "ISTCLKOOR"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "ISTTDMER"}, /* Status tdm error , */\
+ { 0x4210, "ISTCLPL"}, /* Status clip left , */\
+ { 0x4220, "ISTCLPR"}, /* Status clip , */\
+ { 0x4230, "ISTOCPM"}, /* Status mic ocpok , */\
+ { 0x4250, "ISTLP1"}, /* Status low power mode1 , */\
+ { 0x4260, "ISTLA"}, /* Status low amplitude detection , */\
+ { 0x4270, "ISTVDDP"}, /* Status VDDP greater than VBAT , */\
+ { 0x4280, "ISTTAPDET"}, /* Status Tap detected , */\
+ { 0x4290, "ISTAUDMOD"}, /* Status Audio Mode activated , */\
+ { 0x42a0, "ISTSAMMOD"}, /* Status SAM Mode activated , */\
+ { 0x42b0, "ISTTAPMOD"}, /* Status Tap Mode Activated , */\
+ { 0x42c0, "ISTTAPTRG"}, /* Status Tap comparator triggered , */\
+ { 0x4400, "ICLVDDS"}, /* Clear POR , */\
+ { 0x4410, "ICLPLLS"}, /* Clear PLL lock , */\
+ { 0x4420, "ICLOTDS"}, /* Clear OTP alarm , */\
+ { 0x4430, "ICLOVDS"}, /* Clear OVP alarm , */\
+ { 0x4440, "ICLUVDS"}, /* Clear UVP alarm , */\
+ { 0x4450, "ICLCLKS"}, /* Clear clocks stable , */\
+ { 0x4460, "ICLMTPB"}, /* Clear mtp busy , */\
+ { 0x4470, "ICLNOCLK"}, /* Clear lost clk , */\
+ { 0x4480, "ICLSPKS"}, /* Clear speaker error , */\
+ { 0x4490, "ICLACS"}, /* Clear cold started , */\
+ { 0x44a0, "ICLSWS"}, /* Clear amplifier engage , */\
+ { 0x44b0, "ICLWDS"}, /* Clear watchdog , */\
+ { 0x44c0, "ICLAMPS"}, /* Clear enbl amp , */\
+ { 0x44d0, "ICLAREFS"}, /* Clear ref enable , */\
+ { 0x44e0, "ICLADCCR"}, /* Clear control ADC , */\
+ { 0x44f0, "ICLBODNOK"}, /* Clear BOD , */\
+ { 0x4500, "ICLBSTCU"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "ICLBSTHI"}, /* Clear DCDC active , */\
+ { 0x4520, "ICLBSTOC"}, /* Clear DCDC OCP , */\
+ { 0x4530, "ICLBSTPC"}, /* Clear bst peakcur , */\
+ { 0x4540, "ICLBSTVC"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "ICLBST86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "ICLBST93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4570, "ICLRCVLD"}, /* Clear rcvldop ready , */\
+ { 0x4580, "ICLOCPL"}, /* Clear ocp alarm left , */\
+ { 0x4590, "ICLOCPR"}, /* Clear ocp alarm , */\
+ { 0x45a0, "ICLMWSRC"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "ICLMWCFC"}, /* Clear wait cf config , */\
+ { 0x45c0, "ICLMWSMU"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "ICLCFMER"}, /* Clear cfma err , */\
+ { 0x45e0, "ICLCFMAC"}, /* Clear cfma ack , */\
+ { 0x45f0, "ICLCLKOOR"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "ICLTDMER"}, /* Clear tdm error , */\
+ { 0x4610, "ICLCLPL"}, /* Clear clip left , */\
+ { 0x4620, "ICLCLP"}, /* Clear clip , */\
+ { 0x4630, "ICLOCPM"}, /* Clear mic ocpok , */\
+ { 0x4650, "ICLLP1"}, /* Clear low power mode1 , */\
+ { 0x4660, "ICLLA"}, /* Clear low amplitude detection , */\
+ { 0x4670, "ICLVDDP"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4680, "ICLTAPDET"}, /* Clear Tap detected , */\
+ { 0x4690, "ICLAUDMOD"}, /* Clear Audio Mode activated , */\
+ { 0x46a0, "ICLSAMMOD"}, /* Clear SAM Mode activated , */\
+ { 0x46b0, "ICLTAPMOD"}, /* Clear Tap Mode Activated , */\
+ { 0x46c0, "ICLTAPTRG"}, /* Clear Comparator Interrupt , */\
+ { 0x4800, "IEVDDS"}, /* Enable por , */\
+ { 0x4810, "IEPLLS"}, /* Enable pll lock , */\
+ { 0x4820, "IEOTDS"}, /* Enable OTP alarm , */\
+ { 0x4830, "IEOVDS"}, /* Enable OVP alarm , */\
+ { 0x4840, "IEUVDS"}, /* Enable UVP alarm , */\
+ { 0x4850, "IECLKS"}, /* Enable clocks stable , */\
+ { 0x4860, "IEMTPB"}, /* Enable mtp busy , */\
+ { 0x4870, "IENOCLK"}, /* Enable lost clk , */\
+ { 0x4880, "IESPKS"}, /* Enable speaker error , */\
+ { 0x4890, "IEACS"}, /* Enable cold started , */\
+ { 0x48a0, "IESWS"}, /* Enable amplifier engage , */\
+ { 0x48b0, "IEWDS"}, /* Enable watchdog , */\
+ { 0x48c0, "IEAMPS"}, /* Enable enbl amp , */\
+ { 0x48d0, "IEAREFS"}, /* Enable ref enable , */\
+ { 0x48e0, "IEADCCR"}, /* Enable Control ADC , */\
+ { 0x48f0, "IEBODNOK"}, /* Enable BOD , */\
+ { 0x4900, "IEBSTCU"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "IEBSTHI"}, /* Enable DCDC active , */\
+ { 0x4920, "IEBSTOC"}, /* Enable DCDC OCP , */\
+ { 0x4930, "IEBSTPC"}, /* Enable bst peakcur , */\
+ { 0x4940, "IEBSTVC"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "IEBST86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "IEBST93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4970, "IERCVLD"}, /* Enable rcvldop ready , */\
+ { 0x4980, "IEOCPL"}, /* Enable ocp alarm left , */\
+ { 0x4990, "IEOCPR"}, /* Enable ocp alarm , */\
+ { 0x49a0, "IEMWSRC"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "IEMWCFC"}, /* Enable man wait cf config , */\
+ { 0x49c0, "IEMWSMU"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "IECFMER"}, /* Enable cfma err , */\
+ { 0x49e0, "IECFMAC"}, /* Enable cfma ack , */\
+ { 0x49f0, "IECLKOOR"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "IETDMER"}, /* Enable tdm error , */\
+ { 0x4a10, "IECLPL"}, /* Enable clip left , */\
+ { 0x4a20, "IECLPR"}, /* Enable clip , */\
+ { 0x4a30, "IEOCPM1"}, /* Enable mic ocpok , */\
+ { 0x4a50, "IELP1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "IELA"}, /* Enable low amplitude detection , */\
+ { 0x4a70, "IEVDDP"}, /* Enable VDDP greater than VBAT , */\
+ { 0x4a80, "IETAPDET"}, /* Enable Tap detected , */\
+ { 0x4a90, "IEAUDMOD"}, /* Enable Audio Mode activated , */\
+ { 0x4aa0, "IESAMMOD"}, /* Enable SAM Mode activated , */\
+ { 0x4ab0, "IETAPMOD"}, /* Enable Tap Mode Activated , */\
+ { 0x4ac0, "IETAPTRG"}, /* Enable comparator interrupt , */\
+ { 0x4c00, "IPOVDDS"}, /* Polarity por , */\
+ { 0x4c10, "IPOPLLS"}, /* Polarity pll lock , */\
+ { 0x4c20, "IPOOTDS"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "IPOOVDS"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "IPOUVDS"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "IPOCLKS"}, /* Polarity clocks stable , */\
+ { 0x4c60, "IPOMTPB"}, /* Polarity mtp busy , */\
+ { 0x4c70, "IPONOCLK"}, /* Polarity lost clk , */\
+ { 0x4c80, "IPOSPKS"}, /* Polarity speaker error , */\
+ { 0x4c90, "IPOACS"}, /* Polarity cold started , */\
+ { 0x4ca0, "IPOSWS"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "IPOWDS"}, /* Polarity watchdog , */\
+ { 0x4cc0, "IPOAMPS"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "IPOAREFS"}, /* Polarity ref enable , */\
+ { 0x4ce0, "IPOADCCR"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "IPOBODNOK"}, /* Polarity BOD , */\
+ { 0x4d00, "IPOBSTCU"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "IPOBSTHI"}, /* Polarity DCDC active , */\
+ { 0x4d20, "IPOBSTOC"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "IPOBSTPC"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "IPOBSTVC"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "IPOBST86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "IPOBST93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d70, "IPORCVLD"}, /* Polarity rcvldop ready , */\
+ { 0x4d80, "IPOOCPL"}, /* Polarity ocp alarm left , */\
+ { 0x4d90, "IPOOCPR"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "IPOMWSRC"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "IPOMWCFC"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "IPOMWSMU"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "IPOCFMER"}, /* Polarity cfma err , */\
+ { 0x4de0, "IPOCFMAC"}, /* Polarity cfma ack , */\
+ { 0x4df0, "IPOCLKOOR"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "IPOTDMER"}, /* Polarity tdm error , */\
+ { 0x4e10, "IPOCLPL"}, /* Polarity clip left , */\
+ { 0x4e20, "IPOCLPR"}, /* Polarity clip , */\
+ { 0x4e30, "IPOOCPM"}, /* Polarity mic ocpok , */\
+ { 0x4e50, "IPOLP1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "IPOLA"}, /* Polarity low amplitude detection , */\
+ { 0x4e70, "IPOVDDP"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x4e80, "IPOLTAPDET"}, /* PolarityTap detected , */\
+ { 0x4e90, "IPOLAUDMOD"}, /* PolarityAudio Mode activated , */\
+ { 0x4ea0, "IPOLSAMMOD"}, /* PolaritySAM Mode activated , */\
+ { 0x4eb0, "IPOLTAPMOD"}, /* Polarity Tap Mode Activated , */\
+ { 0x4ec0, "IPOLTAPTRG"}, /* PolarityTap Comparator Trigger , */\
+ { 0x5001, "BSSCR"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "BSST"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "BSSRL"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5082, "BSSRR"}, /* Battery Safeguard release time , */\
+ { 0x50b1, "BSSHY"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "BSSAC"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "BSSR"}, /* Battery voltage read out , */\
+ { 0x50f0, "BSSBY"}, /* Bypass HW clipper , */\
+ { 0x5100, "BSSS"}, /* Vbat prot steepness , */\
+ { 0x5110, "INTSMUTE"}, /* Soft mute HW , */\
+ { 0x5120, "CFSML"}, /* Soft mute FW left , */\
+ { 0x5130, "CFSM"}, /* Soft mute FW , */\
+ { 0x5140, "HPFBYPL"}, /* Bypass HPF left , */\
+ { 0x5150, "HPFBYP"}, /* Bypass HPF , */\
+ { 0x5160, "DPSAL"}, /* Enable DPSA left , */\
+ { 0x5170, "DPSA"}, /* Enable DPSA , */\
+ { 0x5187, "VOL"}, /* FW volume control for primary audio channel , */\
+ { 0x5200, "HNDSFRCV"}, /* Selection receiver , */\
+ { 0x5222, "CLIPCTRL"}, /* Clip control setting , */\
+ { 0x5257, "AMPGAIN"}, /* Amplifier gain , */\
+ { 0x52d0, "SLOPEE"}, /* Enables slope control , */\
+ { 0x52e0, "SLOPESET"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5c07, "CFTAPPAT"}, /* Coolflux tap pattern , */\
+ { 0x5c83, "TAPDBGINFO"}, /* Reserved , */\
+ { 0x5d0f, "TATPSTAT1"}, /* Tap Status 1 from CF FW , */\
+ { 0x5f03, "TCOMPTHR"}, /* Comparator threshold (in uV) , */\
+ { 0x6081, "PGAGAIN"}, /* PGA gain selection , */\
+ { 0x6123, "TDMSPKG"}, /* System gain (INPLEV 0) , */\
+ { 0x6505, "LPM1LVL"}, /* low power mode1 detector ctrl threshold for low_audio_lvl , */\
+ { 0x6565, "LPM1HLD"}, /* Low power mode1 detector, ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "LPM1DIS"}, /* low power mode1 detector control , */\
+ { 0x6630, "DCDIS"}, /* DCDC , */\
+ { 0x6801, "TDMSRCMAP"}, /* tdm source mapping , */\
+ { 0x6821, "TDMSRCAS"}, /* frame a selection , */\
+ { 0x6841, "TDMSRCBS"}, /* frame b selection , */\
+ { 0x68a0, "ANC1C"}, /* ANC one s complement , */\
+ { 0x6901, "SAMMODE"}, /* Sam mode , */\
+ { 0x7033, "DCMCC"}, /* Max coil current , */\
+ { 0x7071, "DCCV"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "DCIE"}, /* Adaptive boost mode , */\
+ { 0x70a0, "DCSR"}, /* Soft ramp up/down , */\
+ { 0x70c1, "DCINSEL"}, /* DCDC IIR input Selection , */\
+ { 0x70f0, "DCPWM"}, /* DCDC PWM only mode , */\
+ { 0x7504, "DCTRIP"}, /* Adaptive boost trip levels 1, effective only when boost_intelligent is set to 1, */\
+ { 0x7554, "DCTRIP2"}, /* Adaptive boost trip level 2, effective only when boost_intelligent is set to 1, */\
+ { 0x75a4, "DCTRIPT"}, /* Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x7635, "DCVOF"}, /* First boost voltage level , */\
+ { 0x7695, "DCVOS"}, /* Second boost voltage level , */\
+ { 0x9000, "RST"}, /* Reset , */\
+ { 0x9011, "DMEM"}, /* Target memory , */\
+ { 0x9030, "AIF"}, /* Auto increment , */\
+ { 0x9040, "CFINT"}, /* Interrupt - auto clear , */\
+ { 0x9050, "CFCGATE"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "REQCMD"}, /* Firmware event request rpc command , */\
+ { 0x9090, "REQRST"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "REQMIPS"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "REQMUTED"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "REQVOL"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "REQDMG"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "REQCAL"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "REQRSV"}, /* Firmware event request reserved , */\
+ { 0x910f, "MADD"}, /* Memory address , */\
+ { 0x920f, "MEMA"}, /* Activate memory access , */\
+ { 0x9307, "ERR"}, /* Error flags , */\
+ { 0x9380, "ACKCMD"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "ACKRST"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "ACKMIPS"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "ACKMUTED"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "ACKVOL"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "ACKDMG"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "ACKCAL"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "ACKRSV"}, /* Firmware event acknowledge reserved , */\
+ { 0xa107, "MTPK"}, /* MTP KEY2 register , */\
+ { 0xa200, "KEY1LOCKED"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "KEY2LOCKED"}, /* Indicates KEY2 is locked , */\
+ { 0xa360, "CIMTP"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa50f, "MTPRDMSB"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "MTPRDLSB"}, /* LSB word of MTP manual read data , */\
+ { 0xb108, "EXTTS"}, /* External temperature (C) , */\
+ { 0xb190, "TROS"}, /* Select temp Speaker calibration , */\
+ { 0xee0f, "SWPROFIL"}, /* Software profile data , */\
+ { 0xef0f, "SWVSTEP"}, /* Software vstep information , */\
+ { 0xf000, "MTPOTC"}, /* Calibration schedule , */\
+ { 0xf010, "MTPEX"}, /* Calibration Ron executed , */\
+ { 0xf020, "DCMCCAPI"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "DCMCCSB"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "DCMCCCL"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "USERDEF"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf40f, "R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+#define TFA9912_BITNAMETABLE static tfaBfName_t Tfa9912BitNames[]= {\
+ { 0x0, "powerdown"}, /* Powerdown selection , */\
+ { 0x10, "reset"}, /* I2C Reset - Auto clear , */\
+ { 0x20, "enbl_coolflux"}, /* Enable CoolFlux , */\
+ { 0x30, "enbl_amplifier"}, /* Enables the Amplifier , */\
+ { 0x40, "enbl_boost"}, /* Activate DC-to-DC converter , */\
+ { 0x50, "coolflux_configured"}, /* Coolflux configured , */\
+ { 0x60, "sel_enbl_amplifier"}, /* CoolFlux controls amplifier , */\
+ { 0x71, "int_pad_io"}, /* Interrupt config , */\
+ { 0x90, "fs_pulse_sel"}, /* Audio sample reference , */\
+ { 0xb0, "bypass_ocp"}, /* Bypass OCP , */\
+ { 0xc0, "test_ocp"}, /* OCP testing control , */\
+ { 0x101, "vamp_sel"}, /* Amplifier input selection , */\
+ { 0x120, "src_set_configured"}, /* I2C configured , */\
+ { 0x130, "execute_cold_start"}, /* Execute cold start , */\
+ { 0x140, "enbl_fro8m_auto_off"}, /* Internal osc off at PWDN , */\
+ { 0x150, "man_enbl_brown_out"}, /* Reaction on BOD , */\
+ { 0x160, "enbl_bod"}, /* BOD Enable , */\
+ { 0x170, "enbl_bod_hyst"}, /* BOD Hysteresis , */\
+ { 0x181, "bod_delay"}, /* BOD filter , */\
+ { 0x1a1, "bod_lvlsel"}, /* BOD threshold , */\
+ { 0x1d0, "disable_mute_time_out"}, /* Time out SB mute sequence , */\
+ { 0x1e0, "pwm_sel_rcv_ns"}, /* Noise shaper selection , */\
+ { 0x1f0, "man_enbl_watchdog"}, /* Watchdog enable , */\
+ { 0x203, "audio_fs"}, /* Sample rate (fs) , */\
+ { 0x240, "input_level"}, /* TDM output attenuation , */\
+ { 0x255, "cs_frac_delay"}, /* V/I Fractional delay , */\
+ { 0x2b0, "bypass_hvbat_filter"}, /* Bypass HVBAT filter , */\
+ { 0x2c0, "tdm_tfa9872_compatible"}, /* TDM Compatibility with TFA9872 , */\
+ { 0x2d0, "sel_hysteresis"}, /* Select hysteresis for clock range detector , */\
+ { 0x2e0, "enbl_adc10"}, /* ADC10 Enable - I2C direct mode , */\
+ { 0x30f, "device_rev"}, /* Revision info , */\
+ { 0x401, "pll_clkin_sel"}, /* PLL external ref clock , */\
+ { 0x420, "pll_clkin_sel_osc"}, /* PLL internal ref clock , */\
+ { 0x430, "cf_clock_scaling"}, /* Coolflux DSP clock scaling, low power mode , */\
+ { 0x441, "sel_cf_clock"}, /* Coolflux DSP clock scaler selection for low power mode, */\
+ { 0x460, "tdm_intf_sel"}, /* TDM clock selection , */\
+ { 0x470, "disable_auto_sel_refclk"}, /* Disable Automatic dsp clock source selection , */\
+ { 0x480, "sel_clk_src"}, /* I2C selection of DSP clock when auto select is disabled, */\
+ { 0x490, "wdt_tim_clk_src"}, /* I2C selection of Watchdog and Timer clock , */\
+ { 0x510, "enbl_spkr_ss"}, /* Enable speaker path , */\
+ { 0x530, "enbl_volsense"}, /* Voltage sense , */\
+ { 0x550, "enbl_cursense"}, /* Current sense , */\
+ { 0x560, "enbl_pdm_ss"}, /* Sub-system PDM , */\
+ { 0x580, "enbl_pga_chop"}, /* Enable PGA chop clock , */\
+ { 0x590, "enbl_tdm_ss"}, /* Sub-system TDM , */\
+ { 0x5a0, "enbl_bst_ss"}, /* Sub-system boost , */\
+ { 0x5b0, "enbl_adc10_ss"}, /* Sub-system ADC , */\
+ { 0x5c0, "enbl_faim_ss"}, /* Sub-system FAIM , */\
+ { 0x5d0, "enbl_tim_clk"}, /* CF Sub-system timer , */\
+ { 0x5e0, "enbl_wdt_clk"}, /* CF Sub-system WDT , */\
+ { 0x5f0, "faim_enable_vbg"}, /* Over rule of vbg for FaIM access , */\
+ { 0x600, "aux_spkr_sel"}, /* Input selection for TAP/SAM , */\
+ { 0x620, "bypass_tapdec_reset"}, /* Tap decimator reset bypass - Bypass the decimator reset from tapdec, */\
+ { 0x631, "car_dec_in_sel0"}, /* Cardec input 0 sel , */\
+ { 0x651, "car_dec_in_sel1"}, /* Cardec input sel , */\
+ { 0x670, "tapdec_sel"}, /* Select TAP/Cardec for TAP , */\
+ { 0x680, "comp_count"}, /* Comparator o/p filter selection , */\
+ { 0x691, "startup_mode"}, /* Startup Mode Selection , */\
+ { 0x6b0, "enable_auto_tap_switching"}, /* Enable auto tap switching , */\
+ { 0x6c1, "comp_init_time"}, /* Comparator initialization time to be used in Tap Machine, */\
+ { 0x6e1, "ana_init_time"}, /* Analog initialization time to be used in Tap Machine, */\
+ { 0x707, "clkchk_th_hi"}, /* Clock check Higher Threshold , */\
+ { 0x787, "clkchk_th_lo"}, /* Clock check Higher Threshold , */\
+ { 0x802, "ctrl_on2off_criterion"}, /* Amplifier on-off criteria for shutdown , */\
+ { 0x832, "ctrl_on2tap_criterion"}, /* Amplifier on-off criteria for tap mode entry , */\
+ { 0xd00, "side_tone_gain_sel"}, /* PDM side tone gain selector , */\
+ { 0xd18, "side_tone_gain"}, /* Side tone gain , */\
+ { 0xda0, "mute_side_tone"}, /* Side tone soft mute , */\
+ { 0xdb0, "side_tone_1scomplement"}, /* side tone one s complement , */\
+ { 0xe07, "ctrl_digtoana"}, /* Spare control from digital to analog , */\
+ { 0xf0f, "hidden_code"}, /* 5A6Bh, 23147d to access registers (default for engineering), */\
+ { 0x1000, "flag_por"}, /* POR , */\
+ { 0x1010, "flag_pll_lock"}, /* PLL lock , */\
+ { 0x1020, "flag_otpok"}, /* OTP alarm , */\
+ { 0x1030, "flag_ovpok"}, /* OVP alarm , */\
+ { 0x1040, "flag_uvpok"}, /* UVP alarm , */\
+ { 0x1050, "flag_clocks_stable"}, /* Clocks stable , */\
+ { 0x1060, "flag_mtp_busy"}, /* MTP busy , */\
+ { 0x1070, "flag_lost_clk"}, /* Lost clock , */\
+ { 0x1090, "flag_cold_started"}, /* Cold Start , */\
+ { 0x10a0, "flag_engage"}, /* Amplifier engage , */\
+ { 0x10b0, "flag_watchdog_reset"}, /* Watchdog , */\
+ { 0x10c0, "flag_enbl_amp"}, /* Amplifier enable , */\
+ { 0x10d0, "flag_enbl_ref"}, /* References enable , */\
+ { 0x10e0, "flag_adc10_ready"}, /* Control ADC , */\
+ { 0x10f0, "flag_bod_vddd_nok"}, /* BOD , */\
+ { 0x1100, "flag_bst_bstcur"}, /* DCDC current limiting , */\
+ { 0x1110, "flag_bst_hiz"}, /* DCDC active , */\
+ { 0x1120, "flag_bst_ocpok"}, /* DCDC OCP nmos , */\
+ { 0x1130, "flag_bst_peakcur"}, /* Indicates current is max in DC-to-DC converter , */\
+ { 0x1140, "flag_bst_voutcomp"}, /* DCDC level 1x , */\
+ { 0x1150, "flag_bst_voutcomp86"}, /* DCDC level 1.14x , */\
+ { 0x1160, "flag_bst_voutcomp93"}, /* DCDC level 1.07x , */\
+ { 0x1170, "flag_soft_mute_busy"}, /* side tone (un)mute busy , */\
+ { 0x1180, "flag_soft_mute_state"}, /* side tone mute state , */\
+ { 0x1190, "flag_tdm_lut_error"}, /* TDM LUT error , */\
+ { 0x11a2, "flag_tdm_status"}, /* TDM status bits , */\
+ { 0x11d0, "flag_tdm_error"}, /* TDM error , */\
+ { 0x1300, "flag_ocpokap"}, /* OCPOK pmos A , */\
+ { 0x1310, "flag_ocpokan"}, /* OCPOK nmos A , */\
+ { 0x1320, "flag_ocpokbp"}, /* OCPOK pmos B , */\
+ { 0x1330, "flag_ocpokbn"}, /* OCPOK nmos B , */\
+ { 0x1340, "flag_clipa_high"}, /* Clipping A to Vddp , */\
+ { 0x1350, "flag_clipa_low"}, /* Clipping A to gnd , */\
+ { 0x1360, "flag_clipb_high"}, /* Clipping B to Vddp , */\
+ { 0x1370, "flag_clipb_low"}, /* Clipping B to gnd , */\
+ { 0x1380, "flag_ocp_alarm"}, /* OCP amplifier , */\
+ { 0x1390, "flag_clip"}, /* Amplifier clipping , */\
+ { 0x13a0, "flag_tap_comp_trig"}, /* Status Tap comparator triggered , */\
+ { 0x13b0, "flag_cf_tapdetected"}, /* Status Tap detected , */\
+ { 0x13c0, "flag_man_wait_src_settings"}, /* Wait HW I2C settings , */\
+ { 0x13d0, "flag_man_wait_cf_config"}, /* Wait CF config , */\
+ { 0x13e0, "flag_man_start_mute_audio"}, /* Audio mute sequence , */\
+ { 0x1410, "flag_cf_speakererror"}, /* Speaker status , */\
+ { 0x1420, "flag_clk_out_of_range"}, /* External clock status , */\
+ { 0x1433, "man_state"}, /* Device manager status , */\
+ { 0x1471, "status_bst_mode"}, /* DCDC mode status bits , */\
+ { 0x1490, "man_dsp_clk_src"}, /* DSP clock source selected by manager , */\
+ { 0x14a1, "man_startup_mode"}, /* Startup Mode Selected by Manager(Read Only) , */\
+ { 0x14c3, "tap_machine_state"}, /* Tap Machine State , */\
+ { 0x1509, "bat_adc"}, /* Battery voltage (V) , */\
+ { 0x1608, "temp_adc"}, /* IC Temperature (C) , */\
+ { 0x1709, "vddp_adc"}, /* IC VDDP voltage ( 1023*VDDP/13 V) , */\
+ { 0x17a0, "flag_bst_bstcur_cf"}, /* DCDC current limiting for DSP , */\
+ { 0x2000, "tdm_usecase"}, /* Mode setting , */\
+ { 0x2011, "dio4_input_sel"}, /* DIO4 Input selection , */\
+ { 0x2040, "tdm_enable"}, /* Enable TDM interface , */\
+ { 0x2060, "tdm_clk_inversion"}, /* Reception data to BCK clock , */\
+ { 0x2073, "tdm_fs_ws_length"}, /* FS length , */\
+ { 0x20b0, "tdm_fs_ws_polarity"}, /* FS polarity , */\
+ { 0x20c3, "tdm_nbck"}, /* N-BCK's in FS , */\
+ { 0x2103, "tdm_nb_of_slots"}, /* N-slots in Frame , */\
+ { 0x2144, "tdm_slot_length"}, /* N-bits in slot , */\
+ { 0x2194, "tdm_bits_remaining"}, /* N-bits remaining , */\
+ { 0x21e0, "tdm_data_delay"}, /* data delay to FS , */\
+ { 0x21f0, "tdm_data_adjustment"}, /* data adjustment , */\
+ { 0x2201, "tdm_audio_sample_compression"}, /* Received audio compression , */\
+ { 0x2224, "tdm_sample_size"}, /* Sample size per slot , */\
+ { 0x2271, "tdm_txdata_format"}, /* Format unused bits in a slot , */\
+ { 0x2291, "tdm_txdata_format_unused_slot_sd0"}, /* Format unused slots GAINIO , */\
+ { 0x22b1, "tdm_txdata_format_unused_slot_sd1"}, /* Format unused slots DIO1 , */\
+ { 0x22d1, "tdm_txdata_format_unused_slot_sd2"}, /* Format unused slots DIO2 , */\
+ { 0x2300, "tdm_sink0_enable"}, /* Control gain (channel in 0) , */\
+ { 0x2310, "tdm_sink1_enable"}, /* Control audio left (channel in 1 ) , */\
+ { 0x2320, "tdm_sink2_enable"}, /* Control audio right (channel in 2 ) , */\
+ { 0x2330, "tdm_source0_enable"}, /* Current sense , */\
+ { 0x2340, "tdm_source1_enable"}, /* Voltage sense , */\
+ { 0x2350, "tdm_source2_enable"}, /* DSP Gainout , */\
+ { 0x2360, "tdm_source3_enable"}, /* DSP 2 , */\
+ { 0x2370, "tdm_source4_enable"}, /* DSP 3 , */\
+ { 0x2380, "tdm_source5_enable"}, /* DSP , */\
+ { 0x2390, "tdm_source6_enable"}, /* Loopback of Audio left (channel 1) , */\
+ { 0x23a0, "tdm_source7_enable"}, /* Loopback of Audio right (channel 2) , */\
+ { 0x2401, "tdm_sink0_io"}, /* IO gainin , */\
+ { 0x2421, "tdm_sink1_io"}, /* IO audio left , */\
+ { 0x2441, "tdm_sink2_io"}, /* IO audio right , */\
+ { 0x2461, "tdm_source0_io"}, /* IO Current Sense , */\
+ { 0x2481, "tdm_source1_io"}, /* IO voltage sense , */\
+ { 0x24a1, "tdm_source2_io"}, /* IO gain out , */\
+ { 0x24c1, "tdm_source3_io"}, /* IO DSP 2 , */\
+ { 0x24e1, "tdm_source4_io"}, /* IO DSP 3 , */\
+ { 0x2501, "tdm_source5_io"}, /* IO DSP , */\
+ { 0x2521, "tdm_source6_io"}, /* IO Source 6 , */\
+ { 0x2541, "tdm_source7_io"}, /* IO Source 7 , */\
+ { 0x2603, "tdm_sink0_slot"}, /* Control gainin , */\
+ { 0x2643, "tdm_sink1_slot"}, /* tdm slot for audio left (channel 1) , */\
+ { 0x2683, "tdm_sink2_slot"}, /* tdm slot for audio right (channel 2) , */\
+ { 0x26c3, "tdm_source0_slot"}, /* Slot Position of Current Sense Out , */\
+ { 0x2703, "tdm_source1_slot"}, /* Slot Position of Voltage sense , */\
+ { 0x2743, "tdm_source2_slot"}, /* Slot Position of GAIN out , */\
+ { 0x2783, "tdm_source3_slot"}, /* Slot Position DSPout2 , */\
+ { 0x27c3, "tdm_source4_slot"}, /* Slot Position DSPout3 , */\
+ { 0x2803, "tdm_source5_slot"}, /* Slot Position of DSPout , */\
+ { 0x2843, "tdm_source6_slot"}, /* Slot Position of loopback channel left , */\
+ { 0x2883, "tdm_source7_slot"}, /* Slot Position of loopback channel right , */\
+ { 0x2901, "tdm_txdata_format_unused_slot_sd3"}, /* Format unused slots D3 , */\
+ { 0x3100, "pdm_mode"}, /* PDM control , */\
+ { 0x3110, "pdm_input_sel"}, /* PDM Decimator input selection , */\
+ { 0x3120, "enbl_pdm_side_tone"}, /* Side tone input enable , */\
+ { 0x3201, "pdm_nbck"}, /* PDM BCK/Fs ratio , */\
+ { 0x4000, "int_out_flag_por"}, /* Status POR , */\
+ { 0x4010, "int_out_flag_pll_lock"}, /* Status PLL lock , */\
+ { 0x4020, "int_out_flag_otpok"}, /* Status OTP alarm , */\
+ { 0x4030, "int_out_flag_ovpok"}, /* Status OVP alarm , */\
+ { 0x4040, "int_out_flag_uvpok"}, /* Status UVP alarm , */\
+ { 0x4050, "int_out_flag_clocks_stable"}, /* Status clocks stable , */\
+ { 0x4060, "int_out_flag_mtp_busy"}, /* Status MTP busy , */\
+ { 0x4070, "int_out_flag_lost_clk"}, /* Status lost clock , */\
+ { 0x4080, "int_out_flag_cf_speakererror"}, /* Status speaker error , */\
+ { 0x4090, "int_out_flag_cold_started"}, /* Status cold start , */\
+ { 0x40a0, "int_out_flag_engage"}, /* Status amplifier engage , */\
+ { 0x40b0, "int_out_flag_watchdog_reset"}, /* Status watchdog , */\
+ { 0x40c0, "int_out_flag_enbl_amp"}, /* Status amplifier enable , */\
+ { 0x40d0, "int_out_flag_enbl_ref"}, /* Status Ref enable , */\
+ { 0x40e0, "int_out_flag_adc10_ready"}, /* Status Control ADC , */\
+ { 0x40f0, "int_out_flag_bod_vddd_nok"}, /* Status BOD , */\
+ { 0x4100, "int_out_flag_bst_bstcur"}, /* Status DCDC current limiting , */\
+ { 0x4110, "int_out_flag_bst_hiz"}, /* Status DCDC active , */\
+ { 0x4120, "int_out_flag_bst_ocpok"}, /* Status DCDC OCP , */\
+ { 0x4130, "int_out_flag_bst_peakcur"}, /* Status bst peakcur , */\
+ { 0x4140, "int_out_flag_bst_voutcomp"}, /* Status DCDC level 1x , */\
+ { 0x4150, "int_out_flag_bst_voutcomp86"}, /* Status DCDC level 1.14x , */\
+ { 0x4160, "int_out_flag_bst_voutcomp93"}, /* Status DCDC level 1.07x , */\
+ { 0x4190, "int_out_flag_ocp_alarm"}, /* Status ocp alarm , */\
+ { 0x41a0, "int_out_flag_man_wait_src_settings"}, /* Status Waits HW I2C settings , */\
+ { 0x41b0, "int_out_flag_man_wait_cf_config"}, /* Status waits CF config , */\
+ { 0x41c0, "int_out_flag_man_start_mute_audio"}, /* Status Audio mute sequence , */\
+ { 0x41d0, "int_out_flag_cfma_err"}, /* Status cfma error , */\
+ { 0x41e0, "int_out_flag_cfma_ack"}, /* Status cfma ack , */\
+ { 0x41f0, "int_out_flag_clk_out_of_range"}, /* Status flag_clk_out_of_range , */\
+ { 0x4200, "int_out_flag_tdm_error"}, /* Status tdm error , */\
+ { 0x4220, "int_out_flag_clip"}, /* Status clip , */\
+ { 0x4250, "int_out_flag_lp_detect_mode1"}, /* Status low power mode1 , */\
+ { 0x4260, "int_out_flag_low_amplitude"}, /* Status low amplitude detection , */\
+ { 0x4270, "int_out_flag_vddp_gt_vbat"}, /* Status VDDP greater than VBAT , */\
+ { 0x4280, "int_out_newtap"}, /* Status Tap detected , */\
+ { 0x4290, "int_out_audiomodeactive"}, /* Status Audio Mode activated , */\
+ { 0x42a0, "int_out_sammodeactive"}, /* Status SAM Mode activated , */\
+ { 0x42b0, "int_out_tapmodeactive"}, /* Status Tap Mode Activated , */\
+ { 0x42c0, "int_out_flag_tap_comp_trig"}, /* Status Tap comparator triggered , */\
+ { 0x4400, "int_in_flag_por"}, /* Clear POR , */\
+ { 0x4410, "int_in_flag_pll_lock"}, /* Clear PLL lock , */\
+ { 0x4420, "int_in_flag_otpok"}, /* Clear OTP alarm , */\
+ { 0x4430, "int_in_flag_ovpok"}, /* Clear OVP alarm , */\
+ { 0x4440, "int_in_flag_uvpok"}, /* Clear UVP alarm , */\
+ { 0x4450, "int_in_flag_clocks_stable"}, /* Clear clocks stable , */\
+ { 0x4460, "int_in_flag_mtp_busy"}, /* Clear mtp busy , */\
+ { 0x4470, "int_in_flag_lost_clk"}, /* Clear lost clk , */\
+ { 0x4480, "int_in_flag_cf_speakererror"}, /* Clear speaker error , */\
+ { 0x4490, "int_in_flag_cold_started"}, /* Clear cold started , */\
+ { 0x44a0, "int_in_flag_engage"}, /* Clear amplifier engage , */\
+ { 0x44b0, "int_in_flag_watchdog_reset"}, /* Clear watchdog , */\
+ { 0x44c0, "int_in_flag_enbl_amp"}, /* Clear enbl amp , */\
+ { 0x44d0, "int_in_flag_enbl_ref"}, /* Clear ref enable , */\
+ { 0x44e0, "int_in_flag_adc10_ready"}, /* Clear control ADC , */\
+ { 0x44f0, "int_in_flag_bod_vddd_nok"}, /* Clear BOD , */\
+ { 0x4500, "int_in_flag_bst_bstcur"}, /* Clear DCDC current limiting , */\
+ { 0x4510, "int_in_flag_bst_hiz"}, /* Clear DCDC active , */\
+ { 0x4520, "int_in_flag_bst_ocpok"}, /* Clear DCDC OCP , */\
+ { 0x4530, "int_in_flag_bst_peakcur"}, /* Clear bst peakcur , */\
+ { 0x4540, "int_in_flag_bst_voutcomp"}, /* Clear DCDC level 1x , */\
+ { 0x4550, "int_in_flag_bst_voutcomp86"}, /* Clear DCDC level 1.14x , */\
+ { 0x4560, "int_in_flag_bst_voutcomp93"}, /* Clear DCDC level 1.07x , */\
+ { 0x4590, "int_in_flag_ocp_alarm"}, /* Clear ocp alarm , */\
+ { 0x45a0, "int_in_flag_man_wait_src_settings"}, /* Clear wait HW I2C settings , */\
+ { 0x45b0, "int_in_flag_man_wait_cf_config"}, /* Clear wait cf config , */\
+ { 0x45c0, "int_in_flag_man_start_mute_audio"}, /* Clear audio mute sequence , */\
+ { 0x45d0, "int_in_flag_cfma_err"}, /* Clear cfma err , */\
+ { 0x45e0, "int_in_flag_cfma_ack"}, /* Clear cfma ack , */\
+ { 0x45f0, "int_in_flag_clk_out_of_range"}, /* Clear flag_clk_out_of_range , */\
+ { 0x4600, "int_in_flag_tdm_error"}, /* Clear tdm error , */\
+ { 0x4620, "int_in_flag_clip"}, /* Clear clip , */\
+ { 0x4650, "int_in_flag_lp_detect_mode1"}, /* Clear low power mode1 , */\
+ { 0x4660, "int_in_flag_low_amplitude"}, /* Clear low amplitude detection , */\
+ { 0x4670, "int_in_flag_vddp_gt_vbat"}, /* Clear VDDP greater then VBAT , */\
+ { 0x4680, "int_in_newtap"}, /* Clear Tap detected , */\
+ { 0x4690, "int_in_audiomodeactive"}, /* Clear Audio Mode activated , */\
+ { 0x46a0, "int_in_sammodeactive"}, /* Clear SAM Mode activated , */\
+ { 0x46b0, "int_in_tapmodeactive"}, /* Clear Tap Mode Activated , */\
+ { 0x46c0, "int_in_flag_tap_comp_trig"}, /* Clear Comparator Interrupt , */\
+ { 0x4800, "int_enable_flag_por"}, /* Enable por , */\
+ { 0x4810, "int_enable_flag_pll_lock"}, /* Enable pll lock , */\
+ { 0x4820, "int_enable_flag_otpok"}, /* Enable OTP alarm , */\
+ { 0x4830, "int_enable_flag_ovpok"}, /* Enable OVP alarm , */\
+ { 0x4840, "int_enable_flag_uvpok"}, /* Enable UVP alarm , */\
+ { 0x4850, "int_enable_flag_clocks_stable"}, /* Enable clocks stable , */\
+ { 0x4860, "int_enable_flag_mtp_busy"}, /* Enable mtp busy , */\
+ { 0x4870, "int_enable_flag_lost_clk"}, /* Enable lost clk , */\
+ { 0x4880, "int_enable_flag_cf_speakererror"}, /* Enable speaker error , */\
+ { 0x4890, "int_enable_flag_cold_started"}, /* Enable cold started , */\
+ { 0x48a0, "int_enable_flag_engage"}, /* Enable amplifier engage , */\
+ { 0x48b0, "int_enable_flag_watchdog_reset"}, /* Enable watchdog , */\
+ { 0x48c0, "int_enable_flag_enbl_amp"}, /* Enable enbl amp , */\
+ { 0x48d0, "int_enable_flag_enbl_ref"}, /* Enable ref enable , */\
+ { 0x48e0, "int_enable_flag_adc10_ready"}, /* Enable Control ADC , */\
+ { 0x48f0, "int_enable_flag_bod_vddd_nok"}, /* Enable BOD , */\
+ { 0x4900, "int_enable_flag_bst_bstcur"}, /* Enable DCDC current limiting , */\
+ { 0x4910, "int_enable_flag_bst_hiz"}, /* Enable DCDC active , */\
+ { 0x4920, "int_enable_flag_bst_ocpok"}, /* Enable DCDC OCP , */\
+ { 0x4930, "int_enable_flag_bst_peakcur"}, /* Enable bst peakcur , */\
+ { 0x4940, "int_enable_flag_bst_voutcomp"}, /* Enable DCDC level 1x , */\
+ { 0x4950, "int_enable_flag_bst_voutcomp86"}, /* Enable DCDC level 1.14x , */\
+ { 0x4960, "int_enable_flag_bst_voutcomp93"}, /* Enable DCDC level 1.07x , */\
+ { 0x4990, "int_enable_flag_ocp_alarm"}, /* Enable ocp alarm , */\
+ { 0x49a0, "int_enable_flag_man_wait_src_settings"}, /* Enable waits HW I2C settings , */\
+ { 0x49b0, "int_enable_flag_man_wait_cf_config"}, /* Enable man wait cf config , */\
+ { 0x49c0, "int_enable_flag_man_start_mute_audio"}, /* Enable man Audio mute sequence , */\
+ { 0x49d0, "int_enable_flag_cfma_err"}, /* Enable cfma err , */\
+ { 0x49e0, "int_enable_flag_cfma_ack"}, /* Enable cfma ack , */\
+ { 0x49f0, "int_enable_flag_clk_out_of_range"}, /* Enable flag_clk_out_of_range , */\
+ { 0x4a00, "int_enable_flag_tdm_error"}, /* Enable tdm error , */\
+ { 0x4a20, "int_enable_flag_clip"}, /* Enable clip , */\
+ { 0x4a50, "int_enable_flag_lp_detect_mode1"}, /* Enable low power mode1 , */\
+ { 0x4a60, "int_enable_flag_low_amplitude"}, /* Enable low amplitude detection , */\
+ { 0x4a70, "int_enable_flag_vddp_gt_vbat"}, /* Enable VDDP greater than VBAT , */\
+ { 0x4a80, "int_enable_newtap"}, /* Enable Tap detected , */\
+ { 0x4a90, "int_enable_audiomodeactive"}, /* Enable Audio Mode activated , */\
+ { 0x4aa0, "int_enable_sammodeactive"}, /* Enable SAM Mode activated , */\
+ { 0x4ab0, "int_enable_tapmodeactive"}, /* Enable Tap Mode Activated , */\
+ { 0x4ac0, "int_enable_flag_tap_comp_trig"}, /* Enable comparator interrupt , */\
+ { 0x4c00, "int_polarity_flag_por"}, /* Polarity por , */\
+ { 0x4c10, "int_polarity_flag_pll_lock"}, /* Polarity pll lock , */\
+ { 0x4c20, "int_polarity_flag_otpok"}, /* Polarity OTP alarm , */\
+ { 0x4c30, "int_polarity_flag_ovpok"}, /* Polarity OVP alarm , */\
+ { 0x4c40, "int_polarity_flag_uvpok"}, /* Polarity UVP alarm , */\
+ { 0x4c50, "int_polarity_flag_clocks_stable"}, /* Polarity clocks stable , */\
+ { 0x4c60, "int_polarity_flag_mtp_busy"}, /* Polarity mtp busy , */\
+ { 0x4c70, "int_polarity_flag_lost_clk"}, /* Polarity lost clk , */\
+ { 0x4c80, "int_polarity_flag_cf_speakererror"}, /* Polarity speaker error , */\
+ { 0x4c90, "int_polarity_flag_cold_started"}, /* Polarity cold started , */\
+ { 0x4ca0, "int_polarity_flag_engage"}, /* Polarity amplifier engage , */\
+ { 0x4cb0, "int_polarity_flag_watchdog_reset"}, /* Polarity watchdog , */\
+ { 0x4cc0, "int_polarity_flag_enbl_amp"}, /* Polarity enbl amp , */\
+ { 0x4cd0, "int_polarity_flag_enbl_ref"}, /* Polarity ref enable , */\
+ { 0x4ce0, "int_polarity_flag_adc10_ready"}, /* Polarity Control ADC , */\
+ { 0x4cf0, "int_polarity_flag_bod_vddd_nok"}, /* Polarity BOD , */\
+ { 0x4d00, "int_polarity_flag_bst_bstcur"}, /* Polarity DCDC current limiting , */\
+ { 0x4d10, "int_polarity_flag_bst_hiz"}, /* Polarity DCDC active , */\
+ { 0x4d20, "int_polarity_flag_bst_ocpok"}, /* Polarity DCDC OCP , */\
+ { 0x4d30, "int_polarity_flag_bst_peakcur"}, /* Polarity bst peakcur , */\
+ { 0x4d40, "int_polarity_flag_bst_voutcomp"}, /* Polarity DCDC level 1x , */\
+ { 0x4d50, "int_polarity_flag_bst_voutcomp86"}, /* Polarity DCDC level 1.14x , */\
+ { 0x4d60, "int_polarity_flag_bst_voutcomp93"}, /* Polarity DCDC level 1.07x , */\
+ { 0x4d90, "int_polarity_flag_ocp_alarm"}, /* Polarity ocp alarm , */\
+ { 0x4da0, "int_polarity_flag_man_wait_src_settings"}, /* Polarity waits HW I2C settings , */\
+ { 0x4db0, "int_polarity_flag_man_wait_cf_config"}, /* Polarity man wait cf config , */\
+ { 0x4dc0, "int_polarity_flag_man_start_mute_audio"}, /* Polarity man audio mute sequence , */\
+ { 0x4dd0, "int_polarity_flag_cfma_err"}, /* Polarity cfma err , */\
+ { 0x4de0, "int_polarity_flag_cfma_ack"}, /* Polarity cfma ack , */\
+ { 0x4df0, "int_polarity_flag_clk_out_of_range"}, /* Polarity flag_clk_out_of_range , */\
+ { 0x4e00, "int_polarity_flag_tdm_error"}, /* Polarity tdm error , */\
+ { 0x4e20, "int_polarity_flag_clip"}, /* Polarity clip , */\
+ { 0x4e50, "int_polarity_flag_lp_detect_mode1"}, /* Polarity low power mode1 , */\
+ { 0x4e60, "int_polarity_flag_low_amplitude"}, /* Polarity low amplitude detection , */\
+ { 0x4e70, "int_polarity_flag_vddp_gt_vbat"}, /* Polarity VDDP greater than VBAT , */\
+ { 0x4e80, "int_polarity_newtap"}, /* PolarityTap detected , */\
+ { 0x4e90, "int_polarity_audiomodeactive"}, /* PolarityAudio Mode activated , */\
+ { 0x4ea0, "int_polarity_sammodeactive"}, /* PolaritySAM Mode activated , */\
+ { 0x4eb0, "int_polarity_tapmodeactive"}, /* Polarity Tap Mode Activated , */\
+ { 0x4ec0, "int_polarity_flag_tap_comp_trig"}, /* PolarityTap Comparator Trigger , */\
+ { 0x5001, "vbat_prot_attack_time"}, /* Battery Safeguard attack time , */\
+ { 0x5023, "vbat_prot_thlevel"}, /* Battery Safeguard threshold voltage level , */\
+ { 0x5061, "vbat_prot_max_reduct"}, /* Battery Safeguard maximum reduction , */\
+ { 0x5082, "vbat_prot_release_time"}, /* Battery Safeguard release time , */\
+ { 0x50b1, "vbat_prot_hysterese"}, /* Battery Safeguard hysteresis , */\
+ { 0x50d0, "rst_min_vbat"}, /* Reset clipper - Auto clear , */\
+ { 0x50e0, "sel_vbat"}, /* Battery voltage read out , */\
+ { 0x50f0, "bypass_clipper"}, /* Bypass HW clipper , */\
+ { 0x5100, "batsense_steepness"}, /* Vbat prot steepness , */\
+ { 0x5110, "soft_mute"}, /* Soft mute HW , */\
+ { 0x5130, "cf_mute"}, /* Soft mute FW , */\
+ { 0x5150, "bypass_hp"}, /* Bypass HPF , */\
+ { 0x5170, "enbl_dpsa"}, /* Enable DPSA , */\
+ { 0x5187, "cf_volume"}, /* FW volume control for primary audio channel , */\
+ { 0x5222, "ctrl_cc"}, /* Clip control setting , */\
+ { 0x5257, "gain"}, /* Amplifier gain , */\
+ { 0x52d0, "ctrl_slopectrl"}, /* Enables slope control , */\
+ { 0x52e0, "ctrl_slope"}, /* Slope speed setting (bin. coded) , */\
+ { 0x5301, "dpsa_level"}, /* DPSA threshold levels , */\
+ { 0x5321, "dpsa_release"}, /* DPSA Release time , */\
+ { 0x5340, "clipfast"}, /* Clock selection for HW clipper for Battery Safeguard, */\
+ { 0x5350, "bypass_lp"}, /* Bypass the low power filter inside temperature sensor, */\
+ { 0x5360, "enbl_low_latency"}, /* CF low latency outputs for add module , */\
+ { 0x5400, "first_order_mode"}, /* Overrule to 1st order mode of control stage when clipping, */\
+ { 0x5410, "bypass_ctrlloop"}, /* Switch amplifier into open loop configuration , */\
+ { 0x5430, "icomp_engage"}, /* Engage of icomp , */\
+ { 0x5440, "ctrl_kickback"}, /* Prevent double pulses of output stage , */\
+ { 0x5450, "icomp_engage_overrule"}, /* To overrule the functional icomp_engage signal during validation, */\
+ { 0x5503, "ctrl_dem"}, /* Enable DEM icomp and DEM one bit dac , */\
+ { 0x5543, "ctrl_dem_mismatch"}, /* Enable DEM icomp mismatch for testing , */\
+ { 0x5582, "dpsa_drive"}, /* Drive setting (bin. coded) - I2C direct mode , */\
+ { 0x570a, "enbl_amp"}, /* Switch on the class-D power sections, each part of the analog sections can be switched on/off individually , */\
+ { 0x57b0, "enbl_engage"}, /* Enables/engage power stage and control loop - I2C direct mode, */\
+ { 0x57c0, "enbl_engage_pst"}, /* Enables/engage power stage and control loop , */\
+ { 0x5810, "hard_mute"}, /* Hard mute - PWM , */\
+ { 0x5820, "pwm_shape"}, /* PWM shape , */\
+ { 0x5844, "pwm_delay"}, /* PWM delay bits to set the delay, clock is 1/(k*2048*fs), */\
+ { 0x5890, "reclock_pwm"}, /* Reclock the pwm signal inside analog , */\
+ { 0x58a0, "reclock_voltsense"}, /* Reclock the voltage sense pwm signal , */\
+ { 0x58c0, "enbl_pwm_phase_shift"}, /* Control for pwm phase shift , */\
+ { 0x5c07, "flag_cf_tap_pattern"}, /* Coolflux tap pattern , */\
+ { 0x5c83, "tap_debug_info"}, /* Reserved , */\
+ { 0x5d0f, "tap_status_1"}, /* Tap Status 1 from CF FW , */\
+ { 0x5f03, "tap_comp_threshold"}, /* Comparator threshold (in uV) , */\
+ { 0x6081, "pga_gain_set"}, /* PGA gain selection , */\
+ { 0x60b0, "pga_lowpass_enable"}, /* Lowpass enable , */\
+ { 0x60c0, "pga_pwr_enable"}, /* PGA power enable , */\
+ { 0x60d0, "pga_switch_enable"}, /* PGA switch enable , */\
+ { 0x60e0, "pga_switch_aux_enable"}, /* Switch enable aux , */\
+ { 0x6123, "ctrl_att"}, /* System gain (INPLEV 0) , */\
+ { 0x6265, "zero_lvl"}, /* ctrl threshold for zero X-ing , */\
+ { 0x62c1, "ctrl_fb_resistor"}, /* Select amplifier feedback resistor connection , */\
+ { 0x62e1, "lownoisegain_mode"}, /* ctrl select mode , */\
+ { 0x6305, "threshold_lvl"}, /* ctrl threshold for low_audio_lvl , */\
+ { 0x6365, "hold_time"}, /* ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x6405, "lpm1_cal_offset"}, /* low power mode1 detector ctrl cal_offset from gain module , */\
+ { 0x6465, "lpm1_zero_lvl"}, /* low power mode1 detector ctrl threshold for zero X-ing , */\
+ { 0x64e1, "lpm1_mode"}, /* low power mode1 detector ctrl select mode , */\
+ { 0x6505, "lpm1_threshold_lvl"}, /* low power mode1 detector ctrl threshold for low_audio_lvl , */\
+ { 0x6565, "lpm1_hold_time"}, /* Low power mode1 detector, ctrl hold time before low audio is reckoned to be low audio, */\
+ { 0x65c0, "disable_low_power_mode"}, /* low power mode1 detector control , */\
+ { 0x6600, "dcdc_pfm20khz_limit"}, /* DCDC in PFM mode pwm mode is activated each 50us to force a pwm pulse, */\
+ { 0x6611, "dcdc_ctrl_maxzercnt"}, /* DCDC. Number of zero current flags to count before going to pfm mode, */\
+ { 0x6630, "dcdcoff_mode"}, /* DCDC , */\
+ { 0x6656, "dcdc_vbat_delta_detect"}, /* Threshold before booster is reacting on a delta Vbat (in PFM mode) by temporarily switching to PWM mode, */\
+ { 0x66c0, "dcdc_ignore_vbat"}, /* Ignore an increase on Vbat , */\
+ { 0x6700, "enbl_minion"}, /* Enables minion (small) power stage - direct ctrl , */\
+ { 0x6713, "vth_vddpvbat"}, /* select vddp-vbat thres signal , */\
+ { 0x6750, "lpen_vddpvbat"}, /* select vddp-vbat filtered vs unfiltered compare , */\
+ { 0x6761, "ctrl_rfb"}, /* Feedback resistor selection - I2C direct mode , */\
+ { 0x6801, "tdm_source_mapping"}, /* tdm source mapping , */\
+ { 0x6821, "tdm_sourcea_frame_sel"}, /* frame a selection , */\
+ { 0x6841, "tdm_sourceb_frame_sel"}, /* frame b selection , */\
+ { 0x6901, "sam_mode"}, /* Sam mode , */\
+ { 0x6931, "pdmdat_h_sel"}, /* pdm out value when pdm_clk is higth , */\
+ { 0x6951, "pdmdat_l_sel"}, /* pdm out value when pdm_clk is low , */\
+ { 0x6970, "cs_sam_set"}, /* Enable SAM input for current sense - I2C Direct Mode, */\
+ { 0x6980, "cs_adc_nortz"}, /* Return to zero for current sense ADC , */\
+ { 0x6990, "sam_spkr_sel"}, /* SAM o/p sel during SAM and audio , */\
+ { 0x6b00, "disable_engage"}, /* Disable auto engage , */\
+ { 0x6c02, "ns_hp2ln_criterion"}, /* 0..7 zeroes at ns as threshold to swap from high_power to low_noise, */\
+ { 0x6c32, "ns_ln2hp_criterion"}, /* 0..7 zeroes at ns as threshold to swap from low_noise to high_power, */\
+ { 0x6c60, "sel_clip_pwms"}, /* To select clip-flags , */\
+ { 0x6c72, "pwms_clip_lvl"}, /* To set the amount of pwm pulse that may be skipped before clip-flag is triggered. , */\
+ { 0x6ca5, "spare_out"}, /* spare_out , */\
+ { 0x6d0f, "spare_in"}, /* spare_in , */\
+ { 0x6e10, "flag_lp_detect_mode1"}, /* low power mode 1 detection , */\
+ { 0x6e20, "flag_low_amplitude"}, /* low amplitude detection , */\
+ { 0x6e30, "flag_vddp_gt_vbat"}, /* vddp greater than vbat , */\
+ { 0x7033, "boost_cur"}, /* Max coil current , */\
+ { 0x7071, "bst_slpcmplvl"}, /* Slope compensation current, represents LxF (inductance x frequency) value , */\
+ { 0x7090, "boost_intel"}, /* Adaptive boost mode , */\
+ { 0x70a0, "boost_speed"}, /* Soft ramp up/down , */\
+ { 0x70c1, "dcdc_sel"}, /* DCDC IIR input Selection , */\
+ { 0x70f0, "dcdc_pwmonly"}, /* DCDC PWM only mode , */\
+ { 0x7104, "bst_drive"}, /* Binary coded drive setting for boost converter power stage, */\
+ { 0x7151, "bst_scalecur"}, /* For testing direct control scale current , */\
+ { 0x7174, "bst_slopecur"}, /* For testing direct control slope current - I2C direct mode, */\
+ { 0x71c1, "bst_slope"}, /* Boost slope speed , */\
+ { 0x71e0, "bst_bypass_bstcur"}, /* Bypass control for boost current settings , */\
+ { 0x71f0, "bst_bypass_bstfoldback"}, /* Bypass control for boost foldback , */\
+ { 0x7200, "enbl_bst_engage"}, /* Enable power stage dcdc controller - I2C direct mode, */\
+ { 0x7210, "enbl_bst_hizcom"}, /* Enable hiz comparator - I2C direct mode , */\
+ { 0x7220, "enbl_bst_peak2avg"}, /* Enable boost peak2avg functionality , */\
+ { 0x7230, "enbl_bst_peakcur"}, /* Enable peak current - I2C direct mode , */\
+ { 0x7240, "enbl_bst_power"}, /* Enable line of the powerstage - I2C direct mode , */\
+ { 0x7250, "enbl_bst_slopecur"}, /* Enable bit of max-current dac - I2C direct mode , */\
+ { 0x7260, "enbl_bst_voutcomp"}, /* Enable vout comparators - I2C direct mode , */\
+ { 0x7270, "enbl_bst_voutcomp86"}, /* Enable vout-86 comparators - I2C direct mode , */\
+ { 0x7280, "enbl_bst_voutcomp93"}, /* Enable vout-93 comparators - I2C direct mode , */\
+ { 0x7290, "enbl_bst_windac"}, /* Enable window dac - I2C direct mode , */\
+ { 0x72a5, "bst_windac"}, /* for testing direct control windac - I2C direct mode, */\
+ { 0x7300, "boost_alg"}, /* Control for boost adaptive loop gain , */\
+ { 0x7311, "boost_loopgain"}, /* DCDC boost loopgain setting , */\
+ { 0x7331, "bst_freq"}, /* DCDC boost frequency control , */\
+ { 0x7430, "boost_track"}, /* Boost algorithm selection, effective only when boost_intelligent is set to 1, */\
+ { 0x7494, "boost_hold_time"}, /* Hold time for DCDC booster, effective only when boost_intelligent is set to 1, */\
+ { 0x74e0, "sel_dcdc_envelope_8fs"}, /* Selection of data for adaptive boost algorithm, effective only when boost_intelligent is set to 1, */\
+ { 0x74f0, "ignore_flag_voutcomp86"}, /* Ignore flag_voutcomp86 , */\
+ { 0x7504, "boost_trip_lvl_1st"}, /* Adaptive boost trip levels 1, effective only when boost_intelligent is set to 1, */\
+ { 0x7554, "boost_trip_lvl_2nd"}, /* Adaptive boost trip level 2, effective only when boost_intelligent is set to 1, */\
+ { 0x75a4, "boost_trip_lvl_track"}, /* Adaptive boost trip levels, effective only when boost_intelligent is set to 1, */\
+ { 0x7602, "track_decay"}, /* DCDC Boost decay speed after a peak value, effective only when boost_track is set to 1, */\
+ { 0x7635, "frst_boost_voltage"}, /* First boost voltage level , */\
+ { 0x7695, "scnd_boost_voltage"}, /* Second boost voltage level , */\
+ { 0x7720, "pga_test_ldo_bypass"}, /* bypass internal PGA LDO , */\
+ { 0x8001, "sel_clk_cs"}, /* Current sense clock duty cycle control , */\
+ { 0x8021, "micadc_speed"}, /* Current sense clock for MiCADC selection - 32/44.1/48 KHz Fs band only, */\
+ { 0x8050, "cs_gain_control"}, /* Current sense gain control , */\
+ { 0x8060, "cs_bypass_gc"}, /* Bypasses the CS gain correction , */\
+ { 0x8087, "cs_gain"}, /* Current sense gain , */\
+ { 0x8200, "enbl_cmfb"}, /* Current sense common mode feedback control , */\
+ { 0x8210, "invertpwm"}, /* Current sense common mode feedback pwm invert control, */\
+ { 0x8222, "cmfb_gain"}, /* Current sense common mode feedback control gain , */\
+ { 0x8256, "cmfb_offset"}, /* Current sense common mode feedback control offset , */\
+ { 0x8305, "cs_ktemp"}, /* First order temperature compensation coefficient , */\
+ { 0x8364, "cs_ktemp2"}, /* Second order temperature compensation coefficient , */\
+ { 0x8400, "cs_adc_bsoinv"}, /* Bitstream inversion for current sense ADC , */\
+ { 0x8421, "cs_adc_hifreq"}, /* Frequency mode current sense ADC , */\
+ { 0x8453, "cs_adc_offset"}, /* Micadc ADC offset setting , */\
+ { 0x8490, "cs_adc_slowdel"}, /* Select delay for current sense ADC (internal decision circuitry), */\
+ { 0x84a4, "cs_adc_gain"}, /* Gain setting for current sense ADC (two's complement), */\
+ { 0x8500, "cs_resonator_enable"}, /* Enable for resonator to improve SRN , */\
+ { 0x8510, "cs_classd_tran_skip"}, /* Skip current sense connection during a classD amplifier transition, */\
+ { 0x8530, "cs_inn_short"}, /* Short current sense negative to common mode , */\
+ { 0x8540, "cs_inp_short"}, /* Short current sense positive to common mode , */\
+ { 0x8550, "cs_ldo_bypass"}, /* Bypass current sense LDO , */\
+ { 0x8560, "cs_ldo_pulldown"}, /* Pull down current sense LDO, only valid if left_enbl_cs_ldo is high, */\
+ { 0x8574, "cs_ldo_voset"}, /* Current sense LDO voltage level setting (two's complement), */\
+ { 0x8700, "enbl_cs_adc"}, /* Enable current sense ADC - I2C direct mode , */\
+ { 0x8710, "enbl_cs_inn1"}, /* Enable connection of current sense negative1 - I2C direct mode, */\
+ { 0x8720, "enbl_cs_inn2"}, /* Enable connection of current sense negative2 - I2C direct mode, */\
+ { 0x8730, "enbl_cs_inp1"}, /* Enable connection of current sense positive1 , */\
+ { 0x8740, "enbl_cs_inp2"}, /* Enable connection of current sense positive2 - I2C direct mode, */\
+ { 0x8750, "enbl_cs_ldo"}, /* Enable current sense LDO - I2C direct mode , */\
+ { 0x8760, "enbl_cs_nofloating_n"}, /* Connect current sense negative to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8770, "enbl_cs_nofloating_p"}, /* Connect current sense positive to gnda at transitions of booster or classd amplifiers. Otherwise floating (0), */\
+ { 0x8780, "enbl_cs_vbatldo"}, /* Enable of current sense LDO -- I2C direct mode , */\
+ { 0x8800, "volsense_pwm_sel"}, /* Voltage sense PWM source selection control , */\
+ { 0x8810, "vol_cur_sense_dc_offset"}, /* voltage and current sense decimator offset control, */\
+ { 0x8902, "cursense_comp_delay"}, /* To align compensation signal with current sense signal, */\
+ { 0x8930, "cursense_comp_sign"}, /* To change polarity of compensation for current sense compensation, */\
+ { 0x8940, "enbl_cursense_comp"}, /* To enable current sense compensation , */\
+ { 0x9000, "cf_rst_dsp"}, /* Reset , */\
+ { 0x9011, "cf_dmem"}, /* Target memory , */\
+ { 0x9030, "cf_aif"}, /* Auto increment , */\
+ { 0x9040, "cf_int"}, /* Interrupt - auto clear , */\
+ { 0x9050, "cf_cgate_off"}, /* Coolflux clock gating disabling control , */\
+ { 0x9080, "cf_req_cmd"}, /* Firmware event request rpc command , */\
+ { 0x9090, "cf_req_reset"}, /* Firmware event request reset restart , */\
+ { 0x90a0, "cf_req_mips"}, /* Firmware event request short on mips , */\
+ { 0x90b0, "cf_req_mute_ready"}, /* Firmware event request mute sequence ready , */\
+ { 0x90c0, "cf_req_volume_ready"}, /* Firmware event request volume ready , */\
+ { 0x90d0, "cf_req_damage"}, /* Firmware event request speaker damage detected , */\
+ { 0x90e0, "cf_req_calibrate_ready"}, /* Firmware event request calibration completed , */\
+ { 0x90f0, "cf_req_reserved"}, /* Firmware event request reserved , */\
+ { 0x910f, "cf_madd"}, /* Memory address , */\
+ { 0x920f, "cf_mema"}, /* Activate memory access , */\
+ { 0x9307, "cf_err"}, /* Error flags , */\
+ { 0x9380, "cf_ack_cmd"}, /* Firmware event acknowledge rpc command , */\
+ { 0x9390, "cf_ack_reset"}, /* Firmware event acknowledge reset restart , */\
+ { 0x93a0, "cf_ack_mips"}, /* Firmware event acknowledge short on mips , */\
+ { 0x93b0, "cf_ack_mute_ready"}, /* Firmware event acknowledge mute sequence ready , */\
+ { 0x93c0, "cf_ack_volume_ready"}, /* Firmware event acknowledge volume ready , */\
+ { 0x93d0, "cf_ack_damage"}, /* Firmware event acknowledge speaker damage detected, */\
+ { 0x93e0, "cf_ack_calibrate_ready"}, /* Firmware event acknowledge calibration completed , */\
+ { 0x93f0, "cf_ack_reserved"}, /* Firmware event acknowledge reserved , */\
+ { 0xa007, "mtpkey1"}, /* 5Ah, 90d To access KEY1_Protected registers (Default for engineering), */\
+ { 0xa107, "mtpkey2"}, /* MTP KEY2 register , */\
+ { 0xa200, "key01_locked"}, /* Indicates KEY1 is locked , */\
+ { 0xa210, "key02_locked"}, /* Indicates KEY2 is locked , */\
+ { 0xa302, "mtp_man_address_in"}, /* MTP address from I2C register for read/writing mtp in manual single word mode, */\
+ { 0xa330, "man_copy_mtp_to_iic"}, /* Start copying single word from mtp to I2C mtp register, */\
+ { 0xa340, "man_copy_iic_to_mtp"}, /* Start copying single word from I2C mtp register to mtp, */\
+ { 0xa350, "auto_copy_mtp_to_iic"}, /* Start copying all the data from mtp to I2C mtp registers, */\
+ { 0xa360, "auto_copy_iic_to_mtp"}, /* Start copying data from I2C mtp registers to mtp , */\
+ { 0xa400, "faim_set_clkws"}, /* Sets the FaIM controller clock wait state register, */\
+ { 0xa410, "faim_sel_evenrows"}, /* All even rows of the FaIM are selected, active high, */\
+ { 0xa420, "faim_sel_oddrows"}, /* All odd rows of the FaIM are selected, all rows in combination with sel_evenrows, */\
+ { 0xa430, "faim_program_only"}, /* Skip the erase access at wr_faim command (write-program-marginread), */\
+ { 0xa440, "faim_erase_only"}, /* Skip the program access at wr_faim command (write-erase-marginread), */\
+ { 0xa50f, "mtp_man_data_out_msb"}, /* MSB word of MTP manual read data , */\
+ { 0xa60f, "mtp_man_data_out_lsb"}, /* LSB word of MTP manual read data , */\
+ { 0xa70f, "mtp_man_data_in_msb"}, /* MSB word of write data for MTP manual write , */\
+ { 0xa80f, "mtp_man_data_in_lsb"}, /* LSB word of write data for MTP manual write , */\
+ { 0xb010, "bypass_ocpcounter"}, /* Bypass OCP Counter , */\
+ { 0xb020, "bypass_glitchfilter"}, /* Bypass glitch filter , */\
+ { 0xb030, "bypass_ovp"}, /* Bypass OVP , */\
+ { 0xb040, "bypass_uvp"}, /* Bypass UVP , */\
+ { 0xb050, "bypass_otp"}, /* Bypass OTP , */\
+ { 0xb060, "bypass_lost_clk"}, /* Bypass lost clock detector , */\
+ { 0xb070, "ctrl_vpalarm"}, /* vpalarm (uvp ovp handling) , */\
+ { 0xb087, "ocp_threshold"}, /* OCP threshold level , */\
+ { 0xb108, "ext_temp"}, /* External temperature (C) , */\
+ { 0xb190, "ext_temp_sel"}, /* Select temp Speaker calibration , */\
+ { 0xc000, "use_direct_ctrls"}, /* Direct control to overrule several functions for testing, */\
+ { 0xc010, "rst_datapath"}, /* Direct control for datapath reset , */\
+ { 0xc020, "rst_cgu"}, /* Direct control for cgu reset , */\
+ { 0xc038, "enbl_ref"}, /* Switch on the analog references, each part of the references can be switched on/off individually - - I2C direct mode, */\
+ { 0xc0d0, "enbl_ringo"}, /* Enable the ring oscillator for test purpose , */\
+ { 0xc0e0, "use_direct_clk_ctrl"}, /* Direct clock control to overrule several functions for testing, */\
+ { 0xc0f0, "use_direct_pll_ctrl"}, /* Direct PLL control to overrule several functions for testing, */\
+ { 0xc100, "enbl_tsense"}, /* Temperature sensor enable control - I2C direct mode, */\
+ { 0xc110, "tsense_hibias"}, /* Bit to set the biasing in temp sensor to high - I2C direct mode, */\
+ { 0xc120, "enbl_flag_vbg"}, /* Enable flagging of bandgap out of control , */\
+ { 0xc130, "tap_comp_enable"}, /* Tap Comparator enable control - I2C direct mode , */\
+ { 0xc140, "tap_comp_switch_enable"}, /* Tap Comparator Switch enable control - I2C direct mode, */\
+ { 0xc150, "tap_comp_switch_aux_enable"}, /* Tap Comparator Switch enable control - I2C direct mode, */\
+ { 0xc161, "tap_comp_test_enable"}, /* Comparator threshold - fine value , */\
+ { 0xc180, "curdist_enable"}, /* Enable control - I2C direct mode , */\
+ { 0xc190, "vbg2i_enbl"}, /* Enable control - I2C direct mode , */\
+ { 0xc1a0, "bg_filt_bypass_enbl"}, /* Enable control , */\
+ { 0xc20f, "abist_offset"}, /* Offset control for ABIST testing (two's complement), */\
+ { 0xc300, "bypasslatch"}, /* Bypass latch , */\
+ { 0xc311, "sourcea"}, /* Set OUTA to , */\
+ { 0xc331, "sourceb"}, /* Set OUTB to , */\
+ { 0xc350, "inverta"}, /* Invert pwma test signal , */\
+ { 0xc360, "invertb"}, /* Invert pwmb test signal , */\
+ { 0xc374, "pulselength"}, /* Pulse length setting test input for amplifier (clock d - k*2048*fs), */\
+ { 0xc3c0, "tdm_enable_loopback"}, /* TDM loopback test , */\
+ { 0xc3d0, "test_abistfft_enbl"}, /* FFT Coolflux , */\
+ { 0xc3e0, "test_pwr_switch"}, /* Test mode for digital power switches core sw/mem sw/micvdd sw, */\
+ { 0xc400, "bst_bypasslatch"}, /* Bypass latch in boost converter , */\
+ { 0xc411, "bst_source"}, /* Sets the source of the pwmbst output to boost converter input for testing, */\
+ { 0xc430, "bst_invertb"}, /* Invert pwmbst test signal , */\
+ { 0xc444, "bst_pulselength"}, /* Pulse length setting test input for boost converter , */\
+ { 0xc490, "test_bst_ctrlsthv"}, /* Test mode for boost control stage , */\
+ { 0xc4a0, "test_bst_iddq"}, /* IDDQ testing in power stage of boost converter , */\
+ { 0xc4b0, "test_bst_rdson"}, /* RDSON testing - boost power stage , */\
+ { 0xc4c0, "test_bst_cvi"}, /* CVI testing - boost power stage , */\
+ { 0xc4d0, "test_bst_ocp"}, /* Boost OCP. For old ocp (ctrl_reversebst is 0), For new ocp (ctrl_reversebst is 1), */\
+ { 0xc4e0, "test_bst_sense"}, /* Test option for the sense NMOS in booster for current mode control., */\
+ { 0xc500, "test_cvi"}, /* Analog BIST, switch choose which transistor will be used as current source (also cross coupled sources possible), */\
+ { 0xc510, "test_discrete"}, /* Test function noise measurement , */\
+ { 0xc520, "test_iddq"}, /* Set the power stages in iddq mode for gate stress., */\
+ { 0xc540, "test_rdson"}, /* Analog BIST, switch to enable Rdson measurement , */\
+ { 0xc550, "test_sdelta"}, /* Analog BIST, noise test , */\
+ { 0xc560, "bypass_fro8"}, /* Bypass fro8 with pdm_clk , */\
+ { 0xc570, "test_enbl_cs"}, /* Enable for digimux mode of current sense , */\
+ { 0xc5b0, "pga_test_enable"}, /* Enable PGA test mode , */\
+ { 0xc5c0, "pga_test_offset_enable"}, /* Enable PGA test offset , */\
+ { 0xc5d0, "pga_test_shortinput_enable"}, /* Enable PGA test short input , */\
+ { 0xc600, "enbl_pwm_dcc"}, /* Enables direct control of pwm duty cycle for DCDC power stage, */\
+ { 0xc613, "pwm_dcc_cnt"}, /* Control pwm duty cycle when enbl_pwm_dcc is 1 , */\
+ { 0xc650, "enbl_ldo_stress"}, /* Enable stress of internal supply voltages powerstages, */\
+ { 0xc660, "enbl_powerswitch"}, /* Vddd core power switch control - overrules the manager control, */\
+ { 0xc707, "digimuxa_sel"}, /* DigimuxA input selection control routed to DIO4 (see Digimux list for details), */\
+ { 0xc787, "digimuxb_sel"}, /* DigimuxB input selection control routed to DIO3 (see Digimux list for details), */\
+ { 0xc807, "digimuxc_sel"}, /* DigimuxC input selection control routed to TDO (see Digimux list for details), */\
+ { 0xc901, "dio1_ehs"}, /* Speed/load setting for DIO1 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc921, "dio2_ehs"}, /* Speed/load setting for DIO2 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc941, "dio3_ehs"}, /* Speed/load setting for DIO3 cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc961, "dio4_ehs"}, /* Speed/load setting for DIO4 IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc981, "spdmo_ehs"}, /* Speed/load setting for PDMO IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9a1, "tdo_ehs"}, /* Speed/load setting for TDM IO cell, clk or data mode range (see SLIMMF IO cell datasheet), */\
+ { 0xc9c0, "int_ehs"}, /* Slew Rate INT IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xc9d0, "pdmclk_ehs"}, /* Slew RateBCK2/PDMCLK IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xc9e0, "fs2_ehs"}, /* Slew Rate DS2 IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xc9f0, "hs_mode"}, /* I2C high speed mode control , */\
+ { 0xca00, "enbl_anamux1"}, /* Enable anamux1 , */\
+ { 0xca10, "enbl_anamux2"}, /* Enable anamux2 , */\
+ { 0xca20, "enbl_anamux3"}, /* Enable anamux3 , */\
+ { 0xca30, "enbl_anamux4"}, /* Enable anamux4 , */\
+ { 0xca74, "anamux1"}, /* Anamux selection control - anamux on TEST1 , */\
+ { 0xcb04, "anamux2"}, /* Anamux selection control - anamux on TEST2 , */\
+ { 0xcb54, "anamux3"}, /* Anamux selection control - anamux on TEST3 , */\
+ { 0xcba4, "anamux4"}, /* Anamux selection control - anamux on TEST4 , */\
+ { 0xcc05, "pll_seli_lbw"}, /* PLL SELI - Low B/W PLL control mode or I2C direct PLL control mode only, */\
+ { 0xcc64, "pll_selp_lbw"}, /* PLL SELP - Low B/W PLL control mode or I2C direct PLL control mode only, */\
+ { 0xccb3, "pll_selr_lbw"}, /* PLL SELR - Low B/W PLL control mode or I2C direct PLL control mode only, */\
+ { 0xccf0, "sel_user_pll_bw"}, /* PLL Low Bandwidth Mode control , */\
+ { 0xcdf0, "pll_frm"}, /* PLL free running mode control; 1 in TCB direct control mode, else this control bit, */\
+ { 0xce09, "pll_ndec"}, /* PLL NDEC - I2C direct PLL control mode only , */\
+ { 0xcea0, "pll_mdec_msb"}, /* MSB of pll_mdec - I2C direct PLL control mode only, */\
+ { 0xceb0, "enbl_pll"}, /* Enables PLL in I2C direct PLL control mode only , */\
+ { 0xcec0, "enbl_fro8"}, /* Enables FRO8M in I2C direct control mode only , */\
+ { 0xced0, "pll_bypass"}, /* PLL bypass control in I2C direct PLL control mode only, */\
+ { 0xcee0, "pll_directi"}, /* PLL directi control in I2C direct PLL control mode only, */\
+ { 0xcef0, "pll_directo"}, /* PLL directo control in I2C direct PLL control mode only, */\
+ { 0xcf0f, "pll_mdec_lsb"}, /* Bits 15..0 of PLL MDEC are I2C direct PLL control mode only, */\
+ { 0xd006, "pll_pdec"}, /* PLL PDEC - I2C direct PLL control mode only , */\
+ { 0xd10f, "tsig_freq_lsb"}, /* Internal sinus test generator frequency control , */\
+ { 0xd202, "tsig_freq_msb"}, /* Select internal sinus test generator, frequency control msb bits, */\
+ { 0xd230, "inject_tsig"}, /* Control bit to switch to internal sinus test generator, */\
+ { 0xd283, "tsig_gain"}, /* Test signal gain , */\
+ { 0xd300, "adc10_reset"}, /* Reset for ADC10 - I2C direct control mode , */\
+ { 0xd311, "adc10_test"}, /* Test mode selection signal for ADC10 - I2C direct control mode, */\
+ { 0xd332, "adc10_sel"}, /* Select the input to convert for ADC10 - I2C direct control mode, */\
+ { 0xd364, "adc10_prog_sample"}, /* ADC10 program sample setting - I2C direct control mode, */\
+ { 0xd3b0, "adc10_enbl"}, /* Enable ADC10 - I2C direct control mode , */\
+ { 0xd3c0, "bypass_lp_vbat"}, /* Bypass control for Low pass filter in batt sensor , */\
+ { 0xd409, "data_adc10_tempbat"}, /* ADC 10 data output data for testing , */\
+ { 0xd507, "ctrl_digtoana_hidden"}, /* Spare digital to analog control bits - Hidden , */\
+ { 0xd580, "enbl_clk_range_chk"}, /* Clock out of range , */\
+ { 0xd601, "clkdiv_dsp_sel"}, /* DSP clock divider selection in direct clock control mode, */\
+ { 0xd621, "clkdiv_audio_sel"}, /* Audio clock divider selection in direct clock control mode, */\
+ { 0xd641, "clkdiv_muxa_sel"}, /* DCDC MUXA clock divider selection in direct clock control mode, */\
+ { 0xd661, "clkdiv_muxb_sel"}, /* DCDC MUXB clock divider selection in direct clock control mode, */\
+ { 0xd681, "dsp_tap_clk"}, /* Dsp clock frequency selection in TAP mode; , */\
+ { 0xd6a1, "sel_wdt_clk"}, /* Watch dog clock post divider value , */\
+ { 0xd6c1, "sel_tim_clk"}, /* Timer clock post divider value , */\
+ { 0xd700, "ads1_ehs"}, /* Slew Rate ADS1 IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xd710, "ads2_ehs"}, /* Slew Rate ADS2 IO cell, clk or data mode range (see IIC3V3 IO cell datasheet), */\
+ { 0xd822, "test_parametric_io"}, /* test io parametric , */\
+ { 0xd850, "ctrl_bst_clk_lp1"}, /* boost clock control in low power mode1 , */\
+ { 0xd861, "test_spare_out1"}, /* test spare out 1 , */\
+ { 0xd880, "bst_dcmbst"}, /* dcm boost - I2C direct mode , */\
+ { 0xd8a1, "force_pga_clock"}, /* force pga clock , */\
+ { 0xd8c3, "test_spare_out2"}, /* test spare out 1 , */\
+ { 0xd900, "overrules_usercase"}, /* Overrule Mode control use , */\
+ { 0xd910, "ovr_switch_ref"}, /* Overrule Value , */\
+ { 0xd920, "ovr_enbl_pll"}, /* Overrule Value , */\
+ { 0xd930, "ovr_switch_amp"}, /* Overrule Value , */\
+ { 0xd940, "ovr_enbl_clk_cs"}, /* Overrule Value , */\
+ { 0xd951, "ovr_sel_clk_cs"}, /* CS clock selection overrule , */\
+ { 0xd970, "ovr_switch_cs"}, /* Overrule Value , */\
+ { 0xd980, "ovr_enbl_csvs_ss"}, /* Overrule Value , */\
+ { 0xd990, "ovr_enbl_comp"}, /* Overrule Value , */\
+ { 0xed00, "enbl_fro8cal"}, /* Enable FRO calibration , */\
+ { 0xed10, "start_fro8_calibration"}, /* Start FRO8 Calibration , */\
+ { 0xed20, "fro8_calibration_done"}, /* FRO8 Calibration done - Read Only , */\
+ { 0xed45, "fro8_auto_trim_val"}, /* Calibration value from Auto Calibration block, to be written into MTP - Read Only, */\
+ { 0xee0f, "sw_profile"}, /* Software profile data , */\
+ { 0xef0f, "sw_vstep"}, /* Software vstep information , */\
+ { 0xf000, "calibration_onetime"}, /* Calibration schedule , */\
+ { 0xf010, "calibr_ron_done"}, /* Calibration Ron executed , */\
+ { 0xf020, "calibr_dcdc_api_calibrate"}, /* Calibration current limit DCDC , */\
+ { 0xf030, "calibr_dcdc_delta_sign"}, /* Sign bit for delta calibration current limit DCDC , */\
+ { 0xf042, "calibr_dcdc_delta"}, /* Calibration delta current limit DCDC , */\
+ { 0xf078, "calibr_speaker_info"}, /* Reserved space for allowing customer to store speaker information, */\
+ { 0xf105, "calibr_vout_offset"}, /* DCDC offset calibration 2's complement (key1 protected), */\
+ { 0xf163, "spare_mtp1_9_6"}, /* HW gain module - left channel (2's complement) , */\
+ { 0xf1a5, "spare_mtp1_15_10"}, /* Offset for amplifier, HW gain module - left channel (2's complement), */\
+ { 0xf203, "calibr_gain"}, /* HW gain module (2's complement) , */\
+ { 0xf245, "calibr_offset"}, /* Offset for amplifier, HW gain module (2's complement), */\
+ { 0xf2a3, "spare_mtp2_13_10"}, /* Trimming of LDO (2.7V) , */\
+ { 0xf307, "spare_mtp3_7_0"}, /* SPARE , */\
+ { 0xf387, "calibr_gain_cs"}, /* Current sense gain (signed two's complement format), */\
+ { 0xf40f, "calibr_R25C"}, /* Ron resistance of speaker coil , */\
+ { 0xf50f, "spare_mtp5_15_0"}, /* SPARE , */\
+ { 0xf600, "mtp_lock_enbl_coolflux"}, /* Disable function dcdcoff_mode , */\
+ { 0xf610, "mtp_pwm_delay_enbl_clk_auto_gating"}, /* Auto clock gating on pwm_delay , */\
+ { 0xf620, "mtp_ocp_enbl_clk_auto_gating"}, /* Auto clock gating on module ocp , */\
+ { 0xf630, "mtp_disable_clk_a_gating"}, /* Disable clock_a gating , */\
+ { 0xf642, "spare_mtp6_6_3"}, /* SPARE , */\
+ { 0xf686, "spare_mtp6_14_8"}, /* Offset of left amplifier level shifter B , */\
+ { 0xf706, "ctrl_offset_a"}, /* Offset of level shifter A , */\
+ { 0xf786, "ctrl_offset_b"}, /* Offset of amplifier level shifter B , */\
+ { 0xf806, "htol_iic_addr"}, /* 7-bit I2C address to be used during HTOL testing , */\
+ { 0xf870, "htol_iic_addr_en"}, /* HTOL I2C address enable control , */\
+ { 0xf884, "calibr_temp_offset"}, /* Temperature offset 2's compliment (key1 protected), */\
+ { 0xf8d2, "calibr_temp_gain"}, /* Temperature gain 2's compliment (key1 protected) , */\
+ { 0xf910, "disable_sam_mode"}, /* Disable sam mode , */\
+ { 0xf920, "mtp_lock_bypass_clipper"}, /* Disable function bypass_clipper , */\
+ { 0xf930, "mtp_lock_max_dcdc_voltage"}, /* Disable programming of max dcdc boost voltage , */\
+ { 0xf943, "calibr_vbg_trim"}, /* Bandgap trimming control , */\
+ { 0xf987, "type_bits_fw"}, /* MTP-control FW - See Firmware I2C API document for details, */\
+ { 0xfa0f, "mtpdataA"}, /* MTPdataA (key1 protected) , */\
+ { 0xfb0f, "mtpdataB"}, /* MTPdataB (key1 protected) , */\
+ { 0xfc0f, "mtpdataC"}, /* MTPdataC (key1 protected) , */\
+ { 0xfd0f, "mtpdataD"}, /* MTPdataD (key1 protected) , */\
+ { 0xfe0f, "mtpdataE"}, /* MTPdataE (key1 protected) , */\
+ { 0xff05, "fro8_trim"}, /* 8 MHz oscillator trim code , */\
+ { 0xff61, "fro8_short_nwell_r"}, /* Short 4 or 6 n-well resistors , */\
+ { 0xff81, "fro8_boost_i"}, /* Self bias current selection , */\
+ { 0xffff,"Unknown bitfield enum" } /* not found */\
+};
+
+enum tfa9912_irq {
+ tfa9912_irq_stvdds = 0,
+ tfa9912_irq_stplls = 1,
+ tfa9912_irq_stotds = 2,
+ tfa9912_irq_stovds = 3,
+ tfa9912_irq_stuvds = 4,
+ tfa9912_irq_stclks = 5,
+ tfa9912_irq_stmtpb = 6,
+ tfa9912_irq_stnoclk = 7,
+ tfa9912_irq_stspks = 8,
+ tfa9912_irq_stacs = 9,
+ tfa9912_irq_stsws = 10,
+ tfa9912_irq_stwds = 11,
+ tfa9912_irq_stamps = 12,
+ tfa9912_irq_starefs = 13,
+ tfa9912_irq_stadccr = 14,
+ tfa9912_irq_stbodnok = 15,
+ tfa9912_irq_stbstcu = 16,
+ tfa9912_irq_stbsthi = 17,
+ tfa9912_irq_stbstoc = 18,
+ tfa9912_irq_stbstpkcur = 19,
+ tfa9912_irq_stbstvc = 20,
+ tfa9912_irq_stbst86 = 21,
+ tfa9912_irq_stbst93 = 22,
+ tfa9912_irq_strcvld = 23,
+ tfa9912_irq_stocpl = 24,
+ tfa9912_irq_stocpr = 25,
+ tfa9912_irq_stmwsrc = 26,
+ tfa9912_irq_stmwcfc = 27,
+ tfa9912_irq_stmwsmu = 28,
+ tfa9912_irq_stcfmer = 29,
+ tfa9912_irq_stcfmac = 30,
+ tfa9912_irq_stclkoor = 31,
+ tfa9912_irq_sttdmer = 32,
+ tfa9912_irq_stclpl = 33,
+ tfa9912_irq_stclpr = 34,
+ tfa9912_irq_stocpm = 35,
+ tfa9912_irq_stlp1 = 37,
+ tfa9912_irq_stla = 38,
+ tfa9912_irq_stvddp = 39,
+ tfa9912_irq_sttapdet = 40,
+ tfa9912_irq_staudmod = 41,
+ tfa9912_irq_stsammod = 42,
+ tfa9912_irq_sttapmod = 43,
+ tfa9912_irq_sttaptrg = 44,
+ tfa9912_irq_max = 45,
+ tfa9912_irq_all = -1 /* all irqs */};
+
+#define TFA9912_IRQ_NAMETABLE static tfaIrqName_t Tfa9912IrqNames[]= {\
+ { 0, "STVDDS"},\
+ { 1, "STPLLS"},\
+ { 2, "STOTDS"},\
+ { 3, "STOVDS"},\
+ { 4, "STUVDS"},\
+ { 5, "STCLKS"},\
+ { 6, "STMTPB"},\
+ { 7, "STNOCLK"},\
+ { 8, "STSPKS"},\
+ { 9, "STACS"},\
+ { 10, "STSWS"},\
+ { 11, "STWDS"},\
+ { 12, "STAMPS"},\
+ { 13, "STAREFS"},\
+ { 14, "STADCCR"},\
+ { 15, "STBODNOK"},\
+ { 16, "STBSTCU"},\
+ { 17, "STBSTHI"},\
+ { 18, "STBSTOC"},\
+ { 19, "STBSTPKCUR"},\
+ { 20, "STBSTVC"},\
+ { 21, "STBST86"},\
+ { 22, "STBST93"},\
+ { 23, "STRCVLD"},\
+ { 24, "STOCPL"},\
+ { 25, "STOCPR"},\
+ { 26, "STMWSRC"},\
+ { 27, "STMWCFC"},\
+ { 28, "STMWSMU"},\
+ { 29, "STCFMER"},\
+ { 30, "STCFMAC"},\
+ { 31, "STCLKOOR"},\
+ { 32, "STTDMER"},\
+ { 33, "STCLPL"},\
+ { 34, "STCLPR"},\
+ { 35, "STOCPM"},\
+ { 36, "36"},\
+ { 37, "STLP1"},\
+ { 38, "STLA"},\
+ { 39, "STVDDP"},\
+ { 40, "STTAPDET"},\
+ { 41, "STAUDMOD"},\
+ { 42, "STSAMMOD"},\
+ { 43, "STTAPMOD"},\
+ { 44, "STTAPTRG"},\
+ { 45, "45"},\
+};
+#endif /* _TFA9912_TFAFIELDNAMES_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_container.c b/sound/soc/codecs/tfa98xx-downstream/tfa_container.c
new file mode 100644
index 00000000000..44ba073d69e
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_container.c
@@ -0,0 +1,2428 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include "dbgprint.h"
+#include "tfa_container.h"
+#include "tfa.h"
+#include "tfa98xx_tfafieldnames.h"
+#include "tfa_internal.h"
+
+ /* defines */
+#define MODULE_BIQUADFILTERBANK 2
+#define BIQUAD_COEFF_SIZE 6
+
+/* module globals */
+static uint8_t gslave_address = 0; /* This is used to SET the slave with the --slave option */
+
+static int float_to_int(uint32_t x)
+{
+ unsigned e = (0x7F + 31) - ((*(unsigned *)&x & 0x7F800000) >> 23);
+ unsigned m = 0x80000000 | (*(unsigned *)&x << 8);
+ return -(int)((m >> e) & -(e < 32));
+}
+
+/*
+ * check the container file
+*/
+enum tfa_error tfa_load_cnt(void *cnt, int length)
+{
+ TfaContainer_t *cntbuf = (TfaContainer_t *)cnt;
+
+ if (length > TFA_MAX_CNT_LENGTH) {
+ pr_err("incorrect length\n");
+ return tfa_error_container;
+ }
+
+ if (HDR(cntbuf->id[0], cntbuf->id[1]) == 0) {
+ pr_err("header is 0\n");
+ return tfa_error_container;
+ }
+
+ if ((HDR(cntbuf->id[0], cntbuf->id[1])) != paramsHdr) {
+ pr_err("wrong header type: 0x%02x 0x%02x\n", cntbuf->id[0], cntbuf->id[1]);
+ return tfa_error_container;
+ }
+
+ if (cntbuf->size == 0) {
+ pr_err("data size is 0\n");
+ return tfa_error_container;
+ }
+
+ /* check CRC */
+ if (tfaContCrcCheckContainer(cntbuf)) {
+ pr_err("CRC error\n");
+ return tfa_error_container;
+ }
+
+ /* check sub version level */
+ if ((cntbuf->subversion[1] != TFA_PM_SUBVERSION) &&
+ (cntbuf->subversion[0] != '0')) {
+ pr_err("container sub-version not supported: %c%c\n",
+ cntbuf->subversion[0], cntbuf->subversion[1]);
+ return tfa_error_container;
+ }
+
+ return tfa_error_ok;
+}
+
+/*
+ * Dump the contents of the file header
+ */
+void tfaContShowHeader(TfaHeader_t *hdr) {
+ char _id[2];
+
+ pr_debug("File header\n");
+
+ _id[1] = hdr->id >> 8;
+ _id[0] = hdr->id & 0xff;
+ pr_debug("\tid:%.2s version:%.2s subversion:%.2s\n", _id,
+ hdr->version, hdr->subversion);
+ pr_debug("\tsize:%d CRC:0x%08x \n", hdr->size, hdr->CRC);
+ pr_debug("\tcustomer:%.8s application:%.8s type:%.8s\n", hdr->customer,
+ hdr->application, hdr->type);
+}
+
+/*
+ * return device list dsc from index
+ */
+TfaDeviceList_t *tfaContGetDevList(TfaContainer_t *cont, int dev_idx)
+{
+ uint8_t *base = (uint8_t *)cont;
+
+ if (cont == NULL)
+ return NULL;
+
+ if ((dev_idx < 0) || (dev_idx >= cont->ndev))
+ return NULL;
+
+ if (cont->index[dev_idx].type != dscDevice)
+ return NULL;
+
+ base += cont->index[dev_idx].offset;
+ return (TfaDeviceList_t *)base;
+}
+
+/*
+ * get the Nth profile for the Nth device
+ */
+TfaProfileList_t *tfaContGetDevProfList(TfaContainer_t * cont, int devIdx, int profIdx)
+{
+ TfaDeviceList_t *dev;
+ int idx, hit;
+ uint8_t *base = (uint8_t *)cont;
+
+ dev = tfaContGetDevList(cont, devIdx);
+ if (dev) {
+ for (idx = 0, hit = 0; idx < dev->length; idx++) {
+ if (dev->list[idx].type == dscProfile) {
+ if (profIdx == hit++)
+ return (TfaProfileList_t *)(dev->list[idx].offset + base);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * get the number of profiles for the Nth device
+ */
+int tfa_cnt_get_dev_nprof(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev;
+ int idx, nprof = 0;
+
+ if (tfa->cnt == NULL)
+ return 0;
+
+ if ((tfa->dev_idx < 0) || (tfa->dev_idx >= tfa->cnt->ndev))
+ return 0;
+
+ dev = tfaContGetDevList(tfa->cnt, tfa->dev_idx);
+ if (dev) {
+ for (idx = 0; idx < dev->length; idx++) {
+ if (dev->list[idx].type == dscProfile) {
+ nprof++;
+ }
+ }
+ }
+
+ return nprof;
+}
+
+/*
+ * get the Nth lifedata for the Nth device
+ */
+TfaLiveDataList_t *tfaContGetDevLiveDataList(TfaContainer_t * cont, int devIdx,
+ int lifeDataIdx)
+{
+ TfaDeviceList_t *dev;
+ int idx, hit;
+ uint8_t *base = (uint8_t *)cont;
+
+ dev = tfaContGetDevList(cont, devIdx);
+ if (dev) {
+ for (idx = 0, hit = 0; idx < dev->length; idx++) {
+ if (dev->list[idx].type == dscLiveData) {
+ if (lifeDataIdx == hit++)
+ return (TfaLiveDataList_t *)
+ (dev->list[idx].offset + base);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Get the max volume step associated with Nth profile for the Nth device
+ */
+int tfacont_get_max_vstep(struct tfa_device *tfa, int prof_idx) {
+ TfaVolumeStep2File_t *vp;
+ struct TfaVolumeStepMax2File *vp3;
+ int vstep_count = 0;
+ vp = (TfaVolumeStep2File_t *)tfacont_getfiledata(tfa, prof_idx, volstepHdr);
+ if (vp == NULL)
+ return 0;
+ /* check the header type to load different NrOfVStep appropriately */
+ if (tfa->tfa_family == 2) {
+ /* this is actually tfa2, so re-read the buffer*/
+ vp3 = (struct TfaVolumeStepMax2File *)
+ tfacont_getfiledata(tfa, prof_idx, volstepHdr);
+ if (vp3) {
+ vstep_count = vp3->NrOfVsteps;
+ }
+ }
+ else {
+ /* this is max1*/
+ if (vp) {
+ vstep_count = vp->vsteps;
+ }
+ }
+ return vstep_count;
+}
+
+/**
+ * Get the file contents associated with the device or profile
+ * Search within the device tree, if not found, search within the profile
+ * tree. There can only be one type of file within profile or device.
+ */
+TfaFileDsc_t *tfacont_getfiledata(struct tfa_device *tfa, int prof_idx, enum TfaHeaderType type)
+{
+ TfaDeviceList_t *dev;
+ TfaProfileList_t *prof;
+ TfaFileDsc_t *file;
+ TfaHeader_t *hdr;
+ unsigned int i;
+
+ if (tfa->cnt == NULL) {
+ pr_err("invalid pointer to container file\n");
+ return NULL;
+ }
+
+ dev = tfaContGetDevList(tfa->cnt, tfa->dev_idx);
+ if (dev == NULL) {
+ pr_err("invalid pointer to container file device list\n");
+ return NULL;
+ }
+
+ /* process the device list until a file type is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ if (file != NULL) {
+ hdr = (TfaHeader_t *)file->data;
+ /* check for file type */
+ if (hdr->id == type) {
+ return (TfaFileDsc_t *)&file->data;
+ }
+ }
+ }
+ }
+
+ /* File not found in device tree.
+ * So, look in the profile list until the file type is encountered
+ */
+ prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ if (prof == NULL) {
+ pr_err("invalid pointer to container file profile list\n");
+ return NULL;
+ }
+
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (file != NULL) {
+ hdr = (TfaHeader_t *)file->data;
+ if (hdr != NULL) {
+ /* check for file type */
+ if (hdr->id == type) {
+ return (TfaFileDsc_t *)&file->data;
+ }
+ }
+ }
+ }
+ }
+
+ if (tfa->verbose)
+ pr_debug("%s: no file found of type %d\n", __FUNCTION__, type);
+
+ return NULL;
+}
+
+/*
+ * write a parameter file to the device
+ */
+static enum Tfa98xx_Error tfaContWriteVstep(struct tfa_device *tfa, TfaVolumeStep2File_t *vp, int vstep)
+{
+ enum Tfa98xx_Error err;
+ unsigned short vol;
+
+ if (vstep < vp->vsteps) {
+ /* vol = (unsigned short)(voldB / (-0.5f)); */
+ vol = (unsigned short)(-2 * float_to_int(*((uint32_t *)&vp->vstep[vstep].attenuation)));
+ if (vol > 255) /* restricted to 8 bits */
+ vol = 255;
+
+ err = tfa98xx_set_volume_level(tfa, vol);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+
+ err = tfa98xx_dsp_write_preset(tfa, sizeof(vp->vstep[0].preset), vp->vstep[vstep].preset);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+ err = tfa_cont_write_filterbank(tfa, vp->vstep[vstep].filter);
+
+ }
+ else {
+ pr_err("Incorrect volume given. The value vstep[%d] >= %d\n", vstep, vp->vsteps);
+ err = Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose) pr_debug("vstep[%d][%d]\n", tfa->dev_idx, vstep);
+
+ return err;
+}
+
+static struct TfaVolumeStepMessageInfo *
+tfaContGetmsgInfoFromReg(struct TfaVolumeStepRegisterInfo *regInfo)
+{
+ char *p = (char*)regInfo;
+ p += sizeof(regInfo->NrOfRegisters) + (regInfo->NrOfRegisters * sizeof(uint32_t));
+ return (struct TfaVolumeStepMessageInfo*) p;
+}
+
+static int
+tfaContGetmsgLen(struct TfaVolumeStepMessageInfo *msgInfo)
+{
+ return (msgInfo->MessageLength.b[0] << 16) + (msgInfo->MessageLength.b[1] << 8) + msgInfo->MessageLength.b[2];
+}
+
+static struct TfaVolumeStepMessageInfo *
+tfaContGetNextmsgInfo(struct TfaVolumeStepMessageInfo *msgInfo)
+{
+ char *p = (char*)msgInfo;
+ int msgLen = tfaContGetmsgLen(msgInfo);
+ int type = msgInfo->MessageType;
+
+ p += sizeof(msgInfo->MessageType) + sizeof(msgInfo->MessageLength);
+ if (type == 3)
+ p += msgLen;
+ else
+ p += msgLen * 3;
+
+ return (struct TfaVolumeStepMessageInfo*) p;
+}
+
+static struct TfaVolumeStepRegisterInfo*
+tfaContGetNextRegFromEndInfo(struct TfaVolumeStepMessageInfo *msgInfo)
+{
+ char *p = (char*)msgInfo;
+ p += sizeof(msgInfo->NrOfMessages);
+ return (struct TfaVolumeStepRegisterInfo*) p;
+
+}
+
+static struct TfaVolumeStepRegisterInfo*
+tfaContGetRegForVstep(TfaVolumeStepMax2File_t *vp, int idx)
+{
+ int i, j, nrMessage;
+
+ struct TfaVolumeStepRegisterInfo *regInfo
+ = (struct TfaVolumeStepRegisterInfo*) vp->vstepsBin;
+ struct TfaVolumeStepMessageInfo *msgInfo = NULL;
+
+ for (i = 0; i < idx; i++) {
+ msgInfo = tfaContGetmsgInfoFromReg(regInfo);
+ nrMessage = msgInfo->NrOfMessages;
+
+ for (j = 0; j < nrMessage; j++) {
+ msgInfo = tfaContGetNextmsgInfo(msgInfo);
+ }
+ regInfo = tfaContGetNextRegFromEndInfo(msgInfo);
+ }
+
+ return regInfo;
+}
+
+#pragma pack (push, 1)
+struct tfa_partial_msg_block {
+ uint8_t offset;
+ uint16_t change;
+ uint8_t update[16][3];
+};
+#pragma pack (pop)
+
+static enum Tfa98xx_Error tfaContWriteVstepMax2_One(struct tfa_device *tfa, struct TfaVolumeStepMessageInfo *new_msg,
+ struct TfaVolumeStepMessageInfo *old_msg, int enable_partial_update)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int len = (tfaContGetmsgLen(new_msg) - 1) * 3;
+ char *buf = (char*)new_msg->ParameterData;
+ uint8_t *partial = NULL;
+ uint8_t cmdid[3];
+ int use_partial_coeff = 0;
+
+ if (enable_partial_update) {
+ if (new_msg->MessageType != old_msg->MessageType) {
+ pr_debug("Message type differ - Disable Partial Update\n");
+ enable_partial_update = 0;
+ }
+ else if (tfaContGetmsgLen(new_msg) != tfaContGetmsgLen(old_msg)) {
+ pr_debug("Message Length differ - Disable Partial Update\n");
+ enable_partial_update = 0;
+ }
+ }
+
+ if ((enable_partial_update) && (new_msg->MessageType == 1)) {
+ /* No patial updates for message type 1 (Coefficients) */
+ enable_partial_update = 0;
+ if ((tfa->rev & 0xff) == 0x88) {
+ use_partial_coeff = 1;
+ }
+ else if ((tfa->rev & 0xff) == 0x13) {
+ use_partial_coeff = 1;
+ }
+ }
+
+ /* Change Message Len to the actual buffer len */
+ memcpy(cmdid, new_msg->CmdId, sizeof(cmdid));
+
+ /* The algoparams and mbdrc msg id will be changed to the reset type when SBSL=0
+ * if SBSL=1 the msg will remain unchanged. It's up to the tuning engineer to choose the 'without_reset'
+ * types inside the vstep. In other words: the reset msg is applied during SBSL==0 else it remains unchanged.
+ */
+ if (tfa_needs_reset(tfa) == 1) {
+ if (new_msg->MessageType == 0) {
+ cmdid[2] = SB_PARAM_SET_ALGO_PARAMS;
+ if (tfa->verbose)
+ pr_debug("P-ID for SetAlgoParams modified!\n");
+ }
+ else if (new_msg->MessageType == 2) {
+ cmdid[2] = SB_PARAM_SET_MBDRC;
+ if (tfa->verbose)
+ pr_debug("P-ID for SetMBDrc modified!\n");
+ }
+ }
+
+ /*
+ * +sizeof(struct tfa_partial_msg_block) will allow to fit one
+ * additonnal partial block If the partial update goes over the len of
+ * a regular message ,we can safely write our block and check afterward
+ * that we are over the size of a usual update
+ */
+ if (enable_partial_update) {
+ partial = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (!partial)
+ pr_debug("Partial update memory error - Disabling\n");
+ }
+
+ if (partial) {
+ uint8_t offset = 0, i = 0;
+ uint16_t *change;
+ uint8_t *n = new_msg->ParameterData;
+ uint8_t *o = old_msg->ParameterData;
+ uint8_t *p = partial;
+ uint8_t* trim = partial;
+
+ /* set dspFiltersReset */
+ *p++ = 0x02;
+ *p++ = 0x00;
+ *p++ = 0x00;
+
+ while ((o < (old_msg->ParameterData + len)) &&
+ (p < (partial + len - 3))) {
+ if ((offset == 0xff) ||
+ (memcmp(n, o, 3 * sizeof(uint8_t)))) {
+ *p++ = offset;
+ change = (uint16_t*)p;
+ *change = 0;
+ p += 2;
+
+ for (i = 0;
+ (i < 16) && (o < (old_msg->ParameterData + len));
+ i++, n += 3, o += 3) {
+ if (memcmp(n, o, 3 * sizeof(uint8_t))) {
+ *change |= BIT(i);
+ memcpy(p, n, 3);
+ p += 3;
+ trim = p;
+ }
+ }
+
+ offset = 0;
+ *change = cpu_to_be16(*change);
+ }
+ else {
+ n += 3;
+ o += 3;
+ offset++;
+ }
+ }
+
+ if (trim == partial) {
+ pr_debug("No Change in message - discarding %d bytes\n", len);
+ len = 0;
+
+ }
+ else if (trim < (partial + len - 3)) {
+ pr_debug("Using partial update: %d -> %d bytes\n", len, (int)(trim - partial + 3));
+
+ /* Add the termination marker */
+ memset(trim, 0x00, 3);
+ trim += 3;
+
+ /* Signal This will be a partial update */
+ cmdid[2] |= BIT(6);
+ buf = (char*)partial;
+ len = (int)(trim - partial);
+ }
+ else {
+ pr_debug("Partial too big - use regular update\n");
+ }
+ }
+
+ if (use_partial_coeff) {
+ err = tfa_dsp_partial_coefficients(tfa, old_msg->ParameterData, new_msg->ParameterData);
+ }
+ else if (len) {
+ uint8_t *buffer;
+
+ if (tfa->verbose)
+ pr_debug("Command-ID used: 0x%02x%02x%02x \n", cmdid[0], cmdid[1], cmdid[2]);
+
+ buffer = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (buffer == NULL) {
+ err = Tfa98xx_Error_Fail;
+ }
+ else {
+ memcpy(&buffer[0], cmdid, 3);
+ memcpy(&buffer[3], buf, len);
+ err = tfa_dsp_msg(tfa, 3 + len, (char *)buffer);
+ kmem_cache_free(tfa->cachep, buffer);
+ }
+ }
+
+ if (partial)
+ kmem_cache_free(tfa->cachep, partial);
+
+ return err;
+}
+
+static enum Tfa98xx_Error tfaContWriteVstepMax2(struct tfa_device *tfa, TfaVolumeStepMax2File_t *vp, int vstep_idx, int vstep_msg_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ struct TfaVolumeStepRegisterInfo *regInfo = NULL;
+ struct TfaVolumeStepMessageInfo *msgInfo = NULL, *p_msgInfo = NULL;
+ TfaBitfield_t bitF;
+ int i, nrMessages, enp = tfa->partial_enable;
+
+ if (vstep_idx >= vp->NrOfVsteps) {
+ pr_debug("Volumestep %d is not available \n", vstep_idx);
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->p_regInfo == NULL) {
+ if (tfa->verbose)
+ pr_debug("Inital vstep write\n");
+ enp = 0;
+ }
+
+ regInfo = tfaContGetRegForVstep(vp, vstep_idx);
+
+ msgInfo = tfaContGetmsgInfoFromReg(regInfo);
+ nrMessages = msgInfo->NrOfMessages;
+
+ if (enp) {
+ p_msgInfo = tfaContGetmsgInfoFromReg(tfa->p_regInfo);
+ if (nrMessages != p_msgInfo->NrOfMessages) {
+ pr_debug("Message different - Disable partial update\n");
+ enp = 0;
+ }
+ }
+
+ for (i = 0; i < nrMessages; i++) {
+ /* Messagetype(3) is Smartstudio Info! Dont send this! */
+ if (msgInfo->MessageType == 3) {
+ /* MessageLength is in bytes */
+ msgInfo = tfaContGetNextmsgInfo(msgInfo);
+ if (enp)
+ p_msgInfo = tfaContGetNextmsgInfo(p_msgInfo);
+ continue;
+ }
+
+ /* If no vstepMsgIndex is passed on, all message needs to be send */
+ if ((vstep_msg_idx >= TFA_MAX_VSTEP_MSG_MARKER) || (vstep_msg_idx == i)) {
+ err = tfaContWriteVstepMax2_One(tfa, msgInfo, p_msgInfo, enp);
+ if (err != Tfa98xx_Error_Ok) {
+ /*
+ * Force a full update for the next write
+ * As the current status of the DSP is unknown
+ */
+ tfa->p_regInfo = NULL;
+ return err;
+ }
+ }
+
+ msgInfo = tfaContGetNextmsgInfo(msgInfo);
+ if (enp)
+ p_msgInfo = tfaContGetNextmsgInfo(p_msgInfo);
+ }
+
+ tfa->p_regInfo = regInfo;
+
+ for (i = 0; i < regInfo->NrOfRegisters * 2; i++) {
+ /* Byte swap the datasheetname */
+ bitF.field = (uint16_t)(regInfo->registerInfo[i] >> 8) | (regInfo->registerInfo[i] << 8);
+ i++;
+ bitF.value = (uint16_t)regInfo->registerInfo[i] >> 8;
+ err = tfaRunWriteBitfield(tfa, bitF);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+ }
+
+ /* Save the current vstep */
+ tfa_dev_set_swvstep(tfa, (unsigned short)vstep_idx);
+
+ return err;
+}
+
+/*
+ * Write DRC message to the dsp
+ * If needed modify the cmd-id
+ */
+
+enum Tfa98xx_Error tfaContWriteDrcFile(struct tfa_device *tfa, int size, uint8_t data[])
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ uint8_t *msg = NULL;
+
+ msg = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (msg == NULL)
+ return Tfa98xx_Error_Fail;
+ memcpy(msg, data, size);
+
+ if (TFA_GET_BF(tfa, SBSL) == 0) {
+ /* Only do this when not set already */
+ if (msg[2] != SB_PARAM_SET_MBDRC) {
+ msg[2] = SB_PARAM_SET_MBDRC;
+
+ if (tfa->verbose) {
+ pr_debug("P-ID for SetMBDrc modified!: ");
+ pr_debug("Command-ID used: 0x%02x%02x%02x \n",
+ msg[0], msg[1], msg[2]);
+ }
+ }
+ }
+
+ /* Send cmdId + payload to dsp */
+ err = tfa_dsp_msg(tfa, size, (const char *)msg);
+
+ kmem_cache_free(tfa->cachep, msg);
+
+ return err;
+}
+
+
+/*
+ * write a parameter file to the device
+ * The VstepIndex and VstepMsgIndex are only used to write a specific msg from the vstep file.
+ */
+enum Tfa98xx_Error tfaContWriteFile(struct tfa_device *tfa, TfaFileDsc_t *file, int vstep_idx, int vstep_msg_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaHeader_t *hdr = (TfaHeader_t *)file->data;
+ TfaHeaderType_t type;
+ int size, i;
+ char subVerString[8] = { 0 };
+ int subversion = 0;
+
+ if (tfa->verbose) {
+ tfaContShowHeader(hdr);
+ }
+
+ type = (TfaHeaderType_t)hdr->id;
+ if ((type == msgHdr) || ((type == volstepHdr) && (tfa->tfa_family == 2)))
+ {
+ subVerString[0] = hdr->subversion[0];
+ subVerString[1] = hdr->subversion[1];
+ subVerString[2] = '\0';
+
+ sscanf(subVerString, "%d", &subversion);
+
+ if ((subversion > 0) &&
+ (((hdr->customer[0]) == 'A') && ((hdr->customer[1]) == 'P') &&
+ ((hdr->customer[2]) == 'I') && ((hdr->customer[3]) == 'V')))
+ {
+ /* Temporary workaround (example: For climax --calibrate scenario for probus devices) */
+ err = tfaGetFwApiVersion(tfa, (unsigned char *)&tfa->fw_itf_ver[0]);
+ if (err) {
+ pr_debug("[%s] cannot get FWAPI error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+ for (i = 0; i<4; i++)
+ {
+ if (tfa->fw_itf_ver[i] != hdr->customer[i + 4]) //+4 to skip "?PIV" string part in the .msg file.
+ {
+ ERRORMSG("Error: tfaContWriteFile: Expected FW API version = %d.%d.%d.%d, Msg File version: %d.%d.%d.%d \n",
+ tfa->fw_itf_ver[0],
+ tfa->fw_itf_ver[1],
+ tfa->fw_itf_ver[2],
+ tfa->fw_itf_ver[3],
+ hdr->customer[4],
+ hdr->customer[5],
+ hdr->customer[6],
+ hdr->customer[7]);
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ }
+ }
+
+ switch (type) {
+ case msgHdr: /* generic DSP message */
+ size = hdr->size - sizeof(TfaMsgFile_t);
+ err = tfa_dsp_msg(tfa, size, (const char *)((TfaMsgFile_t *)hdr)->data);
+ break;
+ case volstepHdr:
+ if (tfa->tfa_family == 2) {
+ err = tfaContWriteVstepMax2(tfa, (TfaVolumeStepMax2File_t *)hdr, vstep_idx, vstep_msg_idx);
+ }
+ else {
+ err = tfaContWriteVstep(tfa, (TfaVolumeStep2File_t *)hdr, vstep_idx);
+ }
+ break;
+ case speakerHdr:
+ if (tfa->tfa_family == 2) {
+ /* Remove header and xml_id */
+ size = hdr->size - sizeof(struct TfaSpkHeader) - sizeof(struct TfaFWVer);
+
+ err = tfa_dsp_msg(tfa, size,
+ (const char *)(((TfaSpeakerFile_t *)hdr)->data + (sizeof(struct TfaFWVer))));
+ }
+ else {
+ size = hdr->size - sizeof(TfaSpeakerFile_t);
+ err = tfa98xx_dsp_write_speaker_parameters(tfa, size,
+ (const unsigned char *)((TfaSpeakerFile_t *)hdr)->data);
+ }
+ break;
+ case presetHdr:
+ size = hdr->size - sizeof(TfaPreset_t);
+ err = tfa98xx_dsp_write_preset(tfa, size, (const unsigned char *)((TfaPreset_t *)hdr)->data);
+ break;
+ case equalizerHdr:
+ err = tfa_cont_write_filterbank(tfa, ((TfaEqualizerFile_t *)hdr)->filter);
+ break;
+ case patchHdr:
+ size = hdr->size - sizeof(TfaPatch_t); // size is total length
+ err = tfa_dsp_patch(tfa, size, (const unsigned char *)((TfaPatch_t *)hdr)->data);
+ break;
+ case configHdr:
+ size = hdr->size - sizeof(TfaConfig_t);
+ err = tfa98xx_dsp_write_config(tfa, size, (const unsigned char *)((TfaConfig_t *)hdr)->data);
+ break;
+ case drcHdr:
+ if (hdr->version[0] == TFA_DR3_VERSION) {
+ /* Size is total size - hdrsize(36) - xmlversion(3) */
+ size = hdr->size - sizeof(TfaDrc2_t);
+ err = tfaContWriteDrcFile(tfa, size, ((TfaDrc2_t *)hdr)->data);
+ }
+ else {
+ /*
+ * The DRC file is split as:
+ * 36 bytes for generic header (customer, application, and type)
+ * 127x3 (381) bytes first block contains the device and sample rate
+ * independent settings
+ * 127x3 (381) bytes block the device and sample rate specific values.
+ * The second block can always be recalculated from the first block,
+ * if vlsCal and the sample rate are known.
+ */
+ //size = hdr->size - sizeof(TfaDrc_t);
+ size = 381; /* fixed size for first block */
+
+ //+381 is done to only send the second part of the drc block
+ err = tfa98xx_dsp_write_drc(tfa, size, ((const unsigned char *)((TfaDrc_t *)hdr)->data + 381));
+ }
+ break;
+ case infoHdr:
+ /* Ignore */
+ break;
+ default:
+ pr_err("Header is of unknown type: 0x%x\n", type);
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ return err;
+}
+
+/**
+ * get the 1st of this dsc type this devicelist
+ */
+static TfaDescPtr_t *tfa_cnt_get_dsc(TfaContainer_t *cnt, TfaDescriptorType_t type, int dev_idx)
+{
+ TfaDeviceList_t *dev = tfaContDevice(cnt, dev_idx);
+ TfaDescPtr_t *_this;
+ int i;
+
+ if (!dev) {
+ return NULL;
+ }
+ /* process the list until a the type is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == (uint32_t)type) {
+ _this = (TfaDescPtr_t *)(dev->list[i].offset + (uint8_t *)cnt);
+ return _this;
+ }
+
+ }
+
+ return NULL;
+}
+
+/**
+ * get the device type from the patch in this devicelist
+ * - find the patch file for this devidx
+ * - return the devid from the patch or 0 if not found
+ */
+int tfa_cnt_get_devid(TfaContainer_t *cnt, int dev_idx)
+{
+ TfaPatch_t *patchfile;
+ TfaDescPtr_t *patchdsc;
+ uint8_t *patchheader;
+ unsigned short devid, checkaddress;
+ int checkvalue;
+
+ patchdsc = tfa_cnt_get_dsc(cnt, dscPatch, dev_idx);
+ if (!patchdsc) /* no patch for this device, assume non-i2c */
+ return 0;
+ patchdsc += 2; /* first the filename dsc and filesize, so skip them */
+ patchfile = (TfaPatch_t *)patchdsc;
+
+ patchheader = patchfile->data;
+
+ checkaddress = (patchheader[1] << 8) + patchheader[2];
+ checkvalue =
+ (patchheader[3] << 16) + (patchheader[4] << 8) + patchheader[5];
+
+ devid = patchheader[0];
+
+ if (checkaddress == 0xFFFF && checkvalue != 0xFFFFFF && checkvalue != 0) {
+ devid = patchheader[5] << 8 | patchheader[0]; /* full revid */
+ }
+
+ return devid;
+}
+
+/**
+ * get the firmware version from the patch in this devicelist
+ */
+int tfa_cnt_get_patch_version(struct tfa_device *tfa)
+{
+ TfaPatch_t *patchfile;
+ TfaDescPtr_t *patchdsc;
+ uint8_t *data;
+ int size, version;
+
+ if (tfa->cnt == NULL)
+ return -1;
+
+ patchdsc = tfa_cnt_get_dsc(tfa->cnt, dscPatch, tfa->dev_idx);
+ patchdsc += 2; /* first the filename dsc and filesize, so skip them */
+ patchfile = (TfaPatch_t *)patchdsc;
+
+ size = patchfile->hdr.size - sizeof(TfaPatch_t);
+ data = patchfile->data;
+
+ version = (data[size - 3] << 16) + (data[size - 2] << 8) + data[size - 1];
+
+ return version;
+}
+
+
+/*
+ * get the slave for the device if it exists
+ */
+enum Tfa98xx_Error tfaContGetSlave(struct tfa_device *tfa, uint8_t *slave_addr)
+{
+ TfaDeviceList_t *dev = NULL;
+
+ /* Make sure the cnt file is loaded */
+ if (tfa->cnt != NULL) {
+ dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ }
+
+ if (dev == NULL) {
+ /* Check if slave argument is used! */
+ if (gslave_address == 0) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ else {
+ *slave_addr = gslave_address;
+ return Tfa98xx_Error_Ok;
+ }
+ }
+
+ *slave_addr = dev->dev;
+ return Tfa98xx_Error_Ok;
+}
+
+/* If no container file is given, we can always have used the slave argument */
+void tfaContSetSlave(uint8_t slave_addr)
+{
+ gslave_address = slave_addr;
+}
+
+/*
+ * lookup slave and return device index
+ */
+int tfa_cont_get_idx(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev = NULL;
+ int i;
+
+ for (i = 0; i < tfa->cnt->ndev; i++) {
+ dev = tfaContDevice(tfa->cnt, i);
+ if (dev->dev == tfa->slave_address)
+ break;
+
+ }
+ if (i == tfa->cnt->ndev)
+ return -1;
+
+ return i;
+}
+
+/*
+ * write a bit field
+ */
+enum Tfa98xx_Error tfaRunWriteBitfield(struct tfa_device *tfa, TfaBitfield_t bf)
+{
+ enum Tfa98xx_Error error;
+ uint16_t value;
+ union {
+ uint16_t field;
+ TfaBfEnum_t Enum;
+ } bfUni;
+
+ value = bf.value;
+ bfUni.field = bf.field;
+#ifdef TFA_DEBUG
+ if (tfa->verbose)
+ pr_debug("bitfield: %s=0x%x (0x%x[%d..%d]=0x%x)\n", tfaContBfName(bfUni.field, tfa->rev), value,
+ bfUni.Enum.address, bfUni.Enum.pos, bfUni.Enum.pos + bfUni.Enum.len, value);
+#endif
+ error = tfa->dev_ops.tfa_set_bitfield(tfa, bfUni.field, value);
+
+ return error;
+}
+
+/*
+ * read a bit field
+ */
+enum Tfa98xx_Error tfaRunReadBitfield(struct tfa_device *tfa, TfaBitfield_t *bf)
+{
+ enum Tfa98xx_Error error;
+ union {
+ uint16_t field;
+ TfaBfEnum_t Enum;
+ } bfUni;
+ uint16_t regvalue, msk;
+
+ bfUni.field = bf->field;
+
+ error = tfa_reg_read(tfa, (unsigned char)(bfUni.Enum.address), &regvalue);
+ if (error) return error;
+
+ msk = ((1 << (bfUni.Enum.len + 1)) - 1) << bfUni.Enum.pos;
+
+ regvalue &= msk;
+ bf->value = regvalue >> bfUni.Enum.pos;
+
+ return error;
+}
+
+/*
+ dsp mem direct write
+ */
+static enum Tfa98xx_Error tfaRunWriteDspMem(struct tfa_device *tfa, TfaDspMem_t *cfmem)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int i;
+
+ for (i = 0; i < cfmem->size; i++) {
+ if (tfa->verbose)
+ pr_debug("dsp mem (%d): 0x%02x=0x%04x\n", cfmem->type, cfmem->address, cfmem->words[i]);
+
+ error = tfa_mem_write(tfa, cfmem->address++, cfmem->words[i], cfmem->type);
+ if (error) return error;
+ }
+
+ return error;
+}
+
+/*
+ * write filter payload to DSP
+ * note that the data is in an aligned union for all filter variants
+ * the aa data is used but it's the same for all of them
+ */
+static enum Tfa98xx_Error tfaRunWriteFilter(struct tfa_device *tfa, TfaContBiquad_t *bq)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ enum Tfa98xx_DMEM dmem;
+ uint16_t address;
+ uint8_t data[3 * 3 + sizeof(bq->aa.bytes)];
+ int i, channel = 0, runs = 1;
+ int8_t saved_index = bq->aa.index; /* This is used to set back the index */
+
+ /* Channel=1 is primary, Channel=2 is secondary*/
+ if (bq->aa.index > 100) {
+ bq->aa.index -= 100;
+ channel = 2;
+ }
+ else if (bq->aa.index > 50) {
+ bq->aa.index -= 50;
+ channel = 1;
+ }
+ else if ((tfa->rev & 0xff) == 0x88) {
+ runs = 2;
+ }
+
+ if (tfa->verbose) {
+ if (channel == 2)
+ pr_debug("filter[%d,S]", bq->aa.index);
+ else if (channel == 1)
+ pr_debug("filter[%d,P]", bq->aa.index);
+ else
+ pr_debug("filter[%d]", bq->aa.index);
+ }
+
+ for (i = 0; i < runs; i++) {
+ if (runs == 2)
+ channel++;
+
+ /* get the target address for the filter on this device */
+ dmem = tfa98xx_filter_mem(tfa, bq->aa.index, &address, channel);
+ if (dmem == Tfa98xx_DMEM_ERR) {
+ if (tfa->verbose) {
+ pr_debug("Warning: XFilter settings are applied via msg file (ini filter[x] format is skipped).\n");
+ }
+ /* Dont exit with an error here, We could continue without problems */
+ return Tfa98xx_Error_Ok;
+ }
+
+ /* send a DSP memory message that targets the devices specific memory for the filter
+ * msg params: which_mem, start_offset, num_words
+ */
+ memset(data, 0, 3 * 3);
+ data[2] = dmem; /* output[0] = which_mem */
+ data[4] = address >> 8; /* output[1] = start_offset */
+ data[5] = address & 0xff;
+ data[8] = sizeof(bq->aa.bytes) / 3; /*output[2] = num_words */
+ memcpy(&data[9], bq->aa.bytes, sizeof(bq->aa.bytes)); /* payload */
+
+ if (tfa->tfa_family == 2) {
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, FW_PAR_ID_SET_MEMORY, sizeof(data), data);
+ }
+ else {
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, 4 /* param */, sizeof(data), data);
+ }
+ }
+
+#ifdef TFA_DEBUG
+ if (tfa->verbose) {
+ if (bq->aa.index == 13) {
+ pr_debug("=%d,%.0f,%.2f \n",
+ bq->in.type, bq->in.cutOffFreq, bq->in.leakage);
+ }
+ else if (bq->aa.index >= 10 && bq->aa.index <= 12) {
+ pr_debug("=%d,%.0f,%.1f,%.1f \n", bq->aa.type,
+ bq->aa.cutOffFreq, bq->aa.rippleDb, bq->aa.rolloff);
+ }
+ else {
+ pr_debug("= unsupported filter index \n");
+ }
+ }
+#endif
+
+ /* Because we can load the same filters multiple times
+ * For example: When we switch profile we re-write in operating mode.
+ * We then need to remember the index (primary, secondary or both)
+ */
+ bq->aa.index = saved_index;
+
+ return error;
+}
+
+/*
+ * write the register based on the input address, value and mask
+ * only the part that is masked will be updated
+ */
+static enum Tfa98xx_Error tfaRunWriteRegister(struct tfa_device *tfa, TfaRegpatch_t *reg)
+{
+ enum Tfa98xx_Error error;
+ uint16_t value, newvalue;
+
+ if (tfa->verbose)
+ pr_debug("register: 0x%02x=0x%04x (msk=0x%04x)\n", reg->address, reg->value, reg->mask);
+
+ error = tfa_reg_read(tfa, reg->address, &value);
+ if (error) return error;
+
+ value &= ~reg->mask;
+ newvalue = reg->value & reg->mask;
+
+ value |= newvalue;
+ error = tfa_reg_write(tfa, reg->address, value);
+
+ return error;
+
+}
+
+// write reg and bitfield items in the devicelist to the target
+enum Tfa98xx_Error tfaContWriteRegsDev(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ TfaBitfield_t *bitF;
+ int i;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!dev) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ /* process the list until a patch, file of profile is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscPatch ||
+ dev->list[i].type == dscFile ||
+ dev->list[i].type == dscProfile) break;
+
+ if (dev->list[i].type == dscBitfield) {
+ bitF = (TfaBitfield_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaRunWriteBitfield(tfa, *bitF);
+ }
+ if (dev->list[i].type == dscRegister) {
+ err = tfaRunWriteRegister(tfa, (TfaRegpatch_t *)(dev->list[i].offset + (char*)tfa->cnt));
+ }
+
+ if (err) break;
+ }
+
+ return err;
+}
+
+// write reg and bitfield items in the profilelist the target
+enum Tfa98xx_Error tfaContWriteRegsProf(struct tfa_device *tfa, int prof_idx)
+{
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ TfaBitfield_t *bitf;
+ unsigned int i;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!prof) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose)
+ pr_debug("----- profile: %s (%d) -----\n", tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+
+ /* process the list until the end of the profile or the default section */
+ for (i = 0; i < prof->length; i++) {
+ /* We only want to write the values before the default section when we switch profile */
+ if (prof->list[i].type == dscDefault)
+ break;
+
+ if (prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaRunWriteBitfield(tfa, *bitf);
+ }
+ if (prof->list[i].type == dscRegister) {
+ err = tfaRunWriteRegister(tfa, (TfaRegpatch_t *)(prof->list[i].offset + (char*)tfa->cnt));
+ }
+ if (err) break;
+ }
+ return err;
+}
+
+// write patchfile in the devicelist to the target
+enum Tfa98xx_Error tfaContWritePatch(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ TfaFileDsc_t *file;
+ TfaPatch_t *patchfile;
+ int size, i;
+
+ if (!dev) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ /* process the list until a patch is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscPatch) {
+ file = (TfaFileDsc_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ patchfile = (TfaPatch_t *)&file->data;
+ if (tfa->verbose) tfaContShowHeader(&patchfile->hdr);
+ size = patchfile->hdr.size - sizeof(TfaPatch_t); // size is total length
+ err = tfa_dsp_patch(tfa, size, (const unsigned char *)patchfile->data);
+ if (err) return err;
+ }
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+
+/**
+ * Create a buffer which can be used to send to the dsp.
+ */
+static void create_dsp_buffer_msg(struct tfa_device *tfa, TfaMsg_t *msg, char *buffer, int *size)
+{
+ int i, nr = 0;
+
+ (void)tfa;
+
+ /* Copy cmdId. Remember that the cmdId is reversed */
+ buffer[nr++] = msg->cmdId[2];
+ buffer[nr++] = msg->cmdId[1];
+ buffer[nr++] = msg->cmdId[0];
+
+ /* Copy the data to the buffer */
+ for (i = 0; i < msg->msg_size; i++) {
+ buffer[nr++] = (uint8_t)((msg->data[i] >> 16) & 0xffff);
+ buffer[nr++] = (uint8_t)((msg->data[i] >> 8) & 0xff);
+ buffer[nr++] = (uint8_t)(msg->data[i] & 0xff);
+ }
+
+ *size = nr;
+}
+
+// write all param files in the devicelist to the target
+enum Tfa98xx_Error tfaContWriteFiles(struct tfa_device *tfa)
+{
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ TfaFileDsc_t *file;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ char buffer[(MEMTRACK_MAX_WORDS * 3) + 3] = { 0 }; //every word requires 3 and 3 is the msg
+ int i, size = 0;
+
+ if (!dev) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ /* process the list and write all files */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ if (tfaContWriteFile(tfa, file, 0, TFA_MAX_VSTEP_MSG_MARKER)) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ if (dev->list[i].type == dscSetInputSelect ||
+ dev->list[i].type == dscSetOutputSelect ||
+ dev->list[i].type == dscSetProgramConfig ||
+ dev->list[i].type == dscSetLagW ||
+ dev->list[i].type == dscSetGains ||
+ dev->list[i].type == dscSetvBatFactors ||
+ dev->list[i].type == dscSetSensesCal ||
+ dev->list[i].type == dscSetSensesDelay ||
+ dev->list[i].type == dscSetMBDrc ||
+ dev->list[i].type == dscSetFwkUseCase ||
+ dev->list[i].type == dscSetVddpConfig) {
+ create_dsp_buffer_msg(tfa, (TfaMsg_t *)
+ (dev->list[i].offset + (char*)tfa->cnt), buffer, &size);
+ if (tfa->verbose) {
+ pr_debug("command: %s=0x%02x%02x%02x \n",
+ tfaContGetCommandString(dev->list[i].type),
+ (unsigned char)buffer[0], (unsigned char)buffer[1], (unsigned char)buffer[2]);
+ }
+
+ err = tfa_dsp_msg(tfa, size, buffer);
+ }
+
+ if (dev->list[i].type == dscCmd) {
+ size = *(uint16_t *)(dev->list[i].offset + (char*)tfa->cnt);
+
+ err = tfa_dsp_msg(tfa, size, dev->list[i].offset + 2 + (char*)tfa->cnt);
+ if (tfa->verbose) {
+ const char *cmd_id = dev->list[i].offset + 2 + (char*)tfa->cnt;
+ pr_debug("Writing cmd=0x%02x%02x%02x \n", (uint8_t)cmd_id[0], (uint8_t)cmd_id[1], (uint8_t)cmd_id[2]);
+ }
+ }
+ if (err != Tfa98xx_Error_Ok)
+ break;
+
+ if (dev->list[i].type == dscCfMem) {
+ err = tfaRunWriteDspMem(tfa, (TfaDspMem_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt));
+ }
+
+ if (err != Tfa98xx_Error_Ok)
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * write all param files in the profilelist to the target
+ * this is used during startup when maybe ACS is set
+ */
+enum Tfa98xx_Error tfaContWriteFilesProf(struct tfa_device *tfa, int prof_idx, int vstep_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ char buffer[(MEMTRACK_MAX_WORDS * 3) + 3] = { 0 }; //every word requires 3 and 3 is the msg
+ unsigned int i;
+ TfaFileDsc_t *file;
+ TfaPatch_t *patchfile;
+ int size;
+
+ if (!prof) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ /* process the list and write all files */
+ for (i = 0; i < prof->length; i++) {
+ switch (prof->list[i].type) {
+ case dscFile:
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER);
+ break;
+ case dscPatch:
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ patchfile = (TfaPatch_t *)&file->data;
+ if (tfa->verbose) tfaContShowHeader(&patchfile->hdr);
+ size = patchfile->hdr.size - sizeof(TfaPatch_t); // size is total length
+ err = tfa_dsp_patch(tfa, size, (const unsigned char *)patchfile->data);
+ break;
+ case dscCfMem:
+ err = tfaRunWriteDspMem(tfa, (TfaDspMem_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt));
+ break;
+ case dscSetInputSelect:
+ case dscSetOutputSelect:
+ case dscSetProgramConfig:
+ case dscSetLagW:
+ case dscSetGains:
+ case dscSetvBatFactors:
+ case dscSetSensesCal:
+ case dscSetSensesDelay:
+ case dscSetMBDrc:
+ case dscSetFwkUseCase:
+ case dscSetVddpConfig:
+ create_dsp_buffer_msg(tfa, (TfaMsg_t *)
+ (prof->list[i].offset + (uint8_t *)tfa->cnt), buffer, &size);
+ if (tfa->verbose) {
+ pr_debug("command: %s=0x%02x%02x%02x \n",
+ tfaContGetCommandString(prof->list[i].type),
+ (unsigned char)buffer[0], (unsigned char)buffer[1], (unsigned char)buffer[2]);
+ }
+
+ err = tfa_dsp_msg(tfa, size, buffer);
+ break;
+ case dscCmd:
+ size = *(uint16_t *)(prof->list[i].offset + (char*)tfa->cnt);
+
+ err = tfa_dsp_msg(tfa, size, prof->list[i].offset + 2 + (char*)tfa->cnt);
+ if (tfa->verbose) {
+ const char *cmd_id = prof->list[i].offset + 2 + (char*)tfa->cnt;
+ pr_debug("Writing cmd=0x%02x%02x%02x \n", (uint8_t)cmd_id[0], (uint8_t)cmd_id[1], (uint8_t)cmd_id[2]);
+ }
+ break;
+ default:
+ /* ignore any other type */
+ break;
+ }
+ }
+
+ return err;
+}
+
+static enum Tfa98xx_Error tfaContWriteItem(struct tfa_device *tfa, TfaDescPtr_t * dsc)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaRegpatch_t *reg;
+ TfaMode_t *cas;
+ TfaBitfield_t *bitf;
+
+ // When no DSP should only write to HW registers.
+ if (tfa->ext_dsp == 0 && !(dsc->type == dscBitfield || dsc->type == dscRegister)) {
+ return Tfa98xx_Error_Ok;
+ }
+
+ switch (dsc->type) {
+ case dscDefault:
+ case dscDevice: // ignore
+ case dscProfile: // profile list
+ break;
+ case dscRegister: // register patch
+ reg = (TfaRegpatch_t *)(dsc->offset + (uint8_t *)tfa->cnt);
+ return tfaRunWriteRegister(tfa, reg);
+ //pr_debug("$0x%2x=0x%02x,0x%02x\n", reg->address, reg->mask, reg->value);
+ break;
+ case dscString: // ascii: zero terminated string
+ pr_debug(";string: %s\n", tfaContGetString(tfa->cnt, dsc));
+ break;
+ case dscFile: // filename + file contents
+ case dscPatch:
+ break;
+ case dscMode:
+ cas = (TfaMode_t *)(dsc->offset + (uint8_t *)tfa->cnt);
+ if (cas->value == Tfa98xx_Mode_RCV)
+ tfa98xx_select_mode(tfa, Tfa98xx_Mode_RCV);
+ else
+ tfa98xx_select_mode(tfa, Tfa98xx_Mode_Normal);
+ break;
+ case dscCfMem:
+ err = tfaRunWriteDspMem(tfa, (TfaDspMem_t *)(dsc->offset + (uint8_t *)tfa->cnt));
+ break;
+ case dscBitfield:
+ bitf = (TfaBitfield_t *)(dsc->offset + (uint8_t *)tfa->cnt);
+ return tfaRunWriteBitfield(tfa, *bitf);
+ break;
+ case dscFilter:
+ return tfaRunWriteFilter(tfa, (TfaContBiquad_t *)(dsc->offset + (uint8_t *)tfa->cnt));
+ break;
+ }
+
+ return err;
+}
+
+static unsigned int tfa98xx_sr_from_field(unsigned int field)
+{
+ switch (field) {
+ case 0:
+ return 8000;
+ case 1:
+ return 11025;
+ case 2:
+ return 12000;
+ case 3:
+ return 16000;
+ case 4:
+ return 22050;
+ case 5:
+ return 24000;
+ case 6:
+ return 32000;
+ case 7:
+ return 44100;
+ case 8:
+ return 48000;
+ default:
+ return 0;
+ }
+}
+
+enum Tfa98xx_Error tfa_write_filters(struct tfa_device *tfa, int prof_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ unsigned int i;
+ int status;
+
+ if (!prof) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose) {
+ pr_debug("----- profile: %s (%d) -----\n", tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+ pr_debug("Waiting for CLKS... \n");
+ }
+
+ for (i = 10; i > 0; i--) {
+ err = tfa98xx_dsp_system_stable(tfa, &status);
+ if (status)
+ break;
+ else
+ msleep_interruptible(10);
+ }
+
+ if (i == 0) {
+ if (tfa->verbose)
+ pr_err("Unable to write filters, CLKS=0 \n");
+
+ return Tfa98xx_Error_StateTimedOut;
+ }
+
+ /* process the list until the end of the profile or the default section */
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscFilter) {
+ if (tfaContWriteItem(tfa, &prof->list[i]) != Tfa98xx_Error_Ok)
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ return err;
+}
+
+unsigned int tfa98xx_get_profile_sr(struct tfa_device *tfa, unsigned int prof_idx)
+{
+ TfaBitfield_t *bitf;
+ unsigned int i;
+ TfaDeviceList_t *dev;
+ TfaProfileList_t *prof;
+ int fs_profile = -1;
+
+ dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ if (!dev)
+ return 0;
+
+ prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ if (!prof)
+ return 0;
+
+ /* Check profile fields first */
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscDefault)
+ break;
+
+ /* check for profile settingd (AUDFS) */
+ if (prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_profile = bitf->value;
+ break;
+ }
+ }
+ }
+
+ if (tfa->verbose)
+ pr_debug("%s - profile fs: 0x%x = %dHz (%d - %d)\n",
+ __FUNCTION__, fs_profile,
+ tfa98xx_sr_from_field(fs_profile),
+ tfa->dev_idx, prof_idx);
+
+ if (fs_profile != -1)
+ return tfa98xx_sr_from_field(fs_profile);
+
+ /* Check for container default setting */
+ /* process the list until a patch, file of profile is encountered */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscPatch ||
+ dev->list[i].type == dscFile ||
+ dev->list[i].type == dscProfile)
+ break;
+
+ if (dev->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_profile = bitf->value;
+ break;
+ }
+ }
+ /* Ignore register case */
+ }
+
+ if (tfa->verbose)
+ pr_debug("%s - default fs: 0x%x = %dHz (%d - %d)\n",
+ __FUNCTION__, fs_profile,
+ tfa98xx_sr_from_field(fs_profile),
+ tfa->dev_idx, prof_idx);
+
+ if (fs_profile != -1)
+ return tfa98xx_sr_from_field(fs_profile);
+
+ return 48000; /* default of HW */
+}
+
+static enum Tfa98xx_Error get_sample_rate_info(struct tfa_device *tfa, TfaProfileList_t *prof, TfaProfileList_t *previous_prof, int fs_previous_profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaBitfield_t *bitf;
+ unsigned int i;
+ int fs_default_profile = 8; /* default is 48kHz */
+ int fs_next_profile = 8; /* default is 48kHz */
+
+
+ /* ---------- default settings previous profile ---------- */
+ for (i = 0; i < previous_prof->length; i++) {
+ /* Search for the default section */
+ if (i == 0) {
+ while (previous_prof->list[i].type != dscDefault && i < previous_prof->length) {
+ i++;
+ }
+ i++;
+ }
+
+ /* Only if we found the default section search for AUDFS */
+ if (i < previous_prof->length) {
+ if (previous_prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(previous_prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_default_profile = bitf->value;
+ break;
+ }
+ }
+ }
+ }
+
+ /* ---------- settings next profile ---------- */
+ for (i = 0; i < prof->length; i++) {
+ /* We only want to write the values before the default section */
+ if (prof->list[i].type == dscDefault)
+ break;
+ /* search for AUDFS */
+ if (prof->list[i].type == dscBitfield) {
+ bitf = (TfaBitfield_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ if (bitf->field == TFA_FAM(tfa, AUDFS)) {
+ fs_next_profile = bitf->value;
+ break;
+ }
+ }
+ }
+
+ /* Enable if needed for debugging!
+ if (tfa->verbose) {
+ pr_debug("sample rate from the previous profile: %d \n", fs_previous_profile);
+ pr_debug("sample rate in the default section: %d \n", fs_default_profile);
+ pr_debug("sample rate for the next profile: %d \n", fs_next_profile);
+ }
+ */
+
+ if (fs_next_profile != fs_default_profile) {
+ if (tfa->verbose)
+ pr_debug("Writing delay tables for AUDFS=%d \n", fs_next_profile);
+
+ /* If the AUDFS from the next profile is not the same as
+ * the AUDFS from the default we need to write new delay tables
+ */
+ err = tfa98xx_dsp_write_tables(tfa, fs_next_profile);
+ }
+ else if (fs_default_profile != fs_previous_profile) {
+ if (tfa->verbose)
+ pr_debug("Writing delay tables for AUDFS=%d \n", fs_default_profile);
+
+ /* But if we do not have a new AUDFS in the next profile and
+ * the AUDFS from the default profile is not the same as the AUDFS
+ * from the previous profile we also need to write new delay tables
+ */
+ err = tfa98xx_dsp_write_tables(tfa, fs_default_profile);
+ }
+
+ return err;
+}
+/*
+ * process all items in the profilelist
+ * NOTE an error return during processing will leave the device muted
+ *
+ */
+enum Tfa98xx_Error tfaContWriteProfile(struct tfa_device *tfa, int prof_idx, int vstep_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ TfaProfileList_t *previous_prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, tfa_dev_get_swprof(tfa));
+ char buffer[(MEMTRACK_MAX_WORDS * 4) + 4] = { 0 }; //every word requires 3 or 4 bytes, and 3 or 4 is the msg
+ unsigned int i, k = 0, j = 0, tries = 0;
+ TfaFileDsc_t *file;
+ int manstate, size = 0, ready, fs_previous_profile = 8; /* default fs is 48kHz*/
+
+ if (!prof || !previous_prof) {
+ pr_err("Error trying to get the (previous) swprofile \n");
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (tfa->verbose) {
+ tfa98xx_trace_printk("device:%s profile:%s vstep:%d\n", tfaContDeviceName(tfa->cnt, tfa->dev_idx),
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx), vstep_idx);
+ }
+
+ /* We only make a power cycle when the profiles are not in the same group */
+ if (prof->group == previous_prof->group && prof->group != 0) {
+ if (tfa->verbose) {
+ pr_debug("The new profile (%s) is in the same group as the current profile (%s) \n",
+ tfaContGetString(tfa->cnt, &prof->name), tfaContGetString(tfa->cnt, &previous_prof->name));
+ }
+ }
+ else {
+ /* mute */
+ err = tfaRunMute(tfa);
+ if (err) return err;
+
+ /* Get current sample rate before we start switching */
+ fs_previous_profile = TFA_GET_BF(tfa, AUDFS);
+
+ /* clear SBSL to make sure we stay in initCF state */
+ if (tfa->tfa_family == 2) {
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 0);
+ }
+
+ /* When we switch profile we first power down the subsystem
+ * This should only be done when we are in operating mode
+ */
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ if (((tfa->tfa_family == 2) && (manstate >= 6)) || (tfa->tfa_family != 2)) {
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err) return err;
+
+ /* Wait until we are in PLL powerdown */
+ tries = 0;
+ do {
+ err = tfa98xx_dsp_system_stable(tfa, &ready);
+
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ if (manstate == 6) {
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err) return err;
+ } else if (manstate == 0) {
+ /* Reset SBSL back after powering down */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 0);
+ }
+
+ if (!ready)
+ break;
+ else
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ tries++;
+ } while (tries <= 100);
+
+ if (tries > 100) {
+ pr_debug("Wait for PLL powerdown timed out!\n");
+ return Tfa98xx_Error_StateTimedOut;
+ }
+ }
+ else {
+ pr_debug("No need to go to powerdown now \n");
+ }
+ }
+
+ /* set all bitfield settings */
+ /* First set all default settings */
+ if (tfa->verbose) {
+ pr_debug("---------- default settings profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &previous_prof->name), tfa_dev_get_swprof(tfa));
+ }
+
+ err = tfa_show_current_state(tfa);
+
+ /* Loop profile length */
+ for (i = 0; i < previous_prof->length; i++) {
+ /* Search for the default section */
+ if (i == 0) {
+ while (previous_prof->list[i].type != dscDefault && i < previous_prof->length) {
+ i++;
+ }
+ i++;
+ }
+
+ /* Only if we found the default section try writing the items */
+ if (i < previous_prof->length) {
+ if (tfaContWriteItem(tfa, &previous_prof->list[i]) != Tfa98xx_Error_Ok)
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ if (tfa->verbose)
+ pr_debug("---------- new settings profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+
+ /* set new settings */
+ for (i = 0; i < prof->length; i++) {
+ /* Remember where we currently are with writing items*/
+ j = i;
+
+ /* We only want to write the values before the default section when we switch profile */
+ /* process and write all non-file items */
+ switch (prof->list[i].type) {
+ case dscFile:
+ case dscPatch:
+ case dscSetInputSelect:
+ case dscSetOutputSelect:
+ case dscSetProgramConfig:
+ case dscSetLagW:
+ case dscSetGains:
+ case dscSetvBatFactors:
+ case dscSetSensesCal:
+ case dscSetSensesDelay:
+ case dscSetMBDrc:
+ case dscSetFwkUseCase:
+ case dscSetVddpConfig:
+ case dscCmd:
+ case dscFilter:
+ case dscDefault:
+ /* When one of these files are found, we exit */
+ i = prof->length;
+ break;
+ default:
+ err = tfaContWriteItem(tfa, &prof->list[i]);
+ if (err != Tfa98xx_Error_Ok)
+ return Tfa98xx_Error_Bad_Parameter;
+ break;
+ }
+ }
+
+ if (strstr(tfaContGetString(tfa->cnt, &prof->name), ".standby") != NULL) {
+ pr_info("Keep power down without writing files, in standby profile!\n");
+
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err) return err;
+
+ /* Wait until we are in PLL powerdown */
+ tries = 0;
+ do {
+ err = tfa98xx_dsp_system_stable(tfa, &ready);
+ if (!ready)
+ break;
+ else
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ tries++;
+ } while (tries <= 100);
+
+ if (tries > 100) {
+ pr_debug("Wait for PLL powerdown timed out!\n");
+ return Tfa98xx_Error_StateTimedOut;
+ }
+
+ err = tfa_show_current_state(tfa);
+
+ return err;
+ }
+
+ if (prof->group != previous_prof->group || prof->group == 0) {
+ if (tfa->tfa_family == 2)
+ TFA_SET_BF_VOLATILE(tfa, MANSCONF, 1);
+
+ /* Leave powerdown state */
+ err = tfa_cf_powerup(tfa);
+ if (err) return err;
+
+ err = tfa_show_current_state(tfa);
+
+ if (tfa->tfa_family == 2) {
+ /* Reset SBSL to 0 (workaround of enbl_powerswitch=0) */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 0);
+ /* Sending commands to DSP we need to make sure RST is 0 (otherwise we get no response)*/
+ TFA_SET_BF(tfa, RST, 0);
+ }
+ }
+
+ /* Check if there are sample rate changes */
+ err = get_sample_rate_info(tfa, prof, previous_prof, fs_previous_profile);
+ if (err) return err;
+
+
+ /* Write files from previous profile (default section)
+ * Should only be used for the patch&trap patch (file)
+ */
+ if (tfa->ext_dsp != 0) {
+ if (tfa->tfa_family == 2) {
+ for (i = 0; i < previous_prof->length; i++) {
+ /* Search for the default section */
+ if (i == 0) {
+ while (previous_prof->list[i].type != dscDefault && i < previous_prof->length) {
+ i++;
+ }
+ i++;
+ }
+
+ /* Only if we found the default section try writing the file */
+ if (i < previous_prof->length) {
+ if (previous_prof->list[i].type == dscFile || previous_prof->list[i].type == dscPatch) {
+ /* Only write this once */
+ if (tfa->verbose && k == 0) {
+ pr_debug("---------- files default profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &previous_prof->name), prof_idx);
+ k++;
+ }
+ file = (TfaFileDsc_t *)(previous_prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER);
+ }
+ }
+ }
+ }
+
+ if (tfa->verbose) {
+ pr_debug("---------- files new profile: %s (%d) ---------- \n",
+ tfaContGetString(tfa->cnt, &prof->name), prof_idx);
+ }
+ }
+
+ /* write everything until end or the default section starts
+ * Start where we currenly left */
+ for (i = j; i < prof->length; i++) {
+ /* We only want to write the values before the default section when we switch profile */
+
+ if (prof->list[i].type == dscDefault) {
+ break;
+ }
+
+ switch (prof->list[i].type) {
+ case dscFile:
+ case dscPatch:
+ /* For tiberius stereo 1 device does not have a dsp! */
+ if (tfa->ext_dsp != 0) {
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ err = tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER);
+ }
+ break;
+ case dscSetInputSelect:
+ case dscSetOutputSelect:
+ case dscSetProgramConfig:
+ case dscSetLagW:
+ case dscSetGains:
+ case dscSetvBatFactors:
+ case dscSetSensesCal:
+ case dscSetSensesDelay:
+ case dscSetMBDrc:
+ case dscSetFwkUseCase:
+ case dscSetVddpConfig:
+ /* For tiberius stereo 1 device does not have a dsp! */
+ if (tfa->ext_dsp != 0) {
+ create_dsp_buffer_msg(tfa, (TfaMsg_t *)
+ (prof->list[i].offset + (char*)tfa->cnt), buffer, &size);
+ err = tfa_dsp_msg(tfa, size, buffer);
+
+ if (tfa->verbose) {
+ pr_debug("command: %s=0x%02x%02x%02x \n",
+ tfaContGetCommandString(prof->list[i].type),
+ (unsigned char)buffer[0], (unsigned char)buffer[1], (unsigned char)buffer[2]);
+ }
+ }
+ break;
+ case dscCmd:
+ /* For tiberius stereo 1 device does not have a dsp! */
+ if (tfa->ext_dsp != 0) {
+ size = *(uint16_t *)(prof->list[i].offset + (char*)tfa->cnt);
+ err = tfa_dsp_msg(tfa, size, prof->list[i].offset + 2 + (char*)tfa->cnt);
+ if (tfa->verbose) {
+ const char *cmd_id = prof->list[i].offset + 2 + (char*)tfa->cnt;
+ pr_debug("Writing cmd=0x%02x%02x%02x \n", (uint8_t)cmd_id[0], (uint8_t)cmd_id[1], (uint8_t)cmd_id[2]);
+ }
+ }
+ break;
+ default:
+ /* This allows us to write bitfield, registers or xmem after files */
+ if (tfaContWriteItem(tfa, &prof->list[i]) != Tfa98xx_Error_Ok) {
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+ break;
+ }
+
+ if (err != Tfa98xx_Error_Ok) {
+ return err;
+ }
+ }
+
+ if ((prof->group != previous_prof->group || prof->group == 0) && (tfa->tfa_family == 2)) {
+ if (TFA_GET_BF(tfa, REFCKSEL) == 0) {
+ /* set SBSL to go to operation mode */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+ }
+ }
+
+ return err;
+}
+
+/*
+ * process only vstep in the profilelist
+ *
+ */
+enum Tfa98xx_Error tfaContWriteFilesVstep(struct tfa_device *tfa, int prof_idx, int vstep_idx)
+{
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ unsigned int i;
+ TfaFileDsc_t *file;
+ TfaHeader_t *hdr;
+ TfaHeaderType_t type;
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!prof)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ if (tfa->verbose)
+ tfa98xx_trace_printk("device:%s profile:%s vstep:%d\n", tfaContDeviceName(tfa->cnt, tfa->dev_idx),
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx), vstep_idx);
+
+ /* write vstep file only! */
+ for (i = 0; i < prof->length; i++) {
+ if (prof->list[i].type == dscFile) {
+ file = (TfaFileDsc_t *)(prof->list[i].offset + (uint8_t *)tfa->cnt);
+ hdr = (TfaHeader_t *)file->data;
+ type = (TfaHeaderType_t)hdr->id;
+
+ switch (type) {
+ case volstepHdr:
+ if (tfaContWriteFile(tfa, file, vstep_idx, TFA_MAX_VSTEP_MSG_MARKER))
+ return Tfa98xx_Error_Bad_Parameter;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return err;
+}
+
+char *tfaContGetString(TfaContainer_t *cnt, TfaDescPtr_t *dsc)
+{
+ if (dsc->type != dscString)
+ return "Undefined string";
+
+ return dsc->offset + (char*)cnt;
+}
+
+char *tfaContGetCommandString(uint32_t type)
+{
+ if (type == dscSetInputSelect)
+ return "SetInputSelector";
+ else if (type == dscSetOutputSelect)
+ return "SetOutputSelector";
+ else if (type == dscSetProgramConfig)
+ return "SetProgramConfig";
+ else if (type == dscSetLagW)
+ return "SetLagW";
+ else if (type == dscSetGains)
+ return "SetGains";
+ else if (type == dscSetvBatFactors)
+ return "SetvBatFactors";
+ else if (type == dscSetSensesCal)
+ return "SetSensesCal";
+ else if (type == dscSetSensesDelay)
+ return "SetSensesDelay";
+ else if (type == dscSetMBDrc)
+ return "SetMBDrc";
+ else if (type == dscSetFwkUseCase)
+ return "SetFwkUseCase";
+ else if (type == dscSetVddpConfig)
+ return "SetVddpConfig";
+ else if (type == dscFilter)
+ return "filter";
+ else
+ return "Undefined string";
+}
+
+/*
+ * Get the name of the device at a certain index in the container file
+ * return device name
+ */
+char *tfaContDeviceName(TfaContainer_t *cnt, int dev_idx)
+{
+ TfaDeviceList_t *dev;
+
+ dev = tfaContDevice(cnt, dev_idx);
+ if (dev == NULL)
+ return "!ERROR!";
+
+ return tfaContGetString(cnt, &dev->name);
+}
+
+/*
+ * Get the application name from the container file application field
+ * note that the input stringbuffer should be sizeof(application field)+1
+ *
+ */
+int tfa_cnt_get_app_name(struct tfa_device *tfa, char *name)
+{
+ unsigned int i;
+ int len = 0;
+
+ for (i = 0; i < sizeof(tfa->cnt->application); i++) {
+ if (isalnum(tfa->cnt->application[i])) /* copy char if valid */
+ name[len++] = tfa->cnt->application[i];
+ if (tfa->cnt->application[i] == '\0')
+ break;
+ }
+ name[len++] = '\0';
+
+ return len;
+}
+
+/*
+ * Get profile index of the calibration profile.
+ * Returns: (profile index) if found, (-2) if no
+ * calibration profile is found or (-1) on error
+ */
+int tfaContGetCalProfile(struct tfa_device *tfa)
+{
+ int prof, cal_idx = -2;
+
+ if ((tfa->dev_idx < 0) || (tfa->dev_idx >= tfa->cnt->ndev))
+ return -1;
+
+ /* search for the calibration profile in the list of profiles */
+ for (prof = 0; prof < tfa->cnt->nprof; prof++) {
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, prof), ".cal") != NULL) {
+ cal_idx = prof;
+ pr_debug("Using calibration profile: '%s'\n", tfaContProfileName(tfa->cnt, tfa->dev_idx, prof));
+ break;
+ }
+ }
+
+ return cal_idx;
+}
+
+/**
+ * Is the profile a tap profile
+ */
+int tfaContIsTapProfile(struct tfa_device *tfa, int prof_idx)
+{
+ if ((tfa->dev_idx < 0) || (tfa->dev_idx >= tfa->cnt->ndev))
+ return -1;
+
+ /* Check if next profile is tap profile */
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx), ".tap") != NULL) {
+ pr_debug("Using Tap profile: '%s'\n", tfaContProfileName(tfa->cnt, tfa->dev_idx, prof_idx));
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the name of the profile at certain index for a device in the container file
+ * return profile name
+ */
+char *tfaContProfileName(TfaContainer_t *cnt, int dev_idx, int prof_idx)
+{
+ TfaProfileList_t *prof = NULL;
+
+ /* the Nth profiles for this device */
+ prof = tfaContGetDevProfList(cnt, dev_idx, prof_idx);
+
+ /* If the index is out of bound */
+ if (prof == NULL)
+ return "NONE";
+
+ return tfaContGetString(cnt, &prof->name);
+}
+
+/*
+ * return 1st profile list
+ */
+TfaProfileList_t *tfaContGet1stProfList(TfaContainer_t * cont)
+{
+ TfaProfileList_t *prof;
+ uint8_t *b = (uint8_t *)cont;
+
+ int maxdev = 0;
+ TfaDeviceList_t *dev;
+
+ // get nr of devlists
+ maxdev = cont->ndev;
+ // get last devlist
+ dev = tfaContGetDevList(cont, maxdev - 1);
+ if (dev == NULL)
+ return NULL;
+ // the 1st profile starts after the last device list
+ b = (uint8_t *)dev + sizeof(TfaDeviceList_t) + dev->length * (sizeof(TfaDescPtr_t));
+ prof = (TfaProfileList_t *)b;
+ return prof;
+}
+
+/*
+ * return 1st livedata list
+ */
+TfaLiveDataList_t *tfaContGet1stLiveDataList(TfaContainer_t * cont)
+{
+ TfaLiveDataList_t *ldata;
+ TfaProfileList_t *prof;
+ TfaDeviceList_t *dev;
+ uint8_t *b = (uint8_t *)cont;
+ int maxdev, maxprof;
+
+ // get nr of devlists+1
+ maxdev = cont->ndev;
+ // get nr of proflists
+ maxprof = cont->nprof;
+
+ // get last devlist
+ dev = tfaContGetDevList(cont, maxdev - 1);
+ // the 1st livedata starts after the last device list
+ b = (uint8_t *)dev + sizeof(TfaDeviceList_t) +
+ dev->length * (sizeof(TfaDescPtr_t));
+
+ while (maxprof != 0) {
+ // get last proflist
+ prof = (TfaProfileList_t *)b;
+ b += sizeof(TfaProfileList_t) +
+ ((prof->length - 1) * (sizeof(TfaDescPtr_t)));
+ maxprof--;
+ }
+
+ /* Else the marker falls off */
+ b += 4; //bytes
+
+ ldata = (TfaLiveDataList_t *)b;
+ return ldata;
+}
+
+/*
+ * return the device list pointer
+ */
+TfaDeviceList_t *tfaContDevice(TfaContainer_t *cnt, int dev_idx)
+{
+ return tfaContGetDevList(cnt, dev_idx);
+}
+
+/*
+ * return the next profile:
+ * - assume that all profiles are adjacent
+ * - calculate the total length of the input
+ * - the input profile + its length is the next profile
+ */
+TfaProfileList_t* tfaContNextProfile(TfaProfileList_t* prof) {
+ uint8_t *this, *next; /* byte pointers for byte pointer arithmetic */
+ TfaProfileList_t* nextprof;
+ int listlength; /* total length of list in bytes */
+
+ if (prof == NULL)
+ return NULL;
+
+ if (prof->ID != TFA_PROFID)
+ return NULL; /* invalid input */
+
+ this = (uint8_t *)prof;
+ /* nr of items in the list, length includes name dsc so - 1*/
+ listlength = (prof->length - 1) * sizeof(TfaDescPtr_t);
+ /* the sizeof(TfaProfileList_t) includes the list[0] length */
+ next = this + listlength + sizeof(TfaProfileList_t);// - sizeof(TfaDescPtr_t);
+ nextprof = (TfaProfileList_t *)next;
+
+ if (nextprof->ID != TFA_PROFID)
+ return NULL;
+
+ return nextprof;
+}
+
+/*
+ * return the next livedata
+ */
+TfaLiveDataList_t* tfaContNextLiveData(TfaLiveDataList_t* livedata) {
+ TfaLiveDataList_t* nextlivedata = (TfaLiveDataList_t *)((char*)livedata + (livedata->length * 4) +
+ sizeof(TfaLiveDataList_t) - 4);
+
+ if (nextlivedata->ID == TFA_LIVEDATAID)
+ return nextlivedata;
+
+ return NULL;
+}
+
+/*
+ * check CRC for container
+ * CRC is calculated over the bytes following the CRC field
+ *
+ * return non zero value on error
+ */
+int tfaContCrcCheckContainer(TfaContainer_t *cont)
+{
+ uint8_t *base;
+ size_t size;
+ uint32_t crc;
+
+ base = (uint8_t *)&cont->CRC + 4; // ptr to bytes following the CRC field
+ size = (size_t)(cont->size - (base - (uint8_t *)cont)); // nr of bytes following the CRC field
+ crc = ~crc32_le(~0u, base, size);
+
+ return crc != cont->CRC;
+}
+
+static void get_all_features_from_cnt(struct tfa_device *tfa, int *hw_feature_register, int sw_feature_register[2])
+{
+ TfaFeatures_t *features;
+ int i;
+
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+
+ /* Init values in case no keyword is defined in cnt file: */
+ *hw_feature_register = -1;
+ sw_feature_register[0] = -1;
+ sw_feature_register[1] = -1;
+
+ if (dev == NULL)
+ return;
+
+ // process the device list
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscFeatures) {
+ features = (TfaFeatures_t *)(dev->list[i].offset + (uint8_t *)tfa->cnt);
+ *hw_feature_register = features->value[0];
+ sw_feature_register[0] = features->value[1];
+ sw_feature_register[1] = features->value[2];
+ break;
+ }
+ }
+}
+
+/* wrapper function */
+void tfa_get_hw_features_from_cnt(struct tfa_device *tfa, int *hw_feature_register)
+{
+ int sw_feature_register[2];
+ get_all_features_from_cnt(tfa, hw_feature_register, sw_feature_register);
+}
+
+/* wrapper function */
+void tfa_get_sw_features_from_cnt(struct tfa_device *tfa, int sw_feature_register[2])
+{
+ int hw_feature_register;
+ get_all_features_from_cnt(tfa, &hw_feature_register, sw_feature_register);
+}
+
+enum Tfa98xx_Error tfa98xx_factory_trimmer(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.factory_trimmer)(tfa);
+}
+enum Tfa98xx_Error tfa98xx_set_phase_shift(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.phase_shift)(tfa);
+}
+enum Tfa98xx_Error tfa_set_filters(struct tfa_device *tfa, int prof_idx)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaProfileList_t *prof = tfaContGetDevProfList(tfa->cnt, tfa->dev_idx, prof_idx);
+ unsigned int i;
+
+ if (!prof)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ /* If we are in powerdown there is no need to set filters */
+ if (TFA_GET_BF(tfa, PWDN) == 1)
+ return Tfa98xx_Error_Ok;
+
+ /* loop the profile to find filter settings */
+ for (i = 0; i < prof->length; i++) {
+ /* We only want to write the values before the default section */
+ if (prof->list[i].type == dscDefault)
+ break;
+
+ /* write all filter settings */
+ if (prof->list[i].type == dscFilter) {
+ if (tfaContWriteItem(tfa, &prof->list[i]) != Tfa98xx_Error_Ok)
+ return err;
+ }
+ }
+
+ return err;
+}
+
+int tfa_tib_dsp_msgmulti(struct tfa_device *tfa, int length, const char *buffer)
+{
+ uint8_t *buf = (uint8_t *)buffer;
+ static uint8_t *blob = NULL, *blobptr; /* TODO: not multi-thread safe */
+ static int total = 0; /* TODO: not multi-thread safe */
+ int post_len = 0;
+
+ /* checks for 24b_BE or 32_LE */
+ int len_word_in_bytes = (tfa->convert_dsp32) ? 4 : 3;
+ /* TODO: get rid of these magic constants max size should depend on the tfa device type */
+ int tfadsp_max_msg_size = (tfa->convert_dsp32) ? 5336 : 4000;
+
+ /* No data found*/
+ if (length == -1 && blob == NULL) {
+ return -1;
+ }
+
+ if (length == -1) {
+ int i;
+ /* set last length field to zero */
+ for (i = total; i < (total + len_word_in_bytes); i++) {
+ blob[i] = 0;
+ }
+ total += len_word_in_bytes;
+ memcpy(buf, blob, total);
+
+ kfree(blob);
+ blob = NULL; /* Set to NULL pointer, otherwise no new malloc is done! */
+ return total;
+ }
+
+ if (blob == NULL) {
+ if (tfa->verbose)
+ pr_debug("%s, Creating the multi-message \n\n", __FUNCTION__);
+
+ blob = kmalloc(tfadsp_max_msg_size, GFP_KERNEL);
+ /* add command ID for multi-msg = 0x008015 */
+ if (tfa->convert_dsp32) {
+ blob[0] = 0x15;
+ blob[1] = 0x80;
+ blob[2] = 0x0;
+ blob[3] = 0x0;
+ }
+ else {
+ blob[0] = 0x0;
+ blob[1] = 0x80;
+ blob[2] = 0x15;
+ }
+ blobptr = blob;
+ blobptr += len_word_in_bytes;
+ total = len_word_in_bytes;
+ }
+
+ if (tfa->verbose) {
+ pr_debug("%s, id:0x%02x%02x%02x, length:%d \n", __FUNCTION__, buf[0], buf[1], buf[2], length);
+ }
+
+ /* check total message size after concatination */
+ post_len = total + length + (2 * len_word_in_bytes);
+ if (post_len > tfadsp_max_msg_size) {
+ //pr_debug("New multi-message too large! (%d >= %d (max.)), current length: %d\n", post_len, tfadsp_max_msg_size, total);
+ return Tfa98xx_Error_Buffer_too_small;
+ }
+
+ /* add length field (length in words) to the multi message */
+ if (tfa->convert_dsp32) {
+ *blobptr++ = (uint8_t)((length / len_word_in_bytes) & 0xff); /* lsb */
+ *blobptr++ = (uint8_t)(((length / len_word_in_bytes) & 0xff00) >> 8); /* msb */
+ *blobptr++ = 0x0;
+ *blobptr++ = 0x0;
+ }
+ else {
+ *blobptr++ = 0x0;
+ *blobptr++ = (uint8_t)(((length / len_word_in_bytes) & 0xff00) >> 8); /* msb */
+ *blobptr++ = (uint8_t)((length / len_word_in_bytes) & 0xff); /* lsb */
+ }
+ memcpy(blobptr, buf, length);
+ blobptr += length;
+ total += (length + len_word_in_bytes);
+
+ /* SetRe25 message is always the last message of the multi-msg */
+ if (tfa->convert_dsp32) {
+ if (buf[1] == 0x81 && buf[0] == SB_PARAM_SET_RE25C) {
+ return 1; /* 1 means last message is done! */
+ }
+ }
+ else {
+ if (buf[1] == 0x81 && buf[2] == SB_PARAM_SET_RE25C) {
+ return 1; /* 1 means last message is done! */
+ }
+ }
+
+ return 0;
+}
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_container.h b/sound/soc/codecs/tfa98xx-downstream/tfa_container.h
new file mode 100644
index 00000000000..477a9263151
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_container.h
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/*
+ * tfaContainer.h
+ *
+ * Created on: Sep 11, 2013
+ * Author: wim
+ */
+
+#ifndef TFACONTAINER_H_
+#define TFACONTAINER_H_
+
+/* static limits */
+#define TFACONT_MAXDEVS (4) /* maximum nr of devices */
+#define TFACONT_MAXPROFS (16) /* maximum nr of profiles */
+
+#include "tfa98xx_parameters.h"
+
+/**
+* Pass the container buffer, initialize and allocate internal memory.
+*
+* @param cnt pointer to the start of the buffer holding the container file
+* @param length of the data in bytes
+* @return
+* - tfa_error_ok if normal
+* - tfa_error_container invalid container data
+* - tfa_error_bad_param invalid parameter
+*
+*/
+enum tfa_error tfa_load_cnt(void *cnt, int length);
+
+/**
+ * Return the descriptor string
+ * @param cnt pointer to the container struct
+ * @param dsc pointer to Tfa descriptor
+ * @return descriptor string
+ */
+char *tfaContGetString(TfaContainer_t *cnt, TfaDescPtr_t *dsc);
+
+/**
+ * Gets the string for the given command type number
+ * @param type number representing a command
+ * @return string of a command
+ */
+char *tfaContGetCommandString(uint32_t type);
+
+/**
+ * get the device type from the patch in this devicelist
+ * - find the patch file for this devidx
+ * - return the devid from the patch or 0 if not found
+ * @param cnt pointer to container file
+ * @param dev_idx device index
+ * @return descriptor string
+ */
+int tfa_cnt_get_devid(TfaContainer_t *cnt, int dev_idx);
+
+/**
+ * Get the slave for the device if it exists.
+ * @param tfa the device struct pointer
+ * @param slave_addr the index of the device
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContGetSlave(struct tfa_device *tfa, uint8_t *slave_addr);
+
+void tfaContSetSlave(uint8_t slave_addr);
+
+/**
+ * Get the index for a skave address.
+ * @param tfa the device struct pointer
+ * @return the device index
+ */
+int tfa_cont_get_idx(struct tfa_device *tfa);
+
+/**
+ * Write reg and bitfield items in the devicelist to the target.
+ * @param tfa the device struct pointer
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteRegsDev(struct tfa_device *tfa);
+
+/**
+ * Write reg and bitfield items in the profilelist to the target.
+ * @param tfa the device struct pointer
+ * @param prof_idx the profile index
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteRegsProf(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Write a patchfile in the devicelist to the target.
+ * @param tfa the device struct pointer
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWritePatch(struct tfa_device *tfa);
+
+/**
+ * Write all param files in the devicelist to the target.
+ * @param tfa the device struct pointer
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteFiles(struct tfa_device *tfa);
+
+/**
+ * Get sample rate from passed profile index
+ * @param tfa the device struct pointer
+ * @param prof_idx the index of the profile
+ * @return sample rate value
+ */
+unsigned int tfa98xx_get_profile_sr(struct tfa_device *tfa, unsigned int prof_idx);
+
+/**
+ * Get the device name string
+ * @param cnt the pointer to the container struct
+ * @param dev_idx the index of the device
+ * @return device name string or error string if not found
+ */
+char *tfaContDeviceName(TfaContainer_t *cnt, int dev_idx);
+
+/**
+ * Get the application name from the container file application field
+ * @param tfa the device struct pointer
+ * @param name the input stringbuffer with size: sizeof(application field)+1
+ * @return actual string length
+ */
+int tfa_cnt_get_app_name(struct tfa_device *tfa, char *name);
+
+/**
+ * Get profile index of the calibration profile
+ * @param tfa the device struct pointer
+ * @return profile index, -2 if no calibration profile is found or -1 on error
+ */
+int tfaContGetCalProfile(struct tfa_device *tfa);
+
+/**
+ * Is the profile a tap profile ?
+ * @param tfa the device struct pointer
+ * @param prof_idx the index of the profile
+ * @return 1 if the profile is a tap profile or 0 if not
+ */
+int tfaContIsTapProfile(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Get the name of the profile at certain index for a device in the container file
+ * @param cnt the pointer to the container struct
+ * @param dev_idx the index of the device
+ * @param prof_idx the index of the profile
+ * @return profile name string or error string if not found
+ */
+char *tfaContProfileName(TfaContainer_t *cnt, int dev_idx, int prof_idx);
+
+/**
+ * Process all items in the profilelist
+ * NOTE an error return during processing will leave the device muted
+ * @param tfa the device struct pointer
+ * @param prof_idx index of the profile
+ * @param vstep_idx index of the vstep
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteProfile(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+
+/**
+ * Specify the speaker configurations (cmd id) (Left, right, both, none)
+ * @param dev_idx index of the device
+ * @param configuration name string of the configuration
+ */
+void tfa98xx_set_spkr_select(int dev_idx, char *configuration);
+
+enum Tfa98xx_Error tfa_cont_write_filterbank(struct tfa_device *tfa, TfaFilter_t *filter);
+
+/**
+ * Write all param files in the profilelist to the target
+ * this is used during startup when maybe ACS is set
+ * @param tfa the device struct pointer
+ * @param prof_idx the index of the profile
+ * @param vstep_idx the index of the vstep
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteFilesProf(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+enum Tfa98xx_Error tfaContWriteFilesVstep(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+enum Tfa98xx_Error tfaContWriteDrcFile(struct tfa_device *tfa, int size, uint8_t data[]);
+
+/**
+ * Get the device list dsc from the tfaContainer
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @return device list pointer
+ */
+TfaDeviceList_t *tfaContGetDevList(TfaContainer_t *cont, int dev_idx);
+
+/**
+ * Get the Nth profile for the Nth device
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @param prof_idx the index of the profile
+ * @return profile list pointer
+ */
+TfaProfileList_t *tfaContGetDevProfList(TfaContainer_t *cont, int dev_idx, int prof_idx);
+
+/**
+ * Get the number of profiles for device from contaienr
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @return device list pointer
+ */
+int tfa_cnt_get_dev_nprof(struct tfa_device *tfa);
+
+
+/**
+ * Get the Nth livedata for the Nth device
+ * @param cont pointer to the tfaContainer
+ * @param dev_idx the index of the device
+ * @param livedata_idx the index of the livedata
+ * @return livedata list pointer
+ */
+TfaLiveDataList_t *tfaContGetDevLiveDataList(TfaContainer_t *cont, int dev_idx, int livedata_idx);
+
+/**
+ * Check CRC for container
+ * @param cont pointer to the tfaContainer
+ * @return error value 0 on error
+ */
+int tfaContCrcCheckContainer(TfaContainer_t *cont);
+
+/**
+ * Get the device list pointer
+ * @param cnt pointer to the container struct
+ * @param dev_idx the index of the device
+ * @return pointer to device list
+ */
+TfaDeviceList_t *tfaContDevice(TfaContainer_t *cnt, int dev_idx);
+
+/**
+ * Return the pointer to the first profile in a list from the tfaContainer
+ * @param cont pointer to the tfaContainer
+ * @return pointer to first profile in profile list
+ */
+TfaProfileList_t *tfaContGet1stProfList(TfaContainer_t *cont);
+
+/**
+ * Return the pointer to the next profile in a list
+ * @param prof is the pointer to the profile list
+ * @return profile list pointer
+ */
+TfaProfileList_t* tfaContNextProfile(TfaProfileList_t *prof);
+
+/**
+ * Return the pointer to the first livedata in a list from the tfaContainer
+ * @param cont pointer to the tfaContainer
+ * @return pointer to first livedata in profile list
+ */
+TfaLiveDataList_t *tfaContGet1stLiveDataList(TfaContainer_t *cont);
+
+/**
+ * Return the pointer to the next livedata in a list
+ * @param livedata_idx is the pointer to the livedata list
+ * @return livedata list pointer
+ */
+TfaLiveDataList_t* tfaContNextLiveData(TfaLiveDataList_t *livedata_idx);
+
+/**
+ * Write a bit field
+ * @param tfa the device struct pointer
+ * @param bf bitfield to write
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaRunWriteBitfield(struct tfa_device *tfa, TfaBitfield_t bf);
+
+/**
+ * Write a parameter file to the device
+ * @param tfa the device struct pointer
+ * @param file filedescriptor pointer
+ * @param vstep_idx index to vstep
+ * @param vstep_msg_idx index to vstep message
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaContWriteFile(struct tfa_device *tfa, TfaFileDsc_t *file, int vstep_idx, int vstep_msg_idx);
+
+/**
+ * Get the max volume step associated with Nth profile for the Nth device
+ * @param tfa the device struct pointer
+ * @param prof_idx profile index
+ * @return the number of vsteps
+ */
+int tfacont_get_max_vstep(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Get the file contents associated with the device or profile
+ * Search within the device tree, if not found, search within the profile
+ * tree. There can only be one type of file within profile or device.
+ * @param tfa the device struct pointer
+ * @param prof_idx I2C profile index in the device
+ * @param type file type
+ * @return 0 NULL if file type is not found
+ * @return 1 file contents
+ */
+TfaFileDsc_t *tfacont_getfiledata(struct tfa_device *tfa, int prof_idx, enum TfaHeaderType type);
+
+/**
+ * Dump the contents of the file header
+ * @param hdr pointer to file header data
+ */
+void tfaContShowHeader(TfaHeader_t *hdr);
+
+/**
+ * Read a bit field
+ * @param tfa the device struct pointer
+ * @param bf bitfield to read out
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfaRunReadBitfield(struct tfa_device *tfa, TfaBitfield_t *bf);
+
+/**
+ * Get hw feature bits from container file
+ * @param tfa the device struct pointer
+ * @param hw_feature_register pointer to where hw features are stored
+ */
+void tfa_get_hw_features_from_cnt(struct tfa_device *tfa, int *hw_feature_register);
+
+/**
+ * Get sw feature bits from container file
+ * @param tfa the device struct pointer
+ * @param sw_feature_register pointer to where sw features are stored
+ */
+void tfa_get_sw_features_from_cnt(struct tfa_device *tfa, int sw_feature_register[2]);
+
+/**
+ * Factory trimming for the Boost converter
+ * check if there is a correction needed
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa98xx_factory_trimmer(struct tfa_device *tfa);
+
+/**
+ * Control for PWM phase shift
+ * @param tfa the device struct pointer
+ */
+ enum Tfa98xx_Error tfa98xx_set_phase_shift(struct tfa_device *tfa);
+
+
+/**
+ * Search for filters settings and if found then write them to the device
+ * @param tfa the device struct pointer
+ * @param prof_idx profile to look in
+ * @return Tfa98xx_Error
+ */
+enum Tfa98xx_Error tfa_set_filters(struct tfa_device *tfa, int prof_idx);
+
+/**
+ * Get the firmware version from the patch in the container file
+ * @param tfa the device struct pointer
+ * @return firmware version
+ */
+int tfa_cnt_get_patch_version(struct tfa_device *tfa);
+
+int tfa_tib_dsp_msgmulti(struct tfa_device *tfa, int length, const char *buffer);
+
+#endif /* TFACONTAINER_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_device.h b/sound/soc/codecs/tfa98xx-downstream/tfa_device.h
new file mode 100644
index 00000000000..a529b432d55
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_device.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+/**\file
+ *
+ * The tfa_device interface controls a single I2C device instance by
+ * referencing to the device specific context provided by means of the
+ * tfa_device structure pointer.
+ * Multiple instances of tfa_device structures will be created and maintained
+ * by the caller.
+ *
+ * The API is functionally grouped as:
+ * - tfa_dev basic codec interface to probe, start/stop and control the device state
+ * - access to internal MTP storage
+ * - abstraction for interrupt bits and handling
+ * - container reading support
+ */
+#ifndef __TFA_DEVICE_H__
+#define __TFA_DEVICE_H__
+
+#include "config.h"
+
+struct tfa_device;
+
+/*
+ * hw/sw feature bit settings in MTP
+ */
+enum featureSupport {
+ supportNotSet, /**< default means not set yet */
+ supportNo, /**< no support */
+ supportYes /**< supported */
+};
+/*
+ * supported Digital Audio Interfaces bitmap
+ */
+enum Tfa98xx_DAI {
+ Tfa98xx_DAI_I2S = 0x01, /**< I2S only */
+ Tfa98xx_DAI_TDM = 0x02, /**< TDM, I2S */
+ Tfa98xx_DAI_PDM = 0x04, /**< PDM */
+ };
+
+/*
+ * device ops function structure
+ */
+struct tfa_device_ops {
+ enum Tfa98xx_Error(*tfa_dsp_msg)(struct tfa_device *tfa, int length, const char *buf);
+ enum Tfa98xx_Error(*tfa_dsp_msg_read)(struct tfa_device *tfa, int length, unsigned char *bytes);
+ enum Tfa98xx_Error(*tfa_reg_read)(struct tfa_device *tfa, unsigned char subaddress, unsigned short *value);
+ enum Tfa98xx_Error(*tfa_reg_write)(struct tfa_device *tfa, unsigned char subaddress, unsigned short value);
+ enum Tfa98xx_Error(*tfa_mem_read)(struct tfa_device *tfa, unsigned int start_offset, int num_words, int *pValues);
+ enum Tfa98xx_Error(*tfa_mem_write)(struct tfa_device *tfa, unsigned short address, int value, int memtype);
+
+ enum Tfa98xx_Error (*tfa_init)(struct tfa_device *tfa); /**< init typically for loading optimal settings */
+ enum Tfa98xx_Error (*dsp_reset)(struct tfa_device *tfa, int state); /**< reset the coolflux dsp */
+ enum Tfa98xx_Error (*dsp_system_stable)(struct tfa_device *tfa, int *ready); /**< ready when clocks are stable to allow DSP subsystem access */
+ enum Tfa98xx_Error (*dsp_write_tables)(struct tfa_device *tfa, int sample_rate); /**< write the device/type specific delaytables */
+ enum Tfa98xx_Error (*auto_copy_mtp_to_iic)(struct tfa_device *tfa); /**< Set auto_copy_mtp_to_iic */
+ enum Tfa98xx_Error (*factory_trimmer)(struct tfa_device *tfa); /**< Factory trimming for the Boost converter */
+ enum Tfa98xx_Error (*phase_shift)(struct tfa_device *tfa); /**< Control for PWM phase shift */
+ int (*set_swprof)(struct tfa_device *tfa, unsigned short new_value); /**< Set the sw profile in the struct and the hw register */
+ int (*get_swprof)(struct tfa_device *tfa); /**< Get the sw profile from the hw register */
+ int(*set_swvstep)(struct tfa_device *tfa, unsigned short new_value); /**< Set the sw vstep in the struct and the hw register */
+ int(*get_swvstep)(struct tfa_device *tfa); /**< Get the sw vstep from the hw register */
+ int(*get_mtpb)(struct tfa_device *tfa); /**< get status of MTB busy bit*/
+ enum Tfa98xx_Error (*set_mute)(struct tfa_device *tfa, int mute); /**< set mute */
+ enum Tfa98xx_Error (*faim_protect)(struct tfa_device *tfa, int state); /**< Protect FAIM from being corrupted */
+ enum Tfa98xx_Error(*set_osc_powerdown)(struct tfa_device *tfa, int state); /**< Allow to change internal osc. gating settings */
+ enum Tfa98xx_Error(*update_lpm)(struct tfa_device *tfa, int state); /**< Allow to change lowpowermode settings */
+ int (*tfa_set_bitfield)(struct tfa_device* tfa, uint16_t bitfield, uint16_t value);
+ enum Tfa98xx_Error (*tfa_status)(struct tfa_device *tfa);
+};
+
+/**
+ * Device states and modifier flags to allow a device/type independent fine
+ * grained control of the internal state.\n
+ * Values below 0x10 are referred to as base states which can be or-ed with
+ * state modifiers, from 0x10 and higher.
+ *
+ */
+enum tfa_state {
+ TFA_STATE_UNKNOWN, /**< unknown or invalid */
+ TFA_STATE_POWERDOWN, /**< PLL in powerdown, Algo is up/warm */
+ TFA_STATE_INIT_HW, /**< load I2C/PLL hardware setting (~wait2srcsettings) */
+ TFA_STATE_INIT_CF, /**< coolflux HW access possible (~initcf) */
+ TFA_STATE_INIT_FW, /**< DSP framework active (~patch loaded) */
+ TFA_STATE_OPERATING, /**< Amp and Algo running */
+ TFA_STATE_FAULT, /**< An alarm or error occurred */
+ TFA_STATE_RESET, /**< I2C reset and ACS set */
+ /* --sticky state modifiers-- */
+ TFA_STATE_MUTE=0x10, /**< Algo & Amp mute */
+ TFA_STATE_UNMUTE=0x20, /**< Algo & Amp unmute */
+ TFA_STATE_CLOCK_ALWAYS=0x40, /**< PLL connect to internal oscillator */
+ TFA_STATE_CLOCK_AUDIO=0x80, /**< PLL connect to audio clock (BCK/FS) */
+ TFA_STATE_LOW_POWER=0x100, /**< lowest possible power state */
+};
+
+/**
+ * This is the main tfa device context structure, it will carry all information
+ * that is needed to handle a single I2C device instance.
+ * All functions dealing with the device will need access to the fields herein.
+ */
+struct tfa_device {
+ int dev_idx; /**< device container index */
+ int in_use;
+ int buffer_size; /**< lowest level max buffer size */
+ int has_msg; /**< support direct dsp messaging */
+ int dynamicTDMmode; /**tracking dynamic TDM setting from alsa input stream*/
+ int bitwidth; /**bitwdith from alsa input stream*/
+ unsigned char slave_address; /**< I2C slave address (not shifted) */
+ unsigned short rev; /**< full revid of this device */
+ unsigned char tfa_family; /**< tfa1/tfa2 */
+ enum featureSupport supportDrc;
+ enum featureSupport supportFramework;
+ enum featureSupport support_saam;
+ int sw_feature_bits[2]; /**< cached copy of sw feature bits */
+ int hw_feature_bits; /**< cached copy of hw feature bits */
+ int profile; /**< active profile */
+ int vstep; /**< active vstep */
+ unsigned char spkr_count;
+ unsigned char spkr_select;
+ unsigned char support_tcoef;/**< legacy tfa9887, will be removed */
+ enum Tfa98xx_DAI daimap; /**< supported audio interface types */
+ int mohm[3]; /**< speaker calibration values in milli ohms -1 is error */
+ struct tfa_device_ops dev_ops;
+ uint16_t interrupt_enable[3];
+ uint16_t interrupt_status[3];
+ int ext_dsp; /**< respond to external DSP: -1:none, 0:no_dsp, 1:cold, 2:warm */
+ int bus; /* TODO fix ext_dsp and bus handling */
+ int tfadsp_event; /**< enum tfadsp_event_en is for external registry */
+ int verbose; /**< verbosity level for debug print output */
+ enum tfa_state state; /**< last known state or-ed with optional state_modifier */
+ struct TfaContainer *cnt;/**< the loaded container file */
+ struct TfaVolumeStepRegisterInfo *p_regInfo; /**< remember vstep for partial updates */
+ int partial_enable; /**< enable partial updates */
+ void *data; /**< typically pointing to Linux driver structure owning this device */
+ int convert_dsp32; /**< convert 24 bit DSP messages to 32 bit */
+ int sync_iv_delay; /**< synchronize I/V delay at cold start */
+ int is_probus_device; /**< probus device: device without internal DSP */
+ int advance_keys_handling;
+ unsigned int rate;
+ int needs_reset; /**< add the reset trigger for SetAlgoParams and SetMBDrc commands */
+ struct kmem_cache *cachep; /**< Memory allocator handle */
+ char fw_itf_ver[4]; /* Firmware ITF version */
+};
+
+/**
+ * The tfa_dev_probe is called before accessing any device accessing functions.
+ * Access to the tfa device register 3 is attempted and will record the
+ * returned id for further use. If no device responds the function will abort.
+ * The recorded id will by used by the query functions to fill the remaining
+ * relevant data fields of the device structure.
+ * Data such as MTP features that requires device access will only be read when
+ * explicitly called and the result will be then cached in the struct.
+ *
+ * A structure pointer passed to this device needs to refer to existing memory
+ * space allocated by the caller.
+ *
+ * @param slave = I2C slave address of the target device (not shifted)
+ * @param tfa struct = points to memory that holds the context for this device
+ * instance
+ *
+ * @return
+ * - 0 if the I2C device responded to a read of register address 3\n
+ * when the device responds but with an unknown id a warning will be printed
+ * - -1 if no response from the I2C device
+ *
+ */
+int tfa_dev_probe(int slave, struct tfa_device *tfa);
+
+/**
+ * Start this instance at the profile and vstep as provided.
+ * The profile and vstep will be loaded first in case the current value differs
+ * from the requested values.
+ * Note that this call will not change the mute state of the tfa, which means
+ * that of this instance was called in muted state the caller will have to
+ * unmute in order to get audio.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @param profile the selected profile to run
+ * @param vstep the selected vstep to use
+ * @return tfa_error enum
+ */
+enum tfa_error tfa_dev_start(struct tfa_device *tfa, int profile, int vstep);
+
+
+/**
+ * Stop audio for this instance as gracefully as possible.
+ * Audio will be muted and the PLL will be shutdown together with any other
+ * device/type specific settings needed to prevent audio artifacts or
+ * workarounds.
+ *
+ * Note that this call will change state of the tfa to mute and powered down.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @return tfa_error enum
+ */
+enum tfa_error tfa_dev_stop(struct tfa_device *tfa);
+
+/**
+ * This interface allows a device/type independent fine grained control of the
+ * internal state of the instance.
+ * Whenever a base state is requested an attempt is made to actively bring the device
+ * into this state. However this may depend on external conditions beyond control of
+ * this software layer. Therefore in case the state cannot be set an erro will
+ * be returned and the current state remains unchanged.
+ * The base states, lower values below 0x10, are all mutually exclusive, they higher ones
+ * can also function as a sticky modifier which means for example that operating
+ * state could be in either muted or unmuted state. Or in case of init_cf it can be
+ * internal clock (always) or external audio clock.
+ * This function is intended to be used for device mute/unmute synchronization
+ * when called from higher layers. Mostly internal calls will use this to control
+ * the startup and profile transitions in a device/type independent way.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @param state struct = desired device state after function return
+ * @return tfa_error enum
+ */
+enum tfa_error tfa_dev_set_state(struct tfa_device *tfa, enum tfa_state state,int is_calibration);
+
+/**
+ * Retrieve the current state of this instance in an active way.
+ * The state field in tfa structure will reflect the result unless an error is
+ * returned.
+ * Note that the hardware state may change on external events an as such this
+ * field should be treated as volatile.
+ *
+ * @param tfa struct = pointer to context of this device instance
+ * @return tfa_error enum
+ *
+ */
+enum tfa_state tfa_dev_get_state(struct tfa_device *tfa);
+
+/**
+ * Deduce the width from machine driver and decide TDM setting to be
+ * programmed to the TFA amplifier dynamically
+ * @param tfa struct = pointer to context of this device instance
+ * @param width = parmeters read from top layer to decide the applicable TDM settings
+ * @return tfa_error enum
+ - 0 if the width received is correct (16/32/24)
+ * - others if width received is not correct
+ */
+int tfa_dev_set_tdm_bitwidth(struct tfa_device *tfa, int width);
+/**
+ * Fill TDM setting addresses for current device needed with dynamic TDM switch
+ * @param tfa struct = pointer to context of this device instance
+ * @param tdme = pointer to be filled with TDME address
+ * @param tnbck = pointer to be filled with TDMNBCK address
+ * @param tslln = pointer to be filled with TDMSLLN address
+ * @param tsize = pointer to be filled with TDMSSIZE address
+ */
+void tfa_dev_get_tdm_add(struct tfa_device* tfa,uint16_t *tdme,uint16_t * tnbck,uint16_t *tslln,uint16_t *tsize);
+/**
+ * MTP support functions
+ */
+enum tfa_mtp {
+ TFA_MTP_OTC, /**< */
+ TFA_MTP_EX, /**< */
+ TFA_MTP_RE25, /**< */
+ TFA_MTP_RE25_PRIM, /**< */
+ TFA_MTP_RE25_SEC, /**< */
+ TFA_MTP_LOCK, /**< */
+};
+
+/**
+ *
+ */
+int tfa_dev_mtp_get(struct tfa_device *tfa, enum tfa_mtp item);
+
+/**
+ *
+ */
+enum tfa_error tfa_dev_mtp_set(struct tfa_device *tfa, enum tfa_mtp item, int value);
+
+
+//irq
+/* tfa2 interrupt support
+ * !!! enum tfa9912_irq !!!*/
+/*
+ * interrupt bit function to clear
+ */
+int tfa_irq_clear(struct tfa_device *tfa, int bit);
+/*
+ * return state of irq or -1 if illegal bit
+ */
+int tfa_irq_get(struct tfa_device *tfa, int bit);
+/*
+ * interrupt bit function that operates on the shadow regs in the handle
+ */
+int tfa_irq_ena(struct tfa_device *tfa, int bit, int state);
+/*
+ * interrupt bit function that sets the polarity
+ */
+int tfa_irq_set_pol(struct tfa_device *tfa, int bit, int state);
+
+/*
+ * mask interrupts by disabling them
+ */
+int tfa_irq_mask(struct tfa_device *tfa);
+/*
+ * unmask interrupts by enabling them again
+ */
+int tfa_irq_unmask(struct tfa_device *tfa);
+//cnt read
+//debug?
+
+#endif /* __TFA_DEVICE_H__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_dsp.c b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp.c
new file mode 100644
index 00000000000..894fd049f59
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp.c
@@ -0,0 +1,4376 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include "dbgprint.h"
+#include "tfa_container.h"
+#include "tfa.h"
+#include "tfa98xx_tfafieldnames.h"
+#include "tfa_internal.h"
+
+#define TFA_API_SBFW_8_09_00 (31) /**< Corresponds to SB3.5 PRC2 release */
+ /* handle macro for bitfield */
+#define TFA_MK_BF(reg, pos, len) ((reg<<8)|(pos<<4)|(len-1))
+
+/* abstract family for register */
+#define FAM_TFA98XX_CF_CONTROLS (TFA_FAM(tfa,RST) >> 8)
+#define FAM_TFA98XX_CF_MEM (TFA_FAM(tfa,MEMA)>> 8)
+#define FAM_TFA98XX_MTP0 (TFA_FAM(tfa,MTPOTC) >> 8)
+#define FAM_TFA98xx_INT_EN (TFA_FAM(tfa,INTENVDDS) >> 8)
+
+#define CF_STATUS_I2C_CMD_ACK 0x01
+
+/* Defines below are used for irq function (this removed the genregs include) */
+#define TFA98XX_INTERRUPT_ENABLE_REG1 0x48
+#define TFA98XX_INTERRUPT_IN_REG1 0x44
+#define TFA98XX_INTERRUPT_OUT_REG1 0x40
+#define TFA98XX_STATUS_POLARITY_REG1 0x4c
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK 0x2
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MSK 0x1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_POS 1
+#define TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_POS 0
+#define MIN_BATT_LEVEL 640
+#define MAX_BATT_LEVEL 670
+void tfanone_ops(struct tfa_device_ops *ops);
+void tfa9872_ops(struct tfa_device_ops *ops);
+void tfa9873_ops(struct tfa_device_ops *ops);
+void tfa9874_ops(struct tfa_device_ops *ops);
+void tfa9875_ops(struct tfa_device_ops *ops);
+void tfa9878_ops(struct tfa_device_ops *ops);
+void tfa9912_ops(struct tfa_device_ops *ops);
+void tfa9888_ops(struct tfa_device_ops *ops);
+void tfa9891_ops(struct tfa_device_ops *ops);
+void tfa9897_ops(struct tfa_device_ops *ops);
+void tfa9896_ops(struct tfa_device_ops *ops);
+void tfa9890_ops(struct tfa_device_ops *ops);
+void tfa9895_ops(struct tfa_device_ops *ops);
+void tfa9894_ops(struct tfa_device_ops *ops);
+
+#ifndef MIN
+#define MIN(A,B) (A<B?A:B)
+#endif
+
+/* retry values */
+#define CFSTABLE_TRIES 10
+#define AMPOFFWAIT_TRIES 50
+#define MTPBWAIT_TRIES 50
+#define MTPEX_WAIT_NTRIES 50
+
+/* calibration done executed */
+#define TFA_MTPEX_POS TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_POS /**/
+
+int tfa_get_calibration_info(struct tfa_device *tfa, int channel)
+{
+ return tfa->mohm[channel];
+}
+
+/* return sign extended tap pattern */
+int tfa_get_tap_pattern(struct tfa_device *tfa)
+{
+ int value = tfa_get_bf(tfa, TFA9912_BF_CFTAPPAT);
+ int bitshift;
+ uint8_t field_len = 1 + (TFA9912_BF_CFTAPPAT & 0x0f); /* length of bitfield */
+
+ bitshift = 8 * sizeof(int) - field_len;
+ /* signextend */
+ value = (value << bitshift) >> bitshift;
+
+ return value;
+}
+/*
+ * interrupt bit function to clear
+ */
+int tfa_irq_clear(struct tfa_device *tfa, enum tfa9912_irq bit)
+{
+ unsigned char reg;
+
+ /* make bitfield enum */
+ if (bit == tfa9912_irq_all) {
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_IN_REG1; reg < TFA98XX_INTERRUPT_IN_REG1 + 3; reg++)
+ tfa_reg_write(tfa, reg, 0xffff); /* all bits */
+ }
+ else if (bit < tfa9912_irq_max) {
+ reg = (unsigned char)(TFA98XX_INTERRUPT_IN_REG1 + (bit >> 4));
+ tfa_reg_write(tfa, reg, 1 << (bit & 0x0f)); /* only this bit */
+ }
+ else
+ return -1;
+
+ return 0;
+}
+/*
+ * return state of irq or -1 if illegal bit
+ */
+int tfa_irq_get(struct tfa_device *tfa, enum tfa9912_irq bit)
+{
+ uint16_t value;
+ int reg, mask;
+
+ if (bit < tfa9912_irq_max) {
+ /* only this bit */
+ reg = TFA98XX_INTERRUPT_OUT_REG1 + (bit >> 4);
+ mask = 1 << (bit & 0x0f);
+ tfa_reg_read(tfa, (unsigned char)reg, &value);
+ }
+ else
+ return -1;
+
+ return (value & mask) != 0;
+}
+/*
+ * interrupt bit function that operates on the shadow regs in the handle
+ */
+
+int tfa_irq_ena(struct tfa_device *tfa, enum tfa9912_irq bit, int state)
+{
+ uint16_t value, new_value;
+ int reg = 0, mask;
+ /* */
+ if (bit == tfa9912_irq_all) {
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_ENABLE_REG1; reg <= TFA98XX_INTERRUPT_ENABLE_REG1 + tfa9912_irq_max / 16; reg++) {
+ tfa_reg_write(tfa, (unsigned char)reg, state ? 0xffff : 0); /* all bits */
+ tfa->interrupt_enable[reg - TFA98XX_INTERRUPT_ENABLE_REG1] = state ? 0xffff : 0; /* all bits */
+ }
+ }
+ else if (bit < tfa9912_irq_max) {
+ /* only this bit */
+ reg = TFA98XX_INTERRUPT_ENABLE_REG1 + (bit >> 4);
+ mask = 1 << (bit & 0x0f);
+ tfa_reg_read(tfa, (unsigned char)reg, &value);
+ if (state) //set
+ new_value = (uint16_t)(value | mask);
+ else // clear
+ new_value = value & ~mask;
+ if (new_value != value) {
+ tfa_reg_write(tfa, (unsigned char)reg, new_value); /* only this bit */
+ tfa->interrupt_enable[reg - TFA98XX_INTERRUPT_ENABLE_REG1] = new_value;
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/*
+ * mask interrupts by disabling them
+ */
+int tfa_irq_mask(struct tfa_device *tfa)
+{
+ int reg;
+
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_ENABLE_REG1; reg <= TFA98XX_INTERRUPT_ENABLE_REG1 + tfa9912_irq_max / 16; reg++)
+ tfa_reg_write(tfa, (unsigned char)reg, 0);
+
+ return 0;
+}
+
+/*
+ * unmask interrupts by enabling them again
+ */
+int tfa_irq_unmask(struct tfa_device *tfa)
+{
+ int reg;
+
+ /* operate on all bits */
+ for (reg = TFA98XX_INTERRUPT_ENABLE_REG1; reg <= TFA98XX_INTERRUPT_ENABLE_REG1 + tfa9912_irq_max / 16; reg++)
+ tfa_reg_write(tfa, (unsigned char)reg, tfa->interrupt_enable[reg - TFA98XX_INTERRUPT_ENABLE_REG1]);
+
+ return 0;
+}
+
+/*
+ * interrupt bit function that sets the polarity
+ */
+
+int tfa_irq_set_pol(struct tfa_device *tfa, enum tfa9912_irq bit, int state)
+{
+ uint16_t value, new_value;
+ int reg = 0, mask;
+
+ if (bit == tfa9912_irq_all) {
+ /* operate on all bits */
+ for (reg = TFA98XX_STATUS_POLARITY_REG1; reg <= TFA98XX_STATUS_POLARITY_REG1 + tfa9912_irq_max / 16; reg++) {
+ tfa_reg_write(tfa, (unsigned char)reg, state ? 0xffff : 0); /* all bits */
+ }
+ }
+ else if (bit < tfa9912_irq_max) {
+ /* only this bit */
+ reg = TFA98XX_STATUS_POLARITY_REG1 + (bit >> 4);
+ mask = 1 << (bit & 0x0f);
+ tfa_reg_read(tfa, (unsigned char)reg, &value);
+ if (state) /* Active High */
+ new_value = (uint16_t)(value | mask);
+ else /* Active Low */
+ new_value = value & ~mask;
+ if (new_value != value) {
+ tfa_reg_write(tfa, (unsigned char)reg, new_value); /* only this bit */
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/*
+ * set device info and register device ops
+ */
+void tfa_set_query_info(struct tfa_device *tfa)
+{
+ /* invalidate device struct cached values */
+ tfa->hw_feature_bits = -1;
+ tfa->sw_feature_bits[0] = -1;
+ tfa->sw_feature_bits[1] = -1;
+ tfa->profile = -1;
+ tfa->vstep = -1;
+ /* defaults */
+ tfa->is_probus_device = 0;
+ tfa->advance_keys_handling = 0; /*artf65038*/
+ tfa->tfa_family = 1;
+ tfa->daimap = Tfa98xx_DAI_I2S; /* all others */
+ tfa->spkr_count = 1;
+ tfa->spkr_select = 0;
+ tfa->support_tcoef = supportYes;
+ tfa->supportDrc = supportNotSet;
+ tfa->support_saam = supportNotSet;
+ tfa->ext_dsp = -1; /* respond to external DSP: -1:none, 0:no_dsp, 1:cold, 2:warm */
+ tfa->bus = 0;
+ tfa->partial_enable = 0;
+ tfa->convert_dsp32 = 0;
+ tfa->sync_iv_delay = 0;
+ tfa->dynamicTDMmode = -1; /**tracking dynamic TDM setting from alsa input stream*/
+ tfa->rate = 0;
+ tfa->bitwidth = -1;/**bitwdith from alsa input stream*/
+
+ /* TODO use the getfeatures() for retrieving the features [artf103523]
+ tfa->supportDrc = supportNotSet;*/
+
+ switch (tfa->rev & 0xff) {
+ case 0: /* tfanone : non-i2c external DSP device */
+ /* e.g. qc adsp */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 0;
+ tfa->spkr_count = 0;
+ tfa->daimap = 0;
+ tfanone_ops(&tfa->dev_ops); /* register device operations via tfa hal*/
+ tfa->bus = 1;
+ break;
+ case 0x72:
+ /* tfa9872 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9872_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x73:
+ /* tfa9873 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->advance_keys_handling = 1; /*artf65038*/
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9873_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x74:
+ /* tfa9874 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9874_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x75:
+ /* tfa9875 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->advance_keys_handling = 1; /*artf65038*/
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9875_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x78:
+ /* tfa9878 */
+ tfa->supportDrc = supportYes;
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->is_probus_device = 1;
+ tfa->advance_keys_handling = 1; /*artf65038*/
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9878_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x88:
+ /* tfa9888 */
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 2;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9888_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x97:
+ /* tfa9897 */
+ tfa->supportDrc = supportNo;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9897_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x96:
+ /* tfa9896 */
+ tfa->supportDrc = supportNo;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9896_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x92:
+ /* tfa9891 */
+ tfa->spkr_count = 1;
+ tfa->daimap = (Tfa98xx_DAI_PDM | Tfa98xx_DAI_I2S);
+ tfa9891_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x91:
+ /* tfa9890B */
+ tfa->spkr_count = 1;
+ tfa->daimap = (Tfa98xx_DAI_PDM | Tfa98xx_DAI_I2S);
+ break;
+ case 0x80:
+ case 0x81:
+ /* tfa9890 */
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_I2S;
+ tfa->supportDrc = supportNo;
+ tfa->supportFramework = supportNo;
+ tfa9890_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x12:
+ /* tfa9895 */
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_I2S;
+ tfa9895_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x13:
+ /* tfa9912 */
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9912_ops(&tfa->dev_ops); /* register device operations */
+ break;
+ case 0x94:
+ /* tfa9894 */
+ tfa->tfa_family = 2;
+ tfa->spkr_count = 1;
+ tfa->daimap = Tfa98xx_DAI_TDM;
+ tfa9894_ops(&tfa->dev_ops); /* register device operations */
+ break;
+
+ default:
+ pr_err("unknown device type : 0x%02x\n", tfa->rev);
+ _ASSERT(0);
+ break;
+ }
+}
+
+/*
+ * lookup the device type and return the family type
+ */
+int tfa98xx_dev2family(int dev_type)
+{
+ /* only look at the die ID part (lsb byte) */
+ switch (dev_type & 0xff) {
+ case 0x12:
+ case 0x80:
+ case 0x81:
+ case 0x91:
+ case 0x92:
+ case 0x97:
+ case 0x96:
+ return 1;
+ case 0x88:
+ case 0x72:
+ case 0x73:
+ case 0x13:
+ case 0x74:
+ case 0x75:
+ case 0x78:
+ case 0x94:
+ return 2;
+ case 0x50:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * return the target address for the filter on this device
+
+ filter_index:
+ [0..9] reserved for EQ (not deployed, calc. is available)
+ [10..12] anti-alias filter
+ [13] integrator filter
+
+ */
+enum Tfa98xx_DMEM tfa98xx_filter_mem(struct tfa_device *tfa, int filter_index, unsigned short *address, int channel)
+{
+ enum Tfa98xx_DMEM dmem = -1;
+ int idx;
+ unsigned short bq_table[7][4] = {
+ /* index: 10, 11, 12, 13 */
+ {346,351,356,288}, //87 BRA_MAX_MRA4-2_7.00
+ {346,351,356,288}, //90 BRA_MAX_MRA6_9.02
+ {467,472,477,409}, //95 BRA_MAX_MRA7_10.02
+ {406,411,416,348}, //97 BRA_MAX_MRA9_12.01
+ {467,472,477,409}, //91 BRA_MAX_MRAA_13.02
+ {8832, 8837, 8842, 8847}, //88 part1
+ {8853, 8858, 8863, 8868} //88 part2
+ /* Since the 88 is stereo we have 2 parts.
+ * Every index has 5 values except index 13 this one has 6 values
+ */
+ };
+
+ if ((10 <= filter_index) && (filter_index <= 13)) {
+ dmem = Tfa98xx_DMEM_YMEM; /* for all devices */
+ idx = filter_index - 10;
+
+ switch (tfa->rev & 0xff) { // only compare lower byte
+ case 0x12:
+ *address = bq_table[2][idx];
+ break;
+ case 0x97:
+ *address = bq_table[3][idx];
+ break;
+ case 0x96:
+ *address = bq_table[3][idx];
+ break;
+ case 0x80:
+ case 0x81: // for the RAM version
+ case 0x91:
+ *address = bq_table[1][idx];
+ break;
+ case 0x92:
+ *address = bq_table[4][idx];
+ break;
+ case 0x88:
+ /* Channel 1 = primary, 2 = secondary */
+ if (channel == 1)
+ *address = bq_table[5][idx];
+ else
+ *address = bq_table[6][idx];
+ break;
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x78:
+ case 0x13:
+ default:
+ /* unsupported case, possibly intermediate version */
+ return -1;
+ _ASSERT(0);
+ }
+ }
+ return dmem;
+}
+
+/************************ query functions ********************************************************/
+/**
+* return revision
+* Used by the LTT
+*/
+void tfa98xx_rev(int *major, int *minor, int *revision)
+{
+ char version_str[] = TFA98XX_API_REV_STR;
+ sscanf(version_str, "v%d.%d.%d", major, minor, revision);
+}
+
+/**
+ * tfa_supported_speakers
+ * returns the number of the supported speaker count
+ */
+enum Tfa98xx_Error tfa_supported_speakers(struct tfa_device *tfa, int* spkr_count)
+{
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ else
+ *spkr_count = tfa->spkr_count;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/*
+ * tfa98xx_supported_saam
+ * returns the supportedspeaker as microphone feature
+ */
+enum Tfa98xx_Error tfa98xx_supported_saam(struct tfa_device *tfa, enum Tfa98xx_saam *saam)
+{
+ int features;
+ enum Tfa98xx_Error error;
+
+ if (tfa->support_saam == supportNotSet) {
+ error = tfa98xx_dsp_get_hw_feature_bits(tfa, &features);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+ tfa->support_saam =
+ (features & 0x8000) ? supportYes : supportNo; /* SAAM is bit15 */
+ }
+ *saam = tfa->support_saam == supportYes ? Tfa98xx_saam : Tfa98xx_saam_none;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/*
+ * tfa98xx_compare_features
+ * Obtains features_from_MTP and features_from_cnt
+ */
+enum Tfa98xx_Error tfa98xx_compare_features(struct tfa_device *tfa, int features_from_MTP[3], int features_from_cnt[3])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint32_t value;
+ uint16_t mtpbf;
+ unsigned char bytes[3 * 2];
+ int status;
+
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status)
+ return Tfa98xx_Error_NoClock; // Only test when we have a clock.
+
+ /* Set proper MTP location per device: */
+ if (tfa->tfa_family == 1) {
+ mtpbf = 0x850f; /* MTP5 for tfa1,16 bits */
+ }
+ else {
+ mtpbf = 0xf907; /* MTP9 for tfa2, 8 bits */
+ }
+
+ /* Read HW features from MTP: */
+ value = tfa_read_reg(tfa, mtpbf) & 0xffff;
+ features_from_MTP[0] = tfa->hw_feature_bits = value;
+
+ /* Read SW features: */
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK, FW_PAR_ID_GET_FEATURE_INFO, sizeof(bytes), bytes);
+ if (error != Tfa98xx_Error_Ok)
+ return error; /* old ROM code may respond with Tfa98xx_Error_RpcParamId */
+
+ tfa98xx_convert_bytes2data(sizeof(bytes), bytes, &features_from_MTP[1]);
+
+ /* check if feature bits from MTP match feature bits from cnt file: */
+ tfa_get_hw_features_from_cnt(tfa, &features_from_cnt[0]);
+ tfa_get_sw_features_from_cnt(tfa, &features_from_cnt[1]);
+
+ return error;
+}
+
+/********************************* device specific ops ************************************************/
+/* the wrapper for DspReset, in case of full */
+enum Tfa98xx_Error tfa98xx_dsp_reset(struct tfa_device *tfa, int state)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ error = (tfa->dev_ops.dsp_reset)(tfa, state);
+
+ return error;
+}
+
+/* the ops wrapper for tfa98xx_dsp_SystemStable */
+enum Tfa98xx_Error tfa98xx_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ return (tfa->dev_ops.dsp_system_stable)(tfa, ready);
+}
+
+/* the ops wrapper for tfa98xx_dsp_system_stable */
+enum Tfa98xx_Error tfa98xx_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.auto_copy_mtp_to_iic)(tfa);
+}
+
+/* the ops wrapper for tfa98xx_faim_protect */
+enum Tfa98xx_Error tfa98xx_faim_protect(struct tfa_device *tfa, int state)
+{
+ return (tfa->dev_ops.faim_protect)(tfa, state);
+}
+
+/*
+ * bring the device into a state similar to reset
+ */
+enum Tfa98xx_Error tfa98xx_init(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t value = 0;
+
+ /* reset all i2C registers to default
+ * Write the register directly to avoid the read in the bitfield function.
+ * The I2CR bit may overwrite the full register because it is reset anyway.
+ * This will save a reg read transaction.
+ */
+ TFA_SET_BF_VALUE(tfa, I2CR, 1, &value);
+ TFA_WRITE_REG(tfa, I2CR, value);
+
+ /* Put DSP in reset */
+ tfa98xx_dsp_reset(tfa, 1); /* in pair of tfaRunStartDSP() */
+
+ /* some other registers must be set for optimal amplifier behaviour
+ * This is implemented in a file specific for the type number
+ */
+ if (tfa->dev_ops.tfa_init)
+ error = (tfa->dev_ops.tfa_init)(tfa);
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ error = (tfa->dev_ops.dsp_write_tables)(tfa, sample_rate);
+
+ return error;
+}
+
+/** Set internal oscillator into power down mode.
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+enum Tfa98xx_Error tfa98xx_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ if (tfa->dev_ops.set_osc_powerdown) {
+ return tfa->dev_ops.set_osc_powerdown(tfa, state);
+ }
+
+ return Tfa98xx_Error_Not_Implemented;
+}
+
+/** update low power mode of the device.
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - LPMODE is on, 1 LPMODE is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+enum Tfa98xx_Error tfa98xx_update_lpm(struct tfa_device *tfa, int state)
+{
+ if (tfa->dev_ops.update_lpm) {
+ return tfa->dev_ops.update_lpm(tfa, state);
+ }
+
+ return Tfa98xx_Error_Not_Implemented;
+}
+/** Check presence of powerswitch=1 in configuration and optimal setting.
+*
+* @param[in] tfa device description structure
+*
+* @return -1 when error, 0 or 1 depends on switch settings.
+*/
+int tfa98xx_powerswitch_is_enabled(struct tfa_device *tfa)
+{
+ uint16_t value;
+ enum Tfa98xx_Error ret;
+
+ if (((tfa->rev & 0xff) == 0x13) || ((tfa->rev & 0xff) == 0x88)) {
+ ret = tfa_reg_read(tfa, 0xc6, &value);
+ if (ret != Tfa98xx_Error_Ok) {
+ return -1;
+ }
+ /* PLMA5539: Check actual value of powerswitch. TODO: regmap v1.40 should make this bit public. */
+
+ return (int)(value & (1u << 6));
+ }
+
+ return 1;
+}
+
+/********************* new tfa2 *********************************************************************/
+/* newly added messaging for tfa2 tfa1? */
+enum Tfa98xx_Error tfa98xx_dsp_get_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, unsigned char bytes[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ char msg[4 * 3];
+ int nr = 0;
+
+ msg[nr++] = 8;
+ msg[nr++] = MODULE_FRAMEWORK + 128;
+ msg[nr++] = FW_PAR_ID_GET_MEMORY;
+
+ msg[nr++] = 0;
+ msg[nr++] = 0;
+ msg[nr++] = (char)memoryType;
+
+ msg[nr++] = 0;
+ msg[nr++] = (offset >> 8) & 0xff;
+ msg[nr++] = offset & 0xff;
+
+ msg[nr++] = 0;
+ msg[nr++] = (length >> 8) & 0xff;
+ msg[nr++] = length & 0xff;
+
+ /* send msg */
+ error = tfa_dsp_msg(tfa, nr, (char *)msg);
+
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the device (length * 3) */
+ error = tfa_dsp_msg_read(tfa, length * 3, bytes);
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_set_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, int value)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int nr = 0;
+ char msg[5 * 3];
+
+ msg[nr++] = 8;
+ msg[nr++] = MODULE_FRAMEWORK + 128;
+ msg[nr++] = FW_PAR_ID_SET_MEMORY;
+
+ msg[nr++] = 0;
+ msg[nr++] = 0;
+ msg[nr++] = (char)memoryType;
+
+ msg[nr++] = 0;
+ msg[nr++] = (offset >> 8) & 0xff;
+ msg[nr++] = offset & 0xff;
+
+ msg[nr++] = 0;
+ msg[nr++] = (length >> 8) & 0xff;
+ msg[nr++] = length & 0xff;
+
+ msg[nr++] = (value >> 16) & 0xff;
+ msg[nr++] = (value >> 8) & 0xff;
+ msg[nr++] = value & 0xff;
+
+ /* send msg */
+ error = tfa_dsp_msg(tfa, nr, (char *)msg);
+
+ return error;
+}
+/****************************** calibration support **************************/
+/*
+ * get/set the mtp with user controllable values
+ *
+ * check if the relevant clocks are available
+ */
+enum Tfa98xx_Error tfa98xx_get_mtp(struct tfa_device *tfa, uint16_t *value)
+{
+ int status;
+ int result;
+
+ /* not possible if PLL in powerdown */
+ if (TFA_GET_BF(tfa, PWDN)) {
+ pr_debug("PLL in powerdown\n");
+ return Tfa98xx_Error_NoClock;
+ }
+
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (status == 0) {
+ pr_debug("PLL not running\n");
+ return Tfa98xx_Error_NoClock;
+ }
+
+ result = TFA_READ_REG(tfa, MTP0);
+ if (result < 0) {
+ return -result;
+ }
+ *value = (uint16_t)result;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/*
+ * lock or unlock KEY2
+ * lock = 1 will lock
+ * lock = 0 will unlock
+ *
+ * note that on return all the hidden key will be off
+ */
+void tfa98xx_key2(struct tfa_device *tfa, int lock)
+{
+ /* unhide lock registers */
+ tfa_reg_write(tfa, (tfa->tfa_family == 1) ? 0x40 : 0x0F, 0x5A6B);
+ /* lock/unlock key2 MTPK */
+ TFA_WRITE_REG(tfa, MTPKEY2, lock ? 0 : 0x5A);
+ /* unhide lock registers */
+ if (!tfa->advance_keys_handling) /*artf65038*/
+ tfa_reg_write(tfa, (tfa->tfa_family == 1) ? 0x40 : 0x0F, 0);
+}
+void tfa2_manual_mtp_cpy(struct tfa_device *tfa, uint16_t reg_row_to_keep, uint16_t reg_row_to_set, uint8_t row)///MCH_TO_TEST
+{
+ uint16_t value;
+ int loop = 0;
+ enum Tfa98xx_Error error;
+ /* Assure FAIM is enabled (enable it when neccesery) */
+ if (tfa->is_probus_device)
+ {
+ error = tfa98xx_faim_protect(tfa, 1);
+ if (tfa->verbose) {
+ pr_debug("FAIM enabled (err:%d).\n", error);
+ }
+ }
+ tfa_reg_read(tfa, (unsigned char)reg_row_to_keep, &value);
+ if (!row)
+ {
+ tfa_reg_write(tfa, 0xA7, value);
+ tfa_reg_write(tfa, 0xA8, reg_row_to_set);
+ }
+ else
+ {
+ tfa_reg_write(tfa, 0xA7, reg_row_to_set);
+ tfa_reg_write(tfa, 0xA8, value);
+ }
+ tfa_reg_write(tfa, 0xA3, 0x10 | row);
+ if (tfa->is_probus_device)
+ {
+ /* Assure FAIM is enabled (enable it when neccesery) */
+ for (loop = 0; loop < 100 /*x10ms*/; loop++) {
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ if (tfa_dev_get_mtpb(tfa) == 0)
+ break;
+ }
+ error = tfa98xx_faim_protect(tfa, 0);
+ if (tfa->verbose) {
+ pr_debug("FAIM disabled (err:%d).\n", error);
+ }
+ }
+}
+
+enum Tfa98xx_Error tfa98xx_set_mtp(struct tfa_device *tfa, uint16_t value, uint16_t mask)
+{
+ unsigned short mtp_old, mtp_new;
+ int loop, status;
+ enum Tfa98xx_Error error;
+
+ error = tfa98xx_get_mtp(tfa, &mtp_old);
+
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ mtp_new = (value & mask) | (mtp_old & ~mask);
+
+ if (mtp_old == mtp_new) /* no change */ {
+ if (tfa->verbose)
+ pr_info("No change in MTP. Value not written! \n");
+ return Tfa98xx_Error_Ok;
+ }
+ error = tfa98xx_update_lpm(tfa, 1);
+ if (error) {
+ return error;
+ }
+ /* Assure FAIM is enabled (enable it when neccesery) */
+ error = tfa98xx_faim_protect(tfa, 1);
+ if (error) {
+ return error;
+ }
+ if (tfa->verbose) {
+ pr_debug("MTP clock enabled.\n");
+ }
+
+ /* assure that the clock is up, else we can't write MTP */
+ error = tfa98xx_dsp_system_stable(tfa, &status);
+ if (error) {
+ return error;
+ }
+ if (status == 0) {
+ return Tfa98xx_Error_NoClock;
+ }
+
+ tfa98xx_key2(tfa, 0); /* unlock */
+ TFA_WRITE_REG(tfa, MTP0, mtp_new); /* write to i2c shadow reg */
+ /* CIMTP=1 start copying all the data from i2c regs_mtp to mtp*/
+ if (tfa->tfa_family == 2)
+ tfa2_manual_mtp_cpy(tfa, 0xF1, mtp_new, 0);
+ else
+ TFA_SET_BF(tfa, CIMTP, 1);
+ /* wait until MTP write is done */
+ error = Tfa98xx_Error_StateTimedOut;
+ for (loop = 0; loop < 100 /*x10ms*/; loop++) {
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ if (tfa_dev_get_mtpb(tfa) == 0) {
+ error = Tfa98xx_Error_Ok;
+ break;
+ }
+ }
+ tfa98xx_key2(tfa, 1); /* lock */
+ /* MTP setting failed due to timeout ?*/
+ if (error) {
+ tfa98xx_faim_protect(tfa, 0);
+ return error;
+ }
+
+ /* Disable the FAIM, if this is neccessary */
+ error = tfa98xx_faim_protect(tfa, 0);
+ if (error) {
+ return error;
+ }
+ if (tfa->verbose) {
+ pr_debug("MTP clock disabled.\n");
+ }
+ error = tfa98xx_update_lpm(tfa, 0);
+ if (error) {
+ return error;
+ }
+ return error;
+}
+/*
+ * clear mtpex
+ * set ACS
+ * start tfa
+ */
+int tfa_calibrate(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error;
+
+ /* clear mtpex */
+ error = tfa98xx_set_mtp(tfa, 0, TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK);
+ if (error)
+ return error;
+
+ /* set RST=1 to put the DSP in Reset */
+ TFA_SET_BF(tfa, RST, 1);
+
+ /* set ACS/coldboot state */
+ error = tfaRunColdboot(tfa, 1);
+
+ /* start tfa by playing */
+ return error;
+}
+
+static short twos(short x)
+{
+ return (x < 0) ? x + 512 : x;
+}
+
+void tfa98xx_set_exttemp(struct tfa_device *tfa, short ext_temp)
+{
+ if ((-256 <= ext_temp) && (ext_temp <= 255)) {
+ /* make twos complement */
+ pr_debug("Using ext temp %d C\n", twos(ext_temp));
+ TFA_SET_BF(tfa, TROS, 1);
+ TFA_SET_BF(tfa, EXTTS, twos(ext_temp));
+ }
+ else {
+ pr_debug("Clearing ext temp settings\n");
+ TFA_SET_BF(tfa, TROS, 0);
+ }
+}
+short tfa98xx_get_exttemp(struct tfa_device *tfa)
+{
+ short ext_temp = (short)TFA_GET_BF(tfa, EXTTS);
+ return (twos(ext_temp));
+}
+
+/************************** tfa simple bitfield interfacing ***************************************/
+/* convenience functions */
+enum Tfa98xx_Error tfa98xx_set_volume_level(struct tfa_device *tfa, unsigned short vol)
+{
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (vol > 255) /* restricted to 8 bits */
+ vol = 255;
+
+ /* 0x00 -> 0.0 dB
+ * 0x01 -> -0.5 dB
+ * ...
+ * 0xFE -> -127dB
+ * 0xFF -> muted
+ */
+
+ /* volume value is in the top 8 bits of the register */
+ return -TFA_SET_BF(tfa, VOL, (uint16_t)vol);
+}
+
+static enum Tfa98xx_Error
+tfa98xx_set_mute_tfa2(struct tfa_device *tfa, enum Tfa98xx_Mute mute)
+{
+ enum Tfa98xx_Error error;
+
+ if (tfa->dev_ops.set_mute == NULL)
+ return Tfa98xx_Error_Not_Supported;
+
+ switch (mute) {
+ case Tfa98xx_Mute_Off:
+ error = tfa->dev_ops.set_mute(tfa, 0);
+ TFA_SET_BF(tfa, AMPE, 1);
+ break;
+ case Tfa98xx_Mute_Amplifier:
+ case Tfa98xx_Mute_Digital:
+ error = tfa->dev_ops.set_mute(tfa, 1);
+ TFA_SET_BF(tfa, AMPE, 0);
+ break;
+ default:
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ return error;
+}
+
+static enum Tfa98xx_Error
+tfa98xx_set_mute_tfa1(struct tfa_device *tfa, enum Tfa98xx_Mute mute)
+{
+ enum Tfa98xx_Error error;
+ unsigned short audioctrl_value;
+ unsigned short sysctrl_value;
+ int value;
+
+ value = TFA_READ_REG(tfa, CFSM); /* audio control register */
+ if (value < 0)
+ return -value;
+ audioctrl_value = (unsigned short)value;
+ value = TFA_READ_REG(tfa, AMPE); /* system control register */
+ if (value < 0)
+ return -value;
+ sysctrl_value = (unsigned short)value;
+
+ switch (mute) {
+ case Tfa98xx_Mute_Off:
+ /* previous state can be digital or amplifier mute,
+ * clear the cf_mute and set the enbl_amplifier bits
+ *
+ * To reduce PLOP at power on it is needed to switch the
+ * amplifier on with the DCDC in follower mode
+ * (enbl_boost = 0 ?).
+ * This workaround is also needed when toggling the
+ * powerdown bit!
+ */
+ TFA_SET_BF_VALUE(tfa, CFSM, 0, &audioctrl_value);
+ TFA_SET_BF_VALUE(tfa, AMPE, 1, &sysctrl_value);
+ TFA_SET_BF_VALUE(tfa, DCA, 1, &sysctrl_value);
+ break;
+ case Tfa98xx_Mute_Digital:
+ /* expect the amplifier to run */
+ /* set the cf_mute bit */
+ TFA_SET_BF_VALUE(tfa, CFSM, 1, &audioctrl_value);
+ /* set the enbl_amplifier bit */
+ TFA_SET_BF_VALUE(tfa, AMPE, 1, &sysctrl_value);
+ /* clear active mode */
+ TFA_SET_BF_VALUE(tfa, DCA, 0, &sysctrl_value);
+ break;
+ case Tfa98xx_Mute_Amplifier:
+ /* clear the cf_mute bit */
+ TFA_SET_BF_VALUE(tfa, CFSM, 0, &audioctrl_value);
+ /* clear the enbl_amplifier bit and active mode */
+ TFA_SET_BF_VALUE(tfa, AMPE, 0, &sysctrl_value);
+ TFA_SET_BF_VALUE(tfa, DCA, 0, &sysctrl_value);
+ break;
+ default:
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ error = -TFA_WRITE_REG(tfa, CFSM, audioctrl_value);
+ if (error)
+ return error;
+ error = -TFA_WRITE_REG(tfa, AMPE, sysctrl_value);
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_set_mute(struct tfa_device *tfa, enum Tfa98xx_Mute mute)
+{
+ if (tfa->in_use == 0) {
+ pr_err("device is not opened \n");
+ return Tfa98xx_Error_NotOpen;
+ }
+
+ if (tfa->tfa_family == 1)
+ return tfa98xx_set_mute_tfa1(tfa, mute);
+ else
+ return tfa98xx_set_mute_tfa2(tfa, mute);
+}
+
+/****************** patching **********************************************************/
+static enum Tfa98xx_Error
+tfa98xx_process_patch_file(struct tfa_device *tfa, int length,
+ const unsigned char *bytes)
+{
+ unsigned short size;
+ int index = 0;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ while (index < length) {
+ size = bytes[index] + bytes[index + 1] * 256;
+ index += 2;
+ if ((index + size) > length) {
+ /* outside the buffer, error in the input data */
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (size > tfa->buffer_size) {
+ /* too big, must fit buffer */
+ return Tfa98xx_Error_Bad_Parameter;
+ }
+
+ error = tfa98xx_write_raw(tfa, size, &bytes[index]);
+ if (error != Tfa98xx_Error_Ok)
+ break;
+ index += size;
+ }
+ return error;
+}
+
+
+
+/* the patch contains a header with the following
+ * IC revision register: 1 byte, 0xFF means don't care
+ * XMEM address to check: 2 bytes, big endian, 0xFFFF means don't care
+ * XMEM value to expect: 3 bytes, big endian
+ */
+static enum Tfa98xx_Error
+tfa98xx_check_ic_rom_version(struct tfa_device *tfa, const unsigned char patchheader[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short checkrev, revid;
+ unsigned char lsb_revid;
+ unsigned short checkaddress;
+ int checkvalue;
+ int value = 0;
+ int status;
+ checkrev = patchheader[0];
+ lsb_revid = tfa->rev & 0xff; /* only compare lower byte */
+
+ if ((checkrev != 0xFF) && (checkrev != lsb_revid))
+ return Tfa98xx_Error_Not_Supported;
+
+ checkaddress = (patchheader[1] << 8) + patchheader[2];
+ checkvalue =
+ (patchheader[3] << 16) + (patchheader[4] << 8) + patchheader[5];
+ if (checkaddress != 0xFFFF) {
+ /* before reading XMEM, check if we can access the DSP */
+ error = tfa98xx_dsp_system_stable(tfa, &status);
+ if (error == Tfa98xx_Error_Ok) {
+ if (!status) {
+ /* DSP subsys not running */
+ error = Tfa98xx_Error_DSP_not_running;
+ }
+ }
+ /* read register to check the correct ROM version */
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfa_mem_read(tfa, checkaddress, 1, &value);
+ }
+ if (error == Tfa98xx_Error_Ok) {
+ if (value != checkvalue) {
+ pr_err("patch file romid type check failed [0x%04x]: expected 0x%02x, actual 0x%02x\n",
+ checkaddress, value, checkvalue);
+ error = Tfa98xx_Error_Not_Supported;
+ }
+ }
+ }
+ else { /* == 0xffff */
+ /* check if the revid subtype is in there */
+ if (checkvalue != 0xFFFFFF && checkvalue != 0) {
+ revid = patchheader[5] << 8 | patchheader[0]; /* full revid */
+ if (revid != tfa->rev) {
+ pr_err("patch file device type check failed: expected 0x%02x, actual 0x%02x\n",
+ tfa->rev, revid);
+ return Tfa98xx_Error_Not_Supported;
+ }
+ }
+ }
+
+ return error;
+}
+
+
+#define PATCH_HEADER_LENGTH 6
+enum Tfa98xx_Error
+ tfa_dsp_patch(struct tfa_device *tfa, int patchLength,
+ const unsigned char *patchBytes)
+{
+ enum Tfa98xx_Error error;
+ int status;
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (patchLength < PATCH_HEADER_LENGTH)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ error = tfa98xx_check_ic_rom_version(tfa, patchBytes);
+ if (Tfa98xx_Error_Ok != error) {
+ return error;
+ }
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status)
+ return Tfa98xx_Error_NoClock; // Only test when we have a clock.
+ /******MCH_TO_TEST**************/
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfaRunColdboot(tfa, 1);
+ if (error)
+ return Tfa98xx_Error_DSP_not_running;
+ }
+ /**************************/
+ error =
+ tfa98xx_process_patch_file(tfa, patchLength - PATCH_HEADER_LENGTH,
+ patchBytes + PATCH_HEADER_LENGTH);
+
+ return error;
+}
+
+/****************** end patching **********************************************************/
+
+TFA_INTERNAL enum Tfa98xx_Error
+tfa98xx_wait_result(struct tfa_device *tfa, int wait_retry_count)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int cf_status; /* the contents of the CF_STATUS register */
+ int tries = 0;
+ do {
+ cf_status = TFA_GET_BF(tfa, ACK);
+ if (cf_status < 0)
+ error = -cf_status;
+ tries++;
+ }
+ // i2c_cmd_ack
+ /* don't wait forever, DSP is pretty quick to respond (< 1ms) */
+ while ((error == Tfa98xx_Error_Ok) && ((cf_status & CF_STATUS_I2C_CMD_ACK) == 0)
+ && (tries < wait_retry_count));
+ if (tries >= wait_retry_count) {
+ /* something wrong with communication with DSP */
+ error = Tfa98xx_Error_DSP_not_running;
+ }
+ return error;
+}
+
+/*
+ * * support functions for data conversion
+ */
+ /**
+ convert memory bytes to signed 24 bit integers
+ input: bytes contains "num_bytes" byte elements
+ output: data contains "num_bytes/3" int24 elements
+ */
+void tfa98xx_convert_bytes2data(int num_bytes, const unsigned char bytes[],
+ int data[])
+{
+ int i; /* index for data */
+ int k; /* index for bytes */
+ int d;
+ int num_data = num_bytes / 3;
+ _ASSERT((num_bytes % 3) == 0);
+ for (i = 0, k = 0; i < num_data; ++i, k += 3) {
+ d = (bytes[k] << 16) | (bytes[k + 1] << 8) | (bytes[k + 2]);
+ _ASSERT(d >= 0);
+ _ASSERT(d < (1 << 24)); /* max 24 bits in use */
+ if (bytes[k] & 0x80) /* sign bit was set */
+ d = -((1 << 24) - d);
+
+ data[i] = d;
+ }
+}
+
+
+/**
+ convert signed 32 bit integers to 24 bit aligned bytes
+ input: data contains "num_data" int elements
+ output: bytes contains "3 * num_data" byte elements
+*/
+void tfa98xx_convert_data2bytes(int num_data, const int data[],
+ unsigned char bytes[])
+{
+ int i; /* index for data */
+ int k; /* index for bytes */
+ int d;
+ /* note: cannot just take the lowest 3 bytes from the 32 bit
+ * integer, because also need to take care of clipping any
+ * value > 2&23 */
+ for (i = 0, k = 0; i < num_data; ++i, k += 3) {
+ if (data[i] >= 0)
+ d = MIN(data[i], (1 << 23) - 1);
+ else {
+ /* 2's complement */
+ d = (1 << 24) - MIN(-data[i], 1 << 23);
+ }
+ _ASSERT(d >= 0);
+ _ASSERT(d < (1 << 24)); /* max 24 bits in use */
+ bytes[k] = (d >> 16) & 0xFF; /* MSB */
+ bytes[k + 1] = (d >> 8) & 0xFF;
+ bytes[k + 2] = (d) & 0xFF; /* LSB */
+ }
+}
+
+/*
+ * DSP RPC message support functions
+ * depending on framework to be up and running
+ * need base i2c of memaccess (tfa1=0x70/tfa2=0x90)
+ */
+
+
+ /* write dsp messages in function tfa_dsp_msg_rpc() */
+ /* note the 'old' write_parameter() was more efficient because all i2c was in one burst transaction */
+
+ //TODO properly handle bitfields: state should be restored! (now it will change eg dmesg field to xmem)
+enum Tfa98xx_Error tfa_dsp_msg_write(struct tfa_device *tfa, int length, const char *buffer)
+{
+ int offset = 0;
+ int chunk_size = ROUND_DOWN(tfa->buffer_size, 3); /* XMEM word size */
+ int remaining_bytes = length;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t cfctl;
+ int value;
+
+ value = TFA_READ_REG(tfa, DMEM);
+ if (value < 0) {
+ error = -value;
+ return error;
+ }
+ cfctl = (uint16_t)value;
+ /* assume no I2C errors from here */
+
+ TFA_SET_BF_VALUE(tfa, DMEM, (uint16_t)Tfa98xx_DMEM_XMEM, &cfctl); /* set cf ctl to DMEM */
+ TFA_SET_BF_VALUE(tfa, AIF, 0, &cfctl); /* set to autoincrement */
+ TFA_WRITE_REG(tfa, DMEM, cfctl);
+
+ /* xmem[1] is start of message
+ * direct write to register to save cycles avoiding read-modify-write
+ */
+ TFA_WRITE_REG(tfa, MADD, 1);
+
+ /* due to autoincrement in cf_ctrl, next write will happen at
+ * the next address */
+ while ((error == Tfa98xx_Error_Ok) && (remaining_bytes > 0)) {
+ if (remaining_bytes < chunk_size)
+ chunk_size = remaining_bytes;
+ /* else chunk_size remains at initialize value above */
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM,
+ chunk_size, (const unsigned char *)buffer + offset);
+ remaining_bytes -= chunk_size;
+ offset += chunk_size;
+ }
+
+ /* notify the DSP */
+ if (error == Tfa98xx_Error_Ok) {
+ /* cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
+ /* set the cf_req1 and cf_int bit */
+ TFA_SET_BF_VALUE(tfa, REQCMD, 0x01, &cfctl); /* bit 0 */
+ TFA_SET_BF_VALUE(tfa, CFINT, 1, &cfctl);
+ error = -TFA_WRITE_REG(tfa, CFINT, cfctl);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg_write_id(struct tfa_device *tfa, int length, const char *buffer, uint8_t cmdid[3])
+{
+ int offset = 0;
+ int chunk_size = ROUND_DOWN(tfa->buffer_size, 3); /* XMEM word size */
+ int remaining_bytes = length;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t cfctl;
+ int value;
+
+ value = TFA_READ_REG(tfa, DMEM);
+ if (value < 0) {
+ error = -value;
+ return error;
+ }
+ cfctl = (uint16_t)value;
+ /* assume no I2C errors from here */
+
+ TFA_SET_BF_VALUE(tfa, DMEM, (uint16_t)Tfa98xx_DMEM_XMEM, &cfctl); /* set cf ctl to DMEM */
+ TFA_SET_BF_VALUE(tfa, AIF, 0, &cfctl); /* set to autoincrement */
+ TFA_WRITE_REG(tfa, DMEM, cfctl);
+
+ /* xmem[1] is start of message
+ * direct write to register to save cycles avoiding read-modify-write
+ */
+ TFA_WRITE_REG(tfa, MADD, 1);
+
+ /* write cmd-id */
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM, 3, (const unsigned char *)cmdid);
+
+ /* due to autoincrement in cf_ctrl, next write will happen at
+ * the next address */
+ while ((error == Tfa98xx_Error_Ok) && (remaining_bytes > 0)) {
+ if (remaining_bytes < chunk_size)
+ chunk_size = remaining_bytes;
+ /* else chunk_size remains at initialize value above */
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM,
+ chunk_size, (const unsigned char *)buffer + offset);
+ remaining_bytes -= chunk_size;
+ offset += chunk_size;
+ }
+
+ /* notify the DSP */
+ if (error == Tfa98xx_Error_Ok) {
+ /* cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
+ /* set the cf_req1 and cf_int bit */
+ TFA_SET_BF_VALUE(tfa, REQCMD, 0x01, &cfctl); /* bit 0 */
+ TFA_SET_BF_VALUE(tfa, CFINT, 1, &cfctl);
+ error = -TFA_WRITE_REG(tfa, CFINT, cfctl);
+ }
+
+ return error;
+}
+
+/*
+* status function used by tfa_dsp_msg_rpc() to retrieve command/msg status:
+* return a <0 status of the DSP did not ACK.
+*/
+enum Tfa98xx_Error tfa_dsp_msg_status(struct tfa_device *tfa, int *pRpcStatus)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ error = tfa98xx_wait_result(tfa, 2); /* 2 is only one try */
+ if (error == Tfa98xx_Error_DSP_not_running) {
+ *pRpcStatus = -1;
+ return Tfa98xx_Error_Ok;
+ }
+ else if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ error = tfa98xx_check_rpc_status(tfa, pRpcStatus);
+
+ return error;
+}
+
+const char* tfa98xx_get_i2c_status_id_string(int status)
+{
+ const char* p_id_str;
+
+ switch (status)
+ {
+ case Tfa98xx_DSP_Not_Running:
+ p_id_str = "No response from DSP";
+ break;
+ case Tfa98xx_I2C_Req_Done:
+ p_id_str = "Ok";
+ break;
+ case Tfa98xx_I2C_Req_Busy:
+ p_id_str = "Request is being processed";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_M_ID:
+ p_id_str = "Provided M-ID does not fit in valid rang [0..2]";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_P_ID:
+ p_id_str = "Provided P-ID is not valid in the given M-ID context";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_CC:
+ p_id_str = "Invalid channel configuration bits (SC|DS|DP|DC) combination";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_Seq:
+ p_id_str = "Invalid sequence of commands, in case the DSP expects some commands in a specific order";
+ break;
+ case Tfa98xx_I2C_Req_Invalid_Param:
+ p_id_str = "Generic error, invalid parameter";
+ break;
+ case Tfa98xx_I2C_Req_Buffer_Overflow:
+ p_id_str = "I2C buffer has overflowed: host has sent too many parameters, memory integrity is not guaranteed";
+ break;
+ case Tfa98xx_I2C_Req_Calib_Busy:
+ p_id_str = "Calibration not completed";
+ break;
+ case Tfa98xx_I2C_Req_Calib_Failed:
+ p_id_str = "Calibration failed";
+ break;
+
+ default:
+ p_id_str = "Unspecified error";
+ }
+
+ return p_id_str;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg_read_rpc(struct tfa_device *tfa, int length, unsigned char *bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int burst_size; /* number of words per burst size */
+ int bytes_per_word = 3;
+ int num_bytes;
+ int offset = 0;
+ unsigned short start_offset = 2; /* msg starts @xmem[2] ,[1]=cmd */
+
+ if (length > TFA2_MAX_PARAM_SIZE)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ TFA_SET_BF(tfa, DMEM, (uint16_t)Tfa98xx_DMEM_XMEM);
+ error = -TFA_WRITE_REG(tfa, MADD, start_offset);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ num_bytes = length; /* input param */
+ while (num_bytes > 0) {
+ burst_size = ROUND_DOWN(tfa->buffer_size, bytes_per_word);
+ if (num_bytes < burst_size)
+ burst_size = num_bytes;
+ error = tfa98xx_read_data(tfa, FAM_TFA98XX_CF_MEM, burst_size, bytes + offset);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ num_bytes -= burst_size;
+ offset += burst_size;
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg(struct tfa_device *tfa, int length24, const char *buf24)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int lastmessage = 0;
+ uint8_t *blob;
+ int i;
+ int *intbuf = NULL;
+ char* buf = (char *)buf24;
+ int length = length24;
+
+ if (tfa->convert_dsp32) {
+ int idx = 0;
+
+ length = 4 * length24 / 3;
+ intbuf = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ buf = (char *)intbuf;
+
+ /* convert 24 bit DSP messages to a 32 bit integer */
+ for (i = 0; i < length24; i += 3) {
+ int tmp = (buf24[i] << 16) + (buf24[i + 1] << 8) + buf24[i + 2];
+ /* Sign extend to 32-bit from 24-bit */
+ intbuf[idx++] = ((int32_t)tmp << 8) >> 8;
+ }
+ }
+
+ /* Only create multi-msg when the dsp is cold */
+ if (tfa->ext_dsp == 1) {
+ /* Creating the multi-msg */
+ error = tfa_tib_dsp_msgmulti(tfa, length, buf);
+ if (error == Tfa98xx_Error_Fail)
+ return Tfa98xx_Error_Fail;
+
+ /* if the buffer is full we need to send the existing message and add the current message */
+ if (error == Tfa98xx_Error_Buffer_too_small) {
+ int len;
+
+ /* (a) send the existing (full) message */
+ blob = kmalloc(64 * 1024, GFP_KERNEL); // max length is 64k
+ len = tfa_tib_dsp_msgmulti(tfa, -1, (const char*)blob);
+ if (tfa->verbose) {
+ pr_debug("Multi-message buffer full. Sending multi-message, length=%d \n", len);
+ }
+ if (tfa->has_msg == 0) /* via i2c */ {
+ /* Send tot the target selected */
+ error = (tfa->dev_ops.tfa_dsp_msg)(tfa, len, (const char*)blob);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_write_dsp(tfa, len, (const char*)blob);
+ }
+ kfree(blob);
+
+ /* (b) add the current DSP message to a new multi-message */
+ error = tfa_tib_dsp_msgmulti(tfa, length, buf);
+ if (error == Tfa98xx_Error_Fail) {
+ return Tfa98xx_Error_Fail;
+ }
+ }
+
+ lastmessage = error;
+
+ /* When the lastmessage is done we can send the multi-msg to the target */
+ if (lastmessage == 1) {
+
+ /* Get the full multi-msg data */
+ blob = kmalloc(64 * 1024, GFP_KERNEL); //max length is 64k
+ length = tfa_tib_dsp_msgmulti(tfa, -1, (const char*)blob);
+
+ if (tfa->verbose)
+ pr_debug("Last message for the multi-message received. Multi-message length=%d \n", length);
+
+ if (tfa->has_msg == 0) /* via i2c */ {
+ /* Send tot the target selected */
+ error = (tfa->dev_ops.tfa_dsp_msg)(tfa, length, (const char*)blob);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_write_dsp(tfa, length, (const char*)blob);
+ }
+
+ kfree(blob); /* Free the kmalloc blob */
+ lastmessage = 0; /* reset to be able to re-start */
+ }
+ }
+ else {
+ if (tfa->has_msg == 0) /* via i2c */ {
+ error = (tfa->dev_ops.tfa_dsp_msg)(tfa, length, buf);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_write_dsp(tfa, length, (const char*)buf);
+ }
+ }
+
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ /* DSP verbose has argument 0x04 */
+ if ((tfa->verbose & 0x04) != 0) {
+ pr_debug("DSP w [%d]: ", length);
+ for (i = 0; i < length; i++)
+ pr_debug("0x%02x ", (uint8_t)buf[i]);
+ pr_debug("\n");
+ }
+
+ if (tfa->convert_dsp32) {
+ kmem_cache_free(tfa->cachep, intbuf);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_dsp_msg_read(struct tfa_device *tfa, int length24, unsigned char *bytes24)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int i;
+ int length = length24;
+ unsigned char *bytes = bytes24;
+
+ if (tfa->convert_dsp32) {
+ length = 4 * length24 / 3;
+ bytes = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ }
+
+ if (tfa->has_msg == 0) /* via i2c */ {
+ error = (tfa->dev_ops.tfa_dsp_msg_read)(tfa, length, bytes);
+ }
+ else { /* via msg hal */
+ error = tfa98xx_read_dsp(tfa, length, bytes);
+ }
+
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ /* DSP verbose has argument 0x04 */
+ if ((tfa->verbose & 0x04) != 0) {
+ pr_debug("DSP R [%d]: ", length);
+ for (i = 0; i < length; i++)
+ pr_debug("0x%02x ", (uint8_t)bytes[i]);
+ pr_debug("\n");
+ }
+
+ if (tfa->convert_dsp32) {
+ int idx = 0;
+
+ /* convert 32 bit LE to 24 bit BE */
+ for (i = 0; i < length; i += 4) {
+ bytes24[idx++] = bytes[i + 2];
+ bytes24[idx++] = bytes[i + 1];
+ bytes24[idx++] = bytes[i + 0];
+ }
+
+ kmem_cache_free(tfa->cachep, bytes);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_reg_read(struct tfa_device *tfa, unsigned char subaddress, unsigned short *value)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_reg_read)(tfa, subaddress, value);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_reg_write(struct tfa_device *tfa, unsigned char subaddress, unsigned short value)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_reg_write)(tfa, subaddress, value);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_mem_read(struct tfa_device *tfa, unsigned int start_offset, int num_words, int *pValues)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_mem_read)(tfa, start_offset, num_words, pValues);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_mem_write(struct tfa_device *tfa, unsigned short address, int value, int memtype)
+{
+ enum Tfa98xx_Error error;
+
+ error = (tfa->dev_ops.tfa_mem_write)(tfa, address, value, memtype);
+ if (error != Tfa98xx_Error_Ok)
+ error = (enum Tfa98xx_Error) (error + Tfa98xx_Error_RpcBase); /* Get actual error code from softDSP */
+
+ return error;
+}
+
+
+/*
+ * write/read raw msg functions :
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ */
+#define MAX_WORDS (300)
+enum Tfa98xx_Error tfa_dsp_msg_rpc(struct tfa_device *tfa, int length, const char *buf)
+{
+ enum Tfa98xx_Error error;
+ int tries, rpc_status = Tfa98xx_I2C_Req_Done;
+
+ /* write the message and notify the DSP */
+ error = tfa_dsp_msg_write(tfa, length, buf);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* get the result from the DSP (polling) */
+ for (tries = TFA98XX_WAITRESULT_NTRIES; tries > 0; tries--) {
+ error = tfa_dsp_msg_status(tfa, &rpc_status);
+ if (error == Tfa98xx_Error_Ok && rpc_status == Tfa98xx_I2C_Req_Done)
+ break;
+ /* If the rpc status is a specific error we want to know it.
+ * If it is busy or not running it should retry
+ */
+ if (rpc_status != Tfa98xx_I2C_Req_Busy && rpc_status != Tfa98xx_DSP_Not_Running)
+ break;
+ }
+
+ if (rpc_status != Tfa98xx_I2C_Req_Done) {
+ /* DSP RPC call returned an error */
+ error = (enum Tfa98xx_Error) (rpc_status + Tfa98xx_Error_RpcBase);
+ pr_debug("DSP msg status: %d (%s)\n", rpc_status, tfa98xx_get_i2c_status_id_string(rpc_status));
+ }
+ return error;
+}
+
+/**
+ * write/read raw msg functions:
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ * An ID is added to modify the command-ID
+ */
+enum Tfa98xx_Error tfa_dsp_msg_id(struct tfa_device *tfa, int length, const char *buf, uint8_t cmdid[3])
+{
+ enum Tfa98xx_Error error;
+ int tries, rpc_status = Tfa98xx_I2C_Req_Done;
+
+ /* write the message and notify the DSP */
+ error = tfa_dsp_msg_write_id(tfa, length, buf, cmdid);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* get the result from the DSP (polling) */
+ for (tries = TFA98XX_WAITRESULT_NTRIES; tries > 0; tries--) {
+ error = tfa_dsp_msg_status(tfa, &rpc_status);
+ if (error == Tfa98xx_Error_Ok && rpc_status == Tfa98xx_I2C_Req_Done)
+ break;
+ }
+
+ if (rpc_status != Tfa98xx_I2C_Req_Done) {
+ /* DSP RPC call returned an error */
+ error = (enum Tfa98xx_Error) (rpc_status + Tfa98xx_Error_RpcBase);
+ pr_debug("DSP msg status: %d (%s)\n", rpc_status, tfa98xx_get_i2c_status_id_string(rpc_status));
+ }
+ return error;
+}
+
+/* read the return code for the RPC call */
+TFA_INTERNAL enum Tfa98xx_Error
+tfa98xx_check_rpc_status(struct tfa_device *tfa, int *pRpcStatus)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ /* the value to sent to the * CF_CONTROLS register: cf_req=00000000,
+ * cf_int=0, cf_aif=0, cf_dmem=XMEM=01, cf_rst_dsp=0 */
+ unsigned short cf_ctrl = 0x0002;
+ /* memory address to be accessed (0: Status, 1: ID, 2: parameters) */
+ unsigned short cf_mad = 0x0000;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ if (pRpcStatus == NULL)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ /* 1) write DMEM=XMEM to the DSP XMEM */
+ {
+ /* minimize the number of I2C transactions by making use of the autoincrement in I2C */
+ unsigned char buffer[4];
+ /* first the data for CF_CONTROLS */
+ buffer[0] = (unsigned char)((cf_ctrl >> 8) & 0xFF);
+ buffer[1] = (unsigned char)(cf_ctrl & 0xFF);
+ /* write the contents of CF_MAD which is the subaddress following CF_CONTROLS */
+ buffer[2] = (unsigned char)((cf_mad >> 8) & 0xFF);
+ buffer[3] = (unsigned char)(cf_mad & 0xFF);
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_CONTROLS, sizeof(buffer), buffer);
+ }
+ if (error == Tfa98xx_Error_Ok) {
+ /* read 1 word (24 bit) from XMEM */
+ error = tfa98xx_dsp_read_mem(tfa, 0, 1, pRpcStatus);
+ }
+
+ return error;
+}
+
+/***************************** xmem only **********************************/
+enum Tfa98xx_Error
+ tfa98xx_dsp_read_mem(struct tfa_device *tfa,
+ unsigned int start_offset, int num_words, int *pValues)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned char *bytes;
+ int burst_size; /* number of words per burst size */
+ const int bytes_per_word = 3;
+ int dmem;
+ int num_bytes;
+ int *p;
+
+ bytes = (unsigned char *)kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (bytes == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* If no offset is given, assume XMEM! */
+ if (((start_offset >> 16) & 0xf) > 0)
+ dmem = (start_offset >> 16) & 0xf;
+ else
+ dmem = Tfa98xx_DMEM_XMEM;
+
+ /* Remove offset from adress */
+ start_offset = start_offset & 0xffff;
+ num_bytes = num_words * bytes_per_word;
+ p = pValues;
+
+ TFA_SET_BF(tfa, DMEM, (uint16_t)dmem);
+ error = -TFA_WRITE_REG(tfa, MADD, (unsigned short)start_offset);
+ if (error != Tfa98xx_Error_Ok)
+ goto tfa98xx_dsp_read_mem_exit;
+
+ for (; num_bytes > 0;) {
+ burst_size = ROUND_DOWN(tfa->buffer_size, bytes_per_word);
+ if (num_bytes < burst_size)
+ burst_size = num_bytes;
+
+ _ASSERT(burst_size <= sizeof(bytes));
+ error = tfa98xx_read_data(tfa, FAM_TFA98XX_CF_MEM, burst_size, bytes);
+ if (error != Tfa98xx_Error_Ok)
+ goto tfa98xx_dsp_read_mem_exit;
+
+ tfa98xx_convert_bytes2data(burst_size, bytes, p);
+
+ num_bytes -= burst_size;
+ p += burst_size / bytes_per_word;
+ }
+
+tfa98xx_dsp_read_mem_exit:
+ kmem_cache_free(tfa->cachep, bytes);
+
+ return error;
+}
+
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_mem_word(struct tfa_device *tfa, unsigned short address, int value, int memtype)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned char bytes[3];
+
+ TFA_SET_BF(tfa, DMEM, (uint16_t)memtype);
+
+ error = -TFA_WRITE_REG(tfa, MADD, address);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ tfa98xx_convert_data2bytes(1, &value, bytes);
+ error = tfa98xx_write_data(tfa, FAM_TFA98XX_CF_MEM, 3, bytes);
+
+ return error;
+}
+
+enum Tfa98xx_Error tfa_cont_write_filterbank(struct tfa_device *tfa, TfaFilter_t *filter)
+{
+ unsigned char biquad_index;
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ for (biquad_index = 0; biquad_index < 10; biquad_index++) {
+ if (filter[biquad_index].enabled) {
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_BIQUADFILTERBANK,
+ biquad_index + 1, //start @1
+ sizeof(filter[biquad_index].biquad.bytes),
+ filter[biquad_index].biquad.bytes);
+ }
+ else {
+ error = Tfa98xx_DspBiquad_Disable(tfa, biquad_index + 1);
+ }
+ if (error) return error;
+
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ Tfa98xx_DspBiquad_Disable(struct tfa_device *tfa, int biquad_index)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int coeff_buffer[BIQUAD_COEFF_SIZE];
+ unsigned char bytes[3 + BIQUAD_COEFF_SIZE * 3];
+ int nr = 0;
+
+ if (biquad_index > TFA98XX_BIQUAD_NUM)
+ return Tfa98xx_Error_Bad_Parameter;
+ if (biquad_index < 1)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ /* make opcode */
+ bytes[nr++] = 0;
+ bytes[nr++] = MODULE_BIQUADFILTERBANK + 128;
+ bytes[nr++] = (unsigned char)biquad_index;
+
+
+ /* set in correct order and format for the DSP */
+ coeff_buffer[0] = (int)-8388608; /* -1.0f */
+ coeff_buffer[1] = 0;
+ coeff_buffer[2] = 0;
+ coeff_buffer[3] = 0;
+ coeff_buffer[4] = 0;
+ coeff_buffer[5] = 0;
+
+ /* convert to packed 24 */
+ tfa98xx_convert_data2bytes(BIQUAD_COEFF_SIZE, coeff_buffer, &bytes[nr]);
+ nr += BIQUAD_COEFF_SIZE * 3;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)bytes);
+
+ return error;
+}
+
+/* wrapper for tfa_dsp_msg that adds opcode */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ const unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char *buffer;
+ int nr = 0;
+
+ buffer = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (buffer == NULL)
+ return Tfa98xx_Error_Fail;
+
+ buffer[nr++] = tfa->spkr_select;
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ memcpy(&buffer[nr], data, num_bytes);
+ nr += num_bytes;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+
+ kmem_cache_free(tfa->cachep, buffer);
+
+ return error;
+}
+
+/* wrapper for tfa_dsp_msg that adds opcode */
+/* this is as the former tfa98xx_dsp_get_param() */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write_read(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char buffer[3];
+ int nr = 0;
+
+ if (num_bytes <= 0) {
+ pr_debug("Error: The number of READ bytes is smaller or equal to 0! \n");
+ return Tfa98xx_Error_Fail;
+ }
+
+ if ((tfa->is_probus_device) && (tfa->cnt->ndev == 1) &&
+ (param_id == SB_PARAM_GET_RE25C ||
+ param_id == SB_PARAM_GET_LSMODEL ||
+ param_id == SB_PARAM_GET_ALGO_PARAMS)) {
+ /* Modifying the ID for GetRe25C */
+ buffer[nr++] = 4;
+ }
+ else {
+ buffer[nr++] = tfa->spkr_select;
+ }
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the dsp */
+ error = tfa_dsp_msg_read(tfa, num_bytes, data);
+ return error;
+}
+
+/* wrapper for dsp_msg that adds opcode and 3 bytes required for coefs */
+enum Tfa98xx_Error tfa_dsp_cmd_id_coefs(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char buffer[2 * 3];
+ int nr = 0;
+ char api_ver[4] = { 0 };
+
+ //Get rev id
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK, FW_PAR_ID_GET_API_VERSION, 3, api_ver);
+ buffer[nr++] = tfa->spkr_select;
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ if ((api_ver[1] < TFA_API_SBFW_8_09_00) || (api_ver[0] == 2)) { //(api_ver[0] == 2) is for 88 device
+
+ buffer[nr++] = 0;
+ buffer[nr++] = 0;
+ buffer[nr++] = 0;
+ }
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the dsp */
+ error = tfa_dsp_msg_read(tfa, num_bytes, data);
+
+ return error;
+}
+
+/* wrapper for dsp_msg that adds opcode and 3 bytes required for MBDrcDynamics */
+enum Tfa98xx_Error tfa_dsp_cmd_id_MBDrc_dynamics(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int index_subband,
+ int num_bytes, unsigned char data[])
+{
+ enum Tfa98xx_Error error;
+ unsigned char buffer[2 * 3];
+ int nr = 0;
+
+ buffer[nr++] = tfa->spkr_select;
+ buffer[nr++] = module_id + 128;
+ buffer[nr++] = param_id;
+
+ buffer[nr++] = 0;
+ buffer[nr++] = 0;
+ buffer[nr++] = (unsigned char)index_subband;
+
+ error = tfa_dsp_msg(tfa, nr, (char *)buffer);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ /* read the data from the dsp */
+ error = tfa_dsp_msg_read(tfa, num_bytes, data);
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_preset(struct tfa_device *tfa, int length,
+ const unsigned char *p_preset_bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ if (p_preset_bytes != NULL) {
+ /* by design: keep the data opaque and no
+ * interpreting/calculation */
+ error = tfa_dsp_cmd_id_write(tfa, MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_PRESET, length,
+ p_preset_bytes);
+ }
+ else {
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ return error;
+}
+
+/*
+ * get features from MTP
+ */
+enum Tfa98xx_Error
+ tfa98xx_dsp_get_hw_feature_bits(struct tfa_device *tfa, int *features)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint32_t value;
+ uint16_t mtpbf;
+
+ /* return the cache data if it's valid */
+ if (tfa->hw_feature_bits != -1) {
+ *features = tfa->hw_feature_bits;
+ }
+ else {
+ /* for tfa1 check if we have clock */
+ if (tfa->tfa_family == 1) {
+ int status;
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status) {
+ tfa_get_hw_features_from_cnt(tfa, features);
+ /* skip reading MTP: */
+ return (*features == -1) ? Tfa98xx_Error_Fail : Tfa98xx_Error_Ok;
+ }
+ mtpbf = 0x850f; /* MTP5 for tfa1,16 bits */
+ }
+ else
+ mtpbf = 0xf907; /* MTP9 for tfa2, 8 bits */
+ value = tfa_read_reg(tfa, mtpbf) & 0xffff;
+ *features = tfa->hw_feature_bits = value;
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_get_sw_feature_bits(struct tfa_device *tfa, int features[2])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ const int byte_size = 2 * 3;
+ unsigned char bytes[2 * 3];
+
+ /* return the cache data if it's valid */
+ if (tfa->sw_feature_bits[0] != -1) {
+ features[0] = tfa->sw_feature_bits[0];
+ features[1] = tfa->sw_feature_bits[1];
+ }
+ else {
+ /* for tfa1 check if we have clock */
+ if (tfa->tfa_family == 1) {
+ int status;
+ tfa98xx_dsp_system_stable(tfa, &status);
+ if (!status) {
+ tfa_get_sw_features_from_cnt(tfa, features);
+ /* skip reading MTP: */
+ return (features[0] == -1) ? Tfa98xx_Error_Fail : Tfa98xx_Error_Ok;
+ }
+ }
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK,
+ FW_PAR_ID_GET_FEATURE_INFO, byte_size, bytes);
+
+ if (error != Tfa98xx_Error_Ok) {
+ /* old ROM code may respond with Tfa98xx_Error_RpcParamId */
+ return error;
+ }
+
+ tfa98xx_convert_bytes2data(byte_size, bytes, features);
+ }
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_get_state_info(struct tfa_device *tfa, unsigned char bytes[], unsigned int *statesize)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int bSupportFramework = 0;
+ unsigned int stateSize = 9;
+
+ err = tfa98xx_dsp_support_framework(tfa, &bSupportFramework);
+ if (err == Tfa98xx_Error_Ok) {
+ if (bSupportFramework) {
+ err = tfa_dsp_cmd_id_write_read(tfa, MODULE_FRAMEWORK,
+ FW_PARAM_GET_STATE, 3 * stateSize, bytes);
+ }
+ else {
+ /* old ROM code, ask SpeakerBoost and only do first portion */
+ stateSize = 8;
+ err = tfa_dsp_cmd_id_write_read(tfa, MODULE_SPEAKERBOOST,
+ SB_PARAM_GET_STATE, 3 * stateSize, bytes);
+ }
+ }
+
+ *statesize = stateSize;
+
+ return err;
+}
+
+enum Tfa98xx_Error tfa98xx_dsp_support_drc(struct tfa_device *tfa, int *pbSupportDrc)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ *pbSupportDrc = 0;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ if (tfa->supportDrc != supportNotSet) {
+ *pbSupportDrc = (tfa->supportDrc == supportYes);
+ }
+ else {
+ int featureBits[2];
+
+ error = tfa98xx_dsp_get_sw_feature_bits(tfa, featureBits);
+ if (error == Tfa98xx_Error_Ok) {
+ /* easy case: new API available */
+ /* bit=0 means DRC enabled */
+ *pbSupportDrc = (featureBits[0] & FEATURE1_DRC) == 0;
+ }
+ else if (error == Tfa98xx_Error_RpcParamId) {
+ /* older ROM code, doesn't support it */
+ *pbSupportDrc = 0;
+ error = Tfa98xx_Error_Ok;
+ }
+ /* else some other error, return transparently */
+ /* pbSupportDrc only changed when error == Tfa98xx_Error_Ok */
+
+ if (error == Tfa98xx_Error_Ok) {
+ tfa->supportDrc = *pbSupportDrc ? supportYes : supportNo;
+ }
+ }
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_support_framework(struct tfa_device *tfa, int *pbSupportFramework)
+{
+ int featureBits[2] = { 0, 0 };
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ _ASSERT(pbSupportFramework != 0);
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (tfa->supportFramework != supportNotSet) {
+ if (tfa->supportFramework == supportNo)
+ *pbSupportFramework = 0;
+ else
+ *pbSupportFramework = 1;
+ }
+ else {
+ error = tfa98xx_dsp_get_sw_feature_bits(tfa, featureBits);
+ if (error == Tfa98xx_Error_Ok) {
+ *pbSupportFramework = 1;
+ tfa->supportFramework = supportYes;
+ }
+ else {
+ *pbSupportFramework = 0;
+ tfa->supportFramework = supportNo;
+ error = Tfa98xx_Error_Ok;
+ }
+ }
+
+ /* *pbSupportFramework only changed when error == Tfa98xx_Error_Ok */
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_speaker_parameters(struct tfa_device *tfa,
+ int length, const unsigned char *p_speaker_bytes)
+{
+ enum Tfa98xx_Error error;
+ int bSupportDrc;
+
+ if (p_speaker_bytes != NULL) {
+ /* by design: keep the data opaque and no
+ * interpreting/calculation */
+ /* Use long WaitResult retry count */
+ error = tfa_dsp_cmd_id_write(
+ tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_LSMODEL, length,
+ p_speaker_bytes);
+ }
+ else {
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ error = tfa98xx_dsp_support_drc(tfa, &bSupportDrc);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ if (bSupportDrc) {
+ /* Need to set AgcGainInsert back to PRE,
+ * as the SetConfig forces it to POST */
+ uint8_t bytes[3] = { 0, 0, 0 };
+
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_AGCINS,
+ 3,
+ bytes);
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_dsp_write_config(struct tfa_device *tfa, int length,
+ const unsigned char *p_config_bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int bSupportDrc;
+
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_CONFIG, length,
+ p_config_bytes);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ error = tfa98xx_dsp_support_drc(tfa, &bSupportDrc);
+ if (error != Tfa98xx_Error_Ok)
+ return error;
+
+ if (bSupportDrc) {
+ /* Need to set AgcGainInsert back to PRE,
+ * as the SetConfig forces it to POST */
+ uint8_t bytes[3] = { 0, 0, 0 };
+
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_AGCINS,
+ 3,
+ bytes);
+ }
+
+ return error;
+}
+
+/* load all the parameters for the DRC settings from a file */
+enum Tfa98xx_Error tfa98xx_dsp_write_drc(struct tfa_device *tfa,
+ int length, const unsigned char *p_drc_bytes)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ if (p_drc_bytes != NULL) {
+ error = tfa_dsp_cmd_id_write(tfa,
+ MODULE_SPEAKERBOOST,
+ SB_PARAM_SET_DRC, length,
+ p_drc_bytes);
+
+ }
+ else {
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ return error;
+}
+
+enum Tfa98xx_Error tfa98xx_powerdown(struct tfa_device *tfa, int powerdown)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ error = TFA_SET_BF(tfa, PWDN, (uint16_t)powerdown);
+
+ if (powerdown) {
+ /* Workaround for ticket PLMA5337 */
+ if (tfa->tfa_family == 2) {
+ TFA_SET_BF_VOLATILE(tfa, AMPE, 0);
+ }
+ }
+
+ return error;
+}
+
+enum Tfa98xx_Error
+ tfa98xx_select_mode(struct tfa_device *tfa, enum Tfa98xx_Mode mode)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ if (error == Tfa98xx_Error_Ok) {
+ switch (mode) {
+
+ default:
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ }
+
+ return error;
+}
+
+int tfa_set_bf(struct tfa_device *tfa, const uint16_t bf, const uint16_t value)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue, msk, oldvalue;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err) {
+ pr_err("Error getting bf :%d \n", -err);
+ return -err;
+ }
+
+ oldvalue = regvalue;
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= ~msk;
+ regvalue |= value << pos;
+
+ /* Only write when the current register value is not the same as the new value */
+ if (oldvalue != regvalue) {
+ err = tfa_reg_write(tfa, address, regvalue);
+ if (err) {
+ pr_err("Error setting bf :%d \n", -err);
+ return -err;
+ }
+ }
+
+ return 0;
+}
+
+int tfa_set_bf_volatile(struct tfa_device *tfa, const uint16_t bf, const uint16_t value)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue, msk;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err) {
+ pr_err("Error getting bf :%d \n", -err);
+ return -err;
+ }
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= ~msk;
+ regvalue |= value << pos;
+
+ err = tfa_reg_write(tfa, address, regvalue);
+ if (err) {
+ pr_err("Error setting bf :%d \n", -err);
+ return -err;
+ }
+
+ return 0;
+}
+
+int tfa_get_bf(struct tfa_device *tfa, const uint16_t bf)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue, msk;
+ uint16_t value;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err) {
+ pr_err("Error getting bf :%d \n", -err);
+ return -err;
+ }
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= msk;
+ value = regvalue >> pos;
+
+ return value;
+}
+
+int tfa_set_bf_value(const uint16_t bf, const uint16_t bf_value, uint16_t *p_reg_value)
+{
+ uint16_t regvalue, msk;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+
+ regvalue = *p_reg_value;
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ regvalue &= ~msk;
+ regvalue |= bf_value << pos;
+
+ *p_reg_value = regvalue;
+
+ return 0;
+}
+
+uint16_t tfa_get_bf_value(const uint16_t bf, const uint16_t reg_value)
+{
+ uint16_t msk, value;
+
+ /*
+ * bitfield enum:
+ * - 0..3 : len
+ * - 4..7 : pos
+ * - 8..15 : address
+ */
+ uint8_t len = bf & 0x0f;
+ uint8_t pos = (bf >> 4) & 0x0f;
+
+ msk = ((1 << (len + 1)) - 1) << pos;
+ value = (reg_value & msk) >> pos;
+
+ return value;
+}
+
+
+int tfa_write_reg(struct tfa_device *tfa, const uint16_t bf, const uint16_t reg_value)
+{
+ enum Tfa98xx_Error err;
+
+ /* bitfield enum - 8..15 : address */
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_write(tfa, address, reg_value);
+ if (err)
+ return -err;
+
+ return 0;
+}
+
+int tfa_read_reg(struct tfa_device *tfa, const uint16_t bf)
+{
+ enum Tfa98xx_Error err;
+ uint16_t regvalue;
+
+ /* bitfield enum - 8..15 : address */
+ uint8_t address = (bf >> 8) & 0xff;
+
+ err = tfa_reg_read(tfa, address, &regvalue);
+ if (err)
+ return -err;
+
+ return regvalue;
+}
+
+/*
+ * powerup the coolflux subsystem and wait for it
+ */
+enum Tfa98xx_Error tfa_cf_powerup(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int tries, status;
+
+ /* power on the sub system */
+ TFA_SET_BF_VOLATILE(tfa, PWDN, 0);
+
+ // wait until everything is stable, in case clock has been off
+ if (tfa->verbose)
+ pr_info("Waiting for DSP system stable...\n");
+ for (tries = CFSTABLE_TRIES; tries > 0; tries--) {
+ err = tfa98xx_dsp_system_stable(tfa, &status);
+ _ASSERT(err == Tfa98xx_Error_Ok);
+ if (status)
+ break;
+ else
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ }
+ if (tries == 0) {// timedout
+ pr_err("DSP subsystem start timed out\n");
+ return Tfa98xx_Error_StateTimedOut;
+ }
+
+ return err;
+}
+
+/*
+ * Enable/Disable the I2S output for TFA1 devices
+ * without TDM interface
+ */
+static enum Tfa98xx_Error tfa98xx_aec_output(struct tfa_device *tfa, int enable)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if ((tfa->daimap & Tfa98xx_DAI_TDM) == Tfa98xx_DAI_TDM)
+ return err;
+
+ if (tfa->tfa_family == 1)
+ err = -tfa_set_bf(tfa, TFA1_BF_I2SDOE, (enable != 0));
+ else {
+ pr_err("I2SDOE on unsupported family\n");
+ err = Tfa98xx_Error_Not_Supported;
+ }
+
+ return err;
+}
+
+/*
+ * Print the current state of the hardware manager
+ * Device manager status information, man_state from TFA9888_N1B_I2C_regmap_V12
+ */
+int tfa_is_94_N2_device(struct tfa_device *tfa)
+{
+ return ((((tfa->rev) & 0xff) == 0x94) && (((tfa->rev >> 8) & 0xff) > 0x1a));
+}
+enum Tfa98xx_Error tfa_show_current_state(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int manstate = -1;
+
+ if (tfa->tfa_family == 2 && tfa->verbose) {
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ if (manstate < 0)
+ return -manstate;
+
+ pr_debug("Current HW manager state: ");
+
+ switch (manstate) {
+ case 0: pr_debug("power_down_state \n");
+ break;
+ case 1: pr_debug("wait_for_source_settings_state \n");
+ break;
+ case 2: pr_debug("connnect_pll_input_state \n");
+ break;
+ case 3: pr_debug("disconnect_pll_input_state \n");
+ break;
+ case 4: pr_debug("enable_pll_state \n");
+ break;
+ case 5: pr_debug("enable_cgu_state \n");
+ break;
+ case 6: pr_debug("init_cf_state \n");
+ break;
+ case 7: pr_debug("enable_amplifier_state \n");
+ break;
+ case 8: pr_debug("alarm_state \n");
+ break;
+ case 9: pr_debug("operating_state \n");
+ break;
+ case 10: pr_debug("mute_audio_state \n");
+ break;
+ case 11: pr_debug("disable_cgu_pll_state \n");
+ break;
+ default:
+ pr_debug("Unable to find current state \n");
+ break;
+ }
+ }
+
+ return err;
+}
+
+enum Tfa98xx_Error tfaGetFwApiVersion(struct tfa_device *tfa, unsigned char *pFirmwareVersion)
+{
+ enum Tfa98xx_Error err = 0;
+ char cmd_buf[4];
+ int cmd_len, res_len;
+
+ if (tfa == NULL)
+ return Tfa98xx_Error_Bad_Parameter;
+ if (!tfa->is_probus_device)
+ {
+ int buffer;
+ err = tfa_mem_read(tfa, FW_VAR_API_VERSION, 1, (int *)(&buffer));
+ if (err) {
+ pr_debug("%s Error: Unable to get API Version from DSP \n", __FUNCTION__);
+ return err;
+ }
+ pFirmwareVersion[0] = (buffer >> 16) & 0xff;
+ pFirmwareVersion[1] = (buffer >> 8) & 0xff;
+ if ((pFirmwareVersion[0] != 2) && (pFirmwareVersion[1] >= 33)) {
+ pFirmwareVersion[2] = (buffer >> 3) & 0x1F;
+ pFirmwareVersion[3] = (buffer) & 0x07;
+ } else {
+ pFirmwareVersion[2] = (buffer >> 6) & 0x03;
+ pFirmwareVersion[3] = (buffer) & 0x3f;
+ }
+ }
+ else
+ {
+ unsigned char buffer[4 * 3] = { 0 };
+ cmd_len = 0x03;
+
+ /* GetAPI: Command is 0x00 0x80 0xFE */
+ cmd_buf[0] = 0x00;
+ cmd_buf[1] = 0x80;
+ cmd_buf[2] = 0xFE;
+
+ /* Write the command.*/
+
+ err = tfa98xx_write_dsp(tfa, cmd_len, (const char *)cmd_buf);
+
+ /* Read the API Value.*/
+ if (err == 0)
+ {
+ res_len = 3;
+ err = tfa98xx_read_dsp(tfa, res_len, (unsigned char *)buffer);
+
+ }
+
+ /* Split 3rd byte into two seperate ITF version fields (3rd field and 4th field) */
+ pFirmwareVersion[0] = (buffer[0]);
+ pFirmwareVersion[1] = (buffer[1]);
+ if ((pFirmwareVersion[0] != 2) && (pFirmwareVersion[1] >= 33)) {
+ pFirmwareVersion[3] = (buffer[2]) & 0x07;
+ pFirmwareVersion[2] = (buffer[2] >> 3) & 0x1F;
+ } else {
+ pFirmwareVersion[3] = (buffer[2]) & 0x3f;
+ pFirmwareVersion[2] = (buffer[2] >> 6) & 0x03;
+ }
+ }
+
+ if (1 == tfa->cnt->ndev) {
+ /* Mono configuration */
+ /* Workaround for FW 8.9.0 (FW API x.31.y.z) & above.
+ Firmware cannot return the 4th field (mono/stereo) of ITF version correctly, as it requires
+ certain set of messages to be sent before it can detect itself as a mono/stereo configuration.
+ Hence, HostSDK need to handle this at system level */
+ if ((pFirmwareVersion[0] == 8) && (pFirmwareVersion[1] >= 31)) {
+ pFirmwareVersion[3] = 1;
+ }
+ }
+
+
+ return err;
+
+}
+
+
+/*
+ * start the speakerboost algorithm
+ * this implies a full system startup when the system was not already started
+ *
+ */
+enum Tfa98xx_Error tfaRunSpeakerBoost(struct tfa_device *tfa, int force, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int value;
+
+ if (force) {
+ err = tfaRunColdStartup(tfa, profile);
+ if (err) return err;
+ }
+
+ /* Returns 1 when device is "cold" and 0 when device is warm */
+ value = tfa_is_cold(tfa);
+
+ pr_debug("Startup of device [%s] is a %sstart\n", tfaContDeviceName(tfa->cnt, tfa->dev_idx), value ? "cold" : "warm");
+ /* cold start and not tap profile */
+ if (value) {
+ /* Run startup and write all files */
+ err = tfaRunSpeakerStartup(tfa, force, profile);
+ if (err) return err;
+
+ /* Save the current profile and set the vstep to 0 */
+ /* This needs to be overwriten even in CF bypass */
+ tfa_dev_set_swprof(tfa, (unsigned short)profile);
+ tfa_dev_set_swvstep(tfa, 0);
+
+ /* Synchonize I/V delay on 96/97 at cold start */
+ if ((tfa->tfa_family == 1) && (tfa->daimap == Tfa98xx_DAI_TDM))
+ tfa->sync_iv_delay = 1;
+ }
+
+ return err;
+}
+
+enum Tfa98xx_Error tfaRunSpeakerStartup(struct tfa_device *tfa, int force, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ if (!force) { // in case of force CF already runnning
+ err = tfaRunStartup(tfa, profile);
+ PRINT_ASSERT(err);
+ if (err)
+ return err;
+
+ /* Startup with CF in bypass then return here */
+ if (tfa_cf_enabled(tfa) == 0)
+ return err;
+
+ /* respond to external DSP: -1:none, 0:no_dsp, 1:cold, 2:warm */
+ if (tfa->ext_dsp == -1) {
+ err = tfaRunStartDSP(tfa);
+ if (err)
+ return err;
+ }
+ }
+
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1 */
+ tfa98xx_auto_copy_mtp_to_iic(tfa);
+
+ err = tfaGetFwApiVersion(tfa, (unsigned char *)&tfa->fw_itf_ver[0]);
+ if (err) {
+ pr_debug("[%s] cannot get FWAPI error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+ /* write all the files from the device list */
+ err = tfaContWriteFiles(tfa);
+ if (err) {
+ pr_debug("[%s] tfaContWriteFiles error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+
+ /* write all the files from the profile list (use volumstep 0) */
+ err = tfaContWriteFilesProf(tfa, profile, 0);
+ if (err) {
+ pr_debug("[%s] tfaContWriteFilesProf error = %d \n", __FUNCTION__, err);
+ return err;
+ }
+
+ return err;
+}
+
+/*
+ * Run calibration
+ */
+enum Tfa98xx_Error tfaRunSpeakerCalibration(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int calibrateDone;
+
+ /* return if there is no audio running */
+ if ((tfa->tfa_family == 2) && TFA_GET_BF(tfa, NOCLK))
+ return Tfa98xx_Error_NoClock;
+
+ /* When MTPOTC is set (cal=once) unlock key2 */
+ if (TFA_GET_BF(tfa, MTPOTC) == 1) {
+ tfa98xx_key2(tfa, 0);
+ }
+
+ /* await calibration, this should return ok */
+ err = tfaRunWaitCalibration(tfa, &calibrateDone);
+ if (err == Tfa98xx_Error_Ok) {
+ err = tfa_dsp_get_calibration_impedance(tfa);
+ PRINT_ASSERT(err);
+ }
+
+ /* When MTPOTC is set (cal=once) re-lock key2 */
+ if (TFA_GET_BF(tfa, MTPOTC) == 1) {
+ tfa98xx_key2(tfa, 1);
+ }
+
+ return err;
+}
+
+enum Tfa98xx_Error tfaRunColdboot(struct tfa_device *tfa, int state)
+{
+#define CF_CONTROL 0x8100
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int tries = 10;
+
+ /* repeat set ACS bit until set as requested */
+ while (state != TFA_GET_BF(tfa, ACS)) {
+ /* set colstarted in CF_CONTROL to force ACS */
+ err = tfa_mem_write(tfa, CF_CONTROL, state, Tfa98xx_DMEM_IOMEM);
+ PRINT_ASSERT(err);
+
+ if (tries-- == 0) {
+ pr_debug("coldboot (ACS) did not %s\n", state ? "set" : "clear");
+ return Tfa98xx_Error_Other;
+ }
+ }
+
+ return err;
+}
+
+
+
+/*
+ * load the patch if any
+ * else tell no loaded
+ */
+static enum Tfa98xx_Error tfa_run_load_patch(struct tfa_device *tfa)
+{
+ return tfaContWritePatch(tfa);
+}
+
+/*
+ * this will load the patch witch will implicitly start the DSP
+ * if no patch is available the DPS is started immediately
+ */
+enum Tfa98xx_Error tfaRunStartDSP(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ err = tfa_run_load_patch(tfa);
+ if (err) { /* patch load is fatal so return immediately*/
+ return err;
+ }
+
+ /* Clear count_boot, should be reset to 0 before the DSP reset is released */
+ err = tfa_mem_write(tfa, 512, 0, Tfa98xx_DMEM_XMEM);
+ PRINT_ASSERT(err);
+
+ /* Reset DSP once for sure after initializing */
+ if (err == Tfa98xx_Error_Ok) {
+ err = tfa98xx_dsp_reset(tfa, 0);
+ PRINT_ASSERT(err);
+ }
+
+ /* Sample rate is needed to set the correct tables */
+ err = tfa98xx_dsp_write_tables(tfa, TFA_GET_BF(tfa, AUDFS));
+ PRINT_ASSERT(err);
+
+ return err;
+}
+
+/*
+ * start the clocks and wait until the AMP is switching
+ * on return the DSP sub system will be ready for loading
+ */
+enum Tfa98xx_Error tfaRunStartup(struct tfa_device *tfa, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ TfaDeviceList_t *dev = tfaContDevice(tfa->cnt, tfa->dev_idx);
+ int i, noinit = 0, audfs = 0, fractdel = 0;
+
+ if (dev == NULL)
+ return Tfa98xx_Error_Fail;
+
+ if (dev->bus) /* no i2c device, do nothing */
+ return Tfa98xx_Error_Ok;
+
+ /* process the device list to see if the user implemented the noinit */
+ for (i = 0; i < dev->length; i++) {
+ if (dev->list[i].type == dscNoInit) {
+ noinit = 1;
+ break;
+ }
+ }
+
+ if (!noinit) {
+ /* Read AUDFS & FRACTDEL prior to (re)init. */
+ audfs = TFA_GET_BF(tfa, AUDFS);
+ fractdel = TFA_GET_BF(tfa, FRACTDEL);
+ /* load the optimal TFA98XX in HW settings */
+ err = tfa98xx_init(tfa);
+ PRINT_ASSERT(err);
+
+ /* Restore audfs & fractdel after coldboot, so we can calibrate with correct fs setting.
+ * in case something else was given in cnt file, profile below will apply this. */
+ TFA_SET_BF(tfa, AUDFS, audfs);
+ TFA_SET_BF(tfa, FRACTDEL, fractdel);
+#ifdef __KERNEL__
+ if ((tfa->dynamicTDMmode == 3) && tfa_dev_set_tdm_bitwidth(tfa,tfa->bitwidth))
+ return Tfa98xx_Error_Fail;
+#endif//
+ }
+ else {
+ pr_debug("\nWarning: No init keyword found in the cnt file. Init is skipped! \n");
+ }
+
+ /* I2S settings to define the audio input properties
+ * these must be set before the subsys is up */
+ // this will run the list until a non-register item is encountered
+ err = tfaContWriteRegsDev(tfa); // write device register settings
+ PRINT_ASSERT(err);
+ // also write register the settings from the default profile
+ // NOTE we may still have ACS=1 so we can switch sample rate here
+ err = tfaContWriteRegsProf(tfa, profile);
+ PRINT_ASSERT(err);
+
+ /* Factory trimming for the Boost converter */
+ tfa98xx_factory_trimmer(tfa);
+#ifdef __KERNEL__
+#if 0
+ /* Control for PWM phase shift */
+ if (tfa->bitwidth == 24 && tfa->rate == 16)/*TFA9875-240*/
+ tfa98xx_set_phase_shift(tfa);
+#endif
+#endif
+ /* Go to the initCF state */
+ tfa_dev_set_state(tfa, TFA_STATE_INIT_CF, strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, profile), ".cal") != NULL);
+
+ err = tfa_show_current_state(tfa);
+
+ return err;
+}
+
+/*
+ * run the startup/init sequence and set ACS bit
+ */
+enum Tfa98xx_Error tfaRunColdStartup(struct tfa_device *tfa, int profile)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ err = tfaRunStartup(tfa, profile);
+ PRINT_ASSERT(err);
+ if (err)
+ return err;
+
+ if (!tfa->is_probus_device) {
+ /* force cold boot */
+ err = tfaRunColdboot(tfa, 1); // set ACS
+ PRINT_ASSERT(err);
+ if (err)
+ return err;
+ }
+
+ /* start */
+ err = tfaRunStartDSP(tfa);
+ PRINT_ASSERT(err);
+
+ return err;
+}
+
+/*
+ *
+ */
+enum Tfa98xx_Error tfaRunMute(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int status;
+ int tries = 0;
+
+ /* signal the TFA98XX to mute */
+ if (tfa->tfa_family == 1) {
+ err = tfa98xx_set_mute(tfa, Tfa98xx_Mute_Amplifier);
+
+ if (err == Tfa98xx_Error_Ok) {
+ /* now wait for the amplifier to turn off */
+ do {
+ status = TFA_GET_BF(tfa, SWS);
+ if (status != 0)
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ else
+ break;
+ tries++;
+ } while (tries < AMPOFFWAIT_TRIES);
+
+
+ if (tfa->verbose)
+ pr_debug("-------------------- muted --------------------\n");
+
+ /*The amplifier is always switching*/
+ if (tries == AMPOFFWAIT_TRIES)
+ return Tfa98xx_Error_Other;
+ }
+ }
+
+ return err;
+}
+/*
+ *
+ */
+enum Tfa98xx_Error tfaRunUnmute(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ /* signal the TFA98XX to mute */
+ err = tfa98xx_set_mute(tfa, Tfa98xx_Mute_Off);
+
+ if (tfa->verbose)
+ pr_debug("-------------------unmuted ------------------\n");
+
+ return err;
+}
+
+static void individual_calibration_results(struct tfa_device *tfa)
+{
+ int value_P, value_S;
+
+ /* Read the calibration result in xmem (529=primary channel) (530=secondary channel) */
+ tfa_mem_read(tfa, 529, 1, &value_P);
+ tfa_mem_read(tfa, 530, 1, &value_S);
+
+ if (value_P != 1 && value_S != 1)
+ pr_debug("Calibration failed on both channels! \n");
+ else if (value_P != 1) {
+ pr_debug("Calibration failed on Primary (Left) channel! \n");
+ TFA_SET_BF_VOLATILE(tfa, SSLEFTE, 0); /* Disable the sound for the left speaker */
+ }
+ else if (value_S != 1) {
+ pr_debug("Calibration failed on Secondary (Right) channel! \n");
+ TFA_SET_BF_VOLATILE(tfa, SSRIGHTE, 0); /* Disable the sound for the right speaker */
+ }
+
+ TFA_SET_BF_VOLATILE(tfa, AMPINSEL, 0); /* Set amplifier input to TDM */
+ TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+}
+
+/*
+ * wait for calibrateDone
+ */
+enum Tfa98xx_Error tfaRunWaitCalibration(struct tfa_device *tfa, int *calibrateDone)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int tries = 0, mtp_busy = 1, tries_mtp_busy = 0;
+
+ *calibrateDone = 0;
+
+ /* in case of calibrate once wait for MTPEX */
+ if (TFA_GET_BF(tfa, MTPOTC)) {
+ // Check if MTP_busy is clear!
+ while (tries_mtp_busy < MTPBWAIT_TRIES)
+ {
+ mtp_busy = tfa_dev_get_mtpb(tfa);
+ if (mtp_busy == 1)
+ msleep_interruptible(10); /* wait 10ms to avoid busload */
+ else
+ break;
+ tries_mtp_busy++;
+ }
+
+ if (tries_mtp_busy < MTPBWAIT_TRIES) {
+ /* Because of the msleep TFA98XX_API_WAITRESULT_NTRIES is way to long!
+ * Setting this to 25 will take it atleast 25*50ms = 1.25 sec
+ */
+ while ((*calibrateDone == 0) && (tries < MTPEX_WAIT_NTRIES)) {
+ *calibrateDone = TFA_GET_BF(tfa, MTPEX);
+ if (*calibrateDone == 1)
+ break;
+ msleep_interruptible(50); /* wait 50ms to avoid busload */
+ tries++;
+ }
+
+ if (tries >= MTPEX_WAIT_NTRIES) {
+ tries = TFA98XX_API_WAITRESULT_NTRIES;
+ }
+ }
+ else {
+ pr_err("MTP bussy after %d tries\n", MTPBWAIT_TRIES);
+ }
+ }
+
+ /* poll xmem for calibrate always
+ * calibrateDone = 0 means "calibrating",
+ * calibrateDone = -1 (or 0xFFFFFF) means "fails"
+ * calibrateDone = 1 means calibration done
+ */
+ while ((*calibrateDone != 1) && (tries < TFA98XX_API_WAITRESULT_NTRIES)) {
+ err = tfa_mem_read(tfa, TFA_FW_XMEM_CALIBRATION_DONE, 1, calibrateDone);
+ if (*calibrateDone == -1)
+ break;
+ tries++;
+ }
+
+ if (*calibrateDone != 1) {
+ pr_err("Calibration failed! \n");
+ err = Tfa98xx_Error_Bad_Parameter;
+ }
+ else if (tries == TFA98XX_API_WAITRESULT_NTRIES) {
+ pr_debug("Calibration has timedout! \n");
+ err = Tfa98xx_Error_StateTimedOut;
+ }
+ else if (tries_mtp_busy == 1000) {
+ pr_err("Calibrate Failed: MTP_busy stays high! \n");
+ err = Tfa98xx_Error_StateTimedOut;
+ }
+
+ /* Give reason why calibration failed! */
+ if (err != Tfa98xx_Error_Ok) {
+ if ((tfa->tfa_family == 2) && (TFA_GET_BF(tfa, REFCKSEL) == 1)) {
+ pr_err("Unable to calibrate the device with the internal clock! \n");
+ }
+ }
+
+ /* Check which speaker calibration failed. Only for 88C */
+ if ((err != Tfa98xx_Error_Ok) && ((tfa->rev & 0x0FFF) == 0xc88)) {
+ individual_calibration_results(tfa);
+ }
+
+ return err;
+}
+
+/*
+ * tfa_dev_start will only do the basics: Going from powerdown to operating or a profile switch.
+ * for calibrating or akoustic shock handling use the tfa98xxCalibration function.
+ */
+enum tfa_error tfa_dev_start(struct tfa_device *tfa, int next_profile, int vstep)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int active_profile = -1;
+
+ /* Get currentprofile */
+ active_profile = tfa_dev_get_swprof(tfa);
+ if (active_profile == 0xff)
+ active_profile = -1;
+
+ /* TfaRun_SpeakerBoost implies un-mute */
+ pr_debug("Active_profile:%s, next_profile:%s\n",
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, active_profile),
+ tfaContProfileName(tfa->cnt, tfa->dev_idx, next_profile));
+
+ err = tfa_show_current_state(tfa);
+
+ if (tfa->tfa_family == 1) { /* TODO move this to ini file */
+ /* Enable I2S output on TFA1 devices without TDM */
+ err = tfa98xx_aec_output(tfa, 1);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+ }
+
+ if (tfa->bus != 0) { /* non i2c */
+#ifndef __KERNEL__
+ tfadsp_fw_start(tfa, next_profile, vstep);
+#endif /* __KERNEL__ */
+ }
+ else {
+ /* Check if we need coldstart or ACS is set */
+ err = tfaRunSpeakerBoost(tfa, 0, next_profile);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, next_profile), ".standby") != NULL) {
+ pr_info("Skip powering on device, in standby profile!\n");
+ } else {
+ /* Make sure internal oscillator is running for DSP devices (non-dsp and max1 this is no-op) */
+ tfa98xx_set_osc_powerdown(tfa, 0);
+
+ /* Go to the Operating state */
+ tfa_dev_set_state(tfa, TFA_STATE_OPERATING | TFA_STATE_MUTE, 0);
+ }
+ }
+ active_profile = tfa_dev_get_swprof(tfa);
+
+ /* Profile switching */
+ if ((next_profile != active_profile && active_profile >= 0)) {
+ err = tfaContWriteProfile(tfa, next_profile, vstep);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+ }
+
+ /* If the profile contains the .standby suffix go to powerdown
+ * else we should be in operating state
+ */
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, next_profile), ".standby") != NULL) {
+ tfa_dev_set_swprof(tfa, (unsigned short)next_profile);
+ tfa_dev_set_swvstep(tfa, (unsigned short)vstep);
+
+ pr_info("Power down device, by force, in standby profile!\n");
+ err = tfa_dev_stop(tfa);
+ goto error_exit;
+ }
+
+ err = tfa_show_current_state(tfa);
+
+ if ((TFA_GET_BF(tfa, CFE) != 0) && (vstep != tfa->vstep) && (vstep != -1)) {
+ err = tfaContWriteFilesVstep(tfa, next_profile, vstep);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+ }
+
+ /* Always search and apply filters after a startup */
+ err = tfa_set_filters(tfa, next_profile);
+ if (err != Tfa98xx_Error_Ok)
+ goto error_exit;
+
+ tfa_dev_set_swprof(tfa, (unsigned short)next_profile);
+ tfa_dev_set_swvstep(tfa, (unsigned short)vstep);
+
+ /* PLMA5539: Gives information about current setting of powerswitch */
+ if (tfa->verbose) {
+ if (!tfa98xx_powerswitch_is_enabled(tfa))
+ pr_info("Device start without powerswitch enabled!\n");
+ }
+
+error_exit:
+ tfa_show_current_state(tfa);
+
+ return err;
+}
+
+enum tfa_error tfa_dev_stop(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+
+ /* mute */
+ tfaRunMute(tfa);
+
+ /* Make sure internal oscillator is not running for DSP devices (non-dsp and max1 this is no-op) */
+ tfa98xx_set_osc_powerdown(tfa, 1);
+
+ /* powerdown CF */
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err != Tfa98xx_Error_Ok)
+ return err;
+
+ /* disable I2S output on TFA1 devices without TDM */
+ err = tfa98xx_aec_output(tfa, 0);
+
+ return err;
+}
+
+/*
+ * int registers and coldboot dsp
+ */
+int tfa_reset(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ int state = -1;
+ int retry_cnt = 0;
+
+ /* Check device state. Print warning if reset is done from other state than powerdown (when verbose) */
+ state = tfa_dev_get_state(tfa);
+ if (tfa->verbose) {
+ if (((tfa->tfa_family == 1) && state != TFA_STATE_RESET) ||
+ ((tfa->tfa_family == 2) && state != TFA_STATE_POWERDOWN)) {
+ pr_info("WARNING: Device reset should be performed in POWERDOWN state\n");
+ }
+ }
+
+ /* Split TFA1 behavior from TFA2*/
+ if (tfa->tfa_family == 1) {
+ err = TFA_SET_BF(tfa, I2CR, 1);
+ if (err)
+ return err;
+ err = tfa98xx_powerdown(tfa, 0);
+ if (err)
+ return err;
+ err = tfa_cf_powerup(tfa);
+ if (err)
+ return err;
+ err = tfaRunColdboot(tfa, 1);
+ if (err)
+ return err;
+ err = TFA_SET_BF(tfa, I2CR, 1);
+ }
+ else {
+ /* Probus devices needs extra protection to ensure proper reset
+ behavior, this step is valid only in state other than powerdown */
+ if (tfa->is_probus_device && state != TFA_STATE_POWERDOWN) {
+ err = TFA_SET_BF_VOLATILE(tfa, AMPE, 0);
+ if (err)
+ return err;
+ err = tfa98xx_powerdown(tfa, 1);
+ if (err)
+ return err;
+ }
+
+ err = TFA_SET_BF_VOLATILE(tfa, I2CR, 1);
+ if (err)
+ return err;
+
+ /* Restore MANSCONF to POR state */
+ err = TFA_SET_BF_VOLATILE(tfa, MANSCONF, 0);
+ if (err)
+ return err;
+
+ /* Probus devices HW are already reseted here,
+ Last step is to send init message to softDSP */
+ if (tfa->is_probus_device) {
+ if (tfa->ext_dsp > 0) {
+ err = tfa98xx_init_dsp(tfa);
+ /* ext_dsp status from warm to cold after reset */
+ if (tfa->ext_dsp == 2) {
+ tfa->ext_dsp = 1;
+ }
+ }
+ }
+ else {
+ /* Restore MANCOLD to POR state */
+ TFA_SET_BF_VOLATILE(tfa, MANCOLD, 1);
+
+ /* Coolflux has to be powered on to ensure proper ACS
+ bit state */
+
+ /* Powerup CF to access CF io */
+ err = tfa98xx_powerdown(tfa, 0);
+ if (err)
+ return err;
+
+ /* For clock */
+ err = tfa_cf_powerup(tfa);
+ if (err)
+ return err;
+
+ /* Force cold boot */
+ err = tfaRunColdboot(tfa, 1); /* Set ACS */
+ if (err)
+ return err;
+
+ /* Set PWDN = 1, this will transfer device into powerdown state */
+ err = TFA_SET_BF_VOLATILE(tfa, PWDN, 1);
+ if (err)
+ return err;
+
+ /* 88 needs SBSL on top of PWDN bit to start transition,
+ for 92 and 94 this doesn't matter */
+ err = TFA_SET_BF_VOLATILE(tfa, SBSL, 1);
+ if (err)
+ return err;
+
+ /* Powerdown state should be reached within 1ms */
+ for (retry_cnt = 0; retry_cnt < TFA98XX_WAITRESULT_NTRIES; retry_cnt++) {
+ if (tfa_is_94_N2_device(tfa))
+ state = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ state = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ state = TFA_GET_BF(tfa, MANSTATE);
+ if (state < 0) {
+ return err;
+ }
+
+ /* Check for MANSTATE=Powerdown (0) */
+ if (state == 0)
+ break;
+ msleep_interruptible(2);
+ }
+
+ /* Reset all I2C registers to default values,
+ now device state is consistent, same as after powerup */
+ err = TFA_SET_BF(tfa, I2CR, 1);
+ }
+ }
+
+ return err;
+}
+
+/*
+ * Write all the bytes specified by num_bytes and data
+ */
+enum Tfa98xx_Error
+ tfa98xx_write_data(struct tfa_device *tfa,
+ unsigned char subaddress, int num_bytes,
+ const unsigned char data[])
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ /* subaddress followed by data */
+ const int bytes2write = num_bytes + 1;
+ unsigned char *write_data;
+
+ if (num_bytes > TFA2_MAX_PARAM_SIZE)
+ return Tfa98xx_Error_Bad_Parameter;
+
+ write_data = (unsigned char *)kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (write_data == NULL)
+ return Tfa98xx_Error_Fail;
+
+ write_data[0] = subaddress;
+ memcpy(&write_data[1], data, num_bytes);
+
+ error = tfa98xx_write_raw(tfa, bytes2write, write_data);
+
+ kmem_cache_free(tfa->cachep, write_data);
+ return error;
+}
+
+/*
+ * fill the calibration value as milli ohms in the struct
+ *
+ * assume that the device has been calibrated
+ */
+enum Tfa98xx_Error tfa_dsp_get_calibration_impedance(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned char bytes[3 * 2] = { 0 };
+ int nr_bytes, i, data[2], calibrateDone, spkr_count = 0, cal_idx = 0;
+ unsigned int scaled_data;
+ int tries = 0;
+
+ error = tfa_supported_speakers(tfa, &spkr_count);
+
+ if (tfa_dev_mtp_get(tfa, TFA_MTP_OTC)) {
+ pr_debug("Getting calibration values from MTP\n");
+
+ if ((tfa->rev & 0xFF) == 0x88) {
+ for (i = 0; i < spkr_count; i++) {
+ if (i == 0)
+ tfa->mohm[i] = tfa_dev_mtp_get(tfa, TFA_MTP_RE25_PRIM);
+ else
+ tfa->mohm[i] = tfa_dev_mtp_get(tfa, TFA_MTP_RE25_SEC);
+ }
+ }
+ else {
+ tfa->mohm[0] = tfa_dev_mtp_get(tfa, TFA_MTP_RE25);
+ }
+ }
+ else {
+ pr_debug("Getting calibration values from Speakerboost\n");
+
+ /* Make sure the calibrateDone bit is set before getting the values from speakerboost!
+ * This does not work for 72 (because the dsp cannot set this bit)
+ */
+ if (!tfa->is_probus_device) {
+ /* poll xmem for calibrate always
+ * calibrateDone = 0 means "calibrating",
+ * calibrateDone = -1 (or 0xFFFFFF) means "fails"
+ * calibrateDone = 1 means calibration done
+ */
+ calibrateDone = 0;
+ while ((calibrateDone != 1) && (tries < TFA98XX_API_WAITRESULT_NTRIES)) {
+ error = tfa_mem_read(tfa, TFA_FW_XMEM_CALIBRATION_DONE, 1, &calibrateDone);
+ if (calibrateDone == 1)
+ break;
+ tries++;
+ }
+
+ if (calibrateDone != 1) {
+ pr_err("Calibration failed! \n");
+ error = Tfa98xx_Error_Bad_Parameter;
+ }
+ else if (tries == TFA98XX_API_WAITRESULT_NTRIES) {
+ pr_debug("Calibration has timedout! \n");
+ error = Tfa98xx_Error_StateTimedOut;
+ }
+ }
+ /* SoftDSP interface differs from hw-dsp interfaces */
+ if (tfa->is_probus_device && tfa->cnt->ndev > 1) {
+ spkr_count = tfa->cnt->ndev;
+ }
+
+ nr_bytes = spkr_count * 3;
+ error = tfa_dsp_cmd_id_write_read(tfa, MODULE_SPEAKERBOOST, SB_PARAM_GET_RE25C, nr_bytes, bytes);
+ if (error == Tfa98xx_Error_Ok) {
+ tfa98xx_convert_bytes2data(nr_bytes, bytes, data);
+
+ for (i = 0; i < spkr_count; i++) {
+
+ /* for probus devices, calibration values coming from soft-dsp speakerboost,
+ are ordered in a different way. Re-align to standard representation. */
+ cal_idx = i;
+ if ((tfa->is_probus_device && tfa->dev_idx >= 1)) {
+ cal_idx = 0;
+ }
+
+ /* signed data has a limit of 30 Ohm */
+ scaled_data = data[i];
+
+ if (tfa->tfa_family == 2)
+ tfa->mohm[cal_idx] = (scaled_data * 1000) / TFA2_FW_ReZ_SCALE;
+ else
+ tfa->mohm[cal_idx] = (scaled_data * 1000) / TFA1_FW_ReZ_SCALE;
+ }
+ }
+ }
+
+ return error;
+}
+
+/* start count from 1, 0 is invalid */
+int tfa_dev_get_swprof(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.get_swprof)(tfa);
+}
+
+int tfa_dev_set_swprof(struct tfa_device *tfa, unsigned short new_value)
+{
+ return (tfa->dev_ops.set_swprof)(tfa, new_value + 1);
+}
+
+/* same value for all channels
+ * start count from 1, 0 is invalid */
+int tfa_dev_get_swvstep(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.get_swvstep)(tfa);
+}
+
+int tfa_dev_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ return (tfa->dev_ops.set_swvstep)(tfa, new_value + 1);
+}
+
+/*
+ function overload for MTPB
+ */
+int tfa_dev_get_mtpb(struct tfa_device *tfa)
+{
+ return (tfa->dev_ops.get_mtpb)(tfa);
+}
+
+int tfa_is_cold(struct tfa_device *tfa)
+{
+ int value;
+
+ /*
+ * check for cold boot status
+ */
+ if (tfa->is_probus_device) {
+ if (tfa->ext_dsp > 0) {
+ if (tfa->ext_dsp == 2)
+ value = 0; // warm
+ else /* no dsp or cold */
+ value = 1; // cold
+ }
+ else {
+ value = (TFA_GET_BF(tfa, MANSCONF) == 0);
+ }
+ }
+ else {
+ value = TFA_GET_BF(tfa, ACS);
+ }
+
+ return value;
+}
+
+int tfa_needs_reset(struct tfa_device *tfa)
+{
+ int value;
+
+ /* checks if the DSP commands SetAlgoParams and SetMBDrc
+ * need a DSP reset (now: at coldstart or during calibration)
+ */
+ if (tfa_is_cold(tfa) == 1 || tfa->needs_reset == 1)
+ value = 1;
+ else
+ value = 0;
+
+ return value;
+}
+
+int tfa_cf_enabled(struct tfa_device *tfa)
+{
+ int value;
+
+ /* For 72 there is no CF */
+ if (tfa->is_probus_device) {
+ value = (tfa->ext_dsp != 0);
+ }
+ else {
+ value = TFA_GET_BF(tfa, CFE);
+ }
+
+ return value;
+}
+
+#define NR_COEFFS 6
+#define NR_BIQUADS 28
+#define BQ_SIZE (3 * NR_COEFFS)
+#define DSP_MSG_OVERHEAD 27
+
+#pragma pack (push, 1)
+struct dsp_msg_all_coeff {
+ uint8_t select_eq[3];
+ uint8_t biquad[NR_BIQUADS][NR_COEFFS][3];
+};
+#pragma pack (pop)
+
+/* number of biquads for each equalizer */
+static const int eq_biquads[] = {
+ 10, 10, 2, 2, 2, 2
+};
+
+#define NR_EQ (int)(sizeof(eq_biquads) / sizeof(int))
+
+enum Tfa98xx_Error tfa_dsp_partial_coefficients(struct tfa_device *tfa, uint8_t *prev, uint8_t *next)
+{
+ uint8_t bq, eq;
+ int eq_offset;
+ int new_cost, old_cost;
+ uint32_t eq_biquad_mask[NR_EQ];
+ enum Tfa98xx_Error err = Tfa98xx_Error_Ok;
+ struct dsp_msg_all_coeff *data1 = (struct dsp_msg_all_coeff *)prev;
+ struct dsp_msg_all_coeff *data2 = (struct dsp_msg_all_coeff *)next;
+
+ old_cost = DSP_MSG_OVERHEAD + 3 + sizeof(struct dsp_msg_all_coeff);
+ new_cost = 0;
+
+ eq_offset = 0;
+ for (eq = 0; eq < NR_EQ; eq++) {
+ uint8_t *eq1 = &data1->biquad[eq_offset][0][0];
+ uint8_t *eq2 = &data2->biquad[eq_offset][0][0];
+
+ eq_biquad_mask[eq] = 0;
+
+ if (memcmp(eq1, eq2, BQ_SIZE*eq_biquads[eq]) != 0) {
+ int nr_bq = 0;
+ int bq_sz, eq_sz;
+
+ for (bq = 0; bq < eq_biquads[eq]; bq++) {
+ uint8_t *bq1 = &eq1[bq*BQ_SIZE];
+ uint8_t *bq2 = &eq2[bq*BQ_SIZE];
+
+ if (memcmp(bq1, bq2, BQ_SIZE) != 0) {
+ eq_biquad_mask[eq] |= (1 << bq);
+ nr_bq++;
+ }
+ }
+
+ bq_sz = (2 * 3 + BQ_SIZE) * nr_bq;
+ eq_sz = 2 * 3 + BQ_SIZE * eq_biquads[eq];
+
+ /* dsp message i2c transaction overhead */
+ bq_sz += DSP_MSG_OVERHEAD * nr_bq;
+ eq_sz += DSP_MSG_OVERHEAD;
+
+ if (bq_sz >= eq_sz) {
+ eq_biquad_mask[eq] = 0xffffffff;
+
+ new_cost += eq_sz;
+
+ }
+ else {
+ new_cost += bq_sz;
+ }
+ }
+ pr_debug("eq_biquad_mask[%d] = 0x%.8x\n", eq, eq_biquad_mask[eq]);
+
+ eq_offset += eq_biquads[eq];
+ }
+
+ pr_debug("cost for writing all coefficients = %d\n", old_cost);
+ pr_debug("cost for writing changed coefficients = %d\n", new_cost);
+
+ if (new_cost >= old_cost) {
+ const int buffer_sz = 3 + sizeof(struct dsp_msg_all_coeff);
+ uint8_t *buffer;
+
+ buffer = kmalloc(buffer_sz, GFP_KERNEL);
+ if (buffer == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* cmd id */
+ buffer[0] = 0x00;
+ buffer[1] = 0x82;
+ buffer[2] = 0x00;
+
+ /* parameters */
+ memcpy(&buffer[3], data2, sizeof(struct dsp_msg_all_coeff));
+
+ err = tfa_dsp_msg(tfa, buffer_sz, (const char *)buffer);
+
+ kfree(buffer);
+ if (err)
+ return err;
+
+ }
+ else {
+ eq_offset = 0;
+ for (eq = 0; eq < NR_EQ; eq++) {
+ uint8_t *eq2 = &data2->biquad[eq_offset][0][0];
+
+ if (eq_biquad_mask[eq] == 0xffffffff) {
+ const int msg_sz = 6 + BQ_SIZE * eq_biquads[eq];
+ uint8_t *msg;
+
+ msg = kmalloc(msg_sz, GFP_KERNEL);
+ if (msg == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* cmd id */
+ msg[0] = 0x00;
+ msg[1] = 0x82;
+ msg[2] = 0x00;
+
+ /* select eq and bq */
+ msg[3] = 0x00;
+ msg[4] = eq + 1;
+ msg[5] = 0x00; /* all biquads */
+
+ /* biquad parameters */
+ memcpy(&msg[6], eq2, BQ_SIZE * eq_biquads[eq]);
+
+ err = tfa_dsp_msg(tfa, msg_sz, (const char *)msg);
+
+ kfree(msg);
+ if (err)
+ return err;
+
+ }
+ else if (eq_biquad_mask[eq] != 0) {
+ for (bq = 0; bq < eq_biquads[eq]; bq++) {
+
+ if (eq_biquad_mask[eq] & (1 << bq)) {
+ uint8_t *bq2 = &eq2[bq*BQ_SIZE];
+ const int msg_sz = 6 + BQ_SIZE;
+ uint8_t *msg;
+
+ msg = kmem_cache_alloc(tfa->cachep, GFP_KERNEL);
+ if (msg == NULL)
+ return Tfa98xx_Error_Fail;
+
+ /* cmd id */
+ msg[0] = 0x00;
+ msg[1] = 0x82;
+ msg[2] = 0x00;
+
+ /* select eq and bq*/
+ msg[3] = 0x00;
+ msg[4] = eq + 1;
+ msg[5] = bq + 1;
+
+ /* biquad parameters */
+ memcpy(&msg[6], bq2, BQ_SIZE);
+
+ err = tfa_dsp_msg(tfa, msg_sz, (const char *)msg);
+
+ kmem_cache_free(tfa->cachep, msg);
+ if (err)
+ return err;
+ }
+ }
+ }
+ eq_offset += eq_biquads[eq];
+ }
+ }
+
+ return err;
+}
+
+/* fill context info */
+int tfa_dev_probe(int slave, struct tfa_device *tfa)
+{
+ uint16_t rev;
+
+ tfa->slave_address = (unsigned char)slave;
+
+ /* read revid via low level hal, register 3 */
+ if (tfa98xx_read_register16(tfa, 3, &rev) != Tfa98xx_Error_Ok) {
+ PRINT("\nError: Unable to read revid from slave:0x%02x \n", slave);
+ return -1;
+ }
+
+ tfa->rev = rev;
+ tfa->dev_idx = -1;
+ tfa->state = TFA_STATE_UNKNOWN;
+ tfa->p_regInfo = NULL;
+
+ tfa_set_query_info(tfa);
+
+ tfa->in_use = 1;
+
+ return 0;
+}
+
+enum tfa_error tfa_dev_set_state(struct tfa_device *tfa, enum tfa_state state, int is_calibration)
+{
+ enum tfa_error err = tfa_error_ok;
+ int loop = 50, ready = 0;
+ int count;
+
+ /* Base states */
+ /* Do not change the order of setting bits as this is important! */
+ switch (state & 0x0f) {
+ case TFA_STATE_POWERDOWN: /* PLL in powerdown, Algo up */
+ break;
+ case TFA_STATE_INIT_HW: /* load I2C/PLL hardware setting (~wait2srcsettings) */
+ break;
+ case TFA_STATE_INIT_CF: /* coolflux HW access possible (~initcf) */
+ /* Start with SBSL=0 to stay in initCF state */
+ if (!tfa->is_probus_device)
+ TFA_SET_BF(tfa, SBSL, 0);
+
+ /* We want to leave Wait4SrcSettings state for max2 */
+ if (tfa->tfa_family == 2)
+ TFA_SET_BF(tfa, MANSCONF, 1);
+
+ /* And finally set PWDN to 0 to leave powerdown state */
+ TFA_SET_BF(tfa, PWDN, 0);
+
+ /* Make sure the DSP is running! */
+ do {
+ err = tfa98xx_dsp_system_stable(tfa, &ready);
+ if (err != tfa_error_ok)
+ return err;
+ if (ready)
+ break;
+ } while (loop--);
+ if (((!tfa->is_probus_device) && (is_calibration)) || ((tfa->rev & 0xff) == 0x13))
+ {
+ /* Enable FAIM when clock is stable, to avoid MTP corruption */
+ err = tfa98xx_faim_protect(tfa, 1);
+ if (tfa->verbose) {
+ pr_debug("FAIM enabled (err:%d).\n", err);
+ }
+ }
+ break;
+ case TFA_STATE_INIT_FW: /* DSP framework active (~patch loaded) */
+ break;
+ case TFA_STATE_OPERATING: /* Amp and Algo running */
+ /* Depending on our previous state we need to set 3 bits */
+ TFA_SET_BF(tfa, PWDN, 0); /* Coming from state 0 */
+ TFA_SET_BF(tfa, MANSCONF, 1); /* Coming from state 1 */
+ if (!tfa->is_probus_device)
+ TFA_SET_BF(tfa, SBSL, 1); /* Coming from state 6 */
+ else
+ TFA_SET_BF(tfa, AMPE, 1); /* No SBSL for probus device, we set AMPE to 1 */
+
+ /*
+ * Disable MTP clock to protect memory.
+ * However in case of calibration wait for DSP! (This should be case only during calibration).
+ */
+ if (TFA_GET_BF(tfa, MTPOTC) == 1 && tfa->tfa_family == 2) {
+ count = MTPEX_WAIT_NTRIES * 4; /* Calibration takes a lot of time */
+ while ((TFA_GET_BF(tfa, MTPEX) != 1) && count) {
+ msleep_interruptible(10);
+ count--;
+ }
+ }
+ if (((!tfa->is_probus_device) && (is_calibration)) || ((tfa->rev & 0xff) == 0x13))
+ {
+ err = tfa98xx_faim_protect(tfa, 0);
+ if (tfa->verbose) {
+ pr_debug("FAIM disabled (err:%d).\n", err);
+ }
+ }
+ /* Synchonize I/V delay on 96/97 at cold start */
+ if (tfa->sync_iv_delay) {
+ if (tfa->verbose)
+ pr_debug("syncing I/V delay for %x\n",
+ (tfa->rev & 0xff));
+
+ /* wait for ACS to be cleared */
+ count = 10;
+ while ((TFA_GET_BF(tfa, ACS) == 1) &&
+ (count-- > 0)) {
+ msleep_interruptible(1);
+ }
+
+ tfa98xx_dsp_reset(tfa, 1);
+ tfa98xx_dsp_reset(tfa, 0);
+ tfa->sync_iv_delay = 0;
+ }
+ break;
+ case TFA_STATE_FAULT: /* An alarm or error occurred */
+ break;
+ case TFA_STATE_RESET: /* I2C reset and ACS set */
+ tfa98xx_init(tfa);
+ break;
+ default:
+ if (state & 0x0f)
+ return tfa_error_bad_param;
+ }
+
+ /* state modifiers */
+
+ if (state & TFA_STATE_MUTE)
+ tfa98xx_set_mute(tfa, Tfa98xx_Mute_Amplifier);
+
+ if (state & TFA_STATE_UNMUTE)
+ tfa98xx_set_mute(tfa, Tfa98xx_Mute_Off);
+
+ tfa->state = state;
+
+ return tfa_error_ok;
+}
+
+enum tfa_state tfa_dev_get_state(struct tfa_device *tfa)
+{
+ int cold = 0;
+ int manstate;
+
+ /* different per family type */
+ if (tfa->tfa_family == 1) {
+ cold = TFA_GET_BF(tfa, ACS);
+ if (cold && TFA_GET_BF(tfa, PWDN))
+ tfa->state = TFA_STATE_RESET;
+ else if (!cold && TFA_GET_BF(tfa, SWS))
+ tfa->state = TFA_STATE_OPERATING;
+ }
+ else /* family 2 */ {
+ if (tfa_is_94_N2_device(tfa))
+ manstate = tfa_get_bf(tfa, TFA9894N2_BF_MANSTATE);
+ else if ((tfa->rev & 0xff) == 0x75)
+ manstate = tfa_get_bf(tfa, TFA9875_BF_MANSTATE);
+ else
+ manstate = TFA_GET_BF(tfa, MANSTATE);
+ switch (manstate) {
+ case 0:
+ tfa->state = TFA_STATE_POWERDOWN;
+ break;
+ case 8: /* if dsp reset if off assume framework is running */
+ tfa->state = TFA_GET_BF(tfa, RST) ? TFA_STATE_INIT_CF : TFA_STATE_INIT_FW;
+ break;
+ case 9:
+ tfa->state = TFA_STATE_OPERATING;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return tfa->state;
+}
+
+int tfa_dev_mtp_get(struct tfa_device *tfa, enum tfa_mtp item)
+{
+ int value = 0;
+
+ switch (item) {
+ case TFA_MTP_OTC:
+ value = TFA_GET_BF(tfa, MTPOTC);
+ break;
+ case TFA_MTP_EX:
+ value = TFA_GET_BF(tfa, MTPEX);
+ break;
+ case TFA_MTP_RE25:
+ case TFA_MTP_RE25_PRIM:
+ if (tfa->tfa_family == 2) {
+ if ((tfa->rev & 0xFF) == 0x88)
+ value = TFA_GET_BF(tfa, R25CL);
+ else if ((tfa->rev & 0xFF) == 0x13)
+ value = tfa_get_bf(tfa, TFA9912_BF_R25C);
+ else
+ value = TFA_GET_BF(tfa, R25C);
+ }
+ else {
+ tfa_reg_read(tfa, 0x83, (unsigned short*)&value);
+ }
+ break;
+ case TFA_MTP_RE25_SEC:
+ if ((tfa->rev & 0xFF) == 0x88) {
+ value = TFA_GET_BF(tfa, R25CR);
+ }
+ else {
+ pr_debug("Error: Current device has no secondary Re25 channel \n");
+ }
+ break;
+ case TFA_MTP_LOCK:
+ break;
+ }
+
+ return value;
+}
+
+enum tfa_error tfa_dev_mtp_set(struct tfa_device *tfa, enum tfa_mtp item, int value)
+{
+ enum tfa_error err = tfa_error_ok;
+
+ switch (item) {
+ case TFA_MTP_OTC:
+ err = tfa98xx_set_mtp(tfa, (uint16_t)value, TFA98XX_KEY2_PROTECTED_MTP0_MTPOTC_MSK);
+ break;
+ case TFA_MTP_EX:
+ err = tfa98xx_set_mtp(tfa, (uint16_t)value, TFA98XX_KEY2_PROTECTED_MTP0_MTPEX_MSK);
+ break;
+ case TFA_MTP_RE25:
+ case TFA_MTP_RE25_PRIM:
+ if (tfa->tfa_family == 2) {
+ tfa98xx_key2(tfa, 0); /* unlock */
+ if ((tfa->rev & 0xFF) == 0x88)
+ TFA_SET_BF(tfa, R25CL, (uint16_t)value);
+ else
+ {
+ if (tfa->is_probus_device == 1 && TFA_GET_BF(tfa, MTPOTC) == 1)
+ tfa2_manual_mtp_cpy(tfa, 0xF4, value, 2);
+ TFA_SET_BF(tfa, R25C, (uint16_t)value);
+ }
+ tfa98xx_key2(tfa, 1); /* lock */
+ }
+ break;
+ case TFA_MTP_RE25_SEC:
+ if ((tfa->rev & 0xFF) == 0x88) {
+ TFA_SET_BF(tfa, R25CR, (uint16_t)value);
+ }
+ else {
+ pr_debug("Error: Current device has no secondary Re25 channel \n");
+ err = tfa_error_bad_param;
+ }
+ break;
+ case TFA_MTP_LOCK:
+ break;
+ }
+
+ return err;
+}
+
+int tfa_get_pga_gain(struct tfa_device *tfa)
+{
+ return TFA_GET_BF(tfa, SAAMGAIN);
+}
+
+int tfa_set_pga_gain(struct tfa_device *tfa, uint16_t value)
+{
+
+ return TFA_SET_BF(tfa, SAAMGAIN, value);
+}
+
+int tfa_get_noclk(struct tfa_device *tfa)
+{
+ return TFA_GET_BF(tfa, NOCLK);
+}
+
+
+enum Tfa98xx_Error tfa_status(struct tfa_device *tfa)
+{
+ int value;
+ uint16_t val;
+
+ if (tfa->dev_ops.tfa_status != NULL)
+ return(tfa->dev_ops.tfa_status(tfa));
+ /*
+ * check IC status bits: cold start
+ * and DSP watch dog bit to re init
+ */
+ value = TFA_READ_REG(tfa, VDDS); /* STATUSREG */
+ if (value < 0)
+ return -value;
+ val = (uint16_t)value;
+
+ /* pr_debug("SYS_STATUS0: 0x%04x\n", val); */
+ if (TFA_GET_BF_VALUE(tfa, ACS, val) ||
+ TFA_GET_BF_VALUE(tfa, WDS, val)) {
+
+ if (TFA_GET_BF_VALUE(tfa, ACS, val))
+ pr_err("ERROR: ACS\n");
+ if (TFA_GET_BF_VALUE(tfa, WDS, val))
+ pr_err("ERROR: WDS\n");
+
+ return Tfa98xx_Error_DSP_not_running;
+ }
+
+ if (TFA_GET_BF_VALUE(tfa, SPKS, val))
+ pr_err("ERROR: SPKS\n");
+ if (!TFA_GET_BF_VALUE(tfa, SWS, val))
+ pr_err("ERROR: SWS\n");
+
+ /* Check secondary errors */
+ if (!TFA_GET_BF_VALUE(tfa, CLKS, val) ||
+ !TFA_GET_BF_VALUE(tfa, UVDS, val) ||
+ !TFA_GET_BF_VALUE(tfa, OVDS, val) ||
+ !TFA_GET_BF_VALUE(tfa, OTDS, val) ||
+ !TFA_GET_BF_VALUE(tfa, PLLS, val) ||
+ (!(tfa->daimap & Tfa98xx_DAI_TDM) &&
+ !TFA_GET_BF_VALUE(tfa, VDDS, val)))
+ pr_err("Misc errors detected: STATUS_FLAG0 = 0x%x\n", val);
+
+ if ((tfa->daimap & Tfa98xx_DAI_TDM) && (tfa->tfa_family == 2)) {
+ value = TFA_READ_REG(tfa, TDMERR); /* STATUS_FLAGS1 */
+ if (value < 0)
+ return -value;
+ val = (uint16_t)value;
+ if (TFA_GET_BF_VALUE(tfa, TDMERR, val) ||
+ TFA_GET_BF_VALUE(tfa, TDMLUTER, val))
+ pr_err("TDM related errors: STATUS_FLAG1 = 0x%x\n", val);
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+#ifdef __KERNEL__
+void tfa_dev_get_tdm_add(struct tfa_device* tfa, uint16_t* tdme, uint16_t* tnbck, uint16_t* tslln, uint16_t* tsize)
+{
+ unsigned short revid = tfa->rev;
+ switch (revid & 0xff) {
+ case 0x72:
+ *tdme = TFA9872_BF_TDME;
+ *tnbck = TFA9872_BF_TDMNBCK;
+ *tslln = TFA9872_BF_TDMSLLN;
+ *tsize = TFA9872_BF_TDMSSIZE;
+ break;
+ case 0x73:
+ *tdme = TFA9873_BF_TDME;
+ *tnbck = TFA9873_BF_TDMNBCK;
+ *tslln = TFA9873_BF_TDMSLLN;
+ *tsize = TFA9873_BF_TDMSSIZE;
+ break;
+ case 0x74:
+ *tdme = TFA9874_BF_TDME;
+ *tnbck = TFA9874_BF_TDMNBCK;
+ *tslln = TFA9874_BF_TDMSLLN;
+ *tsize = TFA9874_BF_TDMSSIZE;
+ break;
+ case 0x78:
+ *tdme = TFA9878_BF_TDME;
+ *tnbck = TFA9878_BF_TDMNBCK;
+ *tslln = TFA9878_BF_TDMSLLN;
+ *tsize = TFA9878_BF_TDMSSIZE;
+ break;
+ case 0x13:
+ *tdme = TFA9912_BF_TDME;
+ *tnbck = TFA9912_BF_TDMNBCK;
+ *tslln = TFA9912_BF_TDMSLLN;
+ *tsize = TFA9912_BF_TDMSSIZE;
+ break;
+ case 0x94:
+ *tdme = TFA9894_BF_TDME;
+ *tnbck = TFA9894_BF_TDMNBCK;
+ *tslln = TFA9894_BF_TDMSLLN;
+ *tsize = TFA9894_BF_TDMSSIZE;
+ break;
+
+ default:
+ pr_err("unsuported device rev:%x\n", revid);
+ break;
+ }
+}
+int tfa_dev_set_tdm_bitwidth(struct tfa_device* tfa, int width)/*SACAS-26*/
+{
+ uint8_t nbck, slotlen, samplesize;
+
+ switch (width) {
+ case 16: /* 16-bit sample in 16-bit slot */
+ nbck = 0;
+ slotlen = 15;
+ samplesize = 15;
+ break;
+ case 24: /* 24-bit sample in 32-bit slot */
+ nbck = 2;
+ slotlen = 31;
+ samplesize = (tfa->tfa_family == 1) ? 23 : (tfa->is_probus_device == 1) ? 31 : 23;
+ break;
+ case 32: /* 32-bit sample in 32-bit slot */
+ nbck = 2;
+ slotlen = 31;
+ samplesize = (tfa->tfa_family == 1) ? 23 : (tfa->is_probus_device == 1) ? 31 : 23;
+ break;
+ default:
+ pr_err("unsupported tdm bitwidth:%d\n", width);
+ return -EINVAL;
+ break;
+ }
+
+ if (tfa->tfa_family == 2)
+ {
+ uint16_t tdme, tdmnbck, tdmslln,tdmssize;
+ tfa_dev_get_tdm_add(tfa,&tdme,&tdmnbck,&tdmslln,&tdmssize); /*SACAS-26*/
+ /* stop tdm */
+ tfa_set_bf(tfa, tdme, 0);
+ tfa_set_bf(tfa, tdmnbck, nbck);
+ tfa_set_bf(tfa, tdmslln, slotlen);
+ tfa_set_bf(tfa, tdmssize, samplesize);
+ /* enable tdm */
+ tfa_set_bf(tfa, tdme, 1);
+ }
+ else if (tfa->daimap == Tfa98xx_DAI_TDM)
+ {
+ /* stop tdm */
+ tfa_set_bf(tfa, TFA1_BF_TDMEN, 0);
+ tfa_set_bf(tfa, TFA1_BF_NBCK, nbck);
+ tfa_set_bf(tfa, TFA1_BF_TDMSLLN, slotlen);
+ tfa_set_bf(tfa, TFA1_BF_TDMSAMSZ, samplesize);
+ /* enable tdm */
+ tfa_set_bf(tfa, TFA1_BF_TDMEN, 1);
+
+ }
+ return 0;
+
+}
+#define NR_OF_BATS 10
+void tfa_adapt_noisemode(struct tfa_device *tfa)
+{
+ int i, avbatt;
+ long total_bats = 0;
+ if ((tfa_get_bf(tfa, 0x5900) == 0) || (tfa_get_bf(tfa, TFA9873_BF_LP1) == 1))
+ {
+ if (tfa->verbose)
+ pr_debug("Adapting low noise mode is not needed, condition not fulfilled!\n");
+ return;
+ }
+ if (tfa->verbose)
+ pr_debug("Adapting low noise mode\n");
+
+ for (i = 0; i < NR_OF_BATS; i++) {
+ int bat = TFA_GET_BF(tfa, BATS);
+ if (tfa->verbose)
+ pr_debug("bats[%d]=%d\n", i, bat);
+ total_bats += bat;
+ msleep_interruptible(5);
+ }
+
+ avbatt = (int)(total_bats / NR_OF_BATS);
+
+ if (avbatt <= MIN_BATT_LEVEL && !tfa_get_bf(tfa, TFA9873_BF_LNMODE))//640 corresponds to 3.4 volt, MCH_TO_TEST
+ {
+ tfa_set_bf(tfa, TFA9873_BF_LNMODE, 1);
+ pr_debug("\navbatt= %d--Applying high noise gain\n", avbatt);
+ }
+ else if (avbatt > MAX_BATT_LEVEL && tfa_get_bf(tfa, TFA9873_BF_LNMODE))
+ {
+ tfa_set_bf(tfa, TFA9873_BF_LNMODE, 0);
+ pr_debug("\navbatt= %d--Applying automatic noise gain\n", avbatt);
+ }
+
+
+}
+int tfa_plop_noise_interrupt(struct tfa_device *tfa, int profile, int vstep)
+{
+ enum Tfa98xx_Error err;
+ int no_clk = 0;
+
+ /* Remove sticky bit by reading it once */
+ TFA_GET_BF(tfa, NOCLK);
+
+ /* No clock detected */
+ if (tfa_irq_get(tfa, tfa9912_irq_stnoclk)) {
+ no_clk = TFA_GET_BF(tfa, NOCLK);
+
+ /* Detect for clock is lost! (clock is not stable) */
+ if (no_clk == 1) {
+ /* Clock is lost. Set I2CR to remove POP noise */
+ pr_info("No clock detected. Resetting the I2CR to avoid pop on 72! \n");
+ err = tfa_dev_start(tfa, profile, vstep);
+ if (err != Tfa98xx_Error_Ok) {
+ pr_err("Error loading i2c registers (tfa_dev_start), err=%d\n", err);
+ }
+ else {
+ pr_info("Setting i2c registers after I2CR succesfull\n");
+ tfa_dev_set_state(tfa, TFA_STATE_UNMUTE, 0);
+ }
+
+ /* Remove sticky bit by reading it once */
+ tfa_get_noclk(tfa);
+
+ /* This is only for SAAM on the 72.
+ Since the NOCLK interrupt is only enabled for 72 this is the place
+ However: Not tested yet! But also does not harm normal flow!
+ */
+ if (strstr(tfaContProfileName(tfa->cnt, tfa->dev_idx, profile), ".saam")) {
+ pr_info("Powering down from a SAAM profile, workaround PLMA4766 used! \n");
+ TFA_SET_BF(tfa, PWDN, 1);
+ TFA_SET_BF(tfa, AMPE, 0);
+ TFA_SET_BF(tfa, SAMMODE, 0);
+ }
+ }
+
+ /* If clk is stable set polarity to check for LOW (no clock)*/
+ tfa_irq_set_pol(tfa, tfa9912_irq_stnoclk, (no_clk == 0));
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa, tfa9912_irq_stnoclk);
+ }
+
+ /* return no_clk to know we called tfa_dev_start */
+ return no_clk;
+}
+
+void tfa_lp_mode_interrupt(struct tfa_device *tfa)
+{
+ const int irq_stclp0 = 36; /* FIXME: this 72 interrupt does not excist for 9912 */
+ int lp0, lp1;
+
+ if (tfa_irq_get(tfa, irq_stclp0)) {
+ lp0 = TFA_GET_BF(tfa, LP0);
+ if (lp0 > 0) {
+ pr_info("lowpower mode 0 detected\n");
+ }
+ else {
+ pr_info("lowpower mode 0 not detected\n");
+ }
+
+ tfa_irq_set_pol(tfa, irq_stclp0, (lp0 == 0));
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa, irq_stclp0);
+ }
+
+ if (tfa_irq_get(tfa, tfa9912_irq_stclpr)) {
+ lp1 = TFA_GET_BF(tfa, LP1);
+ if (lp1 > 0) {
+ pr_info("lowpower mode 1 detected\n");
+ }
+ else {
+ pr_info("lowpower mode 1 not detected\n");
+ }
+
+ tfa_irq_set_pol(tfa, tfa9912_irq_stclpr, (lp1 == 0));
+
+ /* clear interrupt */
+ tfa_irq_clear(tfa, tfa9912_irq_stclpr);
+ }
+}
+#endif//__KERNEL__
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_dsp_fw.h b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp_fw.h
new file mode 100644
index 00000000000..1621bcb8be6
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_dsp_fw.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef TFA98XX_INTERNALS_H
+#define TFA98XX_INTERNALS_H
+
+#include "config.h"
+
+#include "tfa_service.h" //TODO cleanup for enum Tfa98xx_Status_ID
+/*
+ * tfadsp_fw_api.c
+ */
+/**
+ * Return a text version of the firmware status ID code
+ * @param status the given status ID code
+ * @return the firmware status ID string
+ */
+const char *tfadsp_fw_status_string(enum Tfa98xx_Status_ID status);
+int tfadsp_fw_start(struct tfa_device *tfa, int prof_idx, int vstep_idx);
+int tfadsp_fw_get_api_version(struct tfa_device *tfa, uint8_t *buffer);
+#define FW_MAXTAG 150
+int tfadsp_fw_get_tag(struct tfa_device *tfa, uint8_t *buffer);
+int tfadsp_fw_get_status_change(struct tfa_device *tfa, uint8_t *buffer);
+int tfadsp_fw_set_re25(struct tfa_device *tfa, int prim, int sec );
+int tfadsp_fw_get_re25(struct tfa_device *tfa, uint8_t *buffer);
+
+/*
+ * the order matches the ACK bits order in TFA98XX_CF_STATUS
+ */
+enum tfa_fw_event { /* not all available on each device */
+ tfa_fw_i2c_cmd_ack,
+ tfa_fw_reset_start,
+ tfa_fw_short_on_mips,
+ tfa_fw_soft_mute_ready,
+ tfa_fw_volume_ready,
+ tfa_fw_error_damage,
+ tfa_fw_calibrate_done,
+ tfa_fw_max
+};
+
+/* the following type mappings are compiler specific */
+#define subaddress_t unsigned char
+
+/* module Ids */
+#define MODULE_FRAMEWORK 0
+#define MODULE_SPEAKERBOOST 1
+#define MODULE_BIQUADFILTERBANK 2
+#define MODULE_TAPTRIGGER 5
+#define MODULE_SETRE 9
+
+/* RPC commands */
+/* SET */
+#define FW_PAR_ID_SET_MEMORY 0x03
+#define FW_PAR_ID_SET_SENSES_DELAY 0x04
+#define FW_PAR_ID_SETSENSESCAL 0x05
+#define FW_PAR_ID_SET_INPUT_SELECTOR 0x06
+#define FW_PAR_ID_SET_OUTPUT_SELECTOR 0x08
+#define FW_PAR_ID_SET_PROGRAM_CONFIG 0x09
+#define FW_PAR_ID_SET_GAINS 0x0A
+#define FW_PAR_ID_SET_MEMTRACK 0x0B
+#define FW_PAR_ID_SET_FWKUSECASE 0x11
+#define TFA1_FW_PAR_ID_SET_CURRENT_DELAY 0x03
+#define TFA1_FW_PAR_ID_SET_CURFRAC_DELAY 0x06
+/* GET */
+#define FW_PAR_ID_GET_MEMORY 0x83
+#define FW_PAR_ID_GLOBAL_GET_INFO 0x84
+#define FW_PAR_ID_GET_FEATURE_INFO 0x85
+#define FW_PAR_ID_GET_MEMTRACK 0x8B
+#define FW_PAR_ID_GET_TAG 0xFF
+#define FW_PAR_ID_GET_API_VERSION 0xFE
+#define FW_PAR_ID_GET_STATUS_CHANGE 0x8D
+
+/* Load a full model into SpeakerBoost. */
+/* SET */
+#define SB_PARAM_SET_ALGO_PARAMS 0x00
+#define SB_PARAM_SET_LAGW 0x01
+#define SB_PARAM_SET_ALGO_PARAMS_WITHOUT_RESET 0x02
+#define SB_PARAM_SET_RE25C 0x05
+#define SB_PARAM_SET_LSMODEL 0x06
+#define SB_PARAM_SET_MBDRC 0x07
+#define SB_PARAM_SET_MBDRC_WITHOUT_RESET 0x08
+#define SB_PARAM_SET_EXCURSION_FILTERS 0x0A
+#define SB_PARAM_SET_DRC 0x0F
+/* GET */
+#define SB_PARAM_GET_ALGO_PARAMS 0x80
+#define SB_PARAM_GET_LAGW 0x81
+#define SB_PARAM_GET_RE25C 0x85
+#define SB_PARAM_GET_LSMODEL 0x86
+#define SB_PARAM_GET_MBDRC 0x87
+#define SB_PARAM_GET_MBDRC_DYNAMICS 0x89
+#define SB_PARAM_GET_EXCURSION_FILTERS 0x8A
+#define SB_PARAM_GET_TAG 0xFF
+
+#define SB_PARAM_SET_EQ 0x0A /* 2 Equaliser Filters. */
+#define SB_PARAM_SET_PRESET 0x0D /* Load a preset */
+#define SB_PARAM_SET_CONFIG 0x0E /* Load a config */
+#define SB_PARAM_SET_AGCINS 0x10
+#define SB_PARAM_SET_CURRENT_DELAY 0x03
+#define SB_PARAM_GET_STATE 0xC0
+#define SB_PARAM_GET_XMODEL 0xC1 /* Gets current Excursion Model. */
+#define SB_PARAM_GET_XMODEL_COEFFS 0x8C /* Get coefficients for XModel */
+#define SB_PARAM_GET_EXCURSION_FILTERS 0x8A /* Get excursion filters */
+#define SB_PARAM_SET_EXCURSION_FILTERS 0x0A /* Set excursion filters */
+
+/* SET: TAPTRIGGER */
+#define TAP_PARAM_SET_ALGO_PARAMS 0x01
+#define TAP_PARAM_SET_DECIMATION_PARAMS 0x02
+
+/* GET: TAPTRIGGER*/
+#define TAP_PARAM_GET_ALGO_PARAMS 0x81
+#define TAP_PARAM_GET_TAP_RESULTS 0x84
+
+/* sets the speaker calibration impedance (@25 degrees celsius) */
+#define SB_PARAM_SET_RE0 0x89
+
+#define BFB_PAR_ID_SET_COEFS 0x00
+#define BFB_PAR_ID_GET_COEFS 0x80
+#define BFB_PAR_ID_GET_CONFIG 0x81
+
+/* for compatibility */
+#define FW_PARAM_GET_STATE FW_PAR_ID_GLOBAL_GET_INFO
+#define FW_PARAM_GET_FEATURE_BITS FW_PAR_ID_GET_FEATURE_BITS
+
+/* RPC Status results */
+#define STATUS_OK 0
+#define STATUS_INVALID_MODULE_ID 2
+#define STATUS_INVALID_PARAM_ID 3
+#define STATUS_INVALID_INFO_ID 4
+
+/* the maximum message length in the communication with the DSP */
+#define TFA2_MAX_PARAM_SIZE (507*3) /* TFA2 */
+#define TFA1_MAX_PARAM_SIZE (145*3) /* TFA1 */
+
+#define ROUND_DOWN(a,n) (((a)/(n))*(n))
+
+/* feature bits */
+#define FEATURE1_TCOEF 0x100 /* bit8 set means tCoefA expected */
+#define FEATURE1_DRC 0x200 /* bit9 NOT set means DRC expected */
+
+/* DSP firmware xmem defines */
+#define TFA1_FW_XMEM_CALIBRATION_DONE 231
+#define TFA2_FW_XMEM_CALIBRATION_DONE 516
+#define TFA1_FW_XMEM_COUNT_BOOT 0xa1
+#define TFA2_FW_XMEM_COUNT_BOOT 512
+#define TFA2_FW_XMEM_CMD_COUNT 520
+
+/* note that the following defs rely on the handle variable */
+#define TFA_FW_XMEM_CALIBRATION_DONE TFA_FAM_FW(tfa,XMEM_CALIBRATION_DONE)
+#define TFA_FW_XMEM_COUNT_BOOT TFA_FAM_FW(tfa,XMEM_COUNT_BOOT)
+#define TFA_FW_XMEM_CMD_COUNT TFA_FAM_FW(tfa,XMEM_CMD_COUNT)
+
+#define TFA2_FW_ReZ_SCALE 65536
+#define TFA1_FW_ReZ_SCALE 16384
+
+#endif /* TFA98XX_INTERNALS_H */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_ext.h b/sound/soc/codecs/tfa98xx-downstream/tfa_ext.h
new file mode 100644
index 00000000000..72c65594a1c
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_ext.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/*
+ * tfa_ext.h
+ *
+ * Created on: Jun 8, 2016
+ * Author: wim
+ */
+
+#ifndef TFA_SRC_TFA_EXT_H_
+#define TFA_SRC_TFA_EXT_H_
+
+#include "tfa_device.h"
+
+/*
+ * events
+ */
+/** Maximum value for enumerator */
+#define LVM_MAXENUM (0xffff)
+/**
+This enum type specifies the different events that may trigger a callback.
+*/
+enum tfadsp_event_en
+{
+ TFADSP_CMD_ACK = 1, /**< Command handling is completed */
+ TFADSP_SOFT_MUTE_READY = 8, /**< Muting completed */
+ TFADSP_VOLUME_READY = 16, /**< Volume change completed */
+ TFADSP_DAMAGED_SPEAKER = 32, /**< Damaged speaker was detected */
+ TFADSP_CALIBRATE_DONE = 64, /**< Calibration is completed */
+ TFADSP_SPARSESIG_DETECTED = 128, /**< Sparse signal detected */
+ TFADSP_CMD_READY = 256, /**< Ready to receive commands */
+ TFADSP_EXT_PWRUP = 0x8000,/**< DSP API has started, powered up */
+ TFADSP_EXT_PWRDOWN = 0x8001,/**< DSP API stopped, power down */
+ TFADSP_EVENT_DUMMY = LVM_MAXENUM
+} ;
+
+typedef int (*tfa_event_handler_t)(struct tfa_device *tfa, enum tfadsp_event_en tfadsp_event);
+typedef int (*dsp_send_message_t)(struct tfa_device *tfa, int length, const char *buf);
+typedef int (*dsp_read_message_t)(struct tfa_device *tfa, int length, char *buf);
+typedef int (*dsp_write_reg_t)(struct tfa_device *tfa, unsigned char subaddress, unsigned short value);
+
+int tfa_ext_register(dsp_write_reg_t tfa_write_reg, dsp_send_message_t tfa_send_message, dsp_read_message_t tfa_read_message, tfa_event_handler_t *tfa_event_handler);
+
+#endif /* TFA_SRC_TFA_EXT_H_ */
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_init.c b/sound/soc/codecs/tfa98xx-downstream/tfa_init.c
new file mode 100644
index 00000000000..6dc4e9c0ce9
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_init.c
@@ -0,0 +1,2148 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#include "dbgprint.h"
+#include "tfa_service.h"
+#include "tfa_internal.h"
+#include "tfa_container.h"
+#include "tfa98xx_tfafieldnames.h"
+
+ /* The CurrentSense4 registers are not in the datasheet */
+#define TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF (1<<2)
+#define TFA98XX_CURRENTSENSE4 0x49
+
+/***********************************************************************************/
+/* GLOBAL (Defaults) */
+/***********************************************************************************/
+static enum Tfa98xx_Error no_overload_function_available(struct tfa_device *tfa, int not_used)
+{
+ (void)tfa;
+ (void)not_used;
+
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error no_overload_function_available2(struct tfa_device *tfa)
+{
+ (void)tfa;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short status;
+ int value;
+
+ /* check the contents of the STATUS register */
+ value = TFA_READ_REG(tfa, AREFS);
+ if (value < 0) {
+ error = -value;
+ *ready = 0;
+ _ASSERT(error); /* an error here can be fatal */
+ return error;
+ }
+ status = (unsigned short)value;
+
+ /* check AREFS and CLKS: not ready if either is clear */
+ *ready = !((TFA_GET_BF_VALUE(tfa, AREFS, status) == 0)
+ || (TFA_GET_BF_VALUE(tfa, CLKS, status) == 0));
+
+ return error;
+}
+
+/* tfa98xx_toggle_mtp_clock
+ * Allows to stop clock for MTP/FAim needed for PLMA5505 */
+static enum Tfa98xx_Error tfa_faim_protect(struct tfa_device *tfa, int state)
+{
+ (void)tfa;
+ (void)state;
+
+ return Tfa98xx_Error_Ok;
+}
+
+/** Set internal oscillator into power down mode.
+ *
+ * This function is a worker for tfa98xx_set_osc_powerdown().
+ *
+ * @param[in] tfa device description structure
+ * @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+ *
+ * @return Tfa98xx_Error_Ok when successfull, error otherwise.
+ */
+static enum Tfa98xx_Error tfa_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ /* This function has no effect in general case, only for tfa9912 */
+ (void)tfa;
+ (void)state;
+
+ return Tfa98xx_Error_Ok;
+}
+static enum Tfa98xx_Error tfa_update_lpm(struct tfa_device *tfa, int state)
+{
+ /* This function has no effect in general case, only for tfa9912 */
+ (void)tfa;
+ (void)state;
+
+ return Tfa98xx_Error_Ok;
+}
+static enum Tfa98xx_Error tfa_dsp_reset(struct tfa_device *tfa, int state)
+{
+ /* generic function */
+ TFA_SET_BF_VOLATILE(tfa, RST, (uint16_t)state);
+
+ return Tfa98xx_Error_Ok;
+}
+
+int tfa_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int mtpk, active_value = tfa->profile;
+
+ /* Also set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* for TFA1 devices */
+ /* it's in MTP shadow, so unlock if not done already */
+ mtpk = TFA_GET_BF(tfa, MTPK); /* get current key */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, 0x5a);
+ TFA_SET_BF_VOLATILE(tfa, SWPROFIL, new_value); /* set current profile */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, (uint16_t)mtpk); /* restore key */
+
+ return active_value;
+}
+
+static int tfa_get_swprofile(struct tfa_device *tfa)
+{
+ return /*TFA_GET_BF(tfa, SWPROFIL) - 1*/tfa->profile;
+}
+
+static int tfa_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ int mtpk, active_value = tfa->vstep;
+
+ /* Also set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* for TFA1 devices */
+ /* it's in MTP shadow, so unlock if not done already */
+ mtpk = TFA_GET_BF(tfa, MTPK); /* get current key */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, 0x5a);
+ TFA_SET_BF_VOLATILE(tfa, SWVSTEP, new_value); /* set current vstep */
+ TFA_SET_BF_VOLATILE(tfa, MTPK, (uint16_t)mtpk); /* restore key */
+
+ return active_value;
+}
+
+static int tfa_get_swvstep(struct tfa_device *tfa)
+{
+ int value = 0;
+ /* Set the new value in the hw register */
+ value = TFA_GET_BF(tfa, SWVSTEP);
+
+ /* Also set the new value in the struct */
+ tfa->vstep = value - 1;
+
+ return value - 1; /* invalid if 0 */
+}
+
+static int tfa_get_mtpb(struct tfa_device *tfa) {
+
+ int value = 0;
+
+ /* Set the new value in the hw register */
+ value = TFA_GET_BF(tfa, MTPB);
+
+ return value;
+}
+
+static enum Tfa98xx_Error
+tfa_set_mute_nodsp(struct tfa_device *tfa, int mute)
+{
+ (void)tfa;
+ (void)mute;
+
+ return Tfa98xx_Error_Ok;
+}
+
+static int tfa_set_bitfield(struct tfa_device* tfa, uint16_t bitfield, uint16_t value)
+{
+ return tfa_set_bf(tfa, (uint16_t)bitfield, value);
+}
+
+void tfa_set_ops_defaults(struct tfa_device_ops *ops)
+{
+ /* defaults */
+ ops->tfa_reg_read = tfa98xx_read_register16;
+ ops->tfa_reg_write = tfa98xx_write_register16;
+ ops->tfa_mem_read = tfa98xx_dsp_read_mem;
+ ops->tfa_mem_write = tfa98xx_dsp_write_mem_word;
+ ops->tfa_dsp_msg = tfa_dsp_msg_rpc;
+ ops->tfa_dsp_msg_read = tfa_dsp_msg_read_rpc;
+ ops->dsp_write_tables = no_overload_function_available;
+ ops->dsp_reset = tfa_dsp_reset;
+ ops->dsp_system_stable = tfa_dsp_system_stable;
+ ops->auto_copy_mtp_to_iic = no_overload_function_available2;
+ ops->factory_trimmer = no_overload_function_available2;
+ ops->phase_shift = no_overload_function_available2;
+ ops->set_swprof = tfa_set_swprofile;
+ ops->get_swprof = tfa_get_swprofile;
+ ops->set_swvstep = tfa_set_swvstep;
+ ops->get_swvstep = tfa_get_swvstep;
+ ops->get_mtpb = tfa_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+ ops->faim_protect = tfa_faim_protect;
+ ops->set_osc_powerdown = tfa_set_osc_powerdown;
+ ops->update_lpm = tfa_update_lpm;
+ ops->tfa_set_bitfield = tfa_set_bitfield;
+}
+
+/***********************************************************************************/
+/* no TFA
+ * external DSP SB instance */
+ /***********************************************************************************/
+static short tfanone_swvstep, swprof; //TODO emulate in hal plugin
+static enum Tfa98xx_Error tfanone_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ (void)tfa; /* suppress warning */
+ *ready = 1; /* assume always ready */
+
+ return Tfa98xx_Error_Ok;
+}
+
+static int tfanone_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ swprof = new_value;
+
+ return active_value;
+}
+
+static int tfanone_get_swprofile(struct tfa_device *tfa)
+{
+ (void)tfa; /* suppress warning */
+ return swprof;
+}
+
+static int tfanone_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfanone_swvstep = new_value;
+
+ return new_value;
+}
+
+static int tfanone_get_swvstep(struct tfa_device *tfa)
+{
+ (void)tfa; /* suppress warning */
+ return tfanone_swvstep;
+}
+
+void tfanone_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->dsp_system_stable = tfanone_dsp_system_stable;
+ ops->set_swprof = tfanone_set_swprofile;
+ ops->get_swprof = tfanone_get_swprofile;
+ ops->set_swvstep = tfanone_set_swvstep;
+ ops->get_swvstep = tfanone_get_swvstep;
+
+}
+
+/***********************************************************************************/
+/* TFA9912 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9912_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Fail;
+
+ if (tfa) {
+ if (status == 0 || status == 1) {
+ ret = -(tfa_set_bf(tfa, TFA9912_BF_SSFAIME, (uint16_t)status));
+ }
+ }
+
+ return ret;
+}
+
+static enum Tfa98xx_Error tfa9912_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock keys to write settings */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+
+ /* The optimal settings */
+ if (tfa->rev == 0x1a13) {
+
+ /* ----- generated code start ----- */
+ /* ----- version 1.43 ----- */
+ tfa_reg_write(tfa, 0x00, 0x0255); //POR=0x0245
+ tfa_reg_write(tfa, 0x01, 0x838a); //POR=0x83ca
+ tfa_reg_write(tfa, 0x02, 0x2dc8); //POR=0x2828
+ tfa_reg_write(tfa, 0x05, 0x762a); //POR=0x766a
+ tfa_reg_write(tfa, 0x22, 0x543c); //POR=0x545c
+ tfa_reg_write(tfa, 0x26, 0x0100); //POR=0x0010
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x0080
+ tfa_reg_write(tfa, 0x52, 0x551c); //POR=0x1afc
+ tfa_reg_write(tfa, 0x53, 0x003e); //POR=0x001e
+ tfa_reg_write(tfa, 0x61, 0x000c); //POR=0x0018
+ tfa_reg_write(tfa, 0x63, 0x0a96); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0a82); //POR=0x0a8b
+ tfa_reg_write(tfa, 0x66, 0x0701); //POR=0x0700
+ tfa_reg_write(tfa, 0x6c, 0x00d5); //POR=0x02d5
+ tfa_reg_write(tfa, 0x70, 0x26f8); //POR=0x06e0
+ tfa_reg_write(tfa, 0x71, 0x3074); //POR=0x2074
+ tfa_reg_write(tfa, 0x75, 0x4484); //POR=0x4585
+ tfa_reg_write(tfa, 0x76, 0x72ea); //POR=0x54a2
+ tfa_reg_write(tfa, 0x83, 0x0716); //POR=0x0617
+ tfa_reg_write(tfa, 0x89, 0x0013); //POR=0x0014
+ tfa_reg_write(tfa, 0xb0, 0x4c08); //POR=0x4c00
+ tfa_reg_write(tfa, 0xc6, 0x004e); //POR=0x000e /* PLMA5539: Please make sure bit 6 is always on! */
+ /* ----- generated code end ----- */
+
+ /* PLMA5505: MTP key open makes vulanable for MTP corruption */
+ tfa9912_faim_protect(tfa, 0);
+ }
+ else {
+ pr_info("Warning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ }
+
+ return error;
+}
+
+static enum Tfa98xx_Error tfa9912_factory_trimmer(struct tfa_device *tfa)
+{
+ unsigned short currentValue, delta;
+ int result;
+
+ /* Factory trimming for the Boost converter */
+ /* check if there is a correction needed */
+ result = TFA_GET_BF(tfa, DCMCCAPI);
+ if (result) {
+ /* Get currentvalue of DCMCC and the Delta value */
+ currentValue = (unsigned short)TFA_GET_BF(tfa, DCMCC);
+ delta = (unsigned short)TFA_GET_BF(tfa, USERDEF);
+
+ /* check the sign bit (+/-) */
+ result = TFA_GET_BF(tfa, DCMCCSB);
+ if (result == 0) {
+ /* Do not exceed the maximum value of 15 */
+ if (currentValue + delta < 15) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue + delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue + delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 15);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 15 \n");
+ }
+ }
+ else if (result == 1) {
+ /* Do not exceed the minimum value of 0 */
+ if (currentValue - delta > 0) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue - delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue - delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 0);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 0 \n");
+ }
+ }
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error tfa9912_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1. Workaround for 72, 88 and 9912/9892(see PLMA5290) */
+ return tfa_reg_write(tfa, 0xA3, 0x20);
+}
+
+static int tfa9912_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9912_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9912_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9912_BF_SWPROFIL) - 1;
+}
+
+static int tfa9912_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9912_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9912_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9912_BF_SWVSTEP) - 1;
+}
+
+static enum Tfa98xx_Error
+tfa9912_set_mute(struct tfa_device *tfa, int mute)
+{
+ tfa_set_bf(tfa, TFA9912_BF_CFSM, (const uint16_t)mute);
+
+ return Tfa98xx_Error_Ok;
+}
+
+/* Maksimum value for combination of boost_voltage and vout calibration offset (see PLMA5322, PLMA5528). */
+#define TFA9912_VBOOST_MAX 57
+#define TFA9912_CALIBR_BOOST_MAX 63
+#define TFA9912_DCDCCNT6_REG (TFA9912_BF_DCVOF >> 8)
+#define TFA9912_CALIBR_REG 0xf1
+
+static uint16_t tfa9912_vboost_fixup(struct tfa_device *tfa, uint16_t dcdc_cnt6)
+{
+ unsigned short cal_offset;
+ unsigned short boost_v_1st, boost_v_2nd;
+ uint16_t new_dcdc_cnt6;
+
+ /* Get current calibr_vout_offset, this register is not supported by bitfields */
+ tfa_reg_read(tfa, TFA9912_CALIBR_REG, &cal_offset);
+ cal_offset = (cal_offset & 0x001f);
+ new_dcdc_cnt6 = dcdc_cnt6;
+
+ /* Get current boost_volatage values */
+ boost_v_1st = tfa_get_bf_value(TFA9912_BF_DCVOF, new_dcdc_cnt6);
+ boost_v_2nd = tfa_get_bf_value(TFA9912_BF_DCVOS, new_dcdc_cnt6);
+
+ /* Check boost voltages */
+ if (boost_v_1st > TFA9912_VBOOST_MAX)
+ boost_v_1st = TFA9912_VBOOST_MAX;
+
+ if (boost_v_2nd > TFA9912_VBOOST_MAX)
+ boost_v_2nd = TFA9912_VBOOST_MAX;
+
+ /* Recalculate values, max for the sum is TFA9912_CALIBR_BOOST_MAX */
+ if (boost_v_1st + cal_offset > TFA9912_CALIBR_BOOST_MAX)
+ boost_v_1st = TFA9912_CALIBR_BOOST_MAX - cal_offset;
+
+ if (boost_v_2nd + cal_offset > TFA9912_CALIBR_BOOST_MAX)
+ boost_v_2nd = TFA9912_CALIBR_BOOST_MAX - cal_offset;
+
+ tfa_set_bf_value(TFA9912_BF_DCVOF, boost_v_1st, &new_dcdc_cnt6);
+ tfa_set_bf_value(TFA9912_BF_DCVOS, boost_v_2nd, &new_dcdc_cnt6);
+
+ /* Change register value only when it's neccesary */
+ if (new_dcdc_cnt6 != dcdc_cnt6) {
+ if (tfa->verbose)
+ pr_debug("tfa9912: V boost fixup applied. Old 0x%04x, new 0x%04x\n",
+ dcdc_cnt6, new_dcdc_cnt6);
+ dcdc_cnt6 = new_dcdc_cnt6;
+ }
+
+ return dcdc_cnt6;
+}
+
+/* PLMA5322, PLMA5528 - Limit values of DCVOS and DCVOF to range specified in datasheet. */
+enum Tfa98xx_Error tfa9912_reg_write(struct tfa_device *tfa, unsigned char subaddress, unsigned short value)
+{
+ if (subaddress == TFA9912_DCDCCNT6_REG) {
+ /* Correct V boost (first and secondary) to ensure 12V is not exceeded. */
+ value = tfa9912_vboost_fixup(tfa, value);
+ }
+
+ return tfa98xx_write_register16(tfa, subaddress, value);
+}
+
+/** Set internal oscillator into power down mode for TFA9912.
+*
+* This function is a worker for tfa98xx_set_osc_powerdown().
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+static enum Tfa98xx_Error tfa9912_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ if (state == 1 || state == 0) {
+ return -tfa_set_bf(tfa, TFA9912_BF_MANAOOSC, (uint16_t)state);
+ }
+
+ return Tfa98xx_Error_Bad_Parameter;
+}
+/** update low power mode of the device.
+*
+* @param[in] tfa device description structure
+* @param[in] state State of the low power mode1 detector control
+* 0 - low power mode1 detector control enabled,
+* 1 - low power mode1 detector control disabled(low power mode is also disabled).
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+static enum Tfa98xx_Error tfa9912_update_lpm(struct tfa_device *tfa, int state)
+{
+ if (state == 1 || state == 0) {
+ return -tfa_set_bf(tfa, TFA9912_BF_LPM1DIS, (uint16_t)state);
+ }
+ return Tfa98xx_Error_Bad_Parameter;
+}
+
+void tfa9912_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9912_specific;
+ /* PLMA5322, PLMA5528 - Limits values of DCVOS and DCVOF. */
+ ops->tfa_reg_write = tfa9912_reg_write;
+ ops->factory_trimmer = tfa9912_factory_trimmer;
+ ops->auto_copy_mtp_to_iic = tfa9912_auto_copy_mtp_to_iic;
+ ops->set_swprof = tfa9912_set_swprofile;
+ ops->get_swprof = tfa9912_get_swprofile;
+ ops->set_swvstep = tfa9912_set_swvstep;
+ ops->get_swvstep = tfa9912_get_swvstep;
+ ops->set_mute = tfa9912_set_mute;
+ ops->faim_protect = tfa9912_faim_protect;
+ ops->set_osc_powerdown = tfa9912_set_osc_powerdown;
+ ops->update_lpm = tfa9912_update_lpm;
+}
+
+/***********************************************************************************/
+/* TFA9872 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9872_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ uint16_t MANAOOSC = 0x0140; /* version 17 */
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x1a72:
+ case 0x2a72:
+ /* ----- generated code start ----- */
+ /* ----- version 26 ----- */
+ tfa_reg_write(tfa, 0x00, 0x1801); //POR=0x0001
+ tfa_reg_write(tfa, 0x02, 0x2dc8); //POR=0x2028
+ tfa_reg_write(tfa, 0x20, 0x0890); //POR=0x2890
+ tfa_reg_write(tfa, 0x22, 0x043c); //POR=0x045c
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x0080
+ tfa_reg_write(tfa, 0x52, 0x1a1c); //POR=0x7ae8
+ tfa_reg_write(tfa, 0x58, 0x161c); //POR=0x101c
+ tfa_reg_write(tfa, 0x61, 0x0198); //POR=0x0000
+ tfa_reg_write(tfa, 0x65, 0x0a8b); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x70, 0x07f5); //POR=0x06e6
+ tfa_reg_write(tfa, 0x74, 0xcc84); //POR=0xd823
+ tfa_reg_write(tfa, 0x82, 0x01ed); //POR=0x000d
+ tfa_reg_write(tfa, 0x83, 0x0014); //POR=0x0013
+ tfa_reg_write(tfa, 0x84, 0x0021); //POR=0x0020
+ tfa_reg_write(tfa, 0x85, 0x0001); //POR=0x0003
+ /* ----- generated code end ----- */
+ break;
+ case 0x1b72:
+ case 0x2b72:
+ case 0x3b72:
+ /* ----- generated code start ----- */
+ /* ----- version 25.00 ----- */
+ tfa_reg_write(tfa, 0x02, 0x2dc8); //POR=0x2828
+ tfa_reg_write(tfa, 0x20, 0x0890); //POR=0x2890
+ tfa_reg_write(tfa, 0x22, 0x043c); //POR=0x045c
+ tfa_reg_write(tfa, 0x23, 0x0001); //POR=0x0003
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x0080
+ tfa_reg_write(tfa, 0x52, 0x5a1c); //POR=0x7a08
+ tfa_reg_write(tfa, 0x61, 0x0198); //POR=0x0000
+ tfa_reg_write(tfa, 0x63, 0x0a9a); //POR=0x0a93
+ tfa_reg_write(tfa, 0x65, 0x0a82); //POR=0x0a8d
+ tfa_reg_write(tfa, 0x6f, 0x01e3); //POR=0x02e4
+ tfa_reg_write(tfa, 0x70, 0x06fd); //POR=0x06e6
+ tfa_reg_write(tfa, 0x71, 0x307e); //POR=0x207e
+ tfa_reg_write(tfa, 0x74, 0xcc84); //POR=0xd913
+ tfa_reg_write(tfa, 0x75, 0x1132); //POR=0x118a
+ tfa_reg_write(tfa, 0x82, 0x01ed); //POR=0x000d
+ tfa_reg_write(tfa, 0x83, 0x001a); //POR=0x0013
+ /* ----- generated code end ----- */
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ /* Turn off the osc1m to save power: PLMA4928 */
+ error = tfa_set_bf(tfa, MANAOOSC, 1);
+
+ /* Bypass OVP by setting bit 3 from register 0xB0 (bypass_ovp=1): PLMA5258 */
+ error = tfa_reg_read(tfa, 0xB0, &value);
+ value |= 1 << 3;
+ error = tfa_reg_write(tfa, 0xB0, value);
+
+ return error;
+}
+
+static enum Tfa98xx_Error tfa9872_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1. Workaround for 72 and 88 (see PLMA5290) */
+ return tfa_reg_write(tfa, 0xA3, 0x20);
+}
+
+static int tfa9872_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9872_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9872_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9872_BF_SWPROFIL) - 1;
+}
+
+static int tfa9872_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9872_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9872_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9872_BF_SWVSTEP) - 1;
+}
+
+void tfa9872_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9872_specific;
+ ops->auto_copy_mtp_to_iic = tfa9872_auto_copy_mtp_to_iic;
+ ops->set_swprof = tfa9872_set_swprofile;
+ ops->get_swprof = tfa9872_get_swprofile;
+ ops->set_swvstep = tfa9872_set_swvstep;
+ ops->get_swvstep = tfa9872_get_swvstep;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+
+/***********************************************************************************/
+/* TFA9873 */
+/***********************************************************************************/
+
+static int tfa9873_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9873_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9873_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9873_BF_SWPROFIL) - 1;
+}
+
+static int tfa9873_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9873_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9873_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9873_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9873_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9873_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9873_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9873_BF_MTPB);
+ return value;
+}
+static enum Tfa98xx_Error tfa9873_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9873_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+static enum Tfa98xx_Error tfa9873_specific(struct tfa_device* tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a73:
+ /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 28 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x4c, 0x00e9); //POR=0x00ff
+ tfa_reg_write(tfa, 0x52, 0x17d0); //POR=0x57d0
+ tfa_reg_write(tfa, 0x56, 0x0011); //POR=0x0019
+ tfa_reg_write(tfa, 0x58, 0x0200); //POR=0x0210
+ tfa_reg_write(tfa, 0x59, 0x0001); //POR=0x0000
+ tfa_reg_write(tfa, 0x5f, 0x0180); //POR=0x0100
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0a82
+ tfa_reg_write(tfa, 0x63, 0x055a); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0542); //POR=0x0a82
+ tfa_reg_write(tfa, 0x6f, 0x00a3); //POR=0x0085
+ tfa_reg_write(tfa, 0x70, 0xa3fb); //POR=0x23fb
+ tfa_reg_write(tfa, 0x71, 0x007e); //POR=0x107e
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ tfa_reg_write(tfa, 0x84, 0x0211); //POR=0x0011
+ tfa_reg_write(tfa, 0x85, 0x0382); //POR=0x0380
+ tfa_reg_write(tfa, 0x8c, 0x0210); //POR=0x0010
+ tfa_reg_write(tfa, 0xd5, 0x0000); //POR=0x0100
+ /* ----- generated code end ----- */
+ break;
+ case 0x0b73:
+ /* ----- generated code start ----- */
+ /* ----- version 20 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0182
+ tfa_reg_write(tfa, 0x63, 0x005a); //POR=0x055a
+ tfa_reg_write(tfa, 0x6f, 0x0082); //POR=0x00a5
+ tfa_reg_write(tfa, 0x70, 0xa3eb); //POR=0x23fb
+ tfa_reg_write(tfa, 0x71, 0x107e); //POR=0x007e
+ tfa_reg_write(tfa, 0x73, 0x0187); //POR=0x0107
+ tfa_reg_write(tfa, 0x83, 0x071c); //POR=0x0799
+ tfa_reg_write(tfa, 0x85, 0x0380); //POR=0x0382
+ tfa_reg_write(tfa, 0xd5, 0x004d); //POR=0x014d
+ /* ----- generated code end ----- */
+ break;
+ case 0x1a73:
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+ error = tfa_set_bf_volatile(tfa, TFA9873_BF_FSSYNCEN, 0);
+ pr_info("info : disabled FS synchronisation! \n");
+ return error;
+}
+void tfa9873_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9873_specific;
+ ops->set_swprof = tfa9873_set_swprofile;
+ ops->get_swprof = tfa9873_get_swprofile;
+ ops->set_swvstep = tfa9873_set_swvstep;
+ ops->get_swvstep = tfa9873_get_swvstep;
+ ops->dsp_system_stable = tfa9873_dsp_system_stable;
+ ops->faim_protect = tfa9873_faim_protect;
+ ops->get_mtpb = tfa9873_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+
+/***********************************************************************************/
+/* TFA9874 */
+/***********************************************************************************/
+
+static enum Tfa98xx_Error tfa9874_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9874_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+
+static enum Tfa98xx_Error tfa9874_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a74: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* V25 */
+ tfa_reg_write(tfa, 0x02, 0x22a8); //POR=0x25c8
+ tfa_reg_write(tfa, 0x51, 0x0020); //POR=0x0000
+ tfa_reg_write(tfa, 0x52, 0x57dc); //POR=0x56dc
+ tfa_reg_write(tfa, 0x58, 0x16a4); //POR=0x1614
+ tfa_reg_write(tfa, 0x61, 0x0110); //POR=0x0198
+ tfa_reg_write(tfa, 0x66, 0x0701); //POR=0x0700
+ tfa_reg_write(tfa, 0x6f, 0x00a3); //POR=0x01a3
+ tfa_reg_write(tfa, 0x70, 0x07f8); //POR=0x06f8
+ tfa_reg_write(tfa, 0x73, 0x0007); //POR=0x0005
+ tfa_reg_write(tfa, 0x74, 0x5068); //POR=0xcc80
+ tfa_reg_write(tfa, 0x75, 0x0d28); //POR=0x1138
+ tfa_reg_write(tfa, 0x83, 0x0594); //POR=0x061a
+ tfa_reg_write(tfa, 0x84, 0x0001); //POR=0x0021
+ tfa_reg_write(tfa, 0x85, 0x0001); //POR=0x0003
+ tfa_reg_write(tfa, 0x88, 0x0000); //POR=0x0002
+ tfa_reg_write(tfa, 0xc4, 0x2001); //POR=0x0001
+ /* ----- generated code end ----- */
+ break;
+ case 0x0b74:
+ /* ----- generated code start ----- */
+ /* V1.6 */
+ tfa_reg_write(tfa, 0x02, 0x22a8); //POR=0x25c8
+ tfa_reg_write(tfa, 0x51, 0x0020); //POR=0x0000
+ tfa_reg_write(tfa, 0x52, 0x57dc); //POR=0x56dc
+ tfa_reg_write(tfa, 0x58, 0x16a4); //POR=0x1614
+ tfa_reg_write(tfa, 0x61, 0x0110); //POR=0x0198
+ tfa_reg_write(tfa, 0x66, 0x0701); //POR=0x0700
+ tfa_reg_write(tfa, 0x6f, 0x00a3); //POR=0x01a3
+ tfa_reg_write(tfa, 0x70, 0x07f8); //POR=0x06f8
+ tfa_reg_write(tfa, 0x73, 0x0047); //POR=0x0045
+ tfa_reg_write(tfa, 0x74, 0x5068); //POR=0xcc80
+ tfa_reg_write(tfa, 0x75, 0x0d28); //POR=0x1138
+ tfa_reg_write(tfa, 0x83, 0x0595); //POR=0x061a
+ tfa_reg_write(tfa, 0x84, 0x0001); //POR=0x0021
+ tfa_reg_write(tfa, 0x85, 0x0001); //POR=0x0003
+ tfa_reg_write(tfa, 0x88, 0x0000); //POR=0x0002
+ tfa_reg_write(tfa, 0xc4, 0x2001); //POR=0x0001
+ /* ----- generated code end ----- */
+ break;
+ case 0x0c74:
+ /* ----- generated code start ----- */
+ /* V1.16 */
+ tfa_reg_write(tfa, 0x02, 0x22c8); //POR=0x25c8
+ tfa_reg_write(tfa, 0x52, 0x57dc); //POR=0x56dc
+ tfa_reg_write(tfa, 0x53, 0x003e); //POR=0x001e
+ tfa_reg_write(tfa, 0x56, 0x0400); //POR=0x0600
+ tfa_reg_write(tfa, 0x61, 0x0110); //POR=0x0198
+ tfa_reg_write(tfa, 0x6f, 0x00a5); //POR=0x01a3
+ tfa_reg_write(tfa, 0x70, 0x07f8); //POR=0x06f8
+ tfa_reg_write(tfa, 0x73, 0x0047); //POR=0x0045
+ tfa_reg_write(tfa, 0x74, 0x5098); //POR=0xcc80
+ tfa_reg_write(tfa, 0x75, 0x8d28); //POR=0x1138
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x83, 0x0799); //POR=0x061a
+ tfa_reg_write(tfa, 0x84, 0x0081); //POR=0x0021
+ /* ----- generated code end ----- */
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ return error;
+}
+
+static int tfa9874_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9874_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9874_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9874_BF_SWPROFIL) - 1;
+}
+
+static int tfa9874_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9874_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9874_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9874_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9874_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9874_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9874_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9874_BF_MTPB);
+ return value;
+}
+
+void tfa9874_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9874_specific;
+ ops->set_swprof = tfa9874_set_swprofile;
+ ops->get_swprof = tfa9874_get_swprofile;
+ ops->set_swvstep = tfa9874_set_swvstep;
+ ops->get_swvstep = tfa9874_get_swvstep;
+ ops->dsp_system_stable = tfa9874_dsp_system_stable;
+ ops->faim_protect = tfa9874_faim_protect;
+ ops->get_mtpb = tfa9874_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+/***********************************************************************************/
+/* TFA9875 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9875_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9875_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+
+static enum Tfa98xx_Error tfa9875_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a75: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 26 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x53, 0x0237); //POR=0x0337
+ tfa_reg_write(tfa, 0x58, 0x0210); //POR=0x0200
+ tfa_reg_write(tfa, 0x5f, 0x0080); //POR=0x00c0
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0182
+ tfa_reg_write(tfa, 0x64, 0x4040); //POR=0x0040
+ tfa_reg_write(tfa, 0x6f, 0x0083); //POR=0x00a5
+ tfa_reg_write(tfa, 0x70, 0xdedf); //POR=0xdefb
+ tfa_reg_write(tfa, 0x73, 0x0182); //POR=0x0187
+ tfa_reg_write(tfa, 0x74, 0xd0f8); //POR=0x50f8
+ tfa_reg_write(tfa, 0x75, 0xd57a); //POR=0xd278
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ tfa_reg_write(tfa, 0x85, 0x0380); //POR=0x0382
+ tfa_reg_write(tfa, 0xd5, 0x004d); //POR=0x014d
+ /* ----- generated code end ----- */
+ break;
+ case 0x1a75: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 26 ----- */
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x51, 0x0020); //POR=0x0000
+ tfa_reg_write(tfa, 0x53, 0x0336); //POR=0x0337
+ tfa_reg_write(tfa, 0x58, 0x0210); //POR=0x0200
+ tfa_reg_write(tfa, 0x5f, 0x0080); //POR=0x00c0
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0182
+ tfa_reg_write(tfa, 0x63, 0x056a); //POR=0x055a
+ tfa_reg_write(tfa, 0x64, 0x4040); //POR=0x0040
+ tfa_reg_write(tfa, 0x6f, 0x0385); //POR=0x00a5
+ tfa_reg_write(tfa, 0x70, 0xde5f); //POR=0xdefb
+ tfa_reg_write(tfa, 0x73, 0x0183); //POR=0x0187
+ tfa_reg_write(tfa, 0x74, 0xd118); //POR=0x50f8
+ tfa_reg_write(tfa, 0x75, 0xd77a); //POR=0xd278
+ tfa_reg_write(tfa, 0x83, 0x06de); //POR=0x0799
+ tfa_reg_write(tfa, 0x85, 0x0380); //POR=0x0382
+ tfa_reg_write(tfa, 0x87, 0x040a); //POR=0x060a
+ /* ----- generated code end ----- */
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ return error;
+}
+
+static int tfa9875_set_bitfield(struct tfa_device* tfa, uint16_t bitfield, uint16_t value)
+{
+ if (((bitfield >> 8) & 0xff) == 0x10 || ((bitfield >> 8) & 0xff) == 0x13)
+ return tfa_set_bf_volatile(tfa, (uint16_t)bitfield, value);
+ else
+ return tfa_set_bf(tfa, (uint16_t)bitfield, value);
+}
+enum Tfa98xx_Error tfa9875_tfa_status(struct tfa_device* tfa)
+{
+ int value;
+ uint16_t val;
+ value = tfa_read_reg(tfa, TFA9875_BF_VDDS); /* STATUSREG */
+ if (value < 0)
+ return -value;
+ val = (uint16_t)value;
+ if (!tfa_get_bf_value(TFA9875_BF_UVDS, val) ||
+ !tfa_get_bf_value(TFA9875_BF_OVDS, val) ||
+ !tfa_get_bf_value(TFA9875_BF_OTDS, val) ||
+ tfa_get_bf_value(TFA9875_BF_OCDS, val) ||
+ tfa_get_bf_value(TFA9875_BF_NOCLK, val))
+ pr_err("Misc errors detected: STATUS_FLAG0 = 0x%x\n", val);
+ if (!tfa_get_bf_value(TFA9875_BF_UVDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_UVDS, 1);
+ if (!tfa_get_bf_value(TFA9875_BF_OVDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_OVDS, 1);
+ if (!tfa_get_bf_value(TFA9875_BF_OTDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_OTDS, 1);
+ if (tfa_get_bf_value(TFA9875_BF_OCDS, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_OCDS, 1);
+ if (tfa_get_bf_value(TFA9875_BF_NOCLK, val))
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_NOCLK, 1);
+ /*
+ * checking clocking stability.
+ */
+ if (!tfa_get_bf(tfa, TFA9875_BF_CLKS))
+ pr_err("ERROR: CLKS is unstable\n");
+ if (!tfa_get_bf(tfa, TFA9875_BF_PLLS))
+ pr_err("ERROR: PLL not locked\n");
+ if (tfa_get_bf(tfa, TFA9875_BF_TDMERR) ||
+ tfa_get_bf(tfa, TFA9875_BF_TDMLUTER))
+ pr_err("TDM related errors: STATUS_FLAG1 = 0x%x\n", (uint16_t)tfa_read_reg(tfa, TFA9875_BF_TDMERR));
+ if (tfa_get_bf(tfa, TFA9875_BF_BODNOK))
+ {
+ pr_err("BODNOK error detected : STATUS_FLAG3 = 0x%x\n", (uint16_t)tfa_read_reg(tfa, TFA9875_BF_BODNOK));
+ tfa_set_bf(tfa, (uint16_t)TFA9875_BF_BODNOK, 1);
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+static enum Tfa98xx_Error tfa9875_phase_shift(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 1b = enable phase shift 0b = disable phase shift */
+ ret = tfa_set_bf_volatile(tfa, 0x58c0, (const uint16_t)1);
+ return ret;
+}
+static int tfa9875_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9875_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9875_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9875_BF_SWPROFIL) - 1;
+}
+
+static int tfa9875_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9875_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9875_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9875_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9875_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9875_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9875_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9875_BF_MTPB);
+ return value;
+}
+
+void tfa9875_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9875_specific;
+ ops->set_swprof = tfa9875_set_swprofile;
+ ops->get_swprof = tfa9875_get_swprofile;
+ ops->set_swvstep = tfa9875_set_swvstep;
+ ops->get_swvstep = tfa9875_get_swvstep;
+ ops->dsp_system_stable = tfa9875_dsp_system_stable;
+ ops->faim_protect = tfa9875_faim_protect;
+ ops->get_mtpb = tfa9875_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+ ops->tfa_set_bitfield = tfa9875_set_bitfield;
+ ops->tfa_status = tfa9875_tfa_status;
+ ops->phase_shift = tfa9875_phase_shift;
+}
+/***********************************************************************************/
+/* TFA9878 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9878_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9878_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+
+static enum Tfa98xx_Error tfa9878_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock key 1 and 2 */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ tfa98xx_key2(tfa, 0);
+
+ switch (tfa->rev) {
+ case 0x0a78: /* Initial revision ID */
+/* ----- generated code start ----- */
+/* ----- version 28 ----- */
+ tfa_reg_write(tfa, 0x01, 0x2e18); //POR=0x2e88
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x04, 0x0240); //POR=0x0340
+ tfa_reg_write(tfa, 0x52, 0x587c); //POR=0x57dc
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0a82
+ tfa_reg_write(tfa, 0x63, 0x055a); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0542); //POR=0x0a82
+ tfa_reg_write(tfa, 0x71, 0x303e); //POR=0x307e
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ /* ----- generated code end ----- */
+
+
+ break;
+ case 0x1a78: /* Initial revision ID */
+ /* ----- generated code start ----- */
+ /* ----- version 12 ----- */
+ tfa_reg_write(tfa, 0x01, 0x2e18); //POR=0x2e88
+ tfa_reg_write(tfa, 0x02, 0x0628); //POR=0x0008
+ tfa_reg_write(tfa, 0x04, 0x0241); //POR=0x0340
+ tfa_reg_write(tfa, 0x52, 0x587c); //POR=0x57dc
+ tfa_reg_write(tfa, 0x61, 0x0183); //POR=0x0a82
+ tfa_reg_write(tfa, 0x63, 0x055a); //POR=0x0a9a
+ tfa_reg_write(tfa, 0x65, 0x0542); //POR=0x0a82
+ tfa_reg_write(tfa, 0x70, 0xb7ff); //POR=0x37ff
+ tfa_reg_write(tfa, 0x71, 0x303e); //POR=0x307e
+ tfa_reg_write(tfa, 0x83, 0x009a); //POR=0x0799
+ tfa_reg_write(tfa, 0x84, 0x0211); //POR=0x0011
+ tfa_reg_write(tfa, 0x8c, 0x0210); //POR=0x0010
+ tfa_reg_write(tfa, 0xce, 0x2202); //POR=0xa202
+ tfa_reg_write(tfa, 0xd5, 0x0000); //POR=0x0100
+ /* ----- generated code end ----- */
+
+ break;
+ default:
+ pr_info("\nWarning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ break;
+ }
+
+ return error;
+}
+
+static int tfa9878_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9878_BF_SWPROFIL, new_value);
+
+ return active_value;
+}
+
+static int tfa9878_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9878_BF_SWPROFIL) - 1;
+}
+
+static int tfa9878_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+
+ /* Set the new value in the hw register */
+ tfa_set_bf_volatile(tfa, TFA9878_BF_SWVSTEP, new_value);
+
+ return new_value;
+}
+
+static int tfa9878_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9878_BF_SWVSTEP) - 1;
+}
+
+/* tfa98xx_dsp_system_stable
+* return: *ready = 1 when clocks are stable to allow DSP subsystem access
+*/
+static enum Tfa98xx_Error tfa9878_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9878_BF_CLKS) == 1;
+
+ return error;
+}
+
+static int tfa9878_get_mtpb(struct tfa_device *tfa) {
+
+ int value;
+ value = tfa_get_bf(tfa, TFA9878_BF_MTPB);
+ return value;
+}
+
+void tfa9878_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9878_specific;
+ ops->set_swprof = tfa9878_set_swprofile;
+ ops->get_swprof = tfa9878_get_swprofile;
+ ops->set_swvstep = tfa9878_set_swvstep;
+ ops->get_swvstep = tfa9878_get_swvstep;
+ ops->dsp_system_stable = tfa9878_dsp_system_stable;
+ ops->faim_protect = tfa9878_faim_protect;
+ ops->get_mtpb = tfa9878_get_mtpb;
+ ops->set_mute = tfa_set_mute_nodsp;
+}
+/***********************************************************************************/
+/* TFA9888 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9888_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+ int patch_version;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* Unlock keys to write settings */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+
+ /* Only N1C2 is supported */
+ /* ----- generated code start ----- */
+ /* --------- Version v1 ---------- */
+ if (tfa->rev == 0x2c88) {
+ tfa_reg_write(tfa, 0x00, 0x164d); //POR=0x064d
+ tfa_reg_write(tfa, 0x01, 0x828b); //POR=0x92cb
+ tfa_reg_write(tfa, 0x02, 0x1dc8); //POR=0x1828
+ tfa_reg_write(tfa, 0x0e, 0x0080); //POR=0x0000
+ tfa_reg_write(tfa, 0x20, 0x089e); //POR=0x0890
+ tfa_reg_write(tfa, 0x22, 0x543c); //POR=0x545c
+ tfa_reg_write(tfa, 0x23, 0x0006); //POR=0x0000
+ tfa_reg_write(tfa, 0x24, 0x0014); //POR=0x0000
+ tfa_reg_write(tfa, 0x25, 0x000a); //POR=0x0000
+ tfa_reg_write(tfa, 0x26, 0x0100); //POR=0x0000
+ tfa_reg_write(tfa, 0x28, 0x1000); //POR=0x0000
+ tfa_reg_write(tfa, 0x51, 0x0000); //POR=0x00c0
+ tfa_reg_write(tfa, 0x52, 0xfafe); //POR=0xbaf6
+ tfa_reg_write(tfa, 0x70, 0x3ee4); //POR=0x3ee6
+ tfa_reg_write(tfa, 0x71, 0x1074); //POR=0x3074
+ tfa_reg_write(tfa, 0x83, 0x0014); //POR=0x0013
+ /* ----- generated code end ----- */
+ }
+ else {
+ pr_info("Warning: Optimal settings not found for device with revid = 0x%x \n", tfa->rev);
+ }
+
+ patch_version = tfa_cnt_get_patch_version(tfa);
+ if (patch_version >= 0x060401)
+ tfa->partial_enable = 1;
+
+ return error;
+}
+
+static enum Tfa98xx_Error tfa9888_tfa_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ unsigned char buffer[15] = { 0 };
+ int size = 15 * sizeof(char);
+
+ /* Write the fractional delay in the hardware register 'cs_frac_delay' */
+ switch (sample_rate) {
+ case 0: /* 8kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 40);
+ break;
+ case 1: /* 11.025KHz */
+ TFA_SET_BF(tfa, FRACTDEL, 38);
+ break;
+ case 2: /* 12kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 37);
+ break;
+ case 3: /* 16kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 59);
+ break;
+ case 4: /* 22.05KHz */
+ TFA_SET_BF(tfa, FRACTDEL, 56);
+ break;
+ case 5: /* 24kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 56);
+ break;
+ case 6: /* 32kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 52);
+ break;
+ case 7: /* 44.1kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 48);
+ break;
+ case 8:
+ default:/* 48kHz */
+ TFA_SET_BF(tfa, FRACTDEL, 46);
+ break;
+ }
+
+ /* First copy the msg_id to the buffer */
+ buffer[0] = (uint8_t)0;
+ buffer[1] = (uint8_t)MODULE_FRAMEWORK + 128;
+ buffer[2] = (uint8_t)FW_PAR_ID_SET_SENSES_DELAY;
+
+ /* Required for all FS exept 8kHz (8kHz is all zero) */
+ if (sample_rate != 0) {
+ buffer[5] = 1; /* Vdelay_P */
+ buffer[8] = 0; /* Idelay_P */
+ buffer[11] = 1; /* Vdelay_S */
+ buffer[14] = 0; /* Idelay_S */
+ }
+
+ /* send SetSensesDelay msg */
+ return tfa_dsp_msg(tfa, size, (char *)buffer);
+}
+
+static enum Tfa98xx_Error tfa9888_auto_copy_mtp_to_iic(struct tfa_device *tfa)
+{
+ /* Set auto_copy_mtp_to_iic (bit 5 of A3) to 1. Workaround for 72 and 88 (see PLMA5290) */
+ return tfa_reg_write(tfa, 0xA3, 0x20);
+}
+
+static enum Tfa98xx_Error tfa9888_factory_trimmer(struct tfa_device *tfa)
+{
+ unsigned short currentValue, delta;
+ int result;
+
+ /* Factory trimming for the Boost converter */
+ /* check if there is a correction needed */
+ result = TFA_GET_BF(tfa, DCMCCAPI);
+ if (result) {
+ /* Get currentvalue of DCMCC and the Delta value */
+ currentValue = (unsigned short)TFA_GET_BF(tfa, DCMCC);
+ delta = (unsigned short)TFA_GET_BF(tfa, USERDEF);
+
+ /* check the sign bit (+/-) */
+ result = TFA_GET_BF(tfa, DCMCCSB);
+ if (result == 0) {
+ /* Do not exceed the maximum value of 15 */
+ if (currentValue + delta < 15) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue + delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue + delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 15);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 15 \n");
+ }
+ }
+ else if (result == 1) {
+ /* Do not exceed the minimum value of 0 */
+ if (currentValue - delta > 0) {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, currentValue - delta);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: %d \n", currentValue - delta);
+ }
+ else {
+ TFA_SET_BF_VOLATILE(tfa, DCMCC, 0);
+ if (tfa->verbose)
+ pr_debug("Max coil current is set to: 0 \n");
+ }
+ }
+ }
+
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error
+tfa9888_set_mute(struct tfa_device *tfa, int mute)
+{
+ TFA_SET_BF(tfa, CFSMR, (const uint16_t)mute);
+ TFA_SET_BF(tfa, CFSML, (const uint16_t)mute);
+
+ return Tfa98xx_Error_Ok;
+}
+
+void tfa9888_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9888_specific;
+ ops->dsp_write_tables = tfa9888_tfa_dsp_write_tables;
+ ops->auto_copy_mtp_to_iic = tfa9888_auto_copy_mtp_to_iic;
+ ops->factory_trimmer = tfa9888_factory_trimmer;
+ ops->set_mute = tfa9888_set_mute;
+}
+
+/***********************************************************************************/
+/* TFA9896 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9896_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+
+ if ((tfa->rev == 0x2b96) || (tfa->rev == 0x3b96)) {
+ ret = tfa_set_bf_volatile(tfa, TFA9896_BF_OPENMTP, (uint16_t)status);
+ }
+
+ return ret;
+}
+
+/***********************************************************************************/
+/* TFA9896 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9896_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short check_value;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers must already set to default POR value */
+
+ /* $48:[3] - 1 ==> 0; iddqtestbst - default value changed.
+ * When Iddqtestbst is set to "0", the slewrate is reduced.
+ * This will lower the overshoot on IN-B to avoid NMOS damage of booster.
+ */
+ if (tfa->rev == 0x1b96) {
+ /* ----- generated code start v17 ----- */
+ tfa_reg_write(tfa, 0x06, 0x000b); //POR=0x0001
+ tfa_reg_write(tfa, 0x07, 0x3e7f); //POR=0x1e7f
+ tfa_reg_write(tfa, 0x0a, 0x0d8a); //POR=0x0592
+ tfa_reg_write(tfa, 0x48, 0x0300); //POR=0x0308
+ tfa_reg_write(tfa, 0x88, 0x0100); //POR=0x0000
+ /* ----- generated code end ----- */
+ }
+ else if (tfa->rev == 0x2b96) {
+ /* ----- generated code start ----- v1*/
+ tfa_reg_write(tfa, 0x06, 0x000b); //POR=0x0001
+ tfa_reg_write(tfa, 0x07, 0x3e7f); //POR=0x1e7f
+ tfa_reg_write(tfa, 0x0a, 0x0d8a); //POR=0x0592
+ tfa_reg_write(tfa, 0x48, 0x0300); //POR=0x0308
+ tfa_reg_write(tfa, 0x88, 0x0100); //POR=0x0000
+ /* ----- generated code end ----- */
+ }
+ else if (tfa->rev == 0x3b96) {
+ /* ----- generated code start ----- v1*/
+ tfa_reg_write(tfa, 0x06, 0x000b); //POR=0x0001
+ tfa_reg_write(tfa, 0x07, 0x3e7f); //POR=0x1e7f
+ tfa_reg_write(tfa, 0x0a, 0x0d8a); //POR=0x0592
+ tfa_reg_write(tfa, 0x48, 0x0300); //POR=0x0308
+ tfa_reg_write(tfa, 0x88, 0x0100); //POR=0x0000
+ /* ----- generated code end ----- */
+ }
+ /* $49:[0] - 1 ==> 0; CLIP - default value changed. 0 means CLIPPER on */
+ error = tfa_reg_read(tfa, 0x49, &check_value);
+ check_value &= ~0x1;
+ error = tfa_reg_write(tfa, 0x49, check_value);
+ return error;
+}
+
+/*
+* the int24 values for the vsfw delay table
+*/
+static unsigned char tfa9896_vsfwdelay_table[] = {
+ 0,0,2, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0,0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0,0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,2, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,2, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,2, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,2, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,3 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+/*
+* TODO make this tfa98xx
+* Note that the former products write this table via the patch
+* so moving this to the tfa98xx API requires also updating all patches
+*/
+static enum Tfa98xx_Error tfa9896_dsp_write_vsfwdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURRENT_DELAY, sizeof(tfa9896_vsfwdelay_table), tfa9896_vsfwdelay_table);
+}
+
+/*
+* The int24 values for the fracdelay table
+* For now applicable only for 8 and 48 kHz
+*/
+static unsigned char tfa9896_cvfracdelay_table[] = {
+ 0,0,51, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0, 0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0, 0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,38, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,34, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,33, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,11, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,62 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+static enum Tfa98xx_Error tfa9896_dsp_write_cvfracdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURFRAC_DELAY, sizeof(tfa9896_cvfracdelay_table), tfa9896_cvfracdelay_table);;
+}
+
+static enum Tfa98xx_Error tfa9896_tfa_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ enum Tfa98xx_Error error;
+
+ /* Not used for max1! */
+ (void)sample_rate;
+
+ error = tfa9896_dsp_write_vsfwdelay_table(tfa);
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfa9896_dsp_write_cvfracdelay_table(tfa);
+ }
+
+ return error;
+}
+
+void tfa9896_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9896_specific;
+ ops->dsp_write_tables = tfa9896_tfa_dsp_write_tables;
+ ops->faim_protect = tfa9896_faim_protect;
+}
+
+/***********************************************************************************/
+/* TFA9897 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9897_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short check_value;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers must already set to default POR value */
+
+ /* $48:[3] - 1 ==> 0; iddqtestbst - default value changed.
+ * When Iddqtestbst is set to "0", the slewrate is reduced.
+ * This will lower the overshoot on IN-B to avoid NMOS damage of booster */
+ error = tfa_reg_write(tfa, 0x48, 0x0300); /* POR value = 0x308 */
+
+ /* $49:[0] - 1 ==> 0; CLIP - default value changed. 0 means CLIPPER on */
+ error = tfa_reg_read(tfa, 0x49, &check_value);
+ check_value &= ~0x1;
+ error = tfa_reg_write(tfa, 0x49, check_value);
+
+ return error;
+}
+
+/*
+* the int24 values for the vsfw delay table
+*/
+static unsigned char tfa9897_vsfwdelay_table[] = {
+ 0,0,2, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0,0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0,0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,2, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,2, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,2, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,2, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,3 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+/*
+* TODO make this tfa98xx
+* Note that the former products write this table via the patch
+* so moving this to the tfa98xx API requires also updating all patches
+*/
+static enum Tfa98xx_Error tfa9897_dsp_write_vsfwdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURRENT_DELAY, sizeof(tfa9897_vsfwdelay_table), tfa9897_vsfwdelay_table);;
+}
+
+/*
+* The int24 values for the fracdelay table
+* For now applicable only for 8 and 48 kHz
+*/
+static unsigned char tfa9897_cvfracdelay_table[] = {
+ 0,0,51, /* Index 0 - Current/Volt Fractional Delay for 8KHz */
+ 0,0, 0, /* Index 1 - Current/Volt Fractional Delay for 11KHz */
+ 0,0, 0, /* Index 2 - Current/Volt Fractional Delay for 12KHz */
+ 0,0,38, /* Index 3 - Current/Volt Fractional Delay for 16KHz */
+ 0,0,34, /* Index 4 - Current/Volt Fractional Delay for 22KHz */
+ 0,0,33, /* Index 5 - Current/Volt Fractional Delay for 24KHz */
+ 0,0,11, /* Index 6 - Current/Volt Fractional Delay for 32KHz */
+ 0,0,2, /* Index 7 - Current/Volt Fractional Delay for 44KHz */
+ 0,0,62 /* Index 8 - Current/Volt Fractional Delay for 48KHz */
+};
+
+static enum Tfa98xx_Error tfa9897_dsp_write_cvfracdelay_table(struct tfa_device *tfa)
+{
+ return tfa_dsp_cmd_id_write(tfa, MODULE_FRAMEWORK, TFA1_FW_PAR_ID_SET_CURFRAC_DELAY, sizeof(tfa9897_cvfracdelay_table), tfa9897_cvfracdelay_table);;
+}
+
+static enum Tfa98xx_Error tfa9897_tfa_dsp_write_tables(struct tfa_device *tfa, int sample_rate)
+{
+ enum Tfa98xx_Error error;
+
+ /* Not used for max1! */
+ (void)sample_rate;
+
+ error = tfa9897_dsp_write_vsfwdelay_table(tfa);
+ if (error == Tfa98xx_Error_Ok) {
+ error = tfa9897_dsp_write_cvfracdelay_table(tfa);
+ }
+
+ return error;
+}
+
+void tfa9897_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9897_specific;
+ ops->dsp_write_tables = tfa9897_tfa_dsp_write_tables;
+}
+
+/***********************************************************************************/
+/* TFA9895 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9895_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ int result;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers are already set to default */
+
+ result = TFA_SET_BF(tfa, AMPE, 1);
+ if (result < 0)
+ return -result;
+
+ /* some other registers must be set for optimal amplifier behaviour */
+ tfa_reg_write(tfa, 0x05, 0x13AB);
+ tfa_reg_write(tfa, 0x06, 0x001F);
+ /* peak voltage protection is always on, but may be written */
+ tfa_reg_write(tfa, 0x08, 0x3C4E);
+ /*TFA98XX_SYSCTRL_DCA=0*/
+ tfa_reg_write(tfa, 0x09, 0x024D);
+ tfa_reg_write(tfa, 0x41, 0x0308);
+ error = tfa_reg_write(tfa, 0x49, 0x0E82);
+
+ return error;
+}
+
+void tfa9895_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9895_specific;
+}
+
+/***********************************************************************************/
+/* TFA9891 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9891_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* ----- generated code start ----- */
+ /* ----- version 18.0 ----- */
+ tfa_reg_write(tfa, 0x09, 0x025d); //POR=0x024d
+ tfa_reg_write(tfa, 0x10, 0x0018); //POR=0x0024
+ tfa_reg_write(tfa, 0x22, 0x0003); //POR=0x0023
+ tfa_reg_write(tfa, 0x25, 0x0001); //POR=0x0000
+ tfa_reg_write(tfa, 0x46, 0x0000); //POR=0x4000
+ tfa_reg_write(tfa, 0x55, 0x3ffb); //POR=0x7fff
+ /* ----- generated code end ----- */
+
+ return error;
+}
+
+void tfa9891_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9891_specific;
+}
+
+/***********************************************************************************/
+/* TFA9890 */
+/***********************************************************************************/
+static enum Tfa98xx_Error tfa9890_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short regRead = 0;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+
+ /* all i2C registers are already set to default for N1C2 */
+
+ /* some PLL registers must be set optimal for amplifier behaviour */
+ error = tfa_reg_write(tfa, 0x40, 0x5a6b);
+ if (error)
+ return error;
+ tfa_reg_read(tfa, 0x59, &regRead);
+ regRead |= 0x3;
+ tfa_reg_write(tfa, 0x59, regRead);
+ error = tfa_reg_write(tfa, 0x40, 0x0000);
+ error = tfa_reg_write(tfa, 0x47, 0x7BE1);
+
+ return error;
+}
+
+/*
+* Disable clock gating
+*/
+static enum Tfa98xx_Error tfa9890_clockgating(struct tfa_device *tfa, int on)
+{
+ enum Tfa98xx_Error error;
+ unsigned short value;
+
+ /* for TFA9890 temporarily disable clock gating when dsp reset is used */
+ error = tfa_reg_read(tfa, TFA98XX_CURRENTSENSE4, &value);
+ if (error) return error;
+
+ if (Tfa98xx_Error_Ok == error) {
+ if (on) /* clock gating on - clear the bit */
+ value &= ~TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF;
+ else /* clock gating off - set the bit */
+ value |= TFA98XX_CURRENTSENSE4_CTRL_CLKGATECFOFF;
+
+ error = tfa_reg_write(tfa, TFA98XX_CURRENTSENSE4, value);
+ }
+
+ return error;
+}
+
+/*
+* Tfa9890_DspReset will deal with clock gating control in order
+* to reset the DSP for warm state restart
+*/
+static enum Tfa98xx_Error tfa9890_dsp_reset(struct tfa_device *tfa, int state)
+{
+ enum Tfa98xx_Error error;
+
+ /* for TFA9890 temporarily disable clock gating
+ when dsp reset is used */
+ tfa9890_clockgating(tfa, 0);
+
+ TFA_SET_BF(tfa, RST, (uint16_t)state);
+
+ /* clock gating restore */
+ error = tfa9890_clockgating(tfa, 1);
+
+ return error;
+}
+
+/*
+ * Tfa9890_DspSystemStable will compensate for the wrong behavior of CLKS
+ * to determine if the DSP subsystem is ready for patch and config loading.
+ *
+ * A MTP calibration register is checked for non-zero.
+ *
+ * Note: This only works after i2c reset as this will clear the MTP contents.
+ * When we are configured then the DSP communication will synchronize access.
+ *
+ */
+static enum Tfa98xx_Error tfa9890_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short status, mtp0;
+ int result, tries;
+
+ /* check the contents of the STATUS register */
+ result = TFA_READ_REG(tfa, AREFS);
+ if (result < 0) {
+ error = -result;
+ goto errorExit;
+ }
+ status = (unsigned short)result;
+
+ /* if AMPS is set then we were already configured and running
+ * no need to check further
+ */
+ *ready = (TFA_GET_BF_VALUE(tfa, AMPS, status) == 1);
+ if (*ready) /* if ready go back */
+ return error; /* will be Tfa98xx_Error_Ok */
+
+ /* check AREFS and CLKS: not ready if either is clear */
+ *ready = !((TFA_GET_BF_VALUE(tfa, AREFS, status) == 0)
+ || (TFA_GET_BF_VALUE(tfa, CLKS, status) == 0));
+ if (!*ready) /* if not ready go back */
+ return error; /* will be Tfa98xx_Error_Ok */
+
+ /* check MTPB
+ * mtpbusy will be active when the subsys copies MTP to I2C
+ * 2 times retry avoids catching this short mtpbusy active period
+ */
+ for (tries = 2; tries > 0; tries--) {
+ result = TFA_GET_BF(tfa, MTPB);/*TODO_MTPB*/
+ if (result < 0) {
+ error = -result;
+ goto errorExit;
+ }
+ status = (unsigned short)result;
+
+ /* check the contents of the STATUS register */
+ *ready = (result == 0);
+ if (*ready) /* if ready go on */
+ break;
+ }
+ if (tries == 0) /* ready will be 0 if retries exausted */
+ return Tfa98xx_Error_Ok;
+
+ /* check the contents of MTP register for non-zero,
+ * this indicates that the subsys is ready */
+
+ error = tfa_reg_read(tfa, 0x84, &mtp0);
+ if (error)
+ goto errorExit;
+
+ *ready = (mtp0 != 0); /* The MTP register written? */
+
+ return error;
+
+errorExit:
+ *ready = 0;
+ return error;
+}
+
+void tfa9890_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9890_specific;
+ ops->dsp_reset = tfa9890_dsp_reset;
+ ops->dsp_system_stable = tfa9890_dsp_system_stable;
+}
+
+/***********************************************************************************/
+/* TFA9894 */
+/***********************************************************************************/
+static int tfa9894_set_swprofile(struct tfa_device *tfa, unsigned short new_value)
+{
+ int active_value = tfa_dev_get_swprof(tfa);
+
+ /* Set the new value in the struct */
+ tfa->profile = new_value - 1;
+ tfa_set_bf_volatile(tfa, TFA9894_BF_SWPROFIL, new_value);
+ return active_value;
+}
+
+static int tfa9894_get_swprofile(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9894_BF_SWPROFIL) - 1;
+}
+
+static int tfa9894_set_swvstep(struct tfa_device *tfa, unsigned short new_value)
+{
+ /* Set the new value in the struct */
+ tfa->vstep = new_value - 1;
+ tfa_set_bf_volatile(tfa, TFA9894_BF_SWVSTEP, new_value);
+ return new_value;
+}
+
+static int tfa9894_get_swvstep(struct tfa_device *tfa)
+{
+ return tfa_get_bf(tfa, TFA9894_BF_SWVSTEP) - 1;
+}
+
+static int tfa9894_get_mtpb(struct tfa_device *tfa)
+{
+ int value = 0;
+ value = tfa_get_bf(tfa, TFA9894_BF_MTPB);
+ return value;
+}
+
+/** Set internal oscillator into power down mode for TFA9894.
+*
+* This function is a worker for tfa98xx_set_osc_powerdown().
+*
+* @param[in] tfa device description structure
+* @param[in] state new state 0 - oscillator is on, 1 oscillator is off.
+*
+* @return Tfa98xx_Error_Ok when successfull, error otherwise.
+*/
+static enum Tfa98xx_Error tfa9894_set_osc_powerdown(struct tfa_device *tfa, int state)
+{
+ if (state == 1 || state == 0) {
+ return -tfa_set_bf(tfa, TFA9894_BF_MANAOOSC, (uint16_t)state);
+ }
+
+ return Tfa98xx_Error_Bad_Parameter;
+}
+
+static enum Tfa98xx_Error tfa9894_faim_protect(struct tfa_device *tfa, int status)
+{
+ enum Tfa98xx_Error ret = Tfa98xx_Error_Ok;
+ /* 0b = FAIM protection enabled 1b = FAIM protection disabled*/
+ ret = tfa_set_bf_volatile(tfa, TFA9894_BF_OPENMTP, (uint16_t)(status));
+ return ret;
+}
+
+static enum Tfa98xx_Error tfa9894_specific(struct tfa_device *tfa)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+ unsigned short value, xor;
+
+ if (tfa->in_use == 0)
+ return Tfa98xx_Error_NotOpen;
+ /* Unlock keys to write settings */
+ error = tfa_reg_write(tfa, 0x0F, 0x5A6B);
+ error = tfa_reg_read(tfa, 0xFB, &value);
+ xor = value ^ 0x005A;
+ error = tfa_reg_write(tfa, 0xA0, xor);
+ pr_debug("Device REFID:%x\n", tfa->rev);
+ /* The optimal settings */
+ if (tfa->rev == 0x0a94) {
+ /* V36 */
+ /* ----- generated code start ----- */
+ tfa_reg_write(tfa, 0x00, 0xa245); //POR=0x8245
+ tfa_reg_write(tfa, 0x02, 0x51e8); //POR=0x55c8
+ tfa_reg_write(tfa, 0x52, 0xbe17); //POR=0xb617
+ tfa_reg_write(tfa, 0x57, 0x0344); //POR=0x0366
+ tfa_reg_write(tfa, 0x61, 0x0033); //POR=0x0073
+ tfa_reg_write(tfa, 0x71, 0x00cf); //POR=0x018d
+ tfa_reg_write(tfa, 0x72, 0x34a9); //POR=0x44e8
+ tfa_reg_write(tfa, 0x73, 0x3808); //POR=0x3806
+ tfa_reg_write(tfa, 0x76, 0x0067); //POR=0x0065
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x81, 0x5715); //POR=0x561a
+ tfa_reg_write(tfa, 0x82, 0x0104); //POR=0x0044
+ /* ----- generated code end ----- */
+ }
+ else if (tfa->rev == 0x1a94) {
+ /* V17 */
+ /* ----- generated code start ----- */
+ tfa_reg_write(tfa, 0x00, 0xa245); //POR=0x8245
+ tfa_reg_write(tfa, 0x01, 0x15da); //POR=0x11ca
+ tfa_reg_write(tfa, 0x02, 0x5288); //POR=0x55c8
+ tfa_reg_write(tfa, 0x52, 0xbe17); //POR=0xb617
+ tfa_reg_write(tfa, 0x53, 0x0dbe); //POR=0x0d9e
+ tfa_reg_write(tfa, 0x56, 0x05c3); //POR=0x07c3
+ tfa_reg_write(tfa, 0x57, 0x0344); //POR=0x0366
+ tfa_reg_write(tfa, 0x61, 0x0032); //POR=0x0073
+ tfa_reg_write(tfa, 0x71, 0x00cf); //POR=0x018d
+ tfa_reg_write(tfa, 0x72, 0x34a9); //POR=0x44e8
+ tfa_reg_write(tfa, 0x73, 0x38c8); //POR=0x3806
+ tfa_reg_write(tfa, 0x76, 0x0067); //POR=0x0065
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x81, 0x5799); //POR=0x561a
+ tfa_reg_write(tfa, 0x82, 0x0104); //POR=0x0044
+ /* ----- generated code end ----- */
+
+ }
+ else if (tfa->rev == 0x2a94 || tfa->rev == 0x3a94) {
+ /* ----- generated code start ----- */
+ /* ----- version 25.00 ----- */
+ tfa_reg_write(tfa, 0x01, 0x15da); //POR=0x11ca
+ tfa_reg_write(tfa, 0x02, 0x51e8); //POR=0x55c8
+ tfa_reg_write(tfa, 0x04, 0x0200); //POR=0x0000
+ tfa_reg_write(tfa, 0x52, 0xbe17); //POR=0xb617
+ tfa_reg_write(tfa, 0x53, 0x0dbe); //POR=0x0d9e
+ tfa_reg_write(tfa, 0x57, 0x0344); //POR=0x0366
+ tfa_reg_write(tfa, 0x61, 0x0032); //POR=0x0073
+ tfa_reg_write(tfa, 0x71, 0x6ecf); //POR=0x6f8d
+ tfa_reg_write(tfa, 0x72, 0xb4a9); //POR=0x44e8
+ tfa_reg_write(tfa, 0x73, 0x38c8); //POR=0x3806
+ tfa_reg_write(tfa, 0x76, 0x0067); //POR=0x0065
+ tfa_reg_write(tfa, 0x80, 0x0000); //POR=0x0003
+ tfa_reg_write(tfa, 0x81, 0x5799); //POR=0x561a
+ tfa_reg_write(tfa, 0x82, 0x0104); //POR=0x0044
+ /* ----- generated code end ----- */
+ }
+ return error;
+}
+
+static enum Tfa98xx_Error
+tfa9894_set_mute(struct tfa_device *tfa, int mute)
+{
+ tfa_set_bf(tfa, TFA9894_BF_CFSM, (const uint16_t)mute);
+ return Tfa98xx_Error_Ok;
+}
+
+static enum Tfa98xx_Error tfa9894_dsp_system_stable(struct tfa_device *tfa, int *ready)
+{
+ enum Tfa98xx_Error error = Tfa98xx_Error_Ok;
+
+ /* check CLKS: ready if set */
+ *ready = tfa_get_bf(tfa, TFA9894_BF_CLKS) == 1;
+
+ return error;
+}
+
+void tfa9894_ops(struct tfa_device_ops *ops)
+{
+ /* Set defaults for ops */
+ tfa_set_ops_defaults(ops);
+
+ ops->tfa_init = tfa9894_specific;
+ ops->dsp_system_stable = tfa9894_dsp_system_stable;
+ ops->set_mute = tfa9894_set_mute;
+ ops->faim_protect = tfa9894_faim_protect;
+ ops->get_mtpb = tfa9894_get_mtpb;
+ ops->set_swprof = tfa9894_set_swprofile;
+ ops->get_swprof = tfa9894_get_swprofile;
+ ops->set_swvstep = tfa9894_set_swvstep;
+ ops->get_swvstep = tfa9894_get_swvstep;
+ //ops->auto_copy_mtp_to_iic = tfa9894_auto_copy_mtp_to_iic;
+ ops->set_osc_powerdown = tfa9894_set_osc_powerdown;
+}
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_internal.h b/sound/soc/codecs/tfa98xx-downstream/tfa_internal.h
new file mode 100644
index 00000000000..39ecacf8c36
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_internal.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2020 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/*
+ internal functions for TFA layer (not shared with SRV and HAL layer!)
+*/
+
+#ifndef __TFA_INTERNAL_H__
+#define __TFA_INTERNAL_H__
+
+#include "tfa_dsp_fw.h"
+#include "tfa_ext.h"
+
+#if __GNUC__ >= 4
+ #define TFA_INTERNAL __attribute__ ((visibility ("hidden")))
+#else
+ #define TFA_INTERNAL
+#endif
+
+#define TFA98XX_GENERIC_SLAVE_ADDRESS 0x1C
+
+TFA_INTERNAL enum Tfa98xx_Error tfa98xx_check_rpc_status(struct tfa_device *tfa, int *pRpcStatus);
+TFA_INTERNAL enum Tfa98xx_Error tfa98xx_wait_result(struct tfa_device *tfa, int waitRetryCount);
+
+#endif /* __TFA_INTERNAL_H__ */
+
diff --git a/sound/soc/codecs/tfa98xx-downstream/tfa_service.h b/sound/soc/codecs/tfa98xx-downstream/tfa_service.h
new file mode 100644
index 00000000000..0e57893946e
--- /dev/null
+++ b/sound/soc/codecs/tfa98xx-downstream/tfa_service.h
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
+ * Copyright 2021 GOODIX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+
+#ifndef TFA_SERVICE_H
+#define TFA_SERVICE_H
+
+//#include "config.h"
+// workaround for Visual Studio:
+// fatal error C1083: Cannot open include file: 'config.h': No such file or directory
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+#ifdef __cplusplus
+extern "C" {
+#include "TFA_I2C.h"
+#endif
+
+/* Linux kernel module defines TFA98XX_GIT_VERSIONS in the linux_driver/Makefile */
+#if 0
+#include "versions.h"
+#endif
+#ifdef TFA98XX_GIT_VERSIONS
+ #define TFA98XX_API_REV_STR "v6.7.14"/*TFA98XX_GIT_VERSIONS*/
+#else
+ #define TFA98XX_API_REV_STR "v6.7.14"
+#endif
+
+#include "tfa_device.h"
+
+/*
+ * data previously defined in Tfa9888_dsp.h
+ */
+#define MEMTRACK_MAX_WORDS 150
+#define LSMODEL_MAX_WORDS 150
+#define TFA98XX_MAXTAG (150)
+#define FW_VAR_API_VERSION (521)
+
+/* Indexes and scaling factors of GetLSmodel */
+#define tfa9888_fs_IDX 128
+#define tfa9888_leakageFactor_IDX 130
+#define tfa9888_ReCorrection_IDX 131
+#define tfa9888_Bl_IDX 132
+#define ReZ_IDX 147
+
+#define tfa9872_leakageFactor_IDX 128
+#define tfa9872_ReCorrection_IDX 129
+#define tfa9872_Bl_IDX 130
+
+#define fs_SCALE (double)1
+#define leakageFactor_SCALE (double)8388608
+#define ReCorrection_SCALE (double)8388608
+#define Bl_SCALE (double)2097152
+#define tCoef_SCALE (double)8388608
+
+/* ---------------------------- Max1 ---------------------------- */
+/* Headroom applied to the main input signal */
+#define SPKRBST_HEADROOM 7
+/* Exponent used for AGC Gain related variables */
+#define SPKRBST_AGCGAIN_EXP SPKRBST_HEADROOM
+#define SPKRBST_TEMPERATURE_EXP 9
+/* Exponent used for Gain Corection related variables */
+#define SPKRBST_LIMGAIN_EXP 4
+#define SPKRBST_TIMECTE_EXP 1
+#define DSP_MAX_GAIN_EXP 7
+/* -------------------------------------------------------------- */
+
+/* speaker related parameters */
+#define TFA2_SPEAKERPARAMETER_LENGTH (3*151) /* MAX2=450 */
+#define TFA1_SPEAKERPARAMETER_LENGTH (3*141) /* MAX1=423 */
+
+/* vstep related parameters */
+#define TFA2_ALGOPARAMETER_LENGTH (3*304) /* N1B = (304) 305 is including the cmd-id */
+#define TFA72_ALGOPARAMETER_LENGTH_MONO (3*183)
+#define TFA72_ALGOPARAMETER_LENGTH_STEREO (3*356)
+#define TFA2_MBDRCPARAMETER_LENGTH (3*152) /* 154 is including the cmd-id */
+#define TFA72_MBDRCPARAMETER_LENGTH (3*98)
+#define TFA1_PRESET_LENGTH 87
+#define TFA1_DRC_LENGTH 381 /* 127 words */
+#define TFA2_FILTERCOEFSPARAMETER_LENGTH (3*168) /* 170 is including the cmd-id */
+#define TFA72_FILTERCOEFSPARAMETER_LENGTH (3*156)
+
+/* Maximum number of retries for DSP result
+ * Keep this value low!
+ * If certain calls require longer wait conditions, the
+ * application should poll, not the API
+ * The total wait time depends on device settings. Those
+ * are application specific.
+ */
+#define TFA98XX_WAITRESULT_NTRIES 40
+#define TFA98XX_WAITRESULT_NTRIES_LONG 2000
+
+/* following lengths are in bytes */
+#define TFA98XX_PRESET_LENGTH 87
+#define TFA98XX_CONFIG_LENGTH 201
+#define TFA98XX_DRC_LENGTH 381 /* 127 words */
+
+typedef unsigned char Tfa98xx_Config_t[TFA98XX_CONFIG_LENGTH];
+typedef unsigned char Tfa98xx_Preset_t[TFA98XX_PRESET_LENGTH];
+typedef unsigned char Tfa98xx_DrcParameters_t[TFA98XX_DRC_LENGTH];
+
+/* Type containing all the possible errors that can occur
+ *
+ */
+enum Tfa98xx_Error {
+ Tfa98xx_Error_Ok = 0,
+ Tfa98xx_Error_Device, /* 1. Currently only used to keep in sync with tfa_error */
+ Tfa98xx_Error_Bad_Parameter, /* 2. */
+ Tfa98xx_Error_Fail, /* 3. generic failure, avoid mislead message */
+ Tfa98xx_Error_NoClock, /* 4. no clock detected */
+ Tfa98xx_Error_StateTimedOut, /* 5. */
+ Tfa98xx_Error_DSP_not_running, /* 6. communication with the DSP failed */
+ Tfa98xx_Error_AmpOn, /* 7. amp is still running */
+ Tfa98xx_Error_NotOpen, /* 8. the given handle is not open */
+ Tfa98xx_Error_InUse, /* 9. too many handles */
+ Tfa98xx_Error_Buffer_too_small, /* 10. if a buffer is too small */
+ /* the expected response did not occur within the expected time */
+ Tfa98xx_Error_RpcBase = 100,
+ Tfa98xx_Error_RpcBusy = 101,
+ Tfa98xx_Error_RpcModId = 102,
+ Tfa98xx_Error_RpcParamId = 103,
+ Tfa98xx_Error_RpcInvalidCC = 104,
+ Tfa98xx_Error_RpcInvalidSeq = 105,
+ Tfa98xx_Error_RpcInvalidParam = 106,
+ Tfa98xx_Error_RpcBufferOverflow = 107,
+ Tfa98xx_Error_RpcCalibBusy = 108,
+ Tfa98xx_Error_RpcCalibFailed = 109,
+ Tfa98xx_Error_Not_Implemented,
+ Tfa98xx_Error_Not_Supported,
+ Tfa98xx_Error_I2C_Fatal, /* Fatal I2C error occurred */
+ /* Nonfatal I2C error, and retry count reached */
+ Tfa98xx_Error_I2C_NonFatal,
+ Tfa98xx_Error_Other = 1000
+};
+
+/*
+ * Type containing all the possible msg returns DSP can give
+ * //TODO move to tfa_dsp_fw.h
+ */
+enum Tfa98xx_Status_ID {
+ Tfa98xx_DSP_Not_Running = -1, /* No response from DSP */
+ Tfa98xx_I2C_Req_Done = 0, /* Request executed correctly and result, if any, is available for download */
+ Tfa98xx_I2C_Req_Busy = 1, /* Request is being processed, just wait for result */
+ Tfa98xx_I2C_Req_Invalid_M_ID = 2, /* Provided M-ID does not fit in valid rang [0..2] */
+ Tfa98xx_I2C_Req_Invalid_P_ID = 3, /* Provided P-ID isn<73>t valid in the given M-ID context */
+ Tfa98xx_I2C_Req_Invalid_CC = 4, /* Invalid channel configuration bits (SC|DS|DP|DC) combination */
+ Tfa98xx_I2C_Req_Invalid_Seq = 5, /* Invalid sequence of commands, in case the DSP expects some commands in a specific order */
+ Tfa98xx_I2C_Req_Invalid_Param = 6, /* Generic error */
+ Tfa98xx_I2C_Req_Buffer_Overflow = 7, /* I2C buffer has overflowed: host has sent too many parameters, memory integrity is not guaranteed */
+ Tfa98xx_I2C_Req_Calib_Busy = 8, /* Calibration not finished */
+ Tfa98xx_I2C_Req_Calib_Failed = 9 /* Calibration failed */
+};
+
+/*
+ * speaker as microphone
+ */
+enum Tfa98xx_saam {
+ Tfa98xx_saam_none, /*< SAAM feature not available */
+ Tfa98xx_saam /*< SAAM feature available */
+};
+
+/*
+ * config file subtypes
+ */
+enum Tfa98xx_config_type {
+ Tfa98xx_config_generic,
+ Tfa98xx_config_sub1,
+ Tfa98xx_config_sub2,
+ Tfa98xx_config_sub3,
+};
+
+enum Tfa98xx_AmpInputSel {
+ Tfa98xx_AmpInputSel_I2SLeft,
+ Tfa98xx_AmpInputSel_I2SRight,
+ Tfa98xx_AmpInputSel_DSP
+};
+
+enum Tfa98xx_OutputSel {
+ Tfa98xx_I2SOutputSel_CurrentSense,
+ Tfa98xx_I2SOutputSel_DSP_Gain,
+ Tfa98xx_I2SOutputSel_DSP_AEC,
+ Tfa98xx_I2SOutputSel_Amp,
+ Tfa98xx_I2SOutputSel_DataI3R,
+ Tfa98xx_I2SOutputSel_DataI3L,
+ Tfa98xx_I2SOutputSel_DcdcFFwdCur,
+};
+
+enum Tfa98xx_StereoGainSel {
+ Tfa98xx_StereoGainSel_Left,
+ Tfa98xx_StereoGainSel_Right
+};
+
+#define TFA98XX_MAXPATCH_LENGTH (3*1024)
+
+/* the number of biquads supported */
+#define TFA98XX_BIQUAD_NUM 10
+
+enum Tfa98xx_Channel {
+ Tfa98xx_Channel_L,
+ Tfa98xx_Channel_R,
+ Tfa98xx_Channel_L_R,
+ Tfa98xx_Channel_Stereo
+};
+
+enum Tfa98xx_Mode {
+ Tfa98xx_Mode_Normal = 0,
+ Tfa98xx_Mode_RCV
+};
+
+enum Tfa98xx_Mute {
+ Tfa98xx_Mute_Off,
+ Tfa98xx_Mute_Digital,
+ Tfa98xx_Mute_Amplifier
+};
+
+enum Tfa98xx_SpeakerBoostStatusFlags {
+ Tfa98xx_SpeakerBoost_Activity = 0, /* Input signal activity. */
+ Tfa98xx_SpeakerBoost_S_Ctrl, /* S Control triggers the limiter */
+ Tfa98xx_SpeakerBoost_Muted, /* 1 when signal is muted */
+ Tfa98xx_SpeakerBoost_X_Ctrl, /* X Control triggers the limiter */
+ Tfa98xx_SpeakerBoost_T_Ctrl, /* T Control triggers the limiter */
+ Tfa98xx_SpeakerBoost_NewModel, /* New model is available */
+ Tfa98xx_SpeakerBoost_VolumeRdy, /* 0:stable vol, 1:still smoothing */
+ Tfa98xx_SpeakerBoost_Damaged, /* Speaker Damage detected */
+ Tfa98xx_SpeakerBoost_SignalClipping /* input clipping detected */
+};
+
+struct Tfa98xx_DrcStateInfo {
+ float GRhighDrc1[2];
+ float GRhighDrc2[2];
+ float GRmidDrc1[2];
+ float GRmidDrc2[2];
+ float GRlowDrc1[2];
+ float GRlowDrc2[2];
+ float GRpostDrc1[2];
+ float GRpostDrc2[2];
+ float GRblDrc[2];
+};
+struct Tfa98xx_StateInfo {
+ /* SpeakerBoost State */
+ float agcGain; /* Current AGC Gain value */
+ float limGain; /* Current Limiter Gain value */
+ float sMax; /* Current Clip/Lim threshold */
+ int T; /* Current Speaker Temperature value */
+ int statusFlag; /* Masked bit word */
+ float X1; /* estimated excursion caused by Spkrboost gain ctrl */
+ float X2; /* estimated excursion caused by manual gain setting */
+ float Re; /* Loudspeaker blocked resistance */
+ /* Framework state */
+ /* increments each time a MIPS problem is detected on the DSP */
+ int shortOnMips;
+ struct Tfa98xx_DrcStateInfo drcState; /* DRC state, when enabled */
+};
+
+typedef struct TfaMsg {
+ uint8_t msg_size;
+ unsigned char cmdId[3];
+ int data[9];
+} TfaMsg_t;
+
+typedef struct tfa_vstep_msg {
+ int fw_version;
+ uint8_t no_of_vsteps;
+ uint16_t reg_no;
+ uint8_t *msg_reg;
+ uint8_t msg_no;
+ uint32_t algo_param_length;
+ uint8_t *msg_algo_param;
+ uint32_t filter_coef_length;
+ uint8_t *msg_filter_coef;
+ uint32_t mbdrc_length;
+ uint8_t *msg_mbdrc;
+} tfa_vstep_msg_t;
+
+typedef struct TfaGroup {
+ uint8_t msg_size;
+ uint8_t profileId[64];
+} TfaGroup_t;
+
+
+struct Tfa98xx_Memtrack_data {
+ int length;
+ float mValues[MEMTRACK_MAX_WORDS];
+ int mAdresses[MEMTRACK_MAX_WORDS];
+ int trackers[MEMTRACK_MAX_WORDS];
+ int scalingFactor[MEMTRACK_MAX_WORDS];
+};
+
+/* possible memory values for DMEM in CF_CONTROLs */
+enum Tfa98xx_DMEM {
+ Tfa98xx_DMEM_ERR = -1,
+ Tfa98xx_DMEM_PMEM = 0,
+ Tfa98xx_DMEM_XMEM = 1,
+ Tfa98xx_DMEM_YMEM = 2,
+ Tfa98xx_DMEM_IOMEM = 3,
+};
+
+/**
+ * lookup the device type and return the family type
+ */
+int tfa98xx_dev2family(int dev_type);
+
+/**
+ * register definition structure
+ */
+struct regdef {
+ unsigned char offset; /**< subaddress offset */
+ unsigned short pwronDefault; /**< register contents after poweron */
+ unsigned short pwronTestmask; /**< mask of bits not test */
+ char *name; /**< short register name */
+};
+
+enum Tfa98xx_DMEM tfa98xx_filter_mem(struct tfa_device *tfa, int filter_index, unsigned short *address, int channel);
+
+/**
+ * Load the default HW settings in the device
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa98xx_init(struct tfa_device *tfa);
+
+/**
+ * If needed, this function can be used to get a text version of the status ID code
+ * @param status the given status ID code
+ * @return the I2C status ID string
+ */
+const char *tfa98xx_get_i2c_status_id_string(int status);
+
+/* control the powerdown bit
+ * @param tfa the device struct pointer
+ * @param powerdown must be 1 or 0
+ */
+enum Tfa98xx_Error tfa98xx_powerdown(struct tfa_device *tfa, int powerdown);
+
+/* indicates on which channel of DATAI2 the gain from the IC is set
+ * @param tfa the device struct pointer
+ * @param gain_sel, see Tfa98xx_StereoGainSel_t
+ */
+enum Tfa98xx_Error tfa98xx_select_stereo_gain_channel(struct tfa_device *tfa,
+ enum Tfa98xx_StereoGainSel gain_sel);
+
+/**
+ * set the mtp with user controllable values
+ * @param tfa the device struct pointer
+ * @param value to be written
+ * @param mask to be applied toi the bits affected
+ */
+enum Tfa98xx_Error tfa98xx_set_mtp(struct tfa_device *tfa, uint16_t value, uint16_t mask);
+enum Tfa98xx_Error tfa98xx_get_mtp(struct tfa_device *tfa, uint16_t *value);
+
+/**
+ * lock or unlock KEY2
+ * lock = 1 will lock
+ * lock = 0 will unlock
+ * note that on return all the hidden key will be off
+ */
+void tfa98xx_key2(struct tfa_device *tfa, int lock);
+
+int tfa_calibrate(struct tfa_device *tfa) ;
+void tfa98xx_set_exttemp(struct tfa_device *tfa, short ext_temp);
+short tfa98xx_get_exttemp(struct tfa_device *tfa);
+
+/* control the volume of the DSP
+ * @param vol volume in bit field. It must be between 0 and 255
+ */
+enum Tfa98xx_Error tfa98xx_set_volume_level(struct tfa_device *tfa,
+ unsigned short vol);
+
+/* set the input channel to use
+ * @param channel see Tfa98xx_Channel_t enumeration
+ */
+enum Tfa98xx_Error tfa98xx_select_channel(struct tfa_device *tfa,
+ enum Tfa98xx_Channel channel);
+
+/* set the mode for normal or receiver mode
+ * @param mode see Tfa98xx_Mode enumeration
+ */
+enum Tfa98xx_Error tfa98xx_select_mode(struct tfa_device *tfa, enum Tfa98xx_Mode mode );
+
+/* mute/unmute the audio
+ * @param mute see Tfa98xx_Mute_t enumeration
+ */
+enum Tfa98xx_Error tfa98xx_set_mute(struct tfa_device *tfa,
+ enum Tfa98xx_Mute mute);
+
+/*
+ * tfa_supported_speakers - required for SmartStudio initialization
+ * returns the number of the supported speaker count
+ */
+enum Tfa98xx_Error tfa_supported_speakers(struct tfa_device *tfa, int* spkr_count);
+
+/**
+* Return the tfa revision
+*/
+void tfa98xx_rev(int *major, int *minor, int *revision);
+
+/*
+ * Return the feature bits from MTP and cnt file for comparison
+ */
+enum Tfa98xx_Error
+tfa98xx_compare_features(struct tfa_device *tfa, int features_from_MTP[3], int features_from_cnt[3]);
+
+/*
+ * return feature bits
+ */
+enum Tfa98xx_Error
+tfa98xx_dsp_get_sw_feature_bits(struct tfa_device *tfa, int features[2]);
+enum Tfa98xx_Error
+tfa98xx_dsp_get_hw_feature_bits(struct tfa_device *tfa, int *features);
+
+/*
+ * tfa98xx_supported_saam
+ * returns the speaker as microphone feature
+ * @param saam enum pointer
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_supported_saam(struct tfa_device *tfa, enum Tfa98xx_saam *saam);
+
+/* load the tables to the DSP
+ * called after patch load is done
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_dsp_write_tables(struct tfa_device *tfa, int sample_rate);
+
+
+/* set or clear DSP reset signal
+ * @param new state
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_dsp_reset(struct tfa_device *tfa, int state);
+
+/* check the state of the DSP subsystem
+ * return ready = 1 when clocks are stable to allow safe DSP subsystem access
+ * @param tfa the device struct pointer
+ * @param ready pointer to state flag, non-zero if clocks are not stable
+ * @return error code
+ */
+enum Tfa98xx_Error tfa98xx_dsp_system_stable(struct tfa_device *tfa, int *ready);
+
+enum Tfa98xx_Error tfa98xx_auto_copy_mtp_to_iic(struct tfa_device *tfa);
+
+/**
+ * check the state of the DSP coolflux
+ * @param tfa the device struct pointer
+ * @return the value of CFE
+ */
+int tfa_cf_enabled(struct tfa_device *tfa);
+
+/* The following functions can only be called when the DSP is running
+ * - I2S clock must be active,
+ * - IC must be in operating mode
+ */
+
+/**
+ * patch the ROM code of the DSP
+ * @param tfa the device struct pointer
+ * @param patchLength the number of bytes of patchBytes
+ * @param patchBytes pointer to the bytes to patch
+ */
+enum Tfa98xx_Error tfa_dsp_patch(struct tfa_device *tfa,
+ int patchLength,
+ const unsigned char *patchBytes);
+
+/**
+ * load explicitly the speaker parameters in case of free speaker,
+ * or when using a saved speaker model
+ */
+enum Tfa98xx_Error tfa98xx_dsp_write_speaker_parameters(
+ struct tfa_device *tfa,
+ int length,
+ const unsigned char *pSpeakerBytes);
+
+/**
+ * read the speaker parameters as used by the SpeakerBoost processing
+ */
+enum Tfa98xx_Error tfa98xx_dsp_read_speaker_parameters(
+ struct tfa_device *tfa,
+ int length,
+ unsigned char *pSpeakerBytes);
+
+/**
+ * read the current status of the DSP, typically used for development,
+ * not essential to be used in a product
+ */
+enum Tfa98xx_Error tfa98xx_dsp_get_state_info(
+ struct tfa_device *tfa,
+ unsigned char bytes[],
+ unsigned int *statesize);
+
+/**
+ * Check whether the DSP supports DRC
+ * pbSupportDrc=1 when DSP supports DRC,
+ * pbSupportDrc=0 when DSP doesn't support it
+ */
+enum Tfa98xx_Error tfa98xx_dsp_support_drc(struct tfa_device *tfa,
+ int *pbSupportDrc);
+
+enum Tfa98xx_Error
+tfa98xx_dsp_support_framework(struct tfa_device *tfa, int *pbSupportFramework);
+
+/**
+ * read the speaker excursion model as used by SpeakerBoost processing
+ */
+enum Tfa98xx_Error tfa98xx_dsp_read_excursion_model(
+ struct tfa_device *tfa,
+ int length,
+ unsigned char *pSpeakerBytes);
+
+/**
+ * load all the parameters for a preset from a file
+ */
+enum Tfa98xx_Error tfa98xx_dsp_write_preset(struct tfa_device *tfa,
+ int length, const unsigned char
+ *pPresetBytes);
+
+/**
+ * wrapper for dsp_msg that adds opcode and only writes
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ const unsigned char data[]);
+
+/**
+ * wrapper for dsp_msg that writes opcode and reads back the data
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_write_read(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[]);
+
+/**
+ * wrapper for dsp_msg that adds opcode and 3 bytes required for coefs
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_coefs(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int num_bytes,
+ unsigned char data[]);
+
+/**
+ * wrapper for dsp_msg that adds opcode and 3 bytes required for MBDrcDynamics
+ */
+enum Tfa98xx_Error tfa_dsp_cmd_id_MBDrc_dynamics(struct tfa_device *tfa,
+ unsigned char module_id,
+ unsigned char param_id, int index_subband,
+ int num_bytes, unsigned char data[]);
+
+/**
+ * Disable a certain biquad.
+ * @param tfa the device struct pointer
+ * @param biquad_index: 1-10 of the biquad that needs to be adressed
+*/
+enum Tfa98xx_Error Tfa98xx_DspBiquad_Disable(struct tfa_device *tfa,
+ int biquad_index);
+
+/**
+ * fill the calibration value as milli ohms in the struct
+ * assume that the device has been calibrated
+ */
+enum Tfa98xx_Error
+tfa_dsp_get_calibration_impedance(struct tfa_device *tfa);
+
+/*
+ * return the mohm value
+ */
+int tfa_get_calibration_info(struct tfa_device *tfa, int channel);
+
+/*
+ * return sign extended tap pattern
+ */
+int tfa_get_tap_pattern(struct tfa_device *tfa);
+
+/**
+ * Reads a number of words from dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress write address to set in address register
+ * @param pValue pointer to read data
+*/
+enum Tfa98xx_Error tfa98xx_read_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short *pValue);
+
+/**
+ * Reads a number of words from dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress write address to set in address register
+ * @param value value to write int the memory
+*/
+enum Tfa98xx_Error tfa98xx_write_register16(struct tfa_device *tfa,
+ unsigned char subaddress,
+ unsigned short value);
+
+/**
+ * Intialise the dsp
+ * @param tfa the device struct pointer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_init_dsp(struct tfa_device *tfa);
+
+/**
+ * Get the status of the external DSP
+ * @param tfa the device struct pointer
+ * @return status
+*/
+int tfa98xx_get_dsp_status(struct tfa_device *tfa);
+
+/**
+ * Write a command message (RPC) to the dsp
+ * @param tfa the device struct pointer
+ * @param num_bytes command buffer size in bytes
+ * @param command_buffer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_write_dsp(struct tfa_device *tfa, int num_bytes, const char *command_buffer);
+
+/**
+ * Read the result from the last message from the dsp
+ * @param tfa the device struct pointer
+ * @param num_bytes result buffer size in bytes
+ * @param result_buffer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_read_dsp(struct tfa_device *tfa, int num_bytes, unsigned char *result_buffer);
+
+/**
+ * Write a command message (RPC) to the dsp and return the result
+ * @param tfa the device struct pointer
+ * @param command_length command buffer size in bytes
+ * @param command_buffer command buffer
+ * @param result_length result buffer size in bytes
+ * @param result_buffer result buffer
+ * @return tfa error enum
+*/
+enum Tfa98xx_Error
+tfa98xx_writeread_dsp(struct tfa_device *tfa, int command_length, void *command_buffer,
+ int result_length, void *result_buffer);
+
+/**
+ * Reads a number of words from dsp memory
+ * @param tfa the device struct pointer
+ * @param start_offset offset from where to start reading
+ * @param num_words number of words to read
+ * @param pValues pointer to read data
+*/
+enum Tfa98xx_Error tfa98xx_dsp_read_mem(struct tfa_device *tfa,
+ unsigned int start_offset,
+ int num_words, int *pValues);
+/**
+ * Write a value to dsp memory
+ * @param tfa the device struct pointer
+ * @param address write address to set in address register
+ * @param value value to write int the memory
+ * @param memtype type of memory to write to
+*/
+enum Tfa98xx_Error tfa98xx_dsp_write_mem_word(struct tfa_device *tfa,
+ unsigned short address, int value, int memtype);
+
+/**
+ * Read data from dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress write address to set in address register
+ * @param num_bytes number of bytes to read from dsp
+ * @param data the unsigned char buffer to read data into
+*/
+enum Tfa98xx_Error tfa98xx_read_data(struct tfa_device *tfa,
+ unsigned char subaddress,
+ int num_bytes, unsigned char data[]);
+
+/**
+ * Write all the bytes specified by num_bytes and data to dsp memory
+ * @param tfa the device struct pointer
+ * @param subaddress the subaddress to write to
+ * @param num_bytes number of bytes to write
+ * @param data actual data to write
+*/
+enum Tfa98xx_Error tfa98xx_write_data(struct tfa_device *tfa,
+ unsigned char subaddress,
+ int num_bytes,
+ const unsigned char data[]);
+
+enum Tfa98xx_Error tfa98xx_write_raw(struct tfa_device *tfa,
+ int num_bytes,
+ const unsigned char data[]);
+
+/* support for converting error codes into text */
+const char *tfa98xx_get_error_string(enum Tfa98xx_Error error);
+
+/**
+ * convert signed 24 bit integers to 32bit aligned bytes
+ * input: data contains "num_bytes/3" int24 elements
+ * output: bytes contains "num_bytes" byte elements
+ * @param num_data length of the input data array
+ * @param data input data as integer array
+ * @param bytes output data as unsigned char array
+*/
+void tfa98xx_convert_data2bytes(int num_data, const int data[],
+ unsigned char bytes[]);
+
+/**
+ * convert memory bytes to signed 24 bit integers
+ * input: bytes contains "num_bytes" byte elements
+ * output: data contains "num_bytes/3" int24 elements
+ * @param num_bytes length of the input data array
+ * @param bytes input data as unsigned char array
+ * @param data output data as integer array
+*/
+void tfa98xx_convert_bytes2data(int num_bytes, const unsigned char bytes[],
+ int data[]);
+
+/**
+ * Read a part of the dsp memory
+ * @param tfa the device struct pointer
+ * @param memoryType indicator to the memory type
+ * @param offset from where to start reading
+ * @param length the number of bytes to read
+ * @param bytes output data as unsigned char array
+*/
+enum Tfa98xx_Error tfa98xx_dsp_get_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, unsigned char bytes[]);
+
+/**
+ * Write a value to the dsp memory
+ * @param tfa the device struct pointer
+ * @param memoryType indicator to the memory type
+ * @param offset from where to start writing
+ * @param length the number of bytes to write
+ * @param value the value to write to the dsp
+*/
+enum Tfa98xx_Error tfa98xx_dsp_set_memory(struct tfa_device *tfa, int memoryType,
+ int offset, int length, int value);
+
+enum Tfa98xx_Error tfa98xx_dsp_write_config(struct tfa_device *tfa, int length, const unsigned char *p_config_bytes);
+enum Tfa98xx_Error tfa98xx_dsp_write_drc(struct tfa_device *tfa, int length, const unsigned char *p_drc_bytes);
+
+/**
+ * write/read raw msg functions :
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buf character buffer to write
+*/
+enum Tfa98xx_Error tfa_dsp_msg_rpc(struct tfa_device *tfa, int length, const char *buf);
+
+
+/**
+ * The wrapper functions to call the dsp msg, register and memory function for tfa or probus
+ */
+enum Tfa98xx_Error tfa_dsp_msg(struct tfa_device *tfa, int length, const char *buf);
+enum Tfa98xx_Error tfa_dsp_msg_read(struct tfa_device *tfa, int length, unsigned char *bytes);
+enum Tfa98xx_Error tfa_reg_write(struct tfa_device *tfa, unsigned char subaddress, unsigned short value);
+enum Tfa98xx_Error tfa_reg_read(struct tfa_device *tfa, unsigned char subaddress, unsigned short *value);
+enum Tfa98xx_Error tfa_mem_write(struct tfa_device *tfa, unsigned short address, int value, int memtype);
+enum Tfa98xx_Error tfa_mem_read(struct tfa_device *tfa, unsigned int start_offset, int num_words, int *pValues);
+
+enum Tfa98xx_Error tfa_dsp_partial_coefficients(struct tfa_device *tfa, uint8_t *prev, uint8_t *next);
+int tfa_is_94_N2_device(struct tfa_device *tfa);
+/**
+ * write/read raw msg functions:
+ * the buffer is provided in little endian format, each word occupying 3 bytes, length is in bytes.
+ * The functions will return immediately and do not not wait for DSP reponse.
+ * An ID is added to modify the command-ID
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buf character buffer to write
+ * @param cmdid command identifier
+*/
+enum Tfa98xx_Error tfa_dsp_msg_id(struct tfa_device *tfa, int length, const char *buf, uint8_t cmdid[3]);
+
+/**
+ * write raw dsp msg functions
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buffer character buffer to write
+*/
+enum Tfa98xx_Error tfa_dsp_msg_write(struct tfa_device *tfa, int length, const char *buffer);
+
+/**
+ * write raw dsp msg functions
+ * @param tfa the device struct pointer
+ * @param length length of the character buffer to write
+ * @param buffer character buffer to write
+ * @param cmdid command identifier
+*/
+enum Tfa98xx_Error tfa_dsp_msg_write_id(struct tfa_device *tfa, int length, const char *buffer, uint8_t cmdid[3]);
+
+/**
+ * status function used by tfa_dsp_msg() to retrieve command/msg status:
+ * return a <0 status of the DSP did not ACK.
+ * @param tfa the device struct pointer
+ * @param pRpcStatus status for remote processor communication
+*/
+enum Tfa98xx_Error tfa_dsp_msg_status(struct tfa_device *tfa, int *pRpcStatus);
+
+/**
+ * Read a message from dsp
+ * @param tfa the device struct pointer
+ * @param length number of bytes of the message
+ * @param bytes pointer to unsigned char buffer
+*/
+enum Tfa98xx_Error tfa_dsp_msg_read_rpc(struct tfa_device *tfa,int length, unsigned char *bytes);
+
+int tfa_set_bf(struct tfa_device *tfa, const uint16_t bf, const uint16_t value);
+int tfa_set_bf_volatile(struct tfa_device *tfa, const uint16_t bf, const uint16_t value);
+
+/**
+ * Get the value of a given bitfield
+ * @param tfa the device struct pointer
+ * @param bf the value indicating which bitfield
+ */
+int tfa_get_bf(struct tfa_device *tfa, const uint16_t bf);
+
+/**
+ * Set the value of a given bitfield
+ * @param bf the value indicating which bitfield
+ * @param bf_value the value of the bitfield
+ * @param p_reg_value a pointer to the register where to write the bitfield value
+ */
+int tfa_set_bf_value(const uint16_t bf, const uint16_t bf_value, uint16_t *p_reg_value);
+
+uint16_t tfa_get_bf_value(const uint16_t bf, const uint16_t reg_value);
+int tfa_write_reg(struct tfa_device *tfa, const uint16_t bf, const uint16_t reg_value);
+int tfa_read_reg(struct tfa_device *tfa, const uint16_t bf);
+
+/* bitfield */
+/**
+ * get the datasheet or bitfield name corresponding to the bitfield number
+ * @param num is the number for which to get the bitfield name
+ * @param rev is the device type
+ */
+char *tfaContBfName(uint16_t num, unsigned short rev);
+
+/**
+ * get the datasheet name corresponding to the bitfield number
+ * @param num is the number for which to get the bitfield name
+ * @param rev is the device type
+ */
+char *tfaContDsName(uint16_t num, unsigned short rev);
+
+/**
+ * get the bitfield name corresponding to the bitfield number
+ * @param num is the number for which to get the bitfield name
+ * @param rev is the device type
+ */
+char *tfaContBitName(uint16_t num, unsigned short rev);
+
+/**
+ * get the bitfield number corresponding to the bitfield name
+ * @param name is the bitfield name for which to get the bitfield number
+ * @param rev is the device type
+ */
+uint16_t tfaContBfEnum(const char *name, unsigned short rev);
+
+/**
+* get the bitfield number corresponding to the bitfield name, checks for all devices
+* @param name is the bitfield name for which to get the bitfield number
+ */
+uint16_t tfaContBfEnumAny(const char *name);
+
+#define TFA_FAM(tfa, fieldname) ((tfa->tfa_family == 1) ? TFA1_BF_##fieldname : TFA2_BF_##fieldname)
+#define TFA_FAM_FW(tfa, fwname) ((tfa->tfa_family == 1) ? TFA1_FW_##fwname : TFA2_FW_##fwname)
+#define TFA2_FAM_TDM(tfa, fieldname) (((tfa->rev & 0xff) == 0x94) ? TFA9894_BF_##fieldname : TFA2_BF_##fieldname)
+
+/* set/get bit fields to HW register*/
+#define TFA_SET_BF(tfa, fieldname, value) tfa_set_bf(tfa, TFA_FAM(tfa, fieldname), value)
+#define TFA_SET_BF_VOLATILE(tfa, fieldname, value) tfa_set_bf_volatile(tfa, TFA_FAM(tfa, fieldname), value)
+#define TFA_GET_BF(tfa, fieldname) tfa_get_bf(tfa, TFA_FAM(tfa, fieldname))
+
+
+/* set/get bit field in variable */
+#define TFA_SET_BF_VALUE(tfa, fieldname, bf_value, p_reg_value) tfa_set_bf_value(TFA_FAM(tfa, fieldname), bf_value, p_reg_value)
+#define TFA_GET_BF_VALUE(tfa, fieldname, reg_value) tfa_get_bf_value(TFA_FAM(tfa, fieldname), reg_value)
+
+/* write/read registers using a bit field name to determine the register address */
+#define TFA_WRITE_REG(tfa, fieldname, value) tfa_write_reg(tfa, TFA_FAM(tfa, fieldname), value)
+#define TFA_READ_REG(tfa, fieldname) tfa_read_reg(tfa, TFA_FAM(tfa, fieldname))
+
+/* FOR CALIBRATION RETRIES */
+#define TFA98XX_API_WAITRESULT_NTRIES 3000 // defined in API
+
+/**
+ * run the startup/init sequence and set ACS bit
+ * @param tfa the device struct pointer
+ * @param state the cold start state that is requested
+ */
+enum Tfa98xx_Error tfaRunColdboot(struct tfa_device *tfa, int state);
+enum Tfa98xx_Error tfaRunMute(struct tfa_device *tfa);
+enum Tfa98xx_Error tfaRunUnmute(struct tfa_device *tfa);
+
+/**
+ * wait for calibrateDone
+ * @param tfa the device struct pointer
+ * @param calibrateDone pointer to status of calibration
+ */
+enum Tfa98xx_Error tfaRunWaitCalibration(struct tfa_device *tfa, int *calibrateDone);
+
+/**
+ * run the startup/init sequence and set ACS bit
+ * @param tfa the device struct pointer
+ * @param profile the profile that should be loaded
+ */
+enum Tfa98xx_Error tfaRunColdStartup(struct tfa_device *tfa, int profile);
+
+/**
+ * this will load the patch witch will implicitly start the DSP
+ * if no patch is available the DPS is started immediately
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfaRunStartDSP(struct tfa_device *tfa);
+
+/**
+ * start the clocks and wait until the AMP is switching
+ * on return the DSP sub system will be ready for loading
+ * @param tfa the device struct pointer
+ * @param profile the profile that should be loaded on startup
+ */
+enum Tfa98xx_Error tfaRunStartup(struct tfa_device *tfa, int profile);
+
+/**
+ * start the maximus speakerboost algorithm
+ * this implies a full system startup when the system was not already started
+ * @param tfa the device struct pointer
+ * @param force indicates wether a full system startup should be allowed
+ * @param profile the profile that should be loaded
+ */
+enum Tfa98xx_Error tfaRunSpeakerBoost(struct tfa_device *tfa, int force, int profile);
+
+/**
+ * Startup the device and write all files from device and profile section
+ * @param tfa the device struct pointer
+ * @param force indicates wether a full system startup should be allowed
+ * @param profile the profile that should be loaded on speaker startup
+ */
+enum Tfa98xx_Error tfaRunSpeakerStartup(struct tfa_device *tfa, int force, int profile);
+
+/**
+ * Run calibration
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfaRunSpeakerCalibration(struct tfa_device *tfa);
+
+/**
+ * startup all devices. all step until patch loading is handled
+ * @param tfa the device struct pointer
+ */
+int tfaRunStartupAll(struct tfa_device *tfa);
+
+/**
+ * powerup the coolflux subsystem and wait for it
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa_cf_powerup(struct tfa_device *tfa);
+
+/*
+ * print the current device manager state
+ * @param tfa the device struct pointer
+ */
+enum Tfa98xx_Error tfa_show_current_state(struct tfa_device *tfa);
+
+/**
+ * Init registers and coldboot dsp
+ * @param tfa the device struct pointer
+ */
+int tfa_reset(struct tfa_device *tfa);
+
+/**
+ * Get profile from a register
+ * @param tfa the device struct pointer
+ */
+int tfa_dev_get_swprof(struct tfa_device *tfa);
+
+/**
+ * Save profile in a register
+ */
+int tfa_dev_set_swprof(struct tfa_device *tfa, unsigned short new_value);
+
+int tfa_dev_get_swvstep(struct tfa_device *tfa);
+
+int tfa_dev_set_swvstep(struct tfa_device *tfa, unsigned short new_value);
+
+int tfa_needs_reset(struct tfa_device *tfa);
+
+int tfa_is_cold(struct tfa_device *tfa);
+
+void tfa_set_query_info(struct tfa_device *tfa);
+
+int tfa_get_pga_gain(struct tfa_device *tfa);
+int tfa_set_pga_gain(struct tfa_device *tfa, uint16_t value);
+int tfa_get_noclk(struct tfa_device *tfa);
+
+/**
+ * Status of used for monitoring
+ * @param tfa the device struct pointer
+ * @return tfa error enum
+ */
+
+enum Tfa98xx_Error tfa_status(struct tfa_device *tfa);
+
+/*
+ * function overload for flag_mtp_busy
+ */
+int tfa_dev_get_mtpb(struct tfa_device *tfa);
+
+enum Tfa98xx_Error tfaGetFwApiVersion(struct tfa_device *tfa, unsigned char *pFirmwareVersion);
+#ifdef __cplusplus
+}
+#endif
+#endif /* TFA_SERVICE_H */
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c
index 5da1934527f..c5b72786178 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -65,6 +65,7 @@ struct wcd_mbhc {
bool extn_cable_hph_rem;
bool force_linein;
bool impedance_detect;
+ bool micbias_enabled;
unsigned long event_state;
unsigned long jiffies_atreport;
/* impedance of hphl and hphr */
@@ -193,7 +194,7 @@ int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
* make sure current source is enabled so as to detect
* button press/release events
*/
- if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) {
+ if (mbhc->mbhc_cb->mbhc_micbias_control && mbhc->micbias_enabled) {
if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN))
wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
}
@@ -273,8 +274,10 @@ static void wcd_micbias_disable(struct wcd_mbhc *mbhc)
{
struct snd_soc_component *component = mbhc->component;
- if (mbhc->mbhc_cb->mbhc_micbias_control)
+ if (mbhc->mbhc_cb->mbhc_micbias_control && mbhc->micbias_enabled) {
mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
+ mbhc->micbias_enabled = false;
+ }
if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(component, MIC_BIAS_2, false);
@@ -502,6 +505,7 @@ static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc)
if (mbhc->mbhc_cb->mbhc_micbias_control) {
mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2,
MICB_ENABLE);
+ mbhc->micbias_enabled = true;
wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
}
}
@@ -1235,8 +1239,10 @@ static void wcd_correct_swch_plug(struct work_struct *work)
wcd_mbhc_adc_update_fsm_source(mbhc, plug_type);
exit:
- if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/)
+ if (mbhc->mbhc_cb->mbhc_micbias_control && mbhc->micbias_enabled) {
mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
+ mbhc->micbias_enabled = false;
+ }
/*
* If plug type is corrected from special headset to headphone,
@@ -1464,6 +1470,7 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
mbhc->mbhc_cb = mbhc_cb;
mbhc->fields = fields;
mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
+ mbhc->micbias_enabled = false;
if (mbhc_cb->compute_impedance)
mbhc->impedance_detect = impedance_det_en;
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 1b6e376f383..70a410e61f7 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -3014,6 +3014,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,
@@ -3037,6 +3038,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,
@@ -5891,7 +5894,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/qcom/Kconfig b/sound/soc/qcom/Kconfig
index e7b00d1d9e9..c8356f99d98 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..9c29abab0fd
--- /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)
+ strlcpy(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 252a0f0819b..09c0b445da6 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;
diff --git a/tools/arch/parisc/include/uapi/asm/errno.h b/tools/arch/parisc/include/uapi/asm/errno.h
index 87245c58478..8d94739d75c 100644
--- a/tools/arch/parisc/include/uapi/asm/errno.h
+++ b/tools/arch/parisc/include/uapi/asm/errno.h
@@ -75,7 +75,6 @@
/* We now return you to your regularly scheduled HPUX. */
-#define ENOSYM 215 /* symbol does not exist in executable */
#define ENOTSOCK 216 /* Socket operation on non-socket */
#define EDESTADDRREQ 217 /* Destination address required */
#define EMSGSIZE 218 /* Message too long */
@@ -101,7 +100,6 @@
#define ETIMEDOUT 238 /* Connection timed out */
#define ECONNREFUSED 239 /* Connection refused */
#define EREFUSED ECONNREFUSED /* for HP's NFS apparently */
-#define EREMOTERELEASE 240 /* Remote peer released connection */
#define EHOSTDOWN 241 /* Host is down */
#define EHOSTUNREACH 242 /* No route to host */
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 264eeb9c46a..318e2dad27e 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1421,7 +1421,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
if (error)
goto setval_error;
- if (new_val->addr_family == ADDR_FAMILY_IPV6) {
+ if (new_val->addr_family & ADDR_FAMILY_IPV6) {
error = fprintf(nmfile, "\n[ipv6]\n");
if (error < 0)
goto setval_error;
@@ -1455,14 +1455,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
if (error < 0)
goto setval_error;
- error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
- if (error < 0)
- goto setval_error;
-
- error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
- if (error < 0)
- goto setval_error;
+ /* we do not want ipv4 addresses in ipv6 section and vice versa */
+ if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
+ error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
+ if (error < 0)
+ goto setval_error;
+ }
+ if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
+ error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
+ if (error < 0)
+ goto setval_error;
+ }
fclose(nmfile);
fclose(ifcfg_file);
diff --git a/tools/hv/hv_set_ifconfig.sh b/tools/hv/hv_set_ifconfig.sh
index ae5a7a8249a..440a91b3582 100755
--- a/tools/hv/hv_set_ifconfig.sh
+++ b/tools/hv/hv_set_ifconfig.sh
@@ -53,7 +53,7 @@
# or "manual" if no boot-time protocol should be used)
#
# address1=ipaddr1/plen
-# address=ipaddr2/plen
+# address2=ipaddr2/plen
#
# gateway=gateway1;gateway2
#
@@ -61,7 +61,7 @@
#
# [ipv6]
# address1=ipaddr1/plen
-# address2=ipaddr1/plen
+# address2=ipaddr2/plen
#
# gateway=gateway1;gateway2
#
diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps
index 64d139400db..3110f84dd02 100644
--- a/tools/net/ynl/Makefile.deps
+++ b/tools/net/ynl/Makefile.deps
@@ -18,4 +18,4 @@ CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h)
CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h)
CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h)
CFLAGS_netdev:=$(call get_hdr_inc,_LINUX_NETDEV_H,netdev.h)
-CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_H,nfsd.h)
+CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_NETLINK_H,nfsd_netlink.h)
diff --git a/tools/net/ynl/generated/devlink-user.c b/tools/net/ynl/generated/devlink-user.c
index bc5065bd99b..c12ca87ca2b 100644
--- a/tools/net/ynl/generated/devlink-user.c
+++ b/tools/net/ynl/generated/devlink-user.c
@@ -15,7 +15,7 @@
/* Enums */
static const char * const devlink_op_strmap[] = {
[3] = "get",
- [7] = "port-get",
+ // skip "port-get", duplicate reply value
[DEVLINK_CMD_PORT_NEW] = "port-new",
[13] = "sb-get",
[17] = "sb-pool-get",
diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py
index c4003a83cd5..3bd6b928c14 100755
--- a/tools/net/ynl/ynl-gen-c.py
+++ b/tools/net/ynl/ynl-gen-c.py
@@ -1505,6 +1505,12 @@ def put_op_name(family, cw):
cw.block_start(line=f"static const char * const {map_name}[] =")
for op_name, op in family.msgs.items():
if op.rsp_value:
+ # Make sure we don't add duplicated entries, if multiple commands
+ # produce the same response in legacy families.
+ if family.rsp_by_value[op.rsp_value] != op:
+ cw.p(f'// skip "{op_name}", duplicate reply value')
+ continue
+
if op.req_value == op.rsp_value:
cw.p(f'[{op.enum_name}] = "{op_name}",')
else:
diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py
index 4a356a70678..40ad221e888 100755
--- a/tools/power/pm-graph/sleepgraph.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -4151,7 +4151,7 @@ def parseKernelLog(data):
elif(re.match('Enabling non-boot CPUs .*', msg)):
# start of first cpu resume
cpu_start = ktime
- elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)) \
+ elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) \
or re.match('psci: CPU(?P<cpu>[0-9]*) killed.*', msg)):
# end of a cpu suspend, start of the next
m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)
diff --git a/tools/testing/selftests/arm64/fp/za-fork.c b/tools/testing/selftests/arm64/fp/za-fork.c
index b86cb104949..587b9464822 100644
--- a/tools/testing/selftests/arm64/fp/za-fork.c
+++ b/tools/testing/selftests/arm64/fp/za-fork.c
@@ -85,7 +85,7 @@ int main(int argc, char **argv)
*/
ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0);
if (ret >= 0) {
- ksft_test_result(fork_test(), "fork_test");
+ ksft_test_result(fork_test(), "fork_test\n");
} else {
ksft_print_msg("SME not supported\n");
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
index 6ee22c3b251..518f143c5b0 100644
--- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
+++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
@@ -24,6 +24,7 @@
#include "test_progs.h"
#include "network_helpers.h"
+#include "netlink_helpers.h"
#include "test_tc_neigh_fib.skel.h"
#include "test_tc_neigh.skel.h"
#include "test_tc_peer.skel.h"
@@ -110,11 +111,17 @@ static void netns_setup_namespaces_nofail(const char *verb)
}
}
+enum dev_mode {
+ MODE_VETH,
+ MODE_NETKIT,
+};
+
struct netns_setup_result {
- int ifindex_veth_src;
- int ifindex_veth_src_fwd;
- int ifindex_veth_dst;
- int ifindex_veth_dst_fwd;
+ enum dev_mode dev_mode;
+ int ifindex_src;
+ int ifindex_src_fwd;
+ int ifindex_dst;
+ int ifindex_dst_fwd;
};
static int get_ifaddr(const char *name, char *ifaddr)
@@ -137,58 +144,110 @@ static int get_ifaddr(const char *name, char *ifaddr)
return 0;
}
+static int create_netkit(int mode, char *prim, char *peer)
+{
+ struct rtattr *linkinfo, *data, *peer_info;
+ struct rtnl_handle rth = { .fd = -1 };
+ const char *type = "netkit";
+ struct {
+ struct nlmsghdr n;
+ struct ifinfomsg i;
+ char buf[1024];
+ } req = {};
+ int err;
+
+ err = rtnl_open(&rth, 0);
+ if (!ASSERT_OK(err, "open_rtnetlink"))
+ return err;
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
+ req.n.nlmsg_type = RTM_NEWLINK;
+ req.i.ifi_family = AF_UNSPEC;
+
+ addattr_l(&req.n, sizeof(req), IFLA_IFNAME, prim, strlen(prim));
+ linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
+ addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type));
+ data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA);
+ addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode);
+ peer_info = addattr_nest(&req.n, sizeof(req), IFLA_NETKIT_PEER_INFO);
+ req.n.nlmsg_len += sizeof(struct ifinfomsg);
+ addattr_l(&req.n, sizeof(req), IFLA_IFNAME, peer, strlen(peer));
+ addattr_nest_end(&req.n, peer_info);
+ addattr_nest_end(&req.n, data);
+ addattr_nest_end(&req.n, linkinfo);
+
+ err = rtnl_talk(&rth, &req.n, NULL);
+ ASSERT_OK(err, "talk_rtnetlink");
+ rtnl_close(&rth);
+ return err;
+}
+
static int netns_setup_links_and_routes(struct netns_setup_result *result)
{
struct nstoken *nstoken = NULL;
- char veth_src_fwd_addr[IFADDR_STR_LEN+1] = {};
-
- SYS(fail, "ip link add veth_src type veth peer name veth_src_fwd");
- SYS(fail, "ip link add veth_dst type veth peer name veth_dst_fwd");
+ char src_fwd_addr[IFADDR_STR_LEN+1] = {};
+ int err;
- SYS(fail, "ip link set veth_dst_fwd address " MAC_DST_FWD);
- SYS(fail, "ip link set veth_dst address " MAC_DST);
+ if (result->dev_mode == MODE_VETH) {
+ SYS(fail, "ip link add src type veth peer name src_fwd");
+ SYS(fail, "ip link add dst type veth peer name dst_fwd");
+
+ SYS(fail, "ip link set dst_fwd address " MAC_DST_FWD);
+ SYS(fail, "ip link set dst address " MAC_DST);
+ } else if (result->dev_mode == MODE_NETKIT) {
+ err = create_netkit(NETKIT_L3, "src", "src_fwd");
+ if (!ASSERT_OK(err, "create_ifindex_src"))
+ goto fail;
+ err = create_netkit(NETKIT_L3, "dst", "dst_fwd");
+ if (!ASSERT_OK(err, "create_ifindex_dst"))
+ goto fail;
+ }
- if (get_ifaddr("veth_src_fwd", veth_src_fwd_addr))
+ if (get_ifaddr("src_fwd", src_fwd_addr))
goto fail;
- result->ifindex_veth_src = if_nametoindex("veth_src");
- if (!ASSERT_GT(result->ifindex_veth_src, 0, "ifindex_veth_src"))
+ result->ifindex_src = if_nametoindex("src");
+ if (!ASSERT_GT(result->ifindex_src, 0, "ifindex_src"))
goto fail;
- result->ifindex_veth_src_fwd = if_nametoindex("veth_src_fwd");
- if (!ASSERT_GT(result->ifindex_veth_src_fwd, 0, "ifindex_veth_src_fwd"))
+ result->ifindex_src_fwd = if_nametoindex("src_fwd");
+ if (!ASSERT_GT(result->ifindex_src_fwd, 0, "ifindex_src_fwd"))
goto fail;
- result->ifindex_veth_dst = if_nametoindex("veth_dst");
- if (!ASSERT_GT(result->ifindex_veth_dst, 0, "ifindex_veth_dst"))
+ result->ifindex_dst = if_nametoindex("dst");
+ if (!ASSERT_GT(result->ifindex_dst, 0, "ifindex_dst"))
goto fail;
- result->ifindex_veth_dst_fwd = if_nametoindex("veth_dst_fwd");
- if (!ASSERT_GT(result->ifindex_veth_dst_fwd, 0, "ifindex_veth_dst_fwd"))
+ result->ifindex_dst_fwd = if_nametoindex("dst_fwd");
+ if (!ASSERT_GT(result->ifindex_dst_fwd, 0, "ifindex_dst_fwd"))
goto fail;
- SYS(fail, "ip link set veth_src netns " NS_SRC);
- SYS(fail, "ip link set veth_src_fwd netns " NS_FWD);
- SYS(fail, "ip link set veth_dst_fwd netns " NS_FWD);
- SYS(fail, "ip link set veth_dst netns " NS_DST);
+ SYS(fail, "ip link set src netns " NS_SRC);
+ SYS(fail, "ip link set src_fwd netns " NS_FWD);
+ SYS(fail, "ip link set dst_fwd netns " NS_FWD);
+ SYS(fail, "ip link set dst netns " NS_DST);
/** setup in 'src' namespace */
nstoken = open_netns(NS_SRC);
if (!ASSERT_OK_PTR(nstoken, "setns src"))
goto fail;
- SYS(fail, "ip addr add " IP4_SRC "/32 dev veth_src");
- SYS(fail, "ip addr add " IP6_SRC "/128 dev veth_src nodad");
- SYS(fail, "ip link set dev veth_src up");
+ SYS(fail, "ip addr add " IP4_SRC "/32 dev src");
+ SYS(fail, "ip addr add " IP6_SRC "/128 dev src nodad");
+ SYS(fail, "ip link set dev src up");
- SYS(fail, "ip route add " IP4_DST "/32 dev veth_src scope global");
- SYS(fail, "ip route add " IP4_NET "/16 dev veth_src scope global");
- SYS(fail, "ip route add " IP6_DST "/128 dev veth_src scope global");
+ SYS(fail, "ip route add " IP4_DST "/32 dev src scope global");
+ SYS(fail, "ip route add " IP4_NET "/16 dev src scope global");
+ SYS(fail, "ip route add " IP6_DST "/128 dev src scope global");
- SYS(fail, "ip neigh add " IP4_DST " dev veth_src lladdr %s",
- veth_src_fwd_addr);
- SYS(fail, "ip neigh add " IP6_DST " dev veth_src lladdr %s",
- veth_src_fwd_addr);
+ if (result->dev_mode == MODE_VETH) {
+ SYS(fail, "ip neigh add " IP4_DST " dev src lladdr %s",
+ src_fwd_addr);
+ SYS(fail, "ip neigh add " IP6_DST " dev src lladdr %s",
+ src_fwd_addr);
+ }
close_netns(nstoken);
@@ -201,15 +260,15 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
* needs v4 one in order to start ARP probing. IP4_NET route is added
* to the endpoints so that the ARP processing will reply.
*/
- SYS(fail, "ip addr add " IP4_SLL "/32 dev veth_src_fwd");
- SYS(fail, "ip addr add " IP4_DLL "/32 dev veth_dst_fwd");
- SYS(fail, "ip link set dev veth_src_fwd up");
- SYS(fail, "ip link set dev veth_dst_fwd up");
+ SYS(fail, "ip addr add " IP4_SLL "/32 dev src_fwd");
+ SYS(fail, "ip addr add " IP4_DLL "/32 dev dst_fwd");
+ SYS(fail, "ip link set dev src_fwd up");
+ SYS(fail, "ip link set dev dst_fwd up");
- SYS(fail, "ip route add " IP4_SRC "/32 dev veth_src_fwd scope global");
- SYS(fail, "ip route add " IP6_SRC "/128 dev veth_src_fwd scope global");
- SYS(fail, "ip route add " IP4_DST "/32 dev veth_dst_fwd scope global");
- SYS(fail, "ip route add " IP6_DST "/128 dev veth_dst_fwd scope global");
+ SYS(fail, "ip route add " IP4_SRC "/32 dev src_fwd scope global");
+ SYS(fail, "ip route add " IP6_SRC "/128 dev src_fwd scope global");
+ SYS(fail, "ip route add " IP4_DST "/32 dev dst_fwd scope global");
+ SYS(fail, "ip route add " IP6_DST "/128 dev dst_fwd scope global");
close_netns(nstoken);
@@ -218,16 +277,18 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
if (!ASSERT_OK_PTR(nstoken, "setns dst"))
goto fail;
- SYS(fail, "ip addr add " IP4_DST "/32 dev veth_dst");
- SYS(fail, "ip addr add " IP6_DST "/128 dev veth_dst nodad");
- SYS(fail, "ip link set dev veth_dst up");
+ SYS(fail, "ip addr add " IP4_DST "/32 dev dst");
+ SYS(fail, "ip addr add " IP6_DST "/128 dev dst nodad");
+ SYS(fail, "ip link set dev dst up");
- SYS(fail, "ip route add " IP4_SRC "/32 dev veth_dst scope global");
- SYS(fail, "ip route add " IP4_NET "/16 dev veth_dst scope global");
- SYS(fail, "ip route add " IP6_SRC "/128 dev veth_dst scope global");
+ SYS(fail, "ip route add " IP4_SRC "/32 dev dst scope global");
+ SYS(fail, "ip route add " IP4_NET "/16 dev dst scope global");
+ SYS(fail, "ip route add " IP6_SRC "/128 dev dst scope global");
- SYS(fail, "ip neigh add " IP4_SRC " dev veth_dst lladdr " MAC_DST_FWD);
- SYS(fail, "ip neigh add " IP6_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+ if (result->dev_mode == MODE_VETH) {
+ SYS(fail, "ip neigh add " IP4_SRC " dev dst lladdr " MAC_DST_FWD);
+ SYS(fail, "ip neigh add " IP6_SRC " dev dst lladdr " MAC_DST_FWD);
+ }
close_netns(nstoken);
@@ -293,23 +354,23 @@ static int netns_load_bpf(const struct bpf_program *src_prog,
const struct bpf_program *chk_prog,
const struct netns_setup_result *setup_result)
{
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src_fwd);
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_src_fwd);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd);
int err;
- /* tc qdisc add dev veth_src_fwd clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_src_fwd, setup_result->ifindex_veth_src_fwd);
- /* tc filter add dev veth_src_fwd ingress bpf da src_prog */
- XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS, src_prog, 0);
- /* tc filter add dev veth_src_fwd egress bpf da chk_prog */
- XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS, chk_prog, 0);
+ /* tc qdisc add dev src_fwd clsact */
+ QDISC_CLSACT_CREATE(&qdisc_src_fwd, setup_result->ifindex_src_fwd);
+ /* tc filter add dev src_fwd ingress bpf da src_prog */
+ XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS, src_prog, 0);
+ /* tc filter add dev src_fwd egress bpf da chk_prog */
+ XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS, chk_prog, 0);
- /* tc qdisc add dev veth_dst_fwd clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd);
- /* tc filter add dev veth_dst_fwd ingress bpf da dst_prog */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, dst_prog, 0);
- /* tc filter add dev veth_dst_fwd egress bpf da chk_prog */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, chk_prog, 0);
+ /* tc qdisc add dev dst_fwd clsact */
+ QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd);
+ /* tc filter add dev dst_fwd ingress bpf da dst_prog */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, dst_prog, 0);
+ /* tc filter add dev dst_fwd egress bpf da chk_prog */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, chk_prog, 0);
return 0;
fail:
@@ -539,10 +600,10 @@ static void test_inet_dtime(int family, int type, const char *addr, __u16 port)
static int netns_load_dtime_bpf(struct test_tc_dtime *skel,
const struct netns_setup_result *setup_result)
{
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src_fwd);
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd);
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src);
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_src_fwd);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_src);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_dst);
struct nstoken *nstoken;
int err;
@@ -550,58 +611,58 @@ static int netns_load_dtime_bpf(struct test_tc_dtime *skel,
nstoken = open_netns(NS_SRC);
if (!ASSERT_OK_PTR(nstoken, "setns " NS_SRC))
return -1;
- /* tc qdisc add dev veth_src clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_src, setup_result->ifindex_veth_src);
- /* tc filter add dev veth_src ingress bpf da ingress_host */
- XGRESS_FILTER_ADD(&qdisc_veth_src, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
- /* tc filter add dev veth_src egress bpf da egress_host */
- XGRESS_FILTER_ADD(&qdisc_veth_src, BPF_TC_EGRESS, skel->progs.egress_host, 0);
+ /* tc qdisc add dev src clsact */
+ QDISC_CLSACT_CREATE(&qdisc_src, setup_result->ifindex_src);
+ /* tc filter add dev src ingress bpf da ingress_host */
+ XGRESS_FILTER_ADD(&qdisc_src, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
+ /* tc filter add dev src egress bpf da egress_host */
+ XGRESS_FILTER_ADD(&qdisc_src, BPF_TC_EGRESS, skel->progs.egress_host, 0);
close_netns(nstoken);
/* setup ns_dst tc progs */
nstoken = open_netns(NS_DST);
if (!ASSERT_OK_PTR(nstoken, "setns " NS_DST))
return -1;
- /* tc qdisc add dev veth_dst clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_dst, setup_result->ifindex_veth_dst);
- /* tc filter add dev veth_dst ingress bpf da ingress_host */
- XGRESS_FILTER_ADD(&qdisc_veth_dst, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
- /* tc filter add dev veth_dst egress bpf da egress_host */
- XGRESS_FILTER_ADD(&qdisc_veth_dst, BPF_TC_EGRESS, skel->progs.egress_host, 0);
+ /* tc qdisc add dev dst clsact */
+ QDISC_CLSACT_CREATE(&qdisc_dst, setup_result->ifindex_dst);
+ /* tc filter add dev dst ingress bpf da ingress_host */
+ XGRESS_FILTER_ADD(&qdisc_dst, BPF_TC_INGRESS, skel->progs.ingress_host, 0);
+ /* tc filter add dev dst egress bpf da egress_host */
+ XGRESS_FILTER_ADD(&qdisc_dst, BPF_TC_EGRESS, skel->progs.egress_host, 0);
close_netns(nstoken);
/* setup ns_fwd tc progs */
nstoken = open_netns(NS_FWD);
if (!ASSERT_OK_PTR(nstoken, "setns " NS_FWD))
return -1;
- /* tc qdisc add dev veth_dst_fwd clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd);
- /* tc filter add dev veth_dst_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS,
+ /* tc qdisc add dev dst_fwd clsact */
+ QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd);
+ /* tc filter add dev dst_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS,
skel->progs.ingress_fwdns_prio100, 100);
- /* tc filter add dev veth_dst_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS,
+ /* tc filter add dev dst_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS,
skel->progs.ingress_fwdns_prio101, 101);
- /* tc filter add dev veth_dst_fwd egress prio 100 bpf da egress_fwdns_prio100 */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS,
+ /* tc filter add dev dst_fwd egress prio 100 bpf da egress_fwdns_prio100 */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS,
skel->progs.egress_fwdns_prio100, 100);
- /* tc filter add dev veth_dst_fwd egress prio 101 bpf da egress_fwdns_prio101 */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS,
+ /* tc filter add dev dst_fwd egress prio 101 bpf da egress_fwdns_prio101 */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS,
skel->progs.egress_fwdns_prio101, 101);
- /* tc qdisc add dev veth_src_fwd clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_src_fwd, setup_result->ifindex_veth_src_fwd);
- /* tc filter add dev veth_src_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
- XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS,
+ /* tc qdisc add dev src_fwd clsact */
+ QDISC_CLSACT_CREATE(&qdisc_src_fwd, setup_result->ifindex_src_fwd);
+ /* tc filter add dev src_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */
+ XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS,
skel->progs.ingress_fwdns_prio100, 100);
- /* tc filter add dev veth_src_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
- XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS,
+ /* tc filter add dev src_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */
+ XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS,
skel->progs.ingress_fwdns_prio101, 101);
- /* tc filter add dev veth_src_fwd egress prio 100 bpf da egress_fwdns_prio100 */
- XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS,
+ /* tc filter add dev src_fwd egress prio 100 bpf da egress_fwdns_prio100 */
+ XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS,
skel->progs.egress_fwdns_prio100, 100);
- /* tc filter add dev veth_src_fwd egress prio 101 bpf da egress_fwdns_prio101 */
- XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS,
+ /* tc filter add dev src_fwd egress prio 101 bpf da egress_fwdns_prio101 */
+ XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS,
skel->progs.egress_fwdns_prio101, 101);
close_netns(nstoken);
return 0;
@@ -777,8 +838,8 @@ static void test_tc_redirect_dtime(struct netns_setup_result *setup_result)
if (!ASSERT_OK_PTR(skel, "test_tc_dtime__open"))
return;
- skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
- skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+ skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+ skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
err = test_tc_dtime__load(skel);
if (!ASSERT_OK(err, "test_tc_dtime__load"))
@@ -868,8 +929,8 @@ static void test_tc_redirect_neigh(struct netns_setup_result *setup_result)
if (!ASSERT_OK_PTR(skel, "test_tc_neigh__open"))
goto done;
- skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
- skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+ skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+ skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
err = test_tc_neigh__load(skel);
if (!ASSERT_OK(err, "test_tc_neigh__load"))
@@ -904,8 +965,8 @@ static void test_tc_redirect_peer(struct netns_setup_result *setup_result)
if (!ASSERT_OK_PTR(skel, "test_tc_peer__open"))
goto done;
- skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
- skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+ skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+ skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
err = test_tc_peer__load(skel);
if (!ASSERT_OK(err, "test_tc_peer__load"))
@@ -996,7 +1057,7 @@ static int tun_relay_loop(int src_fd, int target_fd)
static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
{
LIBBPF_OPTS(bpf_tc_hook, qdisc_tun_fwd);
- LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd);
+ LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd);
struct test_tc_peer *skel = NULL;
struct nstoken *nstoken = NULL;
int err;
@@ -1045,7 +1106,7 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
goto fail;
skel->rodata->IFINDEX_SRC = ifindex;
- skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+ skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
err = test_tc_peer__load(skel);
if (!ASSERT_OK(err, "test_tc_peer__load"))
@@ -1053,19 +1114,19 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
/* Load "tc_src_l3" to the tun_fwd interface to redirect packets
* towards dst, and "tc_dst" to redirect packets
- * and "tc_chk" on veth_dst_fwd to drop non-redirected packets.
+ * and "tc_chk" on dst_fwd to drop non-redirected packets.
*/
/* tc qdisc add dev tun_fwd clsact */
QDISC_CLSACT_CREATE(&qdisc_tun_fwd, ifindex);
/* tc filter add dev tun_fwd ingress bpf da tc_src_l3 */
XGRESS_FILTER_ADD(&qdisc_tun_fwd, BPF_TC_INGRESS, skel->progs.tc_src_l3, 0);
- /* tc qdisc add dev veth_dst_fwd clsact */
- QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd);
- /* tc filter add dev veth_dst_fwd ingress bpf da tc_dst_l3 */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, skel->progs.tc_dst_l3, 0);
- /* tc filter add dev veth_dst_fwd egress bpf da tc_chk */
- XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, skel->progs.tc_chk, 0);
+ /* tc qdisc add dev dst_fwd clsact */
+ QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd);
+ /* tc filter add dev dst_fwd ingress bpf da tc_dst_l3 */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, skel->progs.tc_dst_l3, 0);
+ /* tc filter add dev dst_fwd egress bpf da tc_chk */
+ XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, skel->progs.tc_chk, 0);
/* Setup route and neigh tables */
SYS(fail, "ip -netns " NS_SRC " addr add dev tun_src " IP4_TUN_SRC "/24");
@@ -1074,17 +1135,17 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
SYS(fail, "ip -netns " NS_SRC " addr add dev tun_src " IP6_TUN_SRC "/64 nodad");
SYS(fail, "ip -netns " NS_FWD " addr add dev tun_fwd " IP6_TUN_FWD "/64 nodad");
- SYS(fail, "ip -netns " NS_SRC " route del " IP4_DST "/32 dev veth_src scope global");
+ SYS(fail, "ip -netns " NS_SRC " route del " IP4_DST "/32 dev src scope global");
SYS(fail, "ip -netns " NS_SRC " route add " IP4_DST "/32 via " IP4_TUN_FWD
" dev tun_src scope global");
- SYS(fail, "ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev veth_dst scope global");
- SYS(fail, "ip -netns " NS_SRC " route del " IP6_DST "/128 dev veth_src scope global");
+ SYS(fail, "ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev dst scope global");
+ SYS(fail, "ip -netns " NS_SRC " route del " IP6_DST "/128 dev src scope global");
SYS(fail, "ip -netns " NS_SRC " route add " IP6_DST "/128 via " IP6_TUN_FWD
" dev tun_src scope global");
- SYS(fail, "ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev veth_dst scope global");
+ SYS(fail, "ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev dst scope global");
- SYS(fail, "ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD);
- SYS(fail, "ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+ SYS(fail, "ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev dst lladdr " MAC_DST_FWD);
+ SYS(fail, "ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev dst lladdr " MAC_DST_FWD);
if (!ASSERT_OK(set_forwarding(false), "disable forwarding"))
goto fail;
@@ -1106,9 +1167,9 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
close_netns(nstoken);
}
-#define RUN_TEST(name) \
+#define RUN_TEST(name, mode) \
({ \
- struct netns_setup_result setup_result; \
+ struct netns_setup_result setup_result = { .dev_mode = mode, }; \
if (test__start_subtest(#name)) \
if (ASSERT_OK(netns_setup_namespaces("add"), "setup namespaces")) { \
if (ASSERT_OK(netns_setup_links_and_routes(&setup_result), \
@@ -1122,11 +1183,13 @@ static void *test_tc_redirect_run_tests(void *arg)
{
netns_setup_namespaces_nofail("delete");
- RUN_TEST(tc_redirect_peer);
- RUN_TEST(tc_redirect_peer_l3);
- RUN_TEST(tc_redirect_neigh);
- RUN_TEST(tc_redirect_neigh_fib);
- RUN_TEST(tc_redirect_dtime);
+ RUN_TEST(tc_redirect_peer, MODE_VETH);
+ RUN_TEST(tc_redirect_peer, MODE_NETKIT);
+ RUN_TEST(tc_redirect_peer_l3, MODE_VETH);
+ RUN_TEST(tc_redirect_peer_l3, MODE_NETKIT);
+ RUN_TEST(tc_redirect_neigh, MODE_VETH);
+ RUN_TEST(tc_redirect_neigh_fib, MODE_VETH);
+ RUN_TEST(tc_redirect_dtime, MODE_VETH);
return NULL;
}
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index e5c61aa6604..5cfa7a6316b 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -31,6 +31,7 @@
#include "verifier_helper_restricted.skel.h"
#include "verifier_helper_value_access.skel.h"
#include "verifier_int_ptr.skel.h"
+#include "verifier_iterating_callbacks.skel.h"
#include "verifier_jeq_infer_not_null.skel.h"
#include "verifier_ld_ind.skel.h"
#include "verifier_ldsx.skel.h"
@@ -139,6 +140,7 @@ void test_verifier_helper_packet_access(void) { RUN(verifier_helper_packet_acces
void test_verifier_helper_restricted(void) { RUN(verifier_helper_restricted); }
void test_verifier_helper_value_access(void) { RUN(verifier_helper_value_access); }
void test_verifier_int_ptr(void) { RUN(verifier_int_ptr); }
+void test_verifier_iterating_callbacks(void) { RUN(verifier_iterating_callbacks); }
void test_verifier_jeq_infer_not_null(void) { RUN(verifier_jeq_infer_not_null); }
void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); }
void test_verifier_ldsx(void) { RUN(verifier_ldsx); }
diff --git a/tools/testing/selftests/bpf/progs/bpf_loop_bench.c b/tools/testing/selftests/bpf/progs/bpf_loop_bench.c
index 4ce76eb064c..d461746fd3c 100644
--- a/tools/testing/selftests/bpf/progs/bpf_loop_bench.c
+++ b/tools/testing/selftests/bpf/progs/bpf_loop_bench.c
@@ -15,13 +15,16 @@ static int empty_callback(__u32 index, void *data)
return 0;
}
+static int outer_loop(__u32 index, void *data)
+{
+ bpf_loop(nr_loops, empty_callback, NULL, 0);
+ __sync_add_and_fetch(&hits, nr_loops);
+ return 0;
+}
+
SEC("fentry/" SYS_PREFIX "sys_getpgid")
int benchmark(void *ctx)
{
- for (int i = 0; i < 1000; i++) {
- bpf_loop(nr_loops, empty_callback, NULL, 0);
-
- __sync_add_and_fetch(&hits, nr_loops);
- }
+ bpf_loop(1000, outer_loop, NULL, 0);
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/cb_refs.c b/tools/testing/selftests/bpf/progs/cb_refs.c
index 76d661b20e8..56c764df819 100644
--- a/tools/testing/selftests/bpf/progs/cb_refs.c
+++ b/tools/testing/selftests/bpf/progs/cb_refs.c
@@ -33,6 +33,7 @@ int underflow_prog(void *ctx)
if (!p)
return 0;
bpf_for_each_map_elem(&array_map, cb1, &p, 0);
+ bpf_kfunc_call_test_release(p);
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c
index 4c39e920dac..8c0ef274220 100644
--- a/tools/testing/selftests/bpf/progs/exceptions_fail.c
+++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c
@@ -171,6 +171,7 @@ int reject_with_rbtree_add_throw(void *ctx)
return 0;
bpf_spin_lock(&lock);
bpf_rbtree_add(&rbtree, &f->node, rbless);
+ bpf_spin_unlock(&lock);
return 0;
}
@@ -214,6 +215,7 @@ int reject_with_cb_reference(void *ctx)
if (!f)
return 0;
bpf_loop(5, subprog_cb_ref, NULL, 0);
+ bpf_obj_drop(f);
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/strobemeta.h b/tools/testing/selftests/bpf/progs/strobemeta.h
index e02cfd38074..40df2cc26ea 100644
--- a/tools/testing/selftests/bpf/progs/strobemeta.h
+++ b/tools/testing/selftests/bpf/progs/strobemeta.h
@@ -24,9 +24,11 @@ struct task_struct {};
#define STACK_TABLE_EPOCH_SHIFT 20
#define STROBE_MAX_STR_LEN 1
#define STROBE_MAX_CFGS 32
+#define READ_MAP_VAR_PAYLOAD_CAP \
+ ((1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN)
#define STROBE_MAX_PAYLOAD \
(STROBE_MAX_STRS * STROBE_MAX_STR_LEN + \
- STROBE_MAX_MAPS * (1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN)
+ STROBE_MAX_MAPS * READ_MAP_VAR_PAYLOAD_CAP)
struct strobe_value_header {
/*
@@ -355,7 +357,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
size_t idx, void *tls_base,
struct strobe_value_generic *value,
struct strobemeta_payload *data,
- void *payload)
+ size_t off)
{
void *location;
uint64_t len;
@@ -366,7 +368,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
return 0;
bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location);
- len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, value->ptr);
+ len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, value->ptr);
/*
* if bpf_probe_read_user_str returns error (<0), due to casting to
* unsinged int, it will become big number, so next check is
@@ -378,14 +380,14 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
return 0;
data->str_lens[idx] = len;
- return len;
+ return off + len;
}
-static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
- size_t idx, void *tls_base,
- struct strobe_value_generic *value,
- struct strobemeta_payload *data,
- void *payload)
+static __always_inline uint64_t read_map_var(struct strobemeta_cfg *cfg,
+ size_t idx, void *tls_base,
+ struct strobe_value_generic *value,
+ struct strobemeta_payload *data,
+ size_t off)
{
struct strobe_map_descr* descr = &data->map_descrs[idx];
struct strobe_map_raw map;
@@ -397,11 +399,11 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
location = calc_location(&cfg->map_locs[idx], tls_base);
if (!location)
- return payload;
+ return off;
bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location);
if (bpf_probe_read_user(&map, sizeof(struct strobe_map_raw), value->ptr))
- return payload;
+ return off;
descr->id = map.id;
descr->cnt = map.cnt;
@@ -410,10 +412,10 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
data->req_meta_valid = 1;
}
- len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, map.tag);
+ len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, map.tag);
if (len <= STROBE_MAX_STR_LEN) {
descr->tag_len = len;
- payload += len;
+ off += len;
}
#ifdef NO_UNROLL
@@ -426,22 +428,22 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
break;
descr->key_lens[i] = 0;
- len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN,
+ len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN,
map.entries[i].key);
if (len <= STROBE_MAX_STR_LEN) {
descr->key_lens[i] = len;
- payload += len;
+ off += len;
}
descr->val_lens[i] = 0;
- len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN,
+ len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN,
map.entries[i].val);
if (len <= STROBE_MAX_STR_LEN) {
descr->val_lens[i] = len;
- payload += len;
+ off += len;
}
}
- return payload;
+ return off;
}
#ifdef USE_BPF_LOOP
@@ -455,14 +457,20 @@ struct read_var_ctx {
struct strobemeta_payload *data;
void *tls_base;
struct strobemeta_cfg *cfg;
- void *payload;
+ size_t payload_off;
/* value gets mutated */
struct strobe_value_generic *value;
enum read_type type;
};
-static int read_var_callback(__u32 index, struct read_var_ctx *ctx)
+static int read_var_callback(__u64 index, struct read_var_ctx *ctx)
{
+ /* lose precision info for ctx->payload_off, verifier won't track
+ * double xor, barrier_var() is needed to force clang keep both xors.
+ */
+ ctx->payload_off ^= index;
+ barrier_var(ctx->payload_off);
+ ctx->payload_off ^= index;
switch (ctx->type) {
case READ_INT_VAR:
if (index >= STROBE_MAX_INTS)
@@ -472,14 +480,18 @@ static int read_var_callback(__u32 index, struct read_var_ctx *ctx)
case READ_MAP_VAR:
if (index >= STROBE_MAX_MAPS)
return 1;
- ctx->payload = read_map_var(ctx->cfg, index, ctx->tls_base,
- ctx->value, ctx->data, ctx->payload);
+ if (ctx->payload_off > sizeof(ctx->data->payload) - READ_MAP_VAR_PAYLOAD_CAP)
+ return 1;
+ ctx->payload_off = read_map_var(ctx->cfg, index, ctx->tls_base,
+ ctx->value, ctx->data, ctx->payload_off);
break;
case READ_STR_VAR:
if (index >= STROBE_MAX_STRS)
return 1;
- ctx->payload += read_str_var(ctx->cfg, index, ctx->tls_base,
- ctx->value, ctx->data, ctx->payload);
+ if (ctx->payload_off > sizeof(ctx->data->payload) - STROBE_MAX_STR_LEN)
+ return 1;
+ ctx->payload_off = read_str_var(ctx->cfg, index, ctx->tls_base,
+ ctx->value, ctx->data, ctx->payload_off);
break;
}
return 0;
@@ -501,7 +513,8 @@ static void *read_strobe_meta(struct task_struct *task,
pid_t pid = bpf_get_current_pid_tgid() >> 32;
struct strobe_value_generic value = {0};
struct strobemeta_cfg *cfg;
- void *tls_base, *payload;
+ size_t payload_off;
+ void *tls_base;
cfg = bpf_map_lookup_elem(&strobemeta_cfgs, &pid);
if (!cfg)
@@ -509,7 +522,7 @@ static void *read_strobe_meta(struct task_struct *task,
data->int_vals_set_mask = 0;
data->req_meta_valid = 0;
- payload = data->payload;
+ payload_off = 0;
/*
* we don't have struct task_struct definition, it should be:
* tls_base = (void *)task->thread.fsbase;
@@ -522,7 +535,7 @@ static void *read_strobe_meta(struct task_struct *task,
.tls_base = tls_base,
.value = &value,
.data = data,
- .payload = payload,
+ .payload_off = 0,
};
int err;
@@ -540,6 +553,11 @@ static void *read_strobe_meta(struct task_struct *task,
err = bpf_loop(STROBE_MAX_MAPS, read_var_callback, &ctx, 0);
if (err != STROBE_MAX_MAPS)
return NULL;
+
+ payload_off = ctx.payload_off;
+ /* this should not really happen, here only to satisfy verifer */
+ if (payload_off > sizeof(data->payload))
+ payload_off = sizeof(data->payload);
#else
#ifdef NO_UNROLL
#pragma clang loop unroll(disable)
@@ -555,7 +573,7 @@ static void *read_strobe_meta(struct task_struct *task,
#pragma unroll
#endif /* NO_UNROLL */
for (int i = 0; i < STROBE_MAX_STRS; ++i) {
- payload += read_str_var(cfg, i, tls_base, &value, data, payload);
+ payload_off = read_str_var(cfg, i, tls_base, &value, data, payload_off);
}
#ifdef NO_UNROLL
#pragma clang loop unroll(disable)
@@ -563,7 +581,7 @@ static void *read_strobe_meta(struct task_struct *task,
#pragma unroll
#endif /* NO_UNROLL */
for (int i = 0; i < STROBE_MAX_MAPS; ++i) {
- payload = read_map_var(cfg, i, tls_base, &value, data, payload);
+ payload_off = read_map_var(cfg, i, tls_base, &value, data, payload_off);
}
#endif /* USE_BPF_LOOP */
@@ -571,7 +589,7 @@ static void *read_strobe_meta(struct task_struct *task,
* return pointer right after end of payload, so it's possible to
* calculate exact amount of useful data that needs to be sent
*/
- return payload;
+ return &data->payload[payload_off];
}
SEC("raw_tracepoint/kfree_skb")
diff --git a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c
new file mode 100644
index 00000000000..5905e036e0e
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 8);
+ __type(key, __u32);
+ __type(value, __u64);
+} map SEC(".maps");
+
+struct {
+ __uint(type, BPF_MAP_TYPE_USER_RINGBUF);
+ __uint(max_entries, 8);
+} ringbuf SEC(".maps");
+
+struct vm_area_struct;
+struct bpf_map;
+
+struct buf_context {
+ char *buf;
+};
+
+struct num_context {
+ __u64 i;
+ __u64 j;
+};
+
+__u8 choice_arr[2] = { 0, 1 };
+
+static int unsafe_on_2nd_iter_cb(__u32 idx, struct buf_context *ctx)
+{
+ if (idx == 0) {
+ ctx->buf = (char *)(0xDEAD);
+ return 0;
+ }
+
+ if (bpf_probe_read_user(ctx->buf, 8, (void *)(0xBADC0FFEE)))
+ return 1;
+
+ return 0;
+}
+
+SEC("?raw_tp")
+__failure __msg("R1 type=scalar expected=fp")
+int unsafe_on_2nd_iter(void *unused)
+{
+ char buf[4];
+ struct buf_context loop_ctx = { .buf = buf };
+
+ bpf_loop(100, unsafe_on_2nd_iter_cb, &loop_ctx, 0);
+ return 0;
+}
+
+static int unsafe_on_zero_iter_cb(__u32 idx, struct num_context *ctx)
+{
+ ctx->i = 0;
+ return 0;
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_on_zero_iter(void *unused)
+{
+ struct num_context loop_ctx = { .i = 32 };
+
+ bpf_loop(100, unsafe_on_zero_iter_cb, &loop_ctx, 0);
+ return choice_arr[loop_ctx.i];
+}
+
+static int widening_cb(__u32 idx, struct num_context *ctx)
+{
+ ++ctx->i;
+ return 0;
+}
+
+SEC("?raw_tp")
+__success
+int widening(void *unused)
+{
+ struct num_context loop_ctx = { .i = 0, .j = 1 };
+
+ bpf_loop(100, widening_cb, &loop_ctx, 0);
+ /* loop_ctx.j is not changed during callback iteration,
+ * verifier should not apply widening to it.
+ */
+ return choice_arr[loop_ctx.j];
+}
+
+static int loop_detection_cb(__u32 idx, struct num_context *ctx)
+{
+ for (;;) {}
+ return 0;
+}
+
+SEC("?raw_tp")
+__failure __msg("infinite loop detected")
+int loop_detection(void *unused)
+{
+ struct num_context loop_ctx = { .i = 0 };
+
+ bpf_loop(100, loop_detection_cb, &loop_ctx, 0);
+ return 0;
+}
+
+static __always_inline __u64 oob_state_machine(struct num_context *ctx)
+{
+ switch (ctx->i) {
+ case 0:
+ ctx->i = 1;
+ break;
+ case 1:
+ ctx->i = 32;
+ break;
+ }
+ return 0;
+}
+
+static __u64 for_each_map_elem_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data)
+{
+ return oob_state_machine(data);
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_for_each_map_elem(void *unused)
+{
+ struct num_context loop_ctx = { .i = 0 };
+
+ bpf_for_each_map_elem(&map, for_each_map_elem_cb, &loop_ctx, 0);
+ return choice_arr[loop_ctx.i];
+}
+
+static __u64 ringbuf_drain_cb(struct bpf_dynptr *dynptr, void *data)
+{
+ return oob_state_machine(data);
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_ringbuf_drain(void *unused)
+{
+ struct num_context loop_ctx = { .i = 0 };
+
+ bpf_user_ringbuf_drain(&ringbuf, ringbuf_drain_cb, &loop_ctx, 0);
+ return choice_arr[loop_ctx.i];
+}
+
+static __u64 find_vma_cb(struct task_struct *task, struct vm_area_struct *vma, void *data)
+{
+ return oob_state_machine(data);
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=32 size=1")
+int unsafe_find_vma(void *unused)
+{
+ struct task_struct *task = bpf_get_current_task_btf();
+ struct num_context loop_ctx = { .i = 0 };
+
+ bpf_find_vma(task, 0, find_vma_cb, &loop_ctx, 0);
+ return choice_arr[loop_ctx.i];
+}
+
+static int iter_limit_cb(__u32 idx, struct num_context *ctx)
+{
+ ctx->i++;
+ return 0;
+}
+
+SEC("?raw_tp")
+__success
+int bpf_loop_iter_limit_ok(void *unused)
+{
+ struct num_context ctx = { .i = 0 };
+
+ bpf_loop(1, iter_limit_cb, &ctx, 0);
+ return choice_arr[ctx.i];
+}
+
+SEC("?raw_tp")
+__failure __msg("invalid access to map value, value_size=2 off=2 size=1")
+int bpf_loop_iter_limit_overflow(void *unused)
+{
+ struct num_context ctx = { .i = 0 };
+
+ bpf_loop(2, iter_limit_cb, &ctx, 0);
+ return choice_arr[ctx.i];
+}
+
+static int iter_limit_level2a_cb(__u32 idx, struct num_context *ctx)
+{
+ ctx->i += 100;
+ return 0;
+}
+
+static int iter_limit_level2b_cb(__u32 idx, struct num_context *ctx)
+{
+ ctx->i += 10;
+ return 0;
+}
+
+static int iter_limit_level1_cb(__u32 idx, struct num_context *ctx)
+{
+ ctx->i += 1;
+ bpf_loop(1, iter_limit_level2a_cb, ctx, 0);
+ bpf_loop(1, iter_limit_level2b_cb, ctx, 0);
+ return 0;
+}
+
+/* Check that path visiting every callback function once had been
+ * reached by verifier. Variables 'ctx{1,2}i' below serve as flags,
+ * with each decimal digit corresponding to a callback visit marker.
+ */
+SEC("socket")
+__success __retval(111111)
+int bpf_loop_iter_limit_nested(void *unused)
+{
+ struct num_context ctx1 = { .i = 0 };
+ struct num_context ctx2 = { .i = 0 };
+ __u64 a, b, c;
+
+ bpf_loop(1, iter_limit_level1_cb, &ctx1, 0);
+ bpf_loop(1, iter_limit_level1_cb, &ctx2, 0);
+ a = ctx1.i;
+ b = ctx2.i;
+ /* Force 'ctx1.i' and 'ctx2.i' precise. */
+ c = choice_arr[(a + b) % 2];
+ /* This makes 'c' zero, but neither clang nor verifier know it. */
+ c /= 10;
+ /* Make sure that verifier does not visit 'impossible' states:
+ * enumerate all possible callback visit masks.
+ */
+ if (a != 0 && a != 1 && a != 11 && a != 101 && a != 111 &&
+ b != 0 && b != 1 && b != 11 && b != 101 && b != 111)
+ asm volatile ("r0 /= 0;" ::: "r0");
+ return 1000 * a + b + c;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
index db6b3143338..f61d623b1ce 100644
--- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
+++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
@@ -119,15 +119,41 @@ __naked int global_subprog_result_precise(void)
SEC("?raw_tp")
__success __log_level(2)
+/* First simulated path does not include callback body,
+ * r1 and r4 are always precise for bpf_loop() calls.
+ */
+__msg("9: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: parent state regs=r4 stack=:")
+__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9")
+__msg("mark_precise: frame0: regs=r4 stack= before 8: (b7) r4 = 0")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: parent state regs=r1 stack=:")
+__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9")
+__msg("mark_precise: frame0: regs=r1 stack= before 8: (b7) r4 = 0")
+__msg("mark_precise: frame0: regs=r1 stack= before 7: (b7) r3 = 0")
+__msg("mark_precise: frame0: regs=r1 stack= before 6: (bf) r2 = r8")
+__msg("mark_precise: frame0: regs=r1 stack= before 5: (bf) r1 = r6")
+__msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3")
+/* r6 precision propagation */
__msg("14: (0f) r1 += r6")
-__msg("mark_precise: frame0: last_idx 14 first_idx 10")
+__msg("mark_precise: frame0: last_idx 14 first_idx 9")
__msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7")
__msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4")
__msg("mark_precise: frame0: regs=r6 stack= before 11: (25) if r6 > 0x3 goto pc+4")
__msg("mark_precise: frame0: regs=r6 stack= before 10: (bf) r6 = r0")
-__msg("mark_precise: frame0: parent state regs=r0 stack=:")
-__msg("mark_precise: frame0: last_idx 18 first_idx 0")
-__msg("mark_precise: frame0: regs=r0 stack= before 18: (95) exit")
+__msg("mark_precise: frame0: regs=r0 stack= before 9: (85) call bpf_loop")
+/* State entering callback body popped from states stack */
+__msg("from 9 to 17: frame1:")
+__msg("17: frame1: R1=scalar() R2=0 R10=fp0 cb")
+__msg("17: (b7) r0 = 0")
+__msg("18: (95) exit")
+__msg("returning from callee:")
+__msg("to caller at 9:")
+__msg("frame 0: propagating r1,r4")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: regs=r1,r4 stack= before 18: (95) exit")
+__msg("from 18 to 9: safe")
__naked int callback_result_precise(void)
{
asm volatile (
@@ -233,20 +259,36 @@ __naked int parent_callee_saved_reg_precise_global(void)
SEC("?raw_tp")
__success __log_level(2)
+/* First simulated path does not include callback body */
__msg("12: (0f) r1 += r6")
-__msg("mark_precise: frame0: last_idx 12 first_idx 10")
+__msg("mark_precise: frame0: last_idx 12 first_idx 9")
__msg("mark_precise: frame0: regs=r6 stack= before 11: (bf) r1 = r7")
__msg("mark_precise: frame0: regs=r6 stack= before 10: (27) r6 *= 4")
+__msg("mark_precise: frame0: regs=r6 stack= before 9: (85) call bpf_loop")
__msg("mark_precise: frame0: parent state regs=r6 stack=:")
-__msg("mark_precise: frame0: last_idx 16 first_idx 0")
-__msg("mark_precise: frame0: regs=r6 stack= before 16: (95) exit")
-__msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0")
-__msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9")
__msg("mark_precise: frame0: regs=r6 stack= before 8: (b7) r4 = 0")
__msg("mark_precise: frame0: regs=r6 stack= before 7: (b7) r3 = 0")
__msg("mark_precise: frame0: regs=r6 stack= before 6: (bf) r2 = r8")
__msg("mark_precise: frame0: regs=r6 stack= before 5: (b7) r1 = 1")
__msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3")
+/* State entering callback body popped from states stack */
+__msg("from 9 to 15: frame1:")
+__msg("15: frame1: R1=scalar() R2=0 R10=fp0 cb")
+__msg("15: (b7) r0 = 0")
+__msg("16: (95) exit")
+__msg("returning from callee:")
+__msg("to caller at 9:")
+/* r1, r4 are always precise for bpf_loop(),
+ * r6 was marked before backtracking to callback body.
+ */
+__msg("frame 0: propagating r1,r4,r6")
+__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1")
+__msg("mark_precise: frame0: regs=r1,r4,r6 stack= before 16: (95) exit")
+__msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0")
+__msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop")
+__msg("mark_precise: frame0: parent state regs= stack=:")
+__msg("from 16 to 9: safe")
__naked int parent_callee_saved_reg_precise_with_callback(void)
{
asm volatile (
@@ -373,22 +415,38 @@ __naked int parent_stack_slot_precise_global(void)
SEC("?raw_tp")
__success __log_level(2)
+/* First simulated path does not include callback body */
__msg("14: (0f) r1 += r6")
-__msg("mark_precise: frame0: last_idx 14 first_idx 11")
+__msg("mark_precise: frame0: last_idx 14 first_idx 10")
__msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7")
__msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4")
__msg("mark_precise: frame0: regs=r6 stack= before 11: (79) r6 = *(u64 *)(r10 -8)")
+__msg("mark_precise: frame0: regs= stack=-8 before 10: (85) call bpf_loop")
__msg("mark_precise: frame0: parent state regs= stack=-8:")
-__msg("mark_precise: frame0: last_idx 18 first_idx 0")
-__msg("mark_precise: frame0: regs= stack=-8 before 18: (95) exit")
-__msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0")
-__msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: last_idx 9 first_idx 0 subseq_idx 10")
__msg("mark_precise: frame0: regs= stack=-8 before 9: (b7) r4 = 0")
__msg("mark_precise: frame0: regs= stack=-8 before 8: (b7) r3 = 0")
__msg("mark_precise: frame0: regs= stack=-8 before 7: (bf) r2 = r8")
__msg("mark_precise: frame0: regs= stack=-8 before 6: (bf) r1 = r6")
__msg("mark_precise: frame0: regs= stack=-8 before 5: (7b) *(u64 *)(r10 -8) = r6")
__msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3")
+/* State entering callback body popped from states stack */
+__msg("from 10 to 17: frame1:")
+__msg("17: frame1: R1=scalar() R2=0 R10=fp0 cb")
+__msg("17: (b7) r0 = 0")
+__msg("18: (95) exit")
+__msg("returning from callee:")
+__msg("to caller at 10:")
+/* r1, r4 are always precise for bpf_loop(),
+ * fp-8 was marked before backtracking to callback body.
+ */
+__msg("frame 0: propagating r1,r4,fp-8")
+__msg("mark_precise: frame0: last_idx 10 first_idx 10 subseq_idx -1")
+__msg("mark_precise: frame0: regs=r1,r4 stack=-8 before 18: (95) exit")
+__msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0")
+__msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181")
+__msg("mark_precise: frame0: parent state regs= stack=:")
+__msg("from 18 to 10: safe")
__naked int parent_stack_slot_precise_with_callback(void)
{
asm volatile (
diff --git a/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c b/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c
index e959336c7a7..80f620602d5 100644
--- a/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c
+++ b/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c
@@ -53,6 +53,8 @@
#define DEFAULT_TTL 64
#define MAX_ALLOWED_PORTS 8
+#define MAX_PACKET_OFF 0xffff
+
#define swap(a, b) \
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
@@ -183,63 +185,76 @@ static __always_inline __u32 tcp_clock_ms(void)
}
struct tcpopt_context {
- __u8 *ptr;
- __u8 *end;
+ void *data;
void *data_end;
__be32 *tsecr;
__u8 wscale;
bool option_timestamp;
bool option_sack;
+ __u32 off;
};
-static int tscookie_tcpopt_parse(struct tcpopt_context *ctx)
+static __always_inline u8 *next(struct tcpopt_context *ctx, __u32 sz)
{
- __u8 opcode, opsize;
+ __u64 off = ctx->off;
+ __u8 *data;
- if (ctx->ptr >= ctx->end)
- return 1;
- if (ctx->ptr >= ctx->data_end)
- return 1;
+ /* Verifier forbids access to packet when offset exceeds MAX_PACKET_OFF */
+ if (off > MAX_PACKET_OFF - sz)
+ return NULL;
- opcode = ctx->ptr[0];
+ data = ctx->data + off;
+ barrier_var(data);
+ if (data + sz >= ctx->data_end)
+ return NULL;
- if (opcode == TCPOPT_EOL)
- return 1;
- if (opcode == TCPOPT_NOP) {
- ++ctx->ptr;
- return 0;
- }
+ ctx->off += sz;
+ return data;
+}
- if (ctx->ptr + 1 >= ctx->end)
- return 1;
- if (ctx->ptr + 1 >= ctx->data_end)
+static int tscookie_tcpopt_parse(struct tcpopt_context *ctx)
+{
+ __u8 *opcode, *opsize, *wscale, *tsecr;
+ __u32 off = ctx->off;
+
+ opcode = next(ctx, 1);
+ if (!opcode)
return 1;
- opsize = ctx->ptr[1];
- if (opsize < 2)
+
+ if (*opcode == TCPOPT_EOL)
return 1;
+ if (*opcode == TCPOPT_NOP)
+ return 0;
- if (ctx->ptr + opsize > ctx->end)
+ opsize = next(ctx, 1);
+ if (!opsize || *opsize < 2)
return 1;
- switch (opcode) {
+ switch (*opcode) {
case TCPOPT_WINDOW:
- if (opsize == TCPOLEN_WINDOW && ctx->ptr + TCPOLEN_WINDOW <= ctx->data_end)
- ctx->wscale = ctx->ptr[2] < TCP_MAX_WSCALE ? ctx->ptr[2] : TCP_MAX_WSCALE;
+ wscale = next(ctx, 1);
+ if (!wscale)
+ return 1;
+ if (*opsize == TCPOLEN_WINDOW)
+ ctx->wscale = *wscale < TCP_MAX_WSCALE ? *wscale : TCP_MAX_WSCALE;
break;
case TCPOPT_TIMESTAMP:
- if (opsize == TCPOLEN_TIMESTAMP && ctx->ptr + TCPOLEN_TIMESTAMP <= ctx->data_end) {
+ tsecr = next(ctx, 4);
+ if (!tsecr)
+ return 1;
+ if (*opsize == TCPOLEN_TIMESTAMP) {
ctx->option_timestamp = true;
/* Client's tsval becomes our tsecr. */
- *ctx->tsecr = get_unaligned((__be32 *)(ctx->ptr + 2));
+ *ctx->tsecr = get_unaligned((__be32 *)tsecr);
}
break;
case TCPOPT_SACK_PERM:
- if (opsize == TCPOLEN_SACK_PERM)
+ if (*opsize == TCPOLEN_SACK_PERM)
ctx->option_sack = true;
break;
}
- ctx->ptr += opsize;
+ ctx->off = off + *opsize;
return 0;
}
@@ -256,16 +271,21 @@ static int tscookie_tcpopt_parse_batch(__u32 index, void *context)
static __always_inline bool tscookie_init(struct tcphdr *tcp_header,
__u16 tcp_len, __be32 *tsval,
- __be32 *tsecr, void *data_end)
+ __be32 *tsecr, void *data, void *data_end)
{
struct tcpopt_context loop_ctx = {
- .ptr = (__u8 *)(tcp_header + 1),
- .end = (__u8 *)tcp_header + tcp_len,
+ .data = data,
.data_end = data_end,
.tsecr = tsecr,
.wscale = TS_OPT_WSCALE_MASK,
.option_timestamp = false,
.option_sack = false,
+ /* Note: currently verifier would track .off as unbound scalar.
+ * In case if verifier would at some point get smarter and
+ * compute bounded value for this var, beware that it might
+ * hinder bpf_loop() convergence validation.
+ */
+ .off = (__u8 *)(tcp_header + 1) - (__u8 *)data,
};
u32 cookie;
@@ -635,7 +655,7 @@ static __always_inline int syncookie_handle_syn(struct header_pointers *hdr,
cookie = (__u32)value;
if (tscookie_init((void *)hdr->tcp, hdr->tcp_len,
- &tsopt_buf[0], &tsopt_buf[1], data_end))
+ &tsopt_buf[0], &tsopt_buf[1], data, data_end))
tsopt = tsopt_buf;
/* Check that there is enough space for a SYNACK. It also covers
diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh
index 5f2b3f6c0d7..38be9706c45 100755
--- a/tools/testing/selftests/net/rtnetlink.sh
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -859,7 +859,7 @@ kci_test_gretap()
run_cmd ip -netns "$testns" addr add dev "$DEV_NS" 10.1.1.100/24
- run_cmd ip -netns "$testns" link set dev $DEV_NS ups
+ run_cmd ip -netns "$testns" link set dev $DEV_NS up
run_cmd ip -netns "$testns" link del "$DEV_NS"
# test external mode
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 5b0e93f9996..01fa816868b 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -353,11 +353,12 @@ static void test_stream_msg_peek_server(const struct test_opts *opts)
}
#define SOCK_BUF_SIZE (2 * 1024 * 1024)
-#define MAX_MSG_SIZE (32 * 1024)
+#define MAX_MSG_PAGES 4
static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
{
unsigned long curr_hash;
+ size_t max_msg_size;
int page_size;
int msg_count;
int fd;
@@ -373,7 +374,8 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
curr_hash = 0;
page_size = getpagesize();
- msg_count = SOCK_BUF_SIZE / MAX_MSG_SIZE;
+ max_msg_size = MAX_MSG_PAGES * page_size;
+ msg_count = SOCK_BUF_SIZE / max_msg_size;
for (int i = 0; i < msg_count; i++) {
size_t buf_size;
@@ -383,7 +385,7 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
/* Use "small" buffers and "big" buffers. */
if (i & 1)
buf_size = page_size +
- (rand() % (MAX_MSG_SIZE - page_size));
+ (rand() % (max_msg_size - page_size));
else
buf_size = 1 + (rand() % page_size);
@@ -429,7 +431,6 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
unsigned long remote_hash;
unsigned long curr_hash;
int fd;
- char buf[MAX_MSG_SIZE];
struct msghdr msg = {0};
struct iovec iov = {0};
@@ -457,8 +458,13 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
control_writeln("SRVREADY");
/* Wait, until peer sends whole data. */
control_expectln("SENDDONE");
- iov.iov_base = buf;
- iov.iov_len = sizeof(buf);
+ iov.iov_len = MAX_MSG_PAGES * getpagesize();
+ iov.iov_base = malloc(iov.iov_len);
+ if (!iov.iov_base) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
@@ -483,6 +489,7 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
curr_hash += hash_djb2(msg.msg_iov[0].iov_base, recv_size);
}
+ free(iov.iov_base);
close(fd);
remote_hash = control_readulong();